Improve dashboard and marketplace connection (#2666)

* Change env variables related to marketplace, add navigation item

* Change apps order

* Add button to browse marketplace

* Add redirect to Saleor Apps Marketplace on button click

* Move apps tabs state to URL

* Pass theme for initial marketplace iframe load

* Improve marketplace mount

* fix types

* fix cr

* Update env variables to disable marketplace on envs other than master staging

* Extract locales

* update snapshots
This commit is contained in:
Lukasz Ostrowski 2022-11-30 17:20:20 +01:00 committed by GitHub
parent f2af4a1b23
commit e06d3bdf0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 361 additions and 450 deletions

View file

@ -17,8 +17,12 @@ jobs:
REGION: ${{ github.event.client_payload.region }} REGION: ${{ github.event.client_payload.region }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MARKETPLACE_URL: "https://apps.saleor.io/" # Disable preview when new Marketplace features are in progress.
SALEOR_APPS_ENDPOINT: "https://apps.saleor.io/api/saleor-apps" # If marketplace is done till next release this can be easily enabled
# MARKETPLACE_URL: "https://apps.saleor.io/"
# SALEOR_APPS_PAGE_PATH=saleor-apps
# SALEOR_APPS_JSON_PATH=api/saleor-apps
# APP_TEMPLATE_GALLERY_PATH=template-gallery
IS_CLOUD_INSTANCE: true IS_CLOUD_INSTANCE: true
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2

View file

@ -20,8 +20,12 @@ jobs:
SENTRY_URL_PREFIX: "~/dashboard/static" SENTRY_URL_PREFIX: "~/dashboard/static"
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MARKETPLACE_URL: "https://apps.saleor.io/" # Disable preview when new Marketplace features are in progress.
SALEOR_APPS_ENDPOINT: "https://apps.saleor.io/api/saleor-apps" # If marketplace is done till next release this can be easily enabled
# MARKETPLACE_URL: "https://apps.saleor.io/"
# SALEOR_APPS_PAGE_PATH=saleor-apps
# SALEOR_APPS_JSON_PATH=api/saleor-apps
# APP_TEMPLATE_GALLERY_PATH=template-gallery
ENVIRONMENT: demo-staging ENVIRONMENT: demo-staging
DEMO_MODE: true DEMO_MODE: true
steps: steps:

View file

@ -15,8 +15,12 @@ jobs:
SENTRY_URL_PREFIX: "~/dashboard/static" SENTRY_URL_PREFIX: "~/dashboard/static"
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MARKETPLACE_URL: "https://apps.saleor.io/" # Disable preview when new Marketplace features are in progress.
SALEOR_APPS_ENDPOINT: "https://apps.saleor.io/api/saleor-apps" # If marketplace is done till next release this can be easily enabled
# MARKETPLACE_URL: "https://apps.saleor.io/"
# SALEOR_APPS_PAGE_PATH=saleor-apps
# SALEOR_APPS_JSON_PATH=api/saleor-apps
# APP_TEMPLATE_GALLERY_PATH=template-gallery
ENVIRONMENT: demo ENVIRONMENT: demo
DEMO_MODE: true DEMO_MODE: true
steps: steps:

View file

@ -18,7 +18,9 @@ jobs:
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MARKETPLACE_URL: "https://marketplace-gray.vercel.app/" MARKETPLACE_URL: "https://marketplace-gray.vercel.app/"
SALEOR_APPS_ENDPOINT: "https://marketplace-gray.vercel.app/api/saleor-apps" SALEOR_APPS_PAGE_PATH: saleor-apps
SALEOR_APPS_JSON_PATH: api/saleor-apps
APP_TEMPLATE_GALLERY_PATH: template-gallery
ENVIRONMENT: saleor-master-staging ENVIRONMENT: saleor-master-staging
IS_CLOUD_INSTANCE: true IS_CLOUD_INSTANCE: true
steps: steps:

View file

@ -22,8 +22,12 @@ jobs:
SENTRY_URL_PREFIX: "~/dashboard/static" SENTRY_URL_PREFIX: "~/dashboard/static"
SENTRY_DSN: ${{ secrets.SENTRY_DSN }} SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
MARKETPLACE_URL: "https://apps.saleor.io/" # Disable preview when new Marketplace features are in progress.
SALEOR_APPS_ENDPOINT: "https://apps.saleor.io/api/saleor-apps" # If marketplace is done till next release this can be easily enabled
# MARKETPLACE_URL: "https://apps.saleor.io/"
# SALEOR_APPS_PAGE_PATH=saleor-apps
# SALEOR_APPS_JSON_PATH=api/saleor-apps
# APP_TEMPLATE_GALLERY_PATH=template-gallery
VERSION: ${{ github.event.inputs.git_ref || github.ref_name }} VERSION: ${{ github.event.inputs.git_ref || github.ref_name }}
IS_CLOUD_INSTANCE: true IS_CLOUD_INSTANCE: true
steps: steps:

View file

@ -81,6 +81,14 @@ Create `.env` file in a root directory or set environment variables with followi
- `STATIC_URL` - URL where the static files are located. - `STATIC_URL` - URL where the static files are located.
E.g. if you use 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/`. E.g. if you use 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/`.
- `MARKETPLACE_URL` - URL where Marketplace App can is located, if not found, will not render navigation link to Marketplace
- `SALEOR_APPS_PAGE_PATH` - Path joined to `MARKETPLACE_URL` to render Saleor Apps page
- `SALEOR_APPS_JSON_PATH` - Path joined to `MARKETPLACE_URL` to fetch list of Saleor Apps as JSON
- `APP_TEMPLATE_GALLERY_PATH` - Path joined to `MARKETPLACE_URL` to render App Template Gallery page
### Development ### Development
To start the development server run: To start the development server run:

View file

@ -1968,10 +1968,6 @@
"context": "date time attribute type", "context": "date time attribute type",
"string": "Date Time" "string": "Date Time"
}, },
"E+M17x": {
"context": "marketplace section name",
"string": "Marketplace"
},
"E22x4H": { "E22x4H": {
"context": "no card defuned alert message", "context": "no card defuned alert message",
"string": "You havent defined a gift card product!" "string": "You havent defined a gift card product!"
@ -3059,6 +3055,10 @@
"context": "collection", "context": "collection",
"string": "Not Published" "string": "Not Published"
}, },
"M2dPzK": {
"context": "app template gallery section name",
"string": "App Templates Gallery"
},
"M6s/9e": { "M6s/9e": {
"context": "unassign country, dialog header", "context": "unassign country, dialog header",
"string": "Remove from Shipping Zone" "string": "Remove from Shipping Zone"
@ -7238,6 +7238,10 @@
"context": "order total amount", "context": "order total amount",
"string": "Total" "string": "Total"
}, },
"ti4Hqw": {
"context": "saleor marketplace section name",
"string": "Saleor Apps Marketplace"
},
"tlGXkh": { "tlGXkh": {
"context": "input description", "context": "input description",
"string": "Unlimited" "string": "Unlimited"
@ -7287,6 +7291,9 @@
"u0V06N": { "u0V06N": {
"string": "Max. Order Weight" "string": "Max. Order Weight"
}, },
"u0VQMN": {
"string": "Browse Marketplace"
},
"u24Ppd": { "u24Ppd": {
"string": "This attribute cannot be assigned to this product type" "string": "This attribute cannot be assigned to this product type"
}, },

16
package-lock.json generated
View file

@ -106,7 +106,7 @@
"@pollyjs/core": "^5.0.0", "@pollyjs/core": "^5.0.0",
"@pollyjs/persister-fs": "^5.0.0", "@pollyjs/persister-fs": "^5.0.0",
"@release-it/bumper": "^2.0.0", "@release-it/bumper": "^2.0.0",
"@saleor/app-sdk": "~0.20.0", "@saleor/app-sdk": "~0.23.0",
"@sentry/webpack-plugin": "^1.14.0", "@sentry/webpack-plugin": "^1.14.0",
"@storybook/addon-storyshots": "^5.2.8", "@storybook/addon-storyshots": "^5.2.8",
"@storybook/react": "^5.1.9", "@storybook/react": "^5.1.9",
@ -6332,9 +6332,9 @@
} }
}, },
"node_modules/@saleor/app-sdk": { "node_modules/@saleor/app-sdk": {
"version": "0.20.0", "version": "0.23.0",
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.20.0.tgz", "resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.23.0.tgz",
"integrity": "sha512-3vdtnOxt5QGcb4B2o2WR2zQa9fFV3VlxvJWNu22v2Bct1RG6dfv8OrguSFpEARSN2K2E0Bq9Gr80J2vQFiIocg==", "integrity": "sha512-tlSwuMhK0CsPI+HoEPZny4hnpUWLd2uPtKH1I0B3z6/Smv8VPUV4bSEKVsPseZ97KQG472yDDaqmSzsZyo43nQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"debug": "^4.3.4", "debug": "^4.3.4",
@ -6347,7 +6347,7 @@
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"next": "^12", "next": ">=12",
"react": ">=17", "react": ">=17",
"react-dom": ">=17" "react-dom": ">=17"
} }
@ -45315,9 +45315,9 @@
} }
}, },
"@saleor/app-sdk": { "@saleor/app-sdk": {
"version": "0.20.0", "version": "0.23.0",
"resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.20.0.tgz", "resolved": "https://registry.npmjs.org/@saleor/app-sdk/-/app-sdk-0.23.0.tgz",
"integrity": "sha512-3vdtnOxt5QGcb4B2o2WR2zQa9fFV3VlxvJWNu22v2Bct1RG6dfv8OrguSFpEARSN2K2E0Bq9Gr80J2vQFiIocg==", "integrity": "sha512-tlSwuMhK0CsPI+HoEPZny4hnpUWLd2uPtKH1I0B3z6/Smv8VPUV4bSEKVsPseZ97KQG472yDDaqmSzsZyo43nQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"debug": "^4.3.4", "debug": "^4.3.4",

View file

@ -113,7 +113,7 @@
"@pollyjs/core": "^5.0.0", "@pollyjs/core": "^5.0.0",
"@pollyjs/persister-fs": "^5.0.0", "@pollyjs/persister-fs": "^5.0.0",
"@release-it/bumper": "^2.0.0", "@release-it/bumper": "^2.0.0",
"@saleor/app-sdk": "~0.20.0", "@saleor/app-sdk": "~0.23.0",
"@sentry/webpack-plugin": "^1.14.0", "@sentry/webpack-plugin": "^1.14.0",
"@storybook/addon-storyshots": "^5.2.8", "@storybook/addon-storyshots": "^5.2.8",
"@storybook/react": "^5.1.9", "@storybook/react": "^5.1.9",

View file

@ -1,17 +1,22 @@
import { AppPagePathSegment } from "@saleor/apps/hooks/useAppsPageNavigation";
import { PageTab, PageTabs } from "@saleor/macaw-ui"; import { PageTab, PageTabs } from "@saleor/macaw-ui";
import React, { ComponentProps } from "react"; import React, { ComponentProps } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
export type AppPageTabValue = /**
| "THIRD_PARTY" * Bind tab value to path segment to avoid unnecessary mapping
| "WEBHOOKS_AND_EVENTS" */
| "SALEOR_APPS"; const TabValue: Record<string, AppPagePathSegment> = {
SALEOR_APPS: "saleor-apps",
THIRD_PARTY: "third-party",
WEBHOOKS_AND_EVENTS: "webhooks-and-events",
};
type AllProps = ComponentProps<typeof PageTabs>; type AllProps = ComponentProps<typeof PageTabs>;
type AvailableProps = Omit<AllProps, "children" | "onChange" | "value"> & { type AvailableProps = Omit<AllProps, "children" | "onChange" | "value"> & {
value: AppPageTabValue; value: AppPagePathSegment;
showSaleorApps: boolean; showSaleorApps: boolean;
onChange(newValue: AppPageTabValue): void; onChange(newValue: AppPagePathSegment): void;
}; };
export const AppPageTabs = ({ showSaleorApps, ...props }: AvailableProps) => { export const AppPageTabs = ({ showSaleorApps, ...props }: AvailableProps) => {
@ -19,23 +24,23 @@ export const AppPageTabs = ({ showSaleorApps, ...props }: AvailableProps) => {
return ( return (
<PageTabs {...props}> <PageTabs {...props}>
<PageTab <PageTab
value="THIRD_PARTY" value={TabValue.WEBHOOKS_AND_EVENTS}
label={intl.formatMessage({
defaultMessage: "3rd party apps",
id: "J8frvS",
})}
/>
<PageTab
value="WEBHOOKS_AND_EVENTS"
id="WEBHOOKS_AND_EVENTS" id="WEBHOOKS_AND_EVENTS"
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Webhooks & Events", defaultMessage: "Webhooks & Events",
id: "UxTSw7", id: "UxTSw7",
})} })}
/> />
<PageTab
value={TabValue.THIRD_PARTY}
label={intl.formatMessage({
defaultMessage: "3rd party apps",
id: "J8frvS",
})}
/>
{showSaleorApps && ( {showSaleorApps && (
<PageTab <PageTab
value="SALEOR_APPS" value={TabValue.SALEOR_APPS}
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Saleor Apps", defaultMessage: "Saleor Apps",
id: "+niGip", id: "+niGip",

View file

@ -1,16 +1,16 @@
import { import { AppPageTabs } from "@saleor/apps/components/AppPageTabs/AppPageTabs";
AppPageTabs, import { useAppsPageNavigation } from "@saleor/apps/hooks/useAppsPageNavigation";
AppPageTabValue,
} from "@saleor/apps/components/AppPageTabs/AppPageTabs";
import { useSaleorApps } from "@saleor/apps/hooks/useSaleorApps"; import { useSaleorApps } from "@saleor/apps/hooks/useSaleorApps";
import CardSpacer from "@saleor/components/CardSpacer"; import CardSpacer from "@saleor/components/CardSpacer";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
import { AppsInstallationsQuery, AppsListQuery } from "@saleor/graphql"; import { AppsInstallationsQuery, AppsListQuery } from "@saleor/graphql";
import useNavigator from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import { marketplaceUrlResolver } from "@saleor/marketplace/marketplace-url-resolver";
import { ListProps } from "@saleor/types"; import { ListProps } from "@saleor/types";
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo } from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { FormattedMessage, useIntl } from "react-intl";
import AppsInProgress from "../AppsInProgress/AppsInProgress"; import AppsInProgress from "../AppsInProgress/AppsInProgress";
@ -33,6 +33,10 @@ const useStyles = makeStyles(
topTabs: { topTabs: {
marginBottom: theme.spacing(4), marginBottom: theme.spacing(4),
}, },
browseMarketplaceContainer: {
display: "flex",
justifyContent: "flex-end",
},
}), }),
{ {
name: "AppsListPageStyles", name: "AppsListPageStyles",
@ -56,6 +60,8 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
saleorAppsEnabled, saleorAppsEnabled,
} = useSaleorApps(); } = useSaleorApps();
const { updatePath, activeTab } = useAppsPageNavigation();
useEffect(() => { useEffect(() => {
if (saleorAppsEnabled) { if (saleorAppsEnabled) {
fetchApps(); fetchApps();
@ -64,7 +70,7 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
const styles = useStyles(); const styles = useStyles();
const intl = useIntl(); const intl = useIntl();
const [activeTab, setActiveTab] = useState<AppPageTabValue>("THIRD_PARTY"); const navigate = useNavigator();
const appsInProgress = appsInProgressList?.appsInstallations; const appsInProgress = appsInProgressList?.appsInstallations;
@ -93,7 +99,7 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
const renderContent = () => { const renderContent = () => {
switch (activeTab) { switch (activeTab) {
case "THIRD_PARTY": { case "third-party": {
return ( return (
<> <>
<p> <p>
@ -129,7 +135,7 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
</> </>
); );
} }
case "WEBHOOKS_AND_EVENTS": { case "webhooks-and-events": {
return ( return (
<> <>
<p> <p>
@ -147,7 +153,7 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
</> </>
); );
} }
case "SALEOR_APPS": { case "saleor-apps": {
return ( return (
<> <>
<p> <p>
@ -167,6 +173,19 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
onRemove={onInstalledAppRemove} onRemove={onInstalledAppRemove}
{...listProps} {...listProps}
/> />
<div className={styles.browseMarketplaceContainer}>
<Button
variant="primary"
onClick={() => {
navigate(marketplaceUrlResolver.getSaleorAppsDashboardPath());
}}
>
<FormattedMessage
defaultMessage="Browse Marketplace"
id="u0VQMN"
/>
</Button>
</div>
</> </>
); );
} }
@ -179,7 +198,7 @@ const AppsListPage: React.FC<AppsListPageProps> = ({
<AppPageTabs <AppPageTabs
showSaleorApps={saleorAppsEnabled} showSaleorApps={saleorAppsEnabled}
className={styles.topTabs} className={styles.topTabs}
onChange={setActiveTab} onChange={updatePath}
value={activeTab} value={activeTab}
/> />
{renderContent()} {renderContent()}

View file

@ -0,0 +1,43 @@
import { appsSection } from "@saleor/apps/urls";
import useNavigator from "@saleor/hooks/useNavigator";
import { useCallback, useMemo } from "react";
import useRouter from "use-react-router";
export type AppPagePathSegment =
| "webhooks-and-events"
| "third-party"
| "saleor-apps";
const defaultTab: AppPagePathSegment = "webhooks-and-events";
const appTypeQueryParam = "type";
export const useAppsPageNavigation = () => {
const navigate = useNavigator();
const {
location: { search },
} = useRouter();
const updatePath = useCallback(
(value: AppPagePathSegment) => {
const qs = new URLSearchParams({
[appTypeQueryParam]: value,
}).toString();
navigate(`${appsSection}?${qs}`, { replace: true, resetScroll: true });
},
[navigate],
);
const activeTab: AppPagePathSegment = useMemo(
() =>
(new URLSearchParams(search).get(
appTypeQueryParam,
) as AppPagePathSegment) ?? defaultTab,
[search],
);
return {
updatePath,
activeTab,
};
};

View file

@ -1,4 +1,4 @@
import { SALEOR_APPS_ENDPOINT } from "@saleor/config"; import { marketplaceUrlResolver } from "@saleor/marketplace/marketplace-url-resolver";
import { useCallback, useState } from "react"; import { useCallback, useState } from "react";
export interface SaleorApp { export interface SaleorApp {
@ -6,7 +6,7 @@ export interface SaleorApp {
hostname: string; hostname: string;
} }
const saleorAppsEnabled = Boolean(SALEOR_APPS_ENDPOINT); const saleorAppsEnabled = marketplaceUrlResolver.checkMarketplaceConfigExists();
export const useSaleorApps = () => { export const useSaleorApps = () => {
const [apps, setApps] = useState<SaleorApp[] | undefined>(undefined); const [apps, setApps] = useState<SaleorApp[] | undefined>(undefined);
@ -16,7 +16,7 @@ export const useSaleorApps = () => {
return; return;
} }
return fetch(SALEOR_APPS_ENDPOINT) return fetch(marketplaceUrlResolver.getSaleorAppsJsonEndpoint())
.then(response => response.json()) .then(response => response.json())
.then((data: SaleorApp[]) => { .then((data: SaleorApp[]) => {
if ( if (

View file

@ -18,7 +18,7 @@ import { giftCardListUrl } from "@saleor/giftCards/urls";
import { PermissionEnum, UserFragment } from "@saleor/graphql"; import { PermissionEnum, UserFragment } from "@saleor/graphql";
import { commonMessages, sectionNames } from "@saleor/intl"; import { commonMessages, sectionNames } from "@saleor/intl";
import { SidebarMenuItem } from "@saleor/macaw-ui"; import { SidebarMenuItem } from "@saleor/macaw-ui";
import { marketplaceUrl } from "@saleor/marketplace/urls"; import { marketplaceUrlResolver } from "@saleor/marketplace/marketplace-url-resolver";
import { pageListPath } from "@saleor/pages/urls"; import { pageListPath } from "@saleor/pages/urls";
import { IntlShape } from "react-intl"; import { IntlShape } from "react-intl";
@ -76,8 +76,14 @@ function useMenuStructure(
{ {
ariaLabel: "marketplace", ariaLabel: "marketplace",
label: intl.formatMessage(sectionNames.marketplace), label: intl.formatMessage(sectionNames.marketplace),
id: "marketplace", id: "marketplace-saleor-apps",
url: marketplaceUrl, url: marketplaceUrlResolver.getSaleorAppsDashboardPath(),
},
{
ariaLabel: "marketplace",
label: intl.formatMessage(sectionNames.appTemplateGallery),
id: "marketplace-template-gallery",
url: marketplaceUrlResolver.getTemplateGalleryDashboardPath(),
}, },
], ],
}; };

View file

@ -8,8 +8,13 @@ export const getAppMountUri = () =>
export const getApiUrl = () => window.__SALEOR_CONFIG__.API_URL; export const getApiUrl = () => window.__SALEOR_CONFIG__.API_URL;
export const SW_INTERVAL = parseInt(process.env.SW_INTERVAL, 10); export const SW_INTERVAL = parseInt(process.env.SW_INTERVAL, 10);
export const IS_CLOUD_INSTANCE = process.env.IS_CLOUD_INSTANCE === "true"; export const IS_CLOUD_INSTANCE = process.env.IS_CLOUD_INSTANCE === "true";
export const MARKETPLACE_URL = process.env.MARKETPLACE_URL; export const MARKETPLACE_URL = window.__SALEOR_CONFIG__.MARKETPLACE_URL;
export const SALEOR_APPS_ENDPOINT = process.env.SALEOR_APPS_ENDPOINT; export const MARKETPLACE_SALEOR_APPS_PAGE_PATH =
window.__SALEOR_CONFIG__.SALEOR_APPS_PAGE_PATH;
export const MARKETPLACE_SALEOR_APPS_JSON_PATH =
window.__SALEOR_CONFIG__.SALEOR_APPS_JSON_PATH;
export const MARKETPLACE_APP_TEMPLATE_GALLERY_PATH =
window.__SALEOR_CONFIG__.APP_TEMPLATE_GALLERY_PATH;
export const DEFAULT_INITIAL_SEARCH_DATA: SearchVariables = { export const DEFAULT_INITIAL_SEARCH_DATA: SearchVariables = {
after: null, after: null,

View file

@ -10,8 +10,12 @@
<title>Saleor e-commerce</title> <title>Saleor e-commerce</title>
<script> <script>
window.__SALEOR_CONFIG__ = { window.__SALEOR_CONFIG__ = {
API_URL: "<%- API_URL %>", API_URL: "<%= API_URL %>",
APP_MOUNT_URI: "<%- APP_MOUNT_URI %>", APP_MOUNT_URI: "<%= APP_MOUNT_URI %>",
MARKETPLACE_URL: "<%= MARKETPLACE_URL %>",
SALEOR_APPS_PAGE_PATH: "<%= SALEOR_APPS_PAGE_PATH %>",
SALEOR_APPS_JSON_PATH: "<%= SALEOR_APPS_JSON_PATH %>",
APP_TEMPLATE_GALLERY_PATH: "<%= APP_TEMPLATE_GALLERY_PATH %>",
}; };
</script> </script>
</head> </head>

View file

@ -397,9 +397,14 @@ export const sectionNames = defineMessages({
description: "home section name", description: "home section name",
}, },
marketplace: { marketplace: {
id: "E+M17x", id: "ti4Hqw",
defaultMessage: "Marketplace", defaultMessage: "Saleor Apps Marketplace",
description: "marketplace section name", description: "saleor marketplace section name",
},
appTemplateGallery: {
id: "M2dPzK",
defaultMessage: "App Templates Gallery",
description: "app template gallery section name",
}, },
navigation: { navigation: {
id: "9C7PZE", id: "9C7PZE",

View file

@ -6,17 +6,28 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import { MARKETPLACE_URL } from "@saleor/config"; import { MARKETPLACE_URL } from "@saleor/config";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import React from "react"; import { marketplaceUrlResolver } from "@saleor/marketplace/marketplace-url-resolver";
import { marketplaceUrl } from "@saleor/marketplace/urls";
import React, { useMemo } from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import useRouter from "use-react-router";
import { useStyles } from "./styles"; import { useStyles } from "./styles";
const getDeepPath = (path: string) => path.replace(marketplaceUrl, "");
const Component = () => { const Component = () => {
const classes = useStyles(); const classes = useStyles();
const intl = useIntl(); const intl = useIntl();
const navigate = useNavigator(); const navigate = useNavigator();
const router = useRouter();
if (!MARKETPLACE_URL) { const marketplaceUrl = useMemo(
() => new URL(getDeepPath(router.location.pathname), MARKETPLACE_URL).href,
[router.location.pathname],
);
if (!marketplaceUrlResolver.checkMarketplaceConfigExists()) {
return <NotFoundPage onBack={() => navigate("/")} />; return <NotFoundPage onBack={() => navigate("/")} />;
} }
@ -26,7 +37,7 @@ const Component = () => {
<Container> <Container>
<PreviewPill className={classes.previewPill} /> <PreviewPill className={classes.previewPill} />
<AppFrame <AppFrame
src={MARKETPLACE_URL} src={marketplaceUrl}
// Marketplace doesn't require app token nor id // Marketplace doesn't require app token nor id
appToken="" appToken=""
appId="" appId=""

View file

@ -0,0 +1,27 @@
import { MarketplaceUrlResolver } from "@saleor/marketplace/marketplace-url-resolver";
describe("MarketplaceUrlResolver", function() {
it("Resolves deep marketplace url from full path", () => {
const resolver = new MarketplaceUrlResolver();
expect(
resolver.getMarketplaceDeepUrlFromPath("/marketplace/saleor-apps"),
).toEqual("/saleor-apps");
});
it("Generates full dashboard url that points to Marketplace - Saleor Apps", () => {
const resolver = new MarketplaceUrlResolver();
expect(resolver.getSaleorAppsDashboardPath()).toEqual(
"/marketplace/saleor-apps",
);
});
it("Generates full dashboard url that points to Marketplace - App Template Gallery", () => {
const resolver = new MarketplaceUrlResolver();
expect(resolver.getTemplateGalleryDashboardPath()).toEqual(
"/marketplace/template-gallery",
);
});
});

View file

@ -0,0 +1,43 @@
import {
MARKETPLACE_APP_TEMPLATE_GALLERY_PATH,
MARKETPLACE_SALEOR_APPS_JSON_PATH,
MARKETPLACE_SALEOR_APPS_PAGE_PATH,
MARKETPLACE_URL,
} from "@saleor/config";
import urlJoin from "url-join";
export class MarketplaceUrlResolver {
private rootSection = "/marketplace";
private marketplaceAppBaseUrl = MARKETPLACE_URL;
private saleorAppsPath = MARKETPLACE_SALEOR_APPS_PAGE_PATH;
private saleorAppsJsonPath = MARKETPLACE_SALEOR_APPS_JSON_PATH;
private templateGalleryJsonPath = MARKETPLACE_APP_TEMPLATE_GALLERY_PATH;
checkMarketplaceConfigExists() {
return Boolean(
this.marketplaceAppBaseUrl &&
this.saleorAppsPath &&
this.saleorAppsJsonPath &&
this.templateGalleryJsonPath,
);
}
getMarketplaceDeepUrlFromPath(path: string) {
return path.replace(this.rootSection, "");
}
getTemplateGalleryDashboardPath() {
return urlJoin(this.rootSection, MARKETPLACE_APP_TEMPLATE_GALLERY_PATH);
}
getSaleorAppsDashboardPath() {
return urlJoin(this.rootSection, MARKETPLACE_SALEOR_APPS_PAGE_PATH);
}
getSaleorAppsJsonEndpoint() {
return urlJoin(this.marketplaceAppBaseUrl, this.saleorAppsJsonPath);
}
}
export const marketplaceUrlResolver = new MarketplaceUrlResolver();

View file

@ -25434,6 +25434,7 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
<button <button
aria-selected="true" aria-selected="true"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="0" tabindex="0"
type="button" type="button"
@ -25441,7 +25442,7 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
3rd party apps Webhooks & Events
</span> </span>
<span <span
class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id" class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id"
@ -25451,7 +25452,6 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
<button <button
aria-selected="false" aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="-1" tabindex="-1"
type="button" type="button"
@ -25459,17 +25459,30 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
Webhooks & Events 3rd party apps
</span>
</button>
<button
aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
role="tab"
tabindex="-1"
type="button"
>
<span
class="MuiTab-wrapper-id"
>
Saleor Apps
</span> </span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<p> <p>
Third party apps are installed with App Manifests. They contain UI accessible from dashboard and can extend it. Local apps are custom webhooks & token pairs that can be used to connect apps and access Saleor API.
</p> </p>
<div <div
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id" class="MuiPaper-root-id MuiCard-root-id AppList-customApps-id MuiPaper-elevation0-id MuiPaper-rounded-id"
> >
<div <div
class="MuiCardHeader-root-id" class="MuiCardHeader-root-id"
@ -25480,220 +25493,31 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
<span <span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id" class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
> >
Ongoing Installations Internal Apps
</span>
</div>
</div>
<div
class="ResponsiveTable-root-id ResponsiveTable-root-id"
>
<table
class="MuiTable-root-id"
>
<tbody
class="MuiTableBody-root-id"
>
<tr
class="MuiTableRow-root-id AppList-tableRow-id"
>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id"
>
<span
data-tc="name"
>
app
</span>
</td>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colAction-id AppList-colInstallAction-id"
>
<div
class="MuiTypography-root-id AppList-error-id MuiTypography-body2-id"
>
Problem occured during installation
<button
class="TooltipMountWrapper-wrapper-id"
>
<span
class="Indicator-wrapper-id Indicator-wrapper-id"
>
<svg
class="Indicator-absolute-id"
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<circle
class="Indicator-circlePath-id Indicator-circlePath-id"
cx="12"
cy="12"
r="12"
/>
</svg>
<svg
class="Indicator-absolute-id"
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m8 8 8 8m0-8-8 8"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
/>
</svg>
</span>
</button>
</div>
<button
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id MuiButton-outlinedSizeSmall-id MuiButton-sizeSmall-id"
tabindex="0"
type="button"
>
<span
class="MuiButton-label-id"
>
Retry
</span>
</button>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MacawIcon-root-id"
fill="none"
focusable="false"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 10v8m3-8v8m3-8v8M5 4.5V21a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4.5m-14 0H4m1 0h4m10 0h1m-1 0h-4m-6 0V3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1.5m-6 0h6"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
/>
</svg>
</button>
</td>
</tr>
<tr
class="MuiTableRow-root-id AppList-tableRow-id"
>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id"
>
<span
data-tc="name"
>
app pending
</span>
</td>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colAction-id AppList-colInstallAction-id"
>
<div
class="MuiTypography-root-id AppList-text-id MuiTypography-body2-id"
>
Installing app...
</div>
<div
class="AppList-colSpinner-id"
>
<div
class="MuiCircularProgress-root-id MuiCircularProgress-colorSecondary-id MuiCircularProgress-indeterminate-id"
role="progressbar"
style="width:20px;height:20px"
>
<svg
class="MuiCircularProgress-svg-id"
viewBox="22 22 44 44"
>
<circle
class="MuiCircularProgress-circle-id MuiCircularProgress-circleIndeterminate-id"
cx="44"
cy="44"
fill="none"
r="20.2"
stroke-width="3.6"
/>
</svg>
</div>
</div>
</td>
</tr>
<tr
class="MuiTableRow-root-id AppList-tableRow-id"
>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id"
>
<span
data-tc="name"
>
app success
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiPaper-root-id MuiCard-root-id AppList-apps-id MuiPaper-elevation0-id MuiPaper-rounded-id"
>
<div
class="MuiCardHeader-root-id"
>
<div
class="MuiCardHeader-content-id"
>
<span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
>
Third Party Apps
</span> </span>
</div> </div>
<div <div
class="MuiCardHeader-action-id" class="MuiCardHeader-action-id"
> >
<button <a
aria-disabled="false"
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id"
data-test-id="add-app-from-manifest" data-test-id="create-app"
href="/apps/custom/add"
role="button"
tabindex="0" tabindex="0"
type="button"
> >
<span <span
class="MuiButton-label-id" class="MuiButton-label-id"
> >
Install with App Manifest Create App
</span> </span>
</button> </a>
</div> </div>
</div> </div>
<div <div
class="ResponsiveTable-root-id ResponsiveTable-root-id" class="ResponsiveTable-root-id ResponsiveTable-root-id"
> >
<a
class="TableRowLink-link-id"
href="/apps/QXBwOjE3Ng%3D%3D/app"
/>
<a
class="TableRowLink-link-id"
href="/apps/QXBwOjE3Ng%3D%3D/app"
/>
<table <table
class="MuiTable-root-id" class="MuiTable-root-id"
> >
@ -25701,7 +25525,7 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
class="MuiTableBody-root-id" class="MuiTableBody-root-id"
> >
<tr <tr
class="MuiTableRow-root-id AppList-tableRow-id MuiTableRow-hover-id" class="MuiTableRow-root-id AppList-tableRow-id"
> >
<td <td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id" class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id"
@ -25710,162 +25534,12 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
class="AppList-appName-id" class="AppList-appName-id"
data-tc="name" data-tc="name"
> >
app app custom
</span> </span>
</td> </td>
<td <td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colAction-id" class="MuiTableCell-root-id MuiTableCell-body-id AppList-colAction-id"
> >
<div
class="MuiTypography-root-id AppManifestTableDisplay-manifestText-id MuiTypography-body1-id"
>
localhost:3000
</div>
<span
class="MuiSwitch-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiSwitch-switchBase-id MuiSwitch-colorSecondary-id PrivateSwitchBase-checked-id MuiSwitch-checked-id"
>
<span
class="MuiIconButton-label-id"
>
<input
checked=""
class="PrivateSwitchBase-input-id MuiSwitch-input-id"
type="checkbox"
/>
<span
class="MuiSwitch-thumb-id"
/>
</span>
</span>
<span
class="MuiSwitch-track-id"
/>
</span>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MacawIcon-root-id"
fill="none"
focusable="false"
height="25"
viewBox="0 0 24 25"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 11V7.414a1 1 0 0 0-.293-.707l-3.415-3.414A1 1 0 0 0 14.585 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h5M8 11h8m-8 3h8m-8 3h3m4 2 1.5 1.5L20 17"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
/>
</svg>
</button>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MacawIcon-root-id"
fill="none"
focusable="false"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M9 10v8m3-8v8m3-8v8M5 4.5V21a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4.5m-14 0H4m1 0h4m10 0h1m-1 0h-4m-6 0V3a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v1.5m-6 0h6"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
/>
</svg>
</button>
</td>
</tr>
<tr
class="MuiTableRow-root-id AppList-tableRow-id MuiTableRow-hover-id"
>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colName-id"
>
<span
class="AppList-appName-id"
data-tc="name"
>
app1
</span>
</td>
<td
class="MuiTableCell-root-id MuiTableCell-body-id AppList-colAction-id"
>
<div
class="MuiTypography-root-id AppManifestTableDisplay-manifestText-id MuiTypography-body1-id"
>
localhost:3000
</div>
<span
class="MuiSwitch-root-id"
>
<span
aria-disabled="false"
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiSwitch-switchBase-id MuiSwitch-colorSecondary-id"
>
<span
class="MuiIconButton-label-id"
>
<input
class="PrivateSwitchBase-input-id MuiSwitch-input-id"
type="checkbox"
/>
<span
class="MuiSwitch-thumb-id"
/>
</span>
</span>
<span
class="MuiSwitch-track-id"
/>
</span>
<button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary"
tabindex="0"
type="button"
>
<svg
aria-hidden="true"
class="MuiSvgIcon-root-id MacawIcon-root-id"
fill="none"
focusable="false"
height="25"
viewBox="0 0 24 25"
width="24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M19 11V7.414a1 1 0 0 0-.293-.707l-3.415-3.414A1 1 0 0 0 14.585 3H6a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1h5M8 11h8m-8 3h8m-8 3h3m4 2 1.5 1.5L20 17"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="1.5"
/>
</svg>
</button>
<button <button
class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id" class="MuiButtonBase-root-id IconButton-secondary-id IconButton-hoverOutline-id"
color="primary" color="primary"
@ -25897,9 +25571,6 @@ exports[`Storyshots Views / Apps / Apps list default 1`] = `
</table> </table>
</div> </div>
</div> </div>
<div
class="CardSpacer-spacer-id"
/>
</div> </div>
</div> </div>
`; `;
@ -25946,6 +25617,7 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
<button <button
aria-selected="true" aria-selected="true"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="0" tabindex="0"
type="button" type="button"
@ -25953,7 +25625,7 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
3rd party apps Webhooks & Events
</span> </span>
<span <span
class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id" class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id"
@ -25963,7 +25635,6 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
<button <button
aria-selected="false" aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="-1" tabindex="-1"
type="button" type="button"
@ -25971,17 +25642,30 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
Webhooks & Events 3rd party apps
</span>
</button>
<button
aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
role="tab"
tabindex="-1"
type="button"
>
<span
class="MuiTab-wrapper-id"
>
Saleor Apps
</span> </span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<p> <p>
Third party apps are installed with App Manifests. They contain UI accessible from dashboard and can extend it. Local apps are custom webhooks & token pairs that can be used to connect apps and access Saleor API.
</p> </p>
<div <div
class="MuiPaper-root-id MuiCard-root-id AppList-apps-id MuiPaper-elevation0-id MuiPaper-rounded-id" class="MuiPaper-root-id MuiCard-root-id AppList-customApps-id MuiPaper-elevation0-id MuiPaper-rounded-id"
> >
<div <div
class="MuiCardHeader-root-id" class="MuiCardHeader-root-id"
@ -25992,24 +25676,26 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
<span <span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id" class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
> >
Third Party Apps Internal Apps
</span> </span>
</div> </div>
<div <div
class="MuiCardHeader-action-id" class="MuiCardHeader-action-id"
> >
<button <a
aria-disabled="false"
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id"
data-test-id="add-app-from-manifest" data-test-id="create-app"
href="/apps/custom/add"
role="button"
tabindex="0" tabindex="0"
type="button"
> >
<span <span
class="MuiButton-label-id" class="MuiButton-label-id"
> >
Install with App Manifest Create App
</span> </span>
</button> </a>
</div> </div>
</div> </div>
<div <div
@ -26040,9 +25726,6 @@ exports[`Storyshots Views / Apps / Apps list loading 1`] = `
</table> </table>
</div> </div>
</div> </div>
<div
class="CardSpacer-spacer-id"
/>
</div> </div>
</div> </div>
`; `;
@ -26089,6 +25772,7 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<button <button
aria-selected="true" aria-selected="true"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id MuiTab-selected-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="0" tabindex="0"
type="button" type="button"
@ -26096,7 +25780,7 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
3rd party apps Webhooks & Events
</span> </span>
<span <span
class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id" class="PrivateTabIndicator-root-id PrivateTabIndicator-colorSecondary-id MuiTabs-indicator-id"
@ -26106,7 +25790,6 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<button <button
aria-selected="false" aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id" class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
id="WEBHOOKS_AND_EVENTS"
role="tab" role="tab"
tabindex="-1" tabindex="-1"
type="button" type="button"
@ -26114,17 +25797,30 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<span <span
class="MuiTab-wrapper-id" class="MuiTab-wrapper-id"
> >
Webhooks & Events 3rd party apps
</span>
</button>
<button
aria-selected="false"
class="MuiButtonBase-root-id MuiTab-root-id PageTab-tabRoot-id MuiTab-textColorInherit-id"
role="tab"
tabindex="-1"
type="button"
>
<span
class="MuiTab-wrapper-id"
>
Saleor Apps
</span> </span>
</button> </button>
</div> </div>
</div> </div>
</div> </div>
<p> <p>
Third party apps are installed with App Manifests. They contain UI accessible from dashboard and can extend it. Local apps are custom webhooks & token pairs that can be used to connect apps and access Saleor API.
</p> </p>
<div <div
class="MuiPaper-root-id MuiCard-root-id AppList-apps-id MuiPaper-elevation0-id MuiPaper-rounded-id" class="MuiPaper-root-id MuiCard-root-id AppList-customApps-id MuiPaper-elevation0-id MuiPaper-rounded-id"
> >
<div <div
class="MuiCardHeader-root-id" class="MuiCardHeader-root-id"
@ -26135,24 +25831,26 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<span <span
class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id" class="MuiTypography-root-id MuiCardHeader-title-id MuiTypography-h5-id MuiTypography-displayBlock-id"
> >
Third Party Apps Internal Apps
</span> </span>
</div> </div>
<div <div
class="MuiCardHeader-action-id" class="MuiCardHeader-action-id"
> >
<button <a
aria-disabled="false"
class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id" class="MuiButtonBase-root-id MuiButton-root-id MuiButton-outlined-id Button-buttonDefault-id MuiButton-outlinedPrimary-id"
data-test-id="add-app-from-manifest" data-test-id="create-app"
href="/apps/custom/add"
role="button"
tabindex="0" tabindex="0"
type="button"
> >
<span <span
class="MuiButton-label-id" class="MuiButton-label-id"
> >
Install with App Manifest Create App
</span> </span>
</button> </a>
</div> </div>
</div> </div>
<div <div
@ -26173,7 +25871,7 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
<div <div
class="MuiTypography-root-id AppList-text-id MuiTypography-body2-id" class="MuiTypography-root-id AppList-text-id MuiTypography-body2-id"
> >
You dont have any installed apps in your dashboard Your custom-created apps will be shown here.
</div> </div>
</td> </td>
</tr> </tr>
@ -26181,9 +25879,6 @@ exports[`Storyshots Views / Apps / Apps list no data 1`] = `
</table> </table>
</div> </div>
</div> </div>
<div
class="CardSpacer-spacer-id"
/>
</div> </div>
</div> </div>
`; `;

View file

@ -3,4 +3,8 @@ document.getElementById = () => document.createElement("div");
window.__SALEOR_CONFIG__ = { window.__SALEOR_CONFIG__ = {
API_URL: "http://localhost:8000/graphql/", API_URL: "http://localhost:8000/graphql/",
APP_MOUNT_URI: "/", APP_MOUNT_URI: "/",
MARKETPLACE_URL: "http//localhost:3000",
SALEOR_APPS_PAGE_PATH: "/saleor-apps",
SALEOR_APPS_JSON_PATH: "/api/saleor-apps",
APP_TEMPLATE_GALLERY_PATH: "/template-gallery",
}; };

4
types.d.ts vendored
View file

@ -10,5 +10,9 @@ declare interface Window {
__SALEOR_CONFIG__: { __SALEOR_CONFIG__: {
API_URL: string; API_URL: string;
APP_MOUNT_URI: string; APP_MOUNT_URI: string;
MARKETPLACE_URL: string;
SALEOR_APPS_PAGE_PATH: string;
SALEOR_APPS_JSON_PATH: string;
APP_TEMPLATE_GALLERY_PATH: string;
}; };
} }

View file

@ -24,6 +24,9 @@ export default defineConfig(({ command, mode }) => {
SENTRY_DSN, SENTRY_DSN,
ENVIRONMENT, ENVIRONMENT,
STATIC_URL, STATIC_URL,
SALEOR_APPS_PAGE_PATH,
SALEOR_APPS_JSON_PATH,
APP_TEMPLATE_GALLERY_PATH,
} = env; } = env;
const enableSentry = const enableSentry =
@ -38,6 +41,10 @@ export default defineConfig(({ command, mode }) => {
data: { data: {
API_URL: API_URI, API_URL: API_URI,
APP_MOUNT_URI, APP_MOUNT_URI,
SALEOR_APPS_PAGE_PATH,
SALEOR_APPS_JSON_PATH,
APP_TEMPLATE_GALLERY_PATH,
MARKETPLACE_URL,
}, },
}, },
}), }),