diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index 2d255cd00..988d08276 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -1675,6 +1675,10 @@ "context": "button", "string": "Delete" }, + "src_dot_demo": { + "context": "notification message after log in", + "string": "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes." + }, "src_dot_description": { "string": "Description" }, diff --git a/package-lock.json b/package-lock.json index dcdde831a..421499f39 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17951,6 +17951,11 @@ "react-clientside-effect": "^1.2.0" } }, + "react-gtm-module": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.8.tgz", + "integrity": "sha512-OU5FwAHC3gWnnxJ+MLwBMLZO1Pmn1DiVCGHqptwDnNojE3QRrNxjqozkW5cNS4Zp+C6HZ8a4ZIt0QPNlpzua4Q==" + }, "react-helmet": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-5.2.1.tgz", diff --git a/package.json b/package.json index 784d95fd5..780ac8970 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "react-dom": "^16.9.0", "react-dropzone": "^8.2.0", "react-error-boundary": "^1.2.5", + "react-gtm-module": "^2.0.8", "react-helmet": "^5.2.1", "react-infinite-scroller": "^1.2.4", "react-inlinesvg": "^0.8.4", diff --git a/src/auth/AuthProvider.tsx b/src/auth/AuthProvider.tsx index 060da3ab4..e5e470b0d 100644 --- a/src/auth/AuthProvider.tsx +++ b/src/auth/AuthProvider.tsx @@ -1,3 +1,5 @@ +import { DEMO_MODE } from "@saleor/config"; +import useNotifier from "@saleor/hooks/useNotifier"; import { maybe } from "@saleor/misc"; import { isSupported as isCredentialsManagementAPISupported, @@ -6,6 +8,7 @@ import { } from "@saleor/utils/credentialsManagement"; import React from "react"; import { MutationFunction, MutationResult } from "react-apollo"; +import { useIntl } from "react-intl"; import { UserContext } from "./"; import { @@ -17,7 +20,12 @@ import { RefreshToken, RefreshTokenVariables } from "./types/RefreshToken"; import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; import { User } from "./types/User"; import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; -import { getAuthToken, removeAuthToken, setAuthToken } from "./utils"; +import { + displayDemoMessage, + getAuthToken, + removeAuthToken, + setAuthToken +} from "./utils"; interface AuthProviderOperationsProps { children: (props: { @@ -30,27 +38,39 @@ interface AuthProviderOperationsProps { } const AuthProviderOperations: React.FC = ({ children -}) => ( - - {(...tokenAuth) => ( - - {(...tokenVerify) => ( - - {(...tokenRefresh) => ( - - {children} - - )} - - )} - - )} - -); +}) => { + const intl = useIntl(); + const notify = useNotifier(); + + const handleLogin = () => { + if (DEMO_MODE) { + displayDemoMessage(intl, notify); + } + }; + + return ( + + {(...tokenAuth) => ( + + {(...tokenVerify) => ( + + {(...tokenRefresh) => ( + + {children} + + )} + + )} + + )} + + ); +}; interface AuthProviderProps { children: (props: { @@ -72,6 +92,7 @@ interface AuthProviderProps { MutationFunction, MutationResult ]; + onLogin?: () => void; } interface AuthProviderState { @@ -130,11 +151,14 @@ class AuthProvider extends React.Component< } login = async (email: string, password: string) => { - const { tokenAuth } = this.props; + const { tokenAuth, onLogin } = this.props; const [tokenAuthFn] = tokenAuth; tokenAuthFn({ variables: { email, password } }).then(result => { if (result && !result.data.tokenCreate.errors.length) { + if (!!onLogin) { + onLogin(); + } saveCredentials(result.data.tokenCreate.user, password); } }); diff --git a/src/auth/components/LoginPage/LoginPage.tsx b/src/auth/components/LoginPage/LoginPage.tsx index 4ef242773..60f1d9d19 100644 --- a/src/auth/components/LoginPage/LoginPage.tsx +++ b/src/auth/components/LoginPage/LoginPage.tsx @@ -4,6 +4,7 @@ import TextField from "@material-ui/core/TextField"; import Typography from "@material-ui/core/Typography"; import Form from "@saleor/components/Form"; import { FormSpacer } from "@saleor/components/FormSpacer"; +import { DEMO_MODE } from "@saleor/config"; import { commonMessages } from "@saleor/intl"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -53,8 +54,16 @@ const LoginCard: React.FC = props => { const classes = useStyles(props); const intl = useIntl(); + let initialFormData = { email: "", password: "" }; + if (DEMO_MODE) { + initialFormData = { + email: "admin@example.com", + password: "admin" + }; + } + return ( -
+ {({ change: handleChange, data, submit: handleSubmit }) => ( <> {error && ( diff --git a/src/auth/utils.ts b/src/auth/utils.ts index f2ed57e85..72ebf3a45 100644 --- a/src/auth/utils.ts +++ b/src/auth/utils.ts @@ -1,3 +1,7 @@ +import { UseNotifierResult } from "@saleor/hooks/useNotifier"; +import { commonMessages } from "@saleor/intl"; +import { IntlShape } from "react-intl"; + const TOKEN_STORAGE_KEY = "dashboardAuth"; export const getAuthToken = () => @@ -13,3 +17,12 @@ export const removeAuthToken = () => { localStorage.removeItem(TOKEN_STORAGE_KEY); sessionStorage.removeItem(TOKEN_STORAGE_KEY); }; + +export const displayDemoMessage = ( + intl: IntlShape, + notify: UseNotifierResult +) => { + notify({ + text: intl.formatMessage(commonMessages.demo) + }); +}; diff --git a/src/config.ts b/src/config.ts index 90b81e7c8..6dee3beb2 100644 --- a/src/config.ts +++ b/src/config.ts @@ -2,7 +2,7 @@ import packageInfo from "../package.json"; import { SearchVariables } from "./hooks/makeSearch"; import { ListSettings, ListViews, Pagination } from "./types"; -export const APP_MOUNT_URI = process.env.APP_MOUNT_URI || "/"; +export const APP_MOUNT_URI = process.env.APP_MOUNT_URI; export const API_URI = process.env.API_URI; export const DEFAULT_INITIAL_SEARCH_DATA: SearchVariables = { @@ -90,3 +90,5 @@ export const defaultListSettings: AppListViewSettings = { }; export const APP_VERSION = packageInfo.version; +export const DEMO_MODE = process.env.DEMO_MODE === "true"; +export const GTM_ID = process.env.GTM_ID; diff --git a/src/index.tsx b/src/index.tsx index d38f2e5ad..45625ac19 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,6 +11,7 @@ import React from "react"; import { ApolloProvider } from "react-apollo"; import { render } from "react-dom"; import ErrorBoundary from "react-error-boundary"; +import TagManager from "react-gtm-module"; import { useIntl } from "react-intl"; import { BrowserRouter, Route, Switch } from "react-router-dom"; @@ -31,7 +32,7 @@ import { MessageManager } from "./components/messages"; import { ShopProvider } from "./components/Shop"; import ThemeProvider from "./components/Theme"; import { WindowTitle } from "./components/WindowTitle"; -import { API_URI, APP_MOUNT_URI } from "./config"; +import { API_URI, APP_MOUNT_URI, GTM_ID } from "./config"; import ConfigurationSection, { createConfigurationMenu } from "./configuration"; import AppStateProvider from "./containers/AppState"; import { CustomerSection } from "./customers"; @@ -66,6 +67,10 @@ interface ResponseError extends ErrorResponse { }; } +if (process.env.GTM_ID !== undefined) { + TagManager.initialize({ gtmId: GTM_ID }); +} + const invalidTokenLink = onError((error: ResponseError) => { if ( (error.networkError && error.networkError.statusCode === 401) || diff --git a/src/intl.ts b/src/intl.ts index 479b630dc..43c150b65 100644 --- a/src/intl.ts +++ b/src/intl.ts @@ -10,6 +10,11 @@ export const commonMessages = defineMessages({ dashboard: { defaultMessage: "Dashboard" }, + demo: { + defaultMessage: + "Just to let you know... You're in demo mode. You can play around with the dashboard but can't save changes.", + description: "notification message after log in" + }, description: { defaultMessage: "Description" }, diff --git a/webpack.config.js b/webpack.config.js index ad8a00efb..db1920d20 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -22,10 +22,12 @@ const htmlWebpackPlugin = new HtmlWebpackPlugin({ hash: true, template: "./src/index.html" }); -const environmentPlugin = new webpack.EnvironmentPlugin([ - "APP_MOUNT_URI", - "API_URI" -]); +const environmentPlugin = new webpack.EnvironmentPlugin({ + API_URI: "", + APP_MOUNT_URI: "/", + DEMO_MODE: false, + GTM_ID: "" +}); const dashboardBuildPath = "build/dashboard/"; @@ -35,8 +37,8 @@ module.exports = (env, argv) => { let fileLoaderPath; let output; - if(!process.env.API_URI) { - throw new Error("Environment variable API_URI not set") + if (!process.env.API_URI) { + throw new Error("Environment variable API_URI not set"); } if (!devMode) {