hotfixes
This commit is contained in:
parent
b2c38e75bf
commit
71666d2891
6 changed files with 72 additions and 31 deletions
|
|
@ -193,29 +193,31 @@ export async function updateConnection(
|
|||
|
||||
/**
|
||||
* Refresh Microsoft token
|
||||
* Endpoint: POST /api/connections/{connectionId}/refresh-microsoft-token
|
||||
* Endpoint: POST /api/msft/refresh
|
||||
*/
|
||||
export async function refreshMicrosoftToken(
|
||||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<Connection> {
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/refresh-microsoft-token`,
|
||||
method: 'post'
|
||||
url: '/api/msft/refresh',
|
||||
method: 'post',
|
||||
data: { connectionId }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh Google token
|
||||
* Endpoint: POST /api/connections/{connectionId}/refresh-google-token
|
||||
* Endpoint: POST /api/google/refresh
|
||||
*/
|
||||
export async function refreshGoogleToken(
|
||||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<Connection> {
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/refresh-google-token`,
|
||||
method: 'post'
|
||||
url: '/api/google/refresh',
|
||||
method: 'post',
|
||||
data: { connectionId }
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import React from 'react';
|
||||
import { useLanguage } from '../../../providers/language/LanguageContext';
|
||||
import styles from './FormGeneratorControls.module.css';
|
||||
import { Button } from '../../UiComponents/Button';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { useCallback } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import { GenericPageData } from '../../pageInterface';
|
||||
import { FaGoogle, FaMicrosoft, FaLink } from 'react-icons/fa';
|
||||
import { FaGoogle, FaMicrosoft, FaLink, FaSync, FaPlug } from 'react-icons/fa';
|
||||
import { useConnections } from '../../../../hooks/useConnections';
|
||||
|
||||
// Helper function to convert attribute definitions to column config
|
||||
|
|
@ -29,6 +29,8 @@ const createConnectionsHook = () => {
|
|||
createGoogleConnectionAndAuth,
|
||||
createMicrosoftConnectionAndAuth,
|
||||
connectWithPopup,
|
||||
refreshMicrosoftToken,
|
||||
refreshGoogleToken,
|
||||
isConnecting,
|
||||
isLoading,
|
||||
error,
|
||||
|
|
@ -92,9 +94,13 @@ const createConnectionsHook = () => {
|
|||
connectWithPopup,
|
||||
createGoogleConnectionAndAuth,
|
||||
createMicrosoftConnectionAndAuth,
|
||||
// Token refresh operations
|
||||
refreshMicrosoftToken,
|
||||
refreshGoogleToken,
|
||||
// Loading states
|
||||
isConnecting,
|
||||
deletingConnections: new Set(), // Placeholder for consistency with other pages
|
||||
refreshingConnections: new Set<string>(), // Track which connections are refreshing
|
||||
// Attributes and permissions for dynamic column/button generation
|
||||
attributes,
|
||||
permissions,
|
||||
|
|
@ -192,28 +198,14 @@ export const connectionsPageData: GenericPageData = {
|
|||
tableConfig: {
|
||||
hookFactory: createConnectionsHook,
|
||||
// Columns are generated dynamically from attributes via hookData.columns
|
||||
// Standard action buttons
|
||||
actionButtons: [
|
||||
{
|
||||
type: 'connect',
|
||||
title: 'connections.action.connect',
|
||||
idField: 'id',
|
||||
statusField: 'status',
|
||||
operationName: 'connectWithPopup',
|
||||
loadingStateName: 'isConnecting',
|
||||
// Only show if user has update permission (connect = update operation)
|
||||
disabled: (hookData: any) => {
|
||||
if (!hookData?.permissions) return { disabled: false };
|
||||
const hasUpdate = hookData.permissions.update !== 'n' && hookData.permissions.view;
|
||||
return { disabled: !hasUpdate, message: 'No permission to connect' };
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'delete',
|
||||
title: 'connections.action.delete',
|
||||
idField: 'id',
|
||||
operationName: 'handleDelete',
|
||||
loadingStateName: 'deletingConnections',
|
||||
// Only show if user has delete permission
|
||||
disabled: (hookData: any) => {
|
||||
if (!hookData?.permissions) return { disabled: false };
|
||||
const hasDelete = hookData.permissions.delete !== 'n' && hookData.permissions.view;
|
||||
|
|
@ -221,6 +213,50 @@ export const connectionsPageData: GenericPageData = {
|
|||
}
|
||||
}
|
||||
],
|
||||
// Custom action buttons (entity-specific)
|
||||
customActions: [
|
||||
{
|
||||
id: 'connect',
|
||||
icon: React.createElement(FaPlug),
|
||||
title: 'connections.action.connect',
|
||||
onClick: async (row: any, hookData: any) => {
|
||||
if (hookData?.connectWithPopup) {
|
||||
await hookData.connectWithPopup(row.id);
|
||||
}
|
||||
},
|
||||
// Only show connect button if status is not 'active'
|
||||
visible: (row: any) => row.status !== 'active',
|
||||
disabled: (_row: any, hookData: any) => {
|
||||
if (!hookData?.permissions) return { disabled: false, message: '' };
|
||||
const hasUpdate = hookData.permissions.update !== 'n' && hookData.permissions.view;
|
||||
return { disabled: !hasUpdate, message: 'No permission to connect' };
|
||||
},
|
||||
loading: (_row: any, hookData: any) => hookData?.isConnecting || false
|
||||
},
|
||||
{
|
||||
id: 'refresh',
|
||||
icon: React.createElement(FaSync),
|
||||
title: 'connections.action.refresh',
|
||||
onClick: async (row: any, hookData: any) => {
|
||||
// Determine which refresh function to use based on authority
|
||||
if (row.authority === 'msft' && hookData?.refreshMicrosoftToken) {
|
||||
await hookData.refreshMicrosoftToken(row.id);
|
||||
if (hookData?.refetch) await hookData.refetch();
|
||||
} else if (row.authority === 'google' && hookData?.refreshGoogleToken) {
|
||||
await hookData.refreshGoogleToken(row.id);
|
||||
if (hookData?.refetch) await hookData.refetch();
|
||||
}
|
||||
},
|
||||
// Only show refresh button if status is 'active' (already connected)
|
||||
visible: (row: any) => row.status === 'active',
|
||||
disabled: (_row: any, hookData: any) => {
|
||||
if (!hookData?.permissions) return { disabled: false, message: '' };
|
||||
const hasUpdate = hookData.permissions.update !== 'n' && hookData.permissions.view;
|
||||
return { disabled: !hasUpdate, message: 'No permission to refresh token' };
|
||||
},
|
||||
loading: (row: any, hookData: any) => hookData?.refreshingConnections?.has(row.id) || false
|
||||
}
|
||||
],
|
||||
searchable: true,
|
||||
filterable: true,
|
||||
sortable: true,
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ export const filesPageData: GenericPageData = {
|
|||
await hookData.handleDownload(row.id, row.fileName, row.mimeType);
|
||||
}
|
||||
},
|
||||
disabled: (row: any, hookData: any) => {
|
||||
disabled: (_row: any, hookData: any) => {
|
||||
if (!hookData?.permissions) return { disabled: false, message: '' };
|
||||
const hasRead = hookData.permissions.read !== 'n' && hookData.permissions.view;
|
||||
return { disabled: !hasRead, message: 'No permission to download files' };
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export type PrivilegeChecker = () => boolean | Promise<boolean>;
|
|||
export interface ButtonFormField {
|
||||
key: string;
|
||||
label: string | LanguageText;
|
||||
type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'readonly' | 'multiselect';
|
||||
type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'readonly' | 'multiselect' | 'number';
|
||||
required?: boolean;
|
||||
placeholder?: string | LanguageText;
|
||||
minRows?: number;
|
||||
|
|
@ -17,6 +17,7 @@ export interface ButtonFormField {
|
|||
validator?: (value: any) => string | null;
|
||||
defaultValue?: any;
|
||||
options?: string[] | Array<{ value: string | number; label: string }>; // For enum/multiselect fields
|
||||
optionsReference?: string; // Reference to a data source for dynamic options (e.g., 'TrusteeOrganisation', 'User')
|
||||
}
|
||||
|
||||
// Dropdown configuration for header dropdown buttons
|
||||
|
|
@ -262,22 +263,26 @@ export interface GenericDataHook {
|
|||
[key: string]: any; // Allow additional properties for dynamic data sources
|
||||
}
|
||||
|
||||
// Standard action button configuration (built-in actions: edit, delete, view, copy)
|
||||
// Standard action button configuration (built-in actions: edit, delete, view, copy, connect, play)
|
||||
export interface ActionButtonConfig {
|
||||
type: 'view' | 'edit' | 'delete' | 'copy';
|
||||
type: 'view' | 'edit' | 'delete' | 'copy' | 'connect' | 'play';
|
||||
onAction?: (row: any) => Promise<void> | void; // Optional for delete buttons since they handle their own logic
|
||||
title?: string | LanguageText;
|
||||
disabled?: (row: any) => boolean | { disabled: boolean; message?: string };
|
||||
loading?: (row: any) => boolean;
|
||||
disabled?: (row: any, hookData?: any) => boolean | { disabled: boolean; message?: string };
|
||||
loading?: (row: any, hookData?: any) => boolean;
|
||||
// Field mappings for flexible data access
|
||||
idField?: string; // Field name for the unique identifier (default: 'id')
|
||||
nameField?: string; // Field name for display name (default: 'name' or 'file_name')
|
||||
typeField?: string; // Field name for type/mime type (default: 'type' or 'mime_type')
|
||||
contentField?: string; // Field name for content (default: 'content')
|
||||
statusField?: string; // Field name for status (used by connect action)
|
||||
// Operation and loading state names
|
||||
operationName?: string; // Name of the operation function in hookData
|
||||
loadingStateName?: string; // Name of the loading state in hookData
|
||||
fetchItemFunctionName?: string; // Name of the function in hookData to fetch a single item by ID (for edit button)
|
||||
// Navigation and mode (for play action)
|
||||
navigateTo?: string; // Path to navigate to after action
|
||||
mode?: string; // Mode to set (e.g., 'prompt', 'workflow')
|
||||
}
|
||||
|
||||
// Custom action button configuration (for entity-specific actions like download, connect, play, sendPasswordLink)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useApiRequest } from './useApi';
|
||||
import { getUserDataCache } from '../utils/userCache';
|
||||
import api from '../api';
|
||||
import { usePermissions, type UserPermissions } from './usePermissions';
|
||||
import {
|
||||
|
|
|
|||
Loading…
Reference in a new issue