Update Dockerfile (#2523)
Co-authored-by: Francisco Marques <franciscopcmarques@gmail.com>
This commit is contained in:
parent
1eecdfa5c1
commit
ac063c6410
29 changed files with 222 additions and 76 deletions
74
.github/workflows/publish-containers.yml
vendored
Normal file
74
.github/workflows/publish-containers.yml
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
name: Publish container image
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
# Matches stable and pre-releases
|
||||
- "[0-9]+.[0-9]+.[0-9]+*"
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-20.04
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Outputs the name of the repository (owner/repo)
|
||||
- name: Get image name
|
||||
id: image
|
||||
run: |
|
||||
IMAGE_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')
|
||||
echo ::set-output name=image_name::ghcr.io/${IMAGE_NAME}
|
||||
|
||||
# Tags stable versions as :latest
|
||||
# Pre-releases, alphas, etc. as :snapshot
|
||||
- name: Output image tags from git tag events
|
||||
if: ${{ startsWith(github.ref, 'refs/tags/') }}
|
||||
run: |
|
||||
# Remove everything else than the tagged version
|
||||
DASHBOARD_VERSION=${GITHUB_REF#refs/tags/}
|
||||
echo "
|
||||
DASHBOARD_VERSION=${DASHBOARD_VERSION}
|
||||
CONTAINER_TAGS=${{ steps.image.outputs.image_name }}:${DASHBOARD_VERSION}
|
||||
" >> "${GITHUB_ENV}"
|
||||
|
||||
- name: Set up Docker QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
with:
|
||||
platforms: arm64
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and Push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ./
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ env.CONTAINER_TAGS }}
|
||||
cache-from: type=local,src=/tmp/.buildx-cache
|
||||
cache-to: type=local,dest=/tmp/.buildx-cache
|
||||
build-args: |
|
||||
COMMIT_ID=${{ github.sha }}
|
||||
PROJECT_VERSION=$DASHBOARD_VERSION
|
||||
|
||||
- name: Output image digest
|
||||
run: |
|
||||
echo $"\
|
||||
Digest: ${{ steps.docker_build.outputs.digest }}
|
||||
Tags: ${{ env.CONTAINER_TAGS }}"
|
39
Dockerfile
39
Dockerfile
|
@ -1,19 +1,46 @@
|
|||
FROM node:18 as builder
|
||||
FROM node:18-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
ARG APP_MOUNT_URI
|
||||
RUN npm ci --legacy-peer-deps
|
||||
|
||||
COPY nginx/ nginx/
|
||||
COPY assets/ assets/
|
||||
COPY locale/ locale/
|
||||
COPY testUtils testUtils/
|
||||
COPY codegen.yml .
|
||||
COPY webpack.config.js .
|
||||
COPY tsconfig.json .
|
||||
COPY *.d.ts .
|
||||
COPY schema.graphql .
|
||||
COPY introspection.json .
|
||||
COPY src/ src/
|
||||
|
||||
ARG API_URI
|
||||
ARG APP_MOUNT_URI
|
||||
ARG MARKETPLACE_URL
|
||||
ARG SALEOR_APPS_ENDPOINT
|
||||
ARG STATIC_URL
|
||||
|
||||
ENV API_URI ${API_URI:-http://localhost:8000/graphql/}
|
||||
ENV APP_MOUNT_URI ${APP_MOUNT_URI:-/dashboard/}
|
||||
ENV MARKETPLACE_URL ${MARKETPLACE_URL}
|
||||
ENV SALEOR_APPS_ENDPOINT=${SALEOR_APPS_ENDPOINT}
|
||||
ENV STATIC_URL ${STATIC_URL:-/dashboard/}
|
||||
RUN STATIC_URL=${STATIC_URL} API_URI=${API_URI} MARKETPLACE_URL=${MARKETPLACE_URL} SALEOR_APPS_ENDPOINT=${SALEOR_APPS_ENDPOINT} APP_MOUNT_URI=${APP_MOUNT_URI} npm run build
|
||||
|
||||
FROM nginx:stable
|
||||
RUN npm run build
|
||||
|
||||
FROM nginx:stable-alpine as runner
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
|
||||
COPY ./nginx/replace-api-url.sh /docker-entrypoint.d/50-replace-api-url.sh
|
||||
COPY --from=builder /app/build/ /app/
|
||||
|
||||
LABEL org.opencontainers.image.title="saleor/saleor-dashboard" \
|
||||
org.opencontainers.image.description="A GraphQL-powered, single-page dashboard application for Saleor." \
|
||||
org.opencontainers.image.url="https://saleor.io/" \
|
||||
org.opencontainers.image.source="https://github.com/saleor/saleor-dashboard" \
|
||||
org.opencontainers.image.revision="$COMMIT_ID" \
|
||||
org.opencontainers.image.version="$PROJECT_VERSION" \
|
||||
org.opencontainers.image.authors="Saleor Commerce (https://saleor.io)" \
|
||||
org.opencontainers.image.licenses="BSD 3"
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
FROM node:18
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
ARG APP_MOUNT_URI
|
||||
ARG API_URI
|
||||
ARG MARKETPLACE_URL
|
||||
ARG SALEOR_APPS_ENDPOINT
|
||||
ARG STATIC_URL
|
||||
ENV API_URI ${API_URI:-http://localhost:8000/graphql/}
|
||||
ENV APP_MOUNT_URI ${APP_MOUNT_URI:-/}
|
||||
ENV STATIC_URL ${STATIC_URL:-/}
|
||||
|
||||
EXPOSE 9000
|
||||
CMD npm start -- --host 0.0.0.0
|
16
README.md
16
README.md
|
@ -145,6 +145,22 @@ You are ready to run cypress commands like:
|
|||
npm run cy:open
|
||||
```
|
||||
|
||||
### Usage with docker
|
||||
|
||||
Build docker image:
|
||||
|
||||
```shell
|
||||
docker build --tag saleor-dashboard .
|
||||
```
|
||||
|
||||
Run nginx from docker and bind it to port on your machine (in this example 8080):
|
||||
|
||||
```shell
|
||||
docker run --publish 8080:80 --env "API_URL=<YOUR_API_URL>" saleor-dashboard
|
||||
```
|
||||
|
||||
Enter `http://localhost:8080/` to use dashboard.
|
||||
|
||||
##### Usage with Sentry adapter:
|
||||
|
||||
Sentry is used as the default tracker so no changes in code are necessary and the configuration is done via environment variables.
|
||||
|
|
|
@ -29,7 +29,7 @@ export const urlList = {
|
|||
variants: "variant/",
|
||||
vouchers: "discounts/vouchers/",
|
||||
variant: "variant/",
|
||||
warehouses: "warehouses/"
|
||||
warehouses: "warehouses/",
|
||||
};
|
||||
|
||||
export const addVariantUrl = productId =>
|
||||
|
|
|
@ -38,7 +38,7 @@ module.exports = async (on, config) => {
|
|||
config.env.mailHogUrl = process.env.CYPRESS_mailHogUrl;
|
||||
config.env.grepTags = process.env.CYPRESS_grepTags;
|
||||
|
||||
on("before:browser:launch", ({}, launchOptions) => {
|
||||
on("before:browser:launch", (_browser = {}, launchOptions) => {
|
||||
launchOptions.args.push("--proxy-bypass-list=<-loopback>");
|
||||
return launchOptions;
|
||||
});
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// / <reference types="cypress" />
|
||||
|
||||
import "./customCommands/user";
|
||||
import "cypress-file-upload";
|
||||
import "cypress-mailhog";
|
||||
import "cypress-mochawesome-reporter/register";
|
||||
import "./customCommands/basicOperations";
|
||||
import "./customCommands/deleteElementsViaApi";
|
||||
import "./customCommands/softAssertions";
|
||||
import "./customCommands/sharedElementsOperations/addressForm.js";
|
||||
import "./customCommands/sharedElementsOperations/assignElementsForm.js";
|
||||
import "./customCommands/sharedElementsOperations/confirmationMessages.js";
|
||||
import "./customCommands/sharedElementsOperations/deleteElement";
|
||||
import "./customCommands/sharedElementsOperations/progressBar.js";
|
||||
import "./customCommands/sharedElementsOperations/selects.js";
|
||||
import "./customCommands/sharedElementsOperations/tables";
|
||||
import "./customCommands/sharedElementsOperations/deleteElement";
|
||||
import "cypress-mailhog";
|
||||
import "cypress-file-upload";
|
||||
import "cypress-mochawesome-reporter/register";
|
||||
import "./customCommands/softAssertions";
|
||||
import "./customCommands/user";
|
||||
|
||||
import { commandTimings } from "cypress-timings";
|
||||
|
||||
|
@ -49,7 +49,7 @@ Cypress.Commands.add("addAliasToGraphRequest", operationName => {
|
|||
|
||||
Cypress.on(
|
||||
"uncaught:exception",
|
||||
(err, runnable) =>
|
||||
(_err, _runnable) =>
|
||||
// returning false here prevents Cypress from
|
||||
// failing the test
|
||||
false,
|
||||
|
|
16
nginx/replace-api-url.sh
Executable file
16
nginx/replace-api-url.sh
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env sh
|
||||
|
||||
# Replaces the API_URL from the bundle's index.html file with the $API_URL env var.
|
||||
# This script is automatically picked up by the nginx entrypoint on startup.
|
||||
|
||||
set -e
|
||||
|
||||
INDEX_BUNDLE_PATH="/app/dashboard/index.html"
|
||||
|
||||
if [ -z "${API_URL}" ]; then
|
||||
echo "No API_URL provided, using defaults."
|
||||
else
|
||||
echo "Setting API_URL to: $API_URL"
|
||||
|
||||
sed -i "s#API_URL:.*#API_URL: \"$API_URL\",#" "$INDEX_BUNDLE_PATH"
|
||||
fi
|
|
@ -6,7 +6,7 @@ import {
|
|||
RedirectAction,
|
||||
} from "@saleor/app-sdk/app-bridge";
|
||||
import { appPath } from "@saleor/apps/urls";
|
||||
import { APP_MOUNT_URI } from "@saleor/config";
|
||||
import { getAppMountUri } from "@saleor/config";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import useNotifier from "@saleor/hooks/useNotifier";
|
||||
import React from "react";
|
||||
|
@ -78,7 +78,7 @@ export const useAppActions = (
|
|||
if (newContext) {
|
||||
window.open(to);
|
||||
} else if (appDeepUrlChange) {
|
||||
const exactLocation = urlJoin(APP_MOUNT_URI, to);
|
||||
const exactLocation = urlJoin(getAppMountUri(), to);
|
||||
|
||||
// Change only url without reloading if we are in the same app
|
||||
window.history.pushState(null, "", exactLocation);
|
||||
|
|
|
@ -10,14 +10,14 @@ import { FormattedMessage } from "react-intl";
|
|||
import { useStyles } from "./styles";
|
||||
|
||||
export interface CustomAppDefaultTokenProps {
|
||||
apiUri: string;
|
||||
apiUrl: string;
|
||||
token: string;
|
||||
onApiUriClick: () => void;
|
||||
onApiUrlClick: () => void;
|
||||
onTokenClose: () => void;
|
||||
}
|
||||
|
||||
const CustomAppDefaultToken: React.FC<CustomAppDefaultTokenProps> = props => {
|
||||
const { apiUri, token, onApiUriClick, onTokenClose } = props;
|
||||
const { apiUrl, token, onApiUrlClick, onTokenClose } = props;
|
||||
const classes = useStyles(props);
|
||||
const [copied, copy] = useClipboard();
|
||||
|
||||
|
@ -38,8 +38,8 @@ const CustomAppDefaultToken: React.FC<CustomAppDefaultTokenProps> = props => {
|
|||
defaultMessage="This token gives you access to your shop's API, which you'll find here: {url}"
|
||||
values={{
|
||||
url: (
|
||||
<Link href={apiUri} onClick={onApiUriClick}>
|
||||
{apiUri}
|
||||
<Link href={apiUrl} onClick={onApiUrlClick}>
|
||||
{apiUrl}
|
||||
</Link>
|
||||
),
|
||||
}}
|
||||
|
|
|
@ -36,14 +36,14 @@ export interface CustomAppDetailsPageFormData {
|
|||
permissions: PermissionEnum[];
|
||||
}
|
||||
export interface CustomAppDetailsPageProps {
|
||||
apiUri: string;
|
||||
apiUrl: string;
|
||||
disabled: boolean;
|
||||
errors: AppErrorFragment[];
|
||||
permissions: ShopInfoQuery["shop"]["permissions"];
|
||||
saveButtonBarState: ConfirmButtonTransitionState;
|
||||
app: AppUpdateMutation["appUpdate"]["app"];
|
||||
token: string;
|
||||
onApiUriClick: () => void;
|
||||
onApiUrlClick: () => void;
|
||||
onTokenDelete: (id: string) => void;
|
||||
onTokenClose: () => void;
|
||||
onTokenCreate: () => void;
|
||||
|
@ -58,14 +58,14 @@ export interface CustomAppDetailsPageProps {
|
|||
|
||||
const CustomAppDetailsPage: React.FC<CustomAppDetailsPageProps> = props => {
|
||||
const {
|
||||
apiUri,
|
||||
apiUrl,
|
||||
disabled,
|
||||
errors,
|
||||
permissions,
|
||||
saveButtonBarState,
|
||||
app,
|
||||
token,
|
||||
onApiUriClick,
|
||||
onApiUrlClick,
|
||||
onTokenClose,
|
||||
onTokenCreate,
|
||||
onTokenDelete,
|
||||
|
@ -136,9 +136,9 @@ const CustomAppDetailsPage: React.FC<CustomAppDetailsPageProps> = props => {
|
|||
{token && (
|
||||
<>
|
||||
<CustomAppDefaultToken
|
||||
apiUri={apiUri}
|
||||
apiUrl={apiUrl}
|
||||
token={token}
|
||||
onApiUriClick={onApiUriClick}
|
||||
onApiUrlClick={onApiUrlClick}
|
||||
onTokenClose={onTokenClose}
|
||||
/>
|
||||
<CardSpacer />
|
||||
|
|
|
@ -5,7 +5,7 @@ import TokenDeleteDialog from "@saleor/apps/components/TokenDeleteDialog";
|
|||
import { appMessages } from "@saleor/apps/messages";
|
||||
import NotFoundPage from "@saleor/components/NotFoundPage";
|
||||
import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||
import { API_URI } from "@saleor/config";
|
||||
import { getApiUrl } from "@saleor/config";
|
||||
import {
|
||||
AppTokenCreateMutation,
|
||||
AppTokenDeleteMutation,
|
||||
|
@ -220,11 +220,11 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
|
|||
<>
|
||||
<WindowTitle title={getStringOrPlaceholder(customApp?.name)} />
|
||||
<CustomAppDetailsPage
|
||||
apiUri={API_URI}
|
||||
apiUrl={getApiUrl()}
|
||||
disabled={loading}
|
||||
errors={updateAppOpts.data?.appUpdate?.errors || []}
|
||||
token={token}
|
||||
onApiUriClick={() => open(API_URI, "blank")}
|
||||
onApiUrlClick={() => open(getApiUrl(), "blank")}
|
||||
onSubmit={handleSubmit}
|
||||
onTokenClose={onTokenClose}
|
||||
onTokenCreate={() => openModal("create-token")}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { getApiUrl } from "@saleor/config";
|
||||
import { createSaleorClient, SaleorProvider } from "@saleor/sdk";
|
||||
import setupApi from "@test/api";
|
||||
import { act, renderHook } from "@testing-library/react-hooks";
|
||||
|
@ -15,7 +16,7 @@ function renderAuthProvider() {
|
|||
};
|
||||
const notify = jest.fn();
|
||||
const saleorClient = createSaleorClient({
|
||||
apiUrl: process.env.API_URI,
|
||||
apiUrl: getApiUrl(),
|
||||
channel: "",
|
||||
});
|
||||
const wrapper = ({ children }) => (
|
||||
|
@ -50,7 +51,7 @@ beforeEach(() => {
|
|||
sessionStorage.clear();
|
||||
});
|
||||
|
||||
xdescribe("User", () => {
|
||||
describe("User", () => {
|
||||
it("will be logged in if has valid credentials", async done => {
|
||||
const hook = renderAuthProvider();
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { Button } from "@saleor/components/Button";
|
|||
import Form from "@saleor/components/Form";
|
||||
import FormSpacer from "@saleor/components/FormSpacer";
|
||||
import { IconButton } from "@saleor/components/IconButton";
|
||||
import { APP_MOUNT_URI } from "@saleor/config";
|
||||
import { getAppMountUri } from "@saleor/config";
|
||||
import { RequestPasswordResetMutation } from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
|
@ -36,7 +36,7 @@ const ResetPasswordPage: React.FC<ResetPasswordPageProps> = props => {
|
|||
<Form initial={{ email: "" }} onSubmit={onSubmit}>
|
||||
{({ change: handleChange, data, submit: handleSubmit }) => (
|
||||
<>
|
||||
<IconButton className={classes.backBtn} href={APP_MOUNT_URI}>
|
||||
<IconButton className={classes.backBtn} href={getAppMountUri()}>
|
||||
<ArrowRightIcon className={classes.arrow} />
|
||||
</IconButton>
|
||||
<Typography variant="h3" className={classes.header}>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ApolloClient } from "@apollo/client";
|
||||
import { IMessageContext } from "@saleor/components/messages";
|
||||
import { APP_DEFAULT_URI, APP_MOUNT_URI, DEMO_MODE } from "@saleor/config";
|
||||
import { DEMO_MODE } from "@saleor/config";
|
||||
import { useUserDetailsQuery } from "@saleor/graphql";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -16,6 +16,7 @@ import {
|
|||
login as loginWithCredentialsManagementAPI,
|
||||
saveCredentials,
|
||||
} from "@saleor/utils/credentialsManagement";
|
||||
import { getAppMountUriForRedirect } from "@saleor/utils/urls";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { IntlShape } from "react-intl";
|
||||
import urlJoin from "url-join";
|
||||
|
@ -88,8 +89,10 @@ export function useAuthProvider({
|
|||
});
|
||||
|
||||
const handleLogout = async () => {
|
||||
const path = APP_MOUNT_URI === APP_DEFAULT_URI ? "" : APP_MOUNT_URI;
|
||||
const returnTo = urlJoin(window.location.origin, path);
|
||||
const returnTo = urlJoin(
|
||||
window.location.origin,
|
||||
getAppMountUriForRedirect(),
|
||||
);
|
||||
|
||||
const result = await logout({
|
||||
input: JSON.stringify({
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { APP_DEFAULT_URI, APP_MOUNT_URI } from "@saleor/config";
|
||||
import { useAvailableExternalAuthenticationsQuery } from "@saleor/graphql";
|
||||
import useLocalStorage from "@saleor/hooks/useLocalStorage";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { getAppMountUriForRedirect } from "@saleor/utils/urls";
|
||||
import React, { useEffect } from "react";
|
||||
import urlJoin from "url-join";
|
||||
import useRouter from "use-react-router";
|
||||
|
@ -52,7 +52,7 @@ const LoginView: React.FC<LoginViewProps> = ({ params }) => {
|
|||
const result = await requestLoginByExternalPlugin(pluginId, {
|
||||
redirectUri: urlJoin(
|
||||
window.location.origin,
|
||||
APP_MOUNT_URI === APP_DEFAULT_URI ? "" : APP_MOUNT_URI,
|
||||
getAppMountUriForRedirect(),
|
||||
loginCallbackPath,
|
||||
),
|
||||
});
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { APP_MOUNT_URI } from "@saleor/config";
|
||||
import { useRequestPasswordResetMutation } from "@saleor/graphql";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import { commonMessages } from "@saleor/intl";
|
||||
import { extractMutationErrors } from "@saleor/misc";
|
||||
import { getAppMountUriForRedirect } from "@saleor/utils/urls";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
import urlJoin from "url-join";
|
||||
|
@ -49,7 +49,7 @@ const ResetPasswordView: React.FC = () => {
|
|||
email: data.email,
|
||||
redirectUrl: urlJoin(
|
||||
window.location.origin,
|
||||
APP_MOUNT_URI === "/" ? "" : APP_MOUNT_URI,
|
||||
getAppMountUriForRedirect(),
|
||||
newPasswordUrl().replace(/\?/, ""),
|
||||
),
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { APP_MOUNT_URI } from "@saleor/config";
|
||||
import { getAppMountUri } from "@saleor/config";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
import React from "react";
|
||||
|
||||
|
@ -7,7 +7,7 @@ import ResetPasswordSuccessPage from "../components/ResetPasswordSuccessPage";
|
|||
const ResetPasswordSuccessView: React.FC = () => {
|
||||
const navigate = useNavigator();
|
||||
|
||||
return <ResetPasswordSuccessPage onBack={() => navigate(APP_MOUNT_URI)} />;
|
||||
return <ResetPasswordSuccessPage onBack={() => navigate(getAppMountUri())} />;
|
||||
};
|
||||
ResetPasswordSuccessView.displayName = "ResetPasswordSuccessView";
|
||||
export default ResetPasswordSuccessView;
|
||||
|
|
|
@ -2,10 +2,10 @@ import packageInfo from "../package.json";
|
|||
import { SearchVariables } from "./hooks/makeSearch";
|
||||
import { ListSettings, ListViews, Pagination } from "./types";
|
||||
|
||||
export const IS_TEST = process.env.NODE_ENV === "test";
|
||||
export const APP_MOUNT_URI = IS_TEST ? "/" : process.env.APP_MOUNT_URI || "/";
|
||||
export const APP_DEFAULT_URI = "/";
|
||||
export const API_URI = process.env.API_URI;
|
||||
export const getAppDefaultUri = () => "/";
|
||||
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);
|
||||
export const IS_CLOUD_INSTANCE = process.env.IS_CLOUD_INSTANCE === "true";
|
||||
export const MARKETPLACE_URL = process.env.MARKETPLACE_URL;
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ApolloClient, ApolloLink, InMemoryCache } from "@apollo/client";
|
|||
import { createFetch, createSaleorClient } from "@saleor/sdk";
|
||||
import { createUploadLink } from "apollo-upload-client";
|
||||
|
||||
import { API_URI } from "../config";
|
||||
import { getApiUrl } from "../config";
|
||||
import introspectionQueryResultData from "./fragmentTypes.generated";
|
||||
import { TypedTypePolicies } from "./typePolicies.generated";
|
||||
|
||||
|
@ -21,7 +21,7 @@ const attachVariablesLink = new ApolloLink((operation, forward) =>
|
|||
export const link = attachVariablesLink.concat(
|
||||
createUploadLink({
|
||||
credentials: "include",
|
||||
uri: API_URI,
|
||||
uri: getApiUrl(),
|
||||
fetch: createFetch(),
|
||||
}),
|
||||
);
|
||||
|
@ -70,6 +70,6 @@ export const apolloClient = new ApolloClient({
|
|||
});
|
||||
|
||||
export const saleorClient = createSaleorClient({
|
||||
apiUrl: API_URI,
|
||||
apiUrl: getApiUrl(),
|
||||
channel: "",
|
||||
});
|
||||
|
|
|
@ -8,6 +8,12 @@
|
|||
/>
|
||||
<meta name="robots" content="noindex" />
|
||||
<title>Saleor e-commerce</title>
|
||||
<script>
|
||||
window.__SALEOR_CONFIG__ = {
|
||||
API_URL: "<%= API_URL %>",
|
||||
APP_MOUNT_URI: "<%= APP_MOUNT_URI %>",
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
|
|
@ -36,7 +36,7 @@ import { LocaleProvider } from "./components/Locale";
|
|||
import MessageManagerProvider from "./components/messages";
|
||||
import { ShopProvider } from "./components/Shop";
|
||||
import { WindowTitle } from "./components/WindowTitle";
|
||||
import { APP_MOUNT_URI, DEMO_MODE, GTM_ID } from "./config";
|
||||
import { DEMO_MODE, getAppMountUri, GTM_ID } from "./config";
|
||||
import ConfigurationSection from "./configuration";
|
||||
import { getConfigMenuItemsPermissions } from "./configuration/utils";
|
||||
import AppStateProvider from "./containers/AppState";
|
||||
|
@ -80,7 +80,7 @@ errorTracker.init();
|
|||
const App: React.FC = () => (
|
||||
<SaleorProvider client={saleorClient}>
|
||||
<ApolloProvider client={apolloClient}>
|
||||
<BrowserRouter basename={APP_MOUNT_URI}>
|
||||
<BrowserRouter basename={getAppMountUri()}>
|
||||
<ThemeProvider overrides={themeOverrides}>
|
||||
<DateProvider>
|
||||
<LocaleProvider>
|
||||
|
|
|
@ -4,7 +4,7 @@ import SaveFilterTabDialog, {
|
|||
SaveFilterTabDialogFormData,
|
||||
} from "@saleor/components/SaveFilterTabDialog";
|
||||
import { useShopLimitsQuery } from "@saleor/components/Shop/queries";
|
||||
import { APP_MOUNT_URI, DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
|
||||
import { useStaffListQuery, useStaffMemberAddMutation } from "@saleor/graphql";
|
||||
import useListSettings from "@saleor/hooks/useListSettings";
|
||||
import useNavigator from "@saleor/hooks/useNavigator";
|
||||
|
@ -23,6 +23,7 @@ import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
|
|||
import createSortHandler from "@saleor/utils/handlers/sortHandler";
|
||||
import { mapEdgesToItems } from "@saleor/utils/maps";
|
||||
import { getSortParams } from "@saleor/utils/sort";
|
||||
import { getAppMountUriForRedirect } from "@saleor/utils/urls";
|
||||
import React from "react";
|
||||
import { useIntl } from "react-intl";
|
||||
import urlJoin from "url-join";
|
||||
|
@ -159,7 +160,7 @@ export const StaffList: React.FC<StaffListProps> = ({ params }) => {
|
|||
lastName: variables.lastName,
|
||||
redirectUrl: urlJoin(
|
||||
window.location.origin,
|
||||
APP_MOUNT_URI === "/" ? "" : APP_MOUNT_URI,
|
||||
getAppMountUriForRedirect(),
|
||||
newPasswordUrl().replace(/\?/, ""),
|
||||
),
|
||||
},
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ApolloMockedProvider } from "../../testUtils/ApolloMockedProvider";
|
|||
import { Provider as DateProvider } from "../components/Date/DateContext";
|
||||
import MessageManagerProvider from "../components/messages";
|
||||
import { TimezoneProvider } from "../components/Timezone";
|
||||
import { APP_MOUNT_URI } from "../config";
|
||||
import { getAppMountUri } from "../config";
|
||||
|
||||
export const Decorator = storyFn => (
|
||||
<ApolloMockedProvider>
|
||||
|
@ -24,7 +24,7 @@ export const Decorator = storyFn => (
|
|||
<DateProvider value={+new Date("2018-08-07T14:30:44+00:00")}>
|
||||
<TimezoneProvider value="America/New_York">
|
||||
<ThemeProvider overrides={themeOverrides}>
|
||||
<BrowserRouter basename={APP_MOUNT_URI}>
|
||||
<BrowserRouter basename={getAppMountUri()}>
|
||||
<ExternalAppProvider>
|
||||
<MessageManagerProvider>
|
||||
<div
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { getAppDefaultUri, getAppMountUri } from "@saleor/config";
|
||||
import isArray from "lodash/isArray";
|
||||
import { stringify } from "qs";
|
||||
|
||||
|
@ -20,3 +21,6 @@ export function getArrayQueryParam(param: string | string[]): string[] {
|
|||
}
|
||||
|
||||
export const isExternalURL = url => /^https?:\/\//.test(url);
|
||||
|
||||
export const getAppMountUriForRedirect = () =>
|
||||
getAppMountUri() === getAppDefaultUri() ? "" : getAppMountUri();
|
||||
|
|
|
@ -3,6 +3,7 @@ import { BatchHttpLink } from "@apollo/client/link/batch-http";
|
|||
import NodeHttpAdapter from "@pollyjs/adapter-node-http";
|
||||
import { Polly } from "@pollyjs/core";
|
||||
import FSPersister from "@pollyjs/persister-fs";
|
||||
import { getApiUrl } from "@saleor/config";
|
||||
import { createFetch } from "@saleor/sdk";
|
||||
import path from "path";
|
||||
import { setupPolly } from "setup-polly-jest";
|
||||
|
@ -36,7 +37,7 @@ function setupApi() {
|
|||
const cache = new InMemoryCache();
|
||||
const link = new BatchHttpLink({
|
||||
fetch: createFetch(),
|
||||
uri: process.env.API_URI || "http://localhost:8000/graphql/",
|
||||
uri: getApiUrl(),
|
||||
});
|
||||
const apolloClient = new ApolloClient({
|
||||
cache,
|
||||
|
|
|
@ -1 +1,6 @@
|
|||
document.getElementById = () => document.createElement("div");
|
||||
|
||||
window.__SALEOR_CONFIG__ = {
|
||||
API_URL: "http://localhost:8000/graphql/",
|
||||
APP_MOUNT_URI: "/",
|
||||
};
|
||||
|
|
|
@ -35,12 +35,16 @@ const htmlWebpackPlugin = new HtmlWebpackPlugin({
|
|||
filename: "index.html",
|
||||
hash: true,
|
||||
template: "./src/index.html",
|
||||
templateParameters: {
|
||||
// URI is kept for backwards compatibility.
|
||||
// See more at https://github.com/saleor/saleor-dashboard/issues/2502
|
||||
API_URL: process.env.API_URI,
|
||||
APP_MOUNT_URI: process.env.APP_MOUNT_URI,
|
||||
},
|
||||
});
|
||||
const environmentPlugin = new webpack.EnvironmentPlugin({
|
||||
API_URI: "",
|
||||
MARKETPLACE_URL: "",
|
||||
SALEOR_APPS_ENDPOINT: "",
|
||||
APP_MOUNT_URI: "/",
|
||||
DEMO_MODE: false,
|
||||
ENVIRONMENT: "",
|
||||
GTM_ID: "",
|
||||
|
|
4
webpack.d.ts
vendored
4
webpack.d.ts
vendored
|
@ -7,4 +7,8 @@ declare module "*.svg" {
|
|||
|
||||
declare interface Window {
|
||||
PasswordCredential: PasswordCredential;
|
||||
__SALEOR_CONFIG__: {
|
||||
API_URL: string;
|
||||
APP_MOUNT_URI: string;
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue