Extract useDashboardNotification (#362)

* Extract useDashboardNotification

Play with config to make app-sdk working in monorepo

bump pnpm

remove local locks

unify deps

Changesets

Replace appBridge.dispatch(Notification()) with shared useDashboardNotification package

Fix build

Update klaviyo packages

update deps

update deps - root next version

* update and ix

* Restore logic in cms
This commit is contained in:
Lukasz Ostrowski 2023-04-14 17:40:49 +02:00 committed by GitHub
parent 74174c4763
commit 2e518906d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
46 changed files with 233 additions and 80745 deletions

View file

@ -0,0 +1,17 @@
---
"eslint-config-saleor": patch
"saleor-app-emails-and-messages": patch
"saleor-app-data-importer": patch
"saleor-app-products-feed": patch
"saleor-app-monitoring": patch
"@saleor/apps-shared": patch
"saleor-app-invoices": patch
"saleor-app-klaviyo": patch
"saleor-app-search": patch
"saleor-app-slack": patch
"saleor-app-taxes": patch
"saleor-app-cms": patch
"saleor-app-crm": patch
---
Update next.js to 13.3.0

View file

@ -0,0 +1,17 @@
---
"eslint-config-saleor": patch
"saleor-app-emails-and-messages": patch
"saleor-app-data-importer": patch
"saleor-app-products-feed": patch
"saleor-app-monitoring": patch
"@saleor/apps-shared": patch
"saleor-app-invoices": patch
"saleor-app-klaviyo": patch
"saleor-app-search": patch
"saleor-app-slack": patch
"saleor-app-taxes": patch
"saleor-app-cms": patch
"saleor-app-crm": patch
---
Update @saleor/app-sdk to 0.37.2

View file

@ -0,0 +1,5 @@
---
"@saleor/apps-shared": minor
---
Added useDashboardNotification hook, that allows quick access to AppBridge.dispatch(Notification())

View file

@ -0,0 +1,15 @@
---
"saleor-app-emails-and-messages": patch
"saleor-app-data-importer": patch
"saleor-app-products-feed": patch
"saleor-app-monitoring": patch
"saleor-app-invoices": patch
"saleor-app-klaviyo": patch
"saleor-app-search": patch
"saleor-app-slack": patch
"saleor-app-taxes": patch
"saleor-app-cms": patch
"saleor-app-crm": patch
---
Use useDashboardNotification hook from shared package, instead of direct AppBridge usage

View file

@ -2,7 +2,7 @@ import { useChannelsFetch } from "./useChannelsFetch";
import { MergedChannelSchema, SingleChannelSchema } from "../../../../lib/cms/config"; import { MergedChannelSchema, SingleChannelSchema } from "../../../../lib/cms/config";
import { useChannelsQuery } from "../../../../../generated/graphql"; import { useChannelsQuery } from "../../../../../generated/graphql";
import { useIsMounted } from "usehooks-ts"; import { useIsMounted } from "usehooks-ts";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge"; import { useDashboardNotification } from "@saleor/apps-shared";
export interface ChannelsDataLoading { export interface ChannelsDataLoading {
fetching: boolean; fetching: boolean;
@ -15,7 +15,6 @@ export interface ChannelsDataErrors {
} }
export const useChannels = () => { export const useChannels = () => {
const { appBridge } = useAppBridge();
const isMounted = useIsMounted(); const isMounted = useIsMounted();
const [channelsQueryData, channelsQueryOpts] = useChannelsQuery({ const [channelsQueryData, channelsQueryOpts] = useChannelsQuery({
pause: !isMounted, pause: !isMounted,
@ -27,6 +26,7 @@ export const useChannels = () => {
error: fetchingError, error: fetchingError,
isFetching, isFetching,
} = useChannelsFetch(); } = useChannelsFetch();
const { notifySuccess, notifyError } = useDashboardNotification();
const saveChannel = async (channelToSave: SingleChannelSchema) => { const saveChannel = async (channelToSave: SingleChannelSchema) => {
console.log("saveChannel", channelToSave); console.log("saveChannel", channelToSave);
@ -55,21 +55,9 @@ export const useChannels = () => {
}); });
if (fetchResult.success) { if (fetchResult.success) {
appBridge?.dispatch( notifySuccess("Success", "Configuration saved");
actions.Notification({
title: "Success",
status: "success",
text: "Configuration saved",
})
);
} else { } else {
appBridge?.dispatch( notifyError("Error", "Error while saving configuration");
actions.Notification({
title: "Error",
status: "error",
text: "Error while saving configuration",
})
);
} }
}; };

View file

@ -7,6 +7,7 @@ import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import { ProviderInstancesSelect } from "./provider-instances-list"; import { ProviderInstancesSelect } from "./provider-instances-list";
import { Add } from "@material-ui/icons"; import { Add } from "@material-ui/icons";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles({ const useStyles = makeStyles({
wrapper: { wrapper: {
@ -18,13 +19,14 @@ const useStyles = makeStyles({
export const ProviderInstances = () => { export const ProviderInstances = () => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge();
const { providerInstances, saveProviderInstance, deleteProviderInstance, loading, errors } = const { providerInstances, saveProviderInstance, deleteProviderInstance, loading, errors } =
useProviderInstances(); useProviderInstances();
const [activeProviderInstanceId, setActiveProviderInstanceId] = useState<string | null>(null); const [activeProviderInstanceId, setActiveProviderInstanceId] = useState<string | null>(null);
const [newProviderInstance, setNewProviderInstance] = useState<SingleProviderSchema | null>(null); const [newProviderInstance, setNewProviderInstance] = useState<SingleProviderSchema | null>(null);
const { notifySuccess } = useDashboardNotification();
useEffect(() => { useEffect(() => {
if (providerInstances.length && !activeProviderInstanceId) { if (providerInstances.length && !activeProviderInstanceId) {
setActiveProviderInstanceId(providerInstances[0].id); setActiveProviderInstanceId(providerInstances[0].id);
@ -48,13 +50,7 @@ export const ProviderInstances = () => {
const handleSaveProviderInstance = async (providerInstance: SingleProviderSchema) => { const handleSaveProviderInstance = async (providerInstance: SingleProviderSchema) => {
const savedProviderInstance = await saveProviderInstance(providerInstance); const savedProviderInstance = await saveProviderInstance(providerInstance);
appBridge?.dispatch( notifySuccess("Success", "Configuration saved");
actions.Notification({
title: "Success",
status: "success",
text: "Configuration saved",
})
);
if (newProviderInstance) { if (newProviderInstance) {
setNewProviderInstance(null); setNewProviderInstance(null);

File diff suppressed because it is too large Load diff

View file

@ -1,21 +0,0 @@
import { useCallback } from "react";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
export const useDashboardNotification = () => {
const { appBridge } = useAppBridge();
return {
notifySuccess: useCallback(
(title: string, text: string) => {
appBridge?.dispatch(
actions.Notification({
status: "success",
title,
text,
})
);
},
[appBridge]
),
};
};

View file

@ -2,7 +2,7 @@ import { Box, Button, Checkbox, Text } from "@saleor/macaw-ui/next";
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { ComponentProps, useEffect, useState } from "react"; import { ComponentProps, useEffect, useState } from "react";
import { Section } from "../../../ui/section/section"; import { Section } from "../../../ui/section/section";
import { useDashboardNotification } from "../../../../lib/use-dashboard-notification"; import { useDashboardNotification } from "@saleor/apps-shared";
import { MailchimpListPicker } from "../../mailchimp-list-picker/mailchimp-list-picker"; import { MailchimpListPicker } from "../../mailchimp-list-picker/mailchimp-list-picker";
type EnabledState = { type EnabledState = {

View file

@ -1,7 +1,7 @@
import { ComponentProps, useEffect, useState } from "react"; import { ComponentProps, useEffect, useState } from "react";
import { Box, Button, Text, useTheme, WarningIcon } from "@saleor/macaw-ui/next"; import { Box, Button, Text, useTheme, WarningIcon } from "@saleor/macaw-ui/next";
import { trpcClient } from "../trpc/trpc-client"; import { trpcClient } from "../trpc/trpc-client";
import { useDashboardNotification } from "../../lib/use-dashboard-notification"; import { useDashboardNotification } from "@saleor/apps-shared";
import { useFetchAllCustomers } from "./use-fetch-all-customers"; import { useFetchAllCustomers } from "./use-fetch-all-customers";
import { Section } from "../ui/section/section"; import { Section } from "../ui/section/section";
import { MailchimpListPicker } from "../mailchimp/mailchimp-list-picker/mailchimp-list-picker"; import { MailchimpListPicker } from "../mailchimp/mailchimp-list-picker/mailchimp-list-picker";

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,5 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
module.exports = { module.exports = {
reactStrictMode: true, reactStrictMode: true,
transpilePackages: ["@saleor/apps-shared"],
}; };

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ import { trpcClient } from "../../trpc/trpc-client";
import { SideMenu } from "./side-menu"; import { SideMenu } from "./side-menu";
import { LoadingIndicator } from "../../ui/loading-indicator"; import { LoadingIndicator } from "../../ui/loading-indicator";
import { Instructions } from "./instructions"; import { Instructions } from "./instructions";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -26,6 +27,7 @@ export const ChannelsConfigurationTab = () => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { appBridge } = useAppBridge();
const [activeChannelSlug, setActiveChannelSlug] = useState<string | null>(null); const [activeChannelSlug, setActiveChannelSlug] = useState<string | null>(null);
const { notifySuccess } = useDashboardNotification();
const { data: channelsData, isLoading: isChannelsDataLoading } = const { data: channelsData, isLoading: isChannelsDataLoading } =
trpcClient.channels.fetch.useQuery(undefined, { trpcClient.channels.fetch.useQuery(undefined, {
@ -75,13 +77,8 @@ export const ChannelsConfigurationTab = () => {
trpcClient.appConfiguration.setChannelConfiguration.useMutation({ trpcClient.appConfiguration.setChannelConfiguration.useMutation({
onSuccess() { onSuccess() {
refetchConfig(); refetchConfig();
appBridge?.dispatch(
actions.Notification({ notifySuccess("Success", "Saved app configuration");
title: "Success",
text: "Saved app configuration",
status: "success",
})
);
}, },
}); });

View file

@ -6,6 +6,7 @@ import { MjmlConfiguration, smtpEncryptionTypes } from "../mjml-config";
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge"; import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
field: { field: {
@ -30,7 +31,7 @@ type Props = {
export const MjmlConfigurationForm = (props: Props) => { export const MjmlConfigurationForm = (props: Props) => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { notifySuccess, notifyError } = useDashboardNotification();
const { handleSubmit, control, reset, setError } = useForm<MjmlConfiguration>({ const { handleSubmit, control, reset, setError } = useForm<MjmlConfiguration>({
defaultValues: props.initialData, defaultValues: props.initialData,
@ -64,12 +65,7 @@ export const MjmlConfigurationForm = (props: Props) => {
// Trigger refetch to make sure we have a fresh data // Trigger refetch to make sure we have a fresh data
props.onConfigurationSaved(); props.onConfigurationSaved();
appBridge?.dispatch( notifySuccess("Configuration saved");
actions.Notification({
title: "Configuration saved",
status: "success",
})
);
}, },
onError(error) { onError(error) {
let isFieldErrorSet = false; let isFieldErrorSet = false;
@ -85,13 +81,10 @@ export const MjmlConfigurationForm = (props: Props) => {
} }
const formErrors = error.data?.zodError?.formErrors || []; const formErrors = error.data?.zodError?.formErrors || [];
const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined; const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined;
appBridge?.dispatch( notifyError(
actions.Notification({ "Could not save the configuration",
title: "Could not save the configuration", isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration",
text: isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration", formErrorMessage
apiMessage: formErrorMessage,
status: "error",
})
); );
}, },
}); });

View file

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import { IconButton, makeStyles } from "@saleor/macaw-ui"; import { IconButton, makeStyles } from "@saleor/macaw-ui";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { AppColumnsLayout } from "../../../ui/app-columns-layout"; import { AppColumnsLayout } from "../../../ui/app-columns-layout";
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { MjmlConfigurationForm } from "./mjml-configuration-form"; import { MjmlConfigurationForm } from "./mjml-configuration-form";
@ -14,6 +13,7 @@ import { LoadingIndicator } from "../../../ui/loading-indicator";
import { Add } from "@material-ui/icons"; import { Add } from "@material-ui/icons";
import { useQueryClient } from "@tanstack/react-query"; import { useQueryClient } from "@tanstack/react-query";
import { MjmlInstructions } from "./mjml-instructions"; import { MjmlInstructions } from "./mjml-instructions";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -50,7 +50,7 @@ const navigateToFirstConfiguration = (router: NextRouter, configurations?: MjmlC
export const MjmlConfigurationTab = ({ configurationId }: MjmlConfigurationTabProps) => { export const MjmlConfigurationTab = ({ configurationId }: MjmlConfigurationTabProps) => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { notifyError, notifySuccess } = useDashboardNotification();
const router = useRouter(); const router = useRouter();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -72,13 +72,7 @@ export const MjmlConfigurationTab = ({ configurationId }: MjmlConfigurationTabPr
const { mutate: deleteConfiguration } = const { mutate: deleteConfiguration } =
trpcClient.mjmlConfiguration.deleteConfiguration.useMutation({ trpcClient.mjmlConfiguration.deleteConfiguration.useMutation({
onError: (error) => { onError: (error) => {
appBridge?.dispatch( notifyError("Could not remove the configuration", error.message);
actions.Notification({
title: "Could not remove the configuration",
text: error.message,
status: "error",
})
);
}, },
onSuccess: async (_data, variables) => { onSuccess: async (_data, variables) => {
await queryClient.cancelQueries({ queryKey: ["mjmlConfiguration", "getConfigurations"] }); await queryClient.cancelQueries({ queryKey: ["mjmlConfiguration", "getConfigurations"] });
@ -103,13 +97,7 @@ export const MjmlConfigurationTab = ({ configurationId }: MjmlConfigurationTabPr
} }
refetchConfigurations(); refetchConfigurations();
appBridge?.dispatch( notifySuccess("Success", "Removed successfully");
actions.Notification({
title: "Success",
text: "Removed successfully",
status: "success",
})
);
}, },
}); });

View file

@ -22,6 +22,7 @@ import { useRouter } from "next/router";
import { mjmlUrls } from "../../urls"; import { mjmlUrls } from "../../urls";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge"; import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge";
import { examplePayloads } from "../../../event-handlers/default-payloads"; import { examplePayloads } from "../../../event-handlers/default-payloads";
import { useDashboardNotification } from "@saleor/apps-shared";
const PREVIEW_DEBOUNCE_DELAY = 500; const PREVIEW_DEBOUNCE_DELAY = 500;
@ -71,6 +72,7 @@ export const EventConfigurationForm = ({
configurationId, configurationId,
eventType, eventType,
}: EventConfigurationFormProps) => { }: EventConfigurationFormProps) => {
const { notifySuccess, notifyError } = useDashboardNotification();
const router = useRouter(); const router = useRouter();
const { appBridge } = useAppBridge(); const { appBridge } = useAppBridge();
const { handleSubmit, control, getValues, setError } = useForm<MjmlEventConfiguration>({ const { handleSubmit, control, getValues, setError } = useForm<MjmlEventConfiguration>({
@ -113,12 +115,7 @@ export const EventConfigurationForm = ({
const { mutate: updateEventConfiguration } = const { mutate: updateEventConfiguration } =
trpcClient.mjmlConfiguration.updateEventConfiguration.useMutation({ trpcClient.mjmlConfiguration.updateEventConfiguration.useMutation({
onSuccess: (data) => { onSuccess: (data) => {
appBridge?.dispatch( notifySuccess("Success", "Configuration saved");
actions.Notification({
title: "Configuration saved",
status: "success",
})
);
}, },
onError: (error) => { onError: (error) => {
let isFieldErrorSet = false; let isFieldErrorSet = false;
@ -134,13 +131,11 @@ export const EventConfigurationForm = ({
} }
const formErrors = error.data?.zodError?.formErrors || []; const formErrors = error.data?.zodError?.formErrors || [];
const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined; const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined;
appBridge?.dispatch(
actions.Notification({ notifyError(
title: "Could not save the configuration", "Could not save the configuration",
text: isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration", isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration",
apiMessage: formErrorMessage, formErrorMessage
status: "error",
})
); );
}, },
}); });

View file

@ -16,7 +16,7 @@ import { mjmlUrls } from "../../urls";
import { messageEventTypesLabels } from "../../../event-handlers/message-event-types"; import { messageEventTypesLabels } from "../../../event-handlers/message-event-types";
import { MjmlConfiguration } from "../mjml-config"; import { MjmlConfiguration } from "../mjml-config";
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge"; import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -52,18 +52,14 @@ export const MjmlTemplatesCard = ({
}: MjmlTemplatesCardProps) => { }: MjmlTemplatesCardProps) => {
const classes = useStyles(); const classes = useStyles();
const router = useRouter(); const router = useRouter();
const { appBridge } = useAppBridge(); const { notifySuccess } = useDashboardNotification();
const { mutate: updateEventConfiguration } = const { mutate: updateEventConfiguration } =
trpcClient.mjmlConfiguration.updateEventConfiguration.useMutation({ trpcClient.mjmlConfiguration.updateEventConfiguration.useMutation({
onSuccess(data, variables) { onSuccess(data, variables) {
onEventChanged(); onEventChanged();
appBridge?.dispatch(
actions.Notification({ notifySuccess(variables.active ? "Event enabled" : "Event disabled");
title: variables.active ? "Event enabled" : "Event disabled",
status: "success",
})
);
}, },
}); });

View file

@ -16,6 +16,7 @@ import { trpcClient } from "../../../trpc/trpc-client";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge"; import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge";
import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useQuery, useQueryClient } from "@tanstack/react-query";
import { fetchSenders } from "../../sendgrid-api"; import { fetchSenders } from "../../sendgrid-api";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
field: { field: {
@ -41,6 +42,7 @@ type Props = {
export const SendgridConfigurationForm = (props: Props) => { export const SendgridConfigurationForm = (props: Props) => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { appBridge } = useAppBridge();
const { notifySuccess, notifyError } = useDashboardNotification();
const [senderId, setSenderId] = useState<string | undefined>(undefined); const [senderId, setSenderId] = useState<string | undefined>(undefined);
const { handleSubmit, control, reset, setError, setValue } = useForm<SendgridConfiguration>({ const { handleSubmit, control, reset, setError, setValue } = useForm<SendgridConfiguration>({
@ -93,12 +95,7 @@ export const SendgridConfigurationForm = (props: Props) => {
// Trigger refetch to make sure we have a fresh data // Trigger refetch to make sure we have a fresh data
props.onConfigurationSaved(); props.onConfigurationSaved();
appBridge?.dispatch( notifySuccess("Configuration saved");
actions.Notification({
title: "Configuration saved",
status: "success",
})
);
}, },
onError(error) { onError(error) {
let isFieldErrorSet = false; let isFieldErrorSet = false;
@ -114,13 +111,11 @@ export const SendgridConfigurationForm = (props: Props) => {
} }
const formErrors = error.data?.zodError?.formErrors || []; const formErrors = error.data?.zodError?.formErrors || [];
const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined; const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined;
appBridge?.dispatch(
actions.Notification({ notifyError(
title: "Could not save the configuration", "Could not save the configuration",
text: isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration", isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration",
apiMessage: formErrorMessage, formErrorMessage
status: "error",
})
); );
}, },
}); });

View file

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import { IconButton, makeStyles } from "@saleor/macaw-ui"; import { IconButton, makeStyles } from "@saleor/macaw-ui";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { AppColumnsLayout } from "../../../ui/app-columns-layout"; import { AppColumnsLayout } from "../../../ui/app-columns-layout";
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { SendgridConfigurationForm } from "./sendgrid-configuration-form"; import { SendgridConfigurationForm } from "./sendgrid-configuration-form";
@ -14,6 +13,7 @@ import { useQueryClient } from "@tanstack/react-query";
import { sendgridUrls } from "../../urls"; import { sendgridUrls } from "../../urls";
import { SendgridTemplatesCard } from "./sendgrid-templates-card"; import { SendgridTemplatesCard } from "./sendgrid-templates-card";
import { SendgridInstructions } from "./sendgrid-instructions"; import { SendgridInstructions } from "./sendgrid-instructions";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -53,9 +53,9 @@ const navigateToFirstConfiguration = (
export const SendgridConfigurationTab = ({ configurationId }: SendgridConfigurationTabProps) => { export const SendgridConfigurationTab = ({ configurationId }: SendgridConfigurationTabProps) => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge();
const router = useRouter(); const router = useRouter();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { notifySuccess, notifyError } = useDashboardNotification();
const { const {
data: configurations, data: configurations,
@ -75,13 +75,7 @@ export const SendgridConfigurationTab = ({ configurationId }: SendgridConfigurat
const { mutate: deleteConfiguration } = const { mutate: deleteConfiguration } =
trpcClient.sendgridConfiguration.deleteConfiguration.useMutation({ trpcClient.sendgridConfiguration.deleteConfiguration.useMutation({
onError: (error) => { onError: (error) => {
appBridge?.dispatch( notifyError("Could not remove the configuration", error.message);
actions.Notification({
title: "Could not remove the configuration",
text: error.message,
status: "error",
})
);
}, },
onSuccess: async (_data, variables) => { onSuccess: async (_data, variables) => {
await queryClient.cancelQueries({ await queryClient.cancelQueries({
@ -108,13 +102,8 @@ export const SendgridConfigurationTab = ({ configurationId }: SendgridConfigurat
} }
refetchConfigurations(); refetchConfigurations();
appBridge?.dispatch(
actions.Notification({ notifySuccess("Success", "Removed successfully");
title: "Success",
text: "Removed successfully",
status: "success",
})
);
}, },
}); });

View file

@ -5,7 +5,6 @@ import {
InputLabel, InputLabel,
MenuItem, MenuItem,
Select, Select,
TextField,
TextFieldProps, TextFieldProps,
Typography, Typography,
} from "@material-ui/core"; } from "@material-ui/core";
@ -26,9 +25,9 @@ import {
import { trpcClient } from "../../../trpc/trpc-client"; import { trpcClient } from "../../../trpc/trpc-client";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { sendgridUrls } from "../../urls"; import { sendgridUrls } from "../../urls";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { fetchTemplates } from "../../sendgrid-api"; import { fetchTemplates } from "../../sendgrid-api";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
viewContainer: { viewContainer: {
@ -79,7 +78,8 @@ export const EventConfigurationForm = ({
configuration, configuration,
}: EventConfigurationFormProps) => { }: EventConfigurationFormProps) => {
const router = useRouter(); const router = useRouter();
const { appBridge } = useAppBridge(); const { notifySuccess, notifyError } = useDashboardNotification();
const { handleSubmit, control, getValues, setError } = useForm<SendgridEventConfiguration>({ const { handleSubmit, control, getValues, setError } = useForm<SendgridEventConfiguration>({
defaultValues: initialData, defaultValues: initialData,
}); });
@ -100,12 +100,7 @@ export const EventConfigurationForm = ({
const { mutate: updateEventConfiguration } = const { mutate: updateEventConfiguration } =
trpcClient.sendgridConfiguration.updateEventConfiguration.useMutation({ trpcClient.sendgridConfiguration.updateEventConfiguration.useMutation({
onSuccess: (data) => { onSuccess: (data) => {
appBridge?.dispatch( notifySuccess("Configuration saved");
actions.Notification({
title: "Configuration saved",
status: "success",
})
);
}, },
onError: (error) => { onError: (error) => {
let isFieldErrorSet = false; let isFieldErrorSet = false;
@ -121,13 +116,10 @@ export const EventConfigurationForm = ({
} }
const formErrors = error.data?.zodError?.formErrors || []; const formErrors = error.data?.zodError?.formErrors || [];
const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined; const formErrorMessage = formErrors.length ? formErrors.join("\n") : undefined;
appBridge?.dispatch( notifyError(
actions.Notification({ "Could not save the configuration",
title: "Could not save the configuration", isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration",
text: isFieldErrorSet ? "Submitted form contain errors" : "Error saving configuration", formErrorMessage
apiMessage: formErrorMessage,
status: "error",
})
); );
}, },
}); });

View file

@ -17,6 +17,7 @@ import { trpcClient } from "../../../trpc/trpc-client";
import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge"; import { useAppBridge, actions } from "@saleor/app-sdk/app-bridge";
import { SendgridConfiguration } from "../sendgrid-config"; import { SendgridConfiguration } from "../sendgrid-config";
import { sendgridUrls } from "../../urls"; import { sendgridUrls } from "../../urls";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -52,18 +53,13 @@ export const SendgridTemplatesCard = ({
}: SendgridTemplatesCardProps) => { }: SendgridTemplatesCardProps) => {
const classes = useStyles(); const classes = useStyles();
const router = useRouter(); const router = useRouter();
const { appBridge } = useAppBridge(); const { notifySuccess } = useDashboardNotification();
const { mutate: updateEventConfiguration } = const { mutate: updateEventConfiguration } =
trpcClient.sendgridConfiguration.updateEventConfiguration.useMutation({ trpcClient.sendgridConfiguration.updateEventConfiguration.useMutation({
onSuccess(_data, variables) { onSuccess(_data, variables) {
onEventChanged(); onEventChanged();
appBridge?.dispatch( notifySuccess(variables.active ? "Event enabled" : "Event disabled");
actions.Notification({
title: variables.active ? "Event enabled" : "Event disabled",
status: "success",
})
);
}, },
}); });

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,7 @@ import { AddressForm } from "./address-form";
import { ChannelsList } from "./channels-list"; import { ChannelsList } from "./channels-list";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge"; import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { AppColumnsLayout } from "../../ui/app-columns-layout"; import { AppColumnsLayout } from "../../ui/app-columns-layout";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -23,6 +24,7 @@ const useStyles = makeStyles((theme) => {
export const ChannelsConfiguration = () => { export const ChannelsConfiguration = () => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { appBridge } = useAppBridge();
const { notifySuccess } = useDashboardNotification();
const { data: configurationData, refetch: refetchConfig } = const { data: configurationData, refetch: refetchConfig } =
trpcClient.appConfiguration.fetch.useQuery(); trpcClient.appConfiguration.fetch.useQuery();
@ -34,13 +36,7 @@ export const ChannelsConfiguration = () => {
const { mutate, error: saveError } = trpcClient.appConfiguration.setAndReplace.useMutation({ const { mutate, error: saveError } = trpcClient.appConfiguration.setAndReplace.useMutation({
onSuccess() { onSuccess() {
refetchConfig(); refetchConfig();
appBridge?.dispatch( notifySuccess("Success", "Saved app configuration");
actions.Notification({
title: "Success",
text: "Saved app configuration",
status: "success",
})
);
}, },
}); });

View file

@ -15,7 +15,7 @@ const nextConfig = {
disableServerWebpackPlugin: !isSentryPropertiesInEnvironment, disableServerWebpackPlugin: !isSentryPropertiesInEnvironment,
disableClientWebpackPlugin: !isSentryPropertiesInEnvironment, disableClientWebpackPlugin: !isSentryPropertiesInEnvironment,
}, },
transpilePackages: ["nuvo-react", "@saleor/apps-shared"], transpilePackages: ["@saleor/apps-shared"],
redirects() { redirects() {
return [ return [
{ {

File diff suppressed because it is too large Load diff

View file

@ -9,8 +9,7 @@ import { ChangeEvent, SyntheticEvent, useEffect, useState } from "react";
import { AccessWarning } from "../components/AccessWarning/AccessWarning"; import { AccessWarning } from "../components/AccessWarning/AccessWarning";
import { useAppApi } from "../hooks/useAppApi"; import { useAppApi } from "../hooks/useAppApi";
import { AppColumnsLayout } from "../lib/ui/app-columns-layout"; import { AppColumnsLayout } from "../lib/ui/app-columns-layout";
import { useDashboardNotification } from "@saleor/apps-shared";
import { useDashboardNotifier } from "../utils/useDashboardNotifier";
interface ConfigurationField { interface ConfigurationField {
key: string; key: string;
@ -124,7 +123,7 @@ function Instructions() {
function Configuration() { function Configuration() {
const { appBridgeState } = useAppBridge(); const { appBridgeState } = useAppBridge();
const classes = useStyles(); const classes = useStyles();
const [notify] = useDashboardNotifier(); const { notifySuccess, notifyError } = useDashboardNotification();
const [configuration, setConfiguration] = useState<ConfigurationField[]>(); const [configuration, setConfiguration] = useState<ConfigurationField[]>();
const [transitionState, setTransitionState] = useState<ConfirmButtonTransitionState>("default"); const [transitionState, setTransitionState] = useState<ConfirmButtonTransitionState>("default");
@ -160,19 +159,13 @@ function Configuration() {
} }
setTransitionState("success"); setTransitionState("success");
await notify({ notifySuccess("Success", "Configuration updated successfully");
status: "success",
title: "Success",
text: "Configuration updated successfully",
});
}) })
.catch(async () => { .catch(async () => {
setTransitionState("error"); setTransitionState("error");
await notify({ await notifyError(
status: "error", "Configuration update failed. Ensure fields are filled correctly and you have MANAGE_APPS permission"
title: );
"Configuration update failed. Ensure fields are filled correctly and you have MANAGE_APPS permission",
});
}); });
}; };

View file

@ -1,10 +0,0 @@
import { actions, NotificationPayload, useAppBridge } from "@saleor/app-sdk/app-bridge";
export const useDashboardNotifier = () => {
const { appBridgeState, appBridge } = useAppBridge();
const notify = (payload: NotificationPayload) =>
appBridgeState?.ready && appBridge?.dispatch(actions.Notification(payload));
return [notify];
};

View file

@ -1,5 +1,6 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
module.exports = { module.exports = {
transpilePackages: ["@saleor/apps-shared"],
reactStrictMode: true, reactStrictMode: true,
rewrites() { rewrites() {
/** /**

File diff suppressed because it is too large Load diff

View file

@ -1,30 +0,0 @@
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
export const useDashboardNotifications = () => {
const { appBridge } = useAppBridge();
const showSuccessNotification = (title: string, text: string) => {
appBridge?.dispatch(
actions.Notification({
title: title,
text: text,
status: "success",
})
);
};
const showErrorNotification = (title: string, text: string) => {
appBridge?.dispatch(
actions.Notification({
title: title,
text: text,
status: "error",
})
);
};
return {
showSuccessNotification,
showErrorNotification,
};
};

View file

@ -28,8 +28,9 @@ import { gql, useMutation } from "urql";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge"; import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { ArrowBack } from "@material-ui/icons"; import { ArrowBack } from "@material-ui/icons";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useDashboardNotifications } from "../../lib/use-dashboard-notifications";
import { API_KEYS_LINKS } from "../../datadog-urls"; import { API_KEYS_LINKS } from "../../datadog-urls";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles({ const useStyles = makeStyles({
form: { form: {
@ -133,7 +134,7 @@ export const DatadogConfig = () => {
const [, mutateCredentials] = useUpdateCredentialsMutation(); const [, mutateCredentials] = useUpdateCredentialsMutation();
const [, deleteCredentials] = useDeleteDatadogCredentialsMutation(); const [, deleteCredentials] = useDeleteDatadogCredentialsMutation();
const router = useRouter(); const router = useRouter();
const { showSuccessNotification, showErrorNotification } = useDashboardNotifications(); const { notifyError, notifySuccess } = useDashboardNotification();
const { register, handleSubmit, setValue, control, reset, watch } = useForm< const { register, handleSubmit, setValue, control, reset, watch } = useForm<
DataDogCredentialsInput & { DataDogCredentialsInput & {
@ -213,14 +214,11 @@ export const DatadogConfig = () => {
setValue("apiKey", buildMaskedKey(updatedConfig.credentials.apiKeyLast4)); setValue("apiKey", buildMaskedKey(updatedConfig.credentials.apiKeyLast4));
setValue("site", updatedConfig.credentials.site); setValue("site", updatedConfig.credentials.site);
showSuccessNotification( notifySuccess("Configuration updated", "Successfully updated Datadog settings");
"Configuration updated",
"Successfully updated Datadog settings"
);
} }
if (errors?.length) { if (errors?.length) {
showErrorNotification("Error configuring Datadog", errors[0].message); notifyError("Error configuring Datadog", errors[0].message);
} }
}); });
})} })}
@ -278,10 +276,7 @@ export const DatadogConfig = () => {
deleteCredentials({}).then(() => { deleteCredentials({}).then(() => {
fetchConfig(); fetchConfig();
reset(); reset();
showSuccessNotification( notifySuccess("Configuration updated", "Successfully deleted Datadog settings");
"Configuration updated",
"Successfully deleted Datadog settings"
);
}); });
}} }}
> >

View file

@ -1,4 +1,5 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
module.exports = { module.exports = {
reactStrictMode: true, reactStrictMode: true,
transpilePackages: ["@saleor/apps-shared"],
}; };

File diff suppressed because it is too large Load diff

View file

@ -9,6 +9,7 @@ import { AppColumnsLayout } from "../../ui/app-columns-layout";
import { FeedPreviewCard } from "./feed-preview-card"; import { FeedPreviewCard } from "./feed-preview-card";
import { Instructions } from "./instructions"; import { Instructions } from "./instructions";
import { SideMenu } from "./side-menu"; import { SideMenu } from "./side-menu";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => { const useStyles = makeStyles((theme) => {
return { return {
@ -33,6 +34,7 @@ export const ChannelsConfiguration = () => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { appBridge } = useAppBridge();
const { notifySuccess } = useDashboardNotification();
const { data: configurationData, refetch: refetchConfig } = const { data: configurationData, refetch: refetchConfig } =
trpcClient.appConfiguration.fetch.useQuery(); trpcClient.appConfiguration.fetch.useQuery();
@ -44,13 +46,7 @@ export const ChannelsConfiguration = () => {
const { mutate, error: saveError } = trpcClient.appConfiguration.setAndReplace.useMutation({ const { mutate, error: saveError } = trpcClient.appConfiguration.setAndReplace.useMutation({
onSuccess() { onSuccess() {
refetchConfig(); refetchConfig();
appBridge?.dispatch( notifySuccess("Success", "Saved app configuration");
actions.Notification({
title: "Success",
text: "Saved app configuration",
status: "success",
})
);
}, },
}); });

View file

@ -1,16 +1,7 @@
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
import { import { FormControl, Grid, InputLabel, MenuItem, Select, Typography } from "@material-ui/core";
FormControl,
Grid,
InputLabel,
MenuItem,
Select,
TextFieldProps,
Typography,
} from "@material-ui/core";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import React from "react"; import React from "react";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { import {
SetCategoryMappingInputSchema, SetCategoryMappingInputSchema,
@ -19,6 +10,7 @@ import {
import { CategoryWithMappingFragmentFragment } from "../../../../generated/graphql"; import { CategoryWithMappingFragmentFragment } from "../../../../generated/graphql";
import { GoogleProductCategories } from "../google-product-categories"; import { GoogleProductCategories } from "../google-product-categories";
import { trpcClient } from "../../trpc/trpc-client"; import { trpcClient } from "../../trpc/trpc-client";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles({ const useStyles = makeStyles({
field: { field: {
@ -39,7 +31,7 @@ type CategoryMappingFormProps = {
export const CategoryMappingForm = ({ category }: CategoryMappingFormProps) => { export const CategoryMappingForm = ({ category }: CategoryMappingFormProps) => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge(); const { notifySuccess, notifyError } = useDashboardNotification();
const { control, handleSubmit, formState } = useForm<SetCategoryMappingInputType>({ const { control, handleSubmit, formState } = useForm<SetCategoryMappingInputType>({
defaultValues: { defaultValues: {
@ -50,20 +42,10 @@ export const CategoryMappingForm = ({ category }: CategoryMappingFormProps) => {
}); });
const { mutate, isLoading } = trpcClient.categoryMapping.setCategoryMapping.useMutation({ const { mutate, isLoading } = trpcClient.categoryMapping.setCategoryMapping.useMutation({
onError() { onError() {
appBridge?.dispatch( notifyError("Could not save the category mapping");
actions.Notification({
title: "Could not save the category mapping",
status: "error",
})
);
}, },
onSuccess() { onSuccess() {
appBridge?.dispatch( notifySuccess("Success");
actions.Notification({
title: "Success",
status: "success",
})
);
}, },
}); });

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -17,8 +17,8 @@ import { ChangeEvent, ReactElement, SyntheticEvent, useEffect, useState } from "
import { AccessWarning } from "../components/AccessWarning/AccessWarning"; import { AccessWarning } from "../components/AccessWarning/AccessWarning";
import { ConfigurationError } from "../components/ConfigurationError/ConfigurationError"; import { ConfigurationError } from "../components/ConfigurationError/ConfigurationError";
import { useAppApi } from "../hooks/useAppApi"; import { useAppApi } from "../hooks/useAppApi";
import { useDashboardNotifier } from "../utils/useDashboardNotifier";
import { AppColumnsLayout } from "../components/AppColumnsLayout/AppColumnsLayout"; import { AppColumnsLayout } from "../components/AppColumnsLayout/AppColumnsLayout";
import { useDashboardNotification } from "@saleor/apps-shared";
interface ConfigurationField { interface ConfigurationField {
key: string; key: string;
@ -40,7 +40,7 @@ const useStyles = makeStyles((theme) => ({
function Configuration() { function Configuration() {
const classes = useStyles(); const classes = useStyles();
const { appBridgeState } = useAppBridge(); const { appBridgeState } = useAppBridge();
const [notify] = useDashboardNotifier(); const { notifyError, notifySuccess } = useDashboardNotification();
const [configuration, setConfiguration] = useState<ConfigurationField[]>(); const [configuration, setConfiguration] = useState<ConfigurationField[]>();
const [transitionState, setTransitionState] = useState<ConfirmButtonTransitionState>("default"); const [transitionState, setTransitionState] = useState<ConfirmButtonTransitionState>("default");
@ -69,18 +69,11 @@ function Configuration() {
}) })
.then(async (response) => { .then(async (response) => {
setTransitionState(response.status === 200 ? "success" : "error"); setTransitionState(response.status === 200 ? "success" : "error");
await notify({ notifySuccess("Success", "Configuration updated successfully");
status: "success",
title: "Success",
text: "Configuration updated successfully",
});
}) })
.catch(async () => { .catch(async () => {
setTransitionState("error"); setTransitionState("error");
await notify({ await notifyError("Configuration update failed");
status: "error",
title: "Configuration update failed",
});
}); });
}; };

View file

@ -1,10 +0,0 @@
import { actions, NotificationPayload, useAppBridge } from "@saleor/app-sdk/app-bridge";
export const useDashboardNotifier = () => {
const { appBridge, appBridgeState } = useAppBridge();
const notify = (payload: NotificationPayload) =>
appBridgeState?.ready && appBridge?.dispatch(actions.Notification(payload));
return [notify];
};

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,6 @@ import {
TextFieldProps, TextFieldProps,
} from "@material-ui/core"; } from "@material-ui/core";
import { Delete, Save } from "@material-ui/icons"; import { Delete, Save } from "@material-ui/icons";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import React from "react"; import React from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
@ -17,6 +16,7 @@ import { useInstanceId } from "../../taxes/tax-context";
import { trpcClient } from "../../trpc/trpc-client"; import { trpcClient } from "../../trpc/trpc-client";
import { AppLink } from "../../ui/app-link"; import { AppLink } from "../../ui/app-link";
import { avataxConfigSchema } from "../avatax-config"; import { avataxConfigSchema } from "../avatax-config";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
reverseRow: { reverseRow: {
@ -39,9 +39,9 @@ const defaultValues: FormValues = {
}; };
export const AvataxConfigurationForm = () => { export const AvataxConfigurationForm = () => {
const { notifySuccess, notifyError } = useDashboardNotification();
const [isWarningDialogOpen, setIsWarningDialogOpen] = React.useState(false); const [isWarningDialogOpen, setIsWarningDialogOpen] = React.useState(false);
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge();
const { handleSubmit, reset, control, formState } = useForm<FormValues>({ const { handleSubmit, reset, control, formState } = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
defaultValues, defaultValues,
@ -50,13 +50,7 @@ export const AvataxConfigurationForm = () => {
const { refetch: refetchChannelConfigurationData } = const { refetch: refetchChannelConfigurationData } =
trpcClient.channelsConfiguration.fetch.useQuery(undefined, { trpcClient.channelsConfiguration.fetch.useQuery(undefined, {
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
const { refetch: refetchProvidersConfigurationData } = const { refetch: refetchProvidersConfigurationData } =
@ -66,13 +60,7 @@ export const AvataxConfigurationForm = () => {
{ {
enabled: !!instanceId, enabled: !!instanceId,
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
} }
); );
@ -95,22 +83,10 @@ export const AvataxConfigurationForm = () => {
onSuccess({ id }) { onSuccess({ id }) {
setInstanceId(id); setInstanceId(id);
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
appBridge?.dispatch( notifySuccess("Success", "Saved app configuration");
actions.Notification({
title: "Success",
text: "Saved app configuration",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -118,22 +94,10 @@ export const AvataxConfigurationForm = () => {
trpcClient.avataxConfiguration.patch.useMutation({ trpcClient.avataxConfiguration.patch.useMutation({
onSuccess() { onSuccess() {
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
appBridge?.dispatch( notifySuccess("Success", "Updated Avalara configuration");
actions.Notification({
title: "Success",
text: "Updated Avalara configuration",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -142,22 +106,10 @@ export const AvataxConfigurationForm = () => {
resetInstanceId(); resetInstanceId();
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
refetchChannelConfigurationData(); refetchChannelConfigurationData();
appBridge?.dispatch( notifySuccess("Success", "Removed Avatax instance");
actions.Notification({
title: "Success",
text: "Removed Avatax instance",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });

View file

@ -11,7 +11,6 @@ import {
Typography, Typography,
} from "@material-ui/core"; } from "@material-ui/core";
import { Save } from "@material-ui/icons"; import { Save } from "@material-ui/icons";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import React from "react"; import React from "react";
@ -25,6 +24,7 @@ import { ProvidersConfig } from "../../providers-configuration/providers-config"
import { ProviderIcon } from "../../providers-configuration/ui/provider-icon"; import { ProviderIcon } from "../../providers-configuration/ui/provider-icon";
import { useChannelSlug } from "../../taxes/tax-context"; import { useChannelSlug } from "../../taxes/tax-context";
import { trpcClient } from "../../trpc/trpc-client"; import { trpcClient } from "../../trpc/trpc-client";
import { useDashboardNotification } from "@saleor/apps-shared";
type ChannelTaxProviderFormValues = ChannelConfig; type ChannelTaxProviderFormValues = ChannelConfig;
@ -70,23 +70,17 @@ const getDefaultFormValues = (
// todo: rename because address is here // todo: rename because address is here
export const ChannelTaxProviderForm = () => { export const ChannelTaxProviderForm = () => {
const styles = useStyles(); const styles = useStyles();
const { appBridge } = useAppBridge();
const { control, reset, handleSubmit } = useForm<ChannelTaxProviderFormValues>({ const { control, reset, handleSubmit } = useForm<ChannelTaxProviderFormValues>({
resolver: zodResolver(channelSchema), resolver: zodResolver(channelSchema),
}); });
const { notifyError, notifySuccess } = useDashboardNotification();
const { channelSlug } = useChannelSlug(); const { channelSlug } = useChannelSlug();
const { data: channelConfigurationData, refetch: refetchChannelConfigurationData } = const { data: channelConfigurationData, refetch: refetchChannelConfigurationData } =
trpcClient.channelsConfiguration.fetch.useQuery(undefined, { trpcClient.channelsConfiguration.fetch.useQuery(undefined, {
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -94,13 +88,7 @@ export const ChannelTaxProviderForm = () => {
undefined, undefined,
{ {
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
} }
); );
@ -109,22 +97,10 @@ export const ChannelTaxProviderForm = () => {
const { mutate, isLoading } = trpcClient.channelsConfiguration.upsert.useMutation({ const { mutate, isLoading } = trpcClient.channelsConfiguration.upsert.useMutation({
onSuccess() { onSuccess() {
refetchChannelConfigurationData(); refetchChannelConfigurationData();
appBridge?.dispatch( notifySuccess("Success", `Saved configuration of channel: ${channelSlug}`);
actions.Notification({
title: "Success",
text: `Saved configuration of channel: ${channelSlug}`,
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });

View file

@ -8,7 +8,6 @@ import {
TextFieldProps, TextFieldProps,
} from "@material-ui/core"; } from "@material-ui/core";
import { Delete, Save } from "@material-ui/icons"; import { Delete, Save } from "@material-ui/icons";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
import { Button, makeStyles } from "@saleor/macaw-ui"; import { Button, makeStyles } from "@saleor/macaw-ui";
import React from "react"; import React from "react";
import { Controller, useForm } from "react-hook-form"; import { Controller, useForm } from "react-hook-form";
@ -16,6 +15,7 @@ import { z } from "zod";
import { useInstanceId } from "../../taxes/tax-context"; import { useInstanceId } from "../../taxes/tax-context";
import { trpcClient } from "../../trpc/trpc-client"; import { trpcClient } from "../../trpc/trpc-client";
import { taxJarConfigSchema } from "../taxjar-config"; import { taxJarConfigSchema } from "../taxjar-config";
import { useDashboardNotification } from "@saleor/apps-shared";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
reverseRow: { reverseRow: {
@ -38,11 +38,11 @@ export const TaxJarConfigurationForm = () => {
const [isWarningDialogOpen, setIsWarningDialogOpen] = React.useState(false); const [isWarningDialogOpen, setIsWarningDialogOpen] = React.useState(false);
const styles = useStyles(); const styles = useStyles();
const { instanceId, setInstanceId } = useInstanceId(); const { instanceId, setInstanceId } = useInstanceId();
const { appBridge } = useAppBridge();
const { handleSubmit, reset, control, formState } = useForm<FormValues>({ const { handleSubmit, reset, control, formState } = useForm<FormValues>({
resolver: zodResolver(schema), resolver: zodResolver(schema),
defaultValues, defaultValues,
}); });
const { notifySuccess, notifyError } = useDashboardNotification();
const resetInstanceId = () => { const resetInstanceId = () => {
setInstanceId(null); setInstanceId(null);
@ -51,13 +51,7 @@ export const TaxJarConfigurationForm = () => {
const { refetch: refetchChannelConfigurationData } = const { refetch: refetchChannelConfigurationData } =
trpcClient.channelsConfiguration.fetch.useQuery(undefined, { trpcClient.channelsConfiguration.fetch.useQuery(undefined, {
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -68,13 +62,7 @@ export const TaxJarConfigurationForm = () => {
{ {
enabled: !!instanceId, enabled: !!instanceId,
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
} }
); );
@ -85,22 +73,11 @@ export const TaxJarConfigurationForm = () => {
setInstanceId(id); setInstanceId(id);
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
refetchChannelConfigurationData(); refetchChannelConfigurationData();
appBridge?.dispatch(
actions.Notification({ notifySuccess("Success", "Saved TaxJar configuration");
title: "Success",
text: "Saved TaxJar configuration",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -109,22 +86,10 @@ export const TaxJarConfigurationForm = () => {
onSuccess() { onSuccess() {
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
refetchChannelConfigurationData(); refetchChannelConfigurationData();
appBridge?.dispatch( notifySuccess("Success", "Updated TaxJar configuration");
actions.Notification({
title: "Success",
text: "Updated TaxJar configuration",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });
@ -134,22 +99,11 @@ export const TaxJarConfigurationForm = () => {
resetInstanceId(); resetInstanceId();
refetchProvidersConfigurationData(); refetchProvidersConfigurationData();
refetchChannelConfigurationData(); refetchChannelConfigurationData();
appBridge?.dispatch(
actions.Notification({ notifySuccess("Success", "Removed TaxJar instance");
title: "Success",
text: "Removed TaxJar instance",
status: "success",
})
);
}, },
onError(error) { onError(error) {
appBridge?.dispatch( notifyError("Error", error.message);
actions.Notification({
title: "Error",
text: error.message,
status: "error",
})
);
}, },
}); });

View file

@ -1,3 +1,4 @@
export * from "./src/is-in-iframe"; export * from "./src/is-in-iframe";
export * from "./src/macaw-theme-provider/macaw-theme-provider"; export * from "./src/macaw-theme-provider/macaw-theme-provider";
export * from "./src/no-ssr-wrapper"; export * from "./src/no-ssr-wrapper";
export * from "./src/use-dashboard-notification";

View file

@ -0,0 +1,58 @@
import { useCallback } from "react";
import { actions, useAppBridge } from "@saleor/app-sdk/app-bridge";
export const useDashboardNotification = () => {
const { appBridge } = useAppBridge();
return {
notifySuccess: useCallback(
(title: string, text?: string) => {
appBridge?.dispatch(
actions.Notification({
status: "success",
title,
text,
})
);
},
[appBridge]
),
notifyError: useCallback(
(title: string, text?: string, apiMessage?: string) => {
appBridge?.dispatch(
actions.Notification({
status: "error",
title,
text,
apiMessage: apiMessage,
})
);
},
[appBridge]
),
notifyWarning: useCallback(
(title: string, text?: string) => {
appBridge?.dispatch(
actions.Notification({
status: "warning",
title,
text,
})
);
},
[appBridge]
),
notifyInfo: useCallback(
(title: string, text?: string) => {
appBridge?.dispatch(
actions.Notification({
status: "info",
title,
text,
})
);
},
[appBridge]
),
};
};