AI platform insights monitoring and website analysis monitoring services added
This commit is contained in:
86
frontend/src/api/platformInsightsMonitoring.ts
Normal file
86
frontend/src/api/platformInsightsMonitoring.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Platform Insights Monitoring API Client
|
||||
* Provides typed functions for fetching platform insights (GSC/Bing) monitoring data.
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
|
||||
// TypeScript interfaces
|
||||
export interface PlatformInsightsTask {
|
||||
id: number;
|
||||
platform: 'gsc' | 'bing';
|
||||
site_url: string | null;
|
||||
status: 'active' | 'failed' | 'paused';
|
||||
last_check: string | null;
|
||||
last_success: string | null;
|
||||
last_failure: string | null;
|
||||
failure_reason: string | null;
|
||||
next_check: string | null;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface PlatformInsightsStatusResponse {
|
||||
success: boolean;
|
||||
user_id: string;
|
||||
gsc_tasks: PlatformInsightsTask[];
|
||||
bing_tasks: PlatformInsightsTask[];
|
||||
total_tasks: number;
|
||||
}
|
||||
|
||||
export interface PlatformInsightsExecutionLog {
|
||||
id: number;
|
||||
task_id: number;
|
||||
execution_date: string;
|
||||
status: 'success' | 'failed' | 'running' | 'skipped';
|
||||
result_data: any;
|
||||
error_message: string | null;
|
||||
execution_time_ms: number | null;
|
||||
data_source: 'cached' | 'api' | 'onboarding' | 'storage' | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface PlatformInsightsLogsResponse {
|
||||
success: boolean;
|
||||
logs: PlatformInsightsExecutionLog[];
|
||||
total_count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get platform insights status for a user
|
||||
*/
|
||||
export const getPlatformInsightsStatus = async (
|
||||
userId: string
|
||||
): Promise<PlatformInsightsStatusResponse> => {
|
||||
try {
|
||||
const response = await apiClient.get(`/api/scheduler/platform-insights/status/${userId}`);
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching platform insights status:', error);
|
||||
throw new Error(error.response?.data?.detail || 'Failed to fetch platform insights status');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get execution logs for platform insights tasks
|
||||
*/
|
||||
export const getPlatformInsightsLogs = async (
|
||||
userId: string,
|
||||
limit: number = 10,
|
||||
taskId?: number
|
||||
): Promise<PlatformInsightsLogsResponse> => {
|
||||
try {
|
||||
const params: any = { limit };
|
||||
if (taskId) {
|
||||
params.task_id = taskId;
|
||||
}
|
||||
const response = await apiClient.get(`/api/scheduler/platform-insights/logs/${userId}`, {
|
||||
params
|
||||
});
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching platform insights logs:', error);
|
||||
throw new Error(error.response?.data?.detail || 'Failed to fetch platform insights logs');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,8 +9,10 @@ import { apiClient } from './client';
|
||||
export interface ProviderAvailability {
|
||||
google_available: boolean;
|
||||
exa_available: boolean;
|
||||
tavily_available: boolean;
|
||||
gemini_key_status: 'configured' | 'missing';
|
||||
exa_key_status: 'configured' | 'missing';
|
||||
tavily_key_status: 'configured' | 'missing';
|
||||
}
|
||||
|
||||
export interface PersonaDefaults {
|
||||
@@ -140,18 +142,85 @@ export const getResearchConfig = async (): Promise<ResearchConfigResponse> => {
|
||||
|
||||
/**
|
||||
* Get or refresh research persona
|
||||
* @param forceRefresh - If true, regenerate persona even if cache is valid
|
||||
* @param forceRefresh - If true, regenerate persona even if cache is valid
|
||||
*/
|
||||
export const refreshResearchPersona = async (forceRefresh: boolean = false): Promise<ResearchPersona> => {
|
||||
export const refreshResearchPersona = async (forceRefresh: boolean = false): Promise<ResearchPersona> => {
|
||||
try {
|
||||
const url = `/api/research/research-persona${forceRefresh ? '?force_refresh=true' : ''}`;
|
||||
const url = `/api/research/research-persona${forceRefresh ? '?force_refresh=true' : ''}`;
|
||||
const response = await apiClient.get(url);
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('[researchConfig] Error refreshing research persona:', error?.response?.status || error?.message);
|
||||
// Preserve the original error so subscription errors can be detected
|
||||
// The apiClient interceptor should handle 429 errors, but we preserve the error structure
|
||||
console.error('[researchConfig] Error refreshing research persona:', error?.response?.status || error?.message);
|
||||
// Preserve the original error so subscription errors can be detected
|
||||
// The apiClient interceptor should handle 429 errors, but we preserve the error structure
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Competitor Analysis Response Interface
|
||||
*/
|
||||
export interface CompetitorAnalysisResponse {
|
||||
success: boolean;
|
||||
competitors?: Array<{
|
||||
name?: string;
|
||||
url?: string;
|
||||
domain?: string;
|
||||
description?: string;
|
||||
similarity_score?: number;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
social_media_accounts?: Record<string, string>;
|
||||
social_media_citations?: Array<{
|
||||
platform?: string;
|
||||
account?: string;
|
||||
url?: string;
|
||||
[key: string]: any;
|
||||
}>;
|
||||
research_summary?: {
|
||||
total_competitors?: number;
|
||||
industry_insights?: string;
|
||||
[key: string]: any;
|
||||
};
|
||||
analysis_timestamp?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get competitor analysis data from onboarding
|
||||
*/
|
||||
export const getCompetitorAnalysis = async (): Promise<CompetitorAnalysisResponse> => {
|
||||
console.log('[getCompetitorAnalysis] ===== START: Fetching competitor analysis =====');
|
||||
try {
|
||||
console.log('[getCompetitorAnalysis] Making GET request to /api/research/competitor-analysis');
|
||||
const response = await apiClient.get('/api/research/competitor-analysis');
|
||||
console.log('[getCompetitorAnalysis] ✅ Response received:', {
|
||||
success: response.data?.success,
|
||||
competitorsCount: response.data?.competitors?.length || 0,
|
||||
error: response.data?.error,
|
||||
fullResponse: response.data
|
||||
});
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
const statusCode = error?.response?.status;
|
||||
const errorMessage = error?.response?.data?.detail || error?.response?.data?.error || error?.message || 'Unknown error';
|
||||
|
||||
console.error('[getCompetitorAnalysis] ❌ ERROR:', {
|
||||
status: statusCode,
|
||||
message: errorMessage,
|
||||
fullError: error,
|
||||
responseData: error?.response?.data
|
||||
});
|
||||
|
||||
// Return error response instead of throwing
|
||||
const errorResponse = {
|
||||
success: false,
|
||||
error: errorMessage
|
||||
};
|
||||
console.log('[getCompetitorAnalysis] Returning error response:', errorResponse);
|
||||
return errorResponse;
|
||||
} finally {
|
||||
console.log('[getCompetitorAnalysis] ===== END: Fetching competitor analysis =====');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -38,10 +38,14 @@ export interface SchedulerJob {
|
||||
job_store: string;
|
||||
user_job_store: string;
|
||||
function_name?: string | null;
|
||||
platform?: string; // For OAuth token monitoring tasks
|
||||
task_id?: number; // For OAuth token monitoring tasks
|
||||
platform?: string; // For OAuth token monitoring tasks and platform insights
|
||||
task_id?: number; // For OAuth token monitoring tasks, website analysis, and platform insights
|
||||
is_database_task?: boolean; // Flag to indicate DB task vs APScheduler job
|
||||
frequency?: string; // For OAuth tasks (e.g., 'Weekly')
|
||||
task_type?: string; // For website analysis tasks ('user_website' or 'competitor')
|
||||
task_category?: string; // 'website_analysis', 'platform_insights', 'oauth_token_monitoring'
|
||||
website_url?: string | null; // For website analysis tasks
|
||||
competitor_id?: number | null; // For competitor website analysis tasks
|
||||
}
|
||||
|
||||
export interface UserIsolation {
|
||||
@@ -128,6 +132,11 @@ export interface SchedulerEventHistoryResponse {
|
||||
limit: number;
|
||||
offset: number;
|
||||
has_more: boolean;
|
||||
date_filter?: {
|
||||
days: number;
|
||||
cutoff_date: string;
|
||||
showing_events_since: string;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,17 +208,19 @@ export const getSchedulerJobs = async (): Promise<SchedulerJobsResponse> => {
|
||||
/**
|
||||
* Get scheduler event history from database.
|
||||
*
|
||||
* @param limit - Number of events to return (1-1000, default: 100)
|
||||
* @param limit - Number of events to return (1-500, default: 5 for initial load, expand to 50 on hover)
|
||||
* @param offset - Pagination offset (default: 0)
|
||||
* @param eventType - Filter by event type (check_cycle, interval_adjustment, start, stop, etc.)
|
||||
* @param days - Number of days to look back (1-90, default: 7 days)
|
||||
*/
|
||||
export const getSchedulerEventHistory = async (
|
||||
limit: number = 100,
|
||||
limit: number = 5,
|
||||
offset: number = 0,
|
||||
eventType?: 'check_cycle' | 'interval_adjustment' | 'start' | 'stop' | 'job_scheduled' | 'job_cancelled' | 'job_completed' | 'job_failed'
|
||||
eventType?: 'check_cycle' | 'interval_adjustment' | 'start' | 'stop' | 'job_scheduled' | 'job_cancelled' | 'job_completed' | 'job_failed',
|
||||
days: number = 7
|
||||
): Promise<SchedulerEventHistoryResponse> => {
|
||||
try {
|
||||
const params: any = { limit, offset };
|
||||
const params: any = { limit, offset, days };
|
||||
if (eventType) {
|
||||
params.event_type = eventType;
|
||||
}
|
||||
|
||||
122
frontend/src/api/websiteAnalysisMonitoring.ts
Normal file
122
frontend/src/api/websiteAnalysisMonitoring.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Website Analysis Monitoring API Client
|
||||
* Provides typed functions for fetching website analysis monitoring data.
|
||||
*/
|
||||
|
||||
import { apiClient } from './client';
|
||||
|
||||
// TypeScript interfaces
|
||||
export interface WebsiteAnalysisTask {
|
||||
id: number;
|
||||
website_url: string;
|
||||
task_type: 'user_website' | 'competitor';
|
||||
competitor_id: string | null;
|
||||
status: 'active' | 'failed' | 'paused';
|
||||
last_check: string | null;
|
||||
last_success: string | null;
|
||||
last_failure: string | null;
|
||||
failure_reason: string | null;
|
||||
next_check: string | null;
|
||||
frequency_days: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface WebsiteAnalysisStatusResponse {
|
||||
success: boolean;
|
||||
data: {
|
||||
user_id: string;
|
||||
user_website_tasks: WebsiteAnalysisTask[];
|
||||
competitor_tasks: WebsiteAnalysisTask[];
|
||||
total_tasks: number;
|
||||
active_tasks: number;
|
||||
failed_tasks: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface WebsiteAnalysisExecutionLog {
|
||||
id: number;
|
||||
task_id: number;
|
||||
website_url: string;
|
||||
task_type: 'user_website' | 'competitor';
|
||||
execution_date: string;
|
||||
status: 'success' | 'failed' | 'running' | 'skipped';
|
||||
result_data: any;
|
||||
error_message: string | null;
|
||||
execution_time_ms: number | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface WebsiteAnalysisLogsResponse {
|
||||
logs: WebsiteAnalysisExecutionLog[];
|
||||
total_count: number;
|
||||
limit: number;
|
||||
offset: number;
|
||||
has_more: boolean;
|
||||
}
|
||||
|
||||
export interface RetryWebsiteAnalysisResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
task: {
|
||||
id: number;
|
||||
website_url: string;
|
||||
status: string;
|
||||
next_check: string | null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get website analysis status for a user
|
||||
*/
|
||||
export const getWebsiteAnalysisStatus = async (
|
||||
userId: string
|
||||
): Promise<WebsiteAnalysisStatusResponse> => {
|
||||
try {
|
||||
const response = await apiClient.get(`/api/scheduler/website-analysis/status/${userId}`);
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching website analysis status:', error);
|
||||
throw new Error(error.response?.data?.detail || 'Failed to fetch website analysis status');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get execution logs for website analysis tasks
|
||||
*/
|
||||
export const getWebsiteAnalysisLogs = async (
|
||||
userId: string,
|
||||
limit: number = 10,
|
||||
offset: number = 0,
|
||||
taskId?: number
|
||||
): Promise<WebsiteAnalysisLogsResponse> => {
|
||||
try {
|
||||
const params: any = { limit, offset };
|
||||
if (taskId) {
|
||||
params.task_id = taskId;
|
||||
}
|
||||
const response = await apiClient.get(`/api/scheduler/website-analysis/logs/${userId}`, {
|
||||
params
|
||||
});
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('Error fetching website analysis logs:', error);
|
||||
throw new Error(error.response?.data?.detail || 'Failed to fetch website analysis logs');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Manually retry a failed website analysis task
|
||||
*/
|
||||
export const retryWebsiteAnalysis = async (
|
||||
taskId: number
|
||||
): Promise<RetryWebsiteAnalysisResponse> => {
|
||||
try {
|
||||
const response = await apiClient.post(`/api/scheduler/website-analysis/retry/${taskId}`);
|
||||
return response.data;
|
||||
} catch (error: any) {
|
||||
console.error('Error retrying website analysis:', error);
|
||||
throw new Error(error.response?.data?.detail || 'Failed to retry website analysis');
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user