Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[PWA-178] Gift options support in cart page #2114

Merged
merged 42 commits into from
Feb 10, 2020
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a7eab06
Added gift options UI.
revanth0212 Jan 22, 2020
9391620
Added gift options @client caching.
revanth0212 Jan 23, 2020
2056bf9
Added gift message to cache.
revanth0212 Jan 23, 2020
7fcc100
Added styles and throttle for gift message update.
revanth0212 Jan 24, 2020
c736faf
Code refactor.
revanth0212 Jan 24, 2020
47979c8
Minor.
revanth0212 Jan 24, 2020
7672a90
Fixed issue with state update.
revanth0212 Jan 24, 2020
c2edab0
Fixed throttle.
revanth0212 Jan 24, 2020
d3892cd
Code refactor.
revanth0212 Jan 24, 2020
350732a
Added comments.
revanth0212 Jan 24, 2020
f2a4d38
Making rest call to save options.
revanth0212 Jan 27, 2020
d018cb9
Changed message update to 10 second throttle.
revanth0212 Jan 27, 2020
c24ddb8
Merge branch 'develop' into revanth/cart/giftOptions
revanth0212 Jan 27, 2020
eac480f
Requesting id in case CE for giftCardSummary query.
revanth0212 Jan 27, 2020
0463a4e
Minor.
revanth0212 Jan 27, 2020
fa5aae5
Moving queries to component.
revanth0212 Jan 29, 2020
353e785
Removing REST.
revanth0212 Jan 29, 2020
0f69a9d
Minor.
revanth0212 Jan 29, 2020
a4a8819
Scoping gift options to cart in cache.
revanth0212 Jan 30, 2020
145dc92
Using lazy query instead of query.
revanth0212 Jan 30, 2020
4575979
Update gift options get resolver.
revanth0212 Jan 30, 2020
330d11d
Minor.
revanth0212 Jan 30, 2020
cd39389
Minor refactor.
revanth0212 Jan 30, 2020
6cb4b15
Added tests.
revanth0212 Jan 30, 2020
dcea0d1
Merge branch 'develop' into revanth/cart/giftOptions
revanth0212 Jan 30, 2020
35d5050
Minor.
revanth0212 Jan 31, 2020
fcfab06
Removed unnecessary export.
revanth0212 Jan 31, 2020
56ad641
PR changes.
revanth0212 Feb 4, 2020
71b3e34
Nesting gift options into its own folder.
revanth0212 Feb 4, 2020
107fdb2
Minor css change.
revanth0212 Feb 4, 2020
a4a5ffc
Merge branch 'develop' into revanth/cart/giftOptions
dpatil-magento Feb 5, 2020
1359249
Merged develop into current.
revanth0212 Feb 5, 2020
d09e61c
Minor.
revanth0212 Feb 5, 2020
9848594
Merge branch 'develop' into revanth/cart/giftOptions
sirugh Feb 5, 2020
8bb6ea4
Using glob to compile list of files to run gql validation on.
revanth0212 Feb 5, 2020
526443d
PR changes.
revanth0212 Feb 5, 2020
e8c57ba
Merge remote-tracking branch 'origin/develop' into revanth/cart/giftO…
revanth0212 Feb 6, 2020
063cfbc
Gql validator tests fix.
revanth0212 Feb 6, 2020
e095ed4
Prettier fix.
revanth0212 Feb 6, 2020
fbb5a47
Merge branch 'develop' into revanth/cart/giftOptions
dpatil-magento Feb 6, 2020
b0b001a
Minor.
revanth0212 Feb 7, 2020
89641b3
Merge branch 'develop' into revanth/cart/giftOptions
dpatil-magento Feb 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ const plugin = require('../index');

const fs = require('fs');
const eslint = require('eslint');
const glob = require('glob');

jest.mock('fs');
jest.mock('eslint');
jest.mock('glob');

test('it exports the correct command name', () => {
expect(plugin.command).toBe('validate-magento-pwa-queries');
Expand Down Expand Up @@ -56,7 +58,8 @@ describe('handler', () => {
extensions: {
'validate-magento-pwa-queries': {
clients: ['apollo', 'literal'],
filesGlob: '*.graphql'
filesGlob: '*.graphql',
ignore: ['*.js']
}
},
schemaPath: 'unit test'
Expand All @@ -75,6 +78,7 @@ describe('handler', () => {
let mockConsoleLog;
let mockConsoleWarn;
let mockProcessExit;
let globSyncSpy;

beforeAll(() => {
const noop = () => {};
Expand All @@ -91,6 +95,9 @@ describe('handler', () => {
resolveFileGlobPatterns: jest.fn()
}));

globSyncSpy = jest.spyOn(glob, 'sync');
globSyncSpy.mockImplementation(() => []);

// For happy paths, mock the file existing.
existsSyncSpy = jest.spyOn(fs, 'existsSync');
existsSyncSpy.mockImplementation(() => true);
Expand Down
11 changes: 9 additions & 2 deletions packages/graphql-cli-validate-magento-pwa-queries/lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const chalk = require('chalk');
const eslint = require('eslint');
const fs = require('fs');
const semver = require('semver');
const glob = require('glob');

let compatibilityDefinitions;
try {
Expand Down Expand Up @@ -51,7 +52,13 @@ async function validateQueries(context, argv) {

// Get the clients and filesGlob arguments from the .graphqlconfig.
const configArgs = extensions[plugin.COMMAND];
const { clients, filesGlob } = configArgs;
const { clients, filesGlob, ignore } = configArgs;

/**
* List of files to run query validation on ignoring
* files mentioned in the .graphqlconfig file.
*/
const files = glob.sync(filesGlob, { ignore });

// Ensure the schema exists.
context.spinner.start('Locating schema...');
Expand All @@ -68,7 +75,7 @@ async function validateQueries(context, argv) {
// Validate our queries against that schema.
context.spinner.start('Finding queries in files...');
const validator = getValidator({ clients, project, schemaPath });
const queryFiles = validator.resolveFileGlobPatterns([filesGlob]);
const queryFiles = validator.resolveFileGlobPatterns(files);
context.spinner.succeed();

context.spinner.start(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"semver": "~5.6.0"
},
"devDependencies": {
"glob": "~7.1.6",
"graphql-cli": "^3",
"rimraf": "~2.6.3"
},
Expand Down
131 changes: 131 additions & 0 deletions packages/peregrine/lib/talons/CartPage/GiftOptions/useGiftOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { useState, useCallback, useEffect, useMemo } from 'react';
import throttle from 'lodash.throttle';
import { useMutation, useLazyQuery } from '@apollo/react-hooks';

import { useCartContext } from '@magento/peregrine/lib/context/cart';

const useGiftOptions = props => {
const { getGiftOptionsQuery, saveGiftOptionsQuery } = props;
/**
* Using local state instead of awaiting data from mutation to avoid
* weird UX issues generated due to network latency.
*/
const [includeGiftReceipt, setIncludeGiftReceipt] = useState(false);
const [includePrintedCard, setIncludePrintedCard] = useState(false);
const [giftMessage, setGiftMessage] = useState('');

const [{ cartId }] = useCartContext();

const [fetchGiftOptions, { data }] = useLazyQuery(getGiftOptionsQuery, {
fetchPolicy: 'no-cache'
});

/**
* Fetch gift options for a given cart id.
*/
useEffect(() => {
if (cartId) {
fetchGiftOptions({
variables: {
cart_id: cartId
}
});
}
}, [cartId, fetchGiftOptions]);

const [setGiftOptions] = useMutation(saveGiftOptionsQuery);

const updateGiftOptions = useCallback(
optionsToUpdate => {
const newGiftOptions = {
cart_id: cartId,
include_gift_receipt: includeGiftReceipt,
include_printed_card: includePrintedCard,
gift_message: giftMessage,
...optionsToUpdate
};
setGiftOptions({
variables: newGiftOptions
});
},
[
setGiftOptions,
cartId,
includeGiftReceipt,
includePrintedCard,
giftMessage
]
);

/**
* Throttling message update. Only make 1 mutation
* every 1 second. This is to save on bandwidth.
*
* More info: https://lodash.com/docs/4.17.15#throttle
*/
const throttledMessageUpdate = useMemo(() => {
return throttle(
(updateGiftOptions, newGiftMessage) => {
updateGiftOptions({
gift_message: newGiftMessage
});
},
1000,
{
leading: false
}
);
}, []);

const updateGiftMessage = useCallback(
e => {
const newGiftMessage = e.target.value;
setGiftMessage(newGiftMessage);
throttledMessageUpdate(updateGiftOptions, newGiftMessage);
},
[setGiftMessage, throttledMessageUpdate, updateGiftOptions]
);

const toggleIncludeGiftReceiptFlag = useCallback(() => {
setIncludeGiftReceipt(!includeGiftReceipt);
updateGiftOptions({
include_gift_receipt: !includeGiftReceipt
});
}, [updateGiftOptions, includeGiftReceipt, setIncludeGiftReceipt]);

const toggleIncludePrintedCardFlag = useCallback(() => {
setIncludePrintedCard(!includePrintedCard);
updateGiftOptions({
include_printed_card: !includePrintedCard
});
}, [updateGiftOptions, includePrintedCard, setIncludePrintedCard]);

/**
* Once data is available from the query request, update
* the respective values.
*/
useEffect(() => {
if (data) {
const {
include_gift_receipt,
include_printed_card,
gift_message
} = data.gift_options;

setIncludeGiftReceipt(include_gift_receipt);
setIncludePrintedCard(include_printed_card);
setGiftMessage(gift_message);
}
}, [setIncludeGiftReceipt, setIncludePrintedCard, data]);

return {
includeGiftReceipt,
includePrintedCard,
giftMessage,
toggleIncludeGiftReceiptFlag,
toggleIncludePrintedCardFlag,
updateGiftMessage
};
};

export default useGiftOptions;
10 changes: 8 additions & 2 deletions packages/venia-concept/.graphqlconfig
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@
"default": "${env:MAGENTO_BACKEND_URL}/graphql"
},
"validate-magento-pwa-queries": {
"clients": ["apollo", "literal"],
"filesGlob": "../{venia-ui,venia-concept}/{lib,src}/**/*.{js,graphql,gql}"
"clients": [
"apollo",
"literal"
],
"filesGlob": "../{venia-ui,venia-concept}/{lib,src}/**/*.{js,graphql,gql}",
"ignore": [
"../venia-ui/lib/**/giftOptions.js"
]
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`it renders gift options in venia cart page 1`] = `
<div>
<ul>
<label
htmlFor="includeGiftReceipt"
>
<span>
<span>
<svg
fill="none"
height={18}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
width={18}
xmlns="http://www.w3.org/2000/svg"
>
<polyline
points="20 6 9 17 4 12"
/>
</svg>
</span>
</span>
<input
checked={true}
id="includeGiftReceipt"
name="includeGiftReceipt"
onBlur={[Function]}
onChange={[Function]}
onClick={[Function]}
type="checkbox"
/>
<span>
Include gift receipt
</span>
</label>
<p />
</ul>
<ul>
<label
htmlFor="includePrintedCard"
>
<span />
<input
checked={false}
id="includePrintedCard"
name="includePrintedCard"
onBlur={[Function]}
onChange={[Function]}
onClick={[Function]}
type="checkbox"
/>
<span>
Include printed card
</span>
</label>
<p />
</ul>
<ul />
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { createTestInstance } from '@magento/peregrine';

import GiftOptions from '../giftOptions';

jest.mock('@magento/peregrine/lib/context/cart', () => {
const state = { cartId: 'fakeCartId' };
const api = {};
const useCartContext = jest.fn(() => [state, api]);

return { useCartContext };
});

jest.mock('@apollo/react-hooks', () => {
const runQuery = jest.fn();
const queryResult = {
data: {
gift_options: {
include_gift_receipt: true,
include_printed_card: false,
gift_message: 'Sample Message'
}
},
error: null,
loading: false
};

const useLazyQuery = jest.fn(() => [runQuery, queryResult]);

const useMutation = jest.fn(() => [() => {}]);

return { useLazyQuery, useMutation };
});

test('it renders gift options in venia cart page', () => {
const instance = createTestInstance(<GiftOptions />);

expect(instance.toJSON()).toMatchSnapshot();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.root {
}

.option {
padding: 0.5rem 0rem;
}
Loading