bugfix(CON-01, CON-02)
This commit is contained in:
parent
f09f43666a
commit
238dd6ae16
2 changed files with 43 additions and 12 deletions
|
|
@ -333,6 +333,8 @@ export function useConnections() {
|
|||
|
||||
// Create Google connection and open OAuth popup
|
||||
const createGoogleConnectionAndAuth = async (): Promise<void> => {
|
||||
if (isConnecting) return;
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
// Step 1: Create a Google connection
|
||||
const newConnection = await createConnection({
|
||||
|
|
@ -354,7 +356,7 @@ export function useConnections() {
|
|||
authUrl = `${apiBaseUrl}${authUrl}`;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
const popup = window.open(
|
||||
authUrl,
|
||||
'google-connection',
|
||||
|
|
@ -362,6 +364,7 @@ export function useConnections() {
|
|||
);
|
||||
|
||||
if (!popup) {
|
||||
setIsConnecting(false);
|
||||
reject(new Error('Popup was blocked. Please allow popups and try again.'));
|
||||
return;
|
||||
}
|
||||
|
|
@ -371,6 +374,7 @@ export function useConnections() {
|
|||
if (popup.closed) {
|
||||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
setIsConnecting(false);
|
||||
console.log('Google OAuth popup closed');
|
||||
// Refresh connections in case it succeeded
|
||||
fetchConnections();
|
||||
|
|
@ -390,6 +394,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
console.log('Google connection successful');
|
||||
// Refresh connections
|
||||
fetchConnections();
|
||||
|
|
@ -398,6 +403,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
reject(new Error(event.data.error || 'Google connection failed'));
|
||||
}
|
||||
};
|
||||
|
|
@ -405,6 +411,7 @@ export function useConnections() {
|
|||
window.addEventListener('message', messageListener);
|
||||
});
|
||||
} catch (error) {
|
||||
setIsConnecting(false);
|
||||
console.error('Error creating Google connection:', error);
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -412,6 +419,8 @@ export function useConnections() {
|
|||
|
||||
// Create ClickUp connection and open OAuth popup
|
||||
const createClickupConnectionAndAuth = async (): Promise<void> => {
|
||||
if (isConnecting) return;
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
const newConnection = await createConnection({
|
||||
type: 'clickup',
|
||||
|
|
@ -430,7 +439,7 @@ export function useConnections() {
|
|||
authUrl = `${apiBaseUrl}${authUrl}`;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
const popup = window.open(
|
||||
authUrl,
|
||||
'clickup-connection',
|
||||
|
|
@ -438,6 +447,7 @@ export function useConnections() {
|
|||
);
|
||||
|
||||
if (!popup) {
|
||||
setIsConnecting(false);
|
||||
reject(new Error('Popup was blocked. Please allow popups and try again.'));
|
||||
return;
|
||||
}
|
||||
|
|
@ -446,6 +456,7 @@ export function useConnections() {
|
|||
if (popup.closed) {
|
||||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
setIsConnecting(false);
|
||||
console.log('ClickUp OAuth popup closed');
|
||||
fetchConnections();
|
||||
resolve();
|
||||
|
|
@ -462,6 +473,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
console.log('ClickUp connection successful');
|
||||
fetchConnections();
|
||||
resolve();
|
||||
|
|
@ -469,6 +481,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
reject(new Error(event.data.error || 'ClickUp connection failed'));
|
||||
}
|
||||
};
|
||||
|
|
@ -476,6 +489,7 @@ export function useConnections() {
|
|||
window.addEventListener('message', messageListener);
|
||||
});
|
||||
} catch (error) {
|
||||
setIsConnecting(false);
|
||||
console.error('Error creating ClickUp connection:', error);
|
||||
throw error;
|
||||
}
|
||||
|
|
@ -483,6 +497,8 @@ export function useConnections() {
|
|||
|
||||
// Create Microsoft connection and open OAuth popup
|
||||
const createMicrosoftConnectionAndAuth = async (): Promise<void> => {
|
||||
if (isConnecting) return;
|
||||
setIsConnecting(true);
|
||||
try {
|
||||
// Step 1: Create a Microsoft connection
|
||||
const newConnection = await createConnection({
|
||||
|
|
@ -504,7 +520,7 @@ export function useConnections() {
|
|||
authUrl = `${apiBaseUrl}${authUrl}`;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
return await new Promise<void>((resolve, reject) => {
|
||||
const popup = window.open(
|
||||
authUrl,
|
||||
'msft-connection',
|
||||
|
|
@ -512,6 +528,7 @@ export function useConnections() {
|
|||
);
|
||||
|
||||
if (!popup) {
|
||||
setIsConnecting(false);
|
||||
reject(new Error('Popup was blocked. Please allow popups and try again.'));
|
||||
return;
|
||||
}
|
||||
|
|
@ -521,6 +538,7 @@ export function useConnections() {
|
|||
if (popup.closed) {
|
||||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
setIsConnecting(false);
|
||||
console.log('Microsoft OAuth popup closed');
|
||||
// Refresh connections in case it succeeded
|
||||
fetchConnections();
|
||||
|
|
@ -540,6 +558,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
console.log('Microsoft connection successful');
|
||||
// Refresh connections
|
||||
fetchConnections();
|
||||
|
|
@ -548,6 +567,7 @@ export function useConnections() {
|
|||
clearInterval(checkClosed);
|
||||
window.removeEventListener('message', messageListener);
|
||||
popup.close();
|
||||
setIsConnecting(false);
|
||||
reject(new Error(event.data.error || 'Microsoft connection failed'));
|
||||
}
|
||||
};
|
||||
|
|
@ -555,6 +575,7 @@ export function useConnections() {
|
|||
window.addEventListener('message', messageListener);
|
||||
});
|
||||
} catch (error) {
|
||||
setIsConnecting(false);
|
||||
console.error('Error creating Microsoft connection:', error);
|
||||
throw error;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,12 +97,15 @@ export const ConnectionsPage: React.FC = () => {
|
|||
// Handle edit submit
|
||||
const handleEditSubmit = async (data: Partial<Connection>) => {
|
||||
if (!editingConnection) return;
|
||||
// Note: updateConnection is handled through the hook
|
||||
try {
|
||||
// Ensure authority is properly typed - filter and validate authority value
|
||||
const updateData: Partial<import('../../api/connectionApi').Connection> = { ...data };
|
||||
|
||||
// Validate and set authority if present
|
||||
|
||||
// Strip computed/read-only fields the backend cannot write.
|
||||
delete (updateData as any).connectionReference;
|
||||
delete (updateData as any).displayLabel;
|
||||
delete (updateData as any).tokenStatus;
|
||||
delete (updateData as any).tokenExpiresAt;
|
||||
|
||||
if (data.authority) {
|
||||
if (
|
||||
data.authority === 'local' ||
|
||||
|
|
@ -112,7 +115,6 @@ export const ConnectionsPage: React.FC = () => {
|
|||
) {
|
||||
updateData.authority = data.authority;
|
||||
} else {
|
||||
// Remove invalid authority value
|
||||
delete (updateData as any).authority;
|
||||
}
|
||||
}
|
||||
|
|
@ -173,8 +175,10 @@ export const ConnectionsPage: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// Handle create Google connection
|
||||
// Guards prevent double-trigger while the OAuth popup is open, which would
|
||||
// otherwise create additional orphan PENDING connections on every click.
|
||||
const handleCreateGoogle = async () => {
|
||||
if (isConnecting) return;
|
||||
try {
|
||||
await createGoogleConnectionAndAuth();
|
||||
refetch();
|
||||
|
|
@ -183,8 +187,8 @@ export const ConnectionsPage: React.FC = () => {
|
|||
}
|
||||
};
|
||||
|
||||
// Handle create Microsoft connection
|
||||
const handleCreateMicrosoft = async () => {
|
||||
if (isConnecting) return;
|
||||
try {
|
||||
await createMicrosoftConnectionAndAuth();
|
||||
refetch();
|
||||
|
|
@ -194,6 +198,7 @@ export const ConnectionsPage: React.FC = () => {
|
|||
};
|
||||
|
||||
const handleCreateClickup = async () => {
|
||||
if (isConnecting) return;
|
||||
try {
|
||||
await createClickupConnectionAndAuth();
|
||||
refetch();
|
||||
|
|
@ -222,7 +227,12 @@ export const ConnectionsPage: React.FC = () => {
|
|||
|
||||
// Form attributes for edit modal
|
||||
const formAttributes = useMemo(() => {
|
||||
const excludedFields = ['id', 'mandateId', 'userId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt', 'connectedAt', 'lastChecked'];
|
||||
const excludedFields = [
|
||||
'id', 'mandateId', 'userId', 'sysCreatedBy', 'sysCreatedAt', 'sysModifiedAt',
|
||||
'connectedAt', 'lastChecked',
|
||||
// computed/read-only fields the backend rejects on write
|
||||
'connectionReference', 'displayLabel', 'tokenStatus', 'tokenExpiresAt',
|
||||
];
|
||||
return (attributes || [])
|
||||
.filter(attr => !excludedFields.includes(attr.name));
|
||||
}, [attributes]);
|
||||
|
|
@ -255,7 +265,7 @@ export const ConnectionsPage: React.FC = () => {
|
|||
className={styles.secondaryButton}
|
||||
onClick={handleAdminConsent}
|
||||
disabled={adminConsentPending}
|
||||
title={t('Microsoft Admin-Zustimmung erteilt der')}
|
||||
title={t('Microsoft Admin-Zustimmung für die gesamte Organisation erteilen')}
|
||||
>
|
||||
<FaShieldAlt /> {t('Admin-Zustimmung')}
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Reference in a new issue