diff --git a/backend/build/server.js b/backend/build/server.js index f6aa941..9645ef4 100644 --- a/backend/build/server.js +++ b/backend/build/server.js @@ -71,11 +71,6 @@ var AGENTURA_KEY = process.env.AGENTURA_KEY || '1somethingverysecret'; var db = void 0; - //Monogo = await MongoClient.connect(url); - - // TODO: - // db.results.ensureIndex({loc:"2d"}) - //collection.ensureIndex("username",callback) router.get('/search', function () { var _ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee(req, res, next) { @@ -172,7 +167,10 @@ console.log('QUERY: ', query); _context.next = 18; - return properties.find(query).toArray(); + return properties.find(query, { + //"sort": [['field1','asc'], ['field2','desc']] + "sort": [['price', 'asc']] + }).toArray(); case 18: all = _context.sent; diff --git a/backend/server.js b/backend/server.js index 79ad61d..2646427 100644 --- a/backend/server.js +++ b/backend/server.js @@ -11,11 +11,6 @@ const PORT = process.env.PORT || 3001; const AGENTURA_KEY = process.env.AGENTURA_KEY || '1somethingverysecret'; let db; -//Monogo = await MongoClient.connect(url); - -// TODO: -// db.results.ensureIndex({loc:"2d"}) -//collection.ensureIndex("username",callback) router.get('/search', async (req, res, next) => { try { @@ -99,7 +94,10 @@ router.get('/search', async (req, res, next) => { } console.log('QUERY: ', query); - const all = await properties.find(query).toArray(); + const all = await properties.find(query, { + //"sort": [['field1','asc'], ['field2','desc']] + "sort": [['price','asc']] + }).toArray(); res.json(all); res.end(); diff --git a/crawler/specific/olx.js b/crawler/specific/olx.js index 5cc2fc5..e8aa542 100644 --- a/crawler/specific/olx.js +++ b/crawler/specific/olx.js @@ -63,10 +63,12 @@ export default class OlxCrawler { lng = matches[2]; } + const parsedPrice = parsePrice(price); + const data = { url, title, - price: parsePrice(price) || -1, + price: isNaN(parsedPrice) || price, size: parseFloat(size), rooms: parseRooms(rooms), floor: parseInt(floor), diff --git a/web/components/Filters.js b/web/components/Filters.js index 269fa1f..63fad2f 100644 --- a/web/components/Filters.js +++ b/web/components/Filters.js @@ -1,43 +1,72 @@ -import React from 'react'; +import React from "react"; +import { formatFilterNumber } from "../lib/helpers"; export default class Filters extends React.Component { - onCloseClick(e) { if (this.props.onClose) { this.props.onClose(); } } - onMaxPriceChange (e) { - this.props.dispatch({type: 'SET_MAX_PRICE', action: {maxPrice: e.target.value}}) + onMaxPriceChange(e) { + this.props.dispatch({ + type: "SET_MAX_PRICE", + action: { maxPrice: e.target.value } + }); } - onMinPriceChange (e) { - this.props.dispatch({type: 'SET_MIN_PRICE', action: {minPrice: e.target.value}}) + onMinPriceChange(e) { + this.props.dispatch({ + type: "SET_MIN_PRICE", + action: { minPrice: e.target.value } + }); + } + + onMaxSizeChange(e) { + this.props.dispatch({ + type: "SET_MAX_SIZE", + action: { maxSize: e.target.value } + }); + } + + onMinSizeChange(e) { + this.props.dispatch({ + type: "SET_MIN_SIZE", + action: { minSize: e.target.value } + }); } onRoomsClick(rooms) { - console.log('rooms:', rooms); this.props.dispatch({type: 'SET_ROOMS', action: {rooms}}); } - onRefreshClick () { - this.props.dispatch({type: 'UPDATE_SEARCH'}); + onRefreshClick() { + this.updateSearch(); + } + + onKeyPress (e) { + if (e.key === 'Enter') { + this.updateSearch(); + } + } + + updateSearch () { + this.props.dispatch({ type: "UPDATE_SEARCH" }); } render() { - - const {filters} = this.props; - - const selectedRooms = (val) => filters.rooms[val] ? 'selected' : ''; + const { filters } = this.props; + const selectedRooms = val => filters.rooms[val] ? "selected" : ""; return (
Uslovi Pretrage - + aria-hidden="true" + />
@@ -46,71 +75,122 @@ export default class Filters extends React.Component {
- izmedju KM i - {this.props.filters.dirty? : null} -
+ OD + + {" "} + DO + + {this.props.filters.priceDirty + ? + + + : null} +
TIP
-
-
- Stan -
-
- Kuća -
+
+
+ Stan
-
-
- Zemljište -
-
- Poslovni prostor -
+
+ Kuća
+
+
+
+ Zemljište +
+
+ Poslovni prostor +
+
KVADRATA
- izmedju - i + OD + + + DO + {" "} + + {this.props.filters.sizeDirty + ? + : null}
-
+
BROJ SOBA
-
+
Garsonjera
-
+
2
-
+
3
-
+
4+
-
-
+
-
Više Filtera
+
Više Filtera
-
-
-
-
-
) +
+
+
+ ); } } diff --git a/web/components/ListingDetails.js b/web/components/ListingDetails.js index 58bf88b..1b3bee7 100644 --- a/web/components/ListingDetails.js +++ b/web/components/ListingDetails.js @@ -1,5 +1,6 @@ import React from 'react'; import Gallery from './gallery'; +import {formatPrice} from '../lib/helpers'; export default class ListingDetails extends React.Component { onReadMore (e) { @@ -48,7 +49,7 @@ export default class ListingDetails extends React.Component { imageIndex={this.props.imageIndex} />
- {listing.price.toLocaleString('bs')} KM + {formatPrice(listing.price)}
diff --git a/web/components/Listings.js b/web/components/Listings.js index c8d7f1c..51c9fc4 100644 --- a/web/components/Listings.js +++ b/web/components/Listings.js @@ -1,4 +1,5 @@ import React from 'react'; +import {formatPrice} from '../lib/helpers'; export default class Listings extends React.Component { onListingClick(id) { @@ -24,7 +25,7 @@ export default class Listings extends React.Component {
-
{l.price.toLocaleString('bs')} KM
+
{formatPrice(l.price)}
{l.rooms ? `${l.rooms} sobe, `: null}{l.size ? `${l.size}m2`: null}
diff --git a/web/components/Main.js b/web/components/Main.js index d937f70..09b0c5b 100644 --- a/web/components/Main.js +++ b/web/components/Main.js @@ -14,7 +14,6 @@ class Main extends React.Component { listings: (new Map()), imageIndex: 0, filters: { - minPrice: 0, rooms: {} } }; @@ -100,40 +99,44 @@ class Main extends React.Component { refreshListings() { const map = this.map; + const {rooms, minSize, maxSize, minPrice, maxPrice} = this.state.filters; + const properties = loadProperties({ bounds: map.getBounds().toUrlValue(), - minPrice: this.state.filters.minPrice, - maxPrice: this.state.filters.maxPrice, - rooms: this.state.filters.rooms + rooms, + minSize, + maxSize, + minPrice, + maxPrice }); - properties.then(p=> p.text()).then(p => { - const data = JSON.parse(p); - console.log('props', data) - for(const [index, prop] of data.entries()) { - const myLatLng = {lat: prop.loc[0], lng: prop.loc[1]}; + properties.then(p=> p.text()).then(p => { + const data = JSON.parse(p); + console.log('props', data) + for(const [index, prop] of data.entries()) { + const myLatLng = {lat: prop.loc[0], lng: prop.loc[1]}; - const marker = new google.maps.Marker({ - position: myLatLng, - map: map, - title: prop.title - }); - - marker.addListener('click', () => { - console.log('clicking...') - this.dispatch({type: 'VIEW_LISTING_DETAILS', action: { - id: prop.url - }}) - }); - } - - this.dispatch({ - type: 'LISTINGS_LOADED', - action: { - listings: data - } + const marker = new google.maps.Marker({ + position: myLatLng, + map: map, + title: prop.title }); - }) + + marker.addListener('click', () => { + console.log('clicking...') + this.dispatch({type: 'VIEW_LISTING_DETAILS', action: { + id: prop.url + }}) + }); + } + + this.dispatch({ + type: 'LISTINGS_LOADED', + action: { + listings: data + } + }); + }) } onListingClick() { diff --git a/web/dist/index.html b/web/dist/index.html index 251c1c5..5666bf3 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -1,6 +1,7 @@ + KIVI - Najbolji način da pronađeš svoj dom diff --git a/web/dist/main.css b/web/dist/main.css index 05aa0a3..899f3db 100644 --- a/web/dist/main.css +++ b/web/dist/main.css @@ -581,7 +581,7 @@ html { letter-spacing: .26px; border-radius: 3px; background: #fff; - color: #5ab8f8; + color: #51bc6a; cursor: pointer; } @@ -783,3 +783,14 @@ html { } } + +.fa-refresh-custom { + font-size: 1.5em; + cursor: pointer; + color: #b6d53b; + padding: 5px; +} + +.hide { + display: none; +} diff --git a/web/lib/api.js b/web/lib/api.js index 6405ded..9e9851f 100644 --- a/web/lib/api.js +++ b/web/lib/api.js @@ -4,6 +4,8 @@ export const loadProperties = ({ bounds, minPrice = '', maxPrice = '', + minSize = '', + maxSize = '', rooms }) => { const allRooms = Object @@ -13,7 +15,7 @@ export const loadProperties = ({ // TODO: handle errors //return fetch(process.env.API_URL + '/api/search', { - return fetch(`http://localhost:3001/api/search?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}`, { + return fetch(`http://localhost:3001/api/search?bounds=${bounds}&minPrice=${minPrice}&maxPrice=${maxPrice}&rooms=${allRooms}&minSize=${minSize}&maxSize=${maxSize}`, { //credentials: 'include' }); diff --git a/web/lib/handlers.js b/web/lib/handlers.js index 4c69f0f..14c1d5f 100644 --- a/web/lib/handlers.js +++ b/web/lib/handlers.js @@ -1,125 +1,159 @@ -const setMaxPrice = ({type, action}, component) => { +const setMaxPrice = ({ type, action }, component) => { + const maxPrice = parseFloat(action.maxPrice); component.setState({ filters: { ...component.state.filters, - maxPrice: parseFloat(action.maxPrice), - dirty: true + maxPrice: isNaN(maxPrice) ? undefined : maxPrice, + priceDirty: true } - }) -} + }); +}; -const setMinPrice = ({type, action}, component) => { +const setMinPrice = ({ type, action }, component) => { + const minPrice = parseFloat(action.minPrice); component.setState({ filters: { ...component.state.filters, - minPrice: parseFloat(action.minPrice), - dirty: true + minPrice: isNaN(minPrice) ? undefined : minPrice, + priceDirty: true } - }) -} + }); +}; -const viewListingDetails= ({type, action}, component) => { +const setMinSize = ({ type, action }, component) => { + const minSize = parseFloat(action.minSize); + component.setState({ + filters: { + ...component.state.filters, + minSize: isNaN(minSize) ? undefined : minSize, + sizeDirty: true + } + }); +}; + +const setMaxSize = ({ type, action }, component) => { + const maxSize = parseFloat(action.maxSize); + component.setState({ + filters: { + ...component.state.filters, + maxSize: isNaN(maxSize) ? undefined : maxSize, + sizeDirty: true + } + }); +}; + +const viewListingDetails = ({ type, action }, component) => { component.setState({ listingDetails: true, listingId: action.id, descriptionExpanded: false, imageIndex: 0 - }) -} + }); +}; -const listingsLoaded = ({type, action}, component) => { +const listingsLoaded = ({ type, action }, component) => { const currentListings = new Map(); //component.state.listings; - for(const listing of action.listings) { - currentListings.set(listing.url, listing) + for (const listing of action.listings) { + currentListings.set(listing.url, listing); } component.setState({ listings: currentListings }); -} +}; -const expandDescription = ({type, action}, component) => { +const expandDescription = ({ type, action }, component) => { component.setState({ descriptionExpanded: true }); -} +}; -const prevImage = ({type, action}, component) => { +const prevImage = ({ type, action }, component) => { const index = component.state.imageIndex; if (index > 0) { component.setState({ imageIndex: index - 1 }); } -} +}; -const nextImage = ({type, action}, component) => { +const nextImage = ({ type, action }, component) => { const index = component.state.imageIndex; component.setState({ imageIndex: index + 1 }); -} +}; -const viewImage = ({type, action}, component) => { +const viewImage = ({ type, action }, component) => { component.setState({ imageIndex: action.index }); -} +}; -const searchPlaceChanged = ({type, action}, component) => { +const searchPlaceChanged = ({ type, action }, component) => { component.setState({ listingDetails: false }); -} +}; -const setRooms = ({type, action}, component) => { - const prevRooms = (component.state.filters.rooms || {}); +const setRooms = ({ type, action }, component) => { + const prevRooms = component.state.filters.rooms || {}; + console.log('BERORE ROOMS'); - component.setState({ - filters: { - ...component.state.filters, - rooms: { - ...prevRooms, - [action.rooms]: !prevRooms[action.rooms] + component.setState( + { + filters: { + ...component.state.filters, + rooms: { + ...prevRooms, + [action.rooms]: !prevRooms[action.rooms] + } } + }, + () => { + console.log('after rooms'); + component.refreshListings(); } - }, () => { - component.refreshListings(); - }); -} + ); +}; -const updateSearch = ({type, action}, component) => { - console.log('updating search'); - component.setState({ - filters: { - ...component.state.filters, - dirty: false +const updateSearch = ({ type, action }, component) => { + console.log("updating search"); + component.setState( + { + filters: { + ...component.state.filters, + sizeDirty: false, + priceDirty: false + } + }, + () => { + component.refreshListings(); } - }, () => { - component.refreshListings(); - }); -} + ); +}; const handlers = { - 'SET_MIN_PRICE': setMinPrice, - 'SET_MAX_PRICE': setMaxPrice, - 'LISTINGS_LOADED': listingsLoaded, - 'EXPAND_DESCRIPTION': expandDescription, - 'PREV_IMAGE': prevImage, - 'NEXT_IMAGE': nextImage, - 'VIEW_IMAGE': viewImage, - 'SEARCH_PLACE_CHANGED': searchPlaceChanged, - 'SET_ROOMS': setRooms, - 'VIEW_LISTING_DETAILS': viewListingDetails, - 'UPDATE_SEARCH': updateSearch -} - -export const handleMessage = ({type, action}, component) => { + SET_MIN_PRICE: setMinPrice, + SET_MAX_PRICE: setMaxPrice, + SET_MIN_SIZE: setMinSize, + SET_MAX_SIZE: setMaxSize, + LISTINGS_LOADED: listingsLoaded, + EXPAND_DESCRIPTION: expandDescription, + PREV_IMAGE: prevImage, + NEXT_IMAGE: nextImage, + VIEW_IMAGE: viewImage, + SEARCH_PLACE_CHANGED: searchPlaceChanged, + SET_ROOMS: setRooms, + VIEW_LISTING_DETAILS: viewListingDetails, + UPDATE_SEARCH: updateSearch +}; +export const handleMessage = ({ type, action }, component) => { if (!handlers[type]) { - throw new `Unhandled message: ${type}`; + throw new `Unhandled message: ${type}`(); } - return handlers[type]({type, action}, component); -} + return handlers[type]({ type, action }, component); +}; diff --git a/web/lib/helpers.js b/web/lib/helpers.js new file mode 100644 index 0000000..25ddffb --- /dev/null +++ b/web/lib/helpers.js @@ -0,0 +1,14 @@ +export const formatPrice = (p) => { + if (p === -1) { + return 'Po dogovoru' + } + + return p.toLocaleString('bs') + ' KM'; +} + +export const formatFilterNumber = (num) => { + if (isNaN(num) || num == null) { + return '' + } + return num; +} diff --git a/web/package.json b/web/package.json index 7a8995d..b406aed 100644 --- a/web/package.json +++ b/web/package.json @@ -19,6 +19,7 @@ "babel-loader": "^6.2.7", "babel-preset-es2015": "^6.18.0", "babel-preset-react": "^6.16.0", + "prettier": "^0.22.0", "webpack": "^1.13.3", "webpack-dev-server": "^1.16.2" } diff --git a/web/yarn.lock b/web/yarn.lock index c57e84e..17a1e6d 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -42,6 +42,12 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1" + dependencies: + color-convert "^1.0.0" + anymatch@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" @@ -104,6 +110,14 @@ assert@^1.1.1: dependencies: util "0.10.3" +ast-types@0.8.18: + version "0.8.18" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.18.tgz#c8b98574898e8914e9d8de74b947564a9fe929af" + +ast-types@0.9.4: + version "0.9.4" + resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.4.tgz#410d1f81890aeb8e0a38621558ba5869ae53c91b" + async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" @@ -132,7 +146,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.22.0: +babel-code-frame@^6.22.0, babel-code-frame@6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -695,6 +709,10 @@ babylon@^6.11.0, babylon@^6.15.0: version "6.16.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" +babylon@6.15.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.15.0.tgz#ba65cfa1a80e1759b0e89fb562e27dccae70348e" + balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" @@ -795,7 +813,7 @@ center-align@^0.1.1: align-text "^0.1.3" lazy-cache "^1.0.3" -chalk@^1.1.0: +chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3, chalk@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -840,6 +858,20 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" +color-convert@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" + +colors@>=0.6.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" + combined-stream@^1.0.5, combined-stream@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" @@ -1044,7 +1076,7 @@ escape-string-regexp@^1.0.2: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -esutils@^2.0.0, esutils@^2.0.2: +esutils@^2.0.0, esutils@^2.0.2, esutils@2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" @@ -1190,6 +1222,14 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" +flow-parser@0.40.0: + version "0.40.0" + resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.40.0.tgz#b3444742189093323c4319c4fe9d35391f46bcbc" + dependencies: + ast-types "0.8.18" + colors ">=0.6.2" + minimist ">=0.2.0" + for-in@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -1261,6 +1301,10 @@ gauge@~2.7.1: strip-ansi "^3.0.1" wide-align "^1.1.0" +get-stdin@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + getpass@^0.1.1: version "0.1.6" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6" @@ -1280,7 +1324,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.5: +glob@^7.0.5, glob@7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -1533,6 +1577,22 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" +jest-matcher-utils@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-19.0.0.tgz#5ecd9b63565d2b001f61fbf7ec4c7f537964564d" + dependencies: + chalk "^1.1.3" + pretty-format "^19.0.0" + +jest-validate@19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-19.0.0.tgz#8c6318a20ecfeaba0ba5378bfbb8277abded4173" + dependencies: + chalk "^1.1.1" + jest-matcher-utils "^19.0.0" + leven "^2.0.0" + pretty-format "^19.0.0" + jodid25519@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" @@ -1600,6 +1660,10 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" +leven@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + loader-utils@^0.2.11, loader-utils@^0.2.16: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" @@ -1691,7 +1755,7 @@ minimatch@^3.0.0, minimatch@^3.0.2: dependencies: brace-expansion "^1.0.0" -minimist@^1.2.0: +minimist@^1.2.0, minimist@>=0.2.0, minimist@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" @@ -1930,6 +1994,27 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier: + version "0.22.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-0.22.0.tgz#7b37c4480d0858180407e5a8e13f0f47da7385d2" + dependencies: + ast-types "0.9.4" + babel-code-frame "6.22.0" + babylon "6.15.0" + chalk "1.1.3" + esutils "2.0.2" + flow-parser "0.40.0" + get-stdin "5.0.1" + glob "7.1.1" + jest-validate "19.0.0" + minimist "1.2.0" + +pretty-format@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-19.0.0.tgz#56530d32acb98a3fa4851c4e2b9d37b420684c84" + dependencies: + ansi-styles "^3.0.0" + private@^0.1.6: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1"