Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add a simple page to list a few products from a GraphQL query. #27

Merged
merged 1 commit into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12,281 changes: 12,243 additions & 38 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@
"devDependencies": {
"@babel/preset-react": "^7.13.13",
"axios": "^0.21",
"laravel-mix": "^6.0.6",
"laravel-mix": "^6.0.19",
"lodash": "^4.17.19",
"postcss": "^8.1.14"
},
"dependencies": {
"@apollo/client": "^3.3.16",
"@shopify/app-bridge": "^2.0.2",
"@shopify/app-bridge-react": "^2.0.2",
"@shopify/app-bridge-utils": "^2.0.2",
"@shopify/polaris": "^6.4.0",
"graphql": "^15.5.0",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react": "^16.14.0",
"react-dom": "^16.14.0"
}
}
45 changes: 28 additions & 17 deletions resources/js/react/App.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React from 'react';
import ReactDOM from 'react-dom';
import createApp from "@shopify/app-bridge";
import {Redirect} from "@shopify/app-bridge/actions";
import {authenticatedFetch} from "@shopify/app-bridge-utils"
import {ApolloClient, gql, HttpLink, InMemoryCache} from '@apollo/client';

const TEST_QUERY = gql`query { shop {name} }`;
import {ApolloClient, HttpLink, InMemoryCache} from '@apollo/client';
import {ApolloProvider} from '@apollo/client/react';
import {AppProvider} from "@shopify/polaris";
import translations from "@shopify/polaris/locales/en.json";
import '@shopify/polaris/dist/styles.css';
import PageLayout from "./components/PageLayout";
import ProductsPage from "./components/ProductsPage";
import {Provider, useAppBridge} from '@shopify/app-bridge-react';

function userLoggedInFetch(app) {
const fetchFunction = authenticatedFetch(app);
Expand All @@ -25,13 +29,8 @@ function userLoggedInFetch(app) {
};
}

function App({shop, host, apiKey}) {
const app = createApp({
shop: shop,
host: host,
apiKey: apiKey,
});

function AppBridgeApolloProvider({children}) {
const app = useAppBridge();
const client = new ApolloClient({
link: new HttpLink({
credentials: 'same-origin',
Expand All @@ -41,14 +40,26 @@ function App({shop, host, apiKey}) {
cache: new InMemoryCache()
});

client
.query({
query: TEST_QUERY
})
.then(result => console.log(result));
return (
<ApolloProvider client={client}>
{children}
</ApolloProvider>
);
}

function App({shop, host, apiKey}) {
const config = {apiKey: apiKey, shopOrigin: shop, host: host, forceRedirect: true};

return (
<h1>Hello React</h1>
<Provider config={config}>
<AppProvider i18n={translations}>
<AppBridgeApolloProvider>
<PageLayout>
<ProductsPage/>
</PageLayout>
</AppBridgeApolloProvider>
</AppProvider>
</Provider>
);
}

Expand Down
16 changes: 16 additions & 0 deletions resources/js/react/components/PageLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {Card, Layout, Page} from "@shopify/polaris";
import React from "react";

function PageLayout({children}) {
return <Page>
<Layout>
<Layout.Section>
<Card>
{children}
</Card>
</Layout.Section>
</Layout>
</Page>
}

export default PageLayout;
31 changes: 31 additions & 0 deletions resources/js/react/components/ProductsList.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {ResourceItem, ResourceList, TextStyle} from "@shopify/polaris";
import React from "react";

export function ProductsList({data}) {

const products = data.products.edges.map((edge) => {
return {
id: edge.node.id,
title: edge.node.title,
};
});
return <ResourceList
showHeader
resourceName={{singular: 'product', plural: 'products'}}
items={products}
renderItem={({id, title}) => {

return (
<ResourceItem
id={id}
accessibilityLabel={`View details for ${title}`}
>
<h3>
<TextStyle variation="strong">{title}</TextStyle>
</h3>
</ResourceItem>
);
}}
>
</ResourceList>
}
37 changes: 37 additions & 0 deletions resources/js/react/components/ProductsPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {gql, useQuery} from '@apollo/client';
import {Banner} from '@shopify/polaris';
import React from 'react';
import {ProductsList} from "./ProductsList";
import {Loading} from '@shopify/app-bridge-react';

const PRODUCTS_QUERY = gql`{
products(first: 10) {
edges {
cursor
node {
id,
title,
onlineStoreUrl
}
}
}
}`;


function ProductsPage() {
const {loading, error, data} = useQuery(PRODUCTS_QUERY);

if (loading) return (
<Loading/>
);

if (error) return (
<Banner status="critical">
There was an issue loading products.
</Banner>
);

return <ProductsList data={data}/>;
}

export default ProductsPage;
2 changes: 1 addition & 1 deletion routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@

Route::post('/graphql', function (Request $request) {
$result = Utils::graphqlProxy($request->header(), $request->cookie(), $request->getContent());
return response($result->getDecodedBody())->withHeaders($result->getHeaders());
return response($result->getDecodedBody());
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If simply passing along all the headers doesn't work, we could come up with a list of the ones we want to set and go over the list here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's a good idea, I wasn't sure though what would be those ones. I will check the issue with the headers separately. Thought of putting it aside given that we do not using it right now.

Copy link
Collaborator

@paulomarg paulomarg May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed! Though we probably also want to make sure to forward the response code we got back!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, let me have those two points in a different PR

})->middleware('shopify.auth:online');

Route::get('/rest-example', function (Request $request) {
Expand Down
1 change: 0 additions & 1 deletion tests/Feature/ProxyGraphqlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@ public function testGraphqlProxyFetchesDataWithJWT(bool $isEmbedded)

$response->assertStatus(200);
$response->assertExactJson($testGraphqlResponse);
$response->assertHeader('response-header', 'header-value');
}

private function encodeJwtPayload(): string
Expand Down