mirror of
https://github.com/docmost/docmost.git
synced 2026-07-14 09:06:45 +10:00
refactor(base): rename baseId to pageId in client atoms, hooks, types
This commit is contained in:
@@ -3,12 +3,12 @@ import { BaseViewDraft } from "@/features/base/types/base.types";
|
||||
|
||||
export type ViewDraftKey = {
|
||||
userId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
viewId: string;
|
||||
};
|
||||
|
||||
export const viewDraftStorageKey = (k: ViewDraftKey) =>
|
||||
`docmost:base-view-draft:v1:${k.userId}:${k.baseId}:${k.viewId}`;
|
||||
`docmost:base-view-draft:v1:${k.userId}:${k.pageId}:${k.viewId}`;
|
||||
|
||||
// `atomWithStorage` handles JSON serialization, cross-tab sync via the
|
||||
// `storage` event, and lazy first-read out of the box. `atomFamily`'s
|
||||
@@ -18,5 +18,5 @@ export const viewDraftAtomFamily = atomFamily(
|
||||
(k: ViewDraftKey) =>
|
||||
atomWithStorage<BaseViewDraft | null>(viewDraftStorageKey(k), null),
|
||||
(a, b) =>
|
||||
a.userId === b.userId && a.baseId === b.baseId && a.viewId === b.viewId,
|
||||
a.userId === b.userId && a.pageId === b.pageId && a.viewId === b.viewId,
|
||||
);
|
||||
|
||||
@@ -13,14 +13,14 @@ import { IPagination } from "@/lib/types";
|
||||
|
||||
type BaseRowCreated = {
|
||||
operation: "base:row:created";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
row: IBaseRow;
|
||||
requestId?: string | null;
|
||||
};
|
||||
|
||||
type BaseRowUpdated = {
|
||||
operation: "base:row:updated";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowId: string;
|
||||
updatedCells: Record<string, unknown>;
|
||||
requestId?: string | null;
|
||||
@@ -28,21 +28,21 @@ type BaseRowUpdated = {
|
||||
|
||||
type BaseRowDeleted = {
|
||||
operation: "base:row:deleted";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowId: string;
|
||||
requestId?: string | null;
|
||||
};
|
||||
|
||||
type BaseRowsDeleted = {
|
||||
operation: "base:rows:deleted";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowIds: string[];
|
||||
requestId?: string | null;
|
||||
};
|
||||
|
||||
type BaseRowReordered = {
|
||||
operation: "base:row:reordered";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowId: string;
|
||||
position: string;
|
||||
requestId?: string | null;
|
||||
@@ -54,7 +54,7 @@ type BasePropertyEvent = {
|
||||
| "base:property:updated"
|
||||
| "base:property:deleted"
|
||||
| "base:property:reordered";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
property?: IBaseProperty;
|
||||
propertyId?: string;
|
||||
requestId?: string | null;
|
||||
@@ -65,14 +65,14 @@ type BaseViewEvent = {
|
||||
| "base:view:created"
|
||||
| "base:view:updated"
|
||||
| "base:view:deleted";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
view?: IBaseView;
|
||||
viewId?: string;
|
||||
};
|
||||
|
||||
type BaseRowsUpdated = {
|
||||
operation: "base:rows:updated";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowIds: string[];
|
||||
propertyIds: string[];
|
||||
requestId?: string | null;
|
||||
@@ -80,14 +80,14 @@ type BaseRowsUpdated = {
|
||||
|
||||
type BaseFormulaRecomputeStarted = {
|
||||
operation: "base:formula:recompute:started";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
propertyIds: string[];
|
||||
jobId: string;
|
||||
};
|
||||
|
||||
type BaseFormulaRecomputeCompleted = {
|
||||
operation: "base:formula:recompute:completed";
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
propertyIds: string[];
|
||||
jobId: string;
|
||||
processed: number;
|
||||
@@ -105,7 +105,7 @@ type BaseInboundEvent =
|
||||
| BaseFormulaRecomputeCompleted
|
||||
| BasePropertyEvent
|
||||
| BaseViewEvent
|
||||
| { operation: string; baseId: string };
|
||||
| { operation: string; pageId: string };
|
||||
|
||||
/*
|
||||
* Module-level set of requestIds we've just sent to the server. When the
|
||||
@@ -126,24 +126,24 @@ export function markRequestIdOutbound(requestId: string): void {
|
||||
}
|
||||
|
||||
/*
|
||||
* Realtime bridge for a single base. Joins the server's `base-{baseId}`
|
||||
* Realtime bridge for a single base. Joins the server's `base-{pageId}`
|
||||
* room on mount, leaves on unmount, and reconciles the React Query caches
|
||||
* (`["base-rows", baseId, ...]` and `["bases", baseId]`) when events
|
||||
* (`["base-rows", pageId, ...]` and `["bases", pageId]`) when events
|
||||
* arrive from other clients.
|
||||
*/
|
||||
export function useBaseSocket(baseId: string | undefined): void {
|
||||
export function useBaseSocket(pageId: string | undefined): void {
|
||||
const socket = useAtomValue(socketAtom);
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
useEffect(() => {
|
||||
if (!socket || !baseId) return;
|
||||
if (!socket || !pageId) return;
|
||||
|
||||
socket.emit("message", { operation: "base:subscribe", baseId });
|
||||
socket.emit("message", { operation: "base:subscribe", pageId });
|
||||
|
||||
const handler = (raw: unknown) => {
|
||||
if (!raw || typeof raw !== "object") return;
|
||||
const event = raw as BaseInboundEvent;
|
||||
if (event.baseId !== baseId) return;
|
||||
if (event.pageId !== pageId) return;
|
||||
|
||||
const requestId = (event as any).requestId as string | undefined;
|
||||
if (requestId && outboundRequestIds.has(requestId)) {
|
||||
@@ -155,7 +155,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
case "base:row:created": {
|
||||
const e = event as BaseRowCreated;
|
||||
queryClient.setQueriesData<InfiniteData<IPagination<IBaseRow>>>(
|
||||
{ queryKey: ["base-rows", baseId] },
|
||||
{ queryKey: ["base-rows", pageId] },
|
||||
(old) => {
|
||||
if (!old) return old;
|
||||
const lastPageIndex = old.pages.length - 1;
|
||||
@@ -174,7 +174,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
case "base:row:updated": {
|
||||
const e = event as BaseRowUpdated;
|
||||
queryClient.setQueriesData<InfiniteData<IPagination<IBaseRow>>>(
|
||||
{ queryKey: ["base-rows", baseId] },
|
||||
{ queryKey: ["base-rows", pageId] },
|
||||
(old) =>
|
||||
!old
|
||||
? old
|
||||
@@ -198,7 +198,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
case "base:row:deleted": {
|
||||
const e = event as BaseRowDeleted;
|
||||
queryClient.setQueriesData<InfiniteData<IPagination<IBaseRow>>>(
|
||||
{ queryKey: ["base-rows", baseId] },
|
||||
{ queryKey: ["base-rows", pageId] },
|
||||
(old) =>
|
||||
!old
|
||||
? old
|
||||
@@ -223,7 +223,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
const e = event as BaseRowsDeleted;
|
||||
const removeSet = new Set(e.rowIds);
|
||||
queryClient.setQueriesData<InfiniteData<IPagination<IBaseRow>>>(
|
||||
{ queryKey: ["base-rows", baseId] },
|
||||
{ queryKey: ["base-rows", pageId] },
|
||||
(old) => {
|
||||
if (!old) return old;
|
||||
return {
|
||||
@@ -250,7 +250,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
case "base:row:reordered": {
|
||||
const e = event as BaseRowReordered;
|
||||
queryClient.setQueriesData<InfiniteData<IPagination<IBaseRow>>>(
|
||||
{ queryKey: ["base-rows", baseId] },
|
||||
{ queryKey: ["base-rows", pageId] },
|
||||
(old) =>
|
||||
!old
|
||||
? old
|
||||
@@ -278,7 +278,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
const updatedIds = new Set(e.rowIds);
|
||||
const caches = queryClient.getQueriesData<
|
||||
InfiniteData<IPagination<IBaseRow>>
|
||||
>({ queryKey: ["base-rows", baseId] });
|
||||
>({ queryKey: ["base-rows", pageId] });
|
||||
let touchesCache = false;
|
||||
outer: for (const [, data] of caches) {
|
||||
if (!data) continue;
|
||||
@@ -292,7 +292,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
}
|
||||
}
|
||||
if (touchesCache) {
|
||||
queryClient.invalidateQueries({ queryKey: ["base-rows", baseId] });
|
||||
queryClient.invalidateQueries({ queryKey: ["base-rows", pageId] });
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -325,9 +325,9 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
case "base:view:deleted": {
|
||||
// Schema/metadata events only touch the base's `properties` /
|
||||
// `views`, not the cell data — so we invalidate just
|
||||
// `["bases", baseId]` here. Row reconciliation is handled
|
||||
// `["bases", pageId]` here. Row reconciliation is handled
|
||||
// per-event by the row cases above.
|
||||
queryClient.invalidateQueries({ queryKey: ["bases", baseId] });
|
||||
queryClient.invalidateQueries({ queryKey: ["bases", pageId] });
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -339,7 +339,7 @@ export function useBaseSocket(baseId: string | undefined): void {
|
||||
|
||||
return () => {
|
||||
socket.off("message", handler);
|
||||
socket.emit("message", { operation: "base:unsubscribe", baseId });
|
||||
socket.emit("message", { operation: "base:unsubscribe", pageId });
|
||||
};
|
||||
}, [socket, baseId, queryClient]);
|
||||
}, [socket, pageId, queryClient]);
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ export function useBaseTable(
|
||||
filter: baseline?.filter,
|
||||
});
|
||||
updateViewMutation.mutate(
|
||||
{ viewId: activeView.id, baseId: base.id, config },
|
||||
{ viewId: activeView.id, pageId: base.id, config },
|
||||
{
|
||||
onSettled: () => {
|
||||
// Don't clear if the user has already scheduled another
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useDeleteRowsMutation } from "@/features/base/queries/base-row-query";
|
||||
|
||||
const BATCH_SIZE = 500;
|
||||
|
||||
export function useDeleteSelectedRows(baseId: string) {
|
||||
export function useDeleteSelectedRows(pageId: string) {
|
||||
const { t } = useTranslation();
|
||||
const { selectedIds, clear } = useRowSelection();
|
||||
const mutation = useDeleteRowsMutation();
|
||||
@@ -21,7 +21,7 @@ export function useDeleteSelectedRows(baseId: string) {
|
||||
}
|
||||
try {
|
||||
for (const chunk of chunks) {
|
||||
await mutation.mutateAsync({ baseId, rowIds: chunk });
|
||||
await mutation.mutateAsync({ pageId, rowIds: chunk });
|
||||
}
|
||||
notifications.show({
|
||||
message: t("{{count}} rows deleted", { count: ids.length }),
|
||||
@@ -31,7 +31,7 @@ export function useDeleteSelectedRows(baseId: string) {
|
||||
// mutation onError already shows notification
|
||||
}
|
||||
},
|
||||
[baseId, mutation, clear, t],
|
||||
[pageId, mutation, clear, t],
|
||||
);
|
||||
|
||||
const deleteSelected = useCallback(() => {
|
||||
|
||||
@@ -11,7 +11,7 @@ import { viewDraftAtomFamily } from "@/features/base/atoms/view-draft-atom";
|
||||
|
||||
export type UseViewDraftArgs = {
|
||||
userId: string | undefined;
|
||||
baseId: string | undefined;
|
||||
pageId: string | undefined;
|
||||
viewId: string | undefined;
|
||||
baselineFilter: FilterGroup | undefined;
|
||||
baselineSorts: ViewSortConfig[] | undefined;
|
||||
@@ -43,18 +43,18 @@ function sortsEq(
|
||||
}
|
||||
|
||||
export function useViewDraft(args: UseViewDraftArgs): ViewDraftState {
|
||||
const { userId, baseId, viewId, baselineFilter, baselineSorts } = args;
|
||||
const ready = !!(userId && baseId && viewId);
|
||||
const { userId, pageId, viewId, baselineFilter, baselineSorts } = args;
|
||||
const ready = !!(userId && pageId && viewId);
|
||||
|
||||
// Always mount an atom with a stable shape so hook order is consistent.
|
||||
// When not ready we still feed a key, but we won't read/write it.
|
||||
const atomKey = useMemo(
|
||||
() => ({
|
||||
userId: userId ?? "",
|
||||
baseId: baseId ?? "",
|
||||
pageId: pageId ?? "",
|
||||
viewId: viewId ?? "",
|
||||
}),
|
||||
[userId, baseId, viewId],
|
||||
[userId, pageId, viewId],
|
||||
);
|
||||
const [storedDraft, setDraft] = useAtom(viewDraftAtomFamily(atomKey));
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ export type TypeOptions =
|
||||
|
||||
export type IBaseProperty = {
|
||||
id: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
type: BasePropertyType;
|
||||
position: string;
|
||||
@@ -99,7 +99,7 @@ export type IBaseProperty = {
|
||||
|
||||
export type IBaseRow = {
|
||||
id: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
cells: Record<string, unknown>;
|
||||
position: string;
|
||||
creatorId: string;
|
||||
@@ -165,7 +165,7 @@ export type ViewConfig = {
|
||||
|
||||
export type IBaseView = {
|
||||
id: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
type: 'table' | 'kanban' | 'calendar';
|
||||
config: ViewConfig;
|
||||
@@ -204,14 +204,14 @@ export type CreateBaseInput = {
|
||||
};
|
||||
|
||||
export type UpdateBaseInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
};
|
||||
|
||||
export type CreatePropertyInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
type: BasePropertyType;
|
||||
typeOptions?: TypeOptions;
|
||||
@@ -220,7 +220,7 @@ export type CreatePropertyInput = {
|
||||
|
||||
export type UpdatePropertyInput = {
|
||||
propertyId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name?: string;
|
||||
typeOptions?: TypeOptions;
|
||||
requestId?: string;
|
||||
@@ -228,19 +228,19 @@ export type UpdatePropertyInput = {
|
||||
|
||||
export type DeletePropertyInput = {
|
||||
propertyId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type ReorderPropertyInput = {
|
||||
propertyId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
position: string;
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type CountRowsInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
filter?: FilterNode;
|
||||
search?: SearchSpec;
|
||||
// When true the server returns an exact (but capped) count. Otherwise
|
||||
@@ -255,7 +255,7 @@ export type CountRowsResult = {
|
||||
};
|
||||
|
||||
export type CreateRowInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
cells?: Record<string, unknown>;
|
||||
afterRowId?: string;
|
||||
requestId?: string;
|
||||
@@ -263,32 +263,32 @@ export type CreateRowInput = {
|
||||
|
||||
export type UpdateRowInput = {
|
||||
rowId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
cells: Record<string, unknown>;
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type DeleteRowInput = {
|
||||
rowId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type DeleteRowsInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
rowIds: string[];
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type ReorderRowInput = {
|
||||
rowId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
position: string;
|
||||
requestId?: string;
|
||||
};
|
||||
|
||||
export type CreateViewInput = {
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name: string;
|
||||
type?: 'table' | 'kanban' | 'calendar';
|
||||
config?: ViewConfig;
|
||||
@@ -296,7 +296,7 @@ export type CreateViewInput = {
|
||||
|
||||
export type UpdateViewInput = {
|
||||
viewId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
name?: string;
|
||||
type?: 'table' | 'kanban' | 'calendar';
|
||||
config?: ViewConfig;
|
||||
@@ -304,7 +304,7 @@ export type UpdateViewInput = {
|
||||
|
||||
export type DeleteViewInput = {
|
||||
viewId: string;
|
||||
baseId: string;
|
||||
pageId: string;
|
||||
};
|
||||
|
||||
export type UpdatePropertyResult = {
|
||||
|
||||
Reference in New Issue
Block a user