mirror of
https://github.com/colanode/colanode.git
synced 2025-12-29 00:25:03 +01:00
Include pagination for app queries
This commit is contained in:
@@ -33,20 +33,23 @@ export const App = () => {
|
||||
|
||||
const accountsQuery = useQuery({
|
||||
queryKey: ['accounts'],
|
||||
queryFn: async () => {
|
||||
queryFn: async ({ queryKey }) => {
|
||||
const query = appDatabase.selectFrom('accounts').selectAll().compile();
|
||||
return await window.neuron.executeAppQueryAndSubscribe('accounts', query);
|
||||
return await window.neuron.executeAppQueryAndSubscribe({
|
||||
key: queryKey,
|
||||
query: query,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const workspacesQuery = useQuery({
|
||||
queryKey: ['workspaces'],
|
||||
queryFn: async () => {
|
||||
queryFn: async ({ queryKey }) => {
|
||||
const query = appDatabase.selectFrom('workspaces').selectAll().compile();
|
||||
return await window.neuron.executeAppQueryAndSubscribe(
|
||||
'workspaces',
|
||||
query,
|
||||
);
|
||||
return await window.neuron.executeAppQueryAndSubscribe({
|
||||
key: queryKey,
|
||||
query: query,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
@@ -61,8 +64,8 @@ export const App = () => {
|
||||
value={{
|
||||
database: appDatabase,
|
||||
query: (query) => window.neuron.executeAppQuery(query),
|
||||
queryAndSubscribe: (queryId, query) =>
|
||||
window.neuron.executeAppQueryAndSubscribe(queryId, query),
|
||||
queryAndSubscribe: (context) =>
|
||||
window.neuron.executeAppQueryAndSubscribe(context),
|
||||
mutate: (mutation) => window.neuron.executeAppMutation(mutation),
|
||||
}}
|
||||
>
|
||||
@@ -84,8 +87,8 @@ export const App = () => {
|
||||
value={{
|
||||
database: appDatabase,
|
||||
query: (query) => window.neuron.executeAppQuery(query),
|
||||
queryAndSubscribe: (queryId, query) =>
|
||||
window.neuron.executeAppQueryAndSubscribe(queryId, query),
|
||||
queryAndSubscribe: (context) =>
|
||||
window.neuron.executeAppQueryAndSubscribe(context),
|
||||
mutate: (mutation) => window.neuron.executeAppMutation(mutation),
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -53,10 +53,43 @@ export const Root = () => {
|
||||
const id = eventBus.subscribe((event) => {
|
||||
if (event.event === 'app_query_updated') {
|
||||
const result = event.payload.result;
|
||||
const queryKey = event.payload.queryId;
|
||||
const queryKey = event.payload.key;
|
||||
const page = event.payload.page;
|
||||
|
||||
if (result && queryKey) {
|
||||
queryClient.setQueryData([queryKey], result);
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!queryKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
const existingData = queryClient.getQueryData<any>(queryKey);
|
||||
|
||||
if (!existingData) {
|
||||
window.neuron.unsubscribeAppQuery(queryKey);
|
||||
return;
|
||||
}
|
||||
|
||||
if (page !== undefined && page != null) {
|
||||
const index = existingData.pageParams.indexOf(page);
|
||||
if (index === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
const newData = {
|
||||
pageParams: existingData.pageParams,
|
||||
pages: existingData.pages.map((p: any, i: number) => {
|
||||
if (i === index) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return p;
|
||||
}),
|
||||
};
|
||||
queryClient.setQueryData(queryKey, newData);
|
||||
} else {
|
||||
queryClient.setQueryData(queryKey, result);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -68,8 +101,7 @@ export const Root = () => {
|
||||
event.query.queryKey &&
|
||||
event.query.queryKey.length > 0
|
||||
) {
|
||||
const queryKey = event.query.queryKey[0];
|
||||
await window.neuron.unsubscribeAppQuery(queryKey);
|
||||
await window.neuron.unsubscribeAppQuery(event.query.queryKey);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React from 'react';
|
||||
import { CompiledQuery, Kysely, QueryResult } from 'kysely';
|
||||
import { AppDatabaseSchema } from '@/data/schemas/app';
|
||||
import { SubscribedQueryContext } from '@/types/databases';
|
||||
|
||||
interface AppDatabaseContext {
|
||||
database: Kysely<AppDatabaseSchema>;
|
||||
mutate: (mutation: CompiledQuery) => Promise<void>;
|
||||
query: <R>(query: CompiledQuery<R>) => Promise<QueryResult<R>>;
|
||||
queryAndSubscribe: <R>(
|
||||
queryId: string,
|
||||
query: CompiledQuery<R>,
|
||||
context: SubscribedQueryContext<R>,
|
||||
) => Promise<QueryResult<R>>;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,12 @@ import {
|
||||
resultHasChanged,
|
||||
} from '@/data/utils';
|
||||
import { Workspace } from '@/types/workspaces';
|
||||
import { SubscribedQueryResult } from '@/types/databases';
|
||||
import {
|
||||
SubscribedQueryContext,
|
||||
SubscribedQueryResult,
|
||||
} from '@/types/databases';
|
||||
import { eventBus } from '@/lib/event-bus';
|
||||
import { isEqual } from 'lodash';
|
||||
|
||||
const EVENT_LOOP_INTERVAL = 1000;
|
||||
|
||||
@@ -75,23 +79,20 @@ class AppManager {
|
||||
}
|
||||
|
||||
public async executeQueryAndSubscribe<T>(
|
||||
queryId: string,
|
||||
query: CompiledQuery<T>,
|
||||
context: SubscribedQueryContext<T>,
|
||||
): Promise<QueryResult<T>> {
|
||||
await this.waitForInit();
|
||||
const result = await this.database.executeQuery(query);
|
||||
const result = await this.database.executeQuery(context.query);
|
||||
|
||||
// only mutations should have side effects
|
||||
if (result.numAffectedRows > 0) {
|
||||
throw new Error('Query should not have any side effects');
|
||||
}
|
||||
|
||||
const selectedTables = extractTablesFromSql(query.sql);
|
||||
const queryId = context.key.join('|') + context.page;
|
||||
const selectedTables = extractTablesFromSql(context.query.sql);
|
||||
const subscriberData: SubscribedQueryResult<T> = {
|
||||
context: {
|
||||
query,
|
||||
key: [queryId],
|
||||
},
|
||||
context,
|
||||
tables: selectedTables,
|
||||
result: result,
|
||||
};
|
||||
@@ -145,8 +146,8 @@ class AppManager {
|
||||
}
|
||||
}
|
||||
|
||||
for (const [subscriberId, subscriberData] of this.subscribers) {
|
||||
const hasAffectedTables = subscriberData.tables.some((table) =>
|
||||
for (const subscriber of this.subscribers.values()) {
|
||||
const hasAffectedTables = subscriber.tables.some((table) =>
|
||||
affectedTables.includes(table),
|
||||
);
|
||||
|
||||
@@ -155,14 +156,15 @@ class AppManager {
|
||||
}
|
||||
|
||||
const newResult = await this.database.executeQuery(
|
||||
subscriberData.context.query,
|
||||
subscriber.context.query,
|
||||
);
|
||||
|
||||
if (resultHasChanged(subscriberData.result, newResult)) {
|
||||
if (resultHasChanged(subscriber.result, newResult)) {
|
||||
eventBus.publish({
|
||||
event: 'app_query_updated',
|
||||
payload: {
|
||||
queryId: subscriberId,
|
||||
key: subscriber.context.key,
|
||||
page: subscriber.context.page,
|
||||
result: newResult,
|
||||
},
|
||||
});
|
||||
@@ -170,8 +172,14 @@ class AppManager {
|
||||
}
|
||||
}
|
||||
|
||||
public unsubscribeQuery(queryId: string): void {
|
||||
this.subscribers.delete(queryId);
|
||||
public unsubscribeQuery(queryKey: string[]): void {
|
||||
var queryIds = [...this.subscribers.keys()];
|
||||
for (const queryId of queryIds) {
|
||||
const subscriberData = this.subscribers.get(queryId);
|
||||
if (isEqual(subscriberData.context.key, queryKey)) {
|
||||
this.subscribers.delete(queryId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async logout(accountId: string): Promise<void> {
|
||||
|
||||
@@ -88,15 +88,14 @@ ipcMain.handle(
|
||||
'execute-app-query-and-subscribe',
|
||||
async (
|
||||
_,
|
||||
queryId: string,
|
||||
query: CompiledQuery<unknown>,
|
||||
context: SubscribedQueryContext<unknown>,
|
||||
): Promise<QueryResult<unknown>> => {
|
||||
return await appManager.executeQueryAndSubscribe(queryId, query);
|
||||
return await appManager.executeQueryAndSubscribe(context);
|
||||
},
|
||||
);
|
||||
|
||||
ipcMain.handle('unsubscribe-app-query', (_, queryId: string): void => {
|
||||
appManager.unsubscribeQuery(queryId);
|
||||
ipcMain.handle('unsubscribe-app-query', (_, queryKey: string[]): void => {
|
||||
appManager.unsubscribeQuery(queryKey);
|
||||
});
|
||||
|
||||
ipcMain.handle(
|
||||
|
||||
5
desktop/src/types/window.d.ts
vendored
5
desktop/src/types/window.d.ts
vendored
@@ -9,10 +9,9 @@ interface NeuronApi {
|
||||
executeAppMutation: (mutation: CompiledQuery) => Promise<void>;
|
||||
executeAppQuery: (query: CompiledQuery<R>) => Promise<QueryResult<R>>;
|
||||
executeAppQueryAndSubscribe: (
|
||||
queryId: string,
|
||||
query: CompiledQuery<R>,
|
||||
context: SubscribedQueryContext<R>,
|
||||
) => Promise<QueryResult<R>>;
|
||||
unsubscribeAppQuery: (queryId: string) => Promise<void>;
|
||||
unsubscribeAppQuery: (queryKey: string[]) => Promise<void>;
|
||||
|
||||
executeWorkspaceMutation: (
|
||||
accountId: string,
|
||||
|
||||
Reference in New Issue
Block a user