(lint) fe

This commit is contained in:
ManishMadan2882
2025-10-02 16:30:08 +05:30
parent 80aaecb5f0
commit c4a54a85be
31 changed files with 787 additions and 561 deletions

View File

@@ -2,8 +2,11 @@ import React, { useState, useEffect } from 'react';
import useDrivePicker from 'react-google-drive-picker';
import ConnectorAuth from './ConnectorAuth';
import { getSessionToken, setSessionToken, removeSessionToken } from '../utils/providerUtils';
import {
getSessionToken,
setSessionToken,
removeSessionToken,
} from '../utils/providerUtils';
interface PickerFile {
id: string;
@@ -31,9 +34,9 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const [authError, setAuthError] = useState<string>('');
const [accessToken, setAccessToken] = useState<string | null>(null);
const [isValidating, setIsValidating] = useState(false);
const [openPicker] = useDrivePicker();
useEffect(() => {
const sessionToken = getSessionToken('google_drive');
if (sessionToken) {
@@ -46,14 +49,20 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const validateSession = async (sessionToken: string) => {
try {
const apiHost = import.meta.env.VITE_API_HOST;
const validateResponse = await fetch(`${apiHost}/api/connectors/validate-session`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
const validateResponse = await fetch(
`${apiHost}/api/connectors/validate-session`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
provider: 'google_drive',
session_token: sessionToken,
}),
},
body: JSON.stringify({ provider: 'google_drive', session_token: sessionToken })
});
);
if (!validateResponse.ok) {
setIsConnected(false);
@@ -72,7 +81,10 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
return true;
} else {
setIsConnected(false);
setAuthError(validateData.error || 'Session expired. Please reconnect your account.');
setAuthError(
validateData.error ||
'Session expired. Please reconnect your account.',
);
setIsValidating(false);
return false;
}
@@ -87,21 +99,23 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const handleOpenPicker = async () => {
setIsLoading(true);
const sessionToken = getSessionToken('google_drive');
if (!sessionToken) {
setAuthError('No valid session found. Please reconnect to Google Drive.');
setIsLoading(false);
return;
}
if (!accessToken) {
setAuthError('No access token available. Please reconnect to Google Drive.');
setAuthError(
'No access token available. Please reconnect to Google Drive.',
);
setIsLoading(false);
return;
}
try {
const clientId: string = import.meta.env.VITE_GOOGLE_CLIENT_ID;
@@ -117,17 +131,18 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
openPicker({
clientId: clientId,
developerKey: "",
developerKey: '',
appId: appId,
setSelectFolderEnabled: false,
viewId: "DOCS",
viewId: 'DOCS',
showUploadView: false,
showUploadFolders: false,
supportDrives: false,
multiselect: true,
token: accessToken,
viewMimeTypes: 'application/vnd.google-apps.document,application/vnd.google-apps.presentation,application/vnd.google-apps.spreadsheet,application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.ms-powerpoint,application/vnd.ms-excel,text/plain,text/csv,text/html,text/markdown,text/x-rst,application/json,application/epub+zip,application/rtf,image/jpeg,image/jpg,image/png',
callbackFunction: (data:any) => {
viewMimeTypes:
'application/vnd.google-apps.document,application/vnd.google-apps.presentation,application/vnd.google-apps.spreadsheet,application/pdf,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.openxmlformats-officedocument.presentationml.presentation,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/msword,application/vnd.ms-powerpoint,application/vnd.ms-excel,text/plain,text/csv,text/html,text/markdown,text/x-rst,application/json,application/epub+zip,application/rtf,image/jpeg,image/jpg,image/png',
callbackFunction: (data: any) => {
setIsLoading(false);
if (data.action === 'picked') {
const docs = data.docs;
@@ -136,14 +151,14 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const newFolders: PickerFile[] = [];
docs.forEach((doc: any) => {
const item = {
id: doc.id,
name: doc.name,
mimeType: doc.mimeType,
iconUrl: doc.iconUrl || '',
description: doc.description,
sizeBytes: doc.sizeBytes
};
const item = {
id: doc.id,
name: doc.name,
mimeType: doc.mimeType,
iconUrl: doc.iconUrl || '',
description: doc.description,
sizeBytes: doc.sizeBytes,
};
if (doc.mimeType === 'application/vnd.google-apps.folder') {
newFolders.push(item);
@@ -152,20 +167,26 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
}
});
setSelectedFiles(prevFiles => {
const existingFileIds = new Set(prevFiles.map(file => file.id));
const uniqueNewFiles = newFiles.filter(file => !existingFileIds.has(file.id));
setSelectedFiles((prevFiles) => {
const existingFileIds = new Set(prevFiles.map((file) => file.id));
const uniqueNewFiles = newFiles.filter(
(file) => !existingFileIds.has(file.id),
);
return [...prevFiles, ...uniqueNewFiles];
});
setSelectedFolders(prevFolders => {
const existingFolderIds = new Set(prevFolders.map(folder => folder.id));
const uniqueNewFolders = newFolders.filter(folder => !existingFolderIds.has(folder.id));
setSelectedFolders((prevFolders) => {
const existingFolderIds = new Set(
prevFolders.map((folder) => folder.id),
);
const uniqueNewFolders = newFolders.filter(
(folder) => !existingFolderIds.has(folder.id),
);
return [...prevFolders, ...uniqueNewFolders];
});
onSelectionChange(
[...selectedFiles, ...newFiles].map(file => file.id),
[...selectedFolders, ...newFolders].map(folder => folder.id)
[...selectedFiles, ...newFiles].map((file) => file.id),
[...selectedFolders, ...newFolders].map((folder) => folder.id),
);
}
},
@@ -186,9 +207,12 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ provider: 'google_drive', session_token: sessionToken })
body: JSON.stringify({
provider: 'google_drive',
session_token: sessionToken,
}),
});
} catch (err) {
console.error('Error disconnecting from Google Drive:', err);
@@ -207,24 +231,24 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
const ConnectedStateSkeleton = () => (
<div className="mb-4">
<div className="w-full flex items-center justify-between rounded-[10px] bg-gray-200 dark:bg-gray-700 px-4 py-2 animate-pulse">
<div className="flex w-full animate-pulse items-center justify-between rounded-[10px] bg-gray-200 px-4 py-2 dark:bg-gray-700">
<div className="flex items-center gap-2">
<div className="h-4 w-4 bg-gray-300 dark:bg-gray-600 rounded"></div>
<div className="h-4 w-32 bg-gray-300 dark:bg-gray-600 rounded"></div>
<div className="h-4 w-4 rounded bg-gray-300 dark:bg-gray-600"></div>
<div className="h-4 w-32 rounded bg-gray-300 dark:bg-gray-600"></div>
</div>
<div className="h-4 w-16 bg-gray-300 dark:bg-gray-600 rounded"></div>
<div className="h-4 w-16 rounded bg-gray-300 dark:bg-gray-600"></div>
</div>
</div>
);
const FilesSectionSkeleton = () => (
<div className="border border-[#EEE6FF78] rounded-lg dark:border-[#6A6A6A]">
<div className="rounded-lg border border-[#EEE6FF78] dark:border-[#6A6A6A]">
<div className="p-4">
<div className="flex justify-between items-center mb-4">
<div className="h-5 w-24 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
<div className="h-8 w-24 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
<div className="mb-4 flex items-center justify-between">
<div className="h-5 w-24 animate-pulse rounded bg-gray-200 dark:bg-gray-700"></div>
<div className="h-8 w-24 animate-pulse rounded bg-gray-200 dark:bg-gray-700"></div>
</div>
<div className="h-4 w-40 bg-gray-200 dark:bg-gray-700 rounded animate-pulse"></div>
<div className="h-4 w-40 animate-pulse rounded bg-gray-200 dark:bg-gray-700"></div>
</div>
</div>
);
@@ -262,13 +286,13 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
/>
{isConnected && (
<div className="border border-[#EEE6FF78] rounded-lg dark:border-[#6A6A6A]">
<div className="rounded-lg border border-[#EEE6FF78] dark:border-[#6A6A6A]">
<div className="p-4">
<div className="flex justify-between items-center mb-4">
<div className="mb-4 flex items-center justify-between">
<h3 className="text-sm font-medium">Selected Files</h3>
<button
onClick={() => handleOpenPicker()}
className="bg-[#A076F6] hover:bg-[#8A5FD4] text-white text-sm py-1 px-3 rounded-md"
className="rounded-md bg-[#A076F6] px-3 py-1 text-sm text-white hover:bg-[#8A5FD4]"
disabled={isLoading}
>
{isLoading ? 'Loading...' : 'Select Files'}
@@ -276,26 +300,42 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
</div>
{selectedFiles.length === 0 && selectedFolders.length === 0 ? (
<p className="text-gray-600 dark:text-gray-400 text-sm">No files or folders selected</p>
<p className="text-sm text-gray-600 dark:text-gray-400">
No files or folders selected
</p>
) : (
<div className="max-h-60 overflow-y-auto">
{selectedFolders.length > 0 && (
<div className="mb-2">
<h4 className="text-xs font-medium text-gray-500 mb-1">Folders</h4>
<h4 className="mb-1 text-xs font-medium text-gray-500">
Folders
</h4>
{selectedFolders.map((folder) => (
<div key={folder.id} className="flex items-center p-2 border-b border-gray-200 dark:border-gray-700">
<img src={folder.iconUrl} alt="Folder" className="w-5 h-5 mr-2" />
<span className="text-sm truncate flex-1">{folder.name}</span>
<div
key={folder.id}
className="flex items-center border-b border-gray-200 p-2 dark:border-gray-700"
>
<img
src={folder.iconUrl}
alt="Folder"
className="mr-2 h-5 w-5"
/>
<span className="flex-1 truncate text-sm">
{folder.name}
</span>
<button
onClick={() => {
const newSelectedFolders = selectedFolders.filter(f => f.id !== folder.id);
const newSelectedFolders =
selectedFolders.filter(
(f) => f.id !== folder.id,
);
setSelectedFolders(newSelectedFolders);
onSelectionChange(
selectedFiles.map(f => f.id),
newSelectedFolders.map(f => f.id)
selectedFiles.map((f) => f.id),
newSelectedFolders.map((f) => f.id),
);
}}
className="text-red-500 hover:text-red-700 text-sm ml-2"
className="ml-2 text-sm text-red-500 hover:text-red-700"
>
Remove
</button>
@@ -306,21 +346,34 @@ const GoogleDrivePicker: React.FC<GoogleDrivePickerProps> = ({
{selectedFiles.length > 0 && (
<div>
<h4 className="text-xs font-medium text-gray-500 mb-1">Files</h4>
<h4 className="mb-1 text-xs font-medium text-gray-500">
Files
</h4>
{selectedFiles.map((file) => (
<div key={file.id} className="flex items-center p-2 border-b border-gray-200 dark:border-gray-700">
<img src={file.iconUrl} alt="File" className="w-5 h-5 mr-2" />
<span className="text-sm truncate flex-1">{file.name}</span>
<div
key={file.id}
className="flex items-center border-b border-gray-200 p-2 dark:border-gray-700"
>
<img
src={file.iconUrl}
alt="File"
className="mr-2 h-5 w-5"
/>
<span className="flex-1 truncate text-sm">
{file.name}
</span>
<button
onClick={() => {
const newSelectedFiles = selectedFiles.filter(f => f.id !== file.id);
const newSelectedFiles = selectedFiles.filter(
(f) => f.id !== file.id,
);
setSelectedFiles(newSelectedFiles);
onSelectionChange(
newSelectedFiles.map(f => f.id),
selectedFolders.map(f => f.id)
newSelectedFiles.map((f) => f.id),
selectedFolders.map((f) => f.id),
);
}}
className="text-red-500 hover:text-red-700 text-sm ml-2"
className="ml-2 text-sm text-red-500 hover:text-red-700"
>
Remove
</button>