mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-10 20:35:17 +02:00
chore: ran frontend and backend linting
This commit is contained in:
parent
ab63b23f0a
commit
b9dc785a1c
9 changed files with 52 additions and 50 deletions
|
|
@ -19,7 +19,7 @@ from alembic import context, op
|
|||
|
||||
# Get Electric SQL user credentials from env.py configuration
|
||||
_config = context.config
|
||||
ELECTRIC_DB_USER =_config.get_main_option("electric_db_user", "electric")
|
||||
ELECTRIC_DB_USER = _config.get_main_option("electric_db_user", "electric")
|
||||
ELECTRIC_DB_PASSWORD = _config.get_main_option(
|
||||
"electric_db_password", "electric_password"
|
||||
)
|
||||
|
|
@ -52,10 +52,18 @@ def upgrade() -> None:
|
|||
)
|
||||
|
||||
# Create indexes (using IF NOT EXISTS for idempotency)
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_notifications_user_id ON notifications (user_id);")
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_notifications_read ON notifications (read);")
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_notifications_created_at ON notifications (created_at);")
|
||||
op.execute("CREATE INDEX IF NOT EXISTS ix_notifications_user_read ON notifications (user_id, read);")
|
||||
op.execute(
|
||||
"CREATE INDEX IF NOT EXISTS ix_notifications_user_id ON notifications (user_id);"
|
||||
)
|
||||
op.execute(
|
||||
"CREATE INDEX IF NOT EXISTS ix_notifications_read ON notifications (read);"
|
||||
)
|
||||
op.execute(
|
||||
"CREATE INDEX IF NOT EXISTS ix_notifications_created_at ON notifications (created_at);"
|
||||
)
|
||||
op.execute(
|
||||
"CREATE INDEX IF NOT EXISTS ix_notifications_user_read ON notifications (user_id, read);"
|
||||
)
|
||||
|
||||
# =====================================================
|
||||
# Electric SQL Setup - User and Publication
|
||||
|
|
|
|||
|
|
@ -438,9 +438,7 @@ export default function EditorPage() {
|
|||
{saving ? (
|
||||
<>
|
||||
<Loader2 className="h-3.5 w-3.5 md:h-4 md:w-4 animate-spin" />
|
||||
<span className="text-xs md:text-sm">
|
||||
{isNewNote ? "Creating" : "Saving"}
|
||||
</span>
|
||||
<span className="text-xs md:text-sm">{isNewNote ? "Creating" : "Saving"}</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@ import { useParams } from "next/navigation";
|
|||
export function NotificationButton() {
|
||||
const { data: user } = useAtomValue(currentUserAtom);
|
||||
const params = useParams();
|
||||
|
||||
|
||||
const userId = user?.id ? String(user.id) : null;
|
||||
// Get searchSpaceId from URL params - the component is rendered within /dashboard/[search_space_id]/
|
||||
const searchSpaceId = params?.search_space_id
|
||||
? Number(params.search_space_id)
|
||||
: null;
|
||||
|
||||
const { notifications, unreadCount, loading, markAsRead, markAllAsRead } =
|
||||
useNotifications(userId, searchSpaceId);
|
||||
const searchSpaceId = params?.search_space_id ? Number(params.search_space_id) : null;
|
||||
|
||||
const { notifications, unreadCount, loading, markAsRead, markAllAsRead } = useNotifications(
|
||||
userId,
|
||||
searchSpaceId
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ interface ElectricProviderProps {
|
|||
export function ElectricProvider({ children }: ElectricProviderProps) {
|
||||
const [electricClient, setElectricClient] = useState<ElectricClient | null>(null);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const { data: user, isSuccess: isUserLoaded, isError: isUserError } = useAtomValue(currentUserAtom);
|
||||
const {
|
||||
data: user,
|
||||
isSuccess: isUserLoaded,
|
||||
isError: isUserError,
|
||||
} = useAtomValue(currentUserAtom);
|
||||
const previousUserIdRef = useRef<string | null>(null);
|
||||
const initializingRef = useRef(false);
|
||||
|
||||
|
|
@ -104,11 +108,7 @@ export function ElectricProvider({ children }: ElectricProviderProps) {
|
|||
// For non-authenticated pages (like landing page), render immediately with null context
|
||||
// Also render immediately if user query failed (e.g., token expired)
|
||||
if (!isUserLoaded || !user?.id || isUserError) {
|
||||
return (
|
||||
<ElectricContext.Provider value={null}>
|
||||
{children}
|
||||
</ElectricContext.Provider>
|
||||
);
|
||||
return <ElectricContext.Provider value={null}>{children}</ElectricContext.Provider>;
|
||||
}
|
||||
|
||||
// Show loading state while initializing for authenticated users
|
||||
|
|
@ -128,9 +128,5 @@ export function ElectricProvider({ children }: ElectricProviderProps) {
|
|||
}
|
||||
|
||||
// Provide the Electric client to children
|
||||
return (
|
||||
<ElectricContext.Provider value={electricClient}>
|
||||
{children}
|
||||
</ElectricContext.Provider>
|
||||
);
|
||||
return <ElectricContext.Provider value={electricClient}>{children}</ElectricContext.Provider>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import type { SearchSourceConnector } from "@/contracts/types/connector.types";
|
|||
|
||||
/**
|
||||
* Hook for managing connectors with Electric SQL real-time sync
|
||||
*
|
||||
*
|
||||
* Uses the Electric client from context (provided by ElectricProvider)
|
||||
* instead of initializing its own - prevents race conditions and memory leaks
|
||||
*/
|
||||
export function useConnectorsElectric(searchSpaceId: number | string | null) {
|
||||
// Get Electric client from context - ElectricProvider handles initialization
|
||||
const electricClient = useElectricClient();
|
||||
|
||||
|
||||
const [connectors, setConnectors] = useState<SearchSourceConnector[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
|
@ -173,7 +173,7 @@ export function useConnectorsElectric(searchSpaceId: number | string | null) {
|
|||
return () => {
|
||||
mounted = false;
|
||||
syncKeyRef.current = null;
|
||||
|
||||
|
||||
if (syncHandleRef.current) {
|
||||
syncHandleRef.current.unsubscribe();
|
||||
syncHandleRef.current = null;
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@ interface Document {
|
|||
|
||||
/**
|
||||
* Hook for managing documents with Electric SQL real-time sync
|
||||
*
|
||||
*
|
||||
* Uses the Electric client from context (provided by ElectricProvider)
|
||||
* instead of initializing its own - prevents race conditions and memory leaks
|
||||
*/
|
||||
export function useDocumentsElectric(searchSpaceId: number | string | null) {
|
||||
// Get Electric client from context - ElectricProvider handles initialization
|
||||
const electricClient = useElectricClient();
|
||||
|
||||
|
||||
const [documents, setDocuments] = useState<Document[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
|
|
@ -169,7 +169,7 @@ export function useDocumentsElectric(searchSpaceId: number | string | null) {
|
|||
return () => {
|
||||
mounted = false;
|
||||
syncKeyRef.current = null;
|
||||
|
||||
|
||||
if (syncHandleRef.current) {
|
||||
syncHandleRef.current.unsubscribe();
|
||||
syncHandleRef.current = null;
|
||||
|
|
|
|||
|
|
@ -10,29 +10,29 @@ export type { Notification } from "@/contracts/types/notification.types";
|
|||
|
||||
/**
|
||||
* Hook for managing notifications with Electric SQL real-time sync
|
||||
*
|
||||
*
|
||||
* Uses the Electric client from context (provided by ElectricProvider)
|
||||
* instead of initializing its own - prevents race conditions and memory leaks
|
||||
*
|
||||
*
|
||||
* Architecture:
|
||||
* - User-level sync: Syncs ALL notifications for a user (runs once per user)
|
||||
* - Search-space-level query: Filters notifications by searchSpaceId (updates on search space change)
|
||||
*
|
||||
*
|
||||
* This separation ensures smooth transitions when switching search spaces (no flash).
|
||||
*
|
||||
*
|
||||
* @param userId - The user ID to fetch notifications for
|
||||
* @param searchSpaceId - The search space ID to filter notifications (null shows global notifications only)
|
||||
*/
|
||||
export function useNotifications(userId: string | null, searchSpaceId: number | null) {
|
||||
// Get Electric client from context - ElectricProvider handles initialization
|
||||
const electricClient = useElectricClient();
|
||||
|
||||
|
||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const syncHandleRef = useRef<SyncHandle | null>(null);
|
||||
const liveQueryRef = useRef<{ unsubscribe: () => void } | null>(null);
|
||||
|
||||
|
||||
// Track user-level sync key to prevent duplicate sync subscriptions
|
||||
const userSyncKeyRef = useRef<string | null>(null);
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ export function useNotifications(userId: string | null, searchSpaceId: number |
|
|||
return () => {
|
||||
mounted = false;
|
||||
userSyncKeyRef.current = null;
|
||||
|
||||
|
||||
if (syncHandleRef.current) {
|
||||
syncHandleRef.current.unsubscribe();
|
||||
syncHandleRef.current = null;
|
||||
|
|
@ -135,7 +135,7 @@ export function useNotifications(userId: string | null, searchSpaceId: number |
|
|||
ORDER BY created_at DESC`,
|
||||
[userId, searchSpaceId]
|
||||
);
|
||||
|
||||
|
||||
if (mounted) {
|
||||
setNotifications(result.rows || []);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,7 +381,10 @@ export async function initElectric(userId: string): Promise<ElectricClient> {
|
|||
},
|
||||
};
|
||||
|
||||
console.log("[Electric] syncShapeToTable config:", JSON.stringify(shapeConfig, null, 2));
|
||||
console.log(
|
||||
"[Electric] syncShapeToTable config:",
|
||||
JSON.stringify(shapeConfig, null, 2)
|
||||
);
|
||||
|
||||
// Type assertion to PGlite with electric extension
|
||||
const pgWithElectric = db as PGlite & {
|
||||
|
|
@ -452,9 +455,7 @@ export async function initElectric(userId: string): Promise<ElectricClient> {
|
|||
(typeof msg === "object" && "up-to-date" in msg)
|
||||
) {
|
||||
if (!syncResolved) {
|
||||
console.log(
|
||||
`[Electric] ✅ Received up-to-date message for ${table}`
|
||||
);
|
||||
console.log(`[Electric] ✅ Received up-to-date message for ${table}`);
|
||||
resolveInitialSync();
|
||||
}
|
||||
// Continue listening for real-time updates - don't return!
|
||||
|
|
@ -477,9 +478,7 @@ export async function initElectric(userId: string): Promise<ElectricClient> {
|
|||
|
||||
// Also check stream's isUpToDate property immediately
|
||||
if (stream?.isUpToDate) {
|
||||
console.log(
|
||||
`[Electric] ✅ Stream isUpToDate is true immediately for ${table}`
|
||||
);
|
||||
console.log(`[Electric] ✅ Stream isUpToDate is true immediately for ${table}`);
|
||||
resolveInitialSync();
|
||||
}
|
||||
}
|
||||
|
|
@ -530,7 +529,9 @@ export async function initElectric(userId: string): Promise<ElectricClient> {
|
|||
|
||||
// Cache the sync handle for reuse (memory optimization)
|
||||
activeSyncHandles.set(cacheKey, syncHandle);
|
||||
console.log(`[Electric] Cached sync handle for: ${cacheKey} (total cached: ${activeSyncHandles.size})`);
|
||||
console.log(
|
||||
`[Electric] Cached sync handle for: ${cacheKey} (total cached: ${activeSyncHandles.size})`
|
||||
);
|
||||
|
||||
return syncHandle;
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import type { ElectricClient } from "./client";
|
|||
|
||||
/**
|
||||
* Context for sharing the Electric SQL client across the app
|
||||
*
|
||||
*
|
||||
* This ensures:
|
||||
* 1. Single initialization point (ElectricProvider only)
|
||||
* 2. No race conditions (hooks wait for context)
|
||||
|
|
@ -34,4 +34,3 @@ export function useElectricClientOrThrow(): ElectricClient {
|
|||
}
|
||||
return client;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue