added infomaniak
This commit is contained in:
parent
974c48e24d
commit
3016806db9
4 changed files with 124 additions and 9 deletions
|
|
@ -7,7 +7,7 @@ import { ApiRequestOptions } from '../hooks/useApi';
|
||||||
export interface Connection {
|
export interface Connection {
|
||||||
id: string;
|
id: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
authority: 'local' | 'google' | 'msft' | 'clickup';
|
authority: 'local' | 'google' | 'msft' | 'clickup' | 'infomaniak';
|
||||||
externalId: string;
|
externalId: string;
|
||||||
externalUsername: string;
|
externalUsername: string;
|
||||||
externalEmail?: string;
|
externalEmail?: string;
|
||||||
|
|
@ -52,7 +52,7 @@ export interface PaginatedResponse<T> {
|
||||||
export interface CreateConnectionData {
|
export interface CreateConnectionData {
|
||||||
id?: string;
|
id?: string;
|
||||||
userId?: string;
|
userId?: string;
|
||||||
authority?: 'msft' | 'google' | 'clickup';
|
authority?: 'msft' | 'google' | 'clickup' | 'infomaniak';
|
||||||
type?: 'msft' | 'google' | 'clickup'; // Backend maps type → authority
|
type?: 'msft' | 'google' | 'clickup'; // Backend maps type → authority
|
||||||
externalId?: string;
|
externalId?: string;
|
||||||
externalUsername?: string;
|
externalUsername?: string;
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,7 @@ const _AUTHORITY_ICONS: Record<string, string> = {
|
||||||
msft: '\uD83D\uDFE6',
|
msft: '\uD83D\uDFE6',
|
||||||
google: '\uD83D\uDFE9',
|
google: '\uD83D\uDFE9',
|
||||||
clickup: '\uD83D\uDCCB',
|
clickup: '\uD83D\uDCCB',
|
||||||
|
infomaniak: '\uD83D\uDFE5',
|
||||||
'local:ftp': '\uD83D\uDD17',
|
'local:ftp': '\uD83D\uDD17',
|
||||||
'local:jira': '\uD83D\uDD27',
|
'local:jira': '\uD83D\uDD27',
|
||||||
};
|
};
|
||||||
|
|
@ -138,6 +139,9 @@ const _SERVICE_ICONS: Record<string, string> = {
|
||||||
drive: '\uD83D\uDCC2',
|
drive: '\uD83D\uDCC2',
|
||||||
gmail: '\uD83D\uDCE8',
|
gmail: '\uD83D\uDCE8',
|
||||||
files: '\uD83D\uDCC2',
|
files: '\uD83D\uDCC2',
|
||||||
|
clickup: '\uD83D\uDCCB',
|
||||||
|
kdrive: '\uD83D\uDCC2',
|
||||||
|
mail: '\uD83D\uDCE7',
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ─── Source colors & icons ──────────────────────────────────────────── */
|
/* ─── Source colors & icons ──────────────────────────────────────────── */
|
||||||
|
|
@ -158,6 +162,10 @@ const _SOURCE_COLORS: Record<string, string> = {
|
||||||
'local:ftp': '#795548',
|
'local:ftp': '#795548',
|
||||||
'local:jira': '#0052CC',
|
'local:jira': '#0052CC',
|
||||||
clickup: '#7b68ee',
|
clickup: '#7b68ee',
|
||||||
|
kdriveFolder: '#0098FF',
|
||||||
|
kdrive: '#0098FF',
|
||||||
|
mailFolder: '#0098FF',
|
||||||
|
mail: '#0098FF',
|
||||||
};
|
};
|
||||||
|
|
||||||
function _getSourceColor(sourceType: string): string {
|
function _getSourceColor(sourceType: string): string {
|
||||||
|
|
@ -188,6 +196,9 @@ const _SERVICE_TO_SOURCE_TYPE: Record<string, string> = {
|
||||||
drive: 'googleDriveFolder',
|
drive: 'googleDriveFolder',
|
||||||
gmail: 'gmailFolder',
|
gmail: 'gmailFolder',
|
||||||
files: 'ftpFolder',
|
files: 'ftpFolder',
|
||||||
|
clickup: 'clickup',
|
||||||
|
kdrive: 'kdriveFolder',
|
||||||
|
mail: 'mailFolder',
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ─── Tree helpers ───────────────────────────────────────────────────── */
|
/* ─── Tree helpers ───────────────────────────────────────────────────── */
|
||||||
|
|
|
||||||
|
|
@ -295,7 +295,8 @@ export function useConnections() {
|
||||||
if (
|
if (
|
||||||
event.data.type === 'msft_connection_success' ||
|
event.data.type === 'msft_connection_success' ||
|
||||||
event.data.type === 'google_connection_success' ||
|
event.data.type === 'google_connection_success' ||
|
||||||
event.data.type === 'clickup_connection_success'
|
event.data.type === 'clickup_connection_success' ||
|
||||||
|
event.data.type === 'infomaniak_connection_success'
|
||||||
) {
|
) {
|
||||||
// Clean up
|
// Clean up
|
||||||
clearInterval(checkClosed);
|
clearInterval(checkClosed);
|
||||||
|
|
@ -309,7 +310,8 @@ export function useConnections() {
|
||||||
} else if (
|
} else if (
|
||||||
event.data.type === 'msft_connection_error' ||
|
event.data.type === 'msft_connection_error' ||
|
||||||
event.data.type === 'google_connection_error' ||
|
event.data.type === 'google_connection_error' ||
|
||||||
event.data.type === 'clickup_connection_error'
|
event.data.type === 'clickup_connection_error' ||
|
||||||
|
event.data.type === 'infomaniak_connection_error'
|
||||||
) {
|
) {
|
||||||
// Handle error
|
// Handle error
|
||||||
clearInterval(checkClosed);
|
clearInterval(checkClosed);
|
||||||
|
|
@ -495,6 +497,84 @@ export function useConnections() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create Infomaniak connection and open OAuth popup
|
||||||
|
const createInfomaniakConnectionAndAuth = async (): Promise<void> => {
|
||||||
|
if (isConnecting) return;
|
||||||
|
setIsConnecting(true);
|
||||||
|
try {
|
||||||
|
const newConnection = await createConnection({
|
||||||
|
type: 'infomaniak',
|
||||||
|
authority: 'infomaniak',
|
||||||
|
});
|
||||||
|
|
||||||
|
const connectResponse = await connectServiceApi(request, newConnection.id);
|
||||||
|
|
||||||
|
if (!connectResponse.authUrl) {
|
||||||
|
throw new Error('No OAuth URL received from backend');
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiBaseUrl = getApiBaseUrl();
|
||||||
|
let authUrl = connectResponse.authUrl;
|
||||||
|
if (authUrl.startsWith('/')) {
|
||||||
|
authUrl = `${apiBaseUrl}${authUrl}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await new Promise<void>((resolve, reject) => {
|
||||||
|
const popup = window.open(
|
||||||
|
authUrl,
|
||||||
|
'infomaniak-connection',
|
||||||
|
'width=500,height=600,scrollbars=yes,resizable=yes'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!popup) {
|
||||||
|
setIsConnecting(false);
|
||||||
|
reject(new Error('Popup was blocked. Please allow popups and try again.'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const checkClosed = setInterval(() => {
|
||||||
|
if (popup.closed) {
|
||||||
|
clearInterval(checkClosed);
|
||||||
|
window.removeEventListener('message', messageListener);
|
||||||
|
setIsConnecting(false);
|
||||||
|
console.log('Infomaniak OAuth popup closed');
|
||||||
|
fetchConnections();
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
const messageListener = (event: MessageEvent) => {
|
||||||
|
const apiUrl = new URL(apiBaseUrl);
|
||||||
|
if (event.origin !== apiUrl.origin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.data.type === 'infomaniak_connection_success') {
|
||||||
|
clearInterval(checkClosed);
|
||||||
|
window.removeEventListener('message', messageListener);
|
||||||
|
popup.close();
|
||||||
|
setIsConnecting(false);
|
||||||
|
console.log('Infomaniak connection successful');
|
||||||
|
fetchConnections();
|
||||||
|
resolve();
|
||||||
|
} else if (event.data.type === 'infomaniak_connection_error') {
|
||||||
|
clearInterval(checkClosed);
|
||||||
|
window.removeEventListener('message', messageListener);
|
||||||
|
popup.close();
|
||||||
|
setIsConnecting(false);
|
||||||
|
reject(new Error(event.data.error || 'Infomaniak connection failed'));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('message', messageListener);
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
setIsConnecting(false);
|
||||||
|
console.error('Error creating Infomaniak connection:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Create Microsoft connection and open OAuth popup
|
// Create Microsoft connection and open OAuth popup
|
||||||
const createMicrosoftConnectionAndAuth = async (): Promise<void> => {
|
const createMicrosoftConnectionAndAuth = async (): Promise<void> => {
|
||||||
if (isConnecting) return;
|
if (isConnecting) return;
|
||||||
|
|
@ -701,6 +781,7 @@ export function useConnections() {
|
||||||
createGoogleConnectionAndAuth,
|
createGoogleConnectionAndAuth,
|
||||||
createMicrosoftConnectionAndAuth,
|
createMicrosoftConnectionAndAuth,
|
||||||
createClickupConnectionAndAuth,
|
createClickupConnectionAndAuth,
|
||||||
|
createInfomaniakConnectionAndAuth,
|
||||||
isLoading,
|
isLoading,
|
||||||
loading: isLoading, // Alias for FormGenerator compatibility
|
loading: isLoading, // Alias for FormGenerator compatibility
|
||||||
isConnecting,
|
isConnecting,
|
||||||
|
|
@ -785,7 +866,8 @@ export function useOAuthConnect() {
|
||||||
if (
|
if (
|
||||||
event.data.type === 'msft_connection_success' ||
|
event.data.type === 'msft_connection_success' ||
|
||||||
event.data.type === 'google_connection_success' ||
|
event.data.type === 'google_connection_success' ||
|
||||||
event.data.type === 'clickup_connection_success'
|
event.data.type === 'clickup_connection_success' ||
|
||||||
|
event.data.type === 'infomaniak_connection_success'
|
||||||
) {
|
) {
|
||||||
// Clean up - IMPORTANT: clear the checkClosed interval first
|
// Clean up - IMPORTANT: clear the checkClosed interval first
|
||||||
clearInterval(checkClosed);
|
clearInterval(checkClosed);
|
||||||
|
|
@ -799,7 +881,8 @@ export function useOAuthConnect() {
|
||||||
} else if (
|
} else if (
|
||||||
event.data.type === 'msft_connection_error' ||
|
event.data.type === 'msft_connection_error' ||
|
||||||
event.data.type === 'google_connection_error' ||
|
event.data.type === 'google_connection_error' ||
|
||||||
event.data.type === 'clickup_connection_error'
|
event.data.type === 'clickup_connection_error' ||
|
||||||
|
event.data.type === 'infomaniak_connection_error'
|
||||||
) {
|
) {
|
||||||
// Handle error - also clear the checkClosed interval
|
// Handle error - also clear the checkClosed interval
|
||||||
clearInterval(checkClosed);
|
clearInterval(checkClosed);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import React, { useState, useMemo, useEffect } from 'react';
|
||||||
import { useConnections, type Connection } from '../../hooks/useConnections';
|
import { useConnections, type Connection } from '../../hooks/useConnections';
|
||||||
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
||||||
import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm';
|
import { FormGeneratorForm } from '../../components/FormGenerator/FormGeneratorForm';
|
||||||
import { FaSync, FaGoogle, FaMicrosoft, FaLink, FaRedo, FaShieldAlt, FaTasks } from 'react-icons/fa';
|
import { FaSync, FaGoogle, FaMicrosoft, FaLink, FaRedo, FaShieldAlt, FaTasks, FaCloud } from 'react-icons/fa';
|
||||||
import { getApiBaseUrl } from '../../../config/config';
|
import { getApiBaseUrl } from '../../../config/config';
|
||||||
import styles from '../admin/Admin.module.css';
|
import styles from '../admin/Admin.module.css';
|
||||||
|
|
||||||
|
|
@ -35,6 +35,7 @@ export const ConnectionsPage: React.FC = () => {
|
||||||
createGoogleConnectionAndAuth,
|
createGoogleConnectionAndAuth,
|
||||||
createMicrosoftConnectionAndAuth,
|
createMicrosoftConnectionAndAuth,
|
||||||
createClickupConnectionAndAuth,
|
createClickupConnectionAndAuth,
|
||||||
|
createInfomaniakConnectionAndAuth,
|
||||||
connectWithPopup,
|
connectWithPopup,
|
||||||
refreshMicrosoftToken,
|
refreshMicrosoftToken,
|
||||||
refreshGoogleToken,
|
refreshGoogleToken,
|
||||||
|
|
@ -106,7 +107,8 @@ export const ConnectionsPage: React.FC = () => {
|
||||||
data.authority === 'local' ||
|
data.authority === 'local' ||
|
||||||
data.authority === 'google' ||
|
data.authority === 'google' ||
|
||||||
data.authority === 'msft' ||
|
data.authority === 'msft' ||
|
||||||
data.authority === 'clickup'
|
data.authority === 'clickup' ||
|
||||||
|
data.authority === 'infomaniak'
|
||||||
) {
|
) {
|
||||||
updateData.authority = data.authority;
|
updateData.authority = data.authority;
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -202,6 +204,16 @@ export const ConnectionsPage: React.FC = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCreateInfomaniak = async () => {
|
||||||
|
if (isConnecting) return;
|
||||||
|
try {
|
||||||
|
await createInfomaniakConnectionAndAuth();
|
||||||
|
refetch();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error creating Infomaniak connection:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Open Microsoft Admin Consent flow in a popup
|
// Open Microsoft Admin Consent flow in a popup
|
||||||
const handleAdminConsent = () => {
|
const handleAdminConsent = () => {
|
||||||
setAdminConsentPending(true);
|
setAdminConsentPending(true);
|
||||||
|
|
@ -252,7 +264,7 @@ export const ConnectionsPage: React.FC = () => {
|
||||||
<div>
|
<div>
|
||||||
<h1 className={styles.pageTitle}>{t('Verbindungen')}</h1>
|
<h1 className={styles.pageTitle}>{t('Verbindungen')}</h1>
|
||||||
<p className={styles.pageSubtitle}>
|
<p className={styles.pageSubtitle}>
|
||||||
{t('Persönliche Datenanbindungen verwalten (OAuth: Google, Microsoft, ClickUp)')}
|
{t('Persönliche Datenanbindungen verwalten (OAuth: Google, Microsoft, ClickUp, Infomaniak)')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.headerActions}>
|
<div className={styles.headerActions}>
|
||||||
|
|
@ -296,6 +308,15 @@ export const ConnectionsPage: React.FC = () => {
|
||||||
>
|
>
|
||||||
<FaTasks /> ClickUp
|
<FaTasks /> ClickUp
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className={styles.secondaryButton}
|
||||||
|
onClick={handleCreateInfomaniak}
|
||||||
|
disabled={isConnecting}
|
||||||
|
title={t('Infomaniak-Konto verbinden (kDrive + Mail)')}
|
||||||
|
>
|
||||||
|
<FaCloud /> Infomaniak
|
||||||
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue