feat: OCI Services page, compliance report v3, DOCX with camo strip, timezone per-user
- New OCI Services page with Service Status (auto-detect + overrides) and OCI Health (real-time Oracle status) tabs - Compliance report: OCI Services section with Cloud Guard recommendations table, back page with Connect with us - DOCX generation: professional styling with Pillow camouflage strip, green header tables, result boxes - Separate Download DOCX button in reports page - Timezone now per-user (not global) — each user configures their own timezone - ADB connection pre-check before report generation (fail fast 503) - Compliance report iframe shows friendly HTML instead of JSON 404 during generation - OCI Health dashboard: proxies ocistatus.oraclecloud.com with search, geo filters, expandable region cards
This commit is contained in:
@@ -69,4 +69,13 @@ export const adminApi = {
|
||||
qs.set('limit', String(params.limit ?? 50));
|
||||
return client.get(`/chat-logs?${qs}`) as unknown as Promise<ChatLogEntry[]>;
|
||||
},
|
||||
|
||||
getMyTimezone: () =>
|
||||
client.get('/users/me/timezone') as unknown as Promise<{ timezone: string }>,
|
||||
|
||||
setMyTimezone: (timezone: string) =>
|
||||
client.put('/users/me/timezone', { timezone }) as unknown as Promise<{ ok: boolean; timezone: string }>,
|
||||
|
||||
getTimezoneOptions: () =>
|
||||
client.get('/settings/timezone/options') as unknown as Promise<{ timezones: string[] }>,
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface User {
|
||||
last_name?: string;
|
||||
email?: string;
|
||||
mfa_enabled?: boolean;
|
||||
timezone?: string;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
|
||||
@@ -5,6 +5,7 @@ import client from '../client';
|
||||
export interface Report {
|
||||
id: string;
|
||||
tenancy_name: string;
|
||||
config_id?: string;
|
||||
status: string;
|
||||
level: number | null;
|
||||
regions?: string[];
|
||||
@@ -74,6 +75,37 @@ export interface CisEngineUpdate {
|
||||
update_available: boolean;
|
||||
}
|
||||
|
||||
export interface OciServiceStatus {
|
||||
service: string;
|
||||
auto_status?: string;
|
||||
auto_description?: string;
|
||||
status: string;
|
||||
description: string;
|
||||
overridden: boolean;
|
||||
}
|
||||
|
||||
export interface OciHealthService {
|
||||
serviceId: string;
|
||||
serviceName: string;
|
||||
serviceCanonicalName: string;
|
||||
serviceCategoryName: string;
|
||||
serviceStatus: string;
|
||||
incidents: { incidentId: string; title: string; status: string }[];
|
||||
}
|
||||
|
||||
export interface OciHealthRegion {
|
||||
regionId: string;
|
||||
regionName: string;
|
||||
regionCanonicalName: string;
|
||||
geographicAreaName: string;
|
||||
serviceHealthReports: OciHealthService[];
|
||||
}
|
||||
|
||||
export interface OciHealthResponse {
|
||||
realm?: string;
|
||||
regionHealthReports: OciHealthRegion[];
|
||||
}
|
||||
|
||||
/* ── API ── */
|
||||
|
||||
export const reportsApi = {
|
||||
@@ -95,9 +127,9 @@ export const reportsApi = {
|
||||
summary: (rid: string) =>
|
||||
client.get(`/reports/${rid}/summary`) as unknown as Promise<ReportSummary>,
|
||||
|
||||
htmlUrl: (rid: string) => `/api/reports/${rid}/html`,
|
||||
htmlUrl: (rid: string) => `/api/reports/${rid}/html?_t=${Date.now()}`,
|
||||
|
||||
complianceReportUrl: (rid: string) => `/api/reports/${rid}/compliance-report`,
|
||||
complianceReportUrl: (rid: string) => `/api/reports/${rid}/compliance-report?_t=${Date.now()}`,
|
||||
|
||||
generateComplianceReport: (rid: string) =>
|
||||
client.post(`/reports/${rid}/compliance-report/generate`) as unknown as Promise<{ status: string; has_rag: boolean }>,
|
||||
@@ -110,6 +142,11 @@ export const reportsApi = {
|
||||
return `/api/reports/${rid}/compliance-report/download?token=${encodeURIComponent(token)}`;
|
||||
},
|
||||
|
||||
complianceReportDocxUrl: (rid: string) => {
|
||||
const token = localStorage.getItem('t') || '';
|
||||
return `/api/reports/${rid}/compliance-report/docx?token=${encodeURIComponent(token)}`;
|
||||
},
|
||||
|
||||
files: (rid: string) =>
|
||||
client.get(`/reports/${rid}/files`) as unknown as Promise<ReportFile[]>,
|
||||
|
||||
@@ -147,4 +184,13 @@ export const reportsApi = {
|
||||
|
||||
embeddingStatus: (taskId: string) =>
|
||||
client.get(`/embeddings/status/${taskId}`) as unknown as Promise<{ status: string; message: string; inserted?: number; total?: number }>,
|
||||
|
||||
getOciServices: (configId: string, detect = true) =>
|
||||
client.get(`/oci-services/${configId}?detect=${detect ? 1 : 0}`) as unknown as Promise<OciServiceStatus[]>,
|
||||
|
||||
setOciServices: (configId: string, services: OciServiceStatus[]) =>
|
||||
client.put(`/oci-services/${configId}`, services) as unknown as Promise<{ ok: boolean }>,
|
||||
|
||||
getOciHealth: () =>
|
||||
client.get('/oci-health') as unknown as Promise<OciHealthResponse>,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user