feat(AddAppConnection): show pop-up reminder hint
This commit is contained in:
@@ -31,7 +31,7 @@ function AddAppConnection(props) {
|
|||||||
const hasConnection = Boolean(connectionId);
|
const hasConnection = Boolean(connectionId);
|
||||||
const useShared = searchParams.get('shared') === 'true';
|
const useShared = searchParams.get('shared') === 'true';
|
||||||
const appAuthClientId = searchParams.get('appAuthClientId') || undefined;
|
const appAuthClientId = searchParams.get('appAuthClientId') || undefined;
|
||||||
const { authenticate } = useAuthenticateApp({
|
const { authenticate, isPopupBlocked } = useAuthenticateApp({
|
||||||
appKey: key,
|
appKey: key,
|
||||||
connectionId,
|
connectionId,
|
||||||
appAuthClientId,
|
appAuthClientId,
|
||||||
@@ -76,6 +76,7 @@ function AddAppConnection(props) {
|
|||||||
async (data) => {
|
async (data) => {
|
||||||
if (!authenticate) return;
|
if (!authenticate) return;
|
||||||
setInProgress(true);
|
setInProgress(true);
|
||||||
|
setError(null);
|
||||||
try {
|
try {
|
||||||
const response = await authenticate({
|
const response = await authenticate({
|
||||||
fields: data,
|
fields: data,
|
||||||
@@ -88,7 +89,12 @@ function AddAppConnection(props) {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
const error = err;
|
const error = err;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
setError(error.graphQLErrors?.[0]);
|
|
||||||
|
if (error.message) {
|
||||||
|
setError(error);
|
||||||
|
} else {
|
||||||
|
setError(error.graphQLErrors?.[0]);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
setInProgress(false);
|
setInProgress(false);
|
||||||
}
|
}
|
||||||
@@ -128,6 +134,12 @@ function AddAppConnection(props) {
|
|||||||
</Alert>
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isPopupBlocked && (
|
||||||
|
<Alert severity="warning" sx={{ fontWeight: 300, mt: 1 }}>
|
||||||
|
{formatMessage('addAppConnection.popupReminder')}
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<Alert
|
<Alert
|
||||||
severity="error"
|
severity="error"
|
||||||
|
@@ -1,13 +1,8 @@
|
|||||||
import apolloClient from 'graphql/client';
|
import apolloClient from 'graphql/client';
|
||||||
import MUTATIONS from 'graphql/mutations';
|
import MUTATIONS from 'graphql/mutations';
|
||||||
var AuthenticationSteps;
|
|
||||||
(function (AuthenticationSteps) {
|
|
||||||
AuthenticationSteps['Mutation'] = 'mutation';
|
|
||||||
AuthenticationSteps['OpenWithPopup'] = 'openWithPopup';
|
|
||||||
})(AuthenticationSteps || (AuthenticationSteps = {}));
|
|
||||||
|
|
||||||
const processMutation = async (step, variables) => {
|
export const processMutation = async (mutationName, variables) => {
|
||||||
const mutation = MUTATIONS[step.name];
|
const mutation = MUTATIONS[mutationName];
|
||||||
const mutationResponse = await apolloClient.mutate({
|
const mutationResponse = await apolloClient.mutate({
|
||||||
mutation,
|
mutation,
|
||||||
variables: { input: variables },
|
variables: { input: variables },
|
||||||
@@ -15,56 +10,70 @@ const processMutation = async (step, variables) => {
|
|||||||
autoSnackbar: false,
|
autoSnackbar: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const responseData = mutationResponse.data[step.name];
|
const responseData = mutationResponse.data[mutationName];
|
||||||
|
|
||||||
return responseData;
|
return responseData;
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseUrlSearchParams = (event) => {
|
const parseUrlSearchParams = (event) => {
|
||||||
const searchParams = new URLSearchParams(event.data.payload.search);
|
const searchParams = new URLSearchParams(event.data.payload.search);
|
||||||
const hashParams = new URLSearchParams(event.data.payload.hash.substring(1));
|
const hashParams = new URLSearchParams(event.data.payload.hash.substring(1));
|
||||||
const searchParamsObject = getObjectOfEntries(searchParams.entries());
|
const searchParamsObject = getObjectOfEntries(searchParams.entries());
|
||||||
const hashParamsObject = getObjectOfEntries(hashParams.entries());
|
const hashParamsObject = getObjectOfEntries(hashParams.entries());
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...hashParamsObject,
|
...hashParamsObject,
|
||||||
...searchParamsObject,
|
...searchParamsObject,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
function getObjectOfEntries(iterator) {
|
function getObjectOfEntries(iterator) {
|
||||||
const result = {};
|
const result = {};
|
||||||
for (const [key, value] of iterator) {
|
for (const [key, value] of iterator) {
|
||||||
result[key] = value;
|
result[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const processOpenWithPopup = (step, variables) => {
|
|
||||||
|
export const processOpenWithPopup = (url) => {
|
||||||
|
const windowFeatures =
|
||||||
|
'toolbar=no, titlebar=no, menubar=no, width=500, height=700, top=100, left=100';
|
||||||
|
const popup = window.open(url, '_blank', windowFeatures);
|
||||||
|
popup?.focus();
|
||||||
|
|
||||||
|
return popup;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const processPopupMessage = (popup) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const windowFeatures =
|
let closeCheckIntervalId;
|
||||||
'toolbar=no, titlebar=no, menubar=no, width=500, height=700, top=100, left=100';
|
|
||||||
const url = variables.url;
|
if (popup) {
|
||||||
const popup = window.open(url, '_blank', windowFeatures);
|
closeCheckIntervalId = setInterval(() => {
|
||||||
popup?.focus();
|
if (popup.closed) {
|
||||||
const closeCheckIntervalId = setInterval(() => {
|
clearInterval(closeCheckIntervalId);
|
||||||
if (!popup) return;
|
|
||||||
if (popup?.closed) {
|
reject({ message: 'Error occured while verifying credentials!' });
|
||||||
clearInterval(closeCheckIntervalId);
|
}
|
||||||
reject({ message: 'Error occured while verifying credentials!' });
|
}, 1000);
|
||||||
}
|
}
|
||||||
}, 1000);
|
|
||||||
const messageHandler = async (event) => {
|
const messageHandler = async (event) => {
|
||||||
if (event.data.source !== 'automatisch') {
|
if (event.data.source !== 'automatisch') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = parseUrlSearchParams(event);
|
const data = parseUrlSearchParams(event);
|
||||||
window.removeEventListener('message', messageHandler);
|
window.removeEventListener('message', messageHandler);
|
||||||
clearInterval(closeCheckIntervalId);
|
|
||||||
|
if (closeCheckIntervalId) {
|
||||||
|
clearInterval(closeCheckIntervalId);
|
||||||
|
}
|
||||||
|
|
||||||
resolve(data);
|
resolve(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('message', messageHandler, false);
|
window.addEventListener('message', messageHandler, false);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const processStep = async (step, variables) => {
|
|
||||||
if (step.type === AuthenticationSteps.Mutation) {
|
|
||||||
return processMutation(step, variables);
|
|
||||||
} else if (step.type === AuthenticationSteps.OpenWithPopup) {
|
|
||||||
return processOpenWithPopup(step, variables);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
|
||||||
import { processStep } from 'helpers/authenticationSteps';
|
import {
|
||||||
|
processMutation,
|
||||||
|
processOpenWithPopup,
|
||||||
|
processPopupMessage,
|
||||||
|
} from 'helpers/authenticationSteps';
|
||||||
import computeAuthStepVariables from 'helpers/computeAuthStepVariables';
|
import computeAuthStepVariables from 'helpers/computeAuthStepVariables';
|
||||||
import useAppAuth from './useAppAuth';
|
import useAppAuth from './useAppAuth';
|
||||||
|
|
||||||
@@ -24,6 +28,7 @@ export default function useAuthenticateApp(payload) {
|
|||||||
const { data: auth } = useAppAuth(appKey);
|
const { data: auth } = useAppAuth(appKey);
|
||||||
const [authenticationInProgress, setAuthenticationInProgress] =
|
const [authenticationInProgress, setAuthenticationInProgress] =
|
||||||
React.useState(false);
|
React.useState(false);
|
||||||
|
const [isPopupBlocked, setPopupBlocked] = React.useState(false);
|
||||||
const steps = getSteps(auth?.data, !!connectionId, useShared);
|
const steps = getSteps(auth?.data, !!connectionId, useShared);
|
||||||
|
|
||||||
const authenticate = React.useMemo(() => {
|
const authenticate = React.useMemo(() => {
|
||||||
@@ -45,10 +50,24 @@ export default function useAuthenticateApp(payload) {
|
|||||||
while (stepIndex < steps?.length) {
|
while (stepIndex < steps?.length) {
|
||||||
const step = steps[stepIndex];
|
const step = steps[stepIndex];
|
||||||
const variables = computeAuthStepVariables(step.arguments, response);
|
const variables = computeAuthStepVariables(step.arguments, response);
|
||||||
|
let popup;
|
||||||
|
|
||||||
|
if (step.type === 'openWithPopup') {
|
||||||
|
popup = processOpenWithPopup(variables.url);
|
||||||
|
|
||||||
|
if (!popup) {
|
||||||
|
setPopupBlocked(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stepResponse = await processStep(step, variables);
|
if (step.type === 'mutation') {
|
||||||
response[step.name] = stepResponse;
|
const stepResponse = await processMutation(step.name, variables);
|
||||||
|
response[step.name] = stepResponse;
|
||||||
|
} else if (step.type === 'openWithPopup') {
|
||||||
|
const stepResponse = await processPopupMessage(popup);
|
||||||
|
response[step.name] = stepResponse;
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
setAuthenticationInProgress(false);
|
setAuthenticationInProgress(false);
|
||||||
@@ -66,6 +85,7 @@ export default function useAuthenticateApp(payload) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
authenticate,
|
authenticate,
|
||||||
|
isPopupBlocked,
|
||||||
inProgress: authenticationInProgress,
|
inProgress: authenticationInProgress,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
"apps.noConnections": "You don't have any connections yet.",
|
"apps.noConnections": "You don't have any connections yet.",
|
||||||
"addAppConnection.submit": "Submit",
|
"addAppConnection.submit": "Submit",
|
||||||
"addAppConnection.callToDocs": "Visit <docsLink>our documentation</docsLink> to see how to add connection for {appName}.",
|
"addAppConnection.callToDocs": "Visit <docsLink>our documentation</docsLink> to see how to add connection for {appName}.",
|
||||||
|
"addAppConnection.popupReminder": "Make sure pop-ups are enabled in your browser.",
|
||||||
"connection.flowCount": "{count} flows",
|
"connection.flowCount": "{count} flows",
|
||||||
"connection.viewFlows": "View flows",
|
"connection.viewFlows": "View flows",
|
||||||
"connection.testConnection": "Test connection",
|
"connection.testConnection": "Test connection",
|
||||||
|
Reference in New Issue
Block a user