Benoit Sida 3 år sedan
förälder
incheckning
dfa9a7eaef

+ 1
- 0
package.json Visa fil

@@ -42,6 +42,7 @@
42 42
     "lodash": "^4.17.4",
43 43
     "markdown-it": "^8.3.1",
44 44
     "react": "^15.5.4",
45
+    "react-ace": "^4.3.0",
45 46
     "react-addons-css-transition-group": "^15.5.2",
46 47
     "react-dom": "^15.5.4",
47 48
     "react-fontawesome": "^1.6.1",

+ 3
- 0
src/App.scss Visa fil

@@ -3,6 +3,9 @@
3 3
 html, body {
4 4
     margin: 0;
5 5
 }
6
+.pt-no-padding {
7
+    padding: 0;
8
+}
6 9
 
7 10
 .pt-toast-container.pt-toast-container-top.app-toaster {
8 11
     top: $pt-navbar-height;

+ 13
- 43
src/Pages/Login/Login.jsx Visa fil

@@ -1,57 +1,27 @@
1 1
 import React from 'react'
2
-import { connect } from 'react-redux'
3
-import axios from 'axios'
2
+import { Map } from '../../utils'
4 3
 import firebase from 'firebase'
5
-import { Card } from '../../Shared/Components'
6
-import { InputGroup, Tooltip, Button, Classes, Intent } from '@blueprintjs/core'
7
-import { LOGIN } from '../../Store/Actions'
4
+import { Card, HiddenPassword } from '../../Shared/Components'
5
+import { InputGroup, Button } from '@blueprintjs/core'
8 6
 import './Login.scss'
9
-import { Map } from '../../utils'
10
-
11
-const PasswordToggler = ({show, toggle}) => 
12
-    <Tooltip content={`${show ? "Hide" : "Show"} Password`}>
13
-        <Button className={Classes.MINIMAL} intent={Intent.WARNING}
14
-            iconName={show ? "eye-off" : "eye-open"} onClick={toggle} />
15
-    </Tooltip>
16 7
 
17
-const Logo = () => <h1 className="logo"><img src="lighthouse.png"/><span>Lighthouse</span></h1>
8
+const send = e => {
9
+    e.preventDefault()
10
+    let data = (new Map(new FormData(e.target))).toObj()
11
+    firebase.auth().signInWithEmailAndPassword(data.email, data.password)
12
+            .catch(e => { console.error(`Firebase auth error: [${e.code}] ${e.message}`) })
13
+}
18 14
 
19
-const LoginTemplate = ({ togglePassword, showPassword, connect }) =>
15
+const Login = () =>
20 16
     <div className="flex-frame center">
21
-        <Logo />
17
+        <h1 className="logo"><img src="lighthouse.png"/><span>Lighthouse</span></h1>
22 18
         <Card>
23
-            <form onSubmit={e => connect('test', e)}>
19
+            <form onSubmit={send}>
24 20
                 <InputGroup name="email" placeholder="Email" leftIconName="user"/>
25
-                <InputGroup name="password" placeholder="Enter your password..." leftIconName="lock" 
26
-                    type={showPassword ? "text" : "password"}
27
-                    rightElement={<PasswordToggler show={showPassword} toggle={togglePassword} />}
28
-                />
21
+                <HiddenPassword name="password" placeholder="Enter your password..." />
29 22
                 <Button iconName="log-in" type="submit">Login</Button>
30 23
             </form>
31 24
         </Card>
32 25
     </div>
33 26
 
34
-class LoginContainer extends React.Component {
35
-    state = { showPassword: false }
36
-
37
-    togglePassword = () => this.setState({ showPassword: !this.state.showPassword })
38
-
39
-    connect = (test, e) => {
40
-        e.preventDefault()
41
-        let data = (new Map(new FormData(e.target))).toObj()
42
-        firebase.auth().signInWithEmailAndPassword(data.email, data.password)
43
-                .catch(e => { console.error(`Firebase auth error: [${e.code}] ${e.message}`) })
44
-    }
45
-
46
-    render() {
47
-        return <LoginTemplate
48
-            showPassword={this.state.showPassword}
49
-            togglePassword={this.togglePassword}
50
-            connect={this.connect}
51
-        />
52
-    }
53
-}
54
-
55
-const Login = connect(null, dispatch => ({ login: user => dispatch(LOGIN(user)) }))(LoginContainer)
56
-
57 27
 export default Login

+ 25
- 0
src/Pages/Notes/Note.jsx Visa fil

@@ -0,0 +1,25 @@
1
+import React from 'react'
2
+import MarkdownIt from 'markdown-it'
3
+import { DeleteButton, Card } from 'Components'
4
+import { EditableText } from '@blueprintjs/core'
5
+import brace from 'brace'
6
+import AceEditor from 'react-ace'
7
+import 'brace/mode/markdown'
8
+import 'brace/theme/tomorrow'
9
+
10
+const md = new MarkdownIt()
11
+
12
+const Note = ({ note, update, remove }) =>
13
+    <div className="Note">
14
+        <DeleteButton className="trash-btn" onConfirm={() => remove(note)} title={`Delete ${note.title}`}>
15
+            Do you really want to delete this note ? You won't be able to recover it.
16
+        </DeleteButton>
17
+        <h2><EditableText value={note.title} onChange={value => update({...note, title: value})} /></h2>
18
+        <div className="editor">
19
+            <Card noPadding className="source"><AceEditor editorProps={{$blockScrolling: true}} mode="markdown" theme="tomorrow"
20
+                        value={note.content} height="500px" width="inherit" onChange={value => update({...note, content: value})} /></Card>
21
+            <Card className="preview"><div dangerouslySetInnerHTML={{__html: md.render(note.content)}}></div></Card>
22
+        </div>
23
+    </div>
24
+
25
+export default Note

+ 12
- 0
src/Pages/Notes/NoteList.jsx Visa fil

@@ -0,0 +1,12 @@
1
+import React from 'react'
2
+import { Menu, MenuDivider, MenuItem } from '@blueprintjs/core'
3
+
4
+const NoteList = ({ notes, add, select }) =>
5
+    <Menu>
6
+        <MenuDivider title="Notes"/>
7
+        { notes.map(e => <MenuItem key={e.id} text={e.title} onClick={() => select(e)} />) }
8
+        <MenuDivider />
9
+        <MenuItem iconName="plus" text="New note" onClick={add}/>
10
+    </Menu>
11
+
12
+export default NoteList

+ 19
- 68
src/Pages/Notes/Notes.jsx Visa fil

@@ -1,86 +1,37 @@
1 1
 import React from 'react'
2 2
 import { connect } from 'react-redux'
3
-import MarkdownIt from 'markdown-it'
4
-import { Card, Placeholder, Icon } from '../../Shared/Components'
3
+import { Card, Placeholder, Icon, DeleteButton } from '../../Shared/Components'
5 4
 import { Menu, MenuDivider, MenuItem, EditableText, Intent, Button, Alert } from '@blueprintjs/core'
6
-import { SELECT_NOTE, UPDATE_NOTE, UPDATE_SELECTED_NOTE, ADD_NOTE, REMOVE_NOTE, UNSELECT_NOTE } from '../../Store/Actions'
5
+import * as actions from '../../Store/Actions/notes'
6
+import NoteList from './NoteList'
7
+import Note from './Note'
7 8
 import './Notes.scss'
8 9
 
9
-const md = new MarkdownIt()
10
-
11
-const NotesList = ({ notes, select }) =>
12
-    <div>
13
-        { notes.map(e => <MenuItem key={e.id} text={e.title} onClick={() => select(e)}></MenuItem>) }
14
-    </div>
15
-
16
-class AlertButton extends React.Component {
17
-    state = { open: false }
18
-
19
-    close = () => this.setState({ open: false })
20
-
21
-    show = () => this.setState({ open: true })
22
-
23
-    confirm = () => {
24
-        this.props.onConfirm()
25
-        this.close();
26
-    }
27
-
28
-    render() {
29
-        return (
30
-            <Button iconName={this.props.iconName} className={this.props.className} onClick={this.show}>
31
-                <Alert intent={Intent.DANGER} isOpen={this.state.open}
32
-                    confirmButtonText={this.props.confirmButtonText} cancelButtonText={this.props.cancelButtonText}
33
-                    onConfirm={this.confirm} onCancel={this.close} >
34
-                    {this.props.children}
35
-                </Alert>
36
-            </Button>
37
-        );
38
-    }
39
-}
40
-
41
-const Note = ({ note, update, remove }) =>
42
-    <div className="Note">
43
-        <AlertButton iconName="trash" className="trash-btn"
44
-            confirmButtonText="delete" cancelButtonText={"Cancel"}
45
-            onConfirm={() => remove(note)}>
46
-            Do you really want to delete this note ? You won't be able to recover it.
47
-        </AlertButton>
48
-        <h2>{note.title}</h2>
49
-        <div className="editor">
50
-            <EditableText className="source" multiline value={note.content} onChange={value => update({...note, content: value})}></EditableText>
51
-            <div className="preview" dangerouslySetInnerHTML={{__html: md.render(note.content)}}></div>
52
-        </div>
53
-    </div>
54
-
55
-
56
-const NotesTemplate = ({ notes, selectedNote, selectNote, updateNote, addNote, removeNote }) =>
10
+const NotesTemplate = ({ notes, selected, select, update, add, remove }) =>
57 11
     <div className="Notes">
58 12
         <Card className="List">
59
-            <Menu>
60
-                <MenuDivider title="Notes"/>
61
-                <NotesList notes={notes} select={selectNote}/>
62
-                <MenuDivider />
63
-                <MenuItem iconName="plus" text="New note" onClick={addNote}/>
64
-            </Menu>
13
+            <NoteList notes={notes} add={add} select={select} />
65 14
         </Card>
66 15
         <Card className="content">
67
-            { selectedNote ? <Note note={selectedNote} update={updateNote} remove={removeNote} /> :
68
-                <Placeholder iconName="clipboard" title="No note selected" description="Choose one in the list on the left"/> }
16
+            { selected ?
17
+                <Note note={selected} update={update} remove={remove} /> :
18
+                <Placeholder iconName="clipboard" title="No note selected"
19
+                             description="Choose one in the list on the left"/> }
69 20
         </Card>
70 21
     </div>
71 22
 
72 23
 const Notes = connect(
73
-    state => ({ notes: state.note.notes, selectedNote: state.note.selectedNote }),
24
+    state => ({ notes: state.note.notes, selected: state.note.selectedNote }),
74 25
     dispatch => ({
75
-        addNote: () => dispatch(ADD_NOTE()),
76
-        selectNote: note => dispatch(SELECT_NOTE(note)),
77
-        removeNote: note => {
78
-            dispatch(REMOVE_NOTE(note))
79
-            dispatch(UNSELECT_NOTE())
26
+        add: () => dispatch(actions.ADD_NOTE()),
27
+        select: note => dispatch(actions.SELECT_NOTE(note)),
28
+        remove: note => {
29
+            dispatch(actions.REMOVE_NOTE(note))
30
+            dispatch(actions.UNSELECT_NOTE())
80 31
         },
81
-        updateNote: note => {
82
-            dispatch(UPDATE_NOTE(note))
83
-            dispatch(UPDATE_SELECTED_NOTE(note))
32
+        update: note => {
33
+            dispatch(actions.UPDATE_NOTE(note))
34
+            dispatch(actions.UPDATE_SELECTED_NOTE(note))
84 35
         }
85 36
     })
86 37
 )(NotesTemplate)

+ 0
- 3
src/Pages/Notes/Notes.scss Visa fil

@@ -13,7 +13,6 @@
13 13
     .content {
14 14
         margin-left: $pt-grid-size;
15 15
         flex: 1;
16
-        max-height: 300px;
17 16
 
18 17
         .Note {
19 18
             .trash-btn {
@@ -23,7 +22,6 @@
23 22
             .editor {
24 23
                 display: flex;
25 24
                 flex-direction: row;
26
-                margin-top: $pt-grid-size * 4;
27 25
 
28 26
                 .source, .preview {
29 27
                     flex: 1;
@@ -32,5 +30,4 @@
32 30
             }
33 31
         }
34 32
     }
35
-
36 33
 }

+ 0
- 35
src/Shared/Components.jsx Visa fil

@@ -1,35 +0,0 @@
1
-import React from 'react'
2
-import cl from 'classnames'
3
-import { Link } from 'react-router-dom'
4
-
5
-export const Icon = ({ name, size, intent, className, ...otherProps }) => {
6
-    const classes = cl({
7
-        [`pt-icon-${size}`]: size,
8
-        [`pt-icon-${name}`]: name,
9
-        [`pt-intent-${intent}`]: intent,
10
-        [className]: true
11
-    })
12
-    return <span className={classes} {...otherProps}></span>
13
-}
14
-
15
-export const Card = ({ className, children, interactive, ...otherProps }) => 
16
-    <div className={cl(["pt-card", className, {'pt-interactive': interactive}])} {...otherProps}>{children}</div>
17
-
18
-export const Placeholder = ({ iconName, title, description, ...otherProps }) => 
19
-    <div className="pt-non-ideal-state" {...otherProps} >
20
-        <div className="pt-non-ideal-state-visual pt-non-ideal-state-icon">
21
-            <span className={`pt-icon pt-icon-${iconName}`}></span>
22
-        </div>
23
-        <h4 className="pt-non-ideal-state-title">{title}</h4>
24
-        <div className="pt-non-ideal-state-description">
25
-            {description}
26
-        </div>
27
-    </div>
28
-
29
-export const MenuLink = ({ to, iconName, children, ...otherProps }) => {
30
-    let classes = cl(["pt-menu-item","pt-popover-dismiss", {[`pt-icon-${iconName}`]: iconName}]);
31
-    return <li><Link to={to} className={classes} {...otherProps}>{children}</Link></li>
32
-}
33
-
34
-export const ProfilePic = ({ src }) => src ? <img src={src} /> :
35
-    <Placeholder iconName="mugshot" title="No picture" description="Click to change"/>

+ 17
- 0
src/Shared/Components/AlertButton.jsx Visa fil

@@ -0,0 +1,17 @@
1
+import React from 'react'
2
+import { Button, Alert, Intent } from '@blueprintjs/core'
3
+import Control from '../Control'
4
+
5
+const AlertButtonTemplate = (props, state) =>
6
+    <Button iconName={props.iconName} className={props.className} onClick={() => props.toggle(true)}>
7
+        <Alert intent={props.intent} isOpen={state.open}
8
+            confirmButtonText={props.confirmButtonText} cancelButtonText={props.cancelButtonText}
9
+            onConfirm={props.confirm} onCancel={() => props.toggle(false)} >
10
+            {props.children}
11
+        </Alert>
12
+    </Button>
13
+
14
+export const AlertButton = Control({ open: false }, {
15
+    toggle: ({ setState }, open) => setState({ open }),
16
+    confirm: ({ props }) => props.onConfirm()
17
+})(AlertButtonTemplate)

+ 6
- 0
src/Shared/Components/Card.jsx Visa fil

@@ -0,0 +1,6 @@
1
+import React from 'react'
2
+import cl from 'classnames'
3
+
4
+export const Card = ({ className, children, noPadding, interactive, ...otherProps }) => 
5
+    <div className={cl(["pt-card", className, {'pt-no-padding': noPadding, 'pt-interactive': interactive}])}
6
+        {...otherProps}>{children}</div>

+ 10
- 0
src/Shared/Components/DeleteButton.jsx Visa fil

@@ -0,0 +1,10 @@
1
+import React from 'react'
2
+import { Intent } from '@blueprintjs/core'
3
+import { DialogButton } from './DialogButton'
4
+
5
+export const DeleteButton = ({ title, onConfirm, children, className }) =>
6
+    <DialogButton iconName="trash" className={className}
7
+        confirmButtonText="Delete" cancelButtonText={"Cancel"}
8
+        title={title} onConfirm={onConfirm} intent={Intent.DANGER}>
9
+        { children }
10
+    </DialogButton>

+ 24
- 0
src/Shared/Components/DialogButton.jsx Visa fil

@@ -0,0 +1,24 @@
1
+import React from 'react'
2
+import { Dialog, Button } from '@blueprintjs/core'
3
+import Control from '../Control'
4
+
5
+const DialogButtonTemplate = (props, state) =>
6
+    <Button iconName={props.iconName} className={props.className}
7
+        onClick={() => props.toggle(true)} text={props.buttonText}>
8
+        <Dialog isOpen={state.open} onClose={() => props.toggle(false)} title={props.title}>
9
+            <div className="pt-dialog-body">
10
+                {props.children}
11
+            </div>
12
+            <div className="pt-dialog-footer">
13
+                <div className="pt-dialog-footer-actions">
14
+                    <Button text={props.cancelButtonText} onClick={() => props.toggle(false)}/>
15
+                    <Button intent={props.intent} onClick={props.confirm} text={props.confirmButtonText} />
16
+                </div>
17
+            </div>
18
+        </Dialog>
19
+    </Button>
20
+
21
+export const DialogButton = Control({ open: false }, {
22
+    toggle: ({ setState }, open) => setState({ open }),
23
+    confirm: ({ props }) => props.onConfirm()
24
+})(DialogButtonTemplate)

+ 21
- 0
src/Shared/Components/HiddenPassword.jsx Visa fil

@@ -0,0 +1,21 @@
1
+import React from 'react'
2
+import { Tooltip, Classes, Intent, InputGroup, Button } from '@blueprintjs/core'
3
+import Control from '../Control'
4
+
5
+const PasswordToggler = ({ show, toggle }) => 
6
+    <Tooltip content={`${show ? "Hide" : "Show"} Password`}>
7
+        <Button className={Classes.MINIMAL} intent={Intent.WARNING}
8
+            iconName={show ? "eye-off" : "eye-open"} onClick={toggle} />
9
+    </Tooltip>
10
+
11
+const PasswordInput = ({ name, placeholder, toggle }, { show }) =>
12
+    <InputGroup name={name} placeholder={placeholder} leftIconName="lock" 
13
+                type={show ? "text" : "password"}
14
+                rightElement={<PasswordToggler show={show} toggle={toggle} />}
15
+    />
16
+
17
+export const HiddenPassword = Control(
18
+    { show: false },
19
+    { toggle: ({ setState, state }) => { setState({ show: !state.show }) } }
20
+)(PasswordInput)
21
+

+ 11
- 0
src/Shared/Components/Icon.jsx Visa fil

@@ -0,0 +1,11 @@
1
+import react from 'react'
2
+
3
+export const Icon = ({ name, size, intent, className, ...otherProps }) => {
4
+    const classes = cl({
5
+        [`pt-icon-${size}`]: size,
6
+        [`pt-icon-${name}`]: name,
7
+        [`pt-intent-${intent}`]: intent,
8
+        [className]: true
9
+    })
10
+    return <span className={classes} {...otherProps}></span>
11
+}

+ 8
- 0
src/Shared/Components/MenuLink.jsx Visa fil

@@ -0,0 +1,8 @@
1
+import React from 'react'
2
+import cl from 'classnames'
3
+import { Link } from 'react-router-dom'
4
+
5
+export const MenuLink = ({ to, iconName, children, ...otherProps }) => {
6
+    let classes = cl(["pt-menu-item","pt-popover-dismiss", {[`pt-icon-${iconName}`]: iconName}]);
7
+    return <li><Link to={to} className={classes} {...otherProps}>{children}</Link></li>
8
+}

+ 12
- 0
src/Shared/Components/Placeholder.jsx Visa fil

@@ -0,0 +1,12 @@
1
+import React from 'react'
2
+
3
+export const Placeholder = ({ iconName, title, description, ...otherProps }) => 
4
+    <div className="pt-non-ideal-state" {...otherProps} >
5
+        <div className="pt-non-ideal-state-visual pt-non-ideal-state-icon">
6
+            <span className={`pt-icon pt-icon-${iconName}`}></span>
7
+        </div>
8
+        <h4 className="pt-non-ideal-state-title">{title}</h4>
9
+        <div className="pt-non-ideal-state-description">
10
+            {description}
11
+        </div>
12
+    </div>

+ 5
- 0
src/Shared/Components/ProfilePic.jsx Visa fil

@@ -0,0 +1,5 @@
1
+import React from 'react'
2
+import { Placeholder } from './Placeholder'
3
+
4
+export const ProfilePic = ({ src }) => src ? <img src={src} /> :
5
+    <Placeholder iconName="mugshot" title="No picture" description="Click to change"/>

+ 11
- 0
src/Shared/Components/index.js Visa fil

@@ -0,0 +1,11 @@
1
+import { DialogButton } from './DialogButton'
2
+import { AlertButton } from './AlertButton'
3
+import { HiddenPassword } from './HiddenPassword'
4
+
5
+export { DialogButton, AlertButton, HiddenPassword }
6
+export { Icon } from './Icon'
7
+export { DeleteButton } from './DeleteButton'
8
+export { Card } from './Card'
9
+export { Placeholder } from './Placeholder'
10
+export { MenuLink } from './MenuLink'
11
+export { ProfilePic } from './ProfilePic'

+ 21
- 0
src/Shared/Control.js Visa fil

@@ -0,0 +1,21 @@
1
+import React from 'react'
2
+import { mapValues } from 'lodash'
3
+
4
+export default (initialState, handlers) => Component => 
5
+    class extends React.Component {
6
+        state = initialState || {}
7
+
8
+        stateHandler = { setState: this.setState.bind(this) }
9
+
10
+        getProps = () => ({ ...this.props, ...this.handlersToProps })
11
+
12
+        prepareHandler = h => typeof h !== 'function' ? h : (...args) => h({
13
+             ...this.stateHandler, state: this.state, props: this.getProps()
14
+        }, ...args)
15
+
16
+        handlersToProps = !handlers ? null : _.mapValues(handlers, this.prepareHandler)
17
+
18
+        render() {
19
+            return Component(this.getProps(), this.state, this.stateHandler)
20
+        }
21
+    }

+ 2
- 4
src/Shared/Toaster.jsx Visa fil

@@ -1,8 +1,6 @@
1 1
 import { Position, Toaster } from "@blueprintjs/core";
2 2
  
3
-const AppToasts = Toaster.create({
3
+export default Toaster.create({
4 4
     className: "app-toaster",
5 5
     position: Position.TOP_RIGHT,
6
-});
7
-
8
-export default AppToasts
6
+});

+ 2
- 10
src/Store/Actions/index.js Visa fil

@@ -1,10 +1,2 @@
1
-import { LOGIN, LOGOUT, CHANGE_PIC } from './user'
2
-import {
3
-    ADD_NOTE, REMOVE_NOTE, UPDATE_NOTE,
4
-    SELECT_NOTE, UNSELECT_NOTE, UPDATE_SELECTED_NOTE
5
-} from './notes'
6
-export {
7
-    LOGIN, LOGOUT, CHANGE_PIC,
8
-    ADD_NOTE, REMOVE_NOTE, UPDATE_NOTE,
9
-    SELECT_NOTE, UNSELECT_NOTE, UPDATE_SELECTED_NOTE
10
-}
1
+export * from './user'
2
+export * from './notes'

+ 1
- 0
src/Store/Actions/notes.js Visa fil

@@ -1,4 +1,5 @@
1 1
 import { createAction } from 'redux-actions'
2
+
2 3
 export const ADD_NOTE = createAction('ADD_NOTE')
3 4
 export const REMOVE_NOTE = createAction('REMOVE_NOTE')
4 5
 export const UPDATE_NOTE = createAction('UPDATE_NOTE')

+ 1
- 0
src/Store/Actions/user.js Visa fil

@@ -1,4 +1,5 @@
1 1
 import { createAction } from 'redux-actions'
2
+
2 3
 export const LOGIN = createAction('LOGIN')
3 4
 export const LOGOUT = createAction('LOGOUT')
4 5
 export const CHANGE_PIC = createAction('CHANGE_PIC')

+ 1
- 3
src/Store/Reducers/index.js Visa fil

@@ -2,6 +2,4 @@ import { combineReducers } from 'redux'
2 2
 import user from './user'
3 3
 import note from './note'
4 4
 
5
-const reducers = combineReducers({ user, note })
6
-
7
-export default reducers
5
+export default combineReducers({ user, note })

+ 7
- 10
src/Store/Reducers/note.js Visa fil

@@ -1,10 +1,7 @@
1 1
 import { _ } from '../../utils'
2 2
 import { handleActions } from 'redux-actions'
3 3
 import { combineReducers } from 'redux'
4
-import {
5
-    ADD_NOTE, UPDATE_NOTE, UPDATE_SELECTED_NOTE,
6
-    REMOVE_NOTE, SELECT_NOTE, UNSELECT_NOTE
7
-} from '../Actions'
4
+import * as actions from '../Actions/notes'
8 5
 
9 6
 const MOCK_NOTES = [
10 7
     {id: _.uniqueId(), title: 'First note', content: 'This is a little note' },
@@ -12,15 +9,15 @@ const MOCK_NOTES = [
12 9
 ]
13 10
 
14 11
 const selectedNote = handleActions({
15
-    [SELECT_NOTE]: (state, action) => state = action.payload,
16
-    [UPDATE_SELECTED_NOTE]: (state, action) => ({...state, ...action.payload }),
17
-    [UNSELECT_NOTE]: (state, action) => null
12
+    [actions.SELECT_NOTE]: (state, action) => state = action.payload,
13
+    [actions.UPDATE_SELECTED_NOTE]: (state, action) => ({...state, ...action.payload }),
14
+    [actions.UNSELECT_NOTE]: (state, action) => null
18 15
 }, null)
19 16
 
20 17
 const notes = handleActions({
21
-    [ADD_NOTE]: (state, action) => [...state, { id: _.uniqueId(), title: 'new_note', content: '' }],
22
-    [UPDATE_NOTE]: (state, action) => _.updateWhere(state, action.payload, _.idCheck(action.payload.id)),
23
-    [REMOVE_NOTE]: (state, action) =>  _.reject(state, _.idCheck(action.payload.id)),
18
+    [actions.ADD_NOTE]: (state, action) => [...state, { id: _.uniqueId(), title: 'new_note', content: '' }],
19
+    [actions.UPDATE_NOTE]: (state, action) => _.updateWhere(state, action.payload, _.idCheck(action.payload.id)),
20
+    [actions.REMOVE_NOTE]: (state, action) =>  _.reject(state, _.idCheck(action.payload.id)),
24 21
 }, MOCK_NOTES)
25 22
 
26 23
 const note = combineReducers({ notes, selectedNote })

+ 4
- 4
src/Store/Reducers/user.js Visa fil

@@ -1,10 +1,10 @@
1 1
 import { handleActions } from 'redux-actions'
2
-import { LOGIN, LOGOUT, CHANGE_PIC } from '../Actions'
2
+import * as actions from '../Actions/user'
3 3
 
4 4
 const user = handleActions({
5
-  [LOGIN]: (state, action) => action.payload,
6
-  [LOGOUT]: (state, action) => null,
7
-  [CHANGE_PIC]: (state, action) => ({ ...state, photoURL: action.payload })
5
+  [actions.LOGIN]: (state, action) => action.payload,
6
+  [actions.LOGOUT]: (state, action) => null,
7
+  [actions.CHANGE_PIC]: (state, action) => ({ ...state, photoURL: action.payload })
8 8
 }, null);
9 9
 
10 10
 export default user;

+ 2
- 4
src/utils.js Visa fil

@@ -7,10 +7,8 @@ Map.prototype.toObj = function() {
7 7
 _.updateIndex = (array, value, index) =>
8 8
     [...array.slice(0, index), value, ...array.slice(index + 1)]
9 9
 
10
-_.updateWhere = (array, value, predicate) => {
11
-     const index = _.findIndex(array, predicate)
12
-     return _.updateIndex(array, value, index)
13
-}
10
+_.updateWhere = (array, value, predicate) => 
11
+    _.updateIndex(array, value, _.findIndex(array, predicate))
14 12
 
15 13
 _.idCheck = id => e => e.id === id
16 14
 

+ 7
- 3
webpack.config.js Visa fil

@@ -1,4 +1,5 @@
1
-const webpack = require('webpack');
1
+const webpack = require('webpack')
2
+const path = require('path')
2 3
 var ExtractTextPlugin = require('extract-text-webpack-plugin')
3 4
 
4 5
 const config = {
@@ -6,7 +7,7 @@ const config = {
6 7
         './src/index.js',
7 8
     ],
8 9
     output: {
9
-        path: __dirname + '/dist',
10
+        path: path.resolve(__dirname, 'dist'),
10 11
         publicPath: '/',
11 12
         filename: 'bundle.js'
12 13
     },
@@ -31,7 +32,10 @@ const config = {
31 32
         ]
32 33
     },
33 34
     resolve: {
34
-        extensions: ['*', '.js', '.jsx']
35
+        extensions: ['*', '.js', '.jsx'],
36
+        alias: {
37
+            Components: path.resolve(__dirname, 'src', 'Shared', 'Components')
38
+        }
35 39
     },
36 40
     plugins: [
37 41
         new ExtractTextPlugin({ filename: 'style.css', allChunks: true }),

+ 23
- 1
yarn.lock Visa fil

@@ -861,6 +861,12 @@ brace-expansion@^1.1.7:
861 861
     balanced-match "^0.4.1"
862 862
     concat-map "0.0.1"
863 863
 
864
+brace@^0.10.0:
865
+  version "0.10.0"
866
+  resolved "https://registry.yarnpkg.com/brace/-/brace-0.10.0.tgz#edef4eb9b0928ba1ee5f717ffc157749a6dd5d76"
867
+  dependencies:
868
+    w3c-blob "0.0.1"
869
+
864 870
 braces@^1.8.2:
865 871
   version "1.8.5"
866 872
   resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7"
@@ -2545,6 +2551,10 @@ lodash.clonedeep@^4.3.2:
2545 2551
   version "4.5.0"
2546 2552
   resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
2547 2553
 
2554
+lodash.isequal@^4.1.1:
2555
+  version "4.5.0"
2556
+  resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
2557
+
2548 2558
 lodash.memoize@^4.1.2:
2549 2559
   version "4.1.2"
2550 2560
   resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@@ -3394,7 +3404,7 @@ promise@^7.1.1:
3394 3404
   dependencies:
3395 3405
     asap "~2.0.3"
3396 3406
 
3397
-prop-types@^15.0.0, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@~15.5.7:
3407
+prop-types@^15.0.0, prop-types@^15.5.4, prop-types@^15.5.6, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@~15.5.7:
3398 3408
   version "15.5.9"
3399 3409
   resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.9.tgz#d478eef0e761396942f70c78e772f76e8be747c9"
3400 3410
   dependencies:
@@ -3495,6 +3505,14 @@ rc@^1.1.7:
3495 3505
     minimist "^1.2.0"
3496 3506
     strip-json-comments "~2.0.1"
3497 3507
 
3508
+react-ace@^4.3.0:
3509
+  version "4.3.0"
3510
+  resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-4.3.0.tgz#915818da019dbb762d034f52b1e0e173671b1292"
3511
+  dependencies:
3512
+    brace "^0.10.0"
3513
+    lodash.isequal "^4.1.1"
3514
+    prop-types "^15.5.8"
3515
+
3498 3516
 react-addons-css-transition-group@^15.5.2:
3499 3517
   version "15.5.2"
3500 3518
   resolved "https://registry.yarnpkg.com/react-addons-css-transition-group/-/react-addons-css-transition-group-15.5.2.tgz#ea7e0a9f0e1c27ca426da4efd3559915bd42ead2"
@@ -4371,6 +4389,10 @@ vm-browserify@0.0.4:
4371 4389
   dependencies:
4372 4390
     indexof "0.0.1"
4373 4391
 
4392
+w3c-blob@0.0.1:
4393
+  version "0.0.1"
4394
+  resolved "https://registry.yarnpkg.com/w3c-blob/-/w3c-blob-0.0.1.tgz#b0cd352a1a50f515563420ffd5861f950f1d85b8"
4395
+
4374 4396
 warning@^3.0.0:
4375 4397
   version "3.0.0"
4376 4398
   resolved "https://registry.yarnpkg.com/warning/-/warning-3.0.0.tgz#32e5377cb572de4ab04753bdf8821c01ed605b7c"