diff --git a/.env.template b/.env.template new file mode 100644 index 000000000..e9ef865c2 --- /dev/null +++ b/.env.template @@ -0,0 +1,3 @@ +API_URI=https://demo.saleor.io/graphql/ +APP_MOUNT_URI=/ +APPS_MARKETPLACE_API_URI=https://apps.saleor.io/api/v2/saleor-apps \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3b6c181a4..14ab07a2a 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ cypress/reports # Exported results file django-queries-results.html + +!.env.template \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9d1e5403f..b259bab27 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,7 +28,7 @@ ARG SKIP_SOURCEMAPS ENV API_URI ${API_URI:-http://localhost:8000/graphql/} ENV APP_MOUNT_URI ${APP_MOUNT_URI:-/dashboard/} -ENV APPS_MARKETPLACE_API_URI ${APPS_MARKETPLACE_API_URI} +ENV APPS_MARKETPLACE_API_URI ${APPS_MARKETPLACE_API_URI:-https://apps.saleor.io/api/v2/saleor-apps} ENV APPS_TUNNEL_URL_KEYWORDS ${APPS_TUNNEL_URL_KEYWORDS} ENV SALEOR_APPS_ENDPOINT=${SALEOR_APPS_ENDPOINT} ENV STATIC_URL ${STATIC_URL:-/dashboard/} diff --git a/docs/configuration.md b/docs/configuration.md index 965caa1db..ca104ceec 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -1,6 +1,12 @@ # Configuration -Create `.env` file in a root directory or set environment variables with the following values: +## Quick start + +Run `cp .env.template .env` to create default configuration that will be connected to [Saleor Demo shop](https://demo.saleor.io/dashboard/) + +## All environment variables + +Create or edit `.env` file in a root directory or set environment variables with the following values: - `API_URI` (required) - URI of Saleor GraphQL API instance. If you are running Saleor locally with the default settings, set `API_URI` to: "http://localhost:8000/graphql/". @@ -12,12 +18,6 @@ Create `.env` file in a root directory or set environment variables with the fol - `STATIC_URL` - URL where the static files are located. E.g., if you use an S3 bucket, you should set it to the bucket's URL. By default, Saleor assumes you serve static files from the root of your site at "http://localhost:9000/". -- `SALEOR_APPS_PAGE_PATH` - Path appended to `MARKETPLACE_URL` to render Saleor Apps page (deprecated). - -- `SALEOR_APPS_JSON_PATH` - Path appended to `MARKETPLACE_URL` to fetch a list of Saleor Apps as JSON (deprecated in favor of `APPS_MARKETPLACE_API_URI`). - -- `APP_TEMPLATE_GALLERY_PATH` - Path appended to `MARKETPLACE_URL` to render App Template Gallery page (deprecated). - - `APPS_MARKETPLACE_API_URI` - URI of Marketplace API to fetch list of Apps in JSON. - `APPS_TUNNEL_URL_KEYWORDS` - Custom apps tunnel URL keywords. diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index e0b5f8444..72edcbd34 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -1455,6 +1455,10 @@ "context": "collection", "string": "Hidden" }, + "9g6Y7a": { + "context": "placeholder", + "string": "Nothing installed yet." + }, "9gb9b4": { "context": "address type", "string": "Add new address" @@ -2624,6 +2628,10 @@ "context": "switch button", "string": "Is this product shippable?" }, + "IEpmGQ": { + "context": "description", + "string": "Use Saleor Cloud to access Saleor Apps" + }, "IFWHn0": { "context": "error message", "string": "Billing address is not set" diff --git a/src/config.ts b/src/config.ts index 29a974ee3..6a51c175b 100644 --- a/src/config.ts +++ b/src/config.ts @@ -7,7 +7,8 @@ export const getAppMountUri = () => window.__SALEOR_CONFIG__.APP_MOUNT_URI || getAppDefaultUri(); export const getApiUrl = () => window.__SALEOR_CONFIG__.API_URL; export const SW_INTERVAL = parseInt(process.env.SW_INTERVAL, 10) || 300; -export const IS_CLOUD_INSTANCE = process.env.IS_CLOUD_INSTANCE === "true"; +export const IS_CLOUD_INSTANCE = + window.__SALEOR_CONFIG__.IS_CLOUD_INSTANCE === "true"; /** * @deprecated */ diff --git a/src/new-apps/components/AppListCard/AppListCard.test.tsx b/src/new-apps/components/AppListCard/AppListCard.test.tsx index 39be57aa8..b0e2cde95 100644 --- a/src/new-apps/components/AppListCard/AppListCard.test.tsx +++ b/src/new-apps/components/AppListCard/AppListCard.test.tsx @@ -22,6 +22,16 @@ jest.mock("@dashboard/new-apps/context", () => ({ })), })); +jest.mock("@dashboard/config", () => { + const original = jest.requireActual("@dashboard/config"); + + return { + __esModule: true, + ...original, + IS_CLOUD_INSTANCE: true, + }; +}); + describe("Apps AppListCard", () => { it("displays released app details when released app data passed", () => { // Arrange diff --git a/src/new-apps/components/AppListCard/AppListCardActions.tsx b/src/new-apps/components/AppListCard/AppListCardActions.tsx index 0a2fb01dc..15e2f922f 100644 --- a/src/new-apps/components/AppListCard/AppListCardActions.tsx +++ b/src/new-apps/components/AppListCard/AppListCardActions.tsx @@ -1,9 +1,11 @@ +import { IS_CLOUD_INSTANCE } from "@dashboard/config"; import { AppInstallationFragment } from "@dashboard/graphql"; import { buttonMessages } from "@dashboard/intl"; import { appInstallationStatusMessages } from "@dashboard/new-apps/messages"; +import { Tooltip } from "@material-ui/core"; import { Box, Button, Text } from "@saleor/macaw-ui/next"; import React from "react"; -import { FormattedMessage } from "react-intl"; +import { FormattedMessage, useIntl } from "react-intl"; import InstallErrorAction from "./ErrorInstallAction"; import { messages } from "./messages"; @@ -27,6 +29,8 @@ const AppListCardActions: React.FC = ({ retryInstallHandler, removeInstallHandler, }) => { + const intl = useIntl(); + if ( !installHandler && !githubForkHandler && @@ -49,7 +53,7 @@ const AppListCardActions: React.FC = ({ )} - {installHandler && ( + {installHandler && IS_CLOUD_INSTANCE && ( )} + {installHandler && !IS_CLOUD_INSTANCE && ( + +
+ +
+
+ )} {installationPending && ( = props => { }); const navigate = useNavigator(); + const nothingInstalled = + appsInstallations?.length === 0 && installedApps?.length === 0; + const navigateToAppInstallPage = useCallback( (manifestUrl: string) => { navigate(AppUrls.resolveAppInstallUrl(manifestUrl)); @@ -80,6 +83,18 @@ export const AppListPage: React.FC = props => { marginY={8} > + {nothingInstalled && ( + + + {intl.formatMessage(messages.installedApps)} + + + + {intl.formatMessage(messages.nothingInstalledPlaceholder)} + + + + )} {sectionsAvailability.installed && ( <> diff --git a/src/new-apps/components/AppListPage/messages.ts b/src/new-apps/components/AppListPage/messages.ts index d44d38123..d8f7affaa 100644 --- a/src/new-apps/components/AppListPage/messages.ts +++ b/src/new-apps/components/AppListPage/messages.ts @@ -27,4 +27,9 @@ export const messages = defineMessages({ defaultMessage: "Coming Soon", description: "section header", }, + nothingInstalledPlaceholder: { + defaultMessage: "Nothing installed yet.", + description: "placeholder", + id: "9g6Y7a", + }, }); diff --git a/types.d.ts b/types.d.ts index b883a30d2..3cdfa03c0 100644 --- a/types.d.ts +++ b/types.d.ts @@ -20,5 +20,6 @@ declare interface Window { APP_TEMPLATE_GALLERY_PATH: string; APPS_MARKETPLACE_API_URI?: string; APPS_TUNNEL_URL_KEYWORDS?: string; + IS_CLOUD_INSTANCE?: string; }; } diff --git a/vite.config.js b/vite.config.js index eadfd0ea2..801a37235 100644 --- a/vite.config.js +++ b/vite.config.js @@ -66,6 +66,7 @@ export default defineConfig(({ command, mode }) => { MARKETPLACE_URL, APPS_MARKETPLACE_API_URI, APPS_TUNNEL_URL_KEYWORDS, + IS_CLOUD_INSTANCE, }, }, }),