Merge pull request #62 from valueonag/feat/demo-system-readieness
Feat/demo system readieness
This commit is contained in:
commit
3f80d6d434
4 changed files with 124 additions and 9 deletions
|
|
@ -7,7 +7,7 @@ import { ApiRequestOptions } from '../hooks/useApi';
|
|||
export interface Connection {
|
||||
id: string;
|
||||
userId: string;
|
||||
authority: 'local' | 'google' | 'msft' | 'clickup';
|
||||
authority: 'local' | 'google' | 'msft' | 'clickup' | 'infomaniak';
|
||||
externalId: string;
|
||||
externalUsername: string;
|
||||
externalEmail?: string;
|
||||
|
|
@ -52,7 +52,7 @@ export interface PaginatedResponse<T> {
|
|||
export interface CreateConnectionData {
|
||||
id?: string;
|
||||
userId?: string;
|
||||
authority?: 'msft' | 'google' | 'clickup';
|
||||
authority?: 'msft' | 'google' | 'clickup' | 'infomaniak';
|
||||
type?: 'msft' | 'google' | 'clickup'; // Backend maps type → authority
|
||||
externalId?: string;
|
||||
externalUsername?: string;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ const _AUTHORITY_ICONS: Record<string, string> = {
|
|||
msft: '\uD83D\uDFE6',
|
||||
google: '\uD83D\uDFE9',
|
||||
clickup: '\uD83D\uDCCB',
|
||||
infomaniak: '\uD83D\uDFE5',
|
||||
'local:ftp': '\uD83D\uDD17',
|
||||
'local:jira': '\uD83D\uDD27',
|
||||
};
|
||||
|
|
@ -138,6 +139,9 @@ const _SERVICE_ICONS: Record<string, string> = {
|
|||
drive: '\uD83D\uDCC2',
|
||||
gmail: '\uD83D\uDCE8',
|
||||
files: '\uD83D\uDCC2',
|
||||
clickup: '\uD83D\uDCCB',
|
||||
kdrive: '\uD83D\uDCC2',
|
||||
mail: '\uD83D\uDCE7',
|
||||
};
|
||||
|
||||
/* ─── Source colors & icons ──────────────────────────────────────────── */
|
||||
|
|
@ -158,6 +162,10 @@ const _SOURCE_COLORS: Record<string, string> = {
|
|||
'local:ftp': '#795548',
|
||||
'local:jira': '#0052CC',
|
||||
clickup: '#7b68ee',
|
||||
kdriveFolder: '#0098FF',
|
||||
kdrive: '#0098FF',
|
||||
mailFolder: '#0098FF',
|
||||
mail: '#0098FF',
|
||||
};
|
||||
|
||||
function _getSourceColor(sourceType: string): string {
|
||||
|
|
@ -188,6 +196,9 @@ const _SERVICE_TO_SOURCE_TYPE: Record<string, string> = {
|
|||
drive: 'googleDriveFolder',
|
||||
gmail: 'gmailFolder',
|
||||
files: 'ftpFolder',
|
||||
clickup: 'clickup',
|
||||
kdrive: 'kdriveFolder',
|
||||
mail: 'mailFolder',
|
||||
};
|
||||
|
||||
/* ─── Tree helpers ───────────────────────────────────────────────────── */
|
||||
|
|
|
|||
|
|
@ -295,7 +295,8 @@ export function useConnections() {
|
|||
if (
|
||||
event.data.type === 'msft_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
|
||||
clearInterval(checkClosed);
|
||||
|
|
@ -309,7 +310,8 @@ export function useConnections() {
|
|||
} else if (
|
||||
event.data.type === 'msft_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
|
||||
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
|
||||
const createMicrosoftConnectionAndAuth = async (): Promise<void> => {
|
||||
if (isConnecting) return;
|
||||
|
|
@ -701,6 +781,7 @@ export function useConnections() {
|
|||
createGoogleConnectionAndAuth,
|
||||
createMicrosoftConnectionAndAuth,
|
||||
createClickupConnectionAndAuth,
|
||||
createInfomaniakConnectionAndAuth,
|
||||
isLoading,
|
||||
loading: isLoading, // Alias for FormGenerator compatibility
|
||||
isConnecting,
|
||||
|
|
@ -785,7 +866,8 @@ export function useOAuthConnect() {
|
|||
if (
|
||||
event.data.type === 'msft_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
|
||||
clearInterval(checkClosed);
|
||||
|
|
@ -799,7 +881,8 @@ export function useOAuthConnect() {
|
|||
} else if (
|
||||
event.data.type === 'msft_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
|
||||
clearInterval(checkClosed);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import React, { useState, useMemo, useEffect } from 'react';
|
|||
import { useConnections, type Connection } from '../../hooks/useConnections';
|
||||
import { FormGeneratorTable } from '../../components/FormGenerator/FormGeneratorTable';
|
||||
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 styles from '../admin/Admin.module.css';
|
||||
|
||||
|
|
@ -35,6 +35,7 @@ export const ConnectionsPage: React.FC = () => {
|
|||
createGoogleConnectionAndAuth,
|
||||
createMicrosoftConnectionAndAuth,
|
||||
createClickupConnectionAndAuth,
|
||||
createInfomaniakConnectionAndAuth,
|
||||
connectWithPopup,
|
||||
refreshMicrosoftToken,
|
||||
refreshGoogleToken,
|
||||
|
|
@ -106,7 +107,8 @@ export const ConnectionsPage: React.FC = () => {
|
|||
data.authority === 'local' ||
|
||||
data.authority === 'google' ||
|
||||
data.authority === 'msft' ||
|
||||
data.authority === 'clickup'
|
||||
data.authority === 'clickup' ||
|
||||
data.authority === 'infomaniak'
|
||||
) {
|
||||
updateData.authority = data.authority;
|
||||
} 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
|
||||
const handleAdminConsent = () => {
|
||||
setAdminConsentPending(true);
|
||||
|
|
@ -252,7 +264,7 @@ export const ConnectionsPage: React.FC = () => {
|
|||
<div>
|
||||
<h1 className={styles.pageTitle}>{t('Verbindungen')}</h1>
|
||||
<p className={styles.pageSubtitle}>
|
||||
{t('Persönliche Datenanbindungen verwalten (OAuth: Google, Microsoft, ClickUp)')}
|
||||
{t('Persönliche Datenanbindungen verwalten (OAuth: Google, Microsoft, ClickUp, Infomaniak)')}
|
||||
</p>
|
||||
</div>
|
||||
<div className={styles.headerActions}>
|
||||
|
|
@ -296,6 +308,15 @@ export const ConnectionsPage: React.FC = () => {
|
|||
>
|
||||
<FaTasks /> ClickUp
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.secondaryButton}
|
||||
onClick={handleCreateInfomaniak}
|
||||
disabled={isConnecting}
|
||||
title={t('Infomaniak-Konto verbinden (kDrive + Mail)')}
|
||||
>
|
||||
<FaCloud /> Infomaniak
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue