diff --git a/package-lock.json b/package-lock.json index 0d789ea1..dbb0a44c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "@types/node": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.0.tgz", - "integrity": "sha512-hWzNviaVFIr1TqcRA8ou49JaSHp+Rfabmnqg2kNvusKqLhPU0rIsGPUj5WJJ7ld4Bb7qdgLmIhLfCD1qS08IVA==", + "version": "10.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.3.3.tgz", + "integrity": "sha512-/gwCgiI2e9RzzZTKbl+am3vgNqOt7a9fJ/uxv4SqYKxenoEDNVU3KZEadlpusWhQI0A0dOrZ0T68JYKVjzmgdQ==", "dev": true }, "abab": { @@ -2961,7 +2961,7 @@ "object.values": "1.0.4", "prop-types": "15.6.1", "react-reconciler": "0.7.0", - "react-test-renderer": "16.4.0" + "react-test-renderer": "16.4.1" } }, "enzyme-adapter-utils": { @@ -2975,6 +2975,15 @@ "prop-types": "15.6.1" } }, + "enzyme-to-json": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.3.4.tgz", + "integrity": "sha1-Z8YEDpMRgvGDQYry659DIyWKp38=", + "dev": true, + "requires": { + "lodash": "4.17.10" + } + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -7399,7 +7408,7 @@ "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "@types/node": "10.3.0" + "@types/node": "10.3.3" } }, "parseurl": { @@ -9005,9 +9014,9 @@ "integrity": "sha512-FlsPxavEyMuR6TjVbSSywovXSEyOg6ZDj5+Z8nbsRl9EkOzAhEIcS+GLoQDC5fz/t9suhUXWmUrOBrgeUvrMxw==" }, "react-is": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.0.tgz", - "integrity": "sha512-8ADZg/mBw+t2Fbr5Hm1K64v8q8Q6E+DprV5wQ5A8PSLW6XP0XJFMdUskVEW8efQ5oUgWHn8EYdHEPAMF0Co6hA==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.1.tgz", + "integrity": "sha512-xpb0PpALlFWNw/q13A+1aHeyJyLYCg0/cCHPUA43zYluZuIPHaHL3k8OBsTgQtxqW0FhyDEMvi8fZ/+7+r4OSQ==", "dev": true }, "react-reconciler": { @@ -9208,15 +9217,15 @@ } }, "react-test-renderer": { - "version": "16.4.0", - "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.4.0.tgz", - "integrity": "sha512-Seh1t9xFY6TKiV/hRlPzUkqX1xHOiKIMsctfU0cggo1ajsLjoIJFL520LlrxV+4/VIj+clrCeH6s/aVv/vTStg==", + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.4.1.tgz", + "integrity": "sha512-wyyiPxRZOTpKnNIgUBOB6xPLTpIzwcQMIURhZvzUqZzezvHjaGNsDPBhMac5fIY3Jf5NuKxoGvV64zDSOECPPQ==", "dev": true, "requires": { "fbjs": "0.8.16", "object-assign": "4.1.1", "prop-types": "15.6.1", - "react-is": "16.4.0" + "react-is": "16.4.1" } }, "read-pkg": { diff --git a/package.json b/package.json index ba61363d..bf1cced6 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,11 @@ "devDependencies": { "enzyme": "^3.3.0", "enzyme-adapter-react-16": "^1.1.1", + "enzyme-to-json": "^3.3.4", "gh-pages": "^1.2.0" }, - "homepage": "http://adagold.github.io/inspiration-board" + "homepage": "http://adagold.github.io/inspiration-board", + "jest": { + "snapshotSerializers": ["enzyme-to-json/serializer"] + } } diff --git a/src/App.js b/src/App.js index c4854e15..6b0a64bd 100644 --- a/src/App.js +++ b/src/App.js @@ -1,21 +1,66 @@ import React, { Component } from 'react'; import './App.css'; import Board from './components/Board'; +import Status from './components/Status'; +import BoardSelection from './components/BoardSelection'; class App extends Component { - render() { - return ( -
-
-

Inspiration Board

-
- -
- ); - } + + constructor(){ + super(); + + this.state = { + status: { + message: "this is a message", + type: "and a type" + }, + board: 'karinna', + url: "https://inspiration-board.herokuapp.com/boards" + } + + } + + updateStatus = (mess, typ) => { + this.setState({ + status: { + message: mess, + type: typ + } + }) + } + + updateBoard = (name) => { + this.setState({ + board: name + }); + } + + + render() { + return ( +
+
+

Inspiration Board

+
+ + + + + + +
+ ); + } } export default App; diff --git a/src/components/Board.css b/src/components/Board.css index ba21589d..d6067eca 100644 --- a/src/components/Board.css +++ b/src/components/Board.css @@ -12,3 +12,13 @@ list-style-type: none; padding: 0; } + +.success { + background-color: grey; + color: darkgreen; +} + +.failure { + background-color: grey; + color: darkred; +} diff --git a/src/components/Board.js b/src/components/Board.js index 9222fd88..4772a25e 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -1,33 +1,125 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import axios from 'axios'; +import emoji from 'emoji-dictionary'; + import './Board.css'; import Card from './Card'; import NewCardForm from './NewCardForm'; import CARD_DATA from '../data/card-data.json'; + class Board extends Component { - constructor() { - super(); - - this.state = { - cards: [], - }; - } - - render() { - return ( -
- Board -
- ) - } -} + static propTypes = { + updateStatusCallback: PropTypes.func, + url: PropTypes.string, + name: PropTypes.string + } + constructor() { + super(); + + this.state = { + cards: [], + }; + + } + + + + componentDidMount(){ + axios.get(`${this.props.url}/${this.props.name}/cards`) + .then((response) =>{ + this.props.updateStatusCallback("Successfully loaded board", "success") + + this.setState({ + cards: response.data + }) + }) + .catch((error) => { + this.props.updateStatusCallback(`Failed to load: ${error.message}`, "failure") + }); + + } + + componentDidUpdate(prop, state) { + if (prop.name !== this.props.name) { + axios.get(`${this.props.url}/${prop.name}/cards`) + .then((response) =>{ + this.props.updateStatusCallback("Successfully loaded board", "success") -Board.propTypes = { + this.setState({ + cards: response.data, + name: prop.name + }) + }) + .catch((error) => { + this.props.updateStatusCallback(`Failed to load: ${error.message}`, "failure") + }); + } + } + + addCard = (card) => { + card.emoji = emoji.getName(card.emoji) + + axios.post(`${this.props.url}/${this.props.name}/cards`, card) + + .then((response) => { + let updatedCards = this.state.cards; + updatedCards.push({card}); + this.setState({ cards: updatedCards }); + this.props.updateStatusCallback(`Successfully added card`, "success") + }) + .catch((error) => { + this.props.updateStatusCallback(`Failed to add Card: ${error.message}`, "failure") + }); + + } + + deleteCard = (card) => { + console.log(card); + axios.delete(`${this.props.url}/${this.props.name}/cards/${card.props.id}`) + .then((response) => { + this.props.updateStatusCallback("Successfully Deleted Card", "success") + let updatedCards = this.state.cards; + updatedCards.splice(card.props.index,1) + this.setState({ + cards: updatedCards + }) + }) + .catch((error) => { + this.props.updateStatusCallback(`Failed to add card: ${error.message}`, "failure") + }); + } + + render() { + + const cardCollection = this.state.cards.map((obj, index) =>{ + return + }); + + return ( +
+
+ +
+
+ {cardCollection} +
+
+ ) + } + +} -}; export default Board; diff --git a/src/components/Board.test.js b/src/components/Board.test.js index e69de29b..8bc155df 100644 --- a/src/components/Board.test.js +++ b/src/components/Board.test.js @@ -0,0 +1,15 @@ +import React from 'react'; +import Board from './Board'; +import {shallow} from 'enzyme'; + +describe('Board', () => { + + test('shallow mount', () => { + const board = shallow( {}} + />); + expect(board).toMatchSnapshot(); + }); +}); diff --git a/src/components/BoardSelection.css b/src/components/BoardSelection.css new file mode 100644 index 00000000..7cbe95e7 --- /dev/null +++ b/src/components/BoardSelection.css @@ -0,0 +1,6 @@ +.selection { + font-family: 'Raleway', sans-serif; + font-size: 1.25em; + text-align: center; + margin-left: 40%; +} diff --git a/src/components/BoardSelection.js b/src/components/BoardSelection.js new file mode 100644 index 00000000..1f1630f6 --- /dev/null +++ b/src/components/BoardSelection.js @@ -0,0 +1,69 @@ +import React from 'react'; +import axios from 'axios'; +import PropTypes from 'prop-types'; +import './BoardSelection.css'; + +class BoardSelection extends React.Component { + + static propTypes = { + updateBoardCallback: PropTypes.func.isRequired, + url: PropTypes.string.isRequired, + board: PropTypes.string + } + + constructor(){ + super(); + this.state = { + boards: [] + } + } + + componentDidMount(){ + axios.get(this.props.url) + .then((response) => { + + const updatedNames = response.data.map((obj, index) => { + return obj.board.name + }); + + this.setState({ + boards: updatedNames + }) + }) + .catch((error) => { + + }); + } + onBoardUpdate = (event) => { + console.log("in update!"); + this.props.updateBoardCallback(event.target.value); + this.setState({ + board: event.target.value + }) + } + + render(){ + const selectOptions = this.state.boards.map((board, index) => { + return + }); + + return ( + + ) + } + + + + + +} + + + +export default BoardSelection; diff --git a/src/components/BoardSelection.test.js b/src/components/BoardSelection.test.js new file mode 100644 index 00000000..5ba48458 --- /dev/null +++ b/src/components/BoardSelection.test.js @@ -0,0 +1,14 @@ +import React from 'react'; +import BoardSelection from './BoardSelection'; +import {shallow} from 'enzyme'; + +describe('BoardSelection', () => { + + test('shallow mount', () => { + const boardSelection = shallow( {}} + />); + expect(boardSelection).toMatchSnapshot(); + }); +}); diff --git a/src/components/Card.css b/src/components/Card.css index e86d4329..977e2ddf 100644 --- a/src/components/Card.css +++ b/src/components/Card.css @@ -12,6 +12,7 @@ display: grid; grid-template-columns: 1fr 5fr 1fr; + grid-template-rows: .5fr 5fr; align-items: center; } @@ -43,5 +44,8 @@ .card__delete { align-self: start; + grid-column-start: 3; + background: inherit; + border: none; font-family: 'Permanent Marker', Helvetica, sans-serif; } diff --git a/src/components/Card.js b/src/components/Card.js index 6788cc03..52a0866e 100644 --- a/src/components/Card.js +++ b/src/components/Card.js @@ -5,17 +5,48 @@ import emoji from 'emoji-dictionary'; import './Card.css'; class Card extends Component { - render() { - return ( -
- Card -
- ) - } -} -Card.propTypes = { + static propTypes = { + index: PropTypes.number, + text: PropTypes.string, + emoji: PropTypes.string, + deleteCardCallback: PropTypes.func.isRequired + } + + getEmoji = () => { + if (this.props.emoji != null) { + return
{emoji.getUnicode(this.props.emoji)}
+ } + } + + getText = () => { + if (this.props.text != null) { + return

{this.props.text}

+ } + } + + onButtonClick = () => { + this.props.deleteCardCallback(this) + } + + + render() { + return ( +
+ +
+ {this.getText()} + {this.getEmoji()} +
+
+ ) + } +} -}; export default Card; diff --git a/src/components/Card.test.js b/src/components/Card.test.js new file mode 100644 index 00000000..bb0ea7a1 --- /dev/null +++ b/src/components/Card.test.js @@ -0,0 +1,16 @@ +import React from 'react'; +import Card from './Card'; +import {shallow} from 'enzyme'; + +describe('Card', () => { + + test('shallow mount', () => { + const card = shallow( {}} + />); + expect(card).toMatchSnapshot(); + }); +}); diff --git a/src/components/NewCardForm.js b/src/components/NewCardForm.js index 47331423..98defab2 100644 --- a/src/components/NewCardForm.js +++ b/src/components/NewCardForm.js @@ -3,4 +3,91 @@ import PropTypes from 'prop-types'; import emoji from 'emoji-dictionary'; import './NewCardForm.css'; -const EMOJI_LIST = ["", "heart_eyes", "beer", "clap", "sparkling_heart", "heart_eyes_cat", "dog"] +const EMOJI_LIST = [ + "", + "heart_eyes", + "beer", + "pizza", + "laughing", + "kissing_heart", + "taco", + "sparkling_heart", + "bug", + "sunflower", + "dog" +] + +class NewCardForm extends Component { + + static propTypes = { + addCardCallback: PropTypes.func.isRequired + } + + constructor(){ + super(); + this.state = { + text: '', + emoji: '' + } + } + + onInputChange = (event) => { + let updatedInput = {}; + updatedInput[event.target.name] = event.target.value; + + this.setState( updatedInput ); + } + + onFormSubmit = (event) => { + event.preventDefault(); + this.props.addCardCallback(this.state); + + this.setState({ + text: '', + emoji: '' + }); + } + + render(){ + + const emojiInput = EMOJI_LIST.map((emo, key) => { + return + }); + + + return( +
+ + + + + +
+ ); + } +} + +export default NewCardForm; diff --git a/src/components/NewCardForm.test.js b/src/components/NewCardForm.test.js index e69de29b..5572a4e9 100644 --- a/src/components/NewCardForm.test.js +++ b/src/components/NewCardForm.test.js @@ -0,0 +1,13 @@ +import React from 'react'; +import NewCardForm from './NewCardForm'; +import {shallow} from 'enzyme'; + +describe('NewCardForm', () => { + + test('shallow mount', () => { + const newForm = shallow( {}} + />); + expect(newForm).toMatchSnapshot(); + }); +}); diff --git a/src/components/Status.js b/src/components/Status.js new file mode 100644 index 00000000..1419b582 --- /dev/null +++ b/src/components/Status.js @@ -0,0 +1,18 @@ +import React from 'react'; +import PropTypes from 'prop-types' + +class Status extends React.Component { + static propTypes = { + message: PropTypes.string, + type: PropTypes.string + } + render(){ + return ( +
+

{this.props.message}

+
+ ) + } +} + +export default Status; diff --git a/src/components/__snapshots__/Board.test.js.snap b/src/components/__snapshots__/Board.test.js.snap new file mode 100644 index 00000000..9f5a7c09 --- /dev/null +++ b/src/components/__snapshots__/Board.test.js.snap @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Board shallow mount 1`] = ` +
+
+ +
+
+
+`; diff --git a/src/components/__snapshots__/BoardSelection.test.js.snap b/src/components/__snapshots__/BoardSelection.test.js.snap new file mode 100644 index 00000000..af7c9487 --- /dev/null +++ b/src/components/__snapshots__/BoardSelection.test.js.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`BoardSelection shallow mount 1`] = ` + + + + +`; diff --git a/src/data/card-data.json b/src/data/card-data.json index 1f9793ec..068e019d 100644 --- a/src/data/card-data.json +++ b/src/data/card-data.json @@ -6,7 +6,7 @@ }, { "text": "", - "Emoji": "heart_eyes" + "emoji": "heart_eyes" }, { "text": "REST is part of work" diff --git a/src/setupTests.js b/src/setupTests.js index fc7b0dce..ca4bc6ea 100644 --- a/src/setupTests.js +++ b/src/setupTests.js @@ -1,4 +1,6 @@ import Enzyme from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; +import { configure } from 'enzyme'; +configure({ adapter: new Adapter() }); Enzyme.configure({ adapter: new Adapter() });