Compare commits

...

936 commits

Author SHA1 Message Date
Omar Najjar
7fa386fb0a
Merge pull request #1 from najomar68/omar-stashDesignChanges
changed logo and background images
2019-09-30 13:37:51 +10:00
Omar
1c77fadc77 stash changes 2019-09-30 13:03:11 +10:00
Juho Makkonen
3fb0c12770
Add link to Slack 2019-09-17 16:56:54 +03:00
Vesa Luusua
1968d26de8
Merge pull request #1202 from sharetribe/v3.5.1
New release: v3.5.1
2019-09-17 12:55:41 +03:00
Vesa Luusua
57c243f191 New release: v3.5.1 2019-09-17 12:53:21 +03:00
Vesa Luusua
e2213a8b18
Merge pull request #1200 from rush1506/master
[fix bugs] current CustomOverlayView in SearchMapWithGoogleMap does not work with new React version
2019-09-17 12:46:02 +03:00
tam.vu
dc6b6f813f Run prettier format for modified files 2019-09-17 13:33:25 +07:00
tam.vu
3ee4612504 Change CustomOverlayView in SearchMapWithGoogleMap:
- Adding onAdd and onRemove function to improve performance
- Rewrite current draw() method to compatible with newer react version
2019-09-16 14:00:44 +07:00
Jenni Laakso
483c590aef
Merge pull request #1197 from sharetribe/v3.5.0
v3.5.0
2019-09-13 13:10:40 +03:00
Jenni Nurmi
64351bb3a2 Update changelog 2019-09-13 13:08:27 +03:00
Jenni Laakso
7ac10dc42e
Merge pull request #1195 from sharetribe/time-to-bookingbreakdown
Show also time in booking breakdown if needed
2019-09-13 12:11:16 +03:00
Jenni Nurmi
54b97cb15e Update changelog 2019-09-13 12:07:31 +03:00
Jenni Nurmi
6e40507ea8 Use updated BookingBreakdown component 2019-09-13 12:07:31 +03:00
Jenni Nurmi
770a487c4d Fix proptype in BookingTimeInfo 2019-09-13 12:07:31 +03:00
Jenni Nurmi
dbf963445c Update BookingBreakdown 2019-09-13 12:07:22 +03:00
Jenni Nurmi
a00bbbfd80 Add new font size 15px 2019-09-12 11:10:01 +03:00
Jenni Nurmi
f3608721ae Create LineItemBasePriceMaybe component 2019-09-12 11:08:36 +03:00
Jenni Laakso
a707c4b4dd
Merge pull request #1194 from sharetribe/show-time-on-inboxpage
Show booking  date and time correctly on InboxPage
2019-09-10 17:25:23 +03:00
Jenni Nurmi
697003d1c6 Update changelog 2019-09-10 17:22:58 +03:00
Jenni Nurmi
570378f88c Use BookingTimeInfo on InboxPage 2019-09-10 17:22:58 +03:00
Jenni Nurmi
4c97c19858 Create BookingTimeInfo component 2019-09-10 17:22:53 +03:00
Jenni Laakso
cca0539c74
Merge pull request #1193 from sharetribe/update-es-translations
Update Spanish translations
2019-09-09 16:58:33 +03:00
Jenni Nurmi
d9a36bacde Update changelog 2019-09-09 10:08:11 +03:00
Jenni Nurmi
281050e696 Update Spanish translations 2019-09-09 10:07:12 +03:00
Vesa Luusua
3abe866e01
Merge pull request #1190 from sharetribe/missing-yarn-lock
Missing yarn.lock change
2019-08-30 11:45:14 +03:00
Vesa Luusua
7ba8a863b1 Update changelog 2019-08-30 11:43:09 +03:00
Vesa Luusua
579eb478ed For some reason yarn.lock was not up to date 2019-08-30 11:41:15 +03:00
Vesa Luusua
c98738aca9
Merge pull request #1189 from sharetribe/v3.4.0
New release: v3.4.0
2019-08-29 18:05:23 +03:00
Vesa Luusua
fbe7f9af37 New release: v3.4.0 2019-08-29 17:40:41 +03:00
Jenni Laakso
2390beab02
Merge pull request #1181 from sharetribe/update-intl
Update intl
2019-08-29 17:34:16 +03:00
Jenni Nurmi
fe92265201 Update changelog 2019-08-29 16:55:07 +03:00
Jenni Nurmi
efd7ac1a68 Update tests 2019-08-29 16:37:47 +03:00
Jenni Nurmi
3a88c0f386 Add textComponent prop to IntlProvider 2019-08-29 16:37:47 +03:00
Jenni Nurmi
a173e7271e Don't use addLocaleData 2019-08-29 16:37:47 +03:00
Jenni Nurmi
601706cc5f Use react-intl through util file 2019-08-29 16:37:47 +03:00
Jenni Nurmi
40c4bfb8fe Update react-intl to 3.1.13 2019-08-29 16:37:47 +03:00
Vesa Luusua
d6d456856d
Merge pull request #1186 from sharetribe/update-helmet-again
Update helmet again
2019-08-29 16:27:32 +03:00
Vesa Luusua
e08e23a8b1 Update changelog 2019-08-29 16:25:26 +03:00
Vesa Luusua
b156397ea0 Update helmet (v3.20.0 > v3.20.1) 2019-08-29 16:24:52 +03:00
Vesa Luusua
4d1e244629
Merge pull request #1188 from sharetribe/circumvent-lodash-vulnerability
Circumvent lodash vulnerability
2019-08-29 16:24:26 +03:00
Vesa Luusua
d85bb55f4f Update changelog 2019-08-29 16:21:31 +03:00
Vesa Luusua
ef11c17384 Fix lodash vulnerability: force newer version for react-google-maps and react-dates 2019-08-29 16:20:11 +03:00
Jenni Laakso
b5bde9da43
Merge pull request #1187 from sharetribe/add-changelog
Add React update to changelog
2019-08-29 16:18:51 +03:00
Jenni Nurmi
76f842f8df Add React update to changelog 2019-08-29 16:14:22 +03:00
Jenni Laakso
959ec06b2c
Merge pull request #1172 from sharetribe/update-react
Update react to 16.9.0
2019-08-29 16:00:19 +03:00
Jenni Nurmi
d5be9eb045 Temporarily remove tests related to react-dates to prevent deprecation warings 2019-08-29 15:44:51 +03:00
Vesa Luusua
e4222beac3 Update yarn.lock after merge conflict 2019-08-29 15:15:58 +03:00
Jenni Nurmi
c4bae634ec Don't use componentWillReceiveProps in Routes 2019-08-29 15:15:58 +03:00
Jenni Nurmi
5f7ffd737f Don't use componentWillReceiveProps in FieldDateRangeInput 2019-08-29 15:15:58 +03:00
Jenni Nurmi
3720591dda Don't use componentWillReceiveProps 2019-08-29 15:15:57 +03:00
Jenni Nurmi
34c4903bad Don't use componentWillReceiveProps related to SearchMap component 2019-08-29 15:15:57 +03:00
Jenni Nurmi
c13413170f Don't use componentWillReceiveProps related to modals 2019-08-29 15:15:57 +03:00
Jenni Nurmi
04fbf454aa Don't use deprecated lifecycle methods in FieldBirthdayInput 2019-08-29 15:15:57 +03:00
Jenni Nurmi
41972f70b3 Don't use componentWillMount 2019-08-29 15:15:57 +03:00
Jenni Nurmi
816584a93e Update react-dom to v16.9.0 2019-08-29 15:15:57 +03:00
Jenni Nurmi
4d906e2e96 Update react-test-renderer to 16.9.0 2019-08-29 15:15:57 +03:00
Jenni Nurmi
60232968da Update react to 16.9.0 2019-08-29 15:15:57 +03:00
Vesa Luusua
b8449fc588
Merge pull request #1185 from sharetribe/fix-willunmount-profilesettingsform
Fix componentWillUnmount on ProfileSettingsForm
2019-08-29 13:26:13 +03:00
Vesa Luusua
bace4600fd Update changelog 2019-08-29 13:19:57 +03:00
Vesa Luusua
fb384544df Fix willUnmount bug from ProfileSettingsForm 2019-08-29 13:17:51 +03:00
Vesa Luusua
8ed76db221
Merge pull request #1183 from sharetribe/fix-availabilityplan-prop
Fix availabilityplan prop validation in EditListingAvailabilityForm
2019-08-29 12:59:26 +03:00
Vesa Luusua
64746f29d7 Update changelog 2019-08-29 12:57:21 +03:00
Vesa Luusua
eed0b9b0e8 Fix: availabilityPlan prop in EditListingAvailabilityForm was missing. 2019-08-29 12:56:49 +03:00
Vesa Luusua
0ac72e2ff4
Merge pull request #1182 from sharetribe/fix-fieldbirthdayinput
Fix FieldBirthdayInput: valueFromForm prop didn't work anymore
2019-08-29 12:55:50 +03:00
Vesa Luusua
a3fd957971 Update changelog 2019-08-29 12:53:05 +03:00
Vesa Luusua
0509f5224f Fix FieldBirthdayInput: valueFromForm prop didn't work anymore 2019-08-29 12:52:24 +03:00
Jenni Laakso
3b463b64be
Merge pull request #1184 from sharetribe/translation-updates
Update French and German translations
2019-08-29 12:46:15 +03:00
Jenni Nurmi
faf3a4337a Update changelog 2019-08-29 10:08:45 +03:00
Jenni Nurmi
3d3af94a24 Update French translations 2019-08-29 10:04:37 +03:00
Jenni Nurmi
eaeece5f5d Update German translations 2019-08-29 10:04:23 +03:00
Vesa Luusua
1b953c4c78
Merge pull request #1180 from sharetribe/update-changelog-after-react-helmet-async
Update changelog
2019-08-28 15:13:18 +03:00
Vesa Luusua
28fcdc3496 Update changelog 2019-08-28 15:11:14 +03:00
Vesa Luusua
c2eb3c5cb0
Merge pull request #1179 from sharetribe/migrate-to-react-helmet-async
Migrate from react-helmet to react-helmet-async
2019-08-28 15:08:27 +03:00
Vesa Luusua
64c8df222d Migrate from react-helmet to react-helmet-async 2019-08-28 14:58:14 +03:00
Jenni Laakso
67a15563f3
Merge pull request #1177 from sharetribe/sanitize-css-to-own-file
Move sanitize.css to assets
2019-08-28 14:11:42 +03:00
Jenni Nurmi
0e98cc2294 Update changelog 2019-08-28 14:09:16 +03:00
Jenni Nurmi
b05b138550 Move sanitize.css to assets 2019-08-28 14:00:51 +03:00
Vesa Luusua
5955732b22
Merge pull request #1178 from sharetribe/fix-tests-after-react-redux
Fix: app.test.js started to throw warnings due to react-redux update
2019-08-28 13:44:23 +03:00
Vesa Luusua
30b4b4fbdd Update changelog 2019-08-28 13:25:41 +03:00
Vesa Luusua
709c36e623 Fix: app.test.js started to throw warnings due to react-redux update 2019-08-28 13:17:00 +03:00
Vesa Luusua
833d9fd76c
Merge pull request #1176 from sharetribe/update-react-redux
Update react-redux v5.1.1 -> v7.1.1
2019-08-27 16:40:20 +03:00
Jenni Laakso
fab719b977
Merge pull request #1175 from sharetribe/update-seedrandom
Update seedrandom to 3.0.3
2019-08-27 16:29:16 +03:00
Vesa Luusua
4232a23fa5 Update react-redux v5.1.1 -> v7.1.1 2019-08-27 16:26:38 +03:00
Jenni Nurmi
22b0b7c47f Update changelog 2019-08-27 16:17:06 +03:00
Jenni Nurmi
ebe069b162 Update seedrandom to 3.0.3 2019-08-27 16:13:14 +03:00
Jenni Laakso
a82dd4039b
Merge pull request #1174 from sharetribe/update-inquirer
Update inquirer to 7.0.0
2019-08-27 15:48:34 +03:00
Jenni Nurmi
edfe3e7095 Update changelog 2019-08-27 15:41:36 +03:00
Jenni Nurmi
c3a99e78e4 Update inquirer to 7.0.0 2019-08-27 15:40:43 +03:00
Vesa Luusua
dbfb5141a4
Merge pull request #1173 from sharetribe/update-final-form
Update Final Form et al.
2019-08-27 15:21:16 +03:00
Vesa Luusua
2fc75aec76 Update changelog 2019-08-27 15:14:55 +03:00
Vesa Luusua
87256f1fa7 Fix: do not remove previous state when publishing a listing 2019-08-27 15:05:26 +03:00
Vesa Luusua
3c80e194a8 Added missing proptype check 2019-08-27 14:16:31 +03:00
Vesa Luusua
cbd6b738a0 fix FieldBirthdayInput: example was broken 2019-08-27 14:15:34 +03:00
Vesa Luusua
dc61925e77 fix: fields having duplicate or undefined ids 2019-08-27 14:14:33 +03:00
Vesa Luusua
9eb4e7a125 pre-final-form naming pattern: form prop was conflicting with form api 2019-08-27 14:12:54 +03:00
Vesa Luusua
494ad56147 final form update: type is nowadays inside input props 2019-08-27 13:52:43 +03:00
Vesa Luusua
35039f5643 final form update: old recommendation format with null is not accepted anymore 2019-08-27 13:50:19 +03:00
Vesa Luusua
875b7ac108 Update final-form, final-form-arrays, react-final-form, react-final-form-arrays 2019-08-27 13:44:45 +03:00
Jenni Laakso
5fc4f43217
Merge pull request #1171 from sharetribe/update-react-dates
Update react-dates to 20.3.0
2019-08-26 17:06:53 +03:00
Jenni Nurmi
d50be5cdf8 Update changelog 2019-08-26 17:03:52 +03:00
Jenni Nurmi
0bb009d897 Update react-dates 2019-08-26 17:03:29 +03:00
Jenni Laakso
76c61bc52d
Merge pull request #1170 from sharetribe/update-prettier
Update prettier to 1.18.2
2019-08-26 17:03:02 +03:00
Jenni Nurmi
3f5c983e44 Update changelog 2019-08-26 17:00:27 +03:00
Jenni Nurmi
72d98a5912 Update prettier 2019-08-26 16:59:39 +03:00
Jenni Laakso
6186480a94
Merge pull request #1169 from sharetribe/update-path-to-regexp
Update path-to-regexp to 3.0.0
2019-08-26 16:58:52 +03:00
Jenni Nurmi
e138a05194 Update changelog 2019-08-26 10:29:15 +03:00
Jenni Nurmi
593777ffa1 Update path-to-regexp to 3.0.0 2019-08-26 10:27:07 +03:00
Jenni Laakso
a83a4057db
Merge pull request #1167 from sharetribe/update-sharetribe-script
Update sharetribe-scripts to 3.1.1
2019-08-23 16:49:02 +03:00
Jenni Nurmi
3cda4f2c81 Update sharetribe-scripts to 3.1.1-alpha 2019-08-23 16:43:59 +03:00
Jenni Laakso
033060c1a5
Merge pull request #1166 from sharetribe/update-en-translations
Add card number to remove card modal
2019-08-23 13:43:21 +03:00
Jenni Nurmi
4a1ab6cc02 Update changelog 2019-08-23 13:41:27 +03:00
Jenni Nurmi
ede229944f Add card number to remove card modal 2019-08-23 13:41:21 +03:00
Jenni Laakso
17cf7e5ee5
Merge pull request #1164 from sharetribe/update-deps
Update Sentry
2019-08-23 13:31:09 +03:00
Jenni Nurmi
9724ed565b Update changelog 2019-08-23 12:05:56 +03:00
Jenni Nurmi
55b043bb7b Update Sentry 2019-08-23 12:05:11 +03:00
Vesa Luusua
c3b8d68c74
Merge pull request #1165 from sharetribe/update-changelog
Update changelog
2019-08-23 12:04:50 +03:00
Vesa Luusua
d6a90c3271 Update changelog 2019-08-23 12:02:06 +03:00
Vesa Luusua
c90c83a10e
Merge pull request #1163 from sharetribe/update-dependencies-minor
Update dependencies: most of the batch and minor updates
2019-08-23 11:49:25 +03:00
Vesa Luusua
bc3f50d702 Update dependencies: most of the batch and minor updates 2019-08-23 11:44:25 +03:00
Jenni Laakso
239914cab0
Merge pull request #1138 from sharetribe/save-credit-card
Save payment card
2019-08-22 16:45:49 +03:00
Jenni Nurmi
ac1559b7dd Update changelog 2019-08-22 16:41:31 +03:00
Jenni Nurmi
95e5f36a48 SavedCardDetails: use portal for modal 2019-08-22 15:44:19 +03:00
Vesa Luusua
120a4b556d TransactionPanel: savePaymentMethodFailed flag used 2019-08-22 15:44:14 +03:00
Vesa Luusua
519ec667da TransactionPage: savePaymentMethodFailed flag added 2019-08-22 15:44:14 +03:00
Vesa Luusua
a62674f187 CheckoutPage: saves card for later use 2019-08-22 15:44:14 +03:00
Vesa Luusua
47fb3b2951 CheckoutPage.duck: fetch stripeCustomer relantionship for currentUser 2019-08-22 15:44:14 +03:00
Vesa Luusua
a6dac66f8e FieldCheckbox: add useSuccessColor prop 2019-08-22 15:44:14 +03:00
Vesa Luusua
dc34e4463d Add new type: defaultPaymentMethod 2019-08-22 15:44:14 +03:00
Jenni Nurmi
72b4f342d9 Create LayoutWrapperAccountSettingsSideNav 2019-08-22 15:44:14 +03:00
Jenni Nurmi
905f99043b Create PaymentMethodsPage 2019-08-22 15:44:14 +03:00
Jenni Nurmi
d4c265c014 Create PaymentMethodsForm 2019-08-22 15:44:14 +03:00
Jenni Nurmi
8ffa38bcc0 Move StripePaymentAddress to components 2019-08-22 15:44:09 +03:00
Jenni Nurmi
40a3ab09aa Create SavedCardDetailsComponent 2019-08-22 15:06:11 +03:00
Jenni Nurmi
89e7846519 IconCheckmark: big and small versions 2019-08-22 15:06:11 +03:00
Janne Koivistoinen
c1bfed5e7d Add more directions to IconArrowHead 2019-08-22 15:06:11 +03:00
Jenni Nurmi
262bfba6b3 Create IconCard 2019-08-22 15:06:11 +03:00
Vesa Luusua
74c0ce96e5 Add ensureStripeCustomer and ensurePaymentMethodCard 2019-08-22 15:06:11 +03:00
Jenni Nurmi
6521ec7ab7 Add handleCardSetup to stripe.duck.js 2019-08-22 15:06:11 +03:00
Vesa Luusua
839afb6f4b user.duck.js can fetch currentUser with different relationships.
It merges old and new relationships.
2019-08-22 15:06:11 +03:00
Vesa Luusua
3ee937757b Shared duck file: paymentMethods.duck.js 2019-08-22 15:06:06 +03:00
Jenni Nurmi
6ef5da91df Update SDK version 2019-08-22 14:32:54 +03:00
Jenni Laakso
15994f9b8b
Merge pull request #1160 from sharetribe/v3.2.1
v3.2.1
2019-08-22 10:26:49 +03:00
Jenni Nurmi
c85d3fdd00 Update changelog 2019-08-22 10:20:57 +03:00
Jenni Laakso
4f21e2c0a7
Merge pull request #1155 from sharetribe/fix-alignment-on-listing-page
Fix alignment on listing page
2019-08-19 13:33:29 +03:00
Jenni Nurmi
30661d5d67 Update changelog 2019-08-19 13:30:30 +03:00
Jenni Nurmi
a66d947838 Fix alignment on listing page 2019-08-19 13:28:19 +03:00
Vesa Luusua
10d25041b6
Merge pull request #1154 from sharetribe/fix-topbar-inbox-hydrate-bug
Rehydrate bug: existing DOM elements were populated incorrectly
2019-08-19 13:24:56 +03:00
Vesa Luusua
3bbfc631a1 Update changelog 2019-08-19 13:21:03 +03:00
Vesa Luusua
468b387499 Rehydrate bug: existing DOM elements were populated incorrectly 2019-08-19 13:19:08 +03:00
Jenni Laakso
f0fdc46ef3
Merge pull request #1151 from sharetribe/fix-changing-country-in-payout-details
Use stripe config to determine US specific fields
2019-08-19 11:07:05 +03:00
Jenni Nurmi
4bc9824400 Update changelog 2019-08-19 10:31:58 +03:00
Jenni Nurmi
a84df90ac3 Add code comment about mcc 2019-08-19 10:31:58 +03:00
Jenni Nurmi
e94c9d9409 Use stripe config to determine us specific fields 2019-08-19 10:31:53 +03:00
Jenni Laakso
1558b9c399
Merge pull request #1148 from sharetribe/update-new-translations
Update fr and es translations
2019-08-01 10:35:56 +03:00
Jenni Nurmi
e946ffa22c Update changelog 2019-08-01 10:32:39 +03:00
Jenni Nurmi
9adf213ef0 Update es.json 2019-08-01 10:28:45 +03:00
Jenni Nurmi
df524d4b89 Update fr.json 2019-08-01 10:28:26 +03:00
Jenni Laakso
4bc0f6f53f
Merge pull request #1139 from sharetribe/update-fr-translations
Update fr translations
2019-07-22 11:19:42 +03:00
Jenni Nurmi
8ffe9cd9a6 Update changelog 2019-07-22 11:12:31 +03:00
Jenni Nurmi
50e48fac84 Update translations related to payment intents to fr.json 2019-07-22 11:05:47 +03:00
Jenni Nurmi
cfdfa2ead1 Small updates to en.json 2019-07-22 11:05:12 +03:00
Vesa Luusua
61449c4d66
Merge pull request #1137 from sharetribe/v3.2.0
New release: v3.2.0
2019-07-18 18:03:32 +03:00
Vesa Luusua
ec778ece2f New release: v3.2.0 2019-07-18 18:00:54 +03:00
Vesa Luusua
bd76364769
Merge pull request #1129 from sharetribe/keyword-search-filter-desktop
Add keyword search
2019-07-18 17:49:55 +03:00
Vesa Luusua
fa79c2c650 Update changelog 2019-07-18 17:46:29 +03:00
Vesa Luusua
8cf99fd6c0 Update FilterPopup: add labelMaxWidth prop and ellipsis: 2019-07-18 17:37:47 +03:00
Vesa Luusua
fb2c11cae2 Update FieldTextInput: use defaultValue if uncontrolled 2019-07-18 17:37:47 +03:00
Jenni Nurmi
cb242413f8 Ensure that values are string before validating them 2019-07-18 17:37:47 +03:00
Jenni Nurmi
3242f01146 Add code comments about restriction tha this can't be used with origin 2019-07-18 17:37:46 +03:00
Jenni Nurmi
2485b46b30 Create KeywordFilter
Add it to desktop and mobile layout
2019-07-18 17:37:41 +03:00
Vesa Luusua
578a02039a
Merge pull request #1136 from sharetribe/temp-remove-audit
Temporarily remove audit CI job
2019-07-16 20:19:33 +03:00
Vesa Luusua
828719085e Temporarily remove audit CI job 2019-07-16 20:03:27 +03:00
Vesa Luusua
0cb982f246
Merge pull request #1135 from sharetribe/dependency-updates
Update dependencies
2019-07-16 19:58:45 +03:00
Jenni Nurmi
468821c9e0 Update changelog 2019-07-12 16:15:42 +03:00
Jenni Nurmi
b945c98463 Update react-router-dom to 5.0.1 2019-07-12 16:09:31 +03:00
Jenni Nurmi
62d67275c3 Update react-intl to 2.9.0 2019-07-12 16:08:30 +03:00
Jenni Nurmi
138fbaa64d Update Inquirer to 6.5.0 2019-07-12 16:06:32 +03:00
Jenni Nurmi
37ebb6b4d6 Update decimal.js to 10.2.0 2019-07-12 16:05:51 +03:00
Jenni Nurmi
8825c166ed Update bfj to 7.0.1 2019-07-12 16:04:55 +03:00
Jenni Nurmi
be310ae251 Update core-js to 3.1.4 2019-07-12 14:30:39 +03:00
Jenni Nurmi
89d46e6487 Update lodash to 4.17.14 2019-07-12 14:30:39 +03:00
Jenni Laakso
423a9200cd
Merge pull request #1131 from sharetribe/ensure-booking-transition-exists
Ensure booking transition exists
2019-07-08 13:47:58 +03:00
Jenni Nurmi
cd525d0708 Update changelog and package.json 2019-07-08 13:46:00 +03:00
Vesa Luusua
f9dae4bac4 TransactionPanel: has correct next transition for enquiry 2019-07-05 17:51:58 +03:00
Vesa Luusua
a3898f6341 TransactionPage.duck: Fetch process transitions on loadData 2019-07-05 17:50:24 +03:00
Vesa Luusua
3eb5f16544 Fix proptype validation for BookingPanel 2019-07-05 17:49:25 +03:00
Vesa Luusua
3791a2e5d4
Merge pull request #1128 from sharetribe/v3.1.0
New release: v3.1.0
2019-07-05 15:50:27 +03:00
Vesa Luusua
5f113608b4 New release: v3.1.0 2019-07-05 15:34:00 +03:00
Vesa Luusua
625d87cf6b
Merge pull request #1124 from sharetribe/fix-heroButton-search-param-bug
fix heroButton search param bug
2019-07-05 15:31:28 +03:00
Vesa Luusua
11dfaff42e Update changelog 2019-07-05 15:29:16 +03:00
Vesa Luusua
5d559e2aa0 Update test 2019-07-05 15:25:54 +03:00
Janne Koivistoinen
c569fe2c51
fix heroButton search param bug
Removed the extra "s?" from the "to" parameter.
2019-07-04 16:34:53 +03:00
Jenni Laakso
ed9ad72b02
Merge pull request #1122 from sharetribe/add-singapore-to-stripe-countries
Add Singapore to supported Stripe countries
2019-07-04 15:15:36 +03:00
Jenni Nurmi
30c8e09cac Update changelog 2019-07-04 15:06:18 +03:00
Jenni Nurmi
6f4e93bbdc Fix bug in passing the id number to Stripe 2019-07-04 15:05:46 +03:00
Jenni Nurmi
426a12288b Add Singapore to Stripe countries 2019-07-04 15:05:46 +03:00
Jenni Laakso
8e550d8392
Merge pull request #1123 from sharetribe/edit-csp
Add events.mapbox.com to connect-src
2019-07-04 15:05:04 +03:00
Jenni Nurmi
841b45c169 Update changelog 2019-07-04 14:58:42 +03:00
Jenni Nurmi
669006015a Add events.mapbox.com to connect-src 2019-07-04 11:16:41 +03:00
Jenni Laakso
18492a2e44
Merge pull request #1121 from sharetribe/automatic-email-verification
Verify email automatically and redirect to landing page
2019-07-03 15:41:26 +03:00
Jenni Nurmi
ecc8657b0d Update changelog 2019-07-03 15:36:05 +03:00
Jenni Nurmi
a8f746a59f Verify email automatically and redirect to landing page 2019-07-03 15:18:57 +03:00
Vesa Luusua
13af1ab471
Merge pull request #1119 from sharetribe/v3.0.0
Prepare for new release
2019-07-02 15:23:49 +03:00
Vesa Luusua
8f26d7917c Prepare for new release 2019-07-02 15:21:54 +03:00
Vesa Luusua
7233aafb55
Merge pull request #1089 from sharetribe/payment-intents
Payment Intents
2019-07-02 15:18:35 +03:00
Vesa Luusua
f9222183e5 Update changelog 2019-07-02 14:13:28 +03:00
Vesa Luusua
8afc7ce29f Fix typo on en.json 2019-07-02 13:13:59 +03:00
Vesa Luusua
9343ab9f30 Update StripePaymentForm: Add billing address fields.
Form is not visible after handleCardPayment is called.
Show errors on various steps of PaymentIntent (SCA) process.
2019-07-02 13:13:59 +03:00
Vesa Luusua
5854ff0ecc Update CheckoutPage container:
Combine initiateOrder and initiateOrderAfterEnquiry thunk functions
Use PaymentIntents flow:
initiateOrder (SDK), handleCardPayment(Stripe), confirmPayment (SDK), sendMessage (SDK)
2019-07-02 13:13:53 +03:00
Vesa Luusua
441ecd9759 Update CheckoutPageSessionHelpers: session storage can save any transaction.
Data serialization is improved too:
Date and Decimal objects within data are serialized automatically
2019-06-28 13:36:12 +03:00
Vesa Luusua
8a71845830 Update ListingPage: clear prev errors from stripe and CheckoutPage stores 2019-06-28 13:36:12 +03:00
Vesa Luusua
e91eaa3866 Update TransactionPage container: use SCA process
(Redirect tx with payment-pending to checkout page and
clear card paymenterrors from store.)
2019-06-28 13:36:04 +03:00
Vesa Luusua
b8381bf2f4 Update TransactionPanel component: use SCA process 2019-06-27 17:38:16 +03:00
Vesa Luusua
551ea6a9b3 Update InboxPage container: use SCA process 2019-06-27 17:38:15 +03:00
Vesa Luusua
5eea53eecf Update ActivityFeed component: use SCA process 2019-06-27 17:38:15 +03:00
Vesa Luusua
d5cf331113 Update BookingBreakdown component: use SCA process 2019-06-27 17:38:15 +03:00
Vesa Luusua
a2deea8b5e Update EstimatedBreakdownMaybe to use SCA process 2019-06-27 17:38:15 +03:00
Vesa Luusua
563e6faa49 Add new calls to stripe.duck.js (PaymentIntents)
and remove unused createStripePaymentToken
2019-06-27 17:37:38 +03:00
Vesa Luusua
4cb1af5703 Change transaction.js process to match alias (SCA version) 2019-06-19 17:13:31 +03:00
Vesa Luusua
3a9f1960c6 Change transaction process alias to SCA version 2019-06-19 17:12:26 +03:00
Vesa Luusua
7ee545f17d Add minutesBetween utility function 2019-06-19 17:09:51 +03:00
Vesa Luusua
e3852a2b20 Fix printAPIErrorsAsConsoleTable function 2019-06-19 17:09:04 +03:00
Vesa Luusua
3d1b041694 Add countryCodes.js file 2019-06-19 17:07:49 +03:00
Vesa Luusua
2b8496222c CheckoutPage: reorder imports 2019-06-11 13:42:20 +03:00
Jenni Laakso
2bf631e0f4
Merge pull request #1115 from sharetribe/v2.17.1
Update changelog
2019-06-11 13:26:19 +03:00
Jenni Nurmi
e713a358c7 Update changelog 2019-06-11 13:24:20 +03:00
Jenni Laakso
bc94c96a55
Merge pull request #1114 from sharetribe/fix-updating-cardtoken
Clear cardtoken before redirecting
2019-06-11 13:21:30 +03:00
Jenni Nurmi
8973b5c4b6 Update changelog 2019-06-11 13:18:37 +03:00
Jenni Nurmi
a937c8474d Remove temporary fix in .auditrc 2019-06-11 13:18:37 +03:00
Jenni Nurmi
d8c5461a58 Clear cardtoken before redirecting 2019-06-11 13:18:32 +03:00
Mikko Koski
b5e8bd3f8c
Merge pull request #1111 from sharetribe/upgrade-sdk
Upgrade SDK
2019-06-11 10:33:20 +03:00
Mikko Koski
76107dd62e Update CHANGELOG.md
Co-Authored-By: Jenni Laakso <jenniknurmi@gmail.com>
2019-06-11 10:31:19 +03:00
Mikko Koski
2b48dfe107 Update CHANGELOG 2019-06-11 10:30:52 +03:00
Mikko Koski
4aeb38f0e6 Upgrade SDK to v1.4.1
This version upgrades dependencies with security issues.
2019-06-11 10:29:20 +03:00
Jenni Laakso
c46e9f2ca0
Merge pull request #1112 from sharetribe/prevent-provider-commission-error
Prevent provider commission error
2019-06-10 14:07:04 +03:00
Jenni Nurmi
2ca26d149a Update changelog 2019-06-10 14:01:57 +03:00
Jenni Nurmi
bab325bccc Add comment about default process 2019-06-10 14:01:53 +03:00
Robin Doherty
4b2560b228 prevent error when a provider commission does not exist 2019-06-10 13:50:01 +03:00
Jenni Laakso
a740d03ca2
Merge pull request #1106 from sharetribe/fix-bug-in-reviewlink
Fix bug in showing the review link after other party has already reviewed it
2019-06-10 11:23:38 +03:00
Jenni Nurmi
e43572ce9c Update changelog 2019-06-10 11:09:38 +03:00
Jenni Nurmi
10c2739629 Temporarily skip audit warning about axios 2019-06-10 11:09:38 +03:00
Jenni Nurmi
0e1d39cb86 Fix bug in review link 2019-06-10 11:09:38 +03:00
Janne Koivistoinen
9262d5c617
Merge pull request #1101 from sharetribe/filter-bug
Fix empty priceFilter bug
2019-05-24 17:31:39 +03:00
Janne Koivistoinen
09ae9c1d1c update changelog 2019-05-24 17:27:38 +03:00
Janne Koivistoinen
a068611536 Fix empty priceFilter bug 2019-05-24 17:22:40 +03:00
Vesa Luusua
0083708e37
Merge pull request #1100 from sharetribe/v2.17.0
Release v2.17.0
2019-05-23 16:50:29 +03:00
Vesa Luusua
95b6c1593a Release v2.17.0 2019-05-23 16:42:31 +03:00
Vesa Luusua
abd4611048
Merge pull request #1099 from sharetribe/update-mapbox
Update Mapbox GL JS library to v1.0.0 and Mapbox SDK to v0.6.0
2019-05-23 16:38:13 +03:00
Vesa Luusua
fa4a0b5e48 Update changelog 2019-05-23 16:34:56 +03:00
Vesa Luusua
e8c8fce012 Update Mapbox GL JS library to v1.0.0 and Mapbox SDK to v0.6.0 2019-05-23 15:12:20 +03:00
Vesa Luusua
236115071e
Merge pull request #1098 from sharetribe/fix-charge-disabled-error
Fix charge disabled error
2019-05-23 15:10:09 +03:00
Vesa Luusua
39175a8be8 Update changelog 2019-05-23 15:06:23 +03:00
Vesa Luusua
db11a921ad Check if the booking error happens due to disabled charge creation 2019-05-23 15:05:59 +03:00
Vesa Luusua
200ca602e1
Merge pull request #1096 from sharetribe/fix-too-early-rendering-of-menu
Fix too early rendering of Menu
2019-05-22 13:24:27 +03:00
Vesa Luusua
5c533e884e Update changelog 2019-05-22 13:00:09 +03:00
Vesa Luusua
740e2f24bc Menu needs to wait mounting to calculate dimensions reliably 2019-05-22 12:54:15 +03:00
Vesa Luusua
e01dfa0258
Merge pull request #1095 from sharetribe/fix-classname-for-examples
Fix class name for Styleguide examples
2019-05-22 12:49:05 +03:00
Vesa Luusua
68abf0e471 Update changelog 2019-05-22 12:44:17 +03:00
Vesa Luusua
df601c3088 Fix class name for Styleguide examples 2019-05-22 12:42:00 +03:00
Vesa Luusua
3486aad00b
Merge pull request #1094 from sharetribe/styleguide-rawonly-flag
Styleguide: add 'rawOnly' flag for examples.
2019-05-21 16:42:20 +03:00
Vesa Luusua
7d9efab5b9 Update changelog 2019-05-21 16:35:04 +03:00
Vesa Luusua
3dd951792f Use rawOnly example parameter in ImageCarousel 2019-05-21 16:30:11 +03:00
Vesa Luusua
926e68f854 StyleguidePage: add rawOnly flag for positioned components 2019-05-21 16:29:29 +03:00
Jenni Nurmi
622dfa18ca
Merge pull request #1092 from sharetribe/fix-showing-error-in-stripe-form
Fix bug in showing error message
2019-05-16 15:20:18 +03:00
Jenni Nurmi
e6250edfe4 Update changelog 2019-05-16 15:17:00 +03:00
Jenni Nurmi
54ee91d2e5 Fix bug in showing error message 2019-05-16 15:07:51 +03:00
Jenni Nurmi
f4a487fb3c
Merge pull request #1088 from sharetribe/use-final-form-in-stripe-payment-form
Use final form in StripePaymentForm
2019-05-16 12:57:22 +03:00
Jenni Nurmi
c772af8f0f Update changelog 2019-05-16 12:51:41 +03:00
Jenni Nurmi
07dc5b0444 Add note about Stripe card not being a Final Form field 2019-05-16 11:04:28 +03:00
Jenni Nurmi
af782db541 Fix small bug in stripe.duck.js 2019-05-16 11:04:28 +03:00
Jenni Nurmi
fcc932441e Update proptypes 2019-05-16 11:04:28 +03:00
Jenni Nurmi
a78777a85b Use Final Form 2019-05-16 11:04:20 +03:00
Jenni Nurmi
07cd93a649
Merge pull request #1086 from sharetribe/create-payment-to-stripe-duck
Move creating payment token to stripe.duck.js
2019-05-09 16:09:21 +03:00
Jenni Nurmi
3029d8dd2c Update changelog 2019-05-09 16:02:45 +03:00
Jenni Nurmi
0896d315f3 Update tests 2019-05-09 16:02:45 +03:00
Jenni Nurmi
20b9c6c8a3 Add proptypes 2019-05-09 16:02:45 +03:00
Jenni Nurmi
291708ff8c Use values from store 2019-05-09 16:02:45 +03:00
Jenni Nurmi
952f713a5d Move creating payment token to strip.duck.js 2019-05-09 16:02:40 +03:00
Vesa Luusua
47e6f10b96
Merge pull request #1085 from sharetribe/v2.16.0
Release v2.16.0
2019-05-08 14:11:43 +03:00
Vesa Luusua
bcde9ac0ac Release v2.16.0 2019-05-08 14:07:49 +03:00
Vesa Luusua
106b1c2c49
Merge pull request #1084 from sharetribe/fix-stripe-connected-check
Fix stripe connected check
2019-05-08 13:39:30 +03:00
Vesa Luusua
44958f876f Update changelog 2019-05-08 13:31:20 +03:00
Vesa Luusua
17bbaad975 Include stripeConnected attribute to currentUser entity 2019-05-08 13:31:20 +03:00
Greg Gutkin
560c0a05a0 Remove spurious modal requesting payment info setup
Current check for Stripe account setup is looking for non-existent `stripeAccount` property, causing a spurious modal asking to set up payment info even though it has already been configured. Changing to check the currect property on the `currentUser` object.
2019-05-08 12:55:37 +03:00
Jenni Nurmi
0a5d60913e
Merge pull request #1079 from sharetribe/no-mutated-args-in-updated-entities
Don't mutate args in updatedEntities
2019-05-08 12:54:50 +03:00
Jenni Nurmi
ec76c3fd8c Update changelog 2019-05-08 12:51:19 +03:00
Jenni Nurmi
8de2513582 Change the place where to spread the object 2019-05-08 12:43:17 +03:00
Jenni Nurmi
9c84c9761f Don't mutate args in updatedEntities 2019-05-08 12:43:17 +03:00
Vesa Luusua
8d0a58a3a3
Merge pull request #1083 from sharetribe/update-missing-changelog-for-sharetribe-scripts-v3
Changelog was missing from sharetribe-scripts dependency update
2019-05-08 12:40:06 +03:00
Vesa Luusua
e9dc59cfc0 Changelog was missing from sharetribe-scripts dependency update 2019-05-08 12:38:10 +03:00
Vesa Luusua
1de7dfa746
Merge pull request #1081 from sharetribe/cra3-update
Testing CRA 3 update
2019-05-08 12:32:14 +03:00
Vesa Luusua
897d67baea Remove unnecessary audit exceptions 2019-05-08 12:25:24 +03:00
Vesa Luusua
a43ab75694 Update scripts/config.js after Prettier version bump 2019-05-08 12:25:24 +03:00
Vesa Luusua
e5e972dc7d Update snapshots after flex-sdk-js version bump 2019-05-08 12:25:24 +03:00
Vesa Luusua
e2159de9f3 Reserve use* function naming pattern for React Hooks
Eslint-plugin rules of hooks assumed that useInitialValues was actually
a wrongly called hook
2019-05-08 12:25:23 +03:00
Vesa Luusua
7161853006 CRA v3.0.0 had custom asset-manifest generator for files 2019-05-08 12:25:23 +03:00
Vesa Luusua
42dc1d5acf Update sharetribe-scripts to v3.0.0 2019-05-08 12:25:15 +03:00
Jenni Nurmi
b4f56071a0
Merge pull request #1082 from sharetribe/fix-bug-in-transaction-page
Check that lineItems exists in transaction attributes
2019-05-07 18:09:16 +03:00
Jenni Nurmi
3fcb75a9e9 Update changelog 2019-05-07 18:05:22 +03:00
Jenni Nurmi
339676a2eb Check that lineItems exists in attributes 2019-05-07 17:55:20 +03:00
Jenni Nurmi
68d25e51f2
Merge pull request #1080 from sharetribe/update-sentry-logout
Use proper method for unsetting Sentry user context on logout
2019-05-07 15:51:47 +03:00
Greg Gutkin
55bf312b87 Use proper method for unsetting Sentry user context on logout
Current implementation causes an error popup on logout if Sentry is enabled. This is because `remove_user` is not a valid method on the `scope` object. Changing to use the `setUser` with a `null` parameter as discussed here - https://github.com/getsentry/sentry-docs/issues/500
2019-05-07 15:25:36 +03:00
Vesa Luusua
313ab16451
Merge pull request #1073 from sharetribe/cra2-update
CRA 2.1.8 update
2019-05-06 18:02:45 +03:00
Vesa Luusua
d0b140a944 Update changelog 2019-05-06 07:58:25 -07:00
Vesa Luusua
5a12a1e65f Update snapshots 2019-05-03 22:31:21 +03:00
Vesa Luusua
5cd7ba5afc Mock window.scroll - otherwise JSDOM prints a not-implemented error 2019-05-03 22:31:20 +03:00
Vesa Luusua
537c001e2f update sharetribe-scripts (2.1.8) 2019-05-03 22:31:20 +03:00
Vesa Luusua
20d619df95 Circumvent intentional hash-link usage on example file (jsx-a11y/anchor-is-valid) 2019-05-03 22:31:20 +03:00
Vesa Luusua
a0fe57dfa4 Fix z-index calculation 2019-05-03 22:31:20 +03:00
Vesa Luusua
ec86dfa596
Merge pull request #1075 from sharetribe/add-audit-alerts-to-exception-list
Add audit alerts to exception list
2019-05-03 21:58:46 +03:00
Vesa Luusua
4c6b8c4686 Update changelog 2019-05-03 21:56:46 +03:00
Vesa Luusua
673077066e New vulnerability warnings checked and added to exception list 2019-05-03 21:56:40 +03:00
Vesa Luusua
ee78b08822
Merge pull request #1074 from milotiger/bugs/fix_minor_bug_on_fetching_reviews
fix dispatch for fetchReviewRequest
2019-05-03 17:33:37 +03:00
Tri Nguyen
7a5e77f3be fix dispatch for fetchReviewRequest 2019-05-03 20:10:31 +07:00
Vesa Luusua
506248bfec
Merge pull request #1072 from sharetribe/v2.15.0
New release: v2.15.0
2019-04-24 14:36:06 +03:00
Vesa Luusua
8981ef32e3 New release: v2.15.0 2019-04-24 14:27:54 +03:00
Vesa Luusua
bce7c8f486
Merge pull request #1071 from sharetribe/improve-api-error-printing
Improve printing API errors
2019-04-24 14:25:07 +03:00
Vesa Luusua
9a97cb6810 Update changelog 2019-04-24 14:18:46 +03:00
Vesa Luusua
41c601784a Improve API errors printing 2019-04-24 14:15:59 +03:00
Vesa Luusua
85aee0b47a
Merge pull request #1069 from sharetribe/fix-availability-utc-handling-v2
Month id (string) should be generated using UTC timezone
2019-04-24 12:37:10 +03:00
Vesa Luusua
ba831ebc9a Update changelog 2019-04-24 12:30:07 +03:00
Vesa Luusua
f1bc1697b6 Month id strig should be generated on utc timezones 2019-04-24 12:25:48 +03:00
Vesa Luusua
0f9c74be68
Merge pull request #1067 from sharetribe/inbox-page-uses-sparse-fields
InboxPage: use sparse fields to improve query performance
2019-04-15 11:28:42 +03:00
Vesa Luusua
976b740156 Update changelog 2019-04-12 16:19:32 +03:00
Vesa Luusua
be0c8a7cf5 InboxPage: use sparse fields to improve query performance 2019-04-12 16:19:32 +03:00
Vesa Luusua
d31055f263
Merge pull request #1066 from sharetribe/search-page-uses-sparse-fields
SearchPage: use sparse fields to improve query performance
2019-04-12 16:18:56 +03:00
Vesa Luusua
812ec463f5 Update changelog 2019-04-12 15:07:14 +03:00
Vesa Luusua
26e82bcc50 SearchPage: use sparse fields when querying listing data 2019-04-12 13:25:12 +03:00
Vesa Luusua
d926f6b8c6 Make ListingPage to work with sparse listing data
while loadData is in progress
2019-04-12 13:21:09 +03:00
Vesa Luusua
fafefea5ee Make listing and user proptypes to work with sparse fields 2019-04-12 13:19:25 +03:00
Vesa Luusua
9eaff734d8
Merge pull request #1065 from sharetribe/v2.14.0
New release: v2.14.0
2019-04-05 15:05:32 +03:00
Vesa Luusua
7526e93f4e New release: v2.14.0 2019-04-05 15:04:19 +03:00
Vesa Luusua
c73bb5209a
Merge pull request #1064 from sharetribe/add-german-translations-for-stripe-changes
Add german translations for stripe changes
2019-04-05 15:01:41 +03:00
Vesa Luusua
29812d2428 Update changelog 2019-04-05 14:59:51 +03:00
Vesa Luusua
405e829554 Add German translations for recent PayoutDetailsForm changes 2019-04-05 14:58:57 +03:00
Vesa Luusua
b6dd976a96 Improve English translations 2019-04-05 14:58:56 +03:00
Vesa Luusua
8758d27ddc
Merge pull request #1063 from sharetribe/update-currency-config
Update currency config
2019-04-05 14:58:01 +03:00
Vesa Luusua
47b6a584c1 Update changelog 2019-04-05 14:56:43 +03:00
Vesa Luusua
ea8217a6ab Refactor configs for currency formatting 2019-04-05 14:56:10 +03:00
Vesa Luusua
18348a6955 Relocate currency configuration 2019-04-05 14:56:09 +03:00
Vesa Luusua
8aba4d5b26 Add divisors for NZD and HKD and reorder 2019-04-05 14:56:09 +03:00
Hannu Lyytikainen
6dfc015d3b Update changelog 2019-04-05 14:55:28 +03:00
Hannu Lyytikäinen
b929493f01
Merge pull request #1062 from sharetribe/custom-pricing-support
Add support for arbitrary line item codes
2019-04-05 14:44:19 +03:00
Hannu Lyytikainen
551dff00ce Change booking breakdown layout
Make the subtotal line stick out a bit more.
2019-04-05 11:47:45 +03:00
Hannu Lyytikainen
1f0938a87c Update booking breakdown styleguide example
Add examples with arbitrary line items.
2019-04-05 11:47:45 +03:00
Hannu Lyytikainen
1fbe92f7e6 Update booking breakdown test
Update line items in test to match those returned from the API.
2019-04-05 11:47:45 +03:00
Hannu Lyytikainen
07f4ad2b3c Add support for arbitrary line items in refund 2019-04-05 11:47:45 +03:00
Hannu Lyytikainen
ec3c74180b Add support for arbitrary line items in sub total 2019-04-05 11:47:45 +03:00
Hannu Lyytikainen
61a9941ce6 Add a component for unknown line items 2019-04-05 11:36:42 +03:00
Hannu Lyytikainen
a15d3d15ab Add a function that humanizes line item codes 2019-04-05 11:30:45 +03:00
Hannu Lyytikainen
d8c614c911 Remove requirement for a known line item
Remove the requirement that a certain kind of line item is found from a transaction.
2019-04-05 11:30:45 +03:00
Vesa Luusua
236798d32a
Merge pull request #1061 from sharetribe/fix-individual-account-url
Fix individual account url
2019-04-02 15:39:04 +03:00
Vesa Luusua
d06f9e8d5d Update changelog 2019-04-02 15:30:13 +03:00
Vesa Luusua
d45f102940 PayoutDetailsForm: Fix individual account business URL for US 2019-04-02 15:26:57 +03:00
Vesa Luusua
8247e54988
Merge pull request #1057 from sharetribe/v2.13.1
New release: v2.13.1
2019-03-29 15:45:16 +02:00
Vesa Luusua
0f52866516 New release: v2.13.1 2019-03-29 15:43:17 +02:00
Vesa Luusua
720b23878f
Merge pull request #1055 from sharetribe/add-comment-about-publicdata-filters
Add comment about category and amenities filters not working by default
2019-03-29 15:39:48 +02:00
Vesa Luusua
16e0874f45 Update changelog 2019-03-29 15:37:39 +02:00
Vesa Luusua
3e2569b693 Add comment about category and amenities filters not working by default 2019-03-29 15:36:35 +02:00
Vesa Luusua
98fb5d40b2
Merge pull request #1056 from sharetribe/fix-editlistingwizard-currentuser-id
Fix editlistingwizard currentuser
2019-03-29 15:33:12 +02:00
Vesa Luusua
b836a5eb8a Update changelog 2019-03-29 15:20:49 +02:00
tam.vu
fa9cb85755 Fix bugs crashed when refresh EditListingPage:
Cause: current user is null when the EditListing page got reloaded.
Solve: ensure current user and then pass in ID
2019-03-29 15:18:33 +02:00
Vesa Luusua
84f272eaad
Merge pull request #1053 from sharetribe/v2.13.0
New release: v2.13.0
2019-03-28 16:45:12 +02:00
Vesa Luusua
be9647fb3b New release: v2.13.0 2019-03-28 16:42:46 +02:00
Vesa Luusua
743ff67ef6
Merge pull request #1052 from sharetribe/update-translations
Update translations (after recent Stripe changes)
2019-03-28 16:39:58 +02:00
Vesa Luusua
b6657bc20e Update changelog 2019-03-28 16:38:03 +02:00
Vesa Luusua
88f635337f Update translations: es.json 2019-03-28 16:33:48 +02:00
Vesa Luusua
6c1ab84e1a Update translations: fr.json 2019-03-28 12:33:22 +02:00
Vesa Luusua
7b5823a598 Update translations: en.json 2019-03-28 12:30:08 +02:00
Vesa Luusua
1fc4c01878
Merge pull request #1051 from sharetribe/fix-JPY-subunit-divisor
JPY was configured wrongly: it doesn't use subunits
2019-03-27 17:25:23 +02:00
Vesa Luusua
3c6143c670 Update changelog 2019-03-27 17:24:39 +02:00
Vesa Luusua
d6545edc25 JPY was configured wrongly: it doesn't use subunits 2019-03-27 17:21:51 +02:00
Vesa Luusua
1e4c26ac77
Merge pull request #1049 from sharetribe/fix-stripe-api-breaking-changes
There was breaking changes in Stripe API 2019-02-19
2019-03-27 16:53:03 +02:00
Vesa Luusua
a6347f1256 Update Changelog and Readme 2019-03-27 13:43:39 +02:00
Vesa Luusua
9ff121c615 Add generic Stripe error messages to PayoutDetailsForm error rendering. 2019-03-27 13:23:29 +02:00
Vesa Luusua
076055f9c2 Add stripe.duck.js to handle Stripe account and person endpoints 2019-03-27 13:23:21 +02:00
Vesa Luusua
be2a0fac8b Update SDK version 2019-03-27 12:55:29 +02:00
Vesa Luusua
63c9d73a3d Removed stripeConnected attributes in favor of stripeAccount entity 2019-03-26 22:20:16 +02:00
Vesa Luusua
b8b919ca11 Add stripeAccount entity to proptypes 2019-03-26 22:20:16 +02:00
Vesa Luusua
905c3ee129 Add currentUser id to components showing individiual Stripe account. 2019-03-26 22:20:15 +02:00
Vesa Luusua
f1b7a2235d Move fname/firstName and lname/lastName renaming in thunk functions 2019-03-26 22:20:15 +02:00
Vesa Luusua
59f5e08897 PayoutDetailsForm: use new individual and company account components 2019-03-26 22:20:15 +02:00
Vesa Luusua
4ffef72a25 Add PayoutDetailsCompanyAccount component 2019-03-26 22:20:14 +02:00
Vesa Luusua
aa35f81b28 Add PayoutDetailsAdditionalPersons component 2019-03-26 22:20:14 +02:00
Vesa Luusua
c0060128f9 Add PayoutDetailsAccountOpener component 2019-03-26 22:20:13 +02:00
Vesa Luusua
84c2894e84 Refactor PayoutDetailsBankDetails 2019-03-26 22:20:13 +02:00
Vesa Luusua
659f2364e6 Refactor PayoutDetailsAddress 2019-03-26 22:20:13 +02:00
Vesa Luusua
760c78e897 Add PayoutDetailsIndividualAccount component 2019-03-26 22:20:12 +02:00
Vesa Luusua
11997a8d7e Update PayoutDetailsPersonalDetails component 2019-03-26 22:20:05 +02:00
Vesa Luusua
d508c974ad Add PayoutDetailsCompany component 2019-03-25 17:49:53 +02:00
Vesa Luusua
0311ef3787 Add PayoutDetailsBusinessProfile component 2019-03-25 17:49:53 +02:00
Vesa Luusua
2ce3be3372 PayoutDetailsForm: helper functions to normalize US phone numbers 2019-03-25 17:49:53 +02:00
Vesa Luusua
cdaabd0f96 Add a list of merchant category codes (mcc) for US 2019-03-25 17:49:52 +02:00
Vesa Luusua
38fc769539 Validator for businessURL 2019-03-25 17:49:52 +02:00
Vesa Luusua
04ffddc52c Update stripe-config.js 2019-03-25 17:49:52 +02:00
Vesa Luusua
8223878f08 Remove deprecated subcomponents 2019-03-25 17:49:52 +02:00
Vesa Luusua
a202a8eab4 Enhancement: FieldSelect didn't reserve space for dropdown arrow. 2019-03-25 17:49:52 +02:00
Vesa Luusua
5c7c83b42a Enhancement: add autocomplete attributes to FieldBirthdayInput 2019-03-25 17:49:51 +02:00
Vesa Luusua
78f314f791 fieldphonenumberinput-allow-props-overwrite 2019-03-25 17:49:51 +02:00
Vesa Luusua
f7d5341988
Merge pull request #1050 from sharetribe/use-booking-displayStart-displayEnd
Use displayStart and dislayEnd (Booking entity)
2019-03-25 17:49:07 +02:00
Vesa Luusua
af9cbe50b2 Update changelog 2019-03-25 15:47:15 +02:00
Vesa Luusua
3ff963192a Update tests 2019-03-25 15:47:14 +02:00
Vesa Luusua
97c7654073 Use displayStart and dislayEnd (Booking entity) 2019-03-25 15:47:09 +02:00
Vesa Luusua
ce9d61adc2
Merge pull request #1048 from sharetribe/fix-empty-slug
Fix empty slug
2019-03-20 13:26:03 +02:00
Vesa Luusua
6337afff9a Update changelog 2019-03-20 13:21:29 +02:00
Vesa Luusua
d9b43a09cd Title containing only stripped characters caused bugs in slug / pathName genetation 2019-03-20 13:21:23 +02:00
Vesa Luusua
5da82192df
Merge pull request #1045 from sharetribe/remove-node-engine-setup
Remove node engine setup
2019-03-11 16:45:38 +02:00
Vesa Luusua
60f48bec27 Update changelog 2019-03-11 16:30:54 +02:00
Vesa Luusua
e5fd1f7510 Run Prettier (bug_report.md was not following Prettier formatting) 2019-03-11 16:30:32 +02:00
Vesa Luusua
0441300628 package.json, remove node engine setup 2019-03-11 16:24:44 +02:00
Kimmo Puputti
f9396716dd
Update issue templates
Use default bug report template
2019-03-11 16:17:34 +02:00
Jenni Nurmi
60af89ac0e
Merge pull request #1042 from sharetribe/show-error-in-payout-modal-if-no-stripe-key
Show error if Stripe publishable key is not configured
2019-03-07 14:29:17 +02:00
Jenni Nurmi
d56ea31ea7 Update changelog 2019-03-07 14:11:32 +02:00
Jenni Nurmi
21d504013c Show error also in StripePaymentForm 2019-03-07 14:10:25 +02:00
Jenni Nurmi
48c1f51797 Edit the error message 2019-03-07 10:21:29 +02:00
Jenni Nurmi
dbe92f5f3d Show error in PayoutDetailsForm if Stripe publishable key is not configured 2019-03-06 15:20:30 +02:00
Vesa Luusua
2f27c3e8a7
Merge pull request #1039 from sharetribe/fix-fieldbirthdayinput-placeholder
Fix fieldbirthdayinput placeholder
2019-03-06 11:35:13 +02:00
Vesa Luusua
99750e112b Update changelog 2019-03-05 17:20:43 +02:00
Vesa Luusua
924b64f38d Placeholder values was not set which caused first real value to be selected by default 2019-03-05 17:20:35 +02:00
Jenni Nurmi
4314580258
Update information about issues with Stripe 2019-02-28 15:46:37 +02:00
Jenni Nurmi
4a3052d618
Merge pull request #1038 from sharetribe/v2.12.0
Release v2.12.0
2019-02-28 14:09:09 +02:00
Jenni Nurmi
ad3daf301f Release v2.12.0 2019-02-28 14:07:07 +02:00
Jenni Nurmi
0d2474e66a
Merge pull request #1037 from sharetribe/update-creating-stripe-accounts
Sent correct params in user.duck.js depending on Stripe API version
2019-02-28 14:04:01 +02:00
Jenni Nurmi
bce2688832 Update changelog 2019-02-28 14:02:01 +02:00
Jenni Nurmi
a659c40486 Sent correct params in user.duck.js depending on Stripe API version 2019-02-28 13:57:17 +02:00
Jenni Nurmi
786e0c4092
Merge pull request #1035 from sharetribe/update-creating-stripe-accounts
Update creating Stripe accounts to match the updated Stripe API
2019-02-28 13:32:57 +02:00
Jenni Nurmi
d5363cc4b0 Update changelog 2019-02-28 13:30:24 +02:00
Jenni Nurmi
0e975d2a61 Hide company account creation if new Stripe API is used 2019-02-28 09:35:14 +02:00
Jenni Nurmi
1c14794ed8 Config for Stripe API version 2019-02-28 09:34:47 +02:00
Vesa Luusua
0c2b5e707d
Merge pull request #1034 from sharetribe/improve-german-translations
Improve german translations
2019-02-25 19:12:07 +02:00
Vesa Luusua
0a6fa6e5ce Update Changelog 2019-02-25 19:08:07 +02:00
Vesa Luusua
9348b73c4c Run Prettier for docs 2019-02-25 19:08:07 +02:00
Vesa Luusua
cfa271066f Improve German translations 2019-02-25 19:08:02 +02:00
Jenni Nurmi
d3fc130082
Add a note about issues with Stripe 2019-02-22 20:11:00 +02:00
Vesa Luusua
be8de4f960
Merge pull request #1031 from sharetribe/update-changelog-for-improve-bundling-order
Add missing Changelog update
2019-02-21 18:24:54 +02:00
Vesa Luusua
b0ca711118 Add missing Changelog update 2019-02-21 18:23:25 +02:00
Vesa Luusua
5cecdc982e
Merge pull request #1024 from sharetribe/improve-bundling-order
Improve bundling order
2019-02-21 17:59:18 +02:00
Vesa Luusua
68bf18e737
Merge pull request #1029 from sharetribe/v2.11.1
Update version to v2.11.1
2019-02-21 14:02:14 +02:00
Vesa Luusua
a373439ac0 Update version to v2.11.1 2019-02-21 14:00:23 +02:00
Vesa Luusua
04b023c63e
Merge pull request #1028 from sharetribe/add-missing-translations
Add missing translations
2019-02-21 13:58:23 +02:00
Vesa Luusua
da5a74abae Update changelog 2019-02-21 13:55:46 +02:00
Vesa Luusua
f9cefe97a8 Add translations for missing keys (French and Spanish) 2019-02-21 13:53:55 +02:00
Vesa Luusua
6ec47e4b6c
Merge pull request #1027 from sharetribe/fix-ui-for-long-words-and-add-german
Fix ui for long words and add german
2019-02-21 13:08:41 +02:00
Vesa Luusua
eae3b98078 Update Changelog 2019-02-21 13:04:16 +02:00
Vesa Luusua
774ffa0177 Added German translations (de.json) 2019-02-21 13:03:54 +02:00
Vesa Luusua
ca284f8d7e Add hyphenation to titles which might contain long words. 2019-02-20 18:11:05 +02:00
Vesa Luusua
0c15dae30e
Merge pull request #1026 from sharetribe/v2.11.0
Update version to v2.11.0
2019-02-20 13:48:00 +02:00
Vesa Luusua
a38b118a6d Update version to v2.11.0 2019-02-20 13:46:21 +02:00
Vesa Luusua
6c7549a7c9
Merge pull request #1025 from sharetribe/fix-select-multiple-filter
Fix select multiple filter
2019-02-20 13:42:53 +02:00
Vesa Luusua
942b379de1 Update Changelog 2019-02-20 13:00:37 +02:00
Vesa Luusua
436151f804 Remove flashing CSS outline from FilterForm. 2019-02-20 12:55:29 +02:00
Vesa Luusua
72adafb895 Fix minor bug in SelectMultipleFilter on desktop.
Rerendering lost dirty values when hovering on ListingCard.
2019-02-20 12:55:29 +02:00
Vesa Luusua
38cb342999 Fix mobile SelectMultipleFilter.
It didn't call onSubmit after latest Final Form update was introduced to PR949.
(v2.9.0))
2019-02-20 12:55:23 +02:00
Vesa Luusua
b1eb69f6d3 Refactored className usage for InlineTextButton
They are changed to use rootClassName for consistency
and protection against future bundling order changes.
2019-02-19 15:49:49 +02:00
Vesa Luusua
d2b1db828e Refactored className usage for SecondaryButton
They are changed to use rootClassName for consistency
and protection against future bundling order changes.
2019-02-19 15:49:48 +02:00
Vesa Luusua
06ae0f24d6 Removed nonexsistent className props copy-pasted for PrimaryButton 2019-02-19 15:49:48 +02:00
Vesa Luusua
32a55232e9 Refactor derivative buttons so that they can also take in rootClassName
This means PrimaryButton, SecondaryButton and InlineTextButton.
However, those can still be used as before.
2019-02-19 15:49:47 +02:00
Vesa Luusua
9e3c8ec51f Reorder components/index.js and fix css for MenuContent 2019-02-19 15:49:43 +02:00
Vesa Luusua
d3b8c558a5 Remove unused MapPanel component 2019-02-19 13:26:57 +02:00
Vesa Luusua
c30a6ab6e2
Merge pull request #1019 from sharetribe/fix-page-widths
Page content width should be enforced to 1056px
2019-02-18 16:40:16 +02:00
Jenni Nurmi
3b2bc6bb26 Update changelog 2019-02-18 16:31:26 +02:00
Jenni Nurmi
41fac4000b Add two new custom breakpoints 2019-02-18 16:08:51 +02:00
Jenni Nurmi
d347ba5cf4 Side navigation matches footer 2019-02-18 15:33:36 +02:00
Jenni Nurmi
aae6380559 Unify page width when page should match to footer 2019-02-18 15:33:20 +02:00
Vesa Luusua
a3239dd1da
Merge pull request #1023 from sharetribe/sanitize-entity-content
Sanitize example for listing and user entities
2019-02-15 16:57:40 +02:00
Vesa Luusua
30efce5ac3 Update Changelog. 2019-02-15 16:09:13 +02:00
Vesa Luusua
ae311b62f0 Sanitize example for listing and user entities 2019-02-15 16:09:08 +02:00
Jenni Nurmi
385b35e264
Merge pull request #1022 from sharetribe/show-deleted-user
Show deleted user
2019-02-14 10:34:32 +02:00
Jenni Nurmi
35893e06b5 Update changelog 2019-02-12 10:22:44 +02:00
Jenni Nurmi
6cf77849c8 Remove unused translation keys 2019-02-12 10:22:44 +02:00
Jenni Nurmi
6440d0ce61 Use UserDisplayName in TransactionPanel 2019-02-12 10:22:44 +02:00
Jenni Nurmi
9ed5f82288 Hide SendMessageForm if one of the users is banned or deleted 2019-02-12 10:22:44 +02:00
Jenni Nurmi
9af5705d40 Use userDisplayNameAsString function on ListingPage 2019-02-12 10:22:44 +02:00
Jenni Nurmi
ccbbc1a290 Update Avatar to use not userDipslayNameAsString function 2019-02-12 10:22:44 +02:00
Jenni Nurmi
fb5e0ec73b Edit userAbbreviatedName function to be usable also when user is deleted 2019-02-12 10:22:44 +02:00
Jenni Nurmi
00414e70f9 Add userDisplayNameAsString function 2019-02-12 10:22:44 +02:00
Jenni Nurmi
37ca536f6e Use UserDisplayName in InboxPage 2019-02-12 10:22:44 +02:00
Jenni Nurmi
52cf6c4abd Use UserDisplayName in Reviews 2019-02-12 10:22:44 +02:00
Jenni Nurmi
cde1ec2e7e Use UserDisplayName in ActivityFeed 2019-02-12 10:22:44 +02:00
Jenni Nurmi
63fc14eeae Create UserDisplayName component 2019-02-12 10:22:44 +02:00
Jenni Nurmi
e96f91de9e Fix mobile view when listing is deleted 2019-02-12 10:22:44 +02:00
Jenni Nurmi
099dd6bd9e Add handling for deleted and banned user to types.js 2019-02-12 10:22:44 +02:00
Jenni Nurmi
3110babfaa
Merge pull request #1021 from sharetribe/reset-password-with-unverified-email
Remove error handling for unverified email from PasswordRecoveryPage
2019-02-06 15:23:35 +02:00
Jenni Nurmi
15c0a05e55 Update changelog 2019-02-06 13:29:51 +02:00
Jenni Nurmi
5f27f2b103 Remove error handling for unverified email from PasswordRecoveryPage 2019-02-06 13:29:46 +02:00
Vesa Luusua
4a36f4ac1c
Merge pull request #1020 from sharetribe/add-audit-script
Add audit script to check dependency vulnerabilities
2019-02-05 15:35:01 +02:00
Vesa Luusua
9590c46861 Update changelog 2019-02-05 15:16:02 +02:00
Vesa Luusua
1732ae42ea Add audit CI job 2019-02-05 15:16:02 +02:00
Vesa Luusua
dbae9ecd84 Add audit script 2019-02-05 15:15:51 +02:00
Vesa Luusua
49ad3f9395 Add bfj dev-dependency 2019-02-05 12:46:13 +02:00
Vesa Luusua
9ae3bfa5be
Merge pull request #1018 from sharetribe/v2.10.0
Release v2.10.0
2019-01-31 15:00:26 +02:00
Vesa Luusua
06be30d5fe Release v2.10.0 2019-01-31 14:58:11 +02:00
Vesa Luusua
a270b9552a
Merge pull request #1004 from sharetribe/refactor-transaction-ui
Refactor transaction handling
2019-01-31 13:58:05 +02:00
Vesa Luusua
bb5141eb50 Update changelog 2019-01-31 12:54:37 +02:00
Jenni Nurmi
f340c19ae8 Use generic functions from transaction.js
(and move some generic in-file functions there).
2019-01-30 18:31:13 +02:00
Jenni Nurmi
f824e4fd2b Refactor ActivityFeed component
Add function for checking ownRole
Use txHasReviewBy function
add isCustomerReview and isProviderReview functions
2019-01-30 18:31:12 +02:00
Vesa Luusua
726389c941 Update tests in TransactionPanel. 2019-01-30 18:31:12 +02:00
Vesa Luusua
caad06353e Add state graph description and refactor transaction.js functions to use it. 2019-01-30 18:31:05 +02:00
Jenni Nurmi
6d6ebbffc1 Refactor InboxPage:
use txHasBeenDelivered function,
rename css classes,
add txIsRequested check and handle unknown transition separately,
filter unknown transitions when fetching data,
don't render InboxItem if latest transition is unknown,
update InboxPage tests.
2019-01-30 15:35:20 +02:00
Vesa Luusua
32fc6ba5b1 Split TransactionPanel to dummy subcomponents
and reduce direct state check agains current transaction.
2019-01-30 15:35:09 +02:00
Vesa Luusua
538faf945d Add tx helpers related to sending a review 2019-01-30 14:21:00 +02:00
Vesa Luusua
c33afc9b0c Expose which transitions lead to request 2019-01-30 14:20:59 +02:00
Vesa Luusua
419dbb05d8 BookingDatesForm doesn't need to test last transition. 2019-01-30 14:20:59 +02:00
Vesa Luusua
6b2b7e9b6c Add txHasBeenDelivered helper function 2019-01-30 14:20:59 +02:00
Vesa Luusua
a7b7c58d80 Extract transaction related code to its own util file
from types.js
2019-01-30 14:20:59 +02:00
Kimmo Puputti
e56864050f
Merge pull request #1015 from sharetribe/customization-checklist-and-related-docs
Move more documentation to Flex Docs
2019-01-29 15:56:34 +02:00
Kimmo Puputti
76823c4d40 Update outdated email template docs 2019-01-29 15:53:22 +02:00
Kimmo Puputti
a56456c1b6 Improve directory tree view 2019-01-29 15:45:44 +02:00
Kimmo Puputti
8bceee2982 Add changelog entry 2019-01-29 15:34:16 +02:00
Kimmo Puputti
bf05354bcd Remove unused Jekyll config file 2019-01-29 15:33:12 +02:00
Kimmo Puputti
885d2840a9 Update readme files 2019-01-29 15:33:12 +02:00
Kimmo Puputti
5d2601000b Move Redux and routing docs to Flex Docs 2019-01-29 15:33:12 +02:00
Kimmo Puputti
e2dc22f38f Move improve performance doc to Flex Docs 2019-01-29 15:33:12 +02:00
Kimmo Puputti
0f272147ce Inline dir structure to docs readme 2019-01-29 15:33:12 +02:00
Kimmo Puputti
bd9bbbed2c Migrate more docs to Flex Docs
- ci
- deploying to production
- extend listing data
- extended data (removed)
- search filters
2019-01-29 15:33:12 +02:00
Kimmo Puputti
f36bc32694 Move documentation to Flex Docs
- customization checklist
- styling
- icons
- translations
- tos and privacy policy
- static pages
2019-01-29 15:33:12 +02:00
Vesa Luusua
86eb33674d
Merge pull request #1017 from sharetribe/v2.9.0
Release v2.9.0
2019-01-29 15:23:04 +02:00
Vesa Luusua
273019af59 Release v2.9.0 2019-01-29 15:19:35 +02:00
Vesa Luusua
6d09d1281c
Merge pull request #1016 from sharetribe/fix-date-filter-fetch-params
SearchPage.duck.js: endDate should not be expanded for night bookings
2019-01-29 15:16:42 +02:00
Vesa Luusua
0e860c480a Update changelog 2019-01-29 14:56:10 +02:00
Vesa Luusua
fbd26bdfec SearchPage.duck.js: endDate should not expand end date for night
DateRangeController: unittype day should allow 0 night
EditListingPage.duck.js booking state should be passed to query
2019-01-29 14:48:08 +02:00
Vesa Luusua
47cda11c90
Merge pull request #949 from sharetribe/date-filter
Date filter
2019-01-29 13:22:52 +02:00
Vesa Luusua
133ee1d44d Update changelog 2019-01-29 13:20:30 +02:00
Jenni Nurmi
94bb6be20a Add availability params to search query 2019-01-29 12:59:48 +02:00
Jenni Nurmi
c185072482 Update translations 2019-01-29 12:59:42 +02:00
Vesa Luusua
2dcea906ec Capitalize month name 2019-01-29 12:59:42 +02:00
Jenni Nurmi
2177ac39c9 Update search filters documentation 2019-01-28 14:37:42 +02:00
Jenni Nurmi
56151850dd Use OutsideClickHandler in FilterPopup 2019-01-28 14:37:42 +02:00
Jenni Nurmi
e5238ca78b Create OutsideClickHandler 2019-01-28 14:37:41 +02:00
Jenni Nurmi
b8db69b5b7 Delete unused code related to SelectSingleFilter 2019-01-28 14:37:41 +02:00
Jenni Nurmi
ac3db9efa3 Refactor SelectSingleFilter to use subcomponents SelectSingleFilterPlain and SelectSingleFilterPopup 2019-01-28 14:37:41 +02:00
Jenni Nurmi
d89aa64e57 Delete unused code related to SelectMultipleFilter 2019-01-28 14:37:41 +02:00
Jenni Nurmi
4c6435e569 Refactor SelectMultipleFilter to use FilterPopup and FilterPlain 2019-01-28 14:37:40 +02:00
Jenni Nurmi
b31656791c Add arrayMutators to FilterForm 2019-01-28 14:37:40 +02:00
Jenni Nurmi
27a49d1534 Add DateRangeFilter to desktop and mobile versions 2019-01-28 14:37:40 +02:00
Jenni Nurmi
6f7e6c2fc0 Add help functions for ISO8601 date format 2019-01-28 14:37:40 +02:00
Jenni Nurmi
601f6cbc5f Create FieldDateRangeController component 2019-01-28 14:37:40 +02:00
Jenni Nurmi
f3b66239a6 Create DateRangeController component 2019-01-28 14:37:40 +02:00
Jenni Nurmi
69631bf5fc Create BookingDateRangeFilter component 2019-01-28 14:37:39 +02:00
Jenni Nurmi
0870f01b13 Create FilterPopup component 2019-01-28 14:37:39 +02:00
Jenni Nurmi
b928c95a3b Create FilterPlain component 2019-01-28 14:37:39 +02:00
Jenni Nurmi
0d30657e90 Add FilterForm component 2019-01-28 14:37:39 +02:00
Vesa Luusua
c6306fc8a6
Merge pull request #1011 from sharetribe/ftw-translation-fix
en translation fix for ReviewForm.reviewRatingRequired
2019-01-28 14:11:23 +02:00
Vesa Luusua
a05448c48a Update changelog 2019-01-28 14:09:12 +02:00
Schwerbelastung
0cb03dc517 en translation fix for ReviewForm.reviewRatingRequired 2019-01-28 14:09:07 +02:00
Kimmo Puputti
0afdaa641d
Merge pull request #1014 from sharetribe/update-guide-and-testing-docs
Move customization guide and testing docs to Flex Docs
2019-01-28 11:52:53 +02:00
Kimmo Puputti
ce26e967d9 Add changelog entry 2019-01-28 10:41:58 +02:00
Kimmo Puputti
dfc3a85557 Move customization guide and testing docs to Flex Docs 2019-01-28 10:39:27 +02:00
Kimmo Puputti
caa074c218
Merge pull request #1012 from sharetribe/update-docs
Update docs
2019-01-25 16:39:23 +02:00
Kimmo Puputti
5f079592a7 Fix changelog entry 2019-01-25 16:34:18 +02:00
Kimmo Puputti
53f8bb3f6f Re-run Prettier with updated dependencies 2019-01-25 16:32:01 +02:00
Kimmo Puputti
87d488d8b6 Add changelog entry 2019-01-25 15:51:51 +02:00
Kimmo Puputti
b8d2170eed Update docs
- Link to Flex Docs
- Replace content with a link to Flex Docs if content is moved there
2019-01-25 15:46:46 +02:00
Jenni Nurmi
499417fe45
Merge pull request #1007 from sharetribe/fix-invalid-proptype-in-booking-panel
Add ownListing to listing prop type
2019-01-23 12:52:54 +02:00
Jenni Nurmi
f8b125e462 Update changelog 2019-01-23 11:47:19 +02:00
Jenni Nurmi
5d5c745c2a Add ownListing to listing prop type 2019-01-23 09:40:15 +02:00
Jenni Nurmi
4d3e1391e7
Merge pull request #1006 from sharetribe/additional-owner-info
Add additional owners info text to PayoutDetails form
2019-01-22 15:46:07 +02:00
Jenni Nurmi
01c2bcfab7 Edit changelog 2019-01-22 15:38:32 +02:00
Jenni Nurmi
7d3b229731 Add link to additional owner info text 2019-01-22 15:35:54 +02:00
Jenni Nurmi
7523971718 Add additional owners info text to PayoutDetails form 2019-01-22 15:35:54 +02:00
Jenni Nurmi
6a5b3af8c3
Merge pull request #1005 from sharetribe/default-to-en-translation
Default to English translation if translation key is missing
2019-01-22 15:33:34 +02:00
Jenni Nurmi
dd2fc19d05 Update changelog 2019-01-22 15:30:33 +02:00
Jenni Nurmi
05474d9e89 Update documentation 2019-01-22 10:57:49 +02:00
Jenni Nurmi
73eb62af1d If keys are missing from selected translation file default to english keys 2019-01-22 10:57:44 +02:00
Jenni Nurmi
aa8c09e43e
Merge pull request #1003 from sharetribe/remove-origin-from-default-searches
Remove origin from default searches
2019-01-18 13:28:56 +02:00
Jenni Nurmi
99a50cdc95 Update changelog 2019-01-18 13:23:50 +02:00
Jenni Nurmi
97da6dd066 Add note to sortSearchByDistance config 2019-01-18 13:22:25 +02:00
Jenni Nurmi
36ed1eff26 Remove origin from default searches 2019-01-18 13:22:25 +02:00
Jenni Nurmi
a3d896329e
Merge pull request #1002 from sharetribe/limit-location-autocomplete
Enable limiting location autocomplete to a certain country
2019-01-18 12:56:10 +02:00
Jenni Nurmi
6ff26d4bfa Update changelog 2019-01-18 11:13:34 +02:00
Jenni Nurmi
9d7d302a7a Update documentation 2019-01-18 11:13:30 +02:00
Jenni Nurmi
e8ec5dbf94 Use country restriction in Google Maps integration 2019-01-18 10:14:45 +02:00
Jenni Nurmi
16246487e4 Use country restriction in Mapbox integration 2019-01-18 10:13:20 +02:00
Jenni Nurmi
b038aa2f5b Add country restriction to config.js file 2019-01-18 10:13:12 +02:00
Jenni Nurmi
dfbaa5449e Update Mapbox SDK 2019-01-17 15:29:46 +02:00
Jenni Nurmi
725fcb5e7a
Merge pull request #1001 from sharetribe/v2.8.0
v2.8.0
2019-01-17 13:32:55 +02:00
Jenni Nurmi
c8f6387b2b update package.json 2019-01-17 13:29:38 +02:00
Jenni Nurmi
c5fd82bd66 Update changelog 2019-01-17 13:23:34 +02:00
Jenni Nurmi
57a26bbe56
Merge pull request #994 from sharetribe/config-cli
Config CLI
2019-01-17 13:19:00 +02:00
Jenni Nurmi
0d2098c364 Update changelog 2019-01-17 12:44:47 +02:00
Jenni Nurmi
2b6795cc61 Edit docs and add comments to code 2019-01-17 12:44:00 +02:00
Jenni Nurmi
f114df7739 Edit environment variables after .env file is created
Merge to edit
2019-01-17 12:44:00 +02:00
Jenni Nurmi
8361c30fa3 Add validation to client id, stripe public key and currency 2019-01-17 12:44:00 +02:00
Jenni Nurmi
1119d51b97 Show error if .env file is missing when running yarn run dev 2019-01-17 12:44:00 +02:00
Jenni Nurmi
6aa2170f84 Remove sdk url from .env-template 2019-01-17 12:44:00 +02:00
Jenni Nurmi
db056aa78a Add instructions to questions and edit texts 2019-01-17 12:44:00 +02:00
Jenni Nurmi
3cabfcbe5b Add more variables to questions 2019-01-17 12:44:00 +02:00
Jenni Nurmi
7706bcd8f0 Save mandatory env variables to .env file 2019-01-17 12:44:00 +02:00
Jenni Nurmi
04a16fe8fe Create .env file if it doesn't exist 2019-01-17 12:44:00 +02:00
Jenni Nurmi
19357e6548 Add folder for scripts 2019-01-17 12:44:00 +02:00
Jenni Nurmi
5ffe9a45c5
Merge pull request #999 from sharetribe/update-sentry
Update sentry
2019-01-17 12:40:30 +02:00
Jenni Nurmi
c43f9c034b Update changelog 2019-01-17 10:29:39 +02:00
Jenni Nurmi
d8bf1c926c Update Sentry DSN related env variables and docs 2019-01-17 10:29:39 +02:00
Jenni Nurmi
21029f549e Use new Sentry SDKs insted of Raven 2019-01-17 10:29:33 +02:00
Jenni Nurmi
999c12b369
Merge pull request #1000 from sharetribe/use-env-variable-to-enable-availability-calendar
Use env variable to enable or disable availability calendar
2019-01-17 09:41:54 +02:00
Jenni Nurmi
1ef6d84839 Update changelog 2019-01-17 09:36:17 +02:00
Jenni Nurmi
44e69bf36c Use enableAvailability in ManageListingCard 2019-01-16 13:30:32 +02:00
Jenni Nurmi
1d15936bae Use enableAvailability in EditListingWizard 2019-01-16 12:52:34 +02:00
Jenni Nurmi
72e20dfb56 Rename variable fetchAvailableTimeSlots to enableAvailability 2019-01-16 12:46:56 +02:00
Vesa Luusua
e1e6681938
Merge pull request #996 from sharetribe/fix-banned-user-in-tx-page
Fix banned user / deleted listing on TransactioPage
2019-01-10 17:56:40 +02:00
Vesa Luusua
db658bb0b8 Update changelog 2019-01-10 17:54:48 +02:00
Vesa Luusua
958ae089c9 Fix banned user / deleted listing on TransactioPage 2019-01-10 17:52:27 +02:00
Vesa Luusua
621f078661
Merge pull request #998 from sharetribe/v2.7.1
New release v2.7.1
2019-01-09 15:05:40 +02:00
Vesa Luusua
6599003fc5 New release v2.7.1 2019-01-09 15:03:05 +02:00
Vesa Luusua
098a00737c
Merge pull request #997 from sharetribe/expand-blockable-dates-to-365
Expand blockable dates to 365
2019-01-09 14:58:13 +02:00
Vesa Luusua
558b43832a Update changelog 2019-01-09 14:28:15 +02:00
Vesa Luusua
676882534b Separate fetching availability exceptions and bookings.
This expands blockable dates to 365 days in advance.
2019-01-09 14:28:08 +02:00
Vesa Luusua
7cb204d94b
Merge pull request #995 from sharetribe/fix-typo
Fix typo
2019-01-09 11:45:55 +02:00
Vesa Luusua
fac1e129e8 Update changelog 2019-01-08 18:10:27 +02:00
Vesa Luusua
2b6e870937 Fix typo 2019-01-08 18:07:24 +02:00
Vesa Luusua
f72700258e
Merge pull request #993 from sharetribe/v2.7.0
New release: v2.7.0
2019-01-08 16:42:44 +02:00
Vesa Luusua
1e732b4c97 New release: v2.7.0 2019-01-08 16:40:36 +02:00
Vesa Luusua
5a93f3a075
Updated a link in docs/translations.md 2019-01-08 16:38:05 +02:00
Vesa Luusua
03fa80ec09
Merge pull request #992 from sharetribe/add-spanish-translations
Add Spanish translations: es.json
2019-01-08 16:34:34 +02:00
Vesa Luusua
4de3544e2c Update changelog 2019-01-08 16:26:47 +02:00
Vesa Luusua
31cf19a87e Add info how to localize moment lib and update translations.md too 2019-01-08 16:26:25 +02:00
Vesa Luusua
dff4df747f Add Spanish translations file: es.json 2019-01-08 16:23:29 +02:00
Jenni Nurmi
c46b168ccc
Merge pull request #991 from sharetribe/update-translations
Update translations
2019-01-08 15:28:09 +02:00
Jenni Nurmi
089a4c4460 Update changelog 2019-01-08 15:26:33 +02:00
Jenni Nurmi
8de77822b1 Small fixes to en.json 2019-01-07 16:58:28 +02:00
Jenni Nurmi
b17036b8d3 Update fr.json 2019-01-07 16:58:14 +02:00
Jenni Nurmi
400a0d3df2
Merge pull request #980 from sharetribe/add-stripe-business-accounts
Add stripe business accounts
2019-01-07 14:40:31 +02:00
Jenni Nurmi
d22da25c73 Update changelog 2019-01-07 14:05:12 +02:00
Jenni Nurmi
ea22f94d43 Synchronize white modal width 2019-01-07 14:04:01 +02:00
Jenni Nurmi
d0bc25f0cf Add new translation keys to fr.json 2019-01-07 14:04:01 +02:00
Jenni Nurmi
08eb9e3a6e Update IconClose so it can be used in smaller size 2019-01-07 14:04:01 +02:00
Jenni Nurmi
9c31f3e0ea Add additional owners to company account if required 2019-01-07 14:04:01 +02:00
Jenni Nurmi
9d8d211677 Create IconAdd 2019-01-07 14:04:01 +02:00
Jenni Nurmi
6319c77731 Add personal address to company account if required 2019-01-07 14:04:01 +02:00
Jenni Nurmi
1ba857c3ce Add country specific tax id field labels 2019-01-07 14:04:01 +02:00
Jenni Nurmi
a3b43cec27 Update user.duck.js to support also business accounts 2019-01-07 14:04:01 +02:00
Jenni Nurmi
338fb79f57 Create PayoutDetailsBankDetails subcomponent 2019-01-07 14:04:01 +02:00
Jenni Nurmi
7dff8331aa Update PayoutDetailsAddress to contain section title 2019-01-07 14:04:01 +02:00
Jenni Nurmi
a3400f4933 Create PayoutDetailsPersonalDetails subcomponent 2019-01-07 14:04:01 +02:00
Jenni Nurmi
1e5e70a5c2 Separate PayoutDetailsForm to PayoutDetailsFormIndividual and PayoutDetailsFormCompany 2019-01-07 14:04:01 +02:00
Jenni Nurmi
abe973337c Use radio buttons in PayoutDetailsForm 2019-01-07 14:04:01 +02:00
Jenni Nurmi
dd33c4d9dc Add fields for company name and tax id 2019-01-07 14:04:01 +02:00
Vesa Luusua
ff682d97cf
Merge pull request #972 from sharetribe/manage-availability
Manage Availability
2019-01-07 13:11:31 +02:00
Vesa Luusua
16d5c41294 Update changelog 2019-01-07 13:08:27 +02:00
Vesa Luusua
3197d74ce4 Initial (english) translations for fr.json 2019-01-04 14:57:30 +02:00
Vesa Luusua
ec44fae2b3 ManageListingCard should have a link to the Availability tab 2019-01-04 14:57:30 +02:00
Vesa Luusua
904637487d Add EditListingAvailabilityPanel to the EditListingWizard 2019-01-04 14:57:29 +02:00
Vesa Luusua
e82a51c607 EditListingAvailabilityPanel component 2019-01-04 14:57:29 +02:00
Vesa Luusua
74a50e5323 EditListingAvailabilityForm component 2019-01-04 14:57:24 +02:00
Vesa Luusua
fe36cf84cc EditListingPage.js: connect calendar data and functions from Redux setup 2019-01-04 14:53:13 +02:00
Vesa Luusua
c04742e160 EditListingPage.duck.js: add thunk functions for availability calendar
- requestFetchBookings
- requestFetchAvailabilityExceptions
- requestCreateAvailabilityException
- requestDeleteAvailabilityException
2019-01-04 14:53:03 +02:00
Vesa Luusua
854958d9e7 Add date utils: monthIdString, isDate, isSameDate 2019-01-03 12:54:41 +02:00
Vesa Luusua
2484b7948b Add new ensure* functions 2019-01-03 12:54:41 +02:00
Vesa Luusua
826aceaebe Add availabilityPlan to OwnListing attributes and add proptype availabilityException 2019-01-03 12:54:41 +02:00
Vesa Luusua
23cac31428 withViewport context helper should listen orientation changes 2019-01-03 12:54:41 +02:00
Vesa Luusua
25ae9f3833
Merge pull request #990 from sharetribe/v2.6.0
v2.6.0
2019-01-02 15:28:16 +02:00
Vesa Luusua
77e19c4a24 v2.6.0 2019-01-02 15:26:28 +02:00
Vesa Luusua
f94828a926
Merge pull request #989 from sharetribe/update-fr-translations
Update fr translations
2019-01-02 15:10:48 +02:00
Vesa Luusua
95749ce765 Update changelog 2019-01-02 15:06:45 +02:00
Vesa Luusua
922dfb2c64 Wrong translation for perUnit (it was english) 2019-01-02 15:05:41 +02:00
Hannu Lyytikäinen
5831cb7d7b
Merge pull request #988 from sharetribe/enquiry-to-tx-ui
Layout changes to listing and tx (enquiry) page
2018-12-31 15:09:31 +02:00
Hannu Lyytikainen
b20c6ca555 Fix BookingPanel title class overriding
Fix the title class overriding so that the css load order does not
affext the styles. Also removes a redundant media query definition.
2018-12-31 15:01:29 +02:00
Hannu Lyytikainen
298018f96f Update changelog 2018-12-27 14:36:52 +02:00
Hannu Lyytikainen
39539f2cdf Change BookingPanel title margin on tx page 2018-12-27 14:28:07 +02:00
Hannu Lyytikainen
2a728a64ad Change layouts to match design
Apply design baseline definitions on BookingDatesForm, BookingPanel and
ListingPage.
2018-12-27 13:57:13 +02:00
Hannu Lyytikäinen
7d64044711
Merge pull request #987 from sharetribe/fix-booking-title
Fix wrong booking title on listing page
2018-12-27 11:43:41 +02:00
Hannu Lyytikainen
4421410990 Update changelog 2018-12-27 11:38:34 +02:00
Hannu Lyytikainen
2c3bb15355 Fix wrong booking title on listing page 2018-12-27 11:35:36 +02:00
Vesa Luusua
4f489ea50c
Merge pull request #986 from sharetribe/fix-yarn-lock
Fix yarn lock
2018-12-21 10:51:53 +02:00
Vesa Luusua
adfce73cb6 Update changelog 2018-12-21 10:40:58 +02:00
Vesa Luusua
bdc1297034 Fix yarn.lock by running yarn install 2018-12-21 10:36:11 +02:00
Hannu Lyytikäinen
d2e8ea08df
Merge pull request #976 from sharetribe/enquire-to-tx
Enable requesting to book straight from enquiry
2018-12-20 18:10:39 +02:00
Hannu Lyytikainen
1dba15331a Streamline sale buttons visibility logic 2018-12-20 18:03:29 +02:00
Hannu Lyytikainen
ad6fc6346b Fix session store handling for enquired tx 2018-12-20 18:03:29 +02:00
Hannu Lyytikainen
4f21f3a214 Hide desktop booking breakdown in mobile 2018-12-20 18:03:29 +02:00
Hannu Lyytikainen
29875d4210 Update changelog 2018-12-20 18:03:29 +02:00
Hannu Lyytikainen
08378d7001 Fix footer overlapping booking calendar
Rise the transaction details section on top of the footer so that the
booking dates calendar won't go below it.
2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
65a1358b93 Fix hidden open booking form section in mobile 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
4663f825a1 Change checkout page booking sub title
Unify the sub title with transaction page.
2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
8d2adf0140 Hide initial message on booking after enquiry 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
bbac34a0e5 Add initiate order after enquiry
If enquired transaction is avalable transition it to prequthorized on
checkout page.
2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
7cc30ee3ef Pass booking data from tx page to checkout 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
a0d1984103 Unify listing info sub titles 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
5fe0ac3d47 Add onManageDisableScrolling to BookingPanel 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
a053a6c81a Fetch time slots on tx page 2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
68f6eaa391 Show BookingPanel on tx page
Show the BookingPanel component on the tx page when the transaction has
been started with an enquiry.
2018-12-20 18:02:29 +02:00
Hannu Lyytikainen
38b780827d Hide listing address link from provider 2018-12-20 18:02:29 +02:00
Hannu Lyytikäinen
f0534bd6a5
Merge pull request #969 from sharetribe/extract-section-booking
Extract booking section from listing page
2018-12-20 17:58:30 +02:00
Hannu Lyytikainen
3d11d733e0 Change BookingPanel dependency import order
Place components and forms as last imports before the ones from the same
folder.
2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
f4f67be661 Change formatted title and sub title type
Change formatted title and sub title type to node in BookingPanel.
Also remove FormattedText component which renders a redundant span element.
2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
080ae345a6 Change unit type translation resolving 2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
bee450d786 Change BookingPanel title handling
Use title and sub title provided by a parent component.
2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
167cc2608d Change name and type for richText prop
Rename the prop to title and allow it to be and object or a string. This
way a normal string or a styled html element can be provided.
2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
3ea7738564 Fix BookingPanel baseline adjustments 2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
01b1830cbd Update changelog 2018-12-20 17:48:26 +02:00
Hannu Lyytikainen
2a886131c4 Remove some unused props passed to BookingPanel 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
e894dead63 Clean up BookingPanel props
Remove isClosed and price from the BookingPanel props as they can be
resolved from the listing.
2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
9cd3c0c5ad Remove redundant style class definitions 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
d6ed766d1b Fix listing page layout 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
a032d06eea Use page specific message key on CheckoutPage 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
936d2955d9 Add BookingPanel styleguide example 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
b7e5165999 Update translation keys 2018-12-20 17:47:10 +02:00
Hannu Lyytikainen
60d5a44d5d Extract SectionBooking into a distinct component
Extract SectionBooking away from ListingPage to a distinct component
called BookingPanel.
2018-12-20 17:47:10 +02:00
Vesa Luusua
5b0443c70f
Merge pull request #985 from sharetribe/fork-button-to-deploy-guide
Add image of fork button to deploy guide
2018-12-20 16:41:13 +02:00
Vesa Luusua
22a8b63b3a Update changelog 2018-12-20 16:14:24 +02:00
Vesa Luusua
c170bc31a3 Run Prettier for docs 2018-12-20 16:09:50 +02:00
Vesa Luusua
55dc734cf0 Add Fork instruction with image 2018-12-20 16:09:09 +02:00
Vesa Luusua
7073234b1e
Add image of fork button to deploy guide 2018-12-20 15:46:29 +02:00
Mikko Koski
d783f96404
Merge pull request #984 from sharetribe/changelog-remove-builtin
CHANGELOG: Removed built-in email templates
2018-12-19 12:42:28 +02:00
Mikko Koski
043ddaf293
Merge pull request #983 from sharetribe/delete-default-builtin-templates
Delete default builtin mail templates
2018-12-19 12:42:14 +02:00
Mikko Koski
adc2d382cb
CHANGELOG: Removed built-in email templates 2018-12-19 11:44:33 +02:00
Antti Salmivaara
e353d7fb4f Update email template readme 2018-12-19 10:25:55 +02:00
Antti Salmivaara
d7b0b2515e Update templates to have default footer 2018-12-18 16:40:52 +02:00
Antti Salmivaara
8c65594ec3 Remove email templates that can be edited in console 2018-12-18 16:39:43 +02:00
Jenni Nurmi
15f0835d76
Merge pull request #982 from sharetribe/v2.5.0
New release v2.5.0
2018-12-17 16:02:28 +02:00
Jenni Nurmi
3d9c644c63 New release v2.5.0 2018-12-17 15:59:44 +02:00
Jenni Nurmi
2650e53844
Merge pull request #981 from sharetribe/add-new-translations
Add new translations
2018-12-17 15:56:17 +02:00
Jenni Nurmi
ede549f80c Update changelog 2018-12-17 15:52:35 +02:00
Jenni Nurmi
49f5a8aef1 Small fixes to English translations for consistency 2018-12-17 15:44:25 +02:00
Jenni Nurmi
6c22b46005 Update French translations 2018-12-17 15:40:55 +02:00
Jenni Nurmi
e8c9863ef1
Merge pull request #977 from sharetribe/create-radio-button-field
Create FieldRadioButton component
2018-12-17 14:03:49 +02:00
Jenni Nurmi
a3f34177bb Update changelog 2018-12-17 13:57:45 +02:00
Jenni Nurmi
fd4d258d05 Add example for not required radio button field 2018-12-17 13:56:01 +02:00
Jenni Nurmi
73bead91f9 Create FieldRadioButton component 2018-12-17 13:56:01 +02:00
Jenni Nurmi
af85a1f7d7
Merge pull request #979 from sharetribe/remove-audit
Temporarily remove audit from CircleCI
2018-12-17 13:54:47 +02:00
Jenni Nurmi
c08ea4eebf Update changelog 2018-12-17 13:52:01 +02:00
Jenni Nurmi
d66d2d55c2 Temporarily remove audit from CircleCI 2018-12-17 13:29:23 +02:00
Jenni Nurmi
2625b4427c
Merge pull request #968 from sharetribe/add-missing-stripe-countries
Add missing stripe countries
2018-12-11 10:49:46 +02:00
Jenni Nurmi
ffa3c7ee2f Update changelog 2018-12-11 10:45:56 +02:00
Jenni Nurmi
687cf7bbe9 Move Stripe config to separate file 2018-12-10 14:50:21 +02:00
Jenni Nurmi
3707a1bc04 Update translations 2018-12-10 14:50:21 +02:00
Jenni Nurmi
0035dae54b Add ID number field with validators to US and HK 2018-12-10 14:50:21 +02:00
Jenni Nurmi
0cc6cf9663 Add ID number field with validators to US and HK 2018-12-10 14:50:21 +02:00
Jenni Nurmi
a137773b82 Add Stripe support for Hong Kong 2018-12-10 14:50:21 +02:00
Jenni Nurmi
fe0102034a Add Stripe support for Norway 2018-12-10 14:50:21 +02:00
Jenni Nurmi
d98d5d8f62 Add Stripe support for Switzerland 2018-12-10 14:50:21 +02:00
Jenni Nurmi
c79fb7e141 Add Stripe support for New Zealand 2018-12-10 14:50:21 +02:00
Jenni Nurmi
45e00d2241 Add Stripe support for Canada 2018-12-10 14:50:21 +02:00
Jenni Nurmi
fe1082e5e5 Add field for personal id number to PayoutDetailsForm 2018-12-10 14:50:21 +02:00
Jenni Nurmi
89c62999be Create PayoutDetailsAddress subcomponent and edit address config 2018-12-10 14:50:21 +02:00
Jenni Nurmi
a84e8ae33e Refactor mapInputsToStripeAccountKeys function to make it easier to add different bank account formats 2018-12-10 14:50:20 +02:00
Jenni Nurmi
1b838091e7
Merge pull request #970 from sharetribe/improve-per-unit-translations
Improve per unit translations
2018-12-10 14:41:08 +02:00
Jenni Nurmi
09455123e1 Update changelog and comment in config 2018-12-10 14:03:29 +02:00
Jenni Nurmi
3fad2dd5d2 Update translations in ManageListingCard 2018-12-10 13:58:28 +02:00
Jenni Nurmi
086963a497 Update translations in ListingPage 2018-12-10 13:58:28 +02:00
Jenni Nurmi
512d820c38 Update translations in ListingCard 2018-12-10 13:58:28 +02:00
Jenni Nurmi
082707d012 Update translations in EditListingPricingForm 2018-12-10 13:58:28 +02:00
Vesa Luusua
8250341399
Merge pull request #975 from sharetribe/fix-add-missing-docs-formatting
Fix add missing docs formatting
2018-12-10 13:44:05 +02:00
Vesa Luusua
aab486c6fd Update changelog 2018-12-10 13:37:01 +02:00
Vesa Luusua
fa76ea5051 Formatting docs with newest Prettier.
Related commit  was lost at some point when dependencies were updated.
2018-12-10 13:34:11 +02:00
Vesa Luusua
69abdd6977
Merge pull request #974 from sharetribe/revert-973-revert-971-improvements-to-instructions
Revert "Revert "Improvements to instructions""
2018-12-10 13:30:42 +02:00
Vesa Luusua
0dde29f061
Revert "Revert "Improvements to instructions"" 2018-12-10 13:29:33 +02:00
Vesa Luusua
40be9e0184
Merge pull request #973 from sharetribe/revert-971-improvements-to-instructions
Revert "Improvements to instructions"
2018-12-10 13:00:58 +02:00
Vesa Luusua
3c8579d7e3
Revert "Improvements to instructions" 2018-12-10 12:59:10 +02:00
Vesa Luusua
f05d260e91
Merge pull request #971 from sharetribe/improvements-to-instructions
Improvements to instructions
2018-12-10 12:42:17 +02:00
Vesa Luusua
72f89e30f8 Update changelog 2018-12-10 12:25:45 +02:00
Thomas Malbaux
8c07b2d655 Remove year from Copyright footer translation key 2018-12-10 12:10:13 +02:00
Thomas Malbaux
99a18de4b1 Improvements to documentation 2018-12-10 12:10:12 +02:00
Vesa Luusua
4d89501af4
Fixed wrong prefix for Stripe publishable key
Prettier formatted prefix to italics.
2018-12-10 11:09:49 +02:00
Jenni Nurmi
d2dc3f26fe
Merge pull request #967 from sharetribe/update-dependencies
Update dependencies
2018-12-05 11:33:30 +02:00
Jenni Nurmi
75aae47da8 Update changelog 2018-12-05 11:27:08 +02:00
Jenni Nurmi
47f2689a4c In react-dates components use readOnly prop on mobile to fix bug 2018-12-05 11:07:47 +02:00
Jenni Nurmi
0aca4567c2 Update Prettier to 1.15.3 2018-12-05 11:07:47 +02:00
Jenni Nurmi
1fa91f7cf7 Update express to 4.16.4 2018-12-05 11:07:47 +02:00
Jenni Nurmi
e34539d78e Update source-map-support to 0.5.9 2018-12-05 11:07:47 +02:00
Jenni Nurmi
1f3f7b2878 Update seedrandom to 2.4.4 2018-12-05 11:07:47 +02:00
Jenni Nurmi
6181758a16 Update redux to 4.0.1 2018-12-05 11:07:47 +02:00
Jenni Nurmi
e3bdc831bc Update raven to 2.6.4 2018-12-05 11:07:47 +02:00
Jenni Nurmi
6884c3f086 Update prop-types to 15.6.2 2018-12-05 11:07:47 +02:00
Jenni Nurmi
d149c44097 Update moment to 2.22.2 2018-12-05 11:07:47 +02:00
Jenni Nurmi
b14f4ec0a5 Update lodash to 4.17.11 2018-12-05 11:07:47 +02:00
Jenni Nurmi
51e38ba3b2 Update enzyme-to-json to 3.3.4 2018-12-05 11:07:47 +02:00
Jenni Nurmi
c644b4ec2d Update core-js to 2.5.7 2018-12-05 11:07:47 +02:00
Jenni Nurmi
eae4bcb9b9 Update compression to 1.7.3 2018-12-05 11:07:47 +02:00
Jenni Nurmi
346abc0483 Update classnames to 2.2.6 2018-12-05 11:07:47 +02:00
Jenni Nurmi
6f66fa82e5 Update body-parser to 1.18.3 2018-12-05 11:07:47 +02:00
Jenni Nurmi
736db7681f Update basic-auth to 2.0.1 2018-12-05 11:07:47 +02:00
Jenni Nurmi
15259a6b18 Update react-moment-proptypes to 1.6.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
fecdb42ce5 Update react-dates to 18.2.2 2018-12-05 11:07:47 +02:00
Jenni Nurmi
a6949bff42 Update react-dates to 17.2.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
1983fca5bb Update react-router-dom to 4.3.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
f00a81d51c Update redux-thunk to 2.3.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
8a5e2d3ebb Update react-redux to 5.1.1 2018-12-05 11:07:47 +02:00
Jenni Nurmi
9f07463731 Update react-intl to 2.7.2 2018-12-05 11:07:47 +02:00
Jenni Nurmi
45716754e6 Update react and react-dom to 16.6.3 2018-12-05 11:07:47 +02:00
Jenni Nurmi
2ef6f297de Update raven-js to 3.27.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
c4b02026fc Update path-to-regexp to 2.4.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
f6cbc47e98 Update Helmet to 3.15.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
7a5f1e3820 Update all Final Form related dependecies 2018-12-05 11:07:47 +02:00
Jenni Nurmi
98f8bdfa12 Update ManageListingCard test because updated Enzyme shows React.Fragment in snapshot 2018-12-05 11:07:47 +02:00
Jenni Nurmi
6926d4eed0 Update Enzyme to 3.7.0 and enzyme-adapter-react-16 to 1.7.0 2018-12-05 11:07:47 +02:00
Jenni Nurmi
c7dc919d0a Update decimal.js to 10.0.1 2018-12-05 11:07:47 +02:00
Hannu Lyytikäinen
a67d5f2694
Merge pull request #964 from sharetribe/update-node
Change supported node version to the latest LTS
2018-12-04 13:34:18 +02:00
Hannu Lyytikainen
2e8dbc02b2 Update changelog 2018-12-04 10:23:16 +02:00
Hannu Lyytikainen
17cbb5c7dd Change supported node version to the latest LTS 2018-12-04 10:22:17 +02:00
Jenni Nurmi
54154a40da
Merge pull request #961 from sharetribe/improve-production-setup
Improve production setup
2018-12-03 14:08:09 +02:00
Jenni Nurmi
62fbf089a2 Update changelog 2018-12-03 14:06:21 +02:00
Jenni Nurmi
0d6fd6627a Update documentation README 2018-12-03 13:54:38 +02:00
Jenni Nurmi
284745fe20 Create deploying to production documentation 2018-11-30 09:35:35 +02:00
Jenni Nurmi
7b008d6d6b Add Heroku button to README.md 2018-11-30 09:35:29 +02:00
Jenni Nurmi
fa8d09c484 Create app.json 2018-11-30 09:34:21 +02:00
Hannu Lyytikäinen
f9f5337e3c
Merge pull request #966 from sharetribe/add-fr-translation
Add a missing translation
2018-11-29 12:10:38 +02:00
Hannu Lyytikainen
12ce4aa8ef Update changelog 2018-11-29 12:07:00 +02:00
Hannu Lyytikainen
baae0af3c8 Add a missing translation
Also removes two obsolete ones.
2018-11-29 12:07:00 +02:00
Hannu Lyytikäinen
2fd19b4877
Merge pull request #965 from sharetribe/release
Release 2.4.0
2018-11-28 11:46:50 +02:00
Hannu Lyytikainen
f71ae73584 Update version in package.json 2018-11-28 11:41:23 +02:00
Hannu Lyytikainen
5ddaa87b4d Update changelog 2018-11-28 11:40:47 +02:00
Hannu Lyytikäinen
361b1b0559
Merge pull request #963 from sharetribe/update-sdk
Update JS SDK to 1.2
2018-11-28 11:37:58 +02:00
Hannu Lyytikainen
560e3cc3d6 Update changelog 2018-11-28 10:11:23 +02:00
Hannu Lyytikainen
1f3e8ac1a0 Disable base url in .env template 2018-11-28 10:07:12 +02:00
Hannu Lyytikainen
7177cb37c7 Pass base url to SDK only if provided 2018-11-28 10:07:03 +02:00
Hannu Lyytikainen
08e23c7c83 Update JS SDK to 1.2 2018-11-28 09:17:43 +02:00
Hannu Lyytikäinen
caa73c2efe
Merge pull request #962 from sharetribe/fr-language
Add French as a default language
2018-11-27 12:55:36 +02:00
Hannu Lyytikainen
baca28f704 Fix an action on changelog 2018-11-27 12:51:02 +02:00
Hannu Lyytikainen
343f76d11f Update changelog 2018-11-27 12:50:25 +02:00
Hannu Lyytikainen
6a222d29bd Change example language from es to it
We'll be adding es as default language soon so better use some
non-default language as an example of a language that a customizer would
add.
2018-11-27 12:50:25 +02:00
Hannu Lyytikainen
f1d8f49ef2 Update documentation regarding default languages 2018-11-27 12:50:25 +02:00
Hannu Lyytikainen
6066b88f81 Add French translations 2018-11-27 12:50:25 +02:00
Hannu Lyytikäinen
e2aca7ac5a
Merge pull request #955 from sharetribe/translations-cli
Translations management CLI
2018-11-27 12:50:01 +02:00
Hannu Lyytikainen
cd796d2141 Update gif to match the changed behaviour 2018-11-27 12:36:45 +02:00
Hannu Lyytikainen
f7368e4824 Change confirmation response to case insensitive 2018-11-27 12:36:45 +02:00
Hannu Lyytikainen
0cfd8ce22b Split execution to two parts
Split execution so that after translating a key the application does not
return to the beginning but to the keys listing with the same language.
2018-11-27 12:36:45 +02:00
Hannu Lyytikainen
44d061052a Format docs 2018-11-27 12:36:45 +02:00
Hannu Lyytikainen
94658707fa Update documentation 2018-11-27 12:36:45 +02:00
Hannu Lyytikainen
ad0c591be5 Rename source lang code field 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
d15a9652e0 Remove confirmation values filter
Use 'y' and 'N' instead of filtering them to booleans as the filtered
value is printed to the console and is confusing is differs from the one
user typed.
2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
3f18707e72 Write new translation on a new line 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
aeb3369914 Change executable to normal .js file
An executable provides little or nothing extra in this case and running
the tool as 'node translations.js' is more universal across platforms
than './translations'.
2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
c9ce608e1f Filter out non .json files 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
1eeccb9153 Wrap file writing to a Promise 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
aa75f56e62 Resolve target languages form translation files 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
5d96c6ac76 Read translation files with fs.readFileSync()
Instead of using require which caches the file contents, read the
translation files using fs.readFileSync().
2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
b565099707 Add confirmation prompt for new translation 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
fecd3ae06e Remove unnecessary print out 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
ae347bdeed Update changelog 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
f3de5c7bb7 Update documentation 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
e52f318750 Change translations.js into an executable 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
eb90087624 Fix formatting 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
31b4cbecba Improve the missing keys list 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
fc7ddb0b63 Add some color to outputs 2018-11-27 12:36:44 +02:00
Hannu Lyytikainen
9808df89f1 Add a CLI tool for managing translations 2018-11-27 12:36:44 +02:00
Jenni Nurmi
f485a5e141
Merge pull request #960 from sharetribe/fix-initial-order-error-bug
Show Stripe error message if error contains Stripe error
2018-11-26 13:40:33 +02:00
Jenni Nurmi
24eeb90d48 Update changelog 2018-11-26 13:35:08 +02:00
Jenni Nurmi
299358f1d2 Show error if payment amount is zero 2018-11-26 13:34:58 +02:00
Jenni Nurmi
381b6d8191 Show Stripe error message if error contains Stripe error 2018-11-23 12:56:41 +02:00
Jenni Nurmi
5425211635
Merge pull request #959 from sharetribe/fix-translation-keys
Fix translation keys
2018-11-22 10:11:58 +02:00
Jenni Nurmi
cbeb61da86 Update changelog 2018-11-22 10:00:52 +02:00
Jenni Nurmi
51329edd62 Remove unused translation keys 2018-11-22 09:18:00 +02:00
Jenni Nurmi
c3be38c1bc Update correct title to PasswordChangePage.title 2018-11-22 09:17:41 +02:00
Vesa Luusua
a612a61772
Merge pull request #956 from sharetribe/fix-ModalMissingInformation-showing-too-early-take2
Fix modal missing information showing too early take2
2018-11-20 15:33:20 +02:00
Vesa Luusua
e51b0cbd42 Update version (v2.3.1 seems to be forgotten last time) 2018-11-20 15:27:50 +02:00
Vesa Luusua
307c6d5ca1 Update changelog 2018-11-20 15:27:50 +02:00
Vesa Luusua
e86f1a792f fix draft listing. ModalMissingInformation was still shown too early. 2018-11-20 15:27:45 +02:00
Vesa Luusua
65a081aa97
Merge pull request #954 from sharetribe/fix-price-filter-styles
Fix price filter styles
2018-11-19 12:57:23 +02:00
Vesa Luusua
450fe8134d Update changelog 2018-11-19 12:28:30 +02:00
Vesa Luusua
62d9be0baf PriceFilterForm: fix the position of a dash between inputs 2018-11-19 12:26:09 +02:00
Vesa Luusua
7422281f31 PriceFilterPlain: fix padding 2018-11-19 12:25:20 +02:00
Jenni Nurmi
ecaa1ece42
Merge pull request #953 from sharetribe/fix-draft-state-nagging-modal
Fix draft state nagging modal
2018-11-16 16:22:30 +02:00
Jenni Nurmi
2ca3f3b2e2 Update changelog 2018-11-16 16:09:18 +02:00
Jenni Nurmi
bcd36e9619 Don't set currenUserHasListings if fetched listing is in draft state 2018-11-16 16:04:26 +02:00
Vesa Luusua
5b8a7145be
Merge pull request #952 from sharetribe/add-index-files-to-prettierignore
Add index files to .prettierignore
2018-11-15 16:40:25 +02:00
Vesa Luusua
10869cde29 Update changelog 2018-11-15 15:18:21 +02:00
Vesa Luusua
8dcca64fb2 Add components and containers index-files to .prettierignore 2018-11-15 15:16:04 +02:00
Hannu Lyytikäinen
ee6a0b724b
Merge pull request #950 from sharetribe/translations-configuration
Review translations configuration and documentation
2018-11-15 10:59:10 +02:00
Hannu Lyytikainen
501d5b08f4 Fix a few typos in a comment 2018-11-15 10:15:09 +02:00
Hannu Lyytikainen
3513dfcfaa Update changelog 2018-11-15 10:15:09 +02:00
Hannu Lyytikainen
c2d29804d8 Add JS annotation to code snippets in docs 2018-11-15 10:14:39 +02:00
Hannu Lyytikainen
8909b5c693 Update translations documentation 2018-11-15 10:14:39 +02:00
Hannu Lyytikainen
f177f6a6ea Remove translation handling for tests
Translations are passed as props so the handling for translations in
tests is already done in test-helpers.js.
2018-11-15 10:14:39 +02:00
Hannu Lyytikainen
19f67fe64e Add a note about translations in tests 2018-11-15 10:14:39 +02:00
Hannu Lyytikainen
aa4ff59618 Pass translations to ReusableMapContainer in props 2018-11-15 10:14:39 +02:00
Jenni Nurmi
0abb0f7cef
Merge pull request #951 from sharetribe/addArrowHeadIcon
Add arrow head icon
2018-11-14 16:27:45 +02:00
Jenni Nurmi
aa8f606f81 Update changelog 2018-11-14 16:24:24 +02:00
Jenni Nurmi
a3acc1961f Update PaginationLinks test 2018-11-14 16:24:24 +02:00
Jenni Nurmi
7bafae01cf Align arrows with month caption 2018-11-14 16:24:24 +02:00
Jenni Nurmi
2338d0dd51 Use IconArrowHead on DateRangeInput 2018-11-14 16:24:09 +02:00
Jenni Nurmi
c0dd47fd02 Use IconArrowHead on PaginationLinks 2018-11-14 16:23:02 +02:00
Jenni Nurmi
f4a14c50f3 Create IconArrowHead 2018-11-14 16:23:02 +02:00
Jenni Nurmi
ac287cfffb
Merge pull request #947 from sharetribe/draft-listing
Draft listing
2018-11-13 10:10:08 +02:00
Jenni Nurmi
516c486e81 Version updated 2018-11-13 09:59:30 +02:00
Jenni Nurmi
7d9d96cf00 Changelog updated 2018-11-13 09:58:52 +02:00
Jenni Nurmi
75f295cbfc ListingPage: ActionBar links to draft edit mode
if listing is a draft.
2018-11-07 16:32:33 +02:00
Jenni Nurmi
9037ed3e70 ManageListingCard uses Overlay subcomponent.
Edit links to correct edit mode: draft vs. edit.
2018-11-07 16:32:33 +02:00
Janne Koivistoinen
0fb69e90ea Adds Overlay component to ManageListingCard 2018-11-07 16:32:33 +02:00
Vesa Luusua
7ed97a7a48 EditListingPhotosPanel: use newListingPublished, not newListingCreated 2018-11-07 16:32:32 +02:00
Vesa Luusua
9e48a1fca7 EditListingWizard: use onCreateListingDraft and onPublishListingDraft
instead of plain createListing.
2018-11-07 16:32:32 +02:00
Vesa Luusua
98e279542d EditListingWizard forms: handle errors from fetchErrors.
Every form should show (at least) updateListingError and showListingsError.
2018-11-07 16:32:31 +02:00
Vesa Luusua
2a31ccc458 EditListingWizard panels: pass all errors as fetchErrors to Final Form 2018-11-07 16:32:31 +02:00
Vesa Luusua
f7efde7baf EditListingPage: use draft thunks and check listing draft state 2018-11-07 16:32:12 +02:00
Vesa Luusua
bbb08d75ee EditListingPage.duck: create listing draft, publish listing draft.
Removing requestCreateListing and actions for storing local draft data to redux store.
2018-11-07 16:25:28 +02:00
Vesa Luusua
aaa8b16657 Update dependencies: Flex SDK 2018-11-07 16:25:28 +02:00
Vesa Luusua
3a797fc653 ListingPage: handle data loading of draft listings 2018-11-07 13:54:47 +02:00
Vesa Luusua
1aaad1d4e1 ListingLink: add draft as a path variant 2018-11-06 11:50:06 +02:00
Vesa Luusua
77743a2e4b Add ListingPage path params to urlHelpers.js 2018-11-06 11:45:03 +02:00
Vesa Luusua
3b834e98d0 Add LISTING_STATE_DRAFT to types.js 2018-11-06 11:42:58 +02:00
Vesa Luusua
f7837e3369 Fix API changes: description can be null. 2018-11-06 10:52:28 +02:00
Vesa Luusua
f09549b546
Merge pull request #946 from sharetribe/fix-ff-category-option
Fix Firefox: color for select options
2018-11-05 12:39:25 +02:00
Vesa Luusua
74c54a38be Run Prettier 2018-11-05 12:34:31 +02:00
Vesa Luusua
e4b56a4aa4 Update changelog 2018-11-05 12:33:53 +02:00
Vesa Luusua
3c99a88708 Fix Firefox: category options were grey 2018-11-05 12:15:23 +02:00
Vesa Luusua
9914504902
Update customization guide
Remove reference to cssnext and added reference to README.md
2018-11-02 15:19:56 +02:00
Vesa Luusua
ac84562108
Merge pull request #945 from sharetribe/v2.2.0
Update version to v2.2.0
2018-10-31 17:56:24 +02:00
Vesa Luusua
3cb4b0c60c Update version 2018-10-31 17:54:28 +02:00
Vesa Luusua
5db24d7770
Merge pull request #944 from sharetribe/pricing-filter
Pricing filter
2018-10-31 15:36:05 +02:00
Vesa Luusua
e472deaee6 Update changelog 2018-10-31 10:53:54 +02:00
Vesa Luusua
4df48013ef Update search-filters.md 2018-10-31 10:53:53 +02:00
Vesa Luusua
d32a4ba638 SearchPage: *fix* range end is exclusive in Flex API 2018-10-31 10:53:53 +02:00
Vesa Luusua
a063733564 SearchPage: add price filter 2018-10-31 10:53:53 +02:00
Vesa Luusua
eea6b7795c Marketplace custom config for price filter 2018-10-31 10:53:52 +02:00
Vesa Luusua
009f14e2c7 SearchFilters and SearchFiltersMobile 2018-10-31 10:53:52 +02:00
Vesa Luusua
647dee1360 PriceFilter 2018-10-31 10:53:51 +02:00
Vesa Luusua
fea522bf5c SelectMultipleFilterForm: fix padding to match design 2018-10-31 10:53:51 +02:00
Vesa Luusua
4c610a7014 PriceFilterForm 2018-10-31 10:53:46 +02:00
Vesa Luusua
433002e637 RangeSlider and FieldRangeSlider 2018-10-31 00:18:39 +02:00
Vesa Luusua
8dcd160817 withDimensions context helper 2018-10-31 00:18:08 +02:00
Vesa Luusua
d81a4b33ae Styleguide cleaning: Menu component label didn't have enough space 2018-10-30 22:55:13 +02:00
Vesa Luusua
6cc16430e3 Styleguide cleaning: ImageCarousel was using vw units (temp fix for styleguide) 2018-10-30 22:55:12 +02:00
Vesa Luusua
6200e7f593 Styleguide cleaning: styleguide links didn't break 2018-10-30 22:54:59 +02:00
Vesa Luusua
080f75f141 Styleguide cleaning: Footer behaved badly 2018-10-30 22:54:50 +02:00
Vesa Luusua
e07f5cf4c8 TopbarDesktop example didn't work on Styleguide - expects to be full width 2018-10-25 13:13:56 +03:00
Vesa Luusua
2b8bbfa7cf
Merge pull request #943 from sharetribe/v2.1.1
Update version to v2.1.1
2018-10-23 15:41:41 +03:00
Vesa Luusua
8c6306f9b7 Update version 2018-10-23 15:37:24 +03:00
Vesa Luusua
b420fb7bbe
Merge pull request #941 from sharetribe/routing-doc
Routing doc
2018-10-23 15:35:20 +03:00
Vesa Luusua
cdc9b692e3 Update changelog 2018-10-23 15:02:14 +03:00
Vesa Luusua
b2348b4c91 Documentation for routing and loading data 2018-10-23 14:58:02 +03:00
Antti Salmivaara
83a18b71af
Merge pull request #942 from sharetribe/remove-plain-text-parts-from-emails
Remove plain text parts from emails
2018-10-23 14:41:27 +03:00
Antti Salmivaara
b43dfc4cc4 Update CHANGELOG 2018-10-23 14:30:42 +03:00
Antti Salmivaara
8174efded1 Remove text only email information from README 2018-10-23 13:34:03 +03:00
Antti Salmivaara
3534ba0b6d Remove plain text email templates 2018-10-23 13:32:20 +03:00
Vesa Luusua
1aef211728
Merge pull request #940 from sharetribe/referrer-policy-updates
Referrer policy updates
2018-10-17 14:23:22 +03:00
Vesa Luusua
2456f24a4e Update changelog 2018-10-17 14:03:10 +03:00
Vesa Luusua
64b51a6bca EmailVerificationPage: add referrer policy due tokens in URL 2018-10-17 14:03:10 +03:00
Vesa Luusua
548adf7f33 PasswordResetPage: add referrer policy due tokens in URL 2018-10-17 14:03:09 +03:00
Vesa Luusua
826c0e5f4d Page: handle enforced referrer 2018-10-17 14:03:04 +03:00
Vesa Luusua
c7c1b918cd Allow canonicalURL helper to return path only 2018-10-17 14:02:57 +03:00
Vesa Luusua
c07b1a7f2c
Merge pull request #939 from sharetribe/redux-doc
Redux doc
2018-10-16 12:57:31 +03:00
Vesa Luusua
c76a44274b Update changelog 2018-10-16 12:52:17 +03:00
Vesa Luusua
10c974f7a0 Added doc about Redux setup 2018-10-16 12:52:13 +03:00
Vesa Luusua
3af960b444
Merge pull request #938 from sharetribe/add-comment-about-code-splitting
Add comment about code splitting
2018-10-08 17:09:42 +03:00
Vesa Luusua
f9ca17ad99 Update changelog 2018-10-08 17:09:01 +03:00
Vesa Luusua
f3b565bed5 Add a comment about the state of code-splitting 2018-10-08 16:28:21 +03:00
558 changed files with 39202 additions and 22571 deletions

5
.auditrc Normal file
View file

@ -0,0 +1,5 @@
exports.exceptions = [
// Add exceptions to audit script:
// // Severity: low, lodash (< 4.17.5), used heavily in our CRA fork
// "https://npmjs.com/advisories/577",
];

View file

@ -2,7 +2,7 @@ version: 2
jobs:
format:
docker:
- image: circleci/node:8.11
- image: circleci/node:10.14
steps:
- checkout
- restore_cache:
@ -25,7 +25,7 @@ jobs:
command: yarn run format-ci
test:
docker:
- image: circleci/node:8.11
- image: circleci/node:10.14
steps:
- checkout
- restore_cache:
@ -48,7 +48,7 @@ jobs:
command: yarn run test-ci
build:
docker:
- image: circleci/node:8.11
- image: circleci/node:10.14
steps:
- checkout
- restore_cache:
@ -71,7 +71,7 @@ jobs:
command: yarn run build
audit:
docker:
- image: circleci/node:8.11
- image: circleci/node:10.14
steps:
- checkout
- restore_cache:
@ -99,4 +99,3 @@ workflows:
- format
- test
- build
- audit

View file

@ -1,7 +1,9 @@
# Mandatory configuration
#
REACT_APP_SHARETRIBE_SDK_CLIENT_ID=
# Note: You also need to set Stripe secret key in Flex Console.
#
REACT_APP_SHARETRIBE_SDK_CLIENT_ID=change-me
REACT_APP_STRIPE_PUBLISHABLE_KEY=
REACT_APP_MAPBOX_ACCESS_TOKEN=
@ -11,7 +13,6 @@ REACT_APP_MAPBOX_ACCESS_TOKEN=
# Defaults
#
REACT_APP_SHARETRIBE_SDK_BASE_URL=https://flex-api.sharetribe.com
REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY=USD
REACT_APP_CANONICAL_ROOT_URL=http://localhost:3000
@ -26,8 +27,7 @@ REACT_APP_ENV=production
# REACT_APP_SHARETRIBE_USING_SSL=true
# SERVER_SHARETRIBE_TRUST_PROXY=true
# REACT_APP_PUBLIC_SENTRY_DSN=change-me
# SERVER_SENTRY_DSN=change-me
# REACT_APP_SENTRY_DSN=change-me
# REACT_APP_CSP=report
# BASIC_AUTH_USERNAME=sharetribe
# BASIC_AUTH_PASSWORD=secret

35
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,35 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug** A clear and concise description of what the bug is.
**To Reproduce** Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior** A clear and concise description of what you expected to happen.
**Screenshots** If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** Add any other context about the problem here.

10
.nsprc
View file

@ -1,10 +0,0 @@
{
"exceptions": [
"https://nodesecurity.io/advisories/532",
"https://nodesecurity.io/advisories/157",
"https://nodesecurity.io/advisories/577",
"https://nodesecurity.io/advisories/654",
"https://nodesecurity.io/advisories/664",
"https://nodesecurity.io/advisories/678"
]
}

View file

@ -2,4 +2,6 @@ build/
coverage/
node_modules/
public/
src/components/index.js
src/containers/index.js
src/forms/index.js

View file

@ -4,84 +4,742 @@ We are not following semantic versioning in this template app since any change c
a breaking change for forked customization projects. We are still experimenting with what is a good
way to update this template, but currently, we follow a pattern:
* Major version change (v**X**.0.0): Changes to several pages and other components. Consider
- Major version change (v**X**.0.0): Changes to several pages and other components. Consider
implementing this without merging upstream (we'll provide instructions).
* Minor version change (v0.**X**.0): New features and changes to a single page. These are likely to
- Minor version change (v0.**X**.0): New features and changes to a single page. These are likely to
cause conflicts.
* Patch (v0.0.**X**): Bug fixes and small changes to components.
- Patch (v0.0.**X**): Bug fixes and small changes to components.
---
## v2.1.0 2018-10-01
## Upcoming version 2019-XX-XX
* [change] Improve performance of public pages. Image assets are optimized and lazy loading is
## [v3.5.1] 2019-09-16
- [add] add orverriding function `onAdd` and `onRemove` for `CustomOverlayView` in
`SearchMapWithGoogleMap` to abide to React rules and do not `unmountComponentAtNode` when a
component is rendered by React and use `appendChild` on `onAdd` instead of `draw` to
[improve performance](https://github.com/tomchentw/react-google-maps/issues/817).
[#1200](https://github.com/sharetribe/flex-template-web/pull/1200)
- [fix] fix `CustomOverlayView` in `SearchMapWithGoogleMap` to work with new `react-intl` version,
overriding `render` method to render child object by using `createPortal` instead of
`unstable_renderSubtreeIntoContainer`.
[#1200](https://github.com/sharetribe/flex-template-web/pull/1200)
## [v3.5.0] 2019-08-29
- [change] Change the design of `BookingBreakdown` and add options to show only dates or booking
date and time there. [#1195](https://github.com/sharetribe/flex-template-web/pull/1195)
- [change] Move `BookingTimeInfo` to separate component from `InboxPage`. Add options to show only
booking dates or booking dates and times.
[#1194](https://github.com/sharetribe/flex-template-web/pull/1194)
- [add] Add new Spanish translations related to storing payment card.
[#1193](https://github.com/sharetribe/flex-template-web/pull/1193)
- [fix] Update yarn.lock (there was Lodash version resolution missing)
[#1190](https://github.com/sharetribe/flex-template-web/pull/1190)
[v3.5.0]: https://github.com/sharetribe/flex-template-web/compare/v3.4.0...v3.5.0
## [v3.4.0] 2019-08-29
- [change] Update `react-intl` to 3.1.13. More information about the changes can be found from
[Upgrade guide for react-intl@3.x](https://github.com/formatjs/react-intl/blob/master/docs/Upgrade-Guide.md)
- Proptype `intlShape` was removed so we needed to create it again. Because of this we added a new
`util/reactIntl.js` file. This file is now used to wrap all the react-intl related imports.
- `addLocaleDate` function was removed and react-intl library is now relying on native Intl APIs:
[Intl.PluralRules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules)
and
[Intl.RelativeTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RelativeTimeFormat).
In order to support older browsers we needed to add `intl-pluralrules` and
`intl-relativetimeformat` to `util/polyfills.js`
- Also Node must be now compiled with `full-icu` which caused changes to `start` and `test`
scripts in `package.json`. We also needed to add a specific config for `nodemon`
- Default `textComponent`in `IntlProvider` changed to `React.Fragment` so we need to explicitly
set `textComponent` to `span`. Otherwise all the snapshots would have changed and it might
affect to UI if there is styles added to these spans generally in customization projects.
Note: `FormattedMessage` component now supports
[`tagName` prop](https://github.com/formatjs/react-intl/blob/master/docs/Components.md#formattedmessage)
and
[improved rich-text formatting](https://github.com/formatjs/react-intl/blob/master/docs/Components.md#rich-text-formatting).
[#1181](https://github.com/sharetribe/flex-template-web/pull/1181)
- [change] Update helmet (v3.20.0 > v3.20.1).
[#1186](https://github.com/sharetribe/flex-template-web/pull/1186)
- [fix] Lodash vulnerability: enforce newer version for react-google-maps and react-dates
[#1188](https://github.com/sharetribe/flex-template-web/pull/1188)
- [change] Update `React`, `react-test-renderer` and `react-dom` to 16.9.0. After these updates old
lifecycle methods `componentWillMount`, `componentWillUpdate` and `componentWillUpdate` will cause
deprecation warnings. Check the updated components from the PR
[#1172](https://github.com/sharetribe/flex-template-web/pull/1172)
- [fix] ProfileSettingsForm: clear correct timeout.
[#1185](https://github.com/sharetribe/flex-template-web/pull/1185)
- [fix] `availabilityPlan` prop in `EditListingAvailabilityForm` was missing.
[#1183](https://github.com/sharetribe/flex-template-web/pull/1183)
- [fix] Bug fix: valueFromForm prop wasn't passed through different subcomponents.
[#1182](https://github.com/sharetribe/flex-template-web/pull/1182)
- [add] Update German and French translations.
[#1184](https://github.com/sharetribe/flex-template-web/pull/1184)
- [change] Migrate from `react-helmet` to `react-helmet-async`
[#1179](https://github.com/sharetribe/flex-template-web/pull/1179)
- [change] Use `sanitize.css` from own file instead of npm package because updating it accidentally
might break the UI. [#1177](https://github.com/sharetribe/flex-template-web/pull/1177)
- [fix] Change app.test.js after `react-redux` update
[#1178](https://github.com/sharetribe/flex-template-web/pull/1178)
- [change] Update `react-redux`: v5.1.1 -> v7.1.1
[#1176](https://github.com/sharetribe/flex-template-web/pull/1176)
- [change] Update `seedrandom` from v2.4.4 to v3.0.3
[#1175](https://github.com/sharetribe/flex-template-web/pull/1175)
- [change] Update `inquirer` from v6.5.0 to v7.0.0
[#1174](https://github.com/sharetribe/flex-template-web/pull/1174)
- [change] Update final-form, final-form-arrays, react-final-form and react-final-form-arrays. This
forced to make some code changes:
- Old recommendation of by-passing default field formatting or parsin isn't accepted anymore
- `format={null}` => use identity function instead: `format={v => v}`
- `parse={null}` => use identity function instead: `parse={v => v}`
- Final Form passes input props (name, value, onChange, onBlur, etc. ) grouped inside input key
- those props now include `type` attribute too.
- We had old form naming pattern with prop 'form', which now conflicted with updated Final Form
(The 'form' prop was used when Redux-Form was the form library)
[#1173](https://github.com/sharetribe/flex-template-web/pull/1173)
- [change] Update `react-dates` from v18.5.0 to v20.3.0
[#1171](https://github.com/sharetribe/flex-template-web/pull/1171)
- [change] Update Prettier to v1.18.2
[#1170](https://github.com/sharetribe/flex-template-web/pull/1170)
- [change] Update `path-to-regexp` to v3.0.0
[#1169](https://github.com/sharetribe/flex-template-web/pull/1169)
- [change] Update `sharetribe-scripts` to v3.1.1
[#1167](https://github.com/sharetribe/flex-template-web/pull/1167)
- [fix] Small change to remove card tect on `SavedCardDetails` modal.
[#1166](https://github.com/sharetribe/flex-template-web/pull/1166)
- [change] Update Sentry (@sentry/browser / @sentry/node) from v4.5.1 to v5.6.2
[#1164](https://github.com/sharetribe/flex-template-web/pull/1164)
- Update dependecies: all the easily updateable minor and batch updates: array.prototype.find,
babel-jest, core-js, enzyme (et al.), express, helmet, inquirer, lodash, nodemon, raf, redux,
source-map-support [#1163](https://github.com/sharetribe/flex-template-web/pull/1163)
[v3.4.0]: https://github.com/sharetribe/flex-template-web/compare/v3.3.0...v3.4.0
## [v3.3.0] 2019-08-22
- [add] Saving payment card after payment or without initial payment. This release contains quite a
lot changes to many files. This includes:
- UI changes to `CheckoutPage` for showing the saved payment method
- One more step to `handlePaymentIntent` flow on `CheckoutPage` if the user decides to save the
payment card
- Showing error notification on `TransactionPage` if saving the payment method has failed
- Use Flex SDK v1.5.0 which has new endpoints for creating Stripe Customer and using Stripe
SetupIntents
- Add `handleCardSetup` function to `stripe.duck.js`
- New shared duck file `paymentMethods.duck.js` for handling saving, deleting and replacing the
payment method
- New page `PaymentMethodsPage` in user's account settings
- `StripePaymenAddress` used in `StripePaymentForm` is now a separate component used also in new
`PaymentMethodsForm`
- New `LayoutWrapperAccountSettingsSideNav` component which is used in account settings pages:
`ContactDetailsPage`, `PasswordChangePage`, `PayoutPreferencesPage`, `PaymentMethodsPage`
[#1138](https://github.com/sharetribe/flex-template-web/pull/1138)
Read more from Flex docs:
[How saving payment card works in FTW](https://www.sharetribe.com/docs/background/save-payment-card/)
[v3.3.0]: https://github.com/sharetribe/flex-template-web/compare/v3.2.1...v3.3.0
## [v3.2.1] 2019-08-22
- [fix] On `ListingPage` align avatar with the left side of the content and fix content width so
that it aligns with the header image.
[#1155](https://github.com/sharetribe/flex-template-web/pull/1155)
- [fix] Rehydrate bug: existing DOM elements were populated incorrectly
[#1154](https://github.com/sharetribe/flex-template-web/pull/1154)
- [fix] Don't send personal id number or business profile to Stripe API when creating a Stripe
customer if they are not required in `stripe-config.js`. This happened e.g. if someone filled the
form after selecting the US and then before sending changed the country to Finland.
[#1151](https://github.com/sharetribe/flex-template-web/pull/1151)
- [add] Add new French and Spanish translations related to keyword search and Spanish translations
related to payment intents. [#1148](https://github.com/sharetribe/flex-template-web/pull/1148)
- [add] Add new French translations related to payment intents. Also few small changes to en.json
for consistency. [#1139](https://github.com/sharetribe/flex-template-web/pull/1139)
[v3.2.1]: https://github.com/sharetribe/flex-template-web/compare/v3.2.0...v3.2.1
## [v3.2.0] 2019-07-08
- [add] Keyword search/filter added to SearchPage component.
[#1129](https://github.com/sharetribe/flex-template-web/pull/1129)
- [fix] temporarily remove audit CI job.
[#1136](https://github.com/sharetribe/flex-template-web/pull/1136)
- [change] Update outdated dependencies. This includes updating lodash to fix the security issue.
[#1135](https://github.com/sharetribe/flex-template-web/pull/1135)
[v3.2.0]: https://github.com/sharetribe/flex-template-web/compare/v3.1.1...v3.2.0
## [v3.1.1] 2019-07-08
- [fix] Ensure on `TransactionPanel` that enquiry has a correct transition when a customer tries to
book the listing. This might happen with transaction process changes (e.g. when changing from
previous default to SCA process).
[#1131](https://github.com/sharetribe/flex-template-web/pull/1131)
[v3.1.1]: https://github.com/sharetribe/flex-template-web/compare/v3.1.0...v3.1.1
## [v3.1.0] 2019-07-05
- [fix] SectionHero: fix type in search params. There was an extra "/s?".
[#1124](https://github.com/sharetribe/flex-template-web/pull/1124)
- [add] Add support for Singapore as the payout country of a provider. Also fix a bug in passing the
personal ID number to Stripe. [#1122](https://github.com/sharetribe/flex-template-web/pull/1122)
- [add] Add events.mapbox.com to `connect-src` in `csp.js` file.
[#1123](https://github.com/sharetribe/flex-template-web/pull/1123)
- [change] Verify email automatically once the verification link is clicked. Redirect the user to
the landing page after verification.
[#1121](https://github.com/sharetribe/flex-template-web/pull/1121)
[v3.0.0]: https://github.com/sharetribe/flex-template-web/compare/v3.0.0...v3.1.0
## [v3.0.0] 2019-07-02
- [add] Strong Customer Authentication (SCA) with Stripe's new PaymentIntents flow. This is a big
change for checkout flow and includes a madatory transaction process change.
[#1089](https://github.com/sharetribe/flex-template-web/pull/1089)
- You should check [the pull request](https://github.com/sharetribe/flex-template-web/pull/1089)
- and read 3 Flex Docs articles:
[SCA](https://www.sharetribe.com/docs/background/strong-customer-authentication/),
[PaymentIntents](https://www.sharetribe.com/docs/background/payment-intents/), and
[How to take PaymentIntents into use](https://www.sharetribe.com/docs/guide/how-to-take-payment-intents-into-use/)
[v3.0.0]: https://github.com/sharetribe/flex-template-web/compare/v2.17.1...v3.0.0
## [v2.17.1] 2019-06-11
- [fix] `stripeCardToken` didn't update when the user tried to book the same listing for a second
time. This update will clear the old cardtoken from Redux store when redirecting to
`TransactionPage`. [#1114](https://github.com/sharetribe/flex-template-web/pull/1114)
- [fix] In `LineItemProviderCommissionMaybe.js` file check that `providerCommissionLineItem` exists.
In default transaction process the `providerCommissionLineItem` can be expected to be there but if
the process is using only customer commission there will be error.
[#1112](https://github.com/sharetribe/flex-template-web/pull/1112)
- [security] Update Flex SDK version to v1.4.1. The new version updates depencencies with security
issues [#1111](https://github.com/sharetribe/flex-template-web/pull/1111)
- [fix] Fix a bug in showing review links. Because of the bug the second review link was not visible
in `ActivityFeed`. [#1106](https://github.com/sharetribe/flex-template-web/pull/1106)
- [fix] Emptying the priceFilter component in the searchPage caused a page breaking error.
[#1101](https://github.com/sharetribe/flex-template-web/pull/1101)
[v2.17.1]: https://github.com/sharetribe/flex-template-web/compare/v2.17.0...v2.17.1
## [v2.17.0] 2019-05-23
- [change] Mapbox library dependencies updated to v1.0.0.
[#1099](https://github.com/sharetribe/flex-template-web/pull/1099)
- Note: Mapbox changed their pricing scheme!
- [fix] missing provider information (like SSN in US), might cause payment to fail on
`CheckoutPage`. This improves related error message.
[#1098](https://github.com/sharetribe/flex-template-web/pull/1098)
- [fix] Menu needs to wait for mounting to calculate dimensions properly.
[#1096](https://github.com/sharetribe/flex-template-web/pull/1096)
- [fix] Renamed Component.example.css files to ComponentExample.css to fix bug introduced in one of
the library updates. [#1095](https://github.com/sharetribe/flex-template-web/pull/1095)
- [add] `rawOnly` flag for Styleguide examples using fixed positioning or full-page dimensions.
[#1094](https://github.com/sharetribe/flex-template-web/pull/1094)
- [fix] Show error when typing credit card number if e.g. the number is invalid. Fixes bug that was
introduced in PR #1088. [#1092](https://github.com/sharetribe/flex-template-web/pull/1092)
- [change] Use Final Form on `StripePaymentForm` for consistency. Note that card form Stripe
Elements in `StripePaymentForm` is not a Final Form field so it's not available trough Final Form
but handled separately. [#1088](https://github.com/sharetribe/flex-template-web/pull/1088)
- [change] Move Stripe SDK call from `StripePaymentForm` to `stripe.duck.js` for consistency.
[#1086](https://github.com/sharetribe/flex-template-web/pull/1086)
[v2.17.0]: https://github.com/sharetribe/flex-template-web/compare/v2.16.0...v2.17.0
## [v2.16.0] 2019-05-08
This release makes 2 big updates to `sharetribe-scripts` package (which is our fork from Create
React App). It is updated from v1.1.5 ->
[2.1.8](https://github.com/sharetribe/create-react-app/blob/master/CHANGELOG-2.x.md#migrating-from-1x-to-203)
-> [3.0.0](https://github.com/sharetribe/create-react-app/blob/master/CHANGELOG.md). This brought up
a couple of changes:
- package.json has now a **"browserlist"** configuration key. This gives you an option to affect
browser support (it affects CSS Autoprefixer and JS build output).
[You might want to update it.](https://github.com/sharetribe/flex-template-web/pull/1073)
- IE support is removed from Create React App, but you can add polyfills yourself if needed.
- React was updated to a version that supports _Hooks_ and _Rules of React_ eslint plugin is
included.
- All the npm vulnerability report exceptions were removed from `.auditrc`
There was also a couple of bug fixes you should check carefully:
[#1082](https://github.com/sharetribe/flex-template-web/pull/1082),
[#1084](https://github.com/sharetribe/flex-template-web/pull/1084).
**Changes:**
- [fix] Previous change from `currentUser.attributes.stripeConnected` to separately included
`stripeAccount` caused errors since updates to currentUser entity didn't include `stripeAccount`.
Including it every time sounds quite error-prone, so we reversed that change.
[#1084](https://github.com/sharetribe/flex-template-web/pull/1084)
- [fix] Edit `updatedEntities` function in `util/data.js` so that it doesn't mutate the
`oldEntities` argument. [#1079](https://github.com/sharetribe/flex-template-web/pull/1079)
- [change] Update sharetribe-scripts (CRA fork) to v3.0.0. There are a couple of changes that you
should check from [#1081](https://github.com/sharetribe/flex-template-web/pull/1081)
- Reserve use\* function naming pattern for React Hooks.
- Recent SDK update changed the proptypes for snapshots.
- Updated scripts/config.js after Prettier version bump
- Removed unnecessary audit exceptions
- [fix] Ensure on `TransactionPage` that all the required data is loaded before showing the page.
[#1082](https://github.com/sharetribe/flex-template-web/pull/1082)
- [fix] Use proper method for Sentry on logout to avoid error message.
[#1080](https://github.com/sharetribe/flex-template-web/pull/1080),
- [change] Update sharetribe-scripts (CRA fork) to v2.1.8. There are a couple of changes that you
should check from [#1073](https://github.com/sharetribe/flex-template-web/pull/1073)
- package.json has now a "browserlist" configuration key. This gives you an option to affect
Autoprefixer configs (aka CSS vendor prefixes / browser support). You might want to update it.
- IE support is removed from Create React App, but you can add polyfills yourself if needed.
- Test snapshots were also changed a bit. (Update your own custom tests if needed.)
- Some CSS and React rules were more strict, you might need to make changes to your custom code.
- [fix] New npm vulnerability alerts checked and added to exception list.
[#1075](https://github.com/sharetribe/flex-template-web/pull/1075)
- [fix] ListingPage.duck: fix minor bug on dispatching the fetchReviewsRequest action
[#1074](https://github.com/sharetribe/flex-template-web/pull/1074)
[v2.16.0]: https://github.com/sharetribe/flex-template-web/compare/v2.15.0...v2.16.0
## [v2.15.0] 2019-04-24
- [add] Improve printing API errors on web inspector (console.table)
[#1071](https://github.com/sharetribe/flex-template-web/pull/1071)
- [fix] ManageAvailabilityCalendar.js didn't use UTC time when fetching data for calendar months.
[#1069](https://github.com/sharetribe/flex-template-web/pull/1069)
- [add] Use sparse fields on InboxPage query to reduce data load.
[#1067](https://github.com/sharetribe/flex-template-web/pull/1067)
- NOTE: if you need more fields on `InboxPage`, you need to add those to `loadData` function.
- [add] Use sparse fields on SearchPage to reduce data load.
[#1066](https://github.com/sharetribe/flex-template-web/pull/1066)
- NOTE: if you need more fields on `ListingCard` than title, price and geolocation - you need to
add those to `loadData` function.
[v2.15.0]: https://github.com/sharetribe/flex-template-web/compare/v2.14.0...v2.15.0
## [v2.14.0] 2019-04-05
- [add] German translations for recent PayoutDetailsForm changes.
[#1064](https://github.com/sharetribe/flex-template-web/pull/1064)
- [add] Added NZD and HKD subunit divisors and refactored currency configuration.
[#1063](https://github.com/sharetribe/flex-template-web/pull/1063)
- [add] Add support for arbitrary line items.
[#1062](https://github.com/sharetribe/flex-template-web/pull/1062)
- [fix] US individual accounts had a non-editable business url in PayoutDetailsForm. It was probably
OK, but there wasn't any reason to for it.
[#1061](https://github.com/sharetribe/flex-template-web/pull/1061)
[v2.14.0]: https://github.com/sharetribe/flex-template-web/compare/v2.13.1...v2.14.0
## [v2.13.1] 2019-03-29
- [add] a comment about category and amenities filters. They don't work out-of-the-box, extended
data needs a schema before it can work as a search filter.
[#1055](https://github.com/sharetribe/flex-template-web/pull/1055)
- [fix] EditListingWizard: currentUser was null when the EditListingPage got reloaded causing
TypeError. [#1056](https://github.com/sharetribe/flex-template-web/pull/1056)
[v2.13.1]: https://github.com/sharetribe/flex-template-web/compare/v2.13.0...v2.13.1
## [v2.13.0] 2019-03-28
- [add] Add translations for recent Stripe API related changes. (German will be included later.)
[#1052](https://github.com/sharetribe/flex-template-web/pull/1052)
- [fix] JPY currency was configured wrongly: it doesn't use subunits.
[#1051](https://github.com/sharetribe/flex-template-web/pull/1051)
- [add] Complete rewrite to `PayoutDetailsForm` due to breaking changes in Stripe API.
[#1049](https://github.com/sharetribe/flex-template-web/pull/1049)
- You should track all your customizations to `PayoutDetailsForm` and related changes in
`user.duck.js` and elsewhere before merging this upstream-update.
- You should update Stripe API to "2019-02-19" or later
- [add] Booking: use attributes `displayStart` and `displayEnd`, instead of reading booking period
directly from `start` and `end` attributes.
[#1050](https://github.com/sharetribe/flex-template-web/pull/1050)
- [fix] A listing title that contained only stripped-off characters caused bugs in slug / pathName
generation. [#1048](https://github.com/sharetribe/flex-template-web/pull/1048)
- [change] Removed Node-engine setup from package.json. Fixed version was causing problems for quite
many in their first FTW installation. Note: when troubleshooting your Heroku installation, you
might want to reintroduce engine setup.
[#1043](https://github.com/sharetribe/flex-template-web/pull/1043)
- [fix] Add error handling to `PayoutDetailsForm` and `StripePaymentForm` in case Stripe publishable
key is not configured yet. [#1042](https://github.com/sharetribe/flex-template-web/pull/1042)
- [fix] FieldBirthdayInput: placeholder text was not selected by default.
[#1039](https://github.com/sharetribe/flex-template-web/pull/1039)
[v2.13.0]: https://github.com/sharetribe/flex-template-web/compare/v2.12.1...v2.13.0
## [v2.12.0] 2019-02-28
- [fix] Fix to PR [#1035](https://github.com/sharetribe/flex-template-web/pull/1035). In
`user.duck.js` send correct params depending on Stripe API in use.
[#1037](https://github.com/sharetribe/flex-template-web/pull/1037)
- [change] Update creating Stripe account token to support the latest Stripe API update. See also
[Stripe API changelog](https://stripe.com/docs/upgrades#api-changelog). **IMPORTANT:** If you are
using a Stripe account created earlier than 19th of February 2019 you need to change the value of
`useDeprecatedLegalEntityWithStripe` in `stripe-config.js`. You can check the Stripe API version
you are using from Stripe Dashboard -> Developers. Since the change in Stripe API was quite big we
are not able to support company accounts with new Stripe API yet! The option for company accounts
will be hidden if the value `useDeprecatedLegalEntityWithStripe` is set to `false`.
[#1035](https://github.com/sharetribe/flex-template-web/pull/1035)
- [change] Improve German translations.
[#1034](https://github.com/sharetribe/flex-template-web/pull/1034)
- [change] Reordered import/exports on src/components/index.js. This helps to mitigate possible
circular dependency problems and strange bugs in CSS bundle. In addition, derivative buttons were
refactored to work with `rootClassName` prop (PrimaryButton, SecondaryButton and
InlineTextButton). [#1024](https://github.com/sharetribe/flex-template-web/pull/1024)
[v2.12.0]: https://github.com/sharetribe/flex-template-web/compare/v2.11.1...v2.12.0
## [v2.11.1] 2019-02-21
- [add] New translations for French and Spanish (fr.json & es.json)
[#1028](https://github.com/sharetribe/flex-template-web/pull/1028)
- [add] New translation file German (de.json). This also adds hyphenation to some of the titles.
[#1027](https://github.com/sharetribe/flex-template-web/pull/1027)
[v2.11.0]: https://github.com/sharetribe/flex-template-web/compare/v2.11.0...v2.11.1
## [v2.11.0] 2019-02-20
- [fix] SelectMultipleFilter had a bug on mobile layout - `onSubmit` didn't get called. This fixes
also two other issues with SelectMultipleFilter: hovering on ListingCard removed dirty values on
repaint and there was an outline flashing on FilterForm when clicking checkboxes.
[#1025](https://github.com/sharetribe/flex-template-web/pull/1025)
- [fix] Small changes in CSS files in order to match content width with the footer in pages where
the footer is visible. Also, make side layout (used e.g. in `TermsOfServicePage`, `InboxPage`,
`ContactDetailsPage`) align width footer better. Check responsive layouts carefulle after taking
update from upstream. [#1090](https://github.com/sharetribe/flex-template-web/pull/1019)
- [add] This adds an example how user-generated content could be sanitized. If you have extended
data you should consider if sanitization is needed for that.
[#1023](https://github.com/sharetribe/flex-template-web/pull/1023)
- [change] A new component `UserDisplayName` is added for showing user display name and also
handling the cases where a user is banned or deleted. When the user name must be a string instead
of a component (e.g. in `Avatar` and in `ListingPage`) you can use a new function
`userDisplayNameAsString`. Together these will replace the old `userDisplayName` function which is
now deprecated. Also some small bug fixes to showing banned user. There is quite a lot of file
changes caused by updating test files.
[#1022](https://github.com/sharetribe/flex-template-web/pull/1022)
- [change] Remove error handling for unverified email from PasswordRecoveryPage and translations
related to that. [#1021](https://github.com/sharetribe/flex-template-web/pull/1021)
[v2.11.0]: https://github.com/sharetribe/flex-template-web/compare/v2.10.0...v2.11.0
## [v2.10.0] 2019-01-31
- [add] Add audit script and include it as a CI job. We had security audit job previously on top of
node security platform (nsp), but that service was closed on December 2018.
[#1020](https://github.com/sharetribe/flex-template-web/pull/1020)
- [change] Extracted and refactored utility functions related to transaction and refactored several
components that show transaction data (incl. InboxPage, TransactionPanel, ActivityFeed). Before
updating your customization project, you should read more about what has changed from the pull
request. [#1004](https://github.com/sharetribe/flex-template-web/pull/1004)
- [change] Rest of the documentation moved to Flex Docs: https://www.sharetribe.com/docs/
[#1015](https://github.com/sharetribe/flex-template-web/pull/1015)
[v2.10.0]: https://github.com/sharetribe/flex-template-web/compare/v2.9.0...v2.10.0
## [v2.9.0] 2019-01-29
- [fix] day boundaries for date filter and pass booking state to bookings.query
- SearchPage.duck.js: endDate should not be expanded for night bookings
- DateRangeController: bookingUnitType: day should allow 0 night
- EditListingPage.duck.js booking state should be passed to query
[#1016](https://github.com/sharetribe/flex-template-web/pull/1016)
- [add] Date filter added and filter components (single and multiselect) are refactored to use
shared subcomponents. [#949](https://github.com/sharetribe/flex-template-web/pull/949)
- [fix] Fixed copy-text in ReviewForm: Rating is required.
[#1011](https://github.com/sharetribe/flex-template-web/pull/1011)
- [change] Some of the documentation moved to Flex Docs: https://www.sharetribe.com/docs/
[#1012](https://github.com/sharetribe/flex-template-web/pull/1012) and
[#1014](https://github.com/sharetribe/flex-template-web/pull/1014)
- [fix] Allow ownListing as listing proptype in BookingPanel component.
[#1007](https://github.com/sharetribe/flex-template-web/pull/1007)
- [add] Add info text about additional owners to `PayoutDetailsForm`.
[#1006](https://github.com/sharetribe/flex-template-web/pull/1006)
- [change] Default to English translation if the translation key is missing. After this update, new
translation keys will not be added to other translation files with English default texts. We keep
providing translations in our supported languages but they might not be up to date all the time.
This means if you want to update your translations beforehand or use your own translations file,
you can use
[translation CLI](https://github.com/sharetribe/flex-template-web/blob/master/docs/translations.md#managing-translations)
to check if there are translations missing.
[#1005](https://github.com/sharetribe/flex-template-web/pull/1005)
- [change] Remove `origin` parameter from `default-location-searches.js`
[#1003](https://github.com/sharetribe/flex-template-web/pull/1003)
- [add] Limit location autocomplete by adding an optional country parameter to geocoding call in
both Mapbox and Google Maps integrations. Also updated Mapbox SDK to version 0.5.0.
[#1002](https://github.com/sharetribe/flex-template-web/pull/1002)
[v2.9.0]: https://github.com/sharetribe/flex-template-web/compare/v2.8.0...v2.9.0
## [v2.8.0] 2019-01-17
- [add] Add CLI tool for creating .env file and setting up the environment variables.
[#994](https://github.com/sharetribe/flex-template-web/pull/994)
- [change] Change from Raven to Sentry SDKs for browser and Node.js to version 4.5.1. With the new
SDKs only one DSN needs to be configured so update also environment variables and documentation
related to Sentry. [#999](https://github.com/sharetribe/flex-template-web/pull/999)
- [fix] Use environment variable `REACT_APP_AVAILABILITY_ENABLED` to enable or disable availability
calendar. In the config.js file variable fetchAvailableTimeSlots is now renamed to more general
enableAvailability because it affects both fetching availability data and enabling the
availability calendar. [#1000](https://github.com/sharetribe/flex-template-web/pull/1000)
- [fix] UI was broken for banned user after transaction enquiry changes.
[#996](https://github.com/sharetribe/flex-template-web/pull/996)
[v2.8.0]: https://github.com/sharetribe/flex-template-web/compare/v2.7.1...v2.8.0
## [v2.7.1] 2019-01-09
- [add] Separate date ranges when fetching availability exceptions and bookings on availability
calendar. After this change, providers can block dates 365 days in advance instead of just 180
days. [#997](https://github.com/sharetribe/flex-template-web/pull/997)
- [fix] Fixed a small typo. [#995](https://github.com/sharetribe/flex-template-web/pull/995)
[v2.7.1]: https://github.com/sharetribe/flex-template-web/compare/v2.7.0...v2.7.1
## [v2.7.0] 2019-01-08
- [add] Add Spanish translations file: es.json and update docs/translations.md
[#992](https://github.com/sharetribe/flex-template-web/pull/992)
- [add] Add French translations to new translations keys. Few minor updates to English translations
for consistency. [#991](https://github.com/sharetribe/flex-template-web/pull/991)
- [add] Support for Stripe company accounts. `PayoutDetailsForm` was separated into smaller
subcomponents. Multiple new translation keys were added and they might not be translated into
French yet. [#980](https://github.com/sharetribe/flex-template-web/pull/980)
- Manage availability of listings. This works for listings that have booking unit type:
'line-item/night', or 'line-item/day'. There's also 'manage availability' link in the
ManageListingCards of "your listings" page.
[#972](https://github.com/sharetribe/flex-template-web/pull/972)
[v2.7.0]: https://github.com/sharetribe/flex-template-web/compare/v2.6.0...v2.7.0
## [v2.6.0] 2019-01-02
- [fix] Wrong translations for perUnit in fr.json.
[#989](https://github.com/sharetribe/flex-template-web/pull/989)
- [change] Layout changes to BookingPanel on listing and transaction pages.
[#988](https://github.com/sharetribe/flex-template-web/pull/988)
- [fix] Fix wrong booking title on listing page that has been introduced in #969.
[#987](https://github.com/sharetribe/flex-template-web/pull/987)
- [fix] yarn.lock file was not up to date
[#986](https://github.com/sharetribe/flex-template-web/pull/986)
- [add] Add an image of fork button to the deploy to production guide.
[#985](https://github.com/sharetribe/flex-template-web/pull/985)
- [remove] Remove the default built-in email templates. Built-in email templates can be edited in
Console. [#983](https://github.com/sharetribe/flex-template-web/pull/983)
- [add] Enable booking a listing straight from an enquiry
[#976](https://github.com/sharetribe/flex-template-web/pull/976)
- [change] Extract SectionBooking to a distinct component from ListingPage.
[#969](https://github.com/sharetribe/flex-template-web/pull/969)
[v2.6.0]: https://github.com/sharetribe/flex-template-web/compare/v2.5.0...v2.6.0
## [v2.5.0] 2018-12-17
- [add] Add French translations to recently added translation keys. Also few minor changes to
English translations for consistency.
[#981](https://github.com/sharetribe/flex-template-web/pull/981)
- [add] Create FieldRadioButton component.
[#977](https://github.com/sharetribe/flex-template-web/pull/977)
- [fix] Temporarily remove audit step from CI because of the Node Security Platform shutting down.
[#979](https://github.com/sharetribe/flex-template-web/pull/979)
- [add] Add Stripe support for new countries: Canada, New Zealand, Switzerland, Norway, and Hong
Kong. Also add more required fields for US and Australia.
- StripeBankAccountTokenInputField component and PayoutDetailsForm have some changes
- Stripe related configuration is separated to new stripe-config.js file.
- Multiple new translation keys were added and they might not be translated into French yet. If
you use French translation check PR for the changed keys.
[#968](https://github.com/sharetribe/flex-template-web/pull/968)
- [change] Remove generic perUnit translations and replace them with specific night, day and unit
translations depending on booking unit chosen in config.
[#970](https://github.com/sharetribe/flex-template-web/pull/970)
- [fix] Formatting docs with newest Prettier - related commit was lost in #967 at some point.
[#975](https://github.com/sharetribe/flex-template-web/pull/975)
- [change] Improved documents related to onboarding: env.md, deploying-to-production.md,
map-providers.md [#971](https://github.com/sharetribe/flex-template-web/pull/971)
- [change] Update outdated dependencies.
[#967](https://github.com/sharetribe/flex-template-web/pull/967)
- **Note:** Updating Prettier caused multiple file changes mostly to `.md` files and `compose`
setup.
- [change] Update supported Node version to the latest LTS (10.14).
[#964](https://github.com/sharetribe/flex-template-web/pull/964)
- [add] Add documentation about deploying to production. Also add _deploy to Heroku_ button.
[#961](https://github.com/sharetribe/flex-template-web/pull/961)
[v2.5.0]: https://github.com/sharetribe/flex-template-web/compare/v2.4.1...v2.5.0
## [v2.4.1] 2018-11-29
- [fix] Add missing French translation.
[#966](https://github.com/sharetribe/flex-template-web/pull/966)
[v2.4.1]: https://github.com/sharetribe/flex-template-web/compare/v2.4.0...v2.4.1
## [v2.4.0] 2018-11-28
- [change] Update Flex JS SDK to 1.2.
[#963](https://github.com/sharetribe/flex-template-web/pull/963)
- [add] Add French as a default language in addition to English.
[#962](https://github.com/sharetribe/flex-template-web/pull/962)
- [fix] Show Stripe error message on CheckoutPage if payment request fails because of Stripe error.
Also show error if payment amount is zero.
[#960](https://github.com/sharetribe/flex-template-web/pull/960)
- [fix] Remove unused translation keys and update PasswordChangePage title
[#959](https://github.com/sharetribe/flex-template-web/pull/959)
- [add] Add translations CLI tool [#955](https://github.com/sharetribe/flex-template-web/pull/955)
[v2.4.0]: https://github.com/sharetribe/flex-template-web/compare/v2.3.2...v2.4.0
## [v2.3.2] 2018-11-20
- [fix] Take 2: don't set currentUserHasListings if fetched listing is in draft state.
[#956](https://github.com/sharetribe/flex-template-web/pull/956)
- [fix] PriceFilter styles [#954](https://github.com/sharetribe/flex-template-web/pull/954)
[v2.3.2]: https://github.com/sharetribe/flex-template-web/compare/v2.3.1...v2.3.2
## [v2.3.1] 2018-11-16
- [fix] Don't set currentUserHasListings if fetched listing is in draft state.
ModalMissingInformation was shown too early for users creating their first listing.
[#953](https://github.com/sharetribe/flex-template-web/pull/953)
- [change] Add index files of components and containers folder to .prettierignore
[#952](https://github.com/sharetribe/flex-template-web/pull/952)
- [fix] the alignment of arrows in FieldDateRangeInput and refactoring arrow icon code.
[#951](https://github.com/sharetribe/flex-template-web/pull/951)
- [change] Remove unnecessary language configuration and improve translations documentation.
[#950](https://github.com/sharetribe/flex-template-web/pull/950)
[v2.3.1]: https://github.com/sharetribe/flex-template-web/compare/v2.3.0...v2.3.1
## [v2.3.0] 2018-11-13
- [add] Draft listing is used in EditListingWizard, ManageListingCard and ListingPage. From now on
description panel creates a draft listing and photos panel publishes it. You can also view your
current draft listings from 'your listings' page.
[#947](https://github.com/sharetribe/flex-template-web/pull/947)
- [fix] Firefox showed select options with the same color as select itself. Now options have their
own color set and _placeholder option needs to be disabled_.
[#946](https://github.com/sharetribe/flex-template-web/pull/946)
[v2.3.0]: https://github.com/sharetribe/flex-template-web/compare/v2.2.0...v2.3.0
## [v2.2.0] 2018-10-31
- [add] SearchPage: adds PriceFilter (and RangeSlider, FieldRangeSlider, PriceFilterForm).
**Note:** You must define min and max for the filter in `src/marketplace-custom-config.js`.
Current maximum value for the range is set to 1000 (USD/EUR/currency units). In addition, this
fixes or removes component examples that don't work in StyleguidePage.
[#944](https://github.com/sharetribe/flex-template-web/pull/944)
[v2.2.0]: https://github.com/sharetribe/flex-template-web/compare/v2.1.1...v2.2.0
## [v2.1.1] 2018-10-23
- [add] Added initial documentation about routing and loading data.
[#941](https://github.com/sharetribe/flex-template-web/pull/941)
- [remove] Removed plain text parts of email templates.
[#942](https://github.com/sharetribe/flex-template-web/pull/942)
- [add] Add referrer policy due tokens in URL on PasswordResetPage and EmailVerificationPage.
[#940](https://github.com/sharetribe/flex-template-web/pull/940)
- [add] Added initial documentation about our Redux setup.
[#939](https://github.com/sharetribe/flex-template-web/pull/939)
- [add] Added a small comment to documentation about the current state of code-splitting.
[#938](https://github.com/sharetribe/flex-template-web/pull/938)
[v2.1.1]: https://github.com/sharetribe/flex-template-web/compare/v2.1.0...v2.1.1
## [v2.1.0] 2018-10-01
- [change] Improve performance of public pages. Image assets are optimized and lazy loading is
applied to images in SectionLocation and ListingCard. Read
[documentation](./docs/improving-performance.md) for implementation details.
[#936](https://github.com/sharetribe/flex-template-web/pull/936)
* [change] Update sharetribe-scripts. **cssnext** (used previously in sharetribe-scripts) has been
- [change] Update sharetribe-scripts. **cssnext** (used previously in sharetribe-scripts) has been
deprecated. Now **postcss-preset-env** is used instead with stage 3 + custom media queries and
nesting-rules. If this change breaks your styling, you could still use v1.1.2. The next version of
[postcss-nesting](https://github.com/jonathantneal/postcss-nesting) (v7.0.0) will no longer
support nested at-rules (like media queries) - therefore, we didn't update to that version yet.
[#935](https://github.com/sharetribe/flex-template-web/pull/935)
* [change] Change Mapbox's default font to marketplace font.
- [change] Change Mapbox's default font to marketplace font.
[#934](https://github.com/sharetribe/flex-template-web/pull/934)
* [add] New default design for the landing page's hero section. Now the CTA button's default
- [add] New default design for the landing page's hero section. Now the CTA button's default
behavior is 'Browse'.
* `marketplaceH1FontStyles`: changed letter spacing to be more tight.
* `SectionHero` has now a search page link that should be customized to point to your marketplace
- `marketplaceH1FontStyles`: changed letter spacing to be more tight.
- `SectionHero` has now a search page link that should be customized to point to your marketplace
primary area [#933](https://github.com/sharetribe/flex-template-web/pull/933)
## v2.0.0 2018-09-19
[v2.1.0]: https://github.com/sharetribe/flex-template-web/compare/v2.0.0...v2.1.0
* [add] New default map provider (Mapbox) and complete refactoring to all map and geocoding
## [v2.0.0] 2018-09-19
- [add] New default map provider (Mapbox) and complete refactoring to all map and geocoding
components. [#888](https://github.com/sharetribe/flex-template-web/pull/888)
**Note:** Before updating to version 2.0.0, you should very carefully track customizations that
you have made to following components:
* **LocationAutocompleteInput**
* **Map**
* **SearchPage** (especially previous `onIdle` function)
* **SearchMap**
* **SearchMapPriceLabel**
* **SearchMapGroupLabel**
* **SearchMapInfoCard**
- **LocationAutocompleteInput**
- **Map**
- **SearchPage** (especially previous `onIdle` function)
- **SearchMap**
- **SearchMapPriceLabel**
- **SearchMapGroupLabel**
- **SearchMapInfoCard**
To get a better understanding of what has changed, you should read documents about how to
[integrate to map providers](./docs/map-providers.md) and especially
[changing map provider to Google Maps](./docs/google-maps.md)
## v1.4.3 2018-09-15
[v2.0.0]: https://github.com/sharetribe/flex-template-web/compare/v1.4.3...v2.0.0
* [fix] fuzzy location didn't change when listing location changed.
## [v1.4.3] 2018-09-15
- [fix] fuzzy location didn't change when listing location changed.
[#931](https://github.com/sharetribe/flex-template-web/pull/931)
* [fix] obfuscatedCoordinatesImpl didn't always return coordinates within given offset radius.
- [fix] obfuscatedCoordinatesImpl didn't always return coordinates within given offset radius.
[#930](https://github.com/sharetribe/flex-template-web/pull/930)
* [fix] LocationAutocompleteInput: blur input when selecting by enter to prevent flash of default
- [fix] LocationAutocompleteInput: blur input when selecting by enter to prevent flash of default
predictions. [#928](https://github.com/sharetribe/flex-template-web/pull/928)
* [fix] LocationAutocompleteInput: selecting with enter key prevented while fetching predictions.
- [fix] LocationAutocompleteInput: selecting with enter key prevented while fetching predictions.
[#923](https://github.com/sharetribe/flex-template-web/pull/923)
## v1.4.2 2018-09-06
[v1.4.3]: https://github.com/sharetribe/flex-template-web/compare/v1.4.2...v1.4.3
* [add] Reduce character queries on LocationAutocompleteInput to reduce geocoding costs.
## [v1.4.2] 2018-09-06
- [add] Reduce character queries on LocationAutocompleteInput to reduce geocoding costs.
[#883](https://github.com/sharetribe/flex-template-web/pull/883)
* [change] Update git links and improve documentation
- [change] Update git links and improve documentation
[#911](https://github.com/sharetribe/flex-template-web/pull/911)
* [change] improve env-template to better defaults.
- [change] improve env-template to better defaults.
[#912](https://github.com/sharetribe/flex-template-web/pull/912)
* [fix] Touch event from location autocomplete prediction list ended up causing clicks.
- [fix] Touch event from location autocomplete prediction list ended up causing clicks.
[#917](https://github.com/sharetribe/flex-template-web/pull/917)
* [change] Disable default predictions in listing wizard
- [change] Disable default predictions in listing wizard
[#906](https://github.com/sharetribe/flex-template-web/pull/906)
## v1.4.1 2018-08-21
[v1.4.2]: https://github.com/sharetribe/flex-template-web/compare/v1.4.1...v1.4.2
* [fix] Fix window resize redirecting to search page with reusable map component
## [v1.4.1] 2018-08-21
- [fix] Fix window resize redirecting to search page with reusable map component
[#905](https://github.com/sharetribe/flex-template-web/pull/905)
* [change] Maps configuration has been restructured. The new configuration is agnostic of the maps
- [change] Maps configuration has been restructured. The new configuration is agnostic of the maps
provider in use and works with both Google Maps as well as Mapbox.
The fuzzy location circle has less configuration, but otherwise all the previous settings can be
@ -93,130 +751,154 @@ way to update this template, but currently, we follow a pattern:
[#900](https://github.com/sharetribe/flex-template-web/pull/900)
## v1.4.0 2018-08-17
[v1.4.1]: https://github.com/sharetribe/flex-template-web/compare/v1.4.0...v1.4.1
* [change] Put availability calendar behind a feature flag
## [v1.4.0] 2018-08-17
- [change] Put availability calendar behind a feature flag
[#902](https://github.com/sharetribe/flex-template-web/pull/902)
* [fix] Drop date time from time slots request query params
- [fix] Drop date time from time slots request query params
[#901](https://github.com/sharetribe/flex-template-web/pull/901)
* [fix] Make a second time slots request when required
- [fix] Make a second time slots request when required
[#901](https://github.com/sharetribe/flex-template-web/pull/901)
* [add] Map component (used in ListingPage) using Mapbox instead of Google Maps
- [add] Map component (used in ListingPage) using Mapbox instead of Google Maps
[#896](https://github.com/sharetribe/flex-template-web/pull/896)
* [add] Listing availability [#868](https://github.com/sharetribe/flex-template-web/pull/868),
- [add] Listing availability [#868](https://github.com/sharetribe/flex-template-web/pull/868),
[#873](https://github.com/sharetribe/flex-template-web/pull/873),
[#891](https://github.com/sharetribe/flex-template-web/pull/891) &
[#892](https://github.com/sharetribe/flex-template-web/pull/892)
* [add] Add support for user's current location as a default suggestion in the location autocomplete
- [add] Add support for user's current location as a default suggestion in the location autocomplete
search. [#895](https://github.com/sharetribe/flex-template-web/pull/895)
* [add] Add support for default locations in the LocationAutocompleteInput component. Common
- [add] Add support for default locations in the LocationAutocompleteInput component. Common
searches can be configured to show when the input has focus. This reduces typing and Google Places
geolocation API usage. The defaults can be configured in
`src/components/LocationAutocompleteInput/GeocoderGoogleMaps.js`.
[#894](https://github.com/sharetribe/flex-template-web/pull/894)
* [change] Removed the `country` parameter from the search page as it was not used anywhere.
- [change] Removed the `country` parameter from the search page as it was not used anywhere.
[#893](https://github.com/sharetribe/flex-template-web/pull/893)
## v1.3.2 2018-08-07
[v1.4.0]: https://github.com/sharetribe/flex-template-web/compare/v1.3.2...v1.4.0
* [change] Update the Sharetribe Flex SDK to the 1.0.0 version in NPM. All the `sharetribe-sdk`
## [v1.3.2] 2018-08-07
- [change] Update the Sharetribe Flex SDK to the 1.0.0 version in NPM. All the `sharetribe-sdk`
imports are now using the new package name `sharetribe-flex-sdk`.
[#884](https://github.com/sharetribe/flex-template-web/pull/884)
* [change] Reusable SearchMap. Fixed the original reverted version. (Includes audit exception 678)
- [change] Reusable SearchMap. Fixed the original reverted version. (Includes audit exception 678)
[#882](https://github.com/sharetribe/flex-template-web/pull/882)
## v1.3.1
[v1.3.2]: https://github.com/sharetribe/flex-template-web/compare/v1.3.1...v1.3.2
* [fix] Hotfix: reverting the usage of ReusableMapContainer due to production build error.
## [v1.3.1]
- [fix] Hotfix: reverting the usage of ReusableMapContainer due to production build error.
[#881](https://github.com/sharetribe/flex-template-web/pull/881)
## v1.3.0
[v1.3.1]: https://github.com/sharetribe/flex-template-web/compare/v1.3.0...v1.3.1
* [change] Reusable SearchMap. [#877](https://github.com/sharetribe/flex-template-web/pull/877)
* [fix] Fix a search filters panel bug where selecting an option in a multi select filter ends up
## [v1.3.0]
- [change] Reusable SearchMap. [#877](https://github.com/sharetribe/flex-template-web/pull/877)
- [fix] Fix a search filters panel bug where selecting an option in a multi select filter ends up
invoking a mobile filter callback function.
[#876](https://github.com/sharetribe/flex-template-web/pull/876)
* [change] Use seeded random for client side coordinate obfuscation
- [change] Use seeded random for client side coordinate obfuscation
[#874](https://github.com/sharetribe/flex-template-web/pull/874)
## v1.2.2
[v1.3.0]: https://github.com/sharetribe/flex-template-web/compare/v1.2.2...v1.3.0
* [change] Change static map to dynamic map when clicked.
## [v1.2.2]
- [change] Change static map to dynamic map when clicked.
[#871](https://github.com/sharetribe/flex-template-web/pull/871)
## v1.2.1
[v1.2.2]: https://github.com/sharetribe/flex-template-web/compare/v1.2.1...v1.2.2
* [fix] Lazy load map only if the map is near current viewport.
## [v1.2.1]
- [fix] Lazy load map only if the map is near current viewport.
[#871](https://github.com/sharetribe/flex-template-web/pull/871)
## v1.2.0
[v1.2.1]: https://github.com/sharetribe/flex-template-web/compare/v1.2.0...v1.2.1
* [change] Use Google's static map on ListingPage. This is a reaction to pricing change of Google
## [v1.2.0]
- [change] Use Google's static map on ListingPage. This is a reaction to pricing change of Google
Maps APIs. [#869](https://github.com/sharetribe/flex-template-web/pull/869)
* [change] Use sessionTokens and fields for Autocomplete calls to Google Maps. This is a reaction to
- [change] Use sessionTokens and fields for Autocomplete calls to Google Maps. This is a reaction to
pricing change of Google Maps APIs.
[#867](https://github.com/sharetribe/flex-template-web/pull/867)
* [change] Change TransactionPage state management in loadData.
- [change] Change TransactionPage state management in loadData.
[#863](https://github.com/sharetribe/flex-template-web/pull/863),
[#865](https://github.com/sharetribe/flex-template-web/pull/865) &
[#866](https://github.com/sharetribe/flex-template-web/pull/866)
* [fix] Fix submit button state on contact details page.
- [fix] Fix submit button state on contact details page.
[#864](https://github.com/sharetribe/flex-template-web/pull/864)
* [fix] Fix listing page host section layout bug.
- [fix] Fix listing page host section layout bug.
[#862](https://github.com/sharetribe/flex-template-web/pull/862)
* [fix] Fix initial message input clearing too early in checkout page.
- [fix] Fix initial message input clearing too early in checkout page.
[#861](https://github.com/sharetribe/flex-template-web/pull/861)
* [fix] Fix setting Topbar search input initial value.
* [change] Update Redux to v4 [#859](https://github.com/sharetribe/flex-template-web/pull/859)
* [fix] Fix setting Topbar search input initial value
- [fix] Fix setting Topbar search input initial value.
- [change] Update Redux to v4 [#859](https://github.com/sharetribe/flex-template-web/pull/859)
- [fix] Fix setting Topbar search input initial value
[#857](https://github.com/sharetribe/flex-template-web/pull/857)
## v1.1.0
[v1.2.0]: https://github.com/sharetribe/flex-template-web/compare/v1.1.0...v1.2.0
* [fix] Improve slug creation (slashes were breaking rendering in some environments)
## [v1.1.0]
- [fix] Improve slug creation (slashes were breaking rendering in some environments)
[#850](https://github.com/sharetribe/flex-template-web/pull/850)
* [fix] Anonymous user should see contact link on UserCard
- [fix] Anonymous user should see contact link on UserCard
[#851](https://github.com/sharetribe/flex-template-web/pull/851)
* [fix] Persisting booking request details across authentication
- [fix] Persisting booking request details across authentication
[#852](https://github.com/sharetribe/flex-template-web/pull/852)
* [change] Footer styles changed to more generic (no disappearing columns etc.) If you have made
- [change] Footer styles changed to more generic (no disappearing columns etc.) If you have made
changes to Footer, consider extracting it to different component before update.
[#853](https://github.com/sharetribe/flex-template-web/pull/853)
* [change] Logo customization refactored to be easier. Check CheckoutPage, TopbarDesktop and Footer
- [change] Logo customization refactored to be easier. Check CheckoutPage, TopbarDesktop and Footer
after update. [#854](https://github.com/sharetribe/flex-template-web/pull/854)
* [fix] Fix showing reviews from banned users.
- [fix] Fix showing reviews from banned users.
[#855](https://github.com/sharetribe/flex-template-web/pull/855)
## v1.0.0
[v1.1.0]: https://github.com/sharetribe/flex-template-web/compare/v1.0.0...v1.1.0
* [change] Migrate remaining Redux Forms to Final Form. Also now all the form components can be
## [v1.0.0]
- [change] Migrate remaining Redux Forms to Final Form. Also now all the form components can be
found in the src/forms folder. Remove redux-form from the dependencies.
[#845](https://github.com/sharetribe/flex-template-web/pull/845)
* [fix] Extract and fix missing information reminder modal from Topbar
- [fix] Extract and fix missing information reminder modal from Topbar
[#846](https://github.com/sharetribe/flex-template-web/pull/846)
* [fix] Add missing styles for ModalMissingInformation from Topbar
- [fix] Add missing styles for ModalMissingInformation from Topbar
[#847](https://github.com/sharetribe/flex-template-web/pull/847)
* [fix] API does not return all image variants anymore, this adds correct variants to update contact
- [fix] API does not return all image variants anymore, this adds correct variants to update contact
details call. [#848](https://github.com/sharetribe/flex-template-web/pull/848)
## v0.3.1
[v1.0.0]: https://github.com/sharetribe/flex-template-web/compare/v0.3.1...v1.0.0
* [change] Change lodash import syntax to reduce bundle size (-15.14 KB)
## [v0.3.1]
- [change] Change lodash import syntax to reduce bundle size (-15.14 KB)
[#839](https://github.com/sharetribe/flex-template-web/pull/839)
* [fix] Use https instead of git to access SDK repo for Heroku build (now that the repo is public).
- [fix] Use https instead of git to access SDK repo for Heroku build (now that the repo is public).
TODO: create SDK releases instead of using direct refs to single commit.
[#841](https://github.com/sharetribe/flex-template-web/pull/841)
* [fix] Typo fix for background-color
- [fix] Typo fix for background-color
[#842](https://github.com/sharetribe/flex-template-web/pull/842)
## v0.3.0
[v0.3.1]: https://github.com/sharetribe/flex-template-web/compare/v0.3.0...v0.3.1
* Remove custom touched handling from `FieldCheckboxGroup` as it has has become obsolete now that
## [v0.3.0]
- Remove custom touched handling from `FieldCheckboxGroup` as it has has become obsolete now that
Final Form is replacing Redux Form.
[#837](https://github.com/sharetribe/flex-template-web/pull/837)
* Create Stripe account directly instead of passing payout details to Flex API (deprecated way).
- Create Stripe account directly instead of passing payout details to Flex API (deprecated way).
[#836](https://github.com/sharetribe/flex-template-web/pull/836)
[v0.3.0]: https://github.com/sharetribe/flex-template-web/compare/v0.2.0...v0.3.0
## v0.2.0
* Starting a change log for Flex Template for Web.
- Starting a change log for Flex Template for Web.

View file

@ -15,26 +15,50 @@ If you just want to get the app running quickly to test it out, first install
```sh
git clone git@github.com:sharetribe/flex-template-web.git # clone this repository
cd flex-template-web/ # change to the cloned directory
cp .env-template .env # copy the env template file to add your local config
emacs .env # in your favorite editor, add the mandatory env vars to the config
yarn install # install dependencies
yarn run config # add the mandatory env vars to your local config
yarn run dev # start the dev server, this will open a browser in localhost:3000
```
See the [Environment configuration variables](docs/env.md) documentation for more information of the
required configuration variables.
You can also follow along the
[Getting started with FTW](https://www.sharetribe.com/docs/tutorials/getting-started-with-ftw/)
tutorial in the [Flex Docs website](https://www.sharetribe.com/docs/).
For more information of the configuration, see the
[FTW Environment configuration variables](https://www.sharetribe.com/docs/references/ftw-env/)
reference in Flex Docs.
**Note:** If you want to build your own Flex marketplace on top of the template, you should fork the
repository instead of cloning it. See the [Customization guide](./docs/customization-guide.md).
repository instead of cloning it. See the
[How to Customize FTW](https://www.sharetribe.com/docs/guides/how-to-customize-ftw/) guide in Flex
Docs.
## Getting started with your own customization
If you want to build your own Flex marketplace by customizing the template application, see the
[Customization guide](docs/customization-guide.md) documentation.
[How to Customize FTW](https://www.sharetribe.com/docs/guides/how-to-customize-ftw/) guide in Flex
Docs.
## Deploying to Heroku
**Note:** Remember to fork the repository before deploying the application. Connecting your own
Github repository to Heroku will make manual deploys easier.
See the
[How to deploy FTW to production](https://www.sharetribe.com/docs/guides/how-to-deploy-ftw-to-production/)
guide in Flex Docs for more information.
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
## Documentation
Full documentation can be found in the [docs directory](docs/).
See the Flex Docs site: https://www.sharetribe.com/docs/
See also the [docs/](docs/) directory for some additional internal documentation.
## Get help join Sharetribe Flex Developer Slack channel
If you have any questions about development, the best place to ask them is the Flex Developer Slack channel at https://www.sharetribe.com/flex-slack
## License

47
app.json Normal file
View file

@ -0,0 +1,47 @@
{
"name": "Sharetribe Flex Template Demo",
"description": "Sharetribe Flex Template Demo - Saunatime!",
"keywords": [
"node",
"react"
],
"repository": "https://github.com/sharetribe/flex-template-web/",
"env": {
"REACT_APP_MAPBOX_ACCESS_TOKEN": {
"description": "See: Integrating to map providers documentation https://github.com/sharetribe/flex-template-web/blob/master/docs/map-providers.md"
},
"REACT_APP_SHARETRIBE_SDK_CLIENT_ID": {
"description": "Client ID (API key). You will get this from the Sharetribe team."
},
"REACT_APP_STRIPE_PUBLISHABLE_KEY": {
"description": "Stripe publishable API key for generating tokens with Stripe API. Use test key (prefix pktest) for development."
},
"REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY": {
"description": "The currency used in the Marketplace as ISO 4217 currency code. For example: USD, EUR, CAD, AUD, etc.",
"value": "USD"
},
"REACT_APP_CANONICAL_ROOT_URL": {
"description": "Canonical root url of the marketplace. E.g. https://the-name-of-your-app.herokuapp.com or your actual domain. This is needed for social media sharing and SEO optimization."
},
"NODE_ENV": {
"description": "Node env. Use 'development' for development and 'production' for production.",
"value": "production"
},
"REACT_APP_ENV": {
"description": "A more fine grained env definition than NODE_ENV. Is used for example to differentiate envs in logging.",
"value": "production"
},
"REACT_APP_SHARETRIBE_USING_SSL": {
"description": "Redirect HTTP to HTTPS?",
"value": "true"
},
"SERVER_SHARETRIBE_TRUST_PROXY": {
"description": "Set when running the app behind a reverse proxy, e.g. in Heroku.",
"value": "true"
},
"REACT_APP_CSP": {
"description": "See: Content Security Policy (CSP) documentation https://github.com/sharetribe/flex-template-web/blob/master/docs/content-security-policy.md",
"value": "report"
}
}
}

View file

@ -13,45 +13,159 @@ used in a browser environment using the JavaScript SDK.
Marketplace features included in Saunatime:
* **Location search** shows the user if there are saunas available in a given location.
* **The listing page** gives a detailed view about what a particular sauna offers.
* **Transaction process**: Saunatime uses nightly booking.
* **Notifications**: Emails are sent during the booking process to alert customers and providers
- **Location search** shows the user if there are saunas available in a given location.
- **The listing page** gives a detailed view about what a particular sauna offers.
- **Transaction process**: Saunatime uses nightly booking.
- **Notifications**: Emails are sent during the booking process to alert customers and providers
about changes in the booking state.
* **Inbox** lists **orders** and **sales**.
* **Reviews** can be given after a completed transaction.
* **User profiles** provide detailed information about a given user.
* **Extended data:** The listing and user data models are modified using extended data.
- **Inbox** lists **orders** and **sales**.
- **Reviews** can be given after a completed transaction.
- **User profiles** provide detailed information about a given user.
- **Extended data:** The listing and user data models are modified using extended data.
## Directory structure
After cloning the repo, your project should look like this:
```
├── ext/
│ └── default-mail-templates/
├── package.json
├── docs/
├── public/
│ ├── static/
│ ├── 500.html
│ ├── index.html
│ └── robots.txt
├── server/
│ ├── csp.js
│ ├── index.js
│ ├── sitemap.js
│ └ ...
└── src/
├── analytics/
├── assets/
├── components/
├── containers/
├── ducks/
├── forms/
├── translations/
├── util/
├── Routes.js
├── app.js
├── config.js
├── examples.js
├── index.js
├── marketplace-custom-config.js
├── marketplace.css
├── marketplaceFonts.css
├── marketplaceIndex.css
├── reducers.js
├── routeConfiguration.js
└── store.js
```
### public/index.html
This is the page template. It includes fonts, Stripe SDK, Mapbox API (and Google Maps JavaScript
API), and app icons. It also specifies placeholders for tags generated by
[React Helmet](https://github.com/nfl/react-helmet)
### src/
- `src/index.js` is the JavaScript entry point on the client-side (it also exports `renderApp`
function to be used for server-side rendering).
- `src/app.js` creates ClientApp and ServerApp
- `src/routeConfiguration.js` defines logic between routes and page-level components
- `src/marketplace.css`, `src/marketplaceIndex.css`, `src/marketplaceIndex.css` define marketplace
level styling using [CSS Properties](http://cssnext.io/features/#custom-properties-var) and CSS
Property Sets.
- `src/translations/en.json` all English translations used in Saunatime template app. (A good place
to start customization.)
#### `src/components/`
Normal components used in Flex Template for Web are defined here. The main file for the component is
behind path `src/components/ComponentName/ComponentName.js`, but you can import it through
`component/index.js`:
`import { NamedLink } from 'path/to/components';`
When creating new components, remember to import marketplace.css file to component's own CSS file -
that way you can use CSS Property variables defined in `src/marketplace.css`.
#### `src/containers/`
Containers are components that are connected to [Redux](https://redux.js.org/) store. Currently,
this folder contains only page-level components and one common component: TopbarContainer.
#### `src/forms/`
Forms are in their own folder since they are using a special library to handle validations, errors,
internal state, etc.
### server/
- `server/index.js` handles server-side rendering (SSR). Built with [Express](http://expressjs.com)
(Node.js framework).
- `server/csp.js` [Content Security Policy](https://content-security-policy.com), whitelist of
domains that the application and loaded scripts are allowed to access from the browser.
- `server/sitemap.js` generates a minimal sitemap.xml for SEO purposes.
### ext/default-mail-templates/
This directory contains default email templates for transaction-specific needs (e.g.
_booking-request-accepted_). However, there are some built-in email templates that you can change in
[Flex Console](http://flex-console.sharetribe.com/email-templates/email-changed).
_**NOTE:** Changing these doesn't change actual email templates - you need to send customized
templates to your Flex contact person._
## Getting started
We recommend going through the
[Getting started articles](https://www.sharetribe.com/docs/background/getting-started/) in the Flex
Docs:
- [Introducing Flex](https://www.sharetribe.com/docs/background/introducing-flex/)
- [What development skills are needed?](https://www.sharetribe.com/docs/background/development-skills/)
- [Getting started with FTW](https://www.sharetribe.com/docs/tutorials/getting-started-with-ftw/)
## Customization guide
The easiest way to start a customization project is to read through the
[How to Customize FTW](https://www.sharetribe.com/docs/guides/how-to-customize-ftw/) guide in Flex
Docs.
## How to customize this template
The easiest way to start a customization project is to read through the
[customization guide](customization-guide.md). After that, you probably should start with changing
[translations](translations.md), [common styles](styling.md) in marketplace.css, and then create
[static pages](static-pages.md) and modify
[Terms of Service and Privacy Policy pages](terms-of-service-and-privacy-policy.md).
After going through the customization guide, you should probably start with the following guides in
Flex Docs:
Documentation for specific topics can be found in the following files:
- [How to set up Mapbox for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-mapbox-for-ftw/)
- [How to change FTW UI texts and translations](https://www.sharetribe.com/docs/guides/how-to-change-ftw-ui-texts-and-translations/)
- [How to customize FTW styles](https://www.sharetribe.com/docs/guides/how-to-customize-ftw-styles/)
- [How to change Terms of Service and Privacy Policy in FTW](https://www.sharetribe.com/docs/guides/how-to-change-tos-and-privacy-policy-in-ftw/)
- [How to change FTW icons](https://www.sharetribe.com/docs/guides/how-to-change-ftw-icons/)
- [FTW customization checklist](https://www.sharetribe.com/docs/guides/ftw-customization-checklist/)
- [How to deploy FTW to production](https://www.sharetribe.com/docs/guides/how-to-deploy-ftw-to-production/)
- [How routing works in FTW](https://www.sharetribe.com/docs/background/ftw-routing/)
- [How the Redux setup works in FTW](https://www.sharetribe.com/docs/background/ftw-redux/)
* [Customization guide](customization-guide.md)
* [Folder structure](folder-structure.md)
* [Integration to map providers](map-providers.md)
* [Translations](translations.md)
* [Styling a marketplace](styling.md)
* [Static pages](static-pages.md)
* [Terms of Service and Privacy Policy](terms-of-service-and-privacy-policy.md)
* [Extended data](extended-data.md)
* [Extend the listing data model](extend-listing.md)
* [Search filters](search-filters.md)
* [Testing](testing.md)
* [Error logging with Sentry](sentry.md)
* [Analytics](analytics.md)
* [Continuous Integration (CI)](ci.md)
* [Content Security Policy (CSP)](content-security-policy.md)
* [Original create-react-app documentation](https://github.com/sharetribe/create-react-app/blob/master/packages/react-scripts/template/README.md)
* [Customization checklist](customization-checklist.md)
* [Icons](icons.md)
* [Improving performance](improving-performance.md)
See also the following articles:
- [How to extend listing data in FTW](https://www.sharetribe.com/docs/guides/how-to-extend-listing-data-in-ftw/)
- [How to change search filters in FTW](https://www.sharetribe.com/docs/guides/how-to-change-search-filters-in-ftw/)
- [How to add static pages in FTW](https://www.sharetribe.com/docs/guides/how-to-add-static-pages-in-ftw/)
- [How to test FTW](https://www.sharetribe.com/docs/guides/how-to-test-ftw/)
- [How to set up Sentry to log errors in FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-sentry-to-log-errors-in-ftw/)
- [How to set up Analytics for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-analytics-for-ftw/)
- [How to set up Content Security Policy (CSP) for FTW](https://www.sharetribe.com/docs/guides/how-to-set-up-csp-for-ftw/)
- [How to use CI with FTW](https://www.sharetribe.com/docs/guides/how-to-use-ci-with-ftw/)
- [How to improve performance](https://www.sharetribe.com/docs/guides/how-to-improve-performance/)
See also the
[original create-react-app documentation](https://github.com/sharetribe/create-react-app/blob/master/packages/react-scripts/template/README.md).
The application was bootstrapped with a forked version of
[create-react-app](https://github.com/facebookincubator/create-react-app). While most of the

View file

@ -1 +0,0 @@
theme: jekyll-theme-minimal

View file

@ -1,66 +0,0 @@
<!DOCTYPE html>
<html lang="{{ site.lang | default: "en-US" }}">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% seo %}
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="wrapper">
<header>
<h1><a href="{{ "/" | absolute_url }}">{{ site.title | default: site.github.repository_name }}</a></h1>
{% if site.logo %}
<img src="{{site.logo | relative_url}}" alt="Logo" />
{% endif %}
<p>{{ site.description | default: site.github.project_tagline }}</p>
{% if site.github.is_project_page %}
<p class="view"><a href="{{ site.github.repository_url }}">View the Project on GitHub <small>{{ site.github.repository_nwo }}</small></a></p>
{% endif %}
{% if site.github.is_user_page %}
<p class="view"><a href="{{ site.github.owner_url }}">View My GitHub Profile</a></p>
{% endif %}
{% if site.show_downloads %}
<ul>
<li><a href="{{ site.github.zip_url }}">Download <strong>ZIP File</strong></a></li>
<li><a href="{{ site.github.tar_url }}">Download <strong>TAR Ball</strong></a></li>
<li><a href="{{ site.github.repository_url }}">View On <strong>GitHub</strong></a></li>
</ul>
{% endif %}
</header>
<aside>Navigation</aside>
<section>
{{ content }}
</section>
<footer>
{% if site.github.is_project_page %}
<p>This project is maintained by <a href="{{ site.github.owner_url }}">{{ site.github.owner_name }}</a></p>
{% endif %}
<p><small>Hosted on GitHub Pages &mdash; Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
</footer>
</div>
<script src="{{ "/assets/js/scale.fix.js" | relative_url }}"></script>
{% if site.google_analytics %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', '{{ site.google_analytics }}', 'auto');
ga('send', 'pageview');
</script>
{% endif %}
</body>
</html>

View file

@ -1,37 +1,5 @@
# Analytics
The application supports tracking page views with pluggable analytics handlers.
Documentation moved to the Flex Docs site:
## Google Analytics
Google Analytics (GA) is supported by default. The enable GA, set the GA tracker ID to the
environment variable `REACT_APP_GOOGLE_ANALYTICS_ID`;
## Custom analytics handler
If you want to add a new analytics library, you can do as follows:
1. Add the analytics library script
If the analytics library has an external script, add the library script tag to the
[src/public/index.html](../public/index.html) file. If you need more control, see how the GA
script is added in [server/renderer.js](../server/renderer.js).
1. Create a handler
To track page views, create a custom handler e.g. in
[src/analytics/handlers.js](../src/analytics/handlers.js). The handler should be a class that
implements a `trackPageView(url)` method.
Note that the `url` parameter might not be the same as in the URL bar of the browser. It is the
canonical form of the URL. For example, in the listing page it doesn't have the dynamic title
slug in the middle. This allows unified analytics and correct tracking of pages that can be
accessed from multiple different URLs.
If you analytics library takes the page URL from the browser, you might need to override that
behavior to use the canonical URL that is given to the method.
1. Initialise the handler
Initialise the handler in the `setupAnalyticsHandlers()` function in
[src/index.js](../src/index.js).
https://www.sharetribe.com/docs/guides/how-to-set-up-analytics-for-ftw/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 KiB

View file

@ -1,34 +1,5 @@
# CI
The application provides a configuration to use [CircleCI](https://circleci.com/) as a continuous
integration server to run tests and other scripts. This ensures quality and can be forced to avoid
merging changes that break tests or fail audits.
Documentation moved to the Flex Docs site:
The [circle.yml](../circle.yml) file is used to configure CircleCI.
Currently the CI runs the following scripts:
## Security audit: `yarn run audit`
This command runs the security audit using [nsp](https://www.npmjs.com/package/nsp). The audit
checks for installed packages with known vulnerabilities and warns about those.
The scripts outputs information about the dependency path that added the package. If that
information is not enough, `yarn why package-name` can be used to get more detailed information
about why the package is installed.
If you are convinced that the vulnerability can be ignored, exceptions can be added to the
[.nsprc](../.nsprc) file.
## Code formatting: `yarn run format-ci`
This command fails if there are changes in the formatting that are not committed. Run
`yarn run format` to format the code and get rid of the error.
## Build: `yarn run build`
This command ensures that the build passes.
## Tests: `yarn run test-ci`
This command runs the tests.
https://www.sharetribe.com/docs/guides/how-to-use-ci-with-ftw/

View file

@ -1,43 +1,5 @@
# Content Security Policy (CSP)
According to [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP):
Documentation moved to the Flex Docs site:
> Content Security Policy (CSP) is an added layer of security that helps to detect and mitigate
> certain types of attacks, including Cross Site Scripting (XSS) and data injection attacks. These
> attacks are used for everything from data theft to site defacement or distribution of malware.
This document describes how to use a CSP with the Flex template app. By default the CSP is disabled.
By turning it on, the default whitelist in [server/csp.js](../server/csp.js) works with the all the
URLs and tools that come with the application.
## Setup
The CSP is configured using the `REACT_APP_CSP` environment variable.
Possible values:
* not set: disabled
* `REACT_APP_CSP=report`: Enabled, but policy violations are only reported
* `REACT_APP_CSP=block`: Enabled. Policy violations are reported and requests that violate the
policy are blocked
If error logging with Sentry is enabled (See [Error logging with Sentry](sentry.md)), the reports
are sent to Sentry. Otherwise the reports are just logged in the backend.
## Extending the policy
If you want to whitelist new sources (for example adding a new external analytics service) and keep
the CSP enabled, you should add the domains to the white list in [server/csp.js](../server/csp.js).
The easiest way to do this is to first turn on the policy in report mode and then see what policy
violations are logged to the browser developer console or to the backend policy violation report
URL.
## Resources
To understand what CSP is and how browsers work, here are some resources:
* https://content-security-policy.com/
* https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
* https://ponyfoo.com/articles/content-security-policy-in-express-apps
* https://helmetjs.github.io/docs/csp/
https://www.sharetribe.com/docs/guides/how-to-set-up-csp-for-ftw/

View file

@ -1,41 +1,5 @@
# Customization checklist
Some generic things to update and check when starting to customize the template.
Documentation moved to the Flex Docs site:
* [Marketplace colors](styling.md)
* [Generate app icons](icons.md)
* [Update translations](../src/translations/en.json) or [change the language](translations.md)
* [LandingPage](../src/containers/LandingPage/LandingPage.js): update and create branded sections
* [Footer](../src/components/Footer/Footer.js)
* [AboutPage](../src/containers/AboutPage/AboutPage.js)
* [Terms of Service](terms-of-service-and-privacy-policy.md#terms-of-service)
* [Privacy Policy](terms-of-service-and-privacy-policy.md#privacy-policy)
* [Social media sharing graphics](../src/components/Page/Page.js);
* [Logo](../src/components/Logo/Logo.js) Change and check that it works on Topbar, Footer, and
CheckoutPage
* [Default background image](../src/assets/background-1440.jpg)
* [Maps Marker icon](../src/components/Map/images/marker-32x32.png)
* [Config: update environment variables](../src/config.js)
* [Config: siteTitle](../src/config.js) for page schema (SEO)
* [Config: marketplace address](../src/config.js): contact details also improve SEO
* [Config: social media pages](../src/config.js)
* [Marketplace custom config](../src/marketplace-custom-config.js)
* Update [ListingPage](../src/containers/ListingPage/ListingPage.js) to show extended data (aka
publicData attribute)
* Update [EditListingWizard](../src/components/EditListingWizard/EditListingWizard.js) and panels to
add extended data
* Update [SearchPage](../src/containers/SearchPage/SearchPage.js) to filter with extended data
* Update [routeConfiguration](../src/routeConfiguration.js) if needed
* Update [Email templates](../ext/default-mail-templates), all of them: .html, subject.txt, and
text.txt
* Update [config: bookingUnitType](../src/config.js) if needed
* If `line-item/units` is used, add quantity handling to
[BookingDatesForm](../src/forms/BookingDatesForm/BookingDatesForm.js),
[ListingPage](../src/containers/ListingPage/ListingPage.js),
[CheckoutPage](../src/containers/CheckoutPage/CheckoutPage.js)
## What else
* Do you need more [static pages](static-pages.md)?
* Changes to existing pages
* Changes to transaction process (API + Web app)
https://www.sharetribe.com/docs/guides/ftw-customization-checklist/

View file

@ -1,145 +1,5 @@
# Customization guide
So you've decided to build your own Flex marketplace using the template. That's awesome! This guide
will help you in setting up your fork and describes the general workflow.
Documentation moved to the Flex Docs site:
**Note:** If you cloned the repository like described in the Quick start section of the project
README file, you probably don't want to make the customizations in that project. Forking the
repository is the recommended way to proceed. Follow this guide for instructions.
## Requirements
Install required tools:
* [Node.js](https://nodejs.org/)
* [Yarn](https://yarnpkg.com/)
## Technologies
Depending on what you want to change in the template, various skills help in achieving your goal.
Some of the basic customizations don't require specific coding skills, but many customisations
become technically involved. We've tried to keep the technology setup as simple as possible, and
frontend developers with experience in widely used tooling should feel comfortable right from the
get-go.
Here are some main technologies that the template uses:
* JavaScript: programming language for the whole application
* [React](https://reactjs.org/): library for creating user interfaces with components
* CSS: styling the user interface using [CSS Modules](https://github.com/css-modules/css-modules)
and [cssnext](http://cssnext.io/)
* [Redux](https://redux.js.org/): state and data flow handling
* [Final Form](https://github.com/final-form/final-form): forms
* [React Router](https://reacttraining.com/react-router/): routing
* [Express](https://expressjs.com/): server
## Setup
To start a new customization project, you should create a separate Git repository and setup the Git
remotes so that you can pull in changes from the main (upstream) repository to your custom
repository.
### Fork the repository
See the [Fork a repo](https://help.github.com/articles/fork-a-repo/) documentation for instructions
for forking a repository in GitHub.
In the directory you want to create the project in:
git clone git@github.com:YOUR_USERNAME/YOUR_FORK.git # clone your fork
cd YOUR_FORK # changed to the cloned directory
git remote add upstream git@github.com:sharetribe/flex-template-web.git # add the template as the upstream remote
See also the
[Configuring a remote for a fork](https://help.github.com/articles/configuring-a-remote-for-a-fork/)
documentation.
### Pull in latest upstream changes
If you want to update your local customization project with changes in the template, you should pull
in changes from the upstream remote.
**Note:** Depending on the changes you've made to the template, this might be hard/impossible
depending on what has changed in the template. You should mainly think of the template being the
starting point of your customization, not something that is constantly updated.
In the `master` branch (or in the branch you want to merge in the upstream changes):
1. Fetch the latest changes from the upstream repository:
```sh
git fetch upstream
```
1. Merge the changes to your local branch
```sh
git merge upstream/master
```
1. Fix possible merge conflicts, commit, and push/deploy.
See also the [Syncing a fork](https://help.github.com/articles/syncing-a-fork/) documentation.
## Configuration
There are some mandatory configuration, and some configuration that you most likely want to at least
go through.
To get started, first copy the config template:
cp .env-template .env
The `.env` file is the place to add your local configuration. It is ignored in Git, so you'll have
to add the corresponding configuration also to your server environment.
There are some mandatory configuration variables that are defined in the template. See the
[Environment configuration variables](env.md) documentation for more information.
See also the [src/config.js](../src/config.js) file for more configuration options.
## Development
In your project root, install dependencies:
yarn install
To develop the application and to see changes live, start the frontend development server:
yarn run dev
**Known issues:**
* Adding/changing `import`s may not be synced properly with ESLint. You may see an error
`Unable to resolve path to module` even though the module existing in right path. Restarting the
server doesn't help. To solve the issue, you need to make a change to the file where the error
occurs.
## Development Server
The usual way to develop the application is to use the frontend development server (see above).
However, in production you likely want to use the server rendering setup. To develop the server
rendering setup locally, run:
yarn run dev-server
This runs the frontend production build and starts the Express.js server in `server/index.js` that
renders the application routes in the server. The server is automatically restarted when there are
changes in the `server/` directory.
**Note:** this server does **not** pick up changes in the frontend application code. For that you
need to build the client bundle by restarting the server manually.
## Tests
To start the test watcher, run
yarn test
See more in the [testing documentation](testing.md).
## Customization
There are many things that you should change in the default template, and many more that you can
change. See the [Customization checklist](customization-checklist.md) documentation for more
information.
https://www.sharetribe.com/docs/guides/how-to-customize-ftw/

View file

@ -0,0 +1,5 @@
# Deploying to production
Documentation moved to the Flex Docs site:
https://www.sharetribe.com/docs/guides/how-to-deploy-ftw-to-production/

View file

@ -1,42 +1,5 @@
# Environment configuration variables
The following configuration variables can be set to control the Flex template app behaviour. Most of
them have defaults that work for development environment. For production deploys most should be set.
Documentation moved to the Flex Docs site:
| Variable | Description |
| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| REACT_APP_MAPBOX_ACCESS_TOKEN | See: [Integrating to map providers](./map-providers.md) |
| REACT_APP_GOOGLE_MAPS_API_KEY | See: [Google Maps API key](./google-maps.md) (Alternative map provider) |
| REACT_APP_SHARETRIBE_SDK_CLIENT_ID | Client ID (API key). You will get this from the Sharetribe team. |
| REACT_APP_STRIPE_PUBLISHABLE_KEY | Stripe publishable API key for generating tokens with Stripe API. Use test key (prefix pk*test*) for development. |
| REACT_APP_SHARETRIBE_SDK_BASE_URL | The base url to access the Sharetribe Flex Marketplace API. |
| REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY | The currency used in the Marketplace as ISO 4217 currency code. For example: USD, EUR, CAD, AUD, etc. |
| REACT_APP_CANONICAL_ROOT_URL | Canonical root url of the marketplace. Needed for social media sharing and SEO optimization. |
| NODE_ENV | Node env. Use 'development' for development and 'production' for production. |
| PORT | Port for server to accept connections. |
| REACT_APP_ENV | A more fine grained env definition than NODE_ENV. Is used for example to differentiate envs in logging. |
| REACT_APP_SHARETRIBE_USING_SSL | Redirect HTTP to HTTPS? |
| SERVER_SHARETRIBE_TRUST_PROXY | Set when running the app behind a reverse proxy, e.g. in Heroku. |
| REACT_APP_PUBLIC_SENTRY_DSN | See: [Error logging with Sentry](./sentry.md) |
| SERVER_SENTRY_DSN | See: [Error logging with Sentry](./sentry.md) |
| REACT_APP_CSP | See: [Content Security Policy (CSP)](./content-security-policy.md) |
| BASIC_AUTH_USERNAME | Set to enable HTTP Basic Auth |
| BASIC_AUTH_PASSWORD | Set to enable HTTP Basic Auth |
| REACT_APP_GOOGLE_ANALYTICS_ID | See: [Google Analytics](./analytics.md) |
| REACT_APP_AVAILABILITY_ENABLED | Enables availability calendar for listings. |
| REACT_APP_DEFAULT_SEARCHES_ENABLED | Enables default search suggestions in location autocomplete search input. |
## Defining configuration
When the app is started locally with `yarn run dev` or `yarn run dev-server`, you can set
environment variables by using the (gitignored) `.env` file. The repository contains a template file
`.env-template` with default configuration. Just copy that as `.env` and edit as necessary.
In production, it's recommended that you set the configuration via env variables and do not deploy
an .env file. The client application will only be packaged with env variables that start with
REACT_APP. This way server secrets don't end up in client bundles.
**With deploys note that the configuration options are bundled in the client package at build
time.** The configuration of the build environment must match run environment for things to work
consistently. To apply changes to configuration values client bundle must be rebuilt. Just
restarting the server is not enough.
https://www.sharetribe.com/docs/references/ftw-env/

View file

@ -1,475 +1,5 @@
# Extend listing data
This guide walks you through the different steps required to expand the listing data model in your
marketplace. We'll have a look on how the data is added, how it can be presented and finally how it
can be used to filter searches.
Documentation moved to the Flex Docs site:
Adding new attributes to the data model relies on a Flex concept called
[extended data](./extended-data.md).
Three main areas in extending the listing data model are:
* [Declare the attribute and it's possible values](#declare-the-attribute-and-its-possible-values)
* [Edit the listing wizard](#edit-the-listing-wizard)
* [Show the attribute on listing page](#show-the-attribute-on-listing-page)
* [Use the attribute as a search filter](#use-the-attribute-as-a-search-filter)
In this guide we will extend the listing data model by adding a _capacity_ attribute.
## Add a new attribute
### Declare the attribute and its possible values
So, you have come up with a great new extension to the listing data model, fantastic! Depending of
the type of data the new attribute is going to be used for it might make sense to define and store
the possible values for the attribute. In case the data will be free form text there might not be
use for this but in our case we wan't to fix the possible values that can be used for the capacity.
Also if the attribute will be used as a search filter it helps to keep track of the possible values
somewhere.
A commonly used way of storing the possible values for a listing attribute is to declare them in the
[marketplace-custom-config.js](../src/marketplace-custom-config.js) file. Place the values in an
array and export the variable containing the array. The exports from that file are included in the
`src/config.js` file and are available as properties in `config.custom`. Search filters and some
components used to edit and present the data rely on a data model of an array of objects that
contain `key` and `label` properties.
For the capacity attribute we'll define a set of values that describe the capacity in a few ranges
of how many people can fit into a given sauna:
```js
export const capacityOptions = [
{ key: '1to3', label: '1 to 3' },
{ key: '4to6', label: '4 to 6' },
{ key: '7to9', label: '7 to 9' },
{ key: '10plus', label: '10 plus' },
];
```
### Edit the listing wizard
Next step is to add means for modifying the attribute data in listings. This is achieved by adding
proper inputs to the `EditListingWizard`. It could probably make sense to add the input to the
_description_ tab or modify the _amenities_ tab to also include capacity but for the sake of clarity
let's add a new tab to the wizard. The new tab will be placed between the _amenities_ and _policy_
tabs.
First lets declare the tab in `EditListingWizardTab`:
```js
export const DESCRIPTION = 'description';
export const FEATURES = 'features';
export const CAPACITY = 'capacity';
export const POLICY = 'policy';
export const LOCATION = 'location';
export const PRICING = 'pricing';
export const PHOTOS = 'photos';
// EditListingWizardTab component supports these tabs
export const SUPPORTED_TABS = [DESCRIPTION, FEATURES, CAPACITY, POLICY, LOCATION, PRICING, PHOTOS];
```
Now in `EditListingWizard` we can take that tab declaration into use. Import the tab name variable
from `EditListingWizardTab` and add it to the `TABS` array.
```js
export const TABS = [DESCRIPTION, FEATURES, CAPACITY, POLICY, LOCATION, PRICING, PHOTOS];
```
Also remember to add a label for the tab in the `tabLabel` function:
```js
const tabLabel = (intl, tab) => {
let key = null;
if (tab === DESCRIPTION) {
key = 'EditListingWizard.tabLabelDescription';
} else if (tab === FEATURES) {
key = 'EditListingWizard.tabLabelFeatures';
} else if (tab === CAPACITY) {
key = 'EditListingWizard.tabLabelCapacity';
} else if (tab === POLICY) {
key = 'EditListingWizard.tabLabelPolicy';
} else if (tab === LOCATION) {
key = 'EditListingWizard.tabLabelLocation';
} else if (tab === PRICING) {
key = 'EditListingWizard.tabLabelPricing';
} else if (tab === PHOTOS) {
key = 'EditListingWizard.tabLabelPhotos';
}
return intl.formatMessage({ id: key });
};
```
The `tabCompleted` function keeps track of which data the user has already provided in order to tell
which tabs are completed. As we will be storing the capacity information in the listing's _public
data_ property (see the [extended data](./extended-data.md) documentation for more info on different
extended data types) we shall look into that property when resolving whether the capacity tab has
alerady been completed or not:
```js
/**
* Check if a wizard tab is completed.
*
* @param tab wizard's tab
* @param listing is contains some specific data if tab is completed
*
* @return true if tab / step is completed.
*/
const tabCompleted = (tab, listing) => {
const { description, geolocation, price, title, publicData } = listing.attributes;
const images = listing.images;
switch (tab) {
case DESCRIPTION:
return !!(description && title);
case FEATURES:
return !!(publicData && publicData.amenities);
case CAPACITY:
return !!(publicData && publicData.capacity);
case POLICY:
return !!(publicData && typeof publicData.rules !== 'undefined');
case LOCATION:
return !!(geolocation && publicData && publicData.location && publicData.location.address);
case PRICING:
return !!price;
case PHOTOS:
return images && images.length > 0;
default:
return false;
}
};
```
Next task is to add form and panel components that render the capacity tab. As for the form, let's
create a `EditListingCapacityForm` component:
```js
import React from 'react';
import { arrayOf, bool, func, shape, string } from 'prop-types';
import { compose } from 'redux';
import { Form as FinalForm } from 'react-final-form';
import { intlShape, injectIntl, FormattedMessage } from 'react-intl';
import classNames from 'classnames';
import { propTypes } from '../../util/types';
import { Form, Button, FieldSelect } from '../../components';
import { required } from '../../util/validators';
import css from './EditListingCapacityForm.css';
export const EditListingCapacityFormComponent = props => (
<FinalForm
{...props}
render={fieldRenderProps => {
const {
className,
disabled,
handleSubmit,
intl,
invalid,
pristine,
saveActionMsg,
updated,
updateError,
updateInProgress,
capacityOptions,
} = fieldRenderProps;
const capacityPlaceholder = intl.formatMessage({
id: 'EditListingCapacityForm.capacityPlaceholder',
});
const errorMessage = updateError ? (
<p className={css.error}>
<FormattedMessage id="EditListingCapacityForm.updateFailed" />
</p>
) : null;
const capacityRequired = required(
intl.formatMessage({
id: 'EditListingCapacityForm.capacityRequired',
})
);
const classes = classNames(css.root, className);
const submitReady = updated && pristine;
const submitInProgress = updateInProgress;
const submitDisabled = invalid || disabled || submitInProgress;
return (
<Form className={classes} onSubmit={handleSubmit}>
{errorMessage}
<FieldSelect
className={css.capacity}
name="capacity"
id="capacity"
validate={capacityRequired}
>
<option value="">{capacityPlaceholder}</option>
{capacityOptions.map(c => (
<option key={c.key} value={c.key}>
{c.label}
</option>
))}
</FieldSelect>
<Button
className={css.submitButton}
type="submit"
inProgress={submitInProgress}
disabled={submitDisabled}
ready={submitReady}
>
{saveActionMsg}
</Button>
</Form>
);
}}
/>
);
EditListingCapacityFormComponent.defaultProps = {
selectedPlace: null,
updateError: null,
};
EditListingCapacityFormComponent.propTypes = {
intl: intlShape.isRequired,
onSubmit: func.isRequired,
saveActionMsg: string.isRequired,
updated: bool.isRequired,
updateError: propTypes.error,
updateInProgress: bool.isRequired,
capacityOptions: arrayOf(
shape({
key: string.isRequired,
label: string.isRequired,
})
).isRequired,
};
export default compose(injectIntl)(EditListingCapacityFormComponent);
```
The form component receives `capacityOptions` as a prop which are used to populate a `FieldSelect`
component for selecting the capacity. The `EditListingCapacityForm` is also added to the
`src/containers/index.js` file so that it can easilly be referenced from other components. To use
the capacity editing form we'll add a panel component which is then used in `EditListingWizardTab`
to render the wizard phase. This component we'll call `EditListingCapacityPanel`:
```js
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { FormattedMessage } from 'react-intl';
import { ensureOwnListing } from '../../util/data';
import { ListingLink } from '../../components';
import { EditListingCapacityForm } from '../../containers';
import config from '../../config.js';
import css from './EditListingCapacityPanel.css';
const EditListingCapacityPanel = props => {
const {
className,
rootClassName,
listing,
onSubmit,
onChange,
submitButtonText,
panelUpdated,
updateInProgress,
errors,
} = props;
const classes = classNames(rootClassName || css.root, className);
const currentListing = ensureOwnListing(listing);
const { publicData } = currentListing.attributes;
const panelTitle = currentListing.id ? (
<FormattedMessage
id="EditListingCapacityPanel.title"
values={{ listingTitle: <ListingLink listing={listing} /> }}
/>
) : (
<FormattedMessage id="EditListingCapacityPanel.createListingTitle" />
);
return (
<div className={classes}>
<h1 className={css.title}>{panelTitle}</h1>
<EditListingCapacityForm
className={css.form}
initialValues={{ capacity: publicData.capacity }}
onSubmit={values => {
const { capacity } = values;
const updateValues = {
publicData: {
capacity,
},
};
onSubmit(updateValues);
}}
onChange={onChange}
saveActionMsg={submitButtonText}
updated={panelUpdated}
updateError={errors.updateListingError}
updateInProgress={updateInProgress}
capacityOptions={config.custom.capacityOptions}
/>
</div>
);
};
const { func, object, string, bool } = PropTypes;
EditListingCapacityPanel.defaultProps = {
className: null,
rootClassName: null,
listing: null,
};
EditListingCapacityPanel.propTypes = {
className: string,
rootClassName: string,
// We cannot use propTypes.listing since the listing might be a draft.
listing: object,
onSubmit: func.isRequired,
onChange: func.isRequired,
submitButtonText: string.isRequired,
panelUpdated: bool.isRequired,
updateInProgress: bool.isRequired,
errors: object.isRequired,
};
export default EditListingCapacityPanel;
```
In the panel component we check for an initial capacity value from the `public_data` property of the
listing. In the submit handler the new capacity value is stored in the same property. The updated
listing object is eventually passed to the `updateListingDraft` and `requestUpdateListing` functions
in the `EditListingDetails.duck.js` file where the data updates are handled. Respectively
`EditListingCapacityPanel` needs to be exported from `src/components/index.js` for easier access
from other files.
Now that we have the panel and the form all ready we can add the panel to the `EditListingWizardTab`
component. This is done by adding a new block to the `switch` structure that handles rendering the
correct panel:
```js
case CAPACITY: {
const submitButtonTranslationKey = isNew
? 'EditListingWizard.saveNewCapacity'
: 'EditListingWizard.saveEditCapacity';
return (
<EditListingCapacityPanel
{...panelProps(CAPACITY)}
submitButtonText={intl.formatMessage({ id: submitButtonTranslationKey })}
onSubmit={values => {
onCompleteEditListingWizardTab(tab, values);
}}
/>
);
}
```
There! Now we've extended the listing data model with capacity information.
![Edit the capacity](./assets/extend-listing/edit_capacity.png)
The capacity data can now be added to new and existing listings. Next chapter describes how that
data can be presented in the listing page.
## Show the attribute on listing page
Next step in adding a new attribute to the listing is to present it in the listing page. On some
cases an extension to the listing data model can be used purely to enhance the application logic but
in our case with the capacity information we want to show the added attribute in the listing page
for potential customers.
To show the capacity attribute in the listing page, let's create a specific component for it and
place it in the `ListingPage` container. Desired outcome could also be achieved just by editing the
`ListingPage` but extracting the capacity UI parts into a separate component will simplify the
`ListingPage` and make possible upstream updates from the Flex web template repo easier as there's
less chances for merge conflicts. So, let's create a `SectionCapacity` component in the
`src/containers/ListingPage/` directory:
```js
import React from 'react';
import { array, shape, string } from 'prop-types';
import { FormattedMessage } from 'react-intl';
import css from './ListingPage.css';
const SectionCapacity = props => {
const { publicData, options } = props;
const capacity = publicData.capacity;
const capacityOption = options.find(option => option.key === capacity);
return capacityOption ? (
<div className={css.sectionCapacity}>
<h2 className={css.capacityTitle}>
<FormattedMessage id="ListingPage.capacityTitle" />
</h2>
<p className={css.capacity}>{capacityOption.label}</p>
</div>
) : null;
};
SectionCapacity.propTypes = {
options: array.isRequired,
publicData: shape({
capacity: string,
}).isRequired,
};
export default SectionCapacity;
```
Remember to add corresponding css definitions to `ListingPage.css` to get the styling right. Import
the component into `ListingPage` and place it inside the `<div className={css.mainContent}>`
element:
```js
import SectionCapacity from './SectionCapacity';
```
```js
<div className={css.mainContent}>
{/* other sections */}
<SectionCapacity publicData={publicData} options={capacityOptions} />
{/* other sections */}
</div>
```
```js
ListingPageComponent.defaultProps = {
// other default props
capacityOptions: config.custom.capacityOptions,
};
ListingPageComponent.propTypes = {
// other props
capacityOptions: array,
};
```
In the snippet above, the capacity options are passed to the `ListingPage` as a property, with the
default property value pulling the options from the custom config (`marketplace-custom-config.js`).
This way the listing page test can define it's own capacity options that are in line with test data
used in the test and custom config changes will not affect test results.
And voilà, we have listing capacity presented in the listing page!
![Capacity on listing page](./assets/extend-listing/capacity_listing_page.png)
## Use the attribute as a search filter
To see how the capacity attribute can be used to filter search results, please refer to the
[search filters documentation](./search-filters.md).
https://www.sharetribe.com/docs/guides/how-to-extend-listing-data-in-ftw/

View file

@ -1,37 +0,0 @@
# Extended Data
_Extended data_ is arbitrary information that can be attached to certain resources in the Flex API.
Extended data values can be of any valid JSON data type, including JSON data structures like object
and array. The purpose of extended data is to expand the ways in which the Flex API can be used.
## Types of extended data
Extended data is divided into two types: _public data_ and _protected data_.
### Public data
Public data can be written by anyone who has write permission to a resource and it is visible to
anyone who can read that resource.
### Protected data
Protected data, just like public data, can be modified by anyone with write access to the resource.
However, it can only be read by marketplace operators. It is also possible to reveal the protected
data at a specific point in the booking transaction process, for example if listing's address is
presented to the customer after a booking has been confirmed.
## Data schema and searched
Extended data works out of the box without any prior configuration to the marketplace. Public and
protected data can be added to listings just by passing it in the create/update request to the API.
However, optionally a _data schema_ can be defined for an extended data key. The data schema allows
that extended data attribute to be used as a search parameter in some API endpoints, like in the
listings query endpoint. Contact Sharetribe team if you need to add a schema to your extended data.
## Extended data in Flex template app
The Flex web template uses extended data by default with listing and user resources. In case of the
listings, category and amenities information is stored in the `publicData` attribute. For the users,
phone number is stored in the `protectedData` attribute. As for indexed data, the template app
relies on data schemas for categories and amenities to be configured for the marketplace in the API
as those values are used as filters in the listing search.

View file

@ -1,97 +0,0 @@
# Folder structure
After cloning the repo, your project should look like this:
```
├── ext
│   └── default-mail-templates
├── package.json
├── docs
├── public
│   ├── 500.html
│   ├── index.html
│   ├── robots.txt
│   └── static
├── server
│   ├── index.js
│   ├── csp.js
│   ├── sitemap.js
│   └ ...
└── src
├── Routes.js
├── analytics
├── app.js
├── assets
├── components
├── config.js
├── containers
├── ducks
├── examples.js
├── forms
├── index.js
├── marketplace-custom-config.js
├── marketplace.css
├── marketplaceFonts.css
├── marketplaceIndex.css
├── reducers.js
├── routeConfiguration.js
├── store.js
├── translations
└── util
```
## public/index.html
This is the page template. It includes fonts, Stripe SDK, Mapbox API (and Google Maps JavaScript
API), and app icons. It also specifies placeholders for tags generated by
[React Helmet](https://github.com/nfl/react-helmet)
## src/
* `src/index.js` is the JavaScript entry point on the client-side (it also exports `renderApp`
function to be used for server-side rendering).
* `src/app.js` creates ClientApp and ServerApp
* `src/routeConfiguration.js` defines logic between routes and page-level components
* `src/marketplace.css`, `src/marketplaceIndex.css`, `src/marketplaceIndex.css` define marketplace
level styling using [CSS Properties](http://cssnext.io/features/#custom-properties-var) and CSS
Property Sets.
* `src/translations/en.json` all English translations used in Saunatime template app. (A good place
to start customization.)
### `src/components/`
Normal components used in Flex Template for Web are defined here. The main file for the component is
behind path `src/components/ComponentName/ComponentName.js`, but you can import it through
`component/index.js`:
`import { NamedLink } from 'path/to/components';`
When creating new components, remember to import marketplace.css file to component's own CSS file -
that way you can use CSS Property variables defined in `src/marketplace.css`.
### `src/containers/`
Containers are components that are connected to [Redux](https://redux.js.org/) store. Currently,
this folder contains only page-level components and one common component: TopbarContainer.
### `src/forms/`
Forms are in their own folder since they are using a special library to handle validations, errors,
internal state, etc.
## server/
* `server/index.js` handles server-side rendering (SSR). Built with [Express](http://expressjs.com)
(Node.js framework).
* `server/csp.js` [Content Security Policy](https://content-security-policy.com), whitelist of
domains that the application and loaded scripts are allowed to access from the browser.
* `server/sitemap.js` generates a minimal sitemap.xml for SEO purposes.
## ext/default-mail-templates/
This file contains default email templates for various needs (e.g. _booking-request-accepted_, or
_verify-your-email_). You should customize all the different files (\*-html.html, \*-subject.txt,
and \*-text.txt).
_**NOTE:** Changing these doesn't change actual email templates - you need to send customized
templates to your Flex contact person._

View file

@ -1,181 +1,5 @@
# Google Maps
Flex Template for Web (FTW) offers out of the box support for Google Maps API for showing a map and
searching locations with search autocompletion. This document describes how to set up the API key
for the API requests to work properly.
Documentation moved to the Flex Docs site:
> Note: before making the change to Google Maps, you should consider if you are OK with their
> current pricing. There's a pricing calculator available in their
> [pricing page](https://cloud.google.com/maps-platform/pricing/). FTW's default map provider is
> Mapbox, which is often cheaper.
> [Learn more about how to use Mapbox or some other map provider instead of Google Maps](https://github.com/sharetribe/flex-template-web/blob/e6034c7690c095553f44092b032689cd6b6f7546/docs/map-providers.md).
## Generate a Google Maps API key
Go to the
[Google Maps JavaScript API V3 Reference](https://developers.google.com/maps/documentation/javascript/reference),
click on the "GET A KEY" button in the top bar, and follow the instructions. You can copy the given
key to your application now.
## Enable Google Places API Web Service
Follow the instructions in the
[Getting started](https://developers.google.com/maps/documentation/javascript/places#GetStarted)
section of the Places library documentation to enable using the Google Places API Web Service. Also
Maps Static API and Maps Javascript API need to be enabled.
## Setup the application to use the API key
The application uses the `REACT_APP_GOOGLE_MAPS_API_KEY` environment variable for the key value. For
local development, you can add the variable in the Gitignored `.env` file in the project root:
```
REACT_APP_GOOGLE_MAPS_API_KEY=my-key-here
```
## Setup common locations to reduce typing
The location autocomplete-input in the landing page and the topbar can be configured to have
specific locations shown by default when the user focuses on the input and hasn't yet typed in any
searches. This reduces the typing required for common searches and also reduces the need to use
Google Map Places API that much.
To use default searches, another environment variable needs to be set:
```
REACT_APP_DEFAULT_SEARCHES_ENABLED=true
```
The default locations have been described in file:
[src/default-location-searches.js](../src/default-location-searches.js).
The same environment variable also shows "current location" suggestion, which will make the browser
to ask user's current location. This is a fast way to search listings nearby. You can specify
whether to use the current location from [config.js](../src/config.js). Search for variables:
`suggestCurrentLocation` and `currentLocationBoundsDistance`.
## Change components: use Google Map versions instead of Mapbox
If you wish to use Google Maps instead of Mapbox, you need to make some changes to FTW default
setup.
### 1. Include Google Map script instead of Mapbox scripts
Mapbox related scripts can be removed from index.html and instead use Google Map script described in
comments.
_public/index.html:_
```html
<script src="%PUBLIC_URL%/static/scripts/mapbox/mapbox-sdk.min.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js"></script>
<script>
window.mapboxgl.accessToken = '%REACT_APP_MAPBOX_ACCESS_TOKEN%';
</script>
<!--
If Google Maps is used instead of Mapbox, you need to include Google's script instead:
<script src="https://maps.googleapis.com/maps/api/js?key=%REACT_APP_GOOGLE_MAPS_API_KEY%&libraries=places"></script>
-->
```
### 2. Searching with Google's geocoding API
Location search aka LocationAutocompleteInput should use Google Map specific geocoder. The correct
import is written to the comments of LocationAutocompleteInput component.
_src/components/LocationAutocompleteInput/LocationAutocompleteInputImpl.js:_
```js
import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderMapbox';
// import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderGoogleMaps';
```
Furthermore, Google Map states in their terms of service that Google logo needs to be visible when
using their geocoding service. It is available as a background image below the autocomplete
predictions. However, there needs to be enough padding for that logo. You can change the padding
through `marketplace.css`.
_src/marketplace.css:_
```js
/* Google Maps needs 72px bottom padding to accommodate logo, Mapbox doesn't have one */
--locationAutocompleteBottomPadding: 8px;
```
### 3. Show correct map on ListingPage (Map component)
Google Map version (containing both static and dynamic maps) can be taken into use by importing
correct map subcomponent.
_src/components/Map/Map.js:_
```js
import { StaticMap, DynamicMap, isMapsLibLoaded } from './MapboxMap';
// import { StaticMap, DynamicMap, isMapsLibLoaded } from './GoogleMap';
```
### 4. SearchMap.js
The most complex change is happening in SearchPage. First, you need to import `SearchMapWithMapbox`
instead of `SearchMapWithGoogleMap`.
_src/components/SearchMap/SearchMap.js:_
Remove this:
```js
import SearchMapWithMapbox, {
LABEL_HANDLE,
INFO_CARD_HANDLE,
getMapBounds,
getMapCenter,
fitMapToBounds,
isMapsLibLoaded,
} from './SearchMapWithMapbox';
```
And add this instead:
```js
import SearchMapWithGoogleMap, {
LABEL_HANDLE,
INFO_CARD_HANDLE,
getMapBounds,
getMapCenter,
fitMapToBounds,
isMapsLibLoaded,
} from './SearchMapWithGoogleMap';
```
Then, in `render` method, you need to put `SearchMapWithGoogleMap` component into use by replacing
`SearchMapWithMapbox` which is defined inside `ReusableMapContainer`. The component with correct
props is already there in the comments:
```js
// When changing from default map provider to Google Maps, you should use the following
// component instead of SearchMapWithMapbox:
//
// <SearchMapWithGoogleMap
// containerElement={
// <div id="search-map-container" className={classes} onClick={this.onMapClicked} />
// }
// mapElement={<div className={mapRootClassName || css.mapRoot} />}
// bounds={bounds}
// center={center}
// location={location}
// infoCardOpen={infoCardOpen}
// listings={listings}
// activeListingId={activeListingId}
// mapComponentRefreshToken={this.state.mapReattachmentCount}
// createURLToListing={this.createURLToListing}
// onListingClicked={this.onListingClicked}
// onListingInfoCardClicked={this.onListingInfoCardClicked}
// onMapLoad={this.onMapLoadHandler}
// onMapMoveEnd={onMapMoveEnd}
// zoom={zoom}
// />
```
The only extra step is to make `mapRootClassName` property available from `this.props` at the
beginning of the `render` method.
https://www.sharetribe.com/docs/guides/how-to-use-google-maps-in-ftw/

View file

@ -1,47 +1,5 @@
# Icons
The default icons are generated with [RealFaviconGenerator](https://realfavicongenerator.net/). You
can upload your original icon to the tool, customize the colors and themes, and download a generated
set if icons and an HTML snippet to point to those images.
Documentation moved to the Flex Docs site:
1. Open https://realfavicongenerator.net/
1. Upload your original icon image
1. Configure platform specific icons
**Note:** Remember to set the "Theme color" in the Android Chrome section
1. Configure the paths to use `/static/icons/` as the root path of the icons
1. Generate the icons
1. Unzip the favicons.zip archive and replace the default icons and files in
[public/static/icons/](../public/static/icons/) with the new icons
1. Replace the default HTML snippet in [public/index.html](../public/index.html) with the snippet
from the generator.
**Note:** Remove the manifest link from the snippet as we have a default manifest with extra
data compared to the generated one. You can edit the default file as you wish.
**Example HTML snippet:**
```html
<!-- Start Favicons from https://realfavicongenerator.net/ -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/icons/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/icons/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/icons/favicon-16x16.png">
<link rel="mask-icon" href="/static/icons/safari-pinned-tab.svg" color="#c0392b">
<link rel="shortcut icon" href="/static/icons/favicon.ico">
<meta name="msapplication-config" content="/static/icons/browserconfig.xml">
<meta name="theme-color" content="#c0392b">
<!-- End Favicons -->
```
## Map marker icon
The map marker icon in the listing can be found in
[src/components/Map/images/marker-32x32.png](../src/components/Map/images/marker-32x32.png). The
dimensions should be 32x32 pixels, so the `favicon-32x32.png` file can be used to replace the map
icon.
https://www.sharetribe.com/docs/guides/how-to-change-ftw-icons/

View file

@ -1,74 +1,5 @@
# Improving page rendering performance
When we think about page speed there are actually two different scenarios that we need to address:
Documentation moved to the Flex Docs site:
* The speed of initial page load and possible reloads after that
* The speed of changing the page within Single page application (SPA)
The first one is usually a slower process. A browser needs to load all the HTML, CSS, JavaScript,
and images - and then it needs to understand and execute those files, calculate layout, paint
components and finally composite the whole view. The initial page load is the slowest since the
consequent page reloads can take benefit from browser caches.
SPAs can improve from that since they don't necessarily need to download anymore JavaScript, HTML,
or CSS - already downloaded JavaScript might be enough for rendering consequent pages when a user
wants to navigate to another page. Most of the time SPAs just fetch data for that page.
These two UX scenarios might also conflict with each other. If all the JavaScript is in one big
bundle, page changes within a SPA are fast. However, downloading and evaluating a big JavaScript
file is slowing initial page rendering down. Even though users rarely experience the full initial
page load speed when they use an SPA like Flex Template for Web, it is good to keep track of that
speed. Especially since that is what search engine bots are experiencing and therefore it might
affect your page rank.
Read more about
[website performance](https://developers.google.com/web/fundamentals/performance/why-performance-matters/).
We haven't yet implemented code splitting to reduce initial page rendering time, but there're other
improvements that could be done to improve both cases of page rendering.
## Check page performance
The first step is, of course, to start measuring performance.
[Lighthouse](https://developers.google.com/web/tools/lighthouse/) is a good tool to check rendering
performance. At least check those pages that are visible to unauthenticated users (e.g. landing
page, search page, listing page, about page and other static pages).
Lighthouse will give you some tips about how to improve performance and other aspects that website
developers should think about.
## Optimize image sizes
If your page is showing images, you should check that the image size is not bigger than what is
needed. So, adjusting image dimensions is the first step, but you should also think about image
quality, advanced rendering options and possibly serving those images from CDN instead of from
within your web app.
Quick checklist:
* Check that the actual dimensions of an image match with DOM element's dimensions.
* Lighthouse suggests that image compression level should be 85% or lower.
[Read more](https://developers.google.com/web/tools/lighthouse/audits/optimize-images)
* Good rule-of-thumb is that use JPEG for images and photos, where PNG is better for graphics, such
as logos, graphs and illustrations.
* If you are using JPEG images, think about saving them as progressive JPEGs.
[Read more](https://cloudinary.com/blog/progressive_jpegs_and_green_martians) +
[Photoshop guide](https://helpx.adobe.com/photoshop-elements/using/optimizing-images-jpeg-format.html)
* If you are using PNG images, consider running them through PNG optimizers to reduce file size.
Plenty of options available, one example is [TinyPNG.com](https://tinypng.com)
* Think about serving images and other static assets from some CDN.
[Read more.](https://www.smashingmagazine.com/2017/04/content-delivery-network-optimize-images/)
## Lazy load off-screen images and other components
Another way of dealing with images is to lazy load those images that are not visible inside an
initially rendered part of the screen. Lazy loading these off-screen images can be done with helper
function: `lazyLoadWithDimensions` (from `util/contextHelpers/`). Check `SectionLocations` component
for details.
## Use sparse fields
Another way to reduce the amount of data that is fetched from API is sparse fields. This is a
relatively new feature and Flex template app has not yet leveraged it fully, but it is created to
reduce unnecessary data and speed up rendering. You can read more from
[Flex API docs](https://flex-docs.sharetribe.com/#sparse-attributes).
https://www.sharetribe.com/docs/guides/how-to-improve-performance/

View file

@ -1,70 +1,5 @@
# Integrating to map providers
Choice of map provider can significantly impact your costs. Flex Template for Web (FTW) originally
supported only [Google Maps](./google-maps.md) out of the box, but after Google increased the
pricing of its APIs a lot, the default provider was changed to Mapbox. The template now supports
both Mapbox and Google Maps, and the map library used by Mapbox is used also by several other map
providers, so integrating new providers that support this is rather easy (see instructions at the
end of this doc).
Documentation moved to the Flex Docs site:
## Setting up the Mapbox integration (the default map provider)
### 1. Generate a Mapbox access key
Sign up for a Mapbox and go to [account page](https://www.mapbox.com/account/). Then click
`Create access token`.
> Read more about
> [access tokens and consider rotating them](https://www.mapbox.com/help/how-access-tokens-work/).
### 2. Setup the application to use the access key
The application uses the `REACT_APP_MAPBOX_ACCESS_TOKEN` environment variable for the key value. For
local development, you can add the variable in the Gitignored `.env` file in the project root:
```
REACT_APP_MAPBOX_ACCESS_TOKEN=my-access-token-here
```
### 3. Setup common locations to reduce typing
The location autocomplete input in the landing page and the topbar can be configured to have
specific locations shown by default when the user focuses on the input and hasn't yet typed in any
searches. This reduces the typing required for common searches and also reduces the need to use
Mapbox geolocation API that much.
To use default searches, another environment variable needs to be set:
```
REACT_APP_DEFAULT_SEARCHES_ENABLED=true
```
The default locations are described in
[src/default-location-searches.js](../src/default-location-searches.js).
The same environment variable also shows "current location" suggestion, which will make the browser
to ask user's current location. This is a fast way to search listings nearby. You can specify
whether to use the current location from [config.js](../src/config.js). Search for variables:
`suggestCurrentLocation` and `currentLocationBoundsDistance`.
### 4. Check rare default configurations
Mapbox geocoding API doesn't always return bounding boxes for locations. Without bounding box
SearchMap component can't adjust zoom level right for that particular place. Therefore there are
default bounding boxes defined to different place types in
[Mapbox specific geocoder](../src/components/LocationAutocompleteInput/GeocoderMapbox.js).
## Changing the map providers
### How to change from Mapbox to Google Maps
It is possible to use Google Map instead of the default map provider. Read more from
[Google Map setup guide](./google-maps.md)
### How to use other map providers
The default map setup of FTW uses library called `mapbox-gl-js`. It is supported by quite many other
map providers too. Thus, if you wish to use a map provider other than Google Maps or Mapbox, first
check if the map provider you are considering is supporting this library. If they are, the change
might be quite easy. Note: if you change the map tile provider you should also change geocoding API
too (i.e. the API endpoint for `LocationAutocompleteInput` component).
https://www.sharetribe.com/docs/guides/how-to-set-up-mapbox-for-ftw/

5
docs/redux.md Normal file
View file

@ -0,0 +1,5 @@
# Redux configuration
Documentation moved to the Flex Docs site:
https://www.sharetribe.com/docs/background/ftw-redux/

5
docs/routing.md Normal file
View file

@ -0,0 +1,5 @@
# Routing
Documentation moved to the Flex Docs site:
https://www.sharetribe.com/docs/background/ftw-routing/

View file

@ -1,174 +1,5 @@
# Search filters
The search experience can be improved by adding search filters to narrow down the results. The
filters rely on listing's indexed data.
Documentation moved to the Flex Docs site:
## Filter types
The Flex template for web has two different filter types: _select single_ and _select multiple_. The
_select single_ one can be used to filter out search result with only one value per search
parameter. The _select multiple_ filters on the other hand can take multiple values for a single
search parameter.
These two filter types are implemented with four different components, a standard and a plain one:
* Select single filter: `SelectSingleFilter` and `SelectSingleFilterPlain`
* Select multiple filter: `SelectMultipleFilter` and `SelectMultipleFilterPlain`
The `SelectSingleFilter` and `SelectMultipleFilter` components are rendered as standard dropdowns in
the search view. The plain filter components `SelectSingleFilterPlain` and
`SelectMultipleFilterPlain` are used with `SearchFiltersMobile` and `SearchFiltersPanel` to provider
filters in mobile view or to open filters in a distinct panel in order to fit more filters to the
desktop search view.
## Adding a new search filter
Next we'll guide you through the steps of adding a _capacity_ filter to the marketplace.
First step for adding a new filter is to make sure that the data being used for filtering is saved
in the listing's `publicData` attribute. On how to achieve this, please refer to the
[documentation on extending the listing data model](./extend-listing.md). Another aspect in search
filters is that the public data needs to be indexed in the API. This is currently achieved with a
manual operation done by the Sharetribe support. Once a public data attribute is added to the
listings and the data attribute is indexed, the listing searches can be filtered by that attribute
by adding a query parameter that consists of a preceding "pub\_" and the attribute name, so for the
_capacity_ attribute the parameter would be "pub_capacity".
Further reading on public data can be found in the
[extended data documentation](./extended-data.md).
**NOTE:** Please contact the Sharetribe support in order to update your listing index schema when
planning to use new listing fields as search filters.
### Common changes
A few common changes are required to add a select single or a select multiple filter to desktop and
mobile views.
First of all, the value options for the filter need to be defined. One handy place to store these is
the `marketplace-custom-config.js` file. The correct format is a list of objects with `key` and
`label` fields:
```js
export const capacityOptions = [
{
key: 'oneToThree',
label: '1 to 3',
},
{
key: 'fourToSix',
label: '4 to 6',
},
...
];
```
A few changes need to be made to the `SearchPage` container in order to get the filters to work.
`SearchPage` needs the filter options. One handy way is to add the options as a prop to the
component and then set `defaultProps` value from `config.custom` (contains the
`marketplace-custom-config.js` exports). This way tests can pass in their own values for the filter
options and filter option changes won't affect tests.
```js
SearchPageComponent.defaultProps = {
// other default props
capacityOptions: config.custom.capacityOptions,
};
SearchPageComponent.propTypes = {
// other props
capacityOptions: array,
};
```
Also a filter configuration needs to be added to the object returned by the `filters` method. The
`filters` method combines query param name and options information of each filter so that those can
be passed on to subcomponents and used for validating the filter values and rendering the filter
components.
To add a filter configuration, extract the filter options from the props and set the param name as
the one defined in your extended data indexing configuration:
```js
filters() {
const { capacityOptions } = this.props;
return {
capacityFilter: {
paramName: 'pub_capacity',
options: capacityOptions,
},
...
};
}
```
Final thing to do in `SearchPage` is to pass the filters configuration on to the components that
take care of rendering the filters. This is achieved by `primaryFilters` and `secondaryFilters`
props that are passed to `MainPanel`. The configurations are passed as an object in the same form as
the configuration object in `filters`.
```js
<MainPanel
...
primaryFilters={{
categoryFilter: filters.categoryFilter,
amenitiesFilter: filters.amenitiesFilter,
}}
secondaryFilters={{
capacityFilter: filters.capacityFilter,
}}
/>
```
These props are used for resolving filter states and validating the filter values. The contents are
passed as props to the components that render the filters: `SearchFilters`, `SearchFiltersPanel` and
`SearchFiltersMobile` .The difference between filters passed as primary and secondary varies in
mobile and desktop views:
* **Desktop:** Primary filters are shown in the top of the search view, secondary filters are
rendered in a distinct panel that opens on top of search results.
* **Mobile:** Both primary and secondary filters are rendered in the same modal.
### Desktop filters
![Desktop filters](./assets/search-filters/desktop-filters.png)
A basic desktop filter that renders as a dropdown button on top of the search results panel is
achieved using the `SelectSingleFilter` and `SelectMultipleFilter` components. To add standard
desktop filters, perform the following in `SearchFilters` component:
* declare a prop with the same name that you added the filter config to `primaryFilters`
* resolve the filters initial value with `initialValue` and `initialValues` functions
* render the filter by using a `SelectSingleFilter` or `SelectMultipleFilter` component inside the
`<div className={css.filters}>` element
### Desktop filters panel
![Desktop filter panel](./assets/search-filters/filters-panel.png)
If more filters are required than can fit into the top filter bar, the `SearchFiltersPanel`
component can be used. It renders as a button in the top filter bar that opens a new panel that can
contain a set of filters.
To use the `SearchFiltersPanel`, do the following:
* declare a prop with the same name that you added the filter config to `secondaryFilters`
* resolve the filters initial value with `initialValue` and `initialValues` methods
* use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the
`<div className={css.filtersWrapper}>` element to render the filters
### Mobile filters
![Mobile filters](./assets/search-filters/mobile-filters.png)
The mobile view uses the same `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components
as the filter panel. In this case the filter components are declared in `SearchFiltersMobile`. The
following steps are required to add a mobile filter:
* declare a prop with the same name that you added the filter config to `primaryFilters` or
`secondaryFilters`
* resolve the filters initial value with `initialValue` and `initialValues` methods
* use the `SelectSingleFilterPlain` and `SelectMultipleFilterPlain` components inside the
`<div className={css.filtersWrapper}>` element to render the filters
https://www.sharetribe.com/docs/guides/how-to-change-search-filters-in-ftw/

View file

@ -1,38 +1,5 @@
# Error logging with Sentry
The Flex template application supports error logging with [Sentry](https://sentry.io/) out of the
box provided that required environment variables are set in place. Other logging solutions can also
be used but the Sentry client comes already strapped into application.
Documentation moved to the Flex Docs site:
## Setting up Sentry keys
To enable the Sentry error logging a DSN, _Data Source Name_ has to be provided as an environment
variable. Browser and Node environments both require their own keys. The key names are as follows:
* **SERVER_SENTRY_DSN** - the private Sentry DSN, used on the server side
* **REACT_APP_PUBLIC_SENTRY_DSN** - the public Sentry DSN, used in the browser
The DSN keys can be aquired from the Sentry project settings. To test them in your local environment
they can be passed for example to the `yarn run dev-server` command:
REACT_APP_PUBLIC_SENTRY_DSN='<public-sentry-dsn>' SERVER_SENTRY_DSN='<private-sentry-dsn>' yarn run dev-server
If the Sentry DSN keys are not provided the template app will log errors to the console. The logging
and Sentry setup is implemented in [util/log.js](../src/util/log.js) and
[server/log.js](../server/log.js) so refer to those files to change the external logging service or
the logging logic in general.
## Source map retrieval
By default Sentry fetches the source maps for minified javascript files. However, this might now
work in case some sort of authentication, e.g. basic auth, is required to reach your application. To
circumvent this a security token can be configured to Sentry. Sentry then adds this token to the
source maps request header so that the server hosting the marketplace can then be configured to let
those requests access the source maps.
For basic auth the security token can be configured as follows:
In _Project > Settings > General > Client Security_ set the following values
* **Security token** - `Basic <your username:password in Base 64>`
* **Security token header** - `Authorization`
https://www.sharetribe.com/docs/guides/how-to-set-up-sentry-to-log-errors-in-ftw/

View file

@ -1,258 +1,5 @@
# Static pages
If you want to create simple pages that just show static content without need for data fetches, you
can create a static page.
Documentation moved to the Flex Docs site:
Steps for creating a static page:
1. [Create a new folder under `src/containers/`](#1-creating-a-new-folder)
2. [Create a new JavaScript file using the same name.](#2-creating-a-javascript-file)
3. [Create a new CSS file using the same name.](#3-creating-a-css-file)
4. [Write the content to a JavaScript file (i.e. AboutPage.js in our example).](#4-creating-the-component)
5. [Write the style rules to CSS file (i.e. AboutPage.css in our example).](#5-adding-some-styles-to-the-css-file)
6. [Add the newly created page component to `src/containers/index.js`](#6-adding-the-component-to-the-component-directory)
7. [Add the newly created page to `src/routeConfiguration.js`](#7-adding-a-route-to-the-page)
## 1. Creating a new folder
Create a new folder under `src/containers/` with the name of your static page. E.g. "about" page
should be named as `AboutPage`.
## 2. Creating a JavaScript file
Create a new JavaScript file using the folder name. The path should look like
`src/containers/AboutPage/AboutPage.js`.
## 3. Creating a CSS file
Create a new CSS file using the folder name. The path should look like
`src/containers/AboutPage/AboutPage.css`.
## 4. Creating the component
Template for a single column static page (AboutPage.js): (We'll go through this line-by-line below.)
```jsx
import React from 'react';
import { StaticPage, TopbarContainer } from '../../containers';
import {
LayoutSingleColumn,
LayoutWrapperTopbar,
LayoutWrapperMain,
LayoutWrapperFooter,
Footer,
NamedLink,
ExternalLink,
} from '../../components';
import css from './AboutPage.css';
import image from './path/to/image.png';
const AboutPage = () => {
return (
<StaticPage
className={css.root}
title="About"
schema={{
'@context': 'http://schema.org',
'@type': 'AboutPage',
description: 'Description of this page',
name: 'About page',
}}
>
<LayoutSingleColumn>
<LayoutWrapperTopbar>
<TopbarContainer />
</LayoutWrapperTopbar>
<LayoutWrapperMain>
<h1>Some content</h1>
<img src={image} alt="My first ice cream." />
<div>
<NamedLink name="LandingPage">Go to home page</NamedLink> or
<ExternalLink href="https://google.com">Go to Google</ExternalLink>
</div>
</LayoutWrapperMain>
<LayoutWrapperFooter>
<Footer />
</LayoutWrapperFooter>
</LayoutSingleColumn>
</StaticPage>
);
};
export default AboutPage;
```
We are using [React](https://reactjs.org/) and [JSX](https://reactjs.org/docs/introducing-jsx.html)
to create components and pages. Therefore, we need to import React to our new component which is
done in the first line.
```jsx
import React from 'react';
```
In the second line we are importing two containers:
* `StaticPage`: helps in creating static pages
* `TopbarContainer`: creates our Topbar component and fetches the data it needs.
```jsx
import { StaticPage, TopbarContainer } from '../../containers';
```
After that we need to import some components:
* `LayoutSingleColumn` and wrappers that it needs to position content
* `Footer` component (to be added inside LayoutWrapperFooter)
* `NamedLink` makes it easier to point to different pages inside the application
* `ExternalLink` can be used to link outside the application. It creates a normal `<a>`link with
extra attributes `target="_blank" rel="noopener noreferrer"` that add some security to these
outbound links.
`LayoutSingleColumn` (and other layouts like LayoutSideNavigation) need to understand what the
content is about. Therefore, different parts of the page need to be wrapped with specific
components - in this case: `LayoutWrapperTopbar`, `LayoutWrapperMain`, and `LayoutWrapperFooter`.
```jsx
import {
LayoutSingleColumn,
LayoutWrapperTopbar,
LayoutWrapperMain,
LayoutWrapperFooter,
Footer,
NamedLink,
ExternalLink,
} from '../../components';
```
Then we need to import styles and possible other files from current folder. With CSS we are using
[CSS Modules](https://github.com/css-modules/css-modules) to tackle possible classhes of different
class names. [Read more.](#5-creating-the-css-file)
```jsx
import css from './AboutPage.css';
```
Then we also import an image which is used later (`<img src={image} alt="My first ice cream." />`).
```jsx
import image from './path/to/image.png';
```
Then after all the imports we are finally getting into phase were we define the component.
`const AboutPage = props => { return <div></div>}` defines a component called AboutPage with content
defined in return part. This is a
[functional component](https://reactjs.org/docs/components-and-props.html).
In the template above we are using StaticPage component with some attributes:
```jsx
<StaticPage
className={css.root}
title="About"
schema={{
"@context": "http://schema.org",
"@type": "AboutPage",
"description": "Description of this page",
"name": "About page",
}}
>
```
* `className` is JSX name for `class` attribute used in plain HTML.
* `title="About"` creates `<title>About</title>` element to `<head>` section of the page. (That
title is also used in OpenGraph meta tags). You could also add
`description="This is about page description"`
* Then we have `schema` tag that defines some data for search engines in JSON-LD format. Check
[schema.org](http://schema.org/docs/full.html) for more information.
Inside `StaticPage` component we define layout (`LayoutSingleColumn`) and add other components
inside semantic content wrappers so that the layout is able to understand where to render those
blocks.
```jsx
<LayoutSingleColumn>
<LayoutWrapperTopbar>
<TopbarContainer />
</LayoutWrapperTopbar>
<LayoutWrapperMain>
<h1>Some content</h1>
<img src={image} alt="My first ice cream." />
<div>
<NamedLink name="LandingPage">Go to home page</NamedLink> or
<ExternalLink href="https://google.com">Go to Google</ExternalLink>
</div>
</LayoutWrapperMain>
<LayoutWrapperFooter>
<Footer />
</LayoutWrapperFooter>
</LayoutSingleColumn>
```
And as a final step we need to export the component. `export default AboutPage;`. See more from
[babeljs.org](https://babeljs.io/learn-es2015/#ecmascript-2015-features-modules)
## 5. Adding some styles to the CSS file
Here's an example what your AboutPage.css file could look like:
```css
@import '../../marketplace.css';
.root {
padding: 24px;
/* Use CSS variable imported from marketplace.css */
background-color: var(--marketplaceColor);
}
```
## 6. Adding the component to the component directory
New component needs to be added to `src/containers/index.js` file or if it's a presentational
component (not page or form) it should be inside components folder and therefore added to
`src/components/index.js`
Inside that index.js you need to add line
`export { default as AboutPage } from './AboutPage/AboutPage';`. This helps other parts of the app
to import new components easily with `import { AboutPage } from '../../components'`.
## 7. Adding a route to the page
As a last step you need to add the newly created static page to the routing. This can be done in
`src/routeConfiguration.js`.
Inside routeConfiguration function you should add a URL path, a page name (it should not conflicting
with other pages), and the component itself.
Add it as first to the list of imported pages in alphabetical order (2nd line):
```jsx
import {
AboutPage,
AuthenticationPage,
CheckoutPage,
```
and after that add the route configuration to your newly created page: (In this example we created
about page so '/about' would work well as a path.)
```javascript
{
path: '/about',
name: 'AboutPage',
component: AboutPage,
},
```
## Read more
We are using several libraries in this example. If you want to read more, here's some pointers:
* [ES2015](https://babeljs.io/learn-es2015/): imports, exports, arrow functions
* [React](https://reactjs.org/): for creating components
* [JSX](https://reactjs.org/docs/introducing-jsx.html): for getting HTML-like markup syntax for own
components
* [CSS Modules](https://github.com/css-modules/css-modules)
* [React Router](https://reacttraining.com/react-router/web/guides/philosophy): routing inside the
application.
https://www.sharetribe.com/docs/guides/how-to-add-static-pages-in-ftw/

View file

@ -1,275 +1,5 @@
# Flex Template for Web: styling
The goal for creating styling for Flex template app was to keep styling as close as possible to
plain CSS while still trying to avoid the mess that comes along with globally defined cascading
behavior that CSS is all about.
Documentation moved to the Flex Docs site:
To tackle this goal, we have split the styling into two levels in this template application:
* [Marketplace level styling](#marketplace-level-styling) through _marketplace.css_ (a kind of
global theme)
* [Component level styling](#styling-components) using
[CSS Modules](https://github.com/css-modules/css-modules)
## Marketplace level styling
On top of functionalities provided by Create React App, we have
[added a couple of extra libraries](https://www.npmjs.com/package/sharetribe-scripts#differences-to-react-scripts)
to help to design consistent UIs faster. CSS Properties and CSS Property Sets are very useful for
all kind of style sharing purposes, and we have created marketplace-level styling variables with
them.
The concept behind CSS Properties is quite straightforward - they are variables that can be defined
in root-element level and then used inside some CSS rule.
```css
:root {
--marketplaceColor: #ffff00;
}
.linkToHomePage {
color: var(--marketplaceColor);
}
```
(Read more about CSS Properties from [cssnext](http://cssnext.io/))
We have used this concept to create a marketplace-level "theming" that's defined in three files:
_src/marketplace.css_, _src/marketplaceFonts.css_, and _marketplaceIndex.css_.
### marketplace.css
This is a good place to start customizing marketplace styles. For example, we define our color
scheme here using CSS Property variables:
```css
/* ================ Colors ================ */
--marketplaceColor: #c0392b;
--marketplaceColorLight: #ff4c38;
--marketplaceColorDark: #8c291e;
/* Used with inline CSS SVGs */
--marketplaceColorEncoded: %23c0392b;
--successColor: #2ecc71;
--successColorDark: #239954;
--failColor: #ff0000;
--attentionColor: #ffaa00;
--matterColorDark: #000000;
--matterColor: #4a4a4a;
--matterColorAnti: #b2b2b2;
--matterColorNegative: #e7e7e7;
--matterColorBright: #fcfcfc;
--matterColorLight: #ffffff;
```
Changing `--marketplaceColor: #c0392b;` to `--marketplaceColor: tomato;` will change the default
marketplace color to tomato color. (It's a certain kind of red color.)
The `--marketplaceColorEncoded` variable holds the same value as `--marketplaceColor` but with the
_#_ URL encoded. This value can be used to maintain a consistent color scheme with inline SVG icons.
`--successColor` (green) is used in form inputs for showing that the input value is valid.
Sometimes, submit buttons (`<PrimaryButton>`) are also using that color to highlight the fact that
user has entered valid information to the form at hand.
Similarly `--failColor` is used to style errors and `--attentionColor` is used to draw user's
attention to certain UI components (e.g. required form inputs, or important info in Inbox)
Our greyscale colors (for borders and background colors) are named with prefix _"matter"_.
Similar pattern is also used to create more consistent UI components by providing variables for
box-shadows, border-radiuses, transitions, and so on. Our current plan is to parameterize styling
even more using this concept.
Breakpoints for media queries are also defined in this file:
```css
/* ================ Custom media queries ================ */
@custom-media --viewportMedium (min-width: 768px);
@custom-media --viewportLarge (min-width: 1024px);
@custom-media --viewportXLarge (min-width: 1921px);
```
### marketplaceFonts.css
Fonts are specified in this files using CSS Property Sets. They provide us a solid way of creating a
fixed set of CSS rules for a specific font.
For example, our default font is defined as:
```css
--fontWeightMedium: 500;
--marketplaceDefaultFontStyles: {
font-family: 'sofiapro', Helvetica, Arial, sans-serif;
font-weight: var(--fontWeightMedium);
font-size: 18px;
line-height: 24px;
letter-spacing: -0.1px;
@media (--viewportMedium) {
font-size: 20px;
line-height: 24px;
}
}
```
And created property set can be used as:
```css
p {
@apply --marketplaceDefaultFontStyles;
}
```
_marketplaceFonts.css_ are included to _marketplace.css_, so you don't need to import this file on
new components (importing _marketplace.css_ is enough).
⚠️ NOTE: template app is following a pattern where the height of an element should be divisible by
`6px` on mobile layout and `8px` on bigger layouts. This affects line-heights of font styles too.
⚠️ NOTE: the `@apply` rule and custom property sets most likely won't get any more support from
browser vendors as the spec is yet considered deprecated and alternative solutions are being
discussed. However, template app will use these until a good enough alternative is available.
### marketplaceIndex.css
This file provides default styles for plain elements like `<body>`, `<a>`, `<p>`, `<input>`, `<h1>`,
`<h2>`, and so on.
## Styling components
Styling a web UI is traditionally quite a messy business due to the global nature of stylesheets and
especially their cascading specificity rule. `.card {/*...*/}` will affect every element on a web
page that has a class `card` - even if the different UI context would like to use a different set of
rules.
Our goal has been to create independent components that can be reused in the UI without paying too
much attention to the global CSS context. To achieve this, we have used
[CSS Modules](https://github.com/css-modules/css-modules), which keeps the syntax close to plain
CSS, but it actually creates unique class names to remove the problems caused by the global nature
of CSS. In practice, this means that a class with name `card` is actually renamed as
`ComponentName__card__3kj4h5`.
To use styles defined in SectionHero.css, we need to import the .css file into the component:
```jsx
import css from './SectionHero.css';
```
and then select the correct class from imported style object (in this case `heroMainTitle`):
```jsx
<h1 className={css.heroMainTitle}>Book saunas everywhere</h1>
```
### Find the component to change its styles
Quite often one needs to find a component that is responsible for certain UI partial in order to
change the styles. In this case, the easiest way to pinpoint a component is to open the inspector
from browser's dev tools. (Right-click on top of the correct element, and select _Inspector_, or
something of the sort depending on the browser, from the context menu.)
![Mobile LandingPage hero title](./assets/styling/styling-find-component.png)
Here we have opened title on LandingPage and the styles for
`<h1 class="SectionHero__heroMainTitle__3mVNg"><span>Book saunas everywhere.</span></h1>` are
defined in a "class" called `SectionHero__heroMainTitle__3mVNg`. As stated before, the first part of
a class name is actually giving us a hint about what component is defining that style - in this
case, it's _SectionHero_ and its styles can be found from the file:
`src/components/SectionHero/SectionHero.css`.
There's only two groups of components that break that rule:
* _src/containers_ (These components are connected to Redux store: Pages and TopbarContainer)
* _src/forms_
### Styling guidelines and good practices
We have a practice of naming the outermost class of a component as `.root { /* styles */ }`. So, if
the component is just rendering single element it only has `.root` class, and if there's more
complex inner DOM structure needed, additional classes are named semantically.
`<SectionHero>` could contain classes named as `.root`, `.heroMainTitle`, `.heroSubtitle`.
Some guidelines we have tried to follow:
* **Use semantic class names** (They improve readability and decouples style changes from DOM
changes.)
* **Use CSS Properties defined in marketplace.css** and create new ones when it makes sense.
* **Use classes**, don't style DOM elements directly. (Element styles are global even with CSS
Modules.)
* **Avoid nesting styles**. (CSS Modules makes specificity rules unnecessary.)
* **Group and comment style rules** inside declaration block if that improves readability.
* **Parent component is responsible for allocating space** for a child component (i.e. dimensions
and margins).
* **Define `@apply` rules early enough** inside declaration block (since rules inside those property
sets might overwrite rules written above the line where the set is applied).
* **Align text and components** to horizontal baselines. I.e. they should be a multiple of `6px` on
mobile layout and `8px` on bigger screens.
* **Component height should follow baselines too**. I.e. they should be a multiple of `6px` on
mobile layout and `8px` on bigger screens. _(Unfortunately, we haven't been strict with this
one.)_
### Styling responsibility: parent component and its children
One important aspect of a component-based UI is the fact that a component is usually only
responsible for what happens inside its outermost element boundary. In parent-child context this
means that the parent component is responsible for its own layout and therefore it usually needs to
be able to give some dimensions to its child components (and naturally margins between them).
This creates a need for the parent to have means to pass `className` to its child as props. One
example could be a component that shows a circle component inside itself and makes it 50px wide.
Style definitions of the (`<Circle />`) child component:
```css
.root {
background-color: tomato;
border-radius: 50%;
}
```
Parent component renders
(`<div className={css.root}><Circle className={css.circleDimensions} /></div>`):
```css
.root {
min-width: 60px;
min-height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.circleDimensions {
flex-grow: 0;
width: 50px;
height: 50px;
margin: 5px;
}
```
Sometimes the child component needs to be styled even further than just allocating space to it. If
the parent component wants to change the theme of child component there are generally two concepts
available:
* Create themed components (e.g. `<PrimaryButton>`, `<SecondaryButton>`, `<InlineButton>`)
* Pass in a `class` property that is able to overwrite original styling rules.
For the latter option, we have created a prop type concept called `rootClassName`. If you pass
`rootClassName` through props to a component, it will use that instead of component's own style
rules defined in `.root`. This ensures that the order of style declarations inside final CSS bundle
doesn't affect the final styles. (CSS bundle is generated in an import order, therefore we want to
avoid situations where `<Component className="classA classB"/>` could end up overwriting each others
depending on the order they are imported.)
In some complex cases, we have also created props for overwriting some inner classes of child
components. In these cases, child component is also replacing its own styling class with the class
passed-in through props. For example, `<LocationAutocompleteInput>` can take a prop called
`iconClassName`, which (if given) replaces `.icon` class defined inside
`LocationAutocompleteInput.css`.
https://www.sharetribe.com/docs/guides/how-to-customize-ftw-styles/

View file

@ -1,16 +1,5 @@
# Terms of Service and Privacy Policy
The Terms of Service and Privacy Policy of a marketplace are static components that can be edited to
suit the marketplace.
Documentation moved to the Flex Docs site:
## Terms of Service
Edit
[src/components/TermsOfService/TermsOfService.js](../src/components/TermsOfService/TermsOfService.js)
file to customize the default dummy content.
## Privacy Policy
Edit
[src/components/PrivacyPolicy/PrivacyPolicy.js](../src/components/PrivacyPolicy/PrivacyPolicy.js)
file to customize the default dummy content.
https://www.sharetribe.com/docs/guides/how-to-change-tos-and-privacy-policy-in-ftw/

View file

@ -1,30 +1,5 @@
# Testing Flex template for the web
# Testing Flex Template for Web
The test setup is based on the `create-react-app` test setup and is using the
[Jest testing framework](https://facebook.github.io/jest/). See the
[Testing Components](create-react-app.md#testing-components) and
[Experimental Snapshot Testing](create-react-app.md#experimental-snapshot-testing) sections in the
`create-react-app` documentation.
Documentation moved to the Flex Docs site:
## Running tests
To start the test watcher that automatically updates when files change, run
yarn test
If you want to run the tests once and not start the watcher, run
CI=true yarn test
Note that this also runs the linter.
## Jest
To learn more about testing with Jest, read the following documentation:
* [Getting Started](https://facebook.github.io/jest/docs/getting-started.html)
* [Tutorial - React](https://facebook.github.io/jest/docs/tutorial-react.html)
* [Tutorial - Async](https://facebook.github.io/jest/docs/tutorial-async.html)
* [Snapshot Testing](https://facebook.github.io/jest/blog/2016/07/27/jest-14.html) blog post
* [API Reference](https://facebook.github.io/jest/docs/api.html) lists the global environment with
the available functions and the assertion matchers
https://www.sharetribe.com/docs/guides/how-to-test-ftw/

View file

@ -1,144 +1,5 @@
# Translations
The Flex template for web supports having a single language for the UI. By default the language is
English.
Documentation moved to the Flex Docs site:
We are using the [React Intl](https://github.com/yahoo/react-intl) library to translate UI texts and
to format dates, numbers, and money values.
## The translation file
All the text translations can be found in the
[src/translations/en.json](../src/translations/en.json) file. The translation data is formatted as
one JSON object with all the translations as properties.
The key - value syntax is as follows:
```
"<component name>.<translation key>": "<translation>"
```
For example:
```
"ManageListingCard.viewListing": "View listing"
```
The keys are namespaced to the corresponding component. This is aligned with the component driven
paradigm that the application follows. It might introduce duplication with same translation texts
occurring multiple times in the translation file but it also emphasizes how all the components are
independent, how a component can be used anywhere and how modifications to a single component do not
affect other components.
## Using the translations
React Intl provides multiple ways to access the translation data but the most commonly used are the
`formatMessage` function and the `FormattedMessage` tag provided by React Intl.
To use the `formatMessage` function, component needs to be wrapped with the `injectIntl` function
which provides a render prop called `intl`. `intl` then provides all the React Intl translation
functions, like `formatMessage`:
```js
import { intlShape, injectIntl } from 'react-intl';
const SomeComponent = props => {
const { intl } = props;
const translation = intl.formatMessage({ id: 'SomeComponent.someKey' });
// ...
};
SomeComponent.propTypes = {
// from injectIntl
intl: intlShape.isRequired,
};
export default injectIntl(SomeComponent);
```
As for the `FormattedMessage` it just needs to be imported from `react-intl` and it takes the id
prop:
```
<FormattedMessage id="SomeCompoennt.someKey" />
```
Other functions and componets can be explored in the
[React Intl documentation](https://github.com/yahoo/react-intl/wiki).
## Formatting
React Intl uses the [FormatJS](https://formatjs.io/) formatters for shaping the translation texts
based on given arguments. Here are a few examples on how to use FormatJS.
### Arguments
Pass a named argument to the format function/component. For the following translation:
```js
"EnquiryForm.messageLabel": "Message to {authorDisplayName}",
```
Pass the author data in the `FormattedMessage` component:
```js
<FormattedMessage id="EnquiryForm.messageLabel" values={{ authorDisplayName: 'Jane D' }} />
```
Or the the `formatMessage` function:
```js
intl.formatMessage({ id: 'EnquiryForm.messageLabel' }, { authorDisplayName: 'Jane D' });
```
### Pluralization
With pluralization a translation can be formatted to adapt to a number argument.
```js
"ManageListingsPage.youHaveListings": "You have {count} {count, plural, one {listing} other {listings}}",
```
This translation takes the `count` argument and uses the `plural`, `one` and `other` keywords to
format the last word of the translation to be _listing_ or _listings_ based on the `count`. The
pluralized translation can be used with the `FormattedMessage` component:
```js
<FormattedMessage id="ManageListingsPage.youHaveListings" values={{ count: 3 }} />
```
Or with the `formatMessage` function:
```js
intl.formatMessage({ id: 'ManageListingsPage.youHaveListings' }, { count: 1 });
```
More formatting examples can be found from the
[FormatJS message syntax documentation](https://formatjs.io/guides/message-syntax/).
## Texts outside the translation file
A few components in the template app contain texts that are not included in the `en.json` file,
namely `AboutPage`, `PrivacyPolicy`, and `TermsOfService`. The reason behind this is that these
components only contain static content that is laid out in more of a document format so the
translations for these texts can easily be changed and maintained in the component files themselves.
More information about adding static content to the application can be found from
[the static pages documentation](./static-pages.md).
## Changing the language
For changing the language of the template application:
1. Copy the default [src/translations/en.json](../src/translations/en.json) English translations
file into some other file like `es.json`.
1. Change the messages in the new translations file to the desired language.
1. In [src/config.js](../src/config.js), change the `locale` variable value to match the new locale
(the name of the new translations file, without the extension).
1. In [src/app.js](../src/app.js), change the translation imports to point to the correct
`react-intl` locale and the new translations file you created.
https://www.sharetribe.com/docs/guides/how-to-change-ftw-ui-texts-and-translations/

View file

@ -1,7 +1,7 @@
# Mail templates
This directory contains the default templates for all mails sent by default as result of activity in
the marketplace.
This directory contains the default templates for transaction emails. Built-in email templates can
be edited in Console.
Before making customizations, copy the templates to another directory (e.g. `mail-templates`). Note
that, at present, changes made to the template files in this repository will not take effect
@ -9,15 +9,14 @@ automatically. Marketplace owner needs to notify the Sharetribe team.
## Template parts
A template consists of three files:
A template consists of two files:
* `TEMPLATE_NAME-subject.txt` - holds the mail Subject line template
* `TEMPLATE_NAME-text.txt` - holds the template for the plain text version of the mail
* `TEMPLATE_NAME-html.html` - contains the template for the HTML version of the mail
- `TEMPLATE_NAME-subject.txt` - holds the mail Subject line template
- `TEMPLATE_NAME-html.html` - contains the template for the HTML version of the mail
All the parts are mandatory. All emails that are sent from the marketplace contain both the plain
text and HTML variants and the recipient's mail client is free to choose which one to visualize and
how.
Both parts are mandatory. All emails that are sent from the marketplace contain both the HTML and
plain text variants and the recipient's mail client is free to choose which one to visualize and
how. The text version is automatically generated from the HTML template.
## Template syntax
@ -35,23 +34,17 @@ Example html:
<p>If you didn&#x27;t make this change, please contact us.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
<hr />
<p>
You have received this email notification because you are a member of {{marketplace.name}}. If
you no longer wish to receive these emails, please contact {{marketplace.name}} team.
</p>
</body>
</html>
```
Example text version:
```
Hello {{recipient.first-name}},
Your {{marketplace.name}} account's email address was changed.
If you didn't make this change, please contact us.
Best regards,
The {{marketplace.name}} team
```
Variables within `{{ }}` are expanded and escaped, so that they are safe to place inside HTML
content. As seen above, some variables have nested values, which can be accessed with dot `.`
operator.
@ -61,41 +54,6 @@ The template syntax supports conditionals, loops, helpers and other constructs.
## List of templates
### Built-in event mails
#### email-changed
Sent to a user when their registered email address has been successfully changed.
#### new-message
Sent to a user when the other party in a transaction has sent them a new message.
#### password-changed
Sent to a user when their account's password was successfully changed.
#### reset-password
Sent to a user when a request for resetting their password is received. The mail contains a link
with password reset token and instructs the user to complete the password reset.
#### verify-changed-email-address
Sent to a user when they have requested to change their registered email address. The mail contains
an email verification link and instructs the user how to verify their email address.
#### verify-email-address
Sent to a user after they sign up for an account in the marketplace and instructs them to verify
their email address.
#### user-joined
Sent to a new marketplace user after they verify their email address.
### Transaction engine mails
The templates in the list below correspond to mails defined in the default transaction process.
Customized transaction processes can have different set of mail templates.

View file

@ -23,14 +23,14 @@
</tr>
</thead>
<tbody>
{{#each line-items}}
{{#each tx-line-items}}
{{#contains include-for "customer"}}
<tr>
{{#eq "day" code}}
{{#eq "line-item/day" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "day" "days"}}</td>
<td style="padding-left: 20px;">{{> format-money money=line-total}}</td>
{{/eq}}
{{#eq "night" code}}
{{#eq "line-item/night" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "night" "nights"}}</td>
<td style="padding-left: 20px;">{{> format-money money=line-total}}</td>
{{/eq}}
@ -47,5 +47,9 @@
</table>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,30 +0,0 @@
{{~#*inline "format-money"~}}
{{money-amount money}} {{money.currency}}
{{~/inline~}}
{{~#*inline "format-date"~}}
{{date date format="MMM d, YYYY"}}
{{~/inline~}}
Your booking request was accepted!
{{#with transaction~}}
{{provider.display-name}} has accepted your booking request for {{listing.title}} from {{> format-date date=booking.start}} to {{> format-date date=booking.end}}.
We have charged {{> format-money money=payin-total}} from your credit card. Here's your receipt.
Payment
{{#each line-items~}}
{{~#contains include-for "customer"~}}
{{~#eq "day" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "day" "days"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~#eq "night" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "night" "nights"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~/contains~}}
{{/each~}}
Payment total: {{> format-money money=payin-total}}
{{~/with}}

View file

@ -12,5 +12,9 @@
{{/with}}
<p><a href="{{marketplace.url}}">Try to book something else instead</a></p>
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,12 +0,0 @@
{{~#*inline "format-date"~}}
{{date date format="MMM d, YYYY"}}
{{~/inline~}}
Your booking request has expired.
{{#with transaction~}}
Unfortunately {{provider.display-name}} didn't respond to your booking request for {{listing.title}} from {{> format-date date=booking.start}} to {{> format-date date=booking.end}} on time, so the request has expired. You have not been billed.
{{~/with}}
Try to book something else instead: {{marketplace.url}}

View file

@ -12,5 +12,9 @@
{{/with}}
<p><a href="{{marketplace.url}}">Try to book something else instead</a></p>
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,12 +0,0 @@
{{~#*inline "format-date"~}}
{{date date format="MMM d, YYYY"}}
{{~/inline~}}
Your booking request was declined.
{{#with transaction~}}
Unfortunately {{provider.display-name}} decided to decline your booking request for {{listing.title}} from {{> format-date date=booking.start}} to {{> format-date date=booking.end}}. You have not been billed.
{{~/with}}
Try to book something else instead: {{marketplace.url}}

View file

@ -1,11 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>Your <em>{{marketplace.name}}</em> account&#x27;s email address was changed.</p>
<p>If you didn&#x27;t make this change, please contact us.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
{{marketplace.name}} email address changed

View file

@ -1,8 +0,0 @@
Hello {{recipient.first-name}},
Your {{marketplace.name}} account's email address was changed.
If you didn't make this change, please contact us.
Best regards,
The {{marketplace.name}} team

View file

@ -23,20 +23,20 @@
</tr>
</thead>
<tbody>
{{#each line-items}}
{{#each tx-line-items}}
{{#contains include-for "provider"}}
<tr>
{{#eq "day" code}}
{{#eq "line-item/day" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "day" "days"}}</td>
<td style="text-align: right; padding-left: 20px">{{> format-money money=line-total}}</td>
{{/eq}}
{{#eq "night" code}}
{{#eq "line-item/night" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "night" "nights"}}</td>
<td style="text-align: right; padding-left: 20px">{{> format-money money=line-total}}</td>
{{/eq}}
{{#eq "provider-commission" code}}
{{#eq "line-item/provider-commission" code}}
<td>{{marketplace.name}} fee:</td>
<td style="text-align: right; padding-left: 20px;">{{> format-money money=line-total}}</td>
{{/eq}}
@ -53,5 +53,9 @@
</table>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,32 +0,0 @@
{{~#*inline "format-money"~}}
{{money-amount money}} {{money.currency}}
{{~/inline~}}
{{~#*inline "format-date"~}}
{{date date format="MMM d, YYYY"}}
{{~/inline~}}
{{#with transaction~}}
You have been paid {{> format-money money=payout-total}}
We have sent you {{> format-money money=payout-total}} for the booking of {{listing.title}} from {{> format-date date=booking.start}} to {{> format-date date=booking.end}} by {{customer.display-name}}. It might take up to 7 days for the money to reach your bank account.
Here's the breakdown.
Payment
{{#each line-items~}}
{{~#contains include-for "provider"~}}
{{~#eq "day" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "day" "days"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~#eq "night" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "night" "nights"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~#eq "provider-commission" code~}}
{{marketplace.name}} fee: {{> format-money money=line-total}}
{{/eq~}}
{{~/contains~}}
{{/each~}}
You earn: {{> format-money money=payout-total}}
{{~/with}}

View file

@ -21,20 +21,20 @@
</tr>
</thead>
<tbody>
{{#each line-items}}
{{#each tx-line-items}}
{{#contains include-for "provider"}}
<tr>
{{#eq "day" code}}
{{#eq "line-item/day" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "day" "days"}}</td>
<td style="text-align: right; padding-left: 20px">{{> format-money money=line-total}}</td>
{{/eq}}
{{#eq "night" code}}
{{#eq "line-item/night" code}}
<td>{{> format-money money=unit-price}} &times; {{number quantity}} {{inflect quantity "night" "nights"}}</td>
<td style="text-align: right; padding-left: 20px">{{> format-money money=line-total}}</td>
{{/eq}}
{{#eq "provider-commission" code}}
{{#eq "line-item/provider-commission" code}}
<td>{{marketplace.name}} fee:</td>
<td style="text-align: right; padding-left: 20px;">{{> format-money money=line-total}}</td>
{{/eq}}
@ -55,5 +55,9 @@
<p><a href="{{marketplace.url}}/sale/{{url-encode id}}/details">Accept or decline the booking</a></p>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,35 +0,0 @@
{{~#*inline "format-money"~}}
{{money-amount money}} {{money.currency}}
{{~/inline~}}
{{~#*inline "format-date"~}}
{{date date format="MMM d, YYYY"}}
{{~/inline~}}
{{#with transaction~}}
Please respond to a request by {{customer.display-name}}
Good news! {{customer.display-name}} just requested to book {{listing.title}} from {{> format-date date=booking.start}} to {{> format-date date=booking.end}}. Here's the breakdown.
Payment
{{#each line-items~}}
{{~#contains include-for "provider"~}}
{{~#eq "day" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "day" "days"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~#eq "night" code~}}
{{> format-money money=unit-price}} x {{number quantity}} {{inflect quantity "night" "nights"}}: {{> format-money money=line-total}}
{{/eq~}}
{{~#eq "provider-commission" code~}}
{{marketplace.name}} fee: {{> format-money money=line-total}}
{{/eq~}}
{{~/contains~}}
{{/each~}}
You earn: {{> format-money money=payout-total}}
You need to accept the request by {{> format-date date=delayed-transition.run-at}}. Otherwise the request will be expired and you won't get paid. If the booked dates won't work for you, you can also choose to decline the request.
Accept or decline the booking: {{marketplace.url}}/sale/{{url-encode id}}/details
{{~/with}}

View file

@ -1,19 +0,0 @@
<html>
<body>
{{#with message}}
<h1>You have a new message from {{sender.display-name}}</h1>
<blockquote>"{{content}}"</blockquote>
{{#eq recipient-role "customer"}}
<p><a href="{{marketplace.url}}/order/{{url-encode transaction.id}}/details">Reply to {{sender.display-name}}</a></p>
{{/eq}}
{{#eq recipient-role "provider"}}
<p><a href="{{marketplace.url}}/sale/{{url-encode transaction.id}}/details">Reply to {{sender.display-name}}</a></p>
{{/eq}}
{{/with}}
</body>
</html>

View file

@ -1 +0,0 @@
{{message.sender.display-name}} has sent you a new message

View file

@ -1,15 +0,0 @@
{{#with message~}}
You have a new message from {{sender.display-name}}
"{{content}}"
{{#eq recipient-role "customer"~}}
Reply to {{sender.display-name}}: {{marketplace.url}}/order/{{url-encode transaction.id}}/details
{{/eq~}}
{{#eq recipient-role "provider"~}}
Reply to {{sender.display-name}}: {{marketplace.url}}/sale/{{url-encode transaction.id}}/details
{{/eq~}}
{{~/with}}

View file

@ -1,11 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>Your <em>{{marketplace.name}}</em> account&#x27;s password was changed.</p>
<p>If you didn&#x27;t make this change, please contact us.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
{{marketplace.name}} password changed

View file

@ -1,8 +0,0 @@
Hello {{recipient.first-name}},
Your {{marketplace.name}} account's password was changed.
If you didn't make this change, please contact us.
Best regards,
The {{marketplace.name}} team

View file

@ -1,15 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>You have indicated that you have forgotten your password for <em>{{marketplace.name}}</em>. Click the following link to reset your password:</p>
<p><a href="{{marketplace.url}}/reset-password?t={{form-encode password-reset.token}}&e={{form-encode password-reset.email-address}}">{{marketplace.url}}/reset-password?t={{form-encode password-reset.token}}&e={{form-encode password-reset.email-address}}</a></p>
<p>If you don't use this link within 1 hour, it will expire. You can request a new password reset link, if you need to.</p>
<p>If you didn't request this, please ignore this email. Your password won't be changed until you use the link above to set a new one.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
Password reset instructions for {{marketplace.name}}

View file

@ -1,12 +0,0 @@
Hello {{recipient.first-name}},
You have indicated that you have forgotten your password for {{marketplace.name}}. Click the following link to reset your password:
{{marketplace.url}}/reset-password?t={{form-encode password-reset.token}}&e={{form-encode password-reset.email-address}}
If you don't use this link within 1 hour, it will expire. You can request a new password reset link, if you need to.
If you didn't request this, please ignore this email. Your password won't be changed until you use the link above to set a new one.
Best regards,
The {{marketplace.name}} team

View file

@ -7,5 +7,8 @@
<p><a href="{{marketplace.url}}/order/{{url-encode id}}/details">Leave a review</a></p>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,9 +0,0 @@
{{~#with transaction~}}
How was your experience with {{listing.title}}? Write a review!
You recently booked {{listing.title}} from {{provider.display-name}}. Please write a review to describe your experience. Reviews are important part of the {{marketplace.name}} community.
Leave a review: {{marketplace.url}}/order/{{url-encode id}}/details
{{~/with~}}

View file

@ -15,5 +15,9 @@
<a href="{{marketplace.url}}/u/{{url-encode recipient.id}}">View your profile.</a>
</p>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,14 +0,0 @@
{{~#with transaction~}}
{{other-party.display-name}} wrote you a review. Here's what they wrote.
{{#each reviews~}}
{{#eq recipient.id subject.id}}"{{content}}"{{/eq}}
{{~/each}}
The review has been published on your {{marketplace.name}} profile.
View your profile: {{marketplace.url}}/u/{{url-encode recipient.id}}
{{~/with~}}

View file

@ -9,5 +9,9 @@
<a href="{{marketplace.url}}/{{#eq recipient-role "customer"}}order{{else}}sale{{/eq}}/{{url-encode id}}/details">Leave a review</a>
</p>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,10 +0,0 @@
{{~#with transaction~}}
Find out what {{other-party.display-name}} wrote!
{{other-party.display-name}} has left you a new review. To see what they wrote, please leave them a review to describe your experience.
Leave a review: {{marketplace.url}}/{{#eq recipient-role "customer"}}order{{else}}sale{{/eq}}/{{url-encode id}}/details
{{~/with~}}

View file

@ -7,5 +7,9 @@
<p><a href="{{marketplace.url}}/sale/{{url-encode id}}/details">Leave a review</a></p>
{{/with}}
<hr />
<p>You have received this email notification because you are a member of {{marketplace.name}}. If you no longer wish to receive these emails, please contact {{marketplace.name}} team.</p>
</body>
</html>
</html>

View file

@ -1,9 +0,0 @@
{{~#with transaction~}}
How was your experience with {{customer.display-name}}? Write a review!
{{customer.display-name}} recently booked {{listing.title}} from you. Please write {{customer.display-name}} a review to describe your experience. Reviews are important part of the {{marketplace.name}} community.
Leave a review: {{marketplace.url}}/sale/{{url-encode id}}/details
{{~/with~}}

View file

@ -1,9 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>Welcome to <em>{{marketplace.name}}</em>!</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
Welcome to {{marketplace.name}}

View file

@ -1,6 +0,0 @@
Hello {{recipient.first-name}},
Welcome to {{marketplace.name}}!
Best regards,
The {{marketplace.name}} team

View file

@ -1,15 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>To complete your email address change in <em>{{marketplace.name}}</em>, verify your email by clicking the link below:</p>
<p><a href="{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}">{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}</a></p>
<p>Alternatively, you can copy the link to your browser's address bar.</p>
<p>If you don't use this link within 2 days, it will expire. You can request a new verification link, if you need to.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
Email verification instructions for {{marketplace.name}}

View file

@ -1,12 +0,0 @@
Hello {{recipient.first-name}},
To complete your email address change in {{marketplace.name}}, verify your email by clicking the link below:
{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}
Alternatively, you can copy the link to your browser's address bar.
If you don't use this link within 2 days, it will expire. You can request a new verification link, if you need to.
Best regards,
The {{marketplace.name}} team

View file

@ -1,15 +0,0 @@
<html>
<body>
<p>Hello {{recipient.first-name}},</p>
<p>To complete your signup to <em>{{marketplace.name}}</em>, verify your email by clicking the link below:</p>
<p><a href="{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}">{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}</a></p>
<p>Alternatively, you can copy the link to your browser's address bar.</p>
<p>If you don't use this link within 2 days, it will expire. You can request a new verification link, if you need to.</p>
<p>Best regards,<br />The {{marketplace.name}} team</p>
</body>
</html>

View file

@ -1 +0,0 @@
Email verification instructions for {{marketplace.name}}

View file

@ -1,12 +0,0 @@
Hello {{recipient.first-name}},
To complete your signup to {{marketplace.name}}, verify your email by clicking the link below:
{{marketplace.url}}/verify-email?t={{form-encode email-verification.token}}
Alternatively, you can copy the link to your browser's address bar.
If you don't use this link within 2 days, it will expire. You can request a new verification link, if you need to.
Best regards,
The {{marketplace.name}} team

View file

@ -1,90 +1,115 @@
{
"name": "app",
"version": "2.1.0",
"version": "3.5.1",
"private": true,
"license": "Apache-2.0",
"dependencies": {
"@formatjs/intl-relativetimeformat": "^2.8.2",
"@mapbox/polyline": "^1.0.0",
"@sentry/browser": "5.6.2",
"@sentry/node": "5.6.2",
"array-includes": "^3.0.3",
"array.prototype.find": "^2.0.4",
"autosize": "^4.0.0",
"basic-auth": "^2.0.0",
"body-parser": "^1.18.2",
"classnames": "^2.2.5",
"compression": "^1.7.2",
"cookie-parser": "^1.4.3",
"core-js": "^2.5.0",
"decimal.js": "7.2.4",
"dotenv": "4.0.0",
"dotenv-expand": "4.0.1",
"express": "^4.16.3",
"basic-auth": "^2.0.1",
"body-parser": "^1.18.3",
"classnames": "^2.2.6",
"compression": "^1.7.4",
"cookie-parser": "^1.4.4",
"core-js": "^3.1.4",
"decimal.js": "10.2.0",
"dotenv": "6.2.0",
"dotenv-expand": "4.2.0",
"express": "^4.16.4",
"express-enforces-ssl": "^1.1.0",
"express-sitemap": "^1.8.0",
"final-form": "^4.4.0",
"final-form-arrays": "^1.0.4",
"helmet": "^3.12.0",
"lodash": "^4.17.5",
"final-form": "^4.18.5",
"final-form-arrays": "^3.0.0",
"full-icu": "^1.3.0",
"helmet": "^3.18.0",
"intl-pluralrules": "^1.0.3",
"lodash": "^4.17.14",
"mapbox-gl-multitouch": "^1.0.3",
"moment": "^2.20.1",
"moment": "^2.22.2",
"object.entries": "^1.0.4",
"object.values": "^1.0.4",
"path-to-regexp": "^2.2.0",
"prop-types": "^15.6.1",
"path-to-regexp": "^3.0.0",
"prop-types": "^15.7.2",
"query-string": "^5.1.1",
"raf": "3.4.0",
"raven": "^2.4.2",
"raven-js": "^3.24.0",
"react": "^16.3.1",
"react-dates": "^16.0.0",
"react-dom": "^16.3.1",
"react-final-form": "^3.1.5",
"react-final-form-arrays": "^1.0.4",
"raf": "^3.4.0",
"react": "^16.9.0",
"react-dates": "^20.3.0",
"react-dom": "^16.9.0",
"react-final-form": "^6.3.0",
"react-final-form-arrays": "^3.1.1",
"react-google-maps": "^9.4.5",
"react-helmet": "^5.2.0",
"react-intl": "^2.4.0",
"react-moment-proptypes": "^1.5.0",
"react-redux": "^5.0.7",
"react-router-dom": "^4.2.2",
"redux": "^4.0.0",
"redux-thunk": "^2.2.0",
"sanitize.css": "^5.0.0",
"seedrandom": "^2.4.3",
"sharetribe-flex-sdk": "^1.0.0",
"sharetribe-scripts": "1.1.5",
"react-helmet-async": "^1.0.2",
"react-intl": "^3.1.13",
"react-moment-proptypes": "^1.6.0",
"react-redux": "^7.1.1",
"react-router-dom": "^5.0.1",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"seedrandom": "^3.0.3",
"sharetribe-flex-sdk": "^1.5.0",
"sharetribe-scripts": "3.1.1",
"smoothscroll-polyfill": "^0.4.0",
"source-map-support": "^0.5.4",
"source-map-support": "^0.5.9",
"url": "^0.11.0"
},
"devDependencies": {
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.3",
"babel-jest": "24.9.0",
"bfj": "^7.0.1",
"chalk": "^2.4.1",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.12.0",
"enzyme-to-json": "^3.3.5",
"inquirer": "^7.0.0",
"nodemon": "^1.17.2",
"nsp": "^3.2.1",
"nsp-preprocessor-yarn": "^1.0.1",
"prettier": "^1.11.1"
"prettier": "^1.18.2"
},
"resolutions": {
"react-dates/lodash": "^4.17.14",
"react-google-maps/lodash": "^4.17.14",
"react-test-renderer": "^16.9.0"
},
"nodemonConfig": {
"execMap": {
"js": "node --icu-data-dir=node_modules/full-icu"
}
},
"scripts": {
"audit": "yarn audit --json | node scripts/audit.js",
"clean": "rm -rf build/*",
"dev": "sharetribe-scripts start",
"config": "node scripts/config.js",
"dev": "node scripts/config.js --check && sharetribe-scripts start",
"build": "sharetribe-scripts build",
"format": "prettier --write '**/*.{js,css}'",
"format-ci": "prettier --list-different '**/*.{js,css}'",
"format-docs": "prettier --write '**/*.md'",
"test": "sharetribe-scripts test --env=jsdom",
"test-ci": "sharetribe-scripts test --env=jsdom --runInBand",
"test": "NODE_ICU_DATA=node_modules/full-icu sharetribe-scripts test",
"test-ci": "sharetribe-scripts test --runInBand",
"eject": "sharetribe-scripts eject",
"start": "node server/index.js",
"start": "node --icu-data-dir=node_modules/full-icu server/index.js",
"dev-server": "export NODE_ENV=development PORT=4000 REACT_APP_CANONICAL_ROOT_URL=http://localhost:4000&&yarn run build&&nodemon --watch server server/index.js",
"heroku-postbuild": "yarn run build",
"audit": "nsp check --preprocessor yarn"
"translate": "node scripts/translations.js"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"prettier": {
"singleQuote": true,
"trailingComma": "es5",
"proseWrap": "always"
},
"engines": {
"node": "8.11"
}
}

View file

@ -88,6 +88,7 @@
</head>
<body>
<div id="root"><!--!body--></div>
<div id="portal-root"></div>
<script>
(function(document){
// Check if Promise exists in window
@ -149,8 +150,8 @@
We didn't bundle it to the main app since it would unnecessarily slow down initial rendering.
-->
<script src="%PUBLIC_URL%/static/scripts/mapbox/mapbox-sdk.min.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.0.0/mapbox-gl.js"></script>
<script>
window.mapboxgl.accessToken = '%REACT_APP_MAPBOX_ACCESS_TOKEN%';
</script>

View file

@ -28,67 +28,12 @@
color: #fff;
background: #00a699
}
.SingleDatePicker {
position: relative;
display: inline-block
}
.SingleDatePicker__block {
display: block
}
.SingleDatePicker_picker {
z-index: 1;
background-color: #fff;
position: absolute
}
.SingleDatePicker_picker__rtl {
direction: rtl
}
.SingleDatePicker_picker__directionLeft {
left: 0
}
.SingleDatePicker_picker__directionRight {
right: 0
}
.SingleDatePicker_picker__portal {
background-color: rgba(0,0,0,.3);
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%
}
.SingleDatePicker_picker__fullScreenPortal {
background-color: #fff
}
.SingleDatePicker_closeButton {
background: 0 0;
border: 0;
color: inherit;
font: inherit;
line-height: normal;
overflow: visible;
cursor: pointer;
position: absolute;
top: 0;
right: 0;
padding: 15px;
z-index: 2
}
.SingleDatePicker_closeButton:focus,
.SingleDatePicker_closeButton:hover {
color: darken(#cacccd,10%);
text-decoration: none
}
.SingleDatePicker_closeButton_svg {
height: 15px;
width: 15px;
fill: #cacccd
}
.SingleDatePickerInput {
display: inline-block;
background-color: #fff
}
.SingleDatePickerInput__withBorder {
border-radius: 2px;
border: 1px solid #dbdbdb
}
.SingleDatePickerInput__rtl {
@ -159,28 +104,28 @@
width: 14px;
vertical-align: middle
}
.DateRangePicker {
.SingleDatePicker {
position: relative;
display: inline-block
}
.DateRangePicker__block {
.SingleDatePicker__block {
display: block
}
.DateRangePicker_picker {
.SingleDatePicker_picker {
z-index: 1;
background-color: #fff;
position: absolute
}
.DateRangePicker_picker__rtl {
.SingleDatePicker_picker__rtl {
direction: rtl
}
.DateRangePicker_picker__directionLeft {
.SingleDatePicker_picker__directionLeft {
left: 0
}
.DateRangePicker_picker__directionRight {
.SingleDatePicker_picker__directionRight {
right: 0
}
.DateRangePicker_picker__portal {
.SingleDatePicker_picker__portal {
background-color: rgba(0,0,0,.3);
position: fixed;
top: 0;
@ -188,10 +133,10 @@
height: 100%;
width: 100%
}
.DateRangePicker_picker__fullScreenPortal {
.SingleDatePicker_picker__fullScreenPortal {
background-color: #fff
}
.DateRangePicker_closeButton {
.SingleDatePicker_closeButton {
background: 0 0;
border: 0;
color: inherit;
@ -205,107 +150,16 @@
padding: 15px;
z-index: 2
}
.DateRangePicker_closeButton:focus,
.DateRangePicker_closeButton:hover {
.SingleDatePicker_closeButton:focus,
.SingleDatePicker_closeButton:hover {
color: darken(#cacccd,10%);
text-decoration: none
}
.DateRangePicker_closeButton_svg {
.SingleDatePicker_closeButton_svg {
height: 15px;
width: 15px;
fill: #cacccd
}
.DayPicker {
background: #fff;
position: relative;
text-align: left
}
.DayPicker__horizontal {
background: #fff
}
.DayPicker__verticalScrollable {
height: 100%
}
.DayPicker__hidden {
visibility: hidden
}
.DayPicker__withBorder {
box-shadow: 0 2px 6px rgba(0,0,0,.05),0 0 0 1px rgba(0,0,0,.07);
border-radius: 3px
}
.DayPicker_portal__horizontal {
box-shadow: none;
position: absolute;
left: 50%;
top: 50%
}
.DayPicker_portal__vertical {
position: initial
}
.DayPicker_focusRegion {
outline: 0
}
.DayPicker_weekHeaders {
position: relative
}
.DayPicker_weekHeaders__horizontal {
margin-left: 9px
}
.DayPicker_weekHeader {
color: #757575;
position: absolute;
top: 62px;
z-index: 2;
padding: 0 13px;
text-align: left
}
.DayPicker_weekHeader__vertical {
left: 50%
}
.DayPicker_weekHeader__verticalScrollable {
top: 0;
display: table-row;
border-bottom: 1px solid #dbdbdb;
background: #fff;
margin-left: 0;
left: 0;
width: 100%;
text-align: center
}
.DayPicker_weekHeader_ul {
list-style: none;
margin: 1px 0;
padding-left: 0;
padding-right: 0;
font-size: 14px
}
.DayPicker_weekHeader_li {
display: inline-block;
text-align: center
}
.DayPicker_transitionContainer {
position: relative;
overflow: hidden;
border-radius: 3px
}
.DayPicker_transitionContainer__horizontal {
-webkit-transition: height .2s ease-in-out;
-moz-transition: height .2s ease-in-out;
transition: height .2s ease-in-out
}
.DayPicker_transitionContainer__vertical {
width: 100%
}
.DayPicker_transitionContainer__verticalScrollable {
padding-top: 20px;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
overflow-y: scroll
}
.DayPickerKeyboardShortcuts_buttonReset {
background: 0 0;
border: 0;
@ -411,164 +265,6 @@
.DayPickerKeyboardShortcuts_closeSvg:hover {
fill: #82888a
}
.KeyboardShortcutRow {
list-style: none;
margin: 6px 0
}
.KeyboardShortcutRow__block {
margin-bottom: 16px
}
.KeyboardShortcutRow_keyContainer {
display: inline-block;
white-space: nowrap;
text-align: right;
margin-right: 6px
}
.KeyboardShortcutRow_keyContainer__block {
text-align: left;
display: inline
}
.KeyboardShortcutRow_key {
font-family: monospace;
font-size: 12px;
text-transform: uppercase;
background: #f2f2f2;
padding: 2px 6px
}
.KeyboardShortcutRow_action {
display: inline;
word-break: break-word;
margin-left: 8px
}
.DayPickerNavigation_container {
position: relative;
z-index: 2
}
.DayPickerNavigation_container__vertical {
background: #fff;
box-shadow: 0 0 5px 2px rgba(0,0,0,.1);
position: absolute;
bottom: 0;
left: 0;
height: 52px;
width: 100%
}
.DayPickerNavigation_container__verticalScrollable {
position: relative
}
.DayPickerNavigation_button {
cursor: pointer;
line-height: .78;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.DayPickerNavigation_button__default {
border: 1px solid #e4e7e7;
background-color: #fff;
color: #757575
}
.DayPickerNavigation_button__default:focus,
.DayPickerNavigation_button__default:hover {
border: 1px solid #c4c4c4
}
.DayPickerNavigation_button__default:active {
background: #f2f2f2
}
.DayPickerNavigation_button__horizontal {
border-radius: 3px;
padding: 6px 9px;
top: 18px;
position: absolute
}
.DayPickerNavigation_leftButton__horizontal {
left: 22px
}
.DayPickerNavigation_rightButton__horizontal {
right: 22px
}
.DayPickerNavigation_button__vertical {
display: inline-block;
position: relative;
height: 100%;
width: 50%
}
.DayPickerNavigation_button__vertical__default {
padding: 5px
}
.DayPickerNavigation_nextButton__vertical__default {
border-left: 0
}
.DayPickerNavigation_nextButton__verticalScrollable {
width: 100%
}
.DayPickerNavigation_svg__horizontal {
height: 19px;
width: 19px;
fill: #82888a
}
.DayPickerNavigation_svg__vertical {
height: 42px;
width: 42px;
fill: #565a5c
}
.CalendarMonthGrid {
background: #fff;
text-align: left;
z-index: 0
}
.CalendarMonthGrid__animating {
z-index: 1
}
.CalendarMonthGrid__horizontal {
position: absolute;
left: 9px
}
.CalendarMonthGrid__vertical {
margin: 0 auto
}
.CalendarMonthGrid__vertical_scrollable {
margin: 0 auto;
overflow-y: scroll
}
.CalendarMonthGrid_month__horizontal {
display: inline-block;
vertical-align: top;
min-height: 100%
}
.CalendarMonthGrid_month__hideForAnimation {
position: absolute;
z-index: -1;
opacity: 0;
pointer-events: none
}
.CalendarMonth {
background: #fff;
text-align: center;
padding: 0 13px;
vertical-align: top;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.CalendarMonth_table {
border-collapse: collapse;
border-spacing: 0
}
.CalendarMonth_caption {
color: #565a5c;
font-size: 18px;
text-align: center;
padding-top: 22px;
padding-bottom: 37px;
caption-side: initial
}
.CalendarMonth_caption__verticalScrollable {
padding-top: 12px;
padding-bottom: 7px
}
.CalendarDay {
-moz-box-sizing: border-box;
box-sizing: border-box;
@ -584,7 +280,7 @@
}
.CalendarDay__default {
border: 1px solid #e4e7e7;
color: #565a5c;
color: #484848;
background: #fff
}
.CalendarDay__default:hover {
@ -592,10 +288,18 @@
border: 1px double #e4e7e7;
color: inherit
}
.CalendarDay__hovered_offset {
background: #f4f5f5;
border: 1px double #e4e7e7;
color: inherit
}
.CalendarDay__outside {
border: 0;
background: #fff;
color: #565a5c
color: #484848
}
.CalendarDay__outside:hover {
border: 0
}
.CalendarDay__blocked_minimum_nights {
background: #fff;
@ -609,12 +313,12 @@
}
.CalendarDay__highlighted_calendar {
background: #ffe8bc;
color: #565a5c
color: #484848
}
.CalendarDay__highlighted_calendar:active,
.CalendarDay__highlighted_calendar:hover {
background: #ffce71;
color: #565a5c
color: #484848
}
.CalendarDay__selected_span {
background: #66e2da;
@ -662,6 +366,327 @@
border: 1px solid #e4e7e7;
color: #cacccd
}
.CalendarMonth {
background: #fff;
text-align: center;
vertical-align: top;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.CalendarMonth_table {
border-collapse: collapse;
border-spacing: 0
}
.CalendarMonth_verticalSpacing {
border-collapse: separate
}
.CalendarMonth_caption {
color: #484848;
font-size: 18px;
text-align: center;
padding-top: 22px;
padding-bottom: 37px;
caption-side: initial
}
.CalendarMonth_caption__verticalScrollable {
padding-top: 12px;
padding-bottom: 7px
}
.CalendarMonthGrid {
background: #fff;
text-align: left;
z-index: 0
}
.CalendarMonthGrid__animating {
z-index: 1
}
.CalendarMonthGrid__horizontal {
position: absolute;
left: 9px
}
.CalendarMonthGrid__vertical {
margin: 0 auto
}
.CalendarMonthGrid__vertical_scrollable {
margin: 0 auto;
overflow-y: scroll
}
.CalendarMonthGrid_month__horizontal {
display: inline-block;
vertical-align: top;
min-height: 100%
}
.CalendarMonthGrid_month__hideForAnimation {
position: absolute;
z-index: -1;
opacity: 0;
pointer-events: none
}
.CalendarMonthGrid_month__hidden {
visibility: hidden
}
.DayPickerNavigation {
position: relative;
z-index: 2
}
.DayPickerNavigation__horizontal {
height: 0
}
.DayPickerNavigation__verticalDefault {
position: absolute;
width: 100%;
height: 52px;
bottom: 0;
left: 0
}
.DayPickerNavigation__verticalScrollableDefault {
position: relative
}
.DayPickerNavigation_button {
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 0;
padding: 0;
margin: 0
}
.DayPickerNavigation_button__default {
border: 1px solid #e4e7e7;
background-color: #fff;
color: #757575
}
.DayPickerNavigation_button__default:focus,
.DayPickerNavigation_button__default:hover {
border: 1px solid #c4c4c4
}
.DayPickerNavigation_button__default:active {
background: #f2f2f2
}
.DayPickerNavigation_button__horizontalDefault {
position: absolute;
top: 18px;
line-height: .78;
border-radius: 3px;
padding: 6px 9px
}
.DayPickerNavigation_leftButton__horizontalDefault {
left: 22px
}
.DayPickerNavigation_rightButton__horizontalDefault {
right: 22px
}
.DayPickerNavigation_button__verticalDefault {
padding: 5px;
background: #fff;
box-shadow: 0 0 5px 2px rgba(0,0,0,.1);
position: relative;
display: inline-block;
height: 100%;
width: 50%
}
.DayPickerNavigation_nextButton__verticalDefault {
border-left: 0
}
.DayPickerNavigation_nextButton__verticalScrollableDefault {
width: 100%
}
.DayPickerNavigation_svg__horizontal {
height: 19px;
width: 19px;
fill: #82888a;
display: block
}
.DayPickerNavigation_svg__vertical {
height: 42px;
width: 42px;
fill: #484848;
display: block
}
.DayPicker {
background: #fff;
position: relative;
text-align: left
}
.DayPicker__horizontal {
background: #fff
}
.DayPicker__verticalScrollable {
height: 100%
}
.DayPicker__hidden {
visibility: hidden
}
.DayPicker__withBorder {
box-shadow: 0 2px 6px rgba(0,0,0,.05),0 0 0 1px rgba(0,0,0,.07);
border-radius: 3px
}
.DayPicker_portal__horizontal {
box-shadow: none;
position: absolute;
left: 50%;
top: 50%
}
.DayPicker_portal__vertical {
position: initial
}
.DayPicker_focusRegion {
outline: 0
}
.DayPicker_calendarInfo__horizontal,
.DayPicker_wrapper__horizontal {
display: inline-block;
vertical-align: top
}
.DayPicker_weekHeaders {
position: relative
}
.DayPicker_weekHeaders__horizontal {
margin-left: 9px
}
.DayPicker_weekHeader {
color: #757575;
position: absolute;
top: 62px;
z-index: 2;
text-align: left
}
.DayPicker_weekHeader__vertical {
left: 50%
}
.DayPicker_weekHeader__verticalScrollable {
top: 0;
display: table-row;
border-bottom: 1px solid #dbdbdb;
background: #fff;
margin-left: 0;
left: 0;
width: 100%;
text-align: center
}
.DayPicker_weekHeader_ul {
list-style: none;
margin: 1px 0;
padding-left: 0;
padding-right: 0;
font-size: 14px
}
.DayPicker_weekHeader_li {
display: inline-block;
text-align: center
}
.DayPicker_transitionContainer {
position: relative;
overflow: hidden;
border-radius: 3px
}
.DayPicker_transitionContainer__horizontal {
-webkit-transition: height .2s ease-in-out;
-moz-transition: height .2s ease-in-out;
transition: height .2s ease-in-out
}
.DayPicker_transitionContainer__vertical {
width: 100%
}
.DayPicker_transitionContainer__verticalScrollable {
padding-top: 20px;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
overflow-y: scroll
}
.DateInput {
margin: 0;
padding: 0;
background: #fff;
position: relative;
display: inline-block;
width: 130px;
vertical-align: middle
}
.DateInput__small {
width: 97px
}
.DateInput__block {
width: 100%
}
.DateInput__disabled {
background: #f2f2f2;
color: #dbdbdb
}
.DateInput_input {
font-weight: 200;
font-size: 19px;
line-height: 24px;
color: #484848;
background-color: #fff;
width: 100%;
padding: 11px 11px 9px;
border: 0;
border-top: 0;
border-right: 0;
border-bottom: 2px solid transparent;
border-left: 0;
border-radius: 0
}
.DateInput_input__small {
font-size: 15px;
line-height: 18px;
letter-spacing: .2px;
padding: 7px 7px 5px
}
.DateInput_input__regular {
font-weight: auto
}
.DateInput_input__readOnly {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.DateInput_input__focused {
outline: 0;
background: #fff;
border: 0;
border-top: 0;
border-right: 0;
border-bottom: 2px solid #008489;
border-left: 0
}
.DateInput_input__disabled {
background: #f2f2f2;
font-style: italic
}
.DateInput_screenReaderMessage {
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px
}
.DateInput_fang {
position: absolute;
width: 20px;
height: 10px;
left: 22px;
z-index: 2
}
.DateInput_fangShape {
fill: #fff
}
.DateInput_fangStroke {
stroke: #dbdbdb;
fill: transparent
}
.DateRangePickerInput {
background-color: #fff;
display: inline-block
@ -670,7 +695,8 @@
background: #f2f2f2
}
.DateRangePickerInput__withBorder {
border: 1px solid #cacccd
border-radius: 2px;
border: 1px solid #dbdbdb
}
.DateRangePickerInput__rtl {
direction: rtl
@ -683,18 +709,15 @@
}
.DateRangePickerInput_arrow {
display: inline-block;
vertical-align: middle
vertical-align: middle;
color: #484848
}
.DateRangePickerInput_arrow_svg {
vertical-align: middle;
fill: #565a5c;
fill: #484848;
height: 24px;
width: 24px
}
.DateRangePickerInput_arrow_svg__small {
height: 19px;
width: 19px
}
.DateRangePickerInput_clearDates {
background: 0 0;
border: 0;
@ -751,81 +774,59 @@
width: 14px;
vertical-align: middle
}
.DateInput {
margin: 0;
padding: 0;
background: #fff;
.DateRangePicker {
position: relative;
display: inline-block;
width: 130px;
vertical-align: middle
display: inline-block
}
.DateInput__small {
width: 90px
.DateRangePicker__block {
display: block
}
.DateInput__disabled {
background: #f2f2f2;
color: #dbdbdb
}
.DateInput_input {
font-weight: 200;
font-size: 18px;
line-height: 24px;
color: #565a5c;
.DateRangePicker_picker {
z-index: 1;
background-color: #fff;
width: 100%;
padding: 13px 12px 11px;
position: absolute
}
.DateRangePicker_picker__rtl {
direction: rtl
}
.DateRangePicker_picker__directionLeft {
left: 0
}
.DateRangePicker_picker__directionRight {
right: 0
}
.DateRangePicker_picker__portal {
background-color: rgba(0,0,0,.3);
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 100%
}
.DateRangePicker_picker__fullScreenPortal {
background-color: #fff
}
.DateRangePicker_closeButton {
background: 0 0;
border: 0;
border-top: 0;
border-right: 0;
border-bottom: 2px solid transparent;
border-left: 0
}
.DateInput_input__small {
font-size: 14px;
line-height: 18px;
padding: 8px 8px 6px
}
.DateInput_input__readOnly {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.DateInput_input__focused {
outline: 0;
background: #fff;
border: 0;
border-top: 0;
border-right: 0;
border-bottom: 2px solid #008489;
border-left: 0
}
.DateInput_input__disabled {
background: #f2f2f2;
font-style: italic
}
.DateInput_screenReaderMessage {
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
color: inherit;
font: inherit;
line-height: normal;
overflow: visible;
cursor: pointer;
position: absolute;
width: 1px
}
.DateInput_fang {
position: absolute;
width: 20px;
height: 10px;
left: 22px;
top: 0;
right: 0;
padding: 15px;
z-index: 2
}
.DateInput_fangShape {
fill: #fff
}
.DateInput_fangStroke {
stroke: #dbdbdb;
fill: transparent
.DateRangePicker_closeButton:focus,
.DateRangePicker_closeButton:hover {
color: darken(#cacccd,10%);
text-decoration: none
}
.DateRangePicker_closeButton_svg {
height: 15px;
width: 15px;
fill: #cacccd
}

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

79
scripts/audit.js Normal file
View file

@ -0,0 +1,79 @@
// Check possible npm dependency vulnerabilities
// Usage: execute "yarn run audit" in the shell
//
// You can add exceptions through .nsprc file, which is a hidden file in root folder.
//
// Note: to use this script, you should pipe in the output of 'yarn audit --json'
const bfj = require('bfj');
const fs = require('fs');
const exceptions = require('../.auditrc').exceptions;
const INDENT = ' ';
const isAuditAdvisory = o => o.type === 'auditAdvisory';
// get an advisory or empty object
const getAdvisory = o => (!o ? {} : !o.data ? {} : !o.data.advisory ? {} : o.data.advisory);
// get a resolution or empty object
const getResolution = o => (!o ? {} : !o.data ? {} : !o.data.resolution ? {} : o.data.resolution);
// Read the output of 'yarn audit --json', which should be piped in through stdin
const stdinStream = process.stdin.resume();
let advisories = {};
bfj
.match(stdinStream, (key, value, depth) => depth === 0, { ndjson: true })
.on('data', object => {
if (isAuditAdvisory(object) && Array.isArray(exceptions)) {
const { id, severity, title, url } = getAdvisory(object);
const { path } = getResolution(object);
const isInExceptionList = url && exceptions.includes(url);
if (!isInExceptionList && url && path) {
const advisory = advisories[id] ? advisories[id] : { url, severity, title };
const paths = advisory.paths ? advisory.paths : [];
advisories[id] = { ...advisory, paths: paths.concat(path) };
}
}
})
.on('dataError', error => {
// A syntax error was found in the JSON
console.error(
`An error occurred while processing data.
You need to pipe the results of "yarn audit --json" to this script from shell.
Error`,
error
);
process.exit(1);
})
.on('error', error => {
// Some kind of operational error occurred
console.error(
`An error occurred while processing data.
You need to pipe the results of "yarn audit --json" to this script from shell.
Error`,
error
);
process.exit(1);
})
.on('end', error => {
const advisoryKeys = Object.keys(advisories);
if (advisoryKeys.length > 0) {
console.log('Vulneralibilities found:');
console.log('\n----------------------------------------\n');
advisoryKeys.forEach(key => {
const { title, severity, url, paths } = advisories[key];
console.log(key, `(${title})`);
console.log('Severity:', severity);
console.log('More info:', url);
console.log('Affected dependencies:');
paths.forEach(path => {
console.log(INDENT, path);
});
console.log('\n----------------------------------------\n');
});
process.exit(1);
} else {
process.exit();
}
});

418
scripts/config.js Normal file
View file

@ -0,0 +1,418 @@
const inquirer = require('inquirer');
const fs = require('fs');
const readline = require('readline');
const chalk = require('chalk');
/**
* If config script is running with flag --check only check if .env file exists.
* Show error if .env file doesn't exist.
*
* When running the script without flag .env file is created.
* User can fill in environment variables needed for running the application.
*
* If .env file already exists user can edit the values configured in the file.
* Old values are used as default.
*
*/
const run = () => {
const hasEnvFile = fs.existsSync(`./.env`);
if (process.argv[2] && process.argv[2] === '--check') {
if (!hasEnvFile) {
process.on('exit', code => {
console.log(`
${chalk.bold.red(`You don't have required .env file!`)}
Some environment variables are required before starting Flex template for web. You can create the .env file and configure the variables by running ${chalk.cyan.bold(
'yarn run config'
)}
`);
});
process.exit(1);
}
} else if (hasEnvFile) {
console.log(`
${chalk.bold.green('.env file already exists!')}
Remember to restart the application after editing the environment variables! You can also edit environment variables by editing the .env file directly in your text editor.
`);
inquirer
.prompt([
{
type: 'confirm',
name: 'editEnvFile',
message: 'Do you want to edit the .env file?',
default: false,
},
])
.then(answers => {
if (answers.editEnvFile) {
const settings = findSavedValues();
askQuestions(settings);
}
})
.catch(err => {
console.log(chalk.red(`An error occurred due to: ${err.message}`));
});
} else {
inquirer
.prompt([
{
type: 'confirm',
name: 'createEmptyEnv',
message: `Do you want to configure required environment variables now?
${chalk.dim(
`If you don't set up variables now .env file is created based on .env-template file. The application will not work correctly without Flex client ID, Stripe publishable API key and MapBox acces token.
We recommend setting up the required variables before starting the application!`
)}`,
default: true,
},
])
.then(answers => {
createEnvFile();
if (answers.createEmptyEnv) {
askQuestions();
} else {
showSuccessMessage();
}
})
.catch(err => {
console.log(chalk.red(`An error occurred due to: ${err.message}`));
});
}
};
/**
* Questions for mandatory variables.
* If some values already exist in the .env file use them as a default.
* Otherwise don't use default value in the questions.
*
* @param {array} settings - array of values used as default if user is editing the .env file
*
* @returns array of questions passed to Inquirer
*
*/
const mandatoryVariables = settings => {
const clientIdDefaultMaybe =
settings &&
settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID !== '' &&
settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID !== 'change-me'
? { default: settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID }
: {};
const stripeDefaultMaybe =
settings && settings.REACT_APP_STRIPE_PUBLISHABLE_KEY !== ''
? { default: settings.REACT_APP_STRIPE_PUBLISHABLE_KEY }
: {};
const mapBoxDefaultMaybe =
settings && settings.REACT_APP_MAPBOX_ACCESS_TOKEN !== ''
? { default: settings.REACT_APP_MAPBOX_ACCESS_TOKEN }
: {};
const currencyDefault =
settings && settings.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY !== ''
? settings.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY
: 'USD';
return [
{
type: 'input',
name: 'REACT_APP_SHARETRIBE_SDK_CLIENT_ID',
message: `What is your Flex client ID?
${chalk.dim(
'Client ID is needed for connecting with Flex API. You can find your client ID from Flex Console.'
)}
`,
validate: function(value) {
if (value.match(/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i)) {
return true;
}
return 'Please enter valid Flex Client ID. You can check it form Flex Console!';
},
...clientIdDefaultMaybe,
},
{
type: 'input',
name: 'REACT_APP_STRIPE_PUBLISHABLE_KEY',
message: `What is your Stripe publishable key?
${chalk.dim(
`Stripe publishable API key is for generating tokens with Stripe API. Use test key (prefix pk_test_) for development. Remember to also add the Stripe secret key to Console before testing the payments.
If you don't set the Stripe key, payments won't work in the application.`
)}
`,
validate: function(value) {
if (value.match(/^pk_/) || value === '') {
return true;
}
return 'Please enter Stripe publishable key with prefix pk_!';
},
...stripeDefaultMaybe,
},
{
type: 'input',
name: 'REACT_APP_MAPBOX_ACCESS_TOKEN',
message: `What is your Mapbox access token?
${chalk.dim(
`Mapbox is the default map provider of the application. Sign up for Mapbox and go the to account page. Then click Create access token. For more information see the: Integrating to map providers documentation.
If you don't set the Mapbox key, the map components won't work in the application.`
)}
`,
...mapBoxDefaultMaybe,
},
{
type: 'input',
name: 'REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY',
message: `What is your marketplace currency?
${chalk.dim(
'The currency used in the Marketplace must be in ISO 4217 currency code. For example USD, EUR, CAD, AUD, etc. The default value is USD.'
)}
`,
default: function() {
return currencyDefault;
},
validate: function(value) {
if (value.match(/^[a-zA-Z]{3}$/)) {
return true;
}
return 'Please enter currency in ISO 4217 format (e.g. USD, EUR, CAD...)';
},
},
];
};
/**
* Questions for advances variables. User can choose to edit these or not.
* If some values already exist in the .env file use them as a default.
* Otherwise don't use default value in the questions.
*
* @param {array} settings - array of values used as default if user is editing the .env file
*
* @returns array of questions passed to Inquirer
*
*/
const advancedSettings = settings => {
const rootUrlDefault = settings ? settings.REACT_APP_CANONICAL_ROOT_URL : null;
const availabilityDefault = settings
? settings.REACT_APP_AVAILABILITY_ENABLED.toLowerCase() === 'true'
: true;
const searchesDefault = settings
? settings.REACT_APP_DEFAULT_SEARCHES_ENABLED.toLowerCase() === 'true'
: true;
return [
{
type: 'confirm',
name: 'showAdvancedSettings',
message: 'Do you want to edit advanced settings?',
default: false,
},
{
type: 'input',
name: 'REACT_APP_CANONICAL_ROOT_URL',
message: `What is your canonical root URL?
${chalk.dim(
'Canonical root URL of the marketplace is needed for social media sharing and SEO optimization. When developing the template application locally URL is usually http://localhost:3000'
)}
`,
default: function() {
return rootUrlDefault ? rootUrlDefault : 'http://localhost:3000';
},
when: function(answers) {
return answers.showAdvancedSettings;
},
},
{
type: 'confirm',
name: 'REACT_APP_AVAILABILITY_ENABLED',
message: `Do you want to enable availability calendar?
${chalk.dim(
'This setting enables the Availability Calendar for listings. The default value for this setting is true.'
)}
`,
default: availabilityDefault,
when: function(answers) {
return answers.showAdvancedSettings;
},
},
{
type: 'confirm',
name: 'REACT_APP_DEFAULT_SEARCHES_ENABLED',
message: `Do you want to enable default search suggestions?
${chalk.dim(
'This setting enables the Default Search Suggestions in location autocomplete search input. The default value for this setting is true.'
)}
`,
default: searchesDefault,
when: function(answers) {
return answers.showAdvancedSettings;
},
},
];
};
/**
* First ask mandatory variables and then check if user also wants to edit the advanced settings.
* Update the .env file with user input.
*
* @param {array} settings - array of values used as default if user is editing the .env file
*
*/
const askQuestions = settings => {
inquirer
.prompt(mandatoryVariables(settings))
.then(answers => {
return readLines(answers);
})
.then(values => {
const data = getData(values);
updateEnvFile(data);
console.log(chalk.yellow.bold(`Advanced settings:`));
inquirer
.prompt(advancedSettings(settings))
.then(answers => {
return readLines(answers);
})
.then(values => {
const data = getData(values);
updateEnvFile(data);
showSuccessMessage();
});
})
.catch(err => {
console.log(chalk.red(`An error occurred due to: ${err.message}`));
});
};
/**
* Show succes message used after creating the .env file
*/
const showSuccessMessage = () => {
console.log(`
${chalk.green.bold('.env file saved succesfully!')}
Start the Flex template application by running ${chalk.bold.cyan('yarn run dev')}
Note that the .env file is a hidden file so it might not be visible directly in directory listing. If you want to update the environment variables run ${chalk.cyan.bold(
'yarn run config'
)} again or edit the .env file directly. Remember to restart the application after editing the environment variables!
`);
};
/**
* Create new .env file using .env-template
*/
const createEnvFile = () => {
fs.copyFileSync('./.env-template', './.env', err => {
if (err) throw err;
});
};
/**
* Get the saved values from .env file so they can be used as a default values
*
* @return array containing all keys and values saved to .env file
*/
const findSavedValues = () => {
const savedEnvFile = fs.readFileSync('./.env').toString();
const settings = savedEnvFile.split('\n').reduce((obj, line) => {
const splits = line.split('=');
const key = splits[0].trim();
if (splits.length > 1) {
obj[key] = splits
.slice(1)
.join('=')
.trim();
}
return obj;
}, {});
return settings;
};
/**
* Read all lines from existing .env file to array.
* If line matches one of the keys in user's answers update add value to that line.
* Otherwise keep the original line.
*
* @param {object} answers object containing all the inputs user has given to questions
*
* @return returns a Promise that resolves with values object containing user input and read lines
*/
const readLines = answers => {
return new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: fs.createReadStream('./.env'),
});
const lines = [];
rl.on('line', function(line) {
lines.push(line);
});
rl.on('close', () => {
const values = { answers, lines };
resolve(values);
});
});
};
/**
*
* Creates array of data that is saved to .env file
*
* @param {object} values contais lines read from .env file and answers from the user
*
* @returns array containing the data that needs to be saved to .env file
*/
const getData = values => {
const { lines, answers } = values;
const data = lines.map(line => {
const key = getKeyFromAnswers(answers, line);
if (key) {
const value = `${answers[key]}`;
return `${key}=${value.trim()}\n`;
} else {
return `${line}\n`;
}
});
return data;
};
/**
* Joins lines to create content that is written to .env file. This will overwrite the previous content.
*
* @param {array} data arry of lines to be written into .env file
*/
const updateEnvFile = data => {
fs.writeFileSync('./.env', data.join(''));
};
/**
* Check if line contains the key from the user answers.
*
* @param {object} answers array of answers user has given to questions
* @param {string} line line from the existing .env file
*
* @returns key if the key matches to the one in the line
*/
const getKeyFromAnswers = (answers, line) => {
let foundKey;
if (answers) {
foundKey = Object.keys(answers).find(function(key) {
if (line.includes(key)) {
return key;
}
});
}
return foundKey;
};
run();

300
scripts/translations.js Normal file
View file

@ -0,0 +1,300 @@
/**
* A translations too that can be used to keep a translation file(s)
* up to date with one source language file.
*
* Possible target languages are resolved from the translation files
* available. When adding a new tranlation file, the language name can
* be added to the TARGET_LANG_NAMES map for clearer prompt messages.
* By default the translations are matched agains English translations
* but that can be changed by modifying the SOURCE_LANG.
*/
const inquirer = require('inquirer');
const difference = require('lodash/difference');
const fs = require('fs');
const chalk = require('chalk');
const PATH = './src/translations/';
const SOURCE_LANG = { name: 'English', code: 'en' };
const TARGET_LANG_NAMES = {
es: 'Spanish',
de: 'German',
fr: 'French',
};
class BreakToRun {}
class BreakToRunWithTarget {}
/**
* Resolves translation file path for a lang code: en, es, de, etc.
*/
const filePath = lang => `${PATH}${lang}.json`;
/**
* Resolves name of a target language based on
* a language code: en, es, de, etc.
*
* If a lang name is not found, language code is returned.
*/
const targetLangName = code => {
const name = TARGET_LANG_NAMES[code];
return name || code;
};
/**
* Resolve a list of target language choices by finding all possible
* translation files and filtering out the SOURCE_LANG. Provides a list
* of objects that can be passed to inquirer.
*
* Relies on translation file naming: <lang code>.json
*/
const targetLangChoices = () => {
const folder = './src/translations/';
const filenames = fs.readdirSync(folder);
const choices = filenames
.filter(name => name.endsWith('.json'))
.map(name => name.split('.')[0])
.filter(code => code !== SOURCE_LANG.code)
.map(code => {
return {
name: targetLangName(code),
value: code,
};
});
return choices;
};
/**
* Sorts an object by key.
*
* Relies on an object keeping the order in which entries are added for string keys.
* See: http://exploringjs.com/es6/ch_oop-besides-classes.html#_traversal-order-of-properties
*/
const sort = obj => {
const sorted = {};
Object.keys(obj)
.sort()
.forEach(key => (sorted[key] = obj[key]));
return sorted;
};
/**
* Reads a file with JSON content and returns
* a JS object.
*
* @param filepath
*/
const readFileToJSON = filepath => {
const rawdata = fs.readFileSync(filepath);
return JSON.parse(rawdata);
};
/**
* Run the application.
*
*/
const run = () => {
const choices = targetLangChoices();
selectLanguage(choices)
.then(answers => {
runWithTarget(answers.lang);
})
.catch(err => {
console.log(chalk.red(`An error occurred due to: ${err.message}`));
});
};
/**
* When a language is selected this will prompt
* the user about adding translations to that language.
*
* @param {String} targetLang Target language code
*/
const runWithTarget = targetLang => {
let key;
let translation;
const sourceLang = SOURCE_LANG.code;
const source = readFileToJSON(filePath(sourceLang));
const target = readFileToJSON(filePath(targetLang));
const sourceKeys = Object.keys(source);
const targetKeys = Object.keys(target);
const diff = difference(sourceKeys, targetKeys);
if (diff.length === 0) {
console.log(`No translations missing from the ${targetLangName(targetLang)} translations`);
run();
} else {
translateLanguage(targetLang, source, target, diff);
}
};
/**
* Does the actual prompting for translations.
*
* @param {String} targetLang Target language code
* @param {Object} source Source translations
* @param {Object} target Target translations
* @param {Array} diff Missing keys in target
*/
const translateLanguage = (targetLang, source, target, diff) => {
selectKey(targetLang, diff, source, target)
.then(answers => {
key = answers.key;
if (key === null) {
throw new BreakToRun();
}
if (key != null) {
return addTranslation(targetLang, key, source);
}
})
.then(answers => {
translation = answers.value;
return confirmTranslation(targetLang, key, translation);
})
.then(answers => {
// y|Y|n|N
const confirmation = answers.value;
if (/n/i.test(confirmation)) {
console.log('Discarding new translation');
throw new BreakToRunWithTarget();
}
target[key] = translation;
const sorted = sort(target);
const data = JSON.stringify(sorted, null, 2);
return updateTranslationsFile(data, targetLang);
})
.then(() => {
runWithTarget(targetLang);
})
.catch(err => {
if (err instanceof BreakToRun) {
// break out of Promise chain, start over
run();
} else if (err instanceof BreakToRunWithTarget) {
// break out of Promise chain, continue with this language
runWithTarget(targetLang);
} else {
console.log(chalk.red(`An error occurred due to: ${err.message}`));
}
});
};
/**
* Prompt for selecting the language of which
* translations are inspected.
*
* @return a Promise
*/
const selectLanguage = choices => {
return inquirer.prompt([
{
type: 'list',
name: 'lang',
message: 'Which language would you like to inspect? (Or hit Ctrl+C to quit)',
choices: choices,
},
]);
};
/**
* Prompt for selecting a key that is missing from the target language translations.
*
* @param {String} targetLang The language that is being translated
* @param {Array} diff Keys missing frrom target language translations
*
* @return a Promise
*/
const selectKey = (targetLang, diff, source, target) => {
const choices = [{ name: 'Back to languages', value: null }, ...diff];
return inquirer.prompt([
{
type: 'list',
name: 'key',
message: `The following translation keys (${
diff.length
}) are missing from the ${targetLangName(
targetLang
)} translations. Select a key to add a translation.`,
choices: choices,
pageSize: 30,
},
]);
};
/**
* Prompt for a new translation in target language.
*
* @param {String} targetLang The language that is being translated
* @param {String} key Key for the new translation
* @param {Object} source Source language translations
*
* @return a Promise
*/
const addTranslation = (targetLang, key, source) => {
return inquirer.prompt([
{
type: 'input',
name: 'value',
message: `Please provide a translation in ${targetLangName(
targetLang
)} for the key ${chalk.blueBright(key)}. The current ${
SOURCE_LANG.name
} translation is ${chalk.green(source[key])} \n`,
},
]);
};
/**
* Prompt for a confirming a new translation with 'y' or 'N'.
*
* @param {String} targetLang The language that is being translated
* @param {String} key Key for the new translation
* @param {Object} source Source language translations
*
* @return a Promise with with answers.value being 'y' or 'N'
*/
const confirmTranslation = (targetLang, key, translation) => {
return inquirer.prompt([
{
type: 'input',
name: 'value',
message: `Do you want to add the ${targetLangName(targetLang)} translation ${chalk.green(
translation
)} for the key ${chalk.blueBright(key)}? (y/n)`,
validate: value => /y/i.test(value) || /n/i.test(value),
},
]);
};
/**
* Update translations file.
*
* @param {String} data String data to be written to file
* @param {String} targetLang Language code of the translation file
*
* @return a Promise that resolves when file is written
*/
const updateTranslationsFile = (data, targetLang) => {
return new Promise((resolve, reject) => {
fs.writeFile(filePath(targetLang), data, err => {
if (err) {
reject(err);
}
console.log(chalk.bold('The translation file is updated'));
resolve();
});
});
};
run();

View file

@ -7,6 +7,7 @@ const unsafeEval = "'unsafe-eval'";
const data = 'data:';
const blob = 'blob:';
const devImagesMaybe = dev ? ['*.localhost:8000'] : [];
const baseUrl = process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL || 'https://flex-api.sharetribe.com';
// Default CSP whitelist.
//
@ -18,10 +19,11 @@ const defaultDirectives = {
childSrc: [blob],
connectSrc: [
self,
process.env.REACT_APP_SHARETRIBE_SDK_BASE_URL,
baseUrl,
'maps.googleapis.com',
'*.tiles.mapbox.com',
'api.mapbox.com',
'events.mapbox.com',
// Google Analytics
'www.google-analytics.com',

View file

@ -9,7 +9,7 @@ const path = require('path');
const buildPath = path.resolve(__dirname, '..', 'build');
const manifestPath = path.join(buildPath, 'asset-manifest.json');
const manifest = require(manifestPath);
const mainJsPath = path.join(buildPath, manifest['main.js']);
const mainJsPath = path.join(buildPath, manifest['files']['main.js']);
const mainJs = require(mainJsPath);
module.exports = {

View file

@ -167,10 +167,11 @@ app.get('*', (req, res) => {
secure: USING_SSL,
});
const baseUrl = BASE_URL ? { baseUrl: BASE_URL } : {};
const sdk = sharetribeSdk.createInstance({
transitVerbose: TRANSIT_VERBOSE,
clientId: CLIENT_ID,
baseUrl: BASE_URL,
httpAgent: httpAgent,
httpsAgent: httpsAgent,
tokenStore,
@ -182,6 +183,7 @@ app.get('*', (req, res) => {
reader: v => new Decimal(v.value),
},
],
...baseUrl,
});
// Until we have a better plan for caching dynamic content and we

View file

@ -4,10 +4,10 @@
* or just plain printing errors to the log.
*/
const Raven = require('raven');
const Sentry = require('@sentry/node');
const ENV = process.env.REACT_APP_ENV;
const SENTRY_DSN = process.env.SERVER_SENTRY_DSN;
const SENTRY_DSN = process.env.REACT_APP_SENTRY_DSN;
/**
* Set up error loggin. If a Sentry DSN is defined
@ -19,12 +19,7 @@ exports.setup = () => {
// exceptions from starting the server etc. but does not catch the
// ones thrown from Express.js middleware functions. For those
// an error handler has to be added to the Express app.
Raven.config(SENTRY_DSN, {
environment: ENV,
autoBreadcrumbs: {
http: true,
},
}).install();
Sentry.init({ dsn: SENTRY_DSN, environment: ENV });
}
};
@ -34,7 +29,7 @@ exports.setup = () => {
*/
exports.requestHandler = () => {
if (SENTRY_DSN) {
return Raven.requestHandler();
return Sentry.Handlers.requestHandler();
} else {
return (req, res, next) => {
next();
@ -48,7 +43,7 @@ exports.requestHandler = () => {
*/
exports.errorHandler = () => {
if (SENTRY_DSN) {
return Raven.errorHandler();
return Sentry.Handlers.errorHandler();
} else {
return (err, req, res, next) => {
next(err);
@ -56,6 +51,17 @@ exports.errorHandler = () => {
}
};
const responseAPIErrors = error => {
return error && error.data && error.data.errors ? error.data.errors : [];
};
const responseApiErrorInfo = err =>
responseAPIErrors(err).map(e => ({
status: e.status,
code: e.code,
meta: e.meta,
}));
/**
* Logs a error. If Sentry client is set up
* passes the error to that. Otherwise prints
@ -67,7 +73,15 @@ exports.errorHandler = () => {
*/
exports.error = (e, code, data) => {
if (SENTRY_DSN) {
Raven.captureException(e, { tags: { code }, extra: data });
const extra = { ...data, apiErrorData: responseApiErrorInfo(e) };
Sentry.withScope(scope => {
scope.setTag('code', code);
Object.keys(extra).forEach(key => {
scope.setExtra(key, extra[key]);
});
Sentry.captureException(e);
});
} else {
console.error(e);
console.error(code);

View file

@ -78,12 +78,12 @@ class RouteComponentRenderer extends Component {
handleLocationChanged(this.props.dispatch, this.props.location);
}
componentWillReceiveProps(nextProps) {
componentDidUpdate() {
// Calling loadData after initial rendering (on client side).
// This makes it possible to use loadData as default client side data loading technique.
// However it is better to fetch data before location change to avoid "Loading data" state.
callLoadData(nextProps);
handleLocationChanged(nextProps.dispatch, nextProps.location);
callLoadData(this.props);
handleLocationChanged(this.props.dispatch, this.props.location);
}
render() {
@ -187,4 +187,7 @@ const mapStateToProps = state => {
// lifecycle hook.
//
// See: https://github.com/ReactTraining/react-router/issues/4671
export default compose(withRouter, connect(mapStateToProps))(Routes);
export default compose(
withRouter,
connect(mapStateToProps)
)(Routes);

View file

@ -6,23 +6,61 @@ import ReactDOMServer from 'react-dom/server';
// https://github.com/airbnb/react-dates#initialize
// NOTE: Initializing it here will initialize it also for app.test.js
import 'react-dates/initialize';
import Helmet from 'react-helmet';
import { HelmetProvider } from 'react-helmet-async';
import { BrowserRouter, StaticRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import difference from 'lodash/difference';
import mapValues from 'lodash/mapValues';
import moment from 'moment';
import { IntlProvider, addLocaleData } from 'react-intl';
import { IntlProvider } from './util/reactIntl';
import configureStore from './store';
import routeConfiguration from './routeConfiguration';
import Routes from './Routes';
import config from './config';
// If you want to change the language, Change the imports to the match
// the wanted locale.
//
// Remember to also change the language in the config.js file.
import localeData from 'react-intl/locale-data/en';
import messages from './translations/en.json';
// Flex template application uses English translations as default.
import defaultMessages from './translations/en.json';
// If you want to change the language, change the imports to match the wanted locale:
// 1) Change the language in the config.js file!
// 2) Import correct locale rules for Moment library
// 3) Use the `messagesInLocale` import to add the correct translation file.
// 4) To support older browsers we need add the correct locale for intl-relativetimeformat to `util/polyfills.js`
// Note that there is also translations in './translations/countryCodes.js' file
// This file contains ISO 3166-1 alpha-2 country codes, country names and their translations in our default languages
// This used to collect billing address in StripePaymentAddress on CheckoutPage
// Step 2:
// If you are using a non-english locale with moment library,
// you should also import time specific formatting rules for that locale
// e.g. for French: import 'moment/locale/fr';
// Step 3:
// If you are using a non-english locale, point `messagesInLocale` to correct .json file
import messagesInLocale from './translations/fr.json';
// If translation key is missing from `messagesInLocale` (e.g. fr.json),
// corresponding key will be added to messages from `defaultMessages` (en.json)
// to prevent missing translation key errors.
const addMissingTranslations = (sourceLangTranslations, targetLangTranslations) => {
const sourceKeys = Object.keys(sourceLangTranslations);
const targetKeys = Object.keys(targetLangTranslations);
const missingKeys = difference(sourceKeys, targetKeys);
const addMissingTranslation = (translations, missingKey) => ({
...translations,
[missingKey]: sourceLangTranslations[missingKey],
});
return missingKeys.reduce(addMissingTranslation, targetLangTranslations);
};
const isDefaultLanguageInUse = config.locale === 'en';
const messages = isDefaultLanguageInUse
? defaultMessages
: addMissingTranslations(defaultMessages, messagesInLocale);
const isTestEnv = process.env.NODE_ENV === 'test';
@ -33,13 +71,12 @@ const localeMessages = isTestEnv ? testMessages : messages;
const setupLocale = () => {
if (isTestEnv) {
// Don't change the locale in tests
// Use english as a default locale in tests
// This affects app.test.js and app.node.test.js tests
config.locale = 'en';
return;
}
// Add the translation messages
addLocaleData([...localeData]);
// Set the Moment locale globally
// See: http://momentjs.com/docs/#/i18n/changing-locale/
moment.locale(config.locale);
@ -49,11 +86,13 @@ export const ClientApp = props => {
const { store } = props;
setupLocale();
return (
<IntlProvider locale={config.locale} messages={localeMessages}>
<IntlProvider locale={config.locale} messages={localeMessages} textComponent="span">
<Provider store={store}>
<BrowserRouter>
<Routes routes={routeConfiguration()} />
</BrowserRouter>
<HelmetProvider>
<BrowserRouter>
<Routes routes={routeConfiguration()} />
</BrowserRouter>
</HelmetProvider>
</Provider>
</IntlProvider>
);
@ -64,14 +103,17 @@ const { any, string } = PropTypes;
ClientApp.propTypes = { store: any.isRequired };
export const ServerApp = props => {
const { url, context, store } = props;
const { url, context, helmetContext, store } = props;
setupLocale();
HelmetProvider.canUseDOM = false;
return (
<IntlProvider locale={config.locale} messages={localeMessages}>
<IntlProvider locale={config.locale} messages={localeMessages} textComponent="span">
<Provider store={store}>
<StaticRouter location={url} context={context}>
<Routes routes={routeConfiguration()} />
</StaticRouter>
<HelmetProvider context={helmetContext}>
<StaticRouter location={url} context={context}>
<Routes routes={routeConfiguration()} />
</StaticRouter>
</HelmetProvider>
</Provider>
</IntlProvider>
);
@ -95,9 +137,11 @@ export const renderApp = (url, serverContext, preloadedState) => {
// shouldn't do any SDK calls in the (server) rendering lifecycle.
const store = configureStore(preloadedState);
const helmetContext = {};
const body = ReactDOMServer.renderToString(
<ServerApp url={url} context={serverContext} store={store} />
<ServerApp url={url} context={serverContext} helmetContext={helmetContext} store={store} />
);
const head = Helmet.renderStatic();
const { helmet: head } = helmetContext;
return { head, body };
};

96
src/app.node.test.js Normal file
View file

@ -0,0 +1,96 @@
/**
* @jest-environment node
*/
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import { Helmet } from 'react-helmet-async';
import forEach from 'lodash/forEach';
import { ClientApp, ServerApp } from './app';
import configureStore from './store';
const render = (url, context) => {
const store = configureStore();
const helmetContext = {};
const body = ReactDOMServer.renderToString(
<ServerApp url={url} context={context} helmetContext={helmetContext} store={store} />
);
const { helmet: head } = helmetContext;
return { head, body };
};
describe('Application - node environment', () => {
it('renders in the server without crashing', () => {
render('/', {});
});
it('renders the styleguide without crashing', () => {
render('/styleguide', {});
});
it('server renders pages that do not require authentication', () => {
const urlTitles = {
'/': 'LandingPage.schemaTitle',
'/s': 'SearchPage.schemaTitle',
'/l/listing-title-slug/1234': 'ListingPage.loadingListingTitle',
'/l/1234': 'ListingPage.loadingListingTitle',
'/u/1234': 'ProfilePage.schemaTitle',
'/login': 'AuthenticationPage.schemaTitleLogin',
'/signup': 'AuthenticationPage.schemaTitleSignup',
'/recover-password': 'PasswordRecoveryPage.title',
'/this-url-should-not-be-found': 'NotFoundPage.title',
'/reset-password?t=token&e=email': 'PasswordResetPage.title',
};
forEach(urlTitles, (title, url) => {
const context = {};
const { head, body } = render(url, context);
expect(head.title.toString()).toContain(title);
// context.url will contain the URL to redirect to if a <Redirect> was used
expect(context.url).not.toBeDefined();
});
});
it('server renders redirects for pages that require authentication', () => {
const loginPath = '/login';
const signupPath = '/signup';
const urlRedirects = {
'/l/new': signupPath,
'/l/listing-title-slug/1234/new/description': signupPath,
'/l/listing-title-slug/1234/checkout': signupPath,
'/profile-settings': loginPath,
'/inbox': loginPath,
'/inbox/orders': loginPath,
'/inbox/sales': loginPath,
'/order/1234': loginPath,
'/order/1234/details': loginPath,
'/sale/1234': loginPath,
'/sale/1234/details': loginPath,
'/listings': loginPath,
'/account': loginPath,
'/account/contact-details': loginPath,
'/account/change-password': loginPath,
'/account/payments': loginPath,
'/verify-email': loginPath,
};
forEach(urlRedirects, (redirectPath, url) => {
const context = {};
const { body } = render(url, context);
expect(context.url).toEqual(redirectPath);
});
});
it('redirects to correct URLs', () => {
const urlRedirects = { '/l': '/', '/u': '/' };
forEach(urlRedirects, (redirectPath, url) => {
const context = {};
const { body } = render(url, context);
expect(context.url).toEqual(redirectPath);
});
});
});

View file

@ -1,21 +1,19 @@
import React from 'react';
import ReactDOM from 'react-dom';
import ReactDOMServer from 'react-dom/server';
import Helmet from 'react-helmet';
import forEach from 'lodash/forEach';
import { ClientApp, ServerApp } from './app';
import { ClientApp } from './app';
import configureStore from './store';
const render = (url, context) => {
const store = configureStore();
const body = ReactDOMServer.renderToString(
<ServerApp url={url} context={context} store={store} />
);
const head = Helmet.peek();
return { head, body };
};
const jsdomScroll = window.scroll;
beforeAll(() => {
// Mock window.scroll - otherwise, Jest/JSDOM will print a not-implemented error.
window.scroll = () => {};
});
describe('Application', () => {
afterAll(() => {
window.scroll = jsdomScroll;
});
describe('Application - JSDOM environment', () => {
it('renders in the client without crashing', () => {
window.google = { maps: {} };
const store = configureStore();
@ -23,74 +21,4 @@ describe('Application', () => {
ReactDOM.render(<ClientApp store={store} />, div);
delete window.google;
});
it('renders in the server without crashing', () => {
render('/', {});
});
it('renders the styleguide without crashing', () => {
render('/styleguide', {});
});
it('server renders pages that do not require authentication', () => {
const urlTitles = {
'/': 'LandingPage.schemaTitle',
'/s': 'SearchPage.schemaTitle',
'/l/listing-title-slug/1234': 'ListingPage.loadingListingTitle',
'/l/1234': 'ListingPage.loadingListingTitle',
'/u/1234': 'ProfilePage.schemaTitle',
'/login': 'AuthenticationPage.schemaTitleLogin',
'/signup': 'AuthenticationPage.schemaTitleSignup',
'/recover-password': 'PasswordRecoveryPage.title',
'/this-url-should-not-be-found': 'NotFoundPage.title',
'/reset-password?t=token&e=email': 'PasswordResetPage.title',
};
forEach(urlTitles, (title, url) => {
const context = {};
const { head, body } = render(url, context);
expect(head.title).toContain(title);
// context.url will contain the URL to redirect to if a <Redirect> was used
expect(context.url).not.toBeDefined();
});
});
it('server renders redirects for pages that require authentication', () => {
const loginPath = '/login';
const signupPath = '/signup';
const urlRedirects = {
'/l/new': signupPath,
'/l/listing-title-slug/1234/new/description': signupPath,
'/l/listing-title-slug/1234/checkout': signupPath,
'/profile-settings': loginPath,
'/inbox': loginPath,
'/inbox/orders': loginPath,
'/inbox/sales': loginPath,
'/order/1234': loginPath,
'/order/1234/details': loginPath,
'/sale/1234': loginPath,
'/sale/1234/details': loginPath,
'/listings': loginPath,
'/account': loginPath,
'/account/contact-details': loginPath,
'/account/change-password': loginPath,
'/account/payments': loginPath,
'/verify-email': loginPath,
};
forEach(urlRedirects, (redirectPath, url) => {
const context = {};
const { body } = render(url, context);
expect(context.url).toEqual(redirectPath);
});
});
it('redirects to correct URLs', () => {
const urlRedirects = { '/l': '/', '/u': '/' };
forEach(urlRedirects, (redirectPath, url) => {
const context = {};
const { body } = render(url, context);
expect(context.url).toEqual(redirectPath);
});
});
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

BIN
src/assets/ideas-image.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

Some files were not shown because too many files have changed in this diff Show more