From f9724f3c8e8bf287d278defe95229013c1dc33c2 Mon Sep 17 00:00:00 2001 From: Mikko Koski Date: Mon, 13 Feb 2017 14:50:44 +0200 Subject: [PATCH] Integration SDK: Search listings from SDK and API --- package.json | 3 +- src/components/ListingCard/ListingCard.js | 4 +- src/containers/SearchPage/SearchPage.ducks.js | 71 ++++++++++++++++++- src/sagas.js | 15 +++- yarn.lock | 33 ++++++++- 5 files changed, 117 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 5d2a1298..ac913cdd 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,8 @@ "sanitize.css": "^4.1.0", "sharetribe-scripts": "0.8.6", "source-map-support": "^0.4.11", - "url": "^0.11.0" + "url": "^0.11.0", + "sharetribe-sdk": "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js.git" }, "devDependencies": { "enzyme": "^2.7.1", diff --git a/src/components/ListingCard/ListingCard.js b/src/components/ListingCard/ListingCard.js index 2d270c20..507fdbd0 100644 --- a/src/components/ListingCard/ListingCard.js +++ b/src/components/ListingCard/ListingCard.js @@ -52,10 +52,10 @@ const ListingCard = props => { ListingCard.defaultProps = { location: null, review: {}, author: {} }; -const { number, shape, string } = PropTypes; +const { shape, string } = PropTypes; ListingCard.propTypes = { - id: number.isRequired, + id: string.isRequired, title: string.isRequired, price: string.isRequired, description: string.isRequired, diff --git a/src/containers/SearchPage/SearchPage.ducks.js b/src/containers/SearchPage/SearchPage.ducks.js index 68626377..949b9fd6 100644 --- a/src/containers/SearchPage/SearchPage.ducks.js +++ b/src/containers/SearchPage/SearchPage.ducks.js @@ -5,8 +5,11 @@ */ import { unionWith, isEqual } from 'lodash'; import { call, put, takeEvery } from 'redux-saga/effects'; +import { types } from 'sharetribe-sdk'; import { createRequestTypes } from '../../util/sagaHelpers'; +const { LatLng } = types; + // ================ Action types ================ // export const ADD_FILTER = 'app/SearchPage/ADD_FILTER'; @@ -64,11 +67,73 @@ export const loadListings = { // ================ Worker sagas ================ // +/** + Take `included` values from the JSON API response + and transforms it to a map which provide easy and fast lookup. + Example: + ``` + const included = [ + { id: new UUID(123), type: 'user', attributes: { name: "John" }}, + { id: new UUID(234), type: 'user', attributes: { name: "Jane" }}, + ]; + const map = lookupMap(included) + #=> returns + # { + # user: { + # 123: { id: 123, type: 'user', attributes: { name: "John" }}, + # 234: { id: 234, type: 'user', attributes: { name: "Jane" }}, + # } + # } + map.user.123 + #=> returns + # { id: 123, type: 'user', attributes: { name: "John" }}, + ``` + */ +const lookupMap = included => included.reduce((memo, resource) => { + const { type, id } = resource; + + // eslint-disable-next-line no-param-reassign + memo[type] = memo[type] || {}; + // eslint-disable-next-line no-param-reassign + memo[type][id.uuid] = resource; + + return memo; +}, {}); + +// Format the data as ListingCard component expects it and +// add some fake data +// TODO Remove this and think about the real implementation +const formatListingData = response => { + const includedMap = lookupMap(response.data.included); + const data = response.data.data; + + return data.map(({ id, attributes, relationships }) => { + const author = includedMap.user[relationships.author.data.id.uuid]; + const { firstName, lastName } = author.attributes.profile; + + return { + id: id.uuid, + title: attributes.title, + description: attributes.description, + location: attributes.address, + price: '55\u20AC / day', + author: { + name: `${firstName} ${lastName}`, + avatar: 'http://placehold.it/44x44', + review: { rating: '4' }, + }, + }; + }); +}; + export function* callFetchListings(sdk) { try { - const response = yield call(sdk.fetchListings); - yield put(loadListings.success(response)); - } catch(error) { + const response = yield call(sdk.listings.search, { + origin: new LatLng(40, 70), + include: ['author'], + }); + yield put(loadListings.success(formatListingData(response))); + } catch (error) { yield put(loadListings.failure(error)); } } diff --git a/src/sagas.js b/src/sagas.js index 86182634..4b43b57f 100644 --- a/src/sagas.js +++ b/src/sagas.js @@ -1,6 +1,14 @@ +import { createInstance } from 'sharetribe-sdk'; + import { watchAuth } from './ducks/Auth.ducks'; import { watchLoadListings } from './containers/SearchPage/SearchPage.ducks'; -import sdk from './util/fakeSDK'; +// eslint-disable-next-line no-unused-vars +import fakeSdk from './util/fakeSDK'; + +const clientId = '08ec69f6-d37e-414d-83eb-324e94afddf0'; +const baseUrl = 'http://localhost:8088'; + +const sdk = createInstance({ clientId, baseUrl }); const mockLogin = (email, password) => new Promise((resolve, reject) => { window.setTimeout( @@ -25,5 +33,10 @@ const mockSdk = { login: mockLogin, logout: mockLogout }; export default function* rootSaga() { // TODO: inject sdk in function arguments + + // FakeSDK + // yield [watchAuth(mockSdk), watchLoadListings(fakeSdk)]; + + // Real SDK yield [watchAuth(mockSdk), watchLoadListings(sdk)]; } diff --git a/yarn.lock b/yarn.lock index 0c062c0a..3bd7ddf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -240,6 +240,12 @@ aws4@^1.2.1: version "1.5.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.5.0.tgz#0a29ffb79c31c9e712eeb087e8e7a64b4a56d755" +axios@^0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.15.3.tgz#2c9d638b2e191a08ea1d6cc988eadd6ba5bdc053" + dependencies: + follow-redirects "1.0.0" + babel-code-frame@6.22.0, babel-code-frame@^6.11.0, babel-code-frame@^6.16.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" @@ -2410,6 +2416,12 @@ flow-parser@0.38.0: colors ">=0.6.2" minimist ">=0.2.0" +follow-redirects@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.0.0.tgz#8e34298cbd2e176f254effec75a1c78cc849fd37" + dependencies: + debug "^2.2.0" + for-in@^0.1.5: version "0.1.6" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" @@ -3432,6 +3444,10 @@ js-base64@^2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" +js-cookie@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.1.3.tgz#48071625217ac9ecfab8c343a13d42ec09ff0526" + js-tokens@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.0.tgz#a2f2a969caae142fb3cd56228358c89366957bd1" @@ -5028,11 +5044,11 @@ pseudomap@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" -punycode@1.3.2: +punycode@1.3.2, punycode@^1.2.4: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" -punycode@^1.2.4, punycode@^1.4.1: +punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -5658,6 +5674,15 @@ sharetribe-scripts@0.8.6: optionalDependencies: fsevents "1.0.14" +"sharetribe-sdk@git+ssh://git@github.com/sharetribe/sharetribe-sdk-js.git": + version "0.0.1" + resolved "git+ssh://git@github.com/sharetribe/sharetribe-sdk-js.git#037a4328da4926428f6d36f19d349186d06f8aad" + dependencies: + axios "^0.15.3" + js-cookie "^2.1.3" + lodash "^4.17.4" + transit-js "^0.8.846" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" @@ -6021,6 +6046,10 @@ tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" +transit-js@^0.8.846: + version "0.8.846" + resolved "https://registry.yarnpkg.com/transit-js/-/transit-js-0.8.846.tgz#76e06e8f0e6be27675e3442112f5c9bb75343464" + tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb"