@agent-native/core 0.133.2 → 0.133.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +6 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/client/use-action.ts +6 -0
- package/corpus/templates/content/actions/_batch-utils.ts +33 -0
- package/corpus/templates/content/actions/_builder-cms-read-client.ts +173 -81
- package/corpus/templates/content/actions/_content-files.ts +31 -21
- package/corpus/templates/content/actions/_database-source-utils.ts +653 -155
- package/corpus/templates/content/actions/_database-utils.ts +535 -41
- package/corpus/templates/content/actions/add-content-database-source-field-property.ts +291 -240
- package/corpus/templates/content/actions/add-database-item.ts +15 -1
- package/corpus/templates/content/actions/attach-content-database-source.ts +156 -58
- package/corpus/templates/content/actions/bind-content-database-source-field.ts +2 -2
- package/corpus/templates/content/actions/cancel-prepared-builder-source-update.ts +4 -1
- package/corpus/templates/content/actions/delete-database-items.ts +8 -2
- package/corpus/templates/content/actions/disconnect-content-database-source.ts +2 -2
- package/corpus/templates/content/actions/duplicate-database-item.ts +15 -1
- package/corpus/templates/content/actions/duplicate-database-items.ts +19 -1
- package/corpus/templates/content/actions/execute-builder-source-execution.ts +2 -1
- package/corpus/templates/content/actions/get-content-database.ts +12 -64
- package/corpus/templates/content/actions/move-database-item.ts +4 -1
- package/corpus/templates/content/actions/prepare-builder-source-execution.ts +1 -1
- package/corpus/templates/content/actions/prepare-builder-source-review.ts +4 -8
- package/corpus/templates/content/actions/preview-content-database-source-attach.ts +92 -0
- package/corpus/templates/content/actions/process-builder-body-hydration.ts +2 -1
- package/corpus/templates/content/actions/query-content-database-items.ts +64 -0
- package/corpus/templates/content/actions/refresh-content-database-source.ts +7 -0
- package/corpus/templates/content/actions/review-content-database-source-change-set.ts +1 -1
- package/corpus/templates/content/actions/set-content-database-source-write-mode.ts +1 -1
- package/corpus/templates/content/actions/stage-builder-revision.ts +1 -1
- package/corpus/templates/content/actions/update-content-database-personal-view.ts +29 -3
- package/corpus/templates/content/actions/update-content-database-view.ts +1 -1
- package/corpus/templates/content/actions/validate-builder-source-execution.ts +1 -1
- package/corpus/templates/content/app/components/editor/DocumentProperties.tsx +3 -22
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +267 -105
- package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +82 -1
- package/corpus/templates/content/app/hooks/use-content-database.ts +285 -24
- package/corpus/templates/content/app/hooks/use-document-properties.ts +7 -6
- package/corpus/templates/content/app/i18n-data.ts +10 -0
- package/corpus/templates/content/changelog/2026-07-29-large-databases-keep-useful-rows-visible.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-builder-source-columns-now-appear-immediately-when-connected.md +6 -0
- package/corpus/templates/content/changelog/2026-07-30-large-builder-backed-tables-show-useful-rows-sooner-and-fini.md +6 -0
- package/corpus/templates/content/changelog/2026-08-01-large-builder-databases-now-show-rows-immediately-and-finish.md +6 -0
- package/corpus/templates/content/parity/matrix.md +2 -1
- package/corpus/templates/content/parity/matrix.ts +25 -0
- package/corpus/templates/content/shared/api.ts +54 -4
- package/corpus/templates/content/shared/database-query.ts +359 -0
- package/dist/client/use-action.d.ts.map +1 -1
- package/dist/client/use-action.js +6 -0
- package/dist/client/use-action.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/package.json +1 -1
- package/src/client/use-action.ts +6 -0
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
type BuilderCmsModelSummary,
|
|
16
16
|
type ContentDatabaseItem,
|
|
17
17
|
type ContentDatabaseResponse,
|
|
18
|
+
type ContentDatabaseSourceAttachmentResult,
|
|
18
19
|
type ContentDatabaseSource,
|
|
19
20
|
type ContentDatabaseSourceChangeSet,
|
|
20
21
|
type ContentDatabaseSourceJoinRequest,
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
type ContentDatabaseRowDensity,
|
|
35
36
|
type ContentDatabaseSort,
|
|
36
37
|
type ContentDatabaseSortDirection,
|
|
38
|
+
type ContentDatabaseTableQuery,
|
|
37
39
|
type ContentDatabaseViewType,
|
|
38
40
|
type Document,
|
|
39
41
|
type DocumentProperty,
|
|
@@ -42,6 +44,7 @@ import {
|
|
|
42
44
|
type DocumentPropertyValue,
|
|
43
45
|
} from "@shared/api";
|
|
44
46
|
import { contentDatabaseFormQuestions } from "@shared/database-form";
|
|
47
|
+
import { applyContentDatabaseTableQuery } from "@shared/database-query";
|
|
45
48
|
import {
|
|
46
49
|
type DocumentPropertyOptionColor,
|
|
47
50
|
countWords,
|
|
@@ -165,6 +168,7 @@ import {
|
|
|
165
168
|
useAddDatabaseItem,
|
|
166
169
|
useAddContentDatabaseSourceFieldProperty,
|
|
167
170
|
useAttachContentDatabaseSource,
|
|
171
|
+
useBuilderCmsAttachPreview,
|
|
168
172
|
useBuilderCmsModels,
|
|
169
173
|
useCancelPreparedBuilderSourceUpdate,
|
|
170
174
|
useChangeContentDatabaseSourceRole,
|
|
@@ -188,6 +192,7 @@ import {
|
|
|
188
192
|
useSuggestSourceJoinKey,
|
|
189
193
|
useUpdateContentDatabasePersonalView,
|
|
190
194
|
useUpdateContentDatabaseView,
|
|
195
|
+
writeBuilderAttachPreviewToCache,
|
|
191
196
|
} from "@/hooks/use-content-database";
|
|
192
197
|
import {
|
|
193
198
|
useContentSpaces,
|
|
@@ -441,6 +446,7 @@ export function databaseCreatedItemForImmediatePreview(
|
|
|
441
446
|
now?: string;
|
|
442
447
|
},
|
|
443
448
|
): ContentDatabaseItem | null {
|
|
449
|
+
if (response.createdItem) return response.createdItem;
|
|
444
450
|
const returnedItem = response.items.find(
|
|
445
451
|
(item) => item.id === response.createdItemId,
|
|
446
452
|
);
|
|
@@ -769,15 +775,51 @@ function DatabaseTable({
|
|
|
769
775
|
SELECTED_CONTENT_SPACE_STORAGE_KEY,
|
|
770
776
|
null,
|
|
771
777
|
);
|
|
778
|
+
const [searchQuery, setSearchQuery] = useState("");
|
|
779
|
+
const [viewConfig, setViewConfig] = useState<ContentDatabaseViewConfig>(
|
|
780
|
+
defaultDatabaseViewConfig(),
|
|
781
|
+
);
|
|
782
|
+
const activeView = useMemo(
|
|
783
|
+
() => activeDatabaseView(viewConfig),
|
|
784
|
+
[viewConfig],
|
|
785
|
+
);
|
|
786
|
+
const tableQuery = useMemo<ContentDatabaseTableQuery | undefined>(() => {
|
|
787
|
+
if (
|
|
788
|
+
activeView.type !== "table" ||
|
|
789
|
+
activeDatabaseConstraintCount(
|
|
790
|
+
searchQuery,
|
|
791
|
+
activeView.sorts,
|
|
792
|
+
activeView.filters,
|
|
793
|
+
) === 0
|
|
794
|
+
) {
|
|
795
|
+
return undefined;
|
|
796
|
+
}
|
|
797
|
+
return {
|
|
798
|
+
search: searchQuery,
|
|
799
|
+
filters: activeView.filters,
|
|
800
|
+
sorts: activeView.sorts,
|
|
801
|
+
filterMode: activeView.filterMode ?? "and",
|
|
802
|
+
};
|
|
803
|
+
}, [activeView, searchQuery]);
|
|
772
804
|
const [manualDatabaseItemLimit, setManualDatabaseItemLimit] = useState(
|
|
773
805
|
CONTENT_DATABASE_PAGE_SIZE,
|
|
774
806
|
);
|
|
775
807
|
const [databaseRequestItemLimit, setDatabaseRequestItemLimit] = useState(
|
|
776
808
|
CONTENT_DATABASE_PAGE_SIZE,
|
|
777
809
|
);
|
|
778
|
-
const database = useContentDatabase(
|
|
810
|
+
const database = useContentDatabase(
|
|
811
|
+
document.id,
|
|
812
|
+
databaseRequestItemLimit,
|
|
813
|
+
tableQuery,
|
|
814
|
+
);
|
|
815
|
+
// A deleted/missing database resolves to the unavailable union (no
|
|
816
|
+
// `database` field) — treat it as no data; the inline-block wrapper owns
|
|
817
|
+
// the user-facing "Database unavailable" state.
|
|
818
|
+
const data = isContentDatabaseUnavailable(database.data)
|
|
819
|
+
? undefined
|
|
820
|
+
: database.data;
|
|
779
821
|
const addItem = useAddDatabaseItem(document.id);
|
|
780
|
-
const attachSource = useAttachContentDatabaseSource(document.id);
|
|
822
|
+
const attachSource = useAttachContentDatabaseSource(document.id, data);
|
|
781
823
|
const changeSourceRole = useChangeContentDatabaseSourceRole(document.id);
|
|
782
824
|
const refreshSource = useRefreshContentDatabaseSource(document.id);
|
|
783
825
|
const disconnectSource = useDisconnectContentDatabaseSource(document.id);
|
|
@@ -794,12 +836,8 @@ function DatabaseTable({
|
|
|
794
836
|
document.id,
|
|
795
837
|
);
|
|
796
838
|
const updateView = useUpdateContentDatabaseView(document.id);
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
// the user-facing "Database unavailable" state.
|
|
800
|
-
const data = isContentDatabaseUnavailable(database.data)
|
|
801
|
-
? undefined
|
|
802
|
-
: database.data;
|
|
839
|
+
const attachPreviewActive = Boolean(data?.attachPreview);
|
|
840
|
+
const effectiveCanEdit = canEdit && !attachPreviewActive;
|
|
803
841
|
const isWorkspaceCatalog = data?.database.systemRole === "workspaces";
|
|
804
842
|
const isCreatingDatabaseItem = addItem.isPending;
|
|
805
843
|
const isDatabaseInitialLoading = database.isLoading && !data;
|
|
@@ -841,7 +879,6 @@ function DatabaseTable({
|
|
|
841
879
|
string | null
|
|
842
880
|
>(null);
|
|
843
881
|
const [searchOpen, setSearchOpen] = useState(false);
|
|
844
|
-
const [searchQuery, setSearchQuery] = useState("");
|
|
845
882
|
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
846
883
|
const [inlineFilterControlsOpen, setInlineFilterControlsOpen] =
|
|
847
884
|
useState(false);
|
|
@@ -876,19 +913,12 @@ function DatabaseTable({
|
|
|
876
913
|
useState<Record<string, string> | null>(null);
|
|
877
914
|
const [settingsPanel, setSettingsPanel] =
|
|
878
915
|
useState<DatabaseSettingsPanel>("main");
|
|
879
|
-
const [viewConfig, setViewConfig] = useState<ContentDatabaseViewConfig>(
|
|
880
|
-
defaultDatabaseViewConfig(),
|
|
881
|
-
);
|
|
882
916
|
const [savedViewConfig, setSavedViewConfig] =
|
|
883
917
|
useState<ContentDatabaseViewConfig>(defaultDatabaseViewConfig());
|
|
884
918
|
const [personalQueryDirty, setPersonalQueryDirty] = useState(false);
|
|
885
919
|
const [dateViewMonth, setDateViewMonth] = useState(() =>
|
|
886
920
|
startOfMonth(new Date()),
|
|
887
921
|
);
|
|
888
|
-
const activeView = useMemo(
|
|
889
|
-
() => activeDatabaseView(viewConfig),
|
|
890
|
-
[viewConfig],
|
|
891
|
-
);
|
|
892
922
|
const orderedProperties = useMemo(
|
|
893
923
|
() => orderDatabasePropertiesForView(properties, activeView),
|
|
894
924
|
[properties, activeView],
|
|
@@ -996,10 +1026,12 @@ function DatabaseTable({
|
|
|
996
1026
|
visibleFilters,
|
|
997
1027
|
);
|
|
998
1028
|
const requiresCompleteClientDataset =
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1029
|
+
databaseViewRequiresCompleteClientDataset({
|
|
1030
|
+
viewType: activeView.type,
|
|
1031
|
+
activeConstraintCount,
|
|
1032
|
+
grouped: !!databaseGroupProperty,
|
|
1033
|
+
tableQueryMode: data?.tableQueryMode,
|
|
1034
|
+
});
|
|
1003
1035
|
const clientQueryExpandedItemLimit = databaseClientQueryExpandedItemLimit(
|
|
1004
1036
|
requiresCompleteClientDataset,
|
|
1005
1037
|
manualDatabaseItemLimit,
|
|
@@ -1011,7 +1043,19 @@ function DatabaseTable({
|
|
|
1011
1043
|
data?.pagination?.limit ?? items.length,
|
|
1012
1044
|
);
|
|
1013
1045
|
const isDatabaseViewLoading =
|
|
1014
|
-
isDatabaseInitialLoading ||
|
|
1046
|
+
isDatabaseInitialLoading ||
|
|
1047
|
+
isClientQueryExpansionPending ||
|
|
1048
|
+
(database.isFetching && Boolean(tableQuery));
|
|
1049
|
+
useEffect(() => {
|
|
1050
|
+
if (isDatabaseViewLoading) return;
|
|
1051
|
+
window.document.documentElement.dataset.contentDatabaseRowsVisibleDocumentId =
|
|
1052
|
+
document.id;
|
|
1053
|
+
window.dispatchEvent(
|
|
1054
|
+
new CustomEvent("content-database-rows-visible", {
|
|
1055
|
+
detail: { documentId: document.id },
|
|
1056
|
+
}),
|
|
1057
|
+
);
|
|
1058
|
+
}, [document.id, isDatabaseViewLoading]);
|
|
1015
1059
|
useEffect(() => {
|
|
1016
1060
|
if (clientQueryExpandedItemLimit === databaseRequestItemLimit) return;
|
|
1017
1061
|
setDatabaseRequestItemLimit(clientQueryExpandedItemLimit);
|
|
@@ -1072,6 +1116,8 @@ function DatabaseTable({
|
|
|
1072
1116
|
() => builderReviewableChangeSets(builderReviewSource),
|
|
1073
1117
|
[builderReviewSource],
|
|
1074
1118
|
);
|
|
1119
|
+
const builderReviewCountIsComplete =
|
|
1120
|
+
databaseSourceChangeSetsAreComplete(builderReviewSource);
|
|
1075
1121
|
const builderReviewPreview = useMemo(
|
|
1076
1122
|
() =>
|
|
1077
1123
|
builderReviewSource && builderReviewChangeSets.length > 0
|
|
@@ -1082,11 +1128,12 @@ function DatabaseTable({
|
|
|
1082
1128
|
: null,
|
|
1083
1129
|
[builderReviewChangeSets, builderReviewSource],
|
|
1084
1130
|
);
|
|
1085
|
-
const activeBuilderReview =
|
|
1086
|
-
builderReviewResult
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1131
|
+
const activeBuilderReview = databaseActiveBuilderReview({
|
|
1132
|
+
prepared: builderReviewResult,
|
|
1133
|
+
complete: completeBuilderReviewPreview?.review ?? null,
|
|
1134
|
+
page: builderReviewPreview,
|
|
1135
|
+
open: builderReviewOpen,
|
|
1136
|
+
});
|
|
1090
1137
|
const sourcePendingOperations: DatabaseSourcePendingOperations = {
|
|
1091
1138
|
attach: attachSource.isPending,
|
|
1092
1139
|
changeRole: changeSourceRole.isPending,
|
|
@@ -1135,6 +1182,7 @@ function DatabaseTable({
|
|
|
1135
1182
|
onError?: () => void,
|
|
1136
1183
|
expectedBuilderContinuationOffset?: number,
|
|
1137
1184
|
onSuccess?: () => void,
|
|
1185
|
+
fullRefresh = false,
|
|
1138
1186
|
) => {
|
|
1139
1187
|
if (!acquireDatabaseSourceOperation(refreshSourceInFlightRef, sourceId)) {
|
|
1140
1188
|
return false;
|
|
@@ -1144,6 +1192,8 @@ function DatabaseTable({
|
|
|
1144
1192
|
documentId: document.id,
|
|
1145
1193
|
sourceId,
|
|
1146
1194
|
expectedBuilderContinuationOffset,
|
|
1195
|
+
fullRefresh: fullRefresh || undefined,
|
|
1196
|
+
finishBuilderPagination: fullRefresh || undefined,
|
|
1147
1197
|
},
|
|
1148
1198
|
{
|
|
1149
1199
|
onError,
|
|
@@ -1190,19 +1240,35 @@ function DatabaseTable({
|
|
|
1190
1240
|
) {
|
|
1191
1241
|
return false;
|
|
1192
1242
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1243
|
+
const pump = () => {
|
|
1244
|
+
let result: ProcessBuilderBodyHydrationResponse | null = null;
|
|
1245
|
+
processBuilderBodies.mutate(
|
|
1246
|
+
{ sourceId, ...request },
|
|
1247
|
+
{
|
|
1248
|
+
onSuccess: (nextResult) => {
|
|
1249
|
+
result = nextResult;
|
|
1250
|
+
options.onSuccess?.(nextResult);
|
|
1251
|
+
},
|
|
1252
|
+
onError: options.onError,
|
|
1253
|
+
onSettled: () => {
|
|
1254
|
+
if (
|
|
1255
|
+
!request.documentId &&
|
|
1256
|
+
result &&
|
|
1257
|
+
builderBodyHydrationMutationMadeProgress(result) &&
|
|
1258
|
+
result.remaining > 0
|
|
1259
|
+
) {
|
|
1260
|
+
pump();
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
releaseDatabaseSourceOperation(
|
|
1264
|
+
hydrationSourceInFlightRef,
|
|
1265
|
+
sourceId,
|
|
1266
|
+
);
|
|
1267
|
+
},
|
|
1203
1268
|
},
|
|
1204
|
-
|
|
1205
|
-
|
|
1269
|
+
);
|
|
1270
|
+
};
|
|
1271
|
+
pump();
|
|
1206
1272
|
return true;
|
|
1207
1273
|
},
|
|
1208
1274
|
[processBuilderBodies.mutate],
|
|
@@ -1246,6 +1312,7 @@ function DatabaseTable({
|
|
|
1246
1312
|
() => handleBuilderContinuationError(continuationKey),
|
|
1247
1313
|
candidate.metadata.lastReadNextOffset,
|
|
1248
1314
|
() => handleBuilderContinuationSuccess(continuationKey),
|
|
1315
|
+
true,
|
|
1249
1316
|
)
|
|
1250
1317
|
) {
|
|
1251
1318
|
autoContinueBuilderSourceRef.current.delete(continuationKey);
|
|
@@ -1325,6 +1392,7 @@ function DatabaseTable({
|
|
|
1325
1392
|
() => handleBuilderContinuationError(continuationKey),
|
|
1326
1393
|
candidate.metadata.lastReadNextOffset,
|
|
1327
1394
|
() => handleBuilderContinuationSuccess(continuationKey),
|
|
1395
|
+
true,
|
|
1328
1396
|
)
|
|
1329
1397
|
) {
|
|
1330
1398
|
builderContinuationWatchdogRef.current.set(
|
|
@@ -2264,7 +2332,7 @@ function DatabaseTable({
|
|
|
2264
2332
|
: viewConfig;
|
|
2265
2333
|
const nextKey = databaseViewStateKey(databaseId, sharedViewConfig);
|
|
2266
2334
|
if (databaseViewStateKey(databaseId, savedViewConfig) === nextKey) return;
|
|
2267
|
-
if (!
|
|
2335
|
+
if (!effectiveCanEdit) return;
|
|
2268
2336
|
if (saveViewTimerRef.current) {
|
|
2269
2337
|
clearTimeout(saveViewTimerRef.current);
|
|
2270
2338
|
}
|
|
@@ -2344,7 +2412,7 @@ function DatabaseTable({
|
|
|
2344
2412
|
<div className="mb-1 flex min-h-8 flex-wrap items-center justify-between gap-x-3 gap-y-1 pb-1">
|
|
2345
2413
|
<DatabaseViewTabs
|
|
2346
2414
|
viewConfig={viewConfig}
|
|
2347
|
-
canEdit={
|
|
2415
|
+
canEdit={effectiveCanEdit}
|
|
2348
2416
|
onViewConfigChange={setViewConfig}
|
|
2349
2417
|
/>
|
|
2350
2418
|
<div className="flex max-w-full flex-wrap items-center justify-end gap-1">
|
|
@@ -2460,12 +2528,16 @@ function DatabaseTable({
|
|
|
2460
2528
|
size="sm"
|
|
2461
2529
|
aria-label={
|
|
2462
2530
|
builderReviewChangeSets.length > 0
|
|
2463
|
-
?
|
|
2531
|
+
? builderReviewCountIsComplete
|
|
2532
|
+
? `Database settings, ${builderReviewChangeSets.length} Builder update pending`
|
|
2533
|
+
: "Database settings, Builder updates pending"
|
|
2464
2534
|
: "Database settings"
|
|
2465
2535
|
}
|
|
2466
2536
|
title={
|
|
2467
2537
|
builderReviewChangeSets.length > 0
|
|
2468
|
-
?
|
|
2538
|
+
? builderReviewCountIsComplete
|
|
2539
|
+
? `${builderReviewChangeSets.length} Builder update pending`
|
|
2540
|
+
: "Builder updates pending"
|
|
2469
2541
|
: "Database settings"
|
|
2470
2542
|
}
|
|
2471
2543
|
className={cn(
|
|
@@ -2485,12 +2557,24 @@ function DatabaseTable({
|
|
|
2485
2557
|
>
|
|
2486
2558
|
<IconAdjustmentsHorizontal className="size-3.5" />
|
|
2487
2559
|
{builderReviewChangeSets.length > 0 ? (
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2560
|
+
builderReviewCountIsComplete ? (
|
|
2561
|
+
<span className="absolute -right-0.5 -top-0.5 flex h-3.5 min-w-3.5 shrink-0 items-center justify-center rounded-full bg-foreground px-1 text-[9px] leading-none text-background">
|
|
2562
|
+
{formatCompactCountBadge(builderReviewChangeSets.length)}
|
|
2563
|
+
</span>
|
|
2564
|
+
) : (
|
|
2565
|
+
<span className="absolute right-0 top-0 size-2 rounded-full bg-foreground" />
|
|
2566
|
+
)
|
|
2491
2567
|
) : null}
|
|
2492
2568
|
</Button>
|
|
2493
|
-
{
|
|
2569
|
+
{data?.attachPreview ? (
|
|
2570
|
+
<span className="rounded border border-border px-1.5 py-0.5 text-[10px] font-medium text-muted-foreground">
|
|
2571
|
+
{data.attachPreview.complete &&
|
|
2572
|
+
typeof data.attachPreview.importedItemCount === "number"
|
|
2573
|
+
? `${data.attachPreview.importedItemCount} rows fetched`
|
|
2574
|
+
: dbText("attachingReadOnly")}
|
|
2575
|
+
</span>
|
|
2576
|
+
) : null}
|
|
2577
|
+
{effectiveCanEdit && isWorkspaceCatalog ? (
|
|
2494
2578
|
<WorkspaceSourceMenu
|
|
2495
2579
|
align="end"
|
|
2496
2580
|
propertyValues={workspaceCreationPropertyValues}
|
|
@@ -2504,7 +2588,7 @@ function DatabaseTable({
|
|
|
2504
2588
|
New
|
|
2505
2589
|
</Button>
|
|
2506
2590
|
</WorkspaceSourceMenu>
|
|
2507
|
-
) :
|
|
2591
|
+
) : effectiveCanEdit ? (
|
|
2508
2592
|
<Button
|
|
2509
2593
|
type="button"
|
|
2510
2594
|
size="sm"
|
|
@@ -2582,7 +2666,7 @@ function DatabaseTable({
|
|
|
2582
2666
|
<BuilderSourceContinuationBar
|
|
2583
2667
|
key={builderSource.id}
|
|
2584
2668
|
source={builderSource}
|
|
2585
|
-
canEdit={
|
|
2669
|
+
canEdit={effectiveCanEdit}
|
|
2586
2670
|
pending={
|
|
2587
2671
|
sourcePendingOperations.refreshSourceId === builderSource.id
|
|
2588
2672
|
}
|
|
@@ -2607,6 +2691,7 @@ function DatabaseTable({
|
|
|
2607
2691
|
() => handleBuilderContinuationError(continuationKey),
|
|
2608
2692
|
builderSource.metadata.lastReadNextOffset,
|
|
2609
2693
|
() => handleBuilderContinuationSuccess(continuationKey),
|
|
2694
|
+
true,
|
|
2610
2695
|
);
|
|
2611
2696
|
}}
|
|
2612
2697
|
/>
|
|
@@ -2620,7 +2705,7 @@ function DatabaseTable({
|
|
|
2620
2705
|
databaseTitle={data?.database.title ?? document.title}
|
|
2621
2706
|
view={activeView}
|
|
2622
2707
|
properties={orderedProperties}
|
|
2623
|
-
canEdit={
|
|
2708
|
+
canEdit={effectiveCanEdit}
|
|
2624
2709
|
/>
|
|
2625
2710
|
) : activeView.type === "board" ? (
|
|
2626
2711
|
<DatabaseBoardView
|
|
@@ -2630,7 +2715,7 @@ function DatabaseTable({
|
|
|
2630
2715
|
items={visibleItems}
|
|
2631
2716
|
groupProperty={boardGroupProperty}
|
|
2632
2717
|
databaseDocumentId={document.id}
|
|
2633
|
-
canEdit={
|
|
2718
|
+
canEdit={effectiveCanEdit}
|
|
2634
2719
|
canCreateItems={!isWorkspaceCatalog}
|
|
2635
2720
|
isLoading={isDatabaseViewLoading}
|
|
2636
2721
|
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
@@ -2659,7 +2744,7 @@ function DatabaseTable({
|
|
|
2659
2744
|
groupableProperties={orderedProperties}
|
|
2660
2745
|
items={visibleItems}
|
|
2661
2746
|
databaseDocumentId={document.id}
|
|
2662
|
-
canEdit={
|
|
2747
|
+
canEdit={effectiveCanEdit}
|
|
2663
2748
|
canCreateItems={!isWorkspaceCatalog}
|
|
2664
2749
|
isLoading={isDatabaseViewLoading}
|
|
2665
2750
|
isCreating={isCreatingDatabaseItem}
|
|
@@ -2683,7 +2768,7 @@ function DatabaseTable({
|
|
|
2683
2768
|
groupableProperties={orderedProperties}
|
|
2684
2769
|
items={visibleItems}
|
|
2685
2770
|
databaseDocumentId={document.id}
|
|
2686
|
-
canEdit={
|
|
2771
|
+
canEdit={effectiveCanEdit}
|
|
2687
2772
|
canCreateItems={!isWorkspaceCatalog}
|
|
2688
2773
|
isLoading={isDatabaseViewLoading}
|
|
2689
2774
|
isCreating={isCreatingDatabaseItem}
|
|
@@ -2708,7 +2793,7 @@ function DatabaseTable({
|
|
|
2708
2793
|
properties={orderedProperties}
|
|
2709
2794
|
items={visibleItems}
|
|
2710
2795
|
databaseDocumentId={document.id}
|
|
2711
|
-
canEdit={
|
|
2796
|
+
canEdit={effectiveCanEdit}
|
|
2712
2797
|
canCreateItems={!isWorkspaceCatalog}
|
|
2713
2798
|
isLoading={isDatabaseViewLoading}
|
|
2714
2799
|
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
@@ -2736,7 +2821,7 @@ function DatabaseTable({
|
|
|
2736
2821
|
properties={orderedProperties}
|
|
2737
2822
|
items={visibleItems}
|
|
2738
2823
|
databaseDocumentId={document.id}
|
|
2739
|
-
canEdit={
|
|
2824
|
+
canEdit={effectiveCanEdit}
|
|
2740
2825
|
canCreateItems={!isWorkspaceCatalog}
|
|
2741
2826
|
isLoading={isDatabaseViewLoading}
|
|
2742
2827
|
isCreating={isCreatingDatabaseItem || setProperty.isPending}
|
|
@@ -2773,7 +2858,7 @@ function DatabaseTable({
|
|
|
2773
2858
|
source={source}
|
|
2774
2859
|
sources={sources}
|
|
2775
2860
|
databaseDocumentId={document.id}
|
|
2776
|
-
canEdit={
|
|
2861
|
+
canEdit={effectiveCanEdit}
|
|
2777
2862
|
workspaceCreationPropertyValues={workspaceCreationPropertyValues}
|
|
2778
2863
|
isLoading={isDatabaseViewLoading}
|
|
2779
2864
|
isCreating={isCreatingDatabaseItem}
|
|
@@ -2894,6 +2979,7 @@ function DatabaseTable({
|
|
|
2894
2979
|
sourceType: "builder-cms",
|
|
2895
2980
|
sourceName: model.displayName,
|
|
2896
2981
|
sourceTable: model.name,
|
|
2982
|
+
builderFieldPaths: model.fields.map((field) => field.name),
|
|
2897
2983
|
relationshipMode,
|
|
2898
2984
|
mode:
|
|
2899
2985
|
relationshipMode === "items"
|
|
@@ -3896,13 +3982,18 @@ export function databaseBulkScalarInputState(
|
|
|
3896
3982
|
type DuplicatedDatabaseItemResponse = {
|
|
3897
3983
|
items: ContentDatabaseResponse["items"];
|
|
3898
3984
|
duplicatedItemId?: ContentDatabaseResponse["duplicatedItemId"];
|
|
3985
|
+
duplicatedItems?: ContentDatabaseResponse["duplicatedItems"];
|
|
3899
3986
|
};
|
|
3900
3987
|
|
|
3901
3988
|
export function databaseDuplicatedItemFromResponse(
|
|
3902
3989
|
response: DuplicatedDatabaseItemResponse,
|
|
3903
3990
|
) {
|
|
3904
3991
|
return (
|
|
3905
|
-
response.
|
|
3992
|
+
response.duplicatedItems?.find(
|
|
3993
|
+
(item) => item.id === response.duplicatedItemId,
|
|
3994
|
+
) ??
|
|
3995
|
+
response.items.find((item) => item.id === response.duplicatedItemId) ??
|
|
3996
|
+
null
|
|
3906
3997
|
);
|
|
3907
3998
|
}
|
|
3908
3999
|
|
|
@@ -5697,7 +5788,7 @@ function DatabaseTableView({
|
|
|
5697
5788
|
) : null}
|
|
5698
5789
|
</div>
|
|
5699
5790
|
|
|
5700
|
-
{isLoading ? (
|
|
5791
|
+
{databaseTableShouldShowBlockingLoader(isLoading, items.length) ? (
|
|
5701
5792
|
<div className="flex h-16 items-center gap-2 border-t border-border px-2 text-sm text-muted-foreground">
|
|
5702
5793
|
<Spinner className="size-4" />
|
|
5703
5794
|
{dbText("loadingDatabase")}
|
|
@@ -5863,6 +5954,29 @@ function DatabaseTableView({
|
|
|
5863
5954
|
);
|
|
5864
5955
|
}
|
|
5865
5956
|
|
|
5957
|
+
export function databaseTableShouldShowBlockingLoader(
|
|
5958
|
+
isLoading: boolean,
|
|
5959
|
+
itemCount: number,
|
|
5960
|
+
) {
|
|
5961
|
+
return isLoading && itemCount === 0;
|
|
5962
|
+
}
|
|
5963
|
+
|
|
5964
|
+
export function databaseViewRequiresCompleteClientDataset(args: {
|
|
5965
|
+
viewType: ContentDatabaseViewType;
|
|
5966
|
+
activeConstraintCount: number;
|
|
5967
|
+
grouped: boolean;
|
|
5968
|
+
tableQueryMode?: ContentDatabaseResponse["tableQueryMode"];
|
|
5969
|
+
}) {
|
|
5970
|
+
return (
|
|
5971
|
+
(args.viewType === "table" && args.tableQueryMode === "client-required") ||
|
|
5972
|
+
(args.viewType !== "table" &&
|
|
5973
|
+
(args.activeConstraintCount > 0 ||
|
|
5974
|
+
args.grouped ||
|
|
5975
|
+
args.viewType === "calendar" ||
|
|
5976
|
+
args.viewType === "timeline"))
|
|
5977
|
+
);
|
|
5978
|
+
}
|
|
5979
|
+
|
|
5866
5980
|
function DatabaseActiveConstraintsBar({
|
|
5867
5981
|
documentId,
|
|
5868
5982
|
items,
|
|
@@ -7305,11 +7419,11 @@ function DatabaseSettingsPanelSheet({
|
|
|
7305
7419
|
onAttachBuilderSource: (
|
|
7306
7420
|
model: BuilderCmsModelSummary,
|
|
7307
7421
|
relationshipMode?: "items" | "details",
|
|
7308
|
-
) => Promise<
|
|
7422
|
+
) => Promise<ContentDatabaseSourceAttachmentResult>;
|
|
7309
7423
|
onFederateSource: (
|
|
7310
7424
|
candidate: PendingSourceCandidate,
|
|
7311
7425
|
join: ContentDatabaseSourceJoinRequest,
|
|
7312
|
-
) => Promise<
|
|
7426
|
+
) => Promise<ContentDatabaseSourceAttachmentResult>;
|
|
7313
7427
|
onChangeSourceRole: (
|
|
7314
7428
|
sourceId: string,
|
|
7315
7429
|
relationshipMode: "items" | "details",
|
|
@@ -7333,10 +7447,44 @@ function DatabaseSettingsPanelSheet({
|
|
|
7333
7447
|
onHideEmptyGroupsChange: (hideEmptyGroups: boolean) => void;
|
|
7334
7448
|
onGroupsCollapsedChange: (groupIds: string[], collapsed: boolean) => void;
|
|
7335
7449
|
}) {
|
|
7450
|
+
const queryClient = useQueryClient();
|
|
7336
7451
|
// Local drill-down path *within* the Source(s) panel. Kept here (not in the
|
|
7337
7452
|
// flat panel enum) because the levels are dynamic — space/model names aren't
|
|
7338
7453
|
// known at compile time. The sheet's back button pops this stack first.
|
|
7339
7454
|
const [sourceNavStack, setSourceNavStack] = useState<SourceNavStep[]>([]);
|
|
7455
|
+
const sourceNavTop = sourceNavStack[sourceNavStack.length - 1];
|
|
7456
|
+
const previewModel =
|
|
7457
|
+
sourceNavTop?.kind === "model" ? (sourceNavTop.model ?? null) : null;
|
|
7458
|
+
const previewFieldPaths = useMemo(
|
|
7459
|
+
() => previewModel?.fields.map((field) => field.name),
|
|
7460
|
+
[previewModel],
|
|
7461
|
+
);
|
|
7462
|
+
const previewAlreadyAttached = previewModel
|
|
7463
|
+
? Boolean(
|
|
7464
|
+
databaseAttachedBuilderSource(sources, source, {
|
|
7465
|
+
modelName: previewModel.name,
|
|
7466
|
+
}),
|
|
7467
|
+
)
|
|
7468
|
+
: false;
|
|
7469
|
+
const builderAttachPreview = useBuilderCmsAttachPreview({
|
|
7470
|
+
documentId,
|
|
7471
|
+
sourceTable: previewModel?.name ?? null,
|
|
7472
|
+
fieldPaths: previewFieldPaths,
|
|
7473
|
+
enabled:
|
|
7474
|
+
open &&
|
|
7475
|
+
panel === "source" &&
|
|
7476
|
+
canEdit &&
|
|
7477
|
+
Boolean(previewModel) &&
|
|
7478
|
+
!previewAlreadyAttached,
|
|
7479
|
+
});
|
|
7480
|
+
useEffect(() => {
|
|
7481
|
+
if (!sourceActionPending || !builderAttachPreview.data) return;
|
|
7482
|
+
writeBuilderAttachPreviewToCache(
|
|
7483
|
+
queryClient,
|
|
7484
|
+
documentId,
|
|
7485
|
+
builderAttachPreview.data,
|
|
7486
|
+
);
|
|
7487
|
+
}, [builderAttachPreview.data, documentId, queryClient, sourceActionPending]);
|
|
7340
7488
|
useEffect(() => {
|
|
7341
7489
|
// Always re-enter the Sources panel at its root, and don't retain a path
|
|
7342
7490
|
// across close/reopen.
|
|
@@ -7425,6 +7573,7 @@ function DatabaseSettingsPanelSheet({
|
|
|
7425
7573
|
onReviewBuilderUpdate={onReviewBuilderUpdate}
|
|
7426
7574
|
onSetBuilderLiveWrites={onSetBuilderLiveWrites}
|
|
7427
7575
|
sourceActionPending={sourceActionPending}
|
|
7576
|
+
builderAttachPreviewPending={builderAttachPreview.isFetching}
|
|
7428
7577
|
sourcePendingOperations={sourcePendingOperations}
|
|
7429
7578
|
/>
|
|
7430
7579
|
) : panel === "layout" ? (
|
|
@@ -7488,7 +7637,9 @@ function DatabaseSettingsMainPanel({
|
|
|
7488
7637
|
onPanelChange: (panel: DatabaseSettingsPanel) => void;
|
|
7489
7638
|
}) {
|
|
7490
7639
|
const groupLabel = activeView.groupByPropertyId ? "On" : "";
|
|
7491
|
-
const sourceBadgeCount =
|
|
7640
|
+
const sourceBadgeCount = databaseSourceChangeSetsAreComplete(source)
|
|
7641
|
+
? builderReviewableChangeSets(source).length
|
|
7642
|
+
: undefined;
|
|
7492
7643
|
return (
|
|
7493
7644
|
<div className="grid gap-3">
|
|
7494
7645
|
<div className="flex h-9 items-center gap-2 rounded-md border border-border bg-background px-2">
|
|
@@ -7550,6 +7701,23 @@ export function builderReviewableChangeSets(
|
|
|
7550
7701
|
);
|
|
7551
7702
|
}
|
|
7552
7703
|
|
|
7704
|
+
export function databaseActiveBuilderReview(args: {
|
|
7705
|
+
prepared: ContentDatabaseSourceReviewPayload | null;
|
|
7706
|
+
complete: ContentDatabaseSourceReviewPayload | null;
|
|
7707
|
+
page: ContentDatabaseSourceReviewPayload | null;
|
|
7708
|
+
open: boolean;
|
|
7709
|
+
}) {
|
|
7710
|
+
return (
|
|
7711
|
+
args.prepared ?? (args.open ? (args.complete ?? args.page) : args.page)
|
|
7712
|
+
);
|
|
7713
|
+
}
|
|
7714
|
+
|
|
7715
|
+
export function databaseSourceChangeSetsAreComplete(
|
|
7716
|
+
source: ContentDatabaseSource | null,
|
|
7717
|
+
) {
|
|
7718
|
+
return source?.projection?.changeSets !== "page";
|
|
7719
|
+
}
|
|
7720
|
+
|
|
7553
7721
|
function sourceReviewRiskRank(
|
|
7554
7722
|
risk: ContentDatabaseSourceReviewPayload["riskLevel"],
|
|
7555
7723
|
) {
|
|
@@ -7807,6 +7975,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
7807
7975
|
onReviewBuilderUpdate,
|
|
7808
7976
|
onSetBuilderLiveWrites,
|
|
7809
7977
|
sourceActionPending,
|
|
7978
|
+
builderAttachPreviewPending,
|
|
7810
7979
|
sourcePendingOperations,
|
|
7811
7980
|
}: {
|
|
7812
7981
|
source: ContentDatabaseSource | null;
|
|
@@ -7823,11 +7992,11 @@ function DatabaseSettingsSourcePanel({
|
|
|
7823
7992
|
onAttachBuilderSource: (
|
|
7824
7993
|
model: BuilderCmsModelSummary,
|
|
7825
7994
|
relationshipMode?: "items" | "details",
|
|
7826
|
-
) => Promise<
|
|
7995
|
+
) => Promise<ContentDatabaseSourceAttachmentResult>;
|
|
7827
7996
|
onFederateSource: (
|
|
7828
7997
|
candidate: PendingSourceCandidate,
|
|
7829
7998
|
join: ContentDatabaseSourceJoinRequest,
|
|
7830
|
-
) => Promise<
|
|
7999
|
+
) => Promise<ContentDatabaseSourceAttachmentResult>;
|
|
7831
8000
|
onChangeSourceRole: (
|
|
7832
8001
|
sourceId: string,
|
|
7833
8002
|
relationshipMode: "items" | "details",
|
|
@@ -7840,13 +8009,17 @@ function DatabaseSettingsSourcePanel({
|
|
|
7840
8009
|
onReviewBuilderUpdate: (sourceId: string) => void;
|
|
7841
8010
|
onSetBuilderLiveWrites: (settings: BuilderSourceWriteSettingsInput) => void;
|
|
7842
8011
|
sourceActionPending: boolean;
|
|
8012
|
+
builderAttachPreviewPending: boolean;
|
|
7843
8013
|
sourcePendingOperations: DatabaseSourcePendingOperations;
|
|
7844
8014
|
}) {
|
|
7845
8015
|
const { isCodeMode } = useCodeMode();
|
|
7846
8016
|
const navigate = useNavigate();
|
|
7847
8017
|
const builderSources = databaseAttachedBuilderSources(sources, source);
|
|
7848
8018
|
const builderStatus = useBuilderStatus();
|
|
8019
|
+
const builderAttachPending =
|
|
8020
|
+
sourceActionPending || builderAttachPreviewPending;
|
|
7849
8021
|
const builderConfigured = builderStatus.status?.configured === true;
|
|
8022
|
+
const builderModelsQuery = useBuilderCmsModels(builderConfigured);
|
|
7850
8023
|
const builderOrgName = builderStatus.status?.orgName ?? null;
|
|
7851
8024
|
// Real space name(s) from the Admin API, falling back to the generic org
|
|
7852
8025
|
// name (then a constant) so the drill-down never renders a blank label.
|
|
@@ -7873,11 +8046,15 @@ function DatabaseSettingsSourcePanel({
|
|
|
7873
8046
|
sources={sources}
|
|
7874
8047
|
builderConfigured={builderConfigured}
|
|
7875
8048
|
builderSpaceLabel={builderSpaceLabel}
|
|
7876
|
-
reviewableCount={
|
|
7877
|
-
(
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
8049
|
+
reviewableCount={
|
|
8050
|
+
builderSources.every(databaseSourceChangeSetsAreComplete)
|
|
8051
|
+
? builderSources.reduce(
|
|
8052
|
+
(total, candidate) =>
|
|
8053
|
+
total + builderReviewableChangeSets(candidate).length,
|
|
8054
|
+
0,
|
|
8055
|
+
)
|
|
8056
|
+
: undefined
|
|
8057
|
+
}
|
|
7881
8058
|
onOpenBuilder={(builderSource) =>
|
|
7882
8059
|
onNavPush(
|
|
7883
8060
|
builderSource
|
|
@@ -8003,6 +8180,11 @@ function DatabaseSettingsSourcePanel({
|
|
|
8003
8180
|
join,
|
|
8004
8181
|
)
|
|
8005
8182
|
: await onFederateSource(top.candidate, join);
|
|
8183
|
+
if ("responseProjection" in result) {
|
|
8184
|
+
throw new Error(
|
|
8185
|
+
"Detail-source attachment returned an item-source acknowledgement.",
|
|
8186
|
+
);
|
|
8187
|
+
}
|
|
8006
8188
|
const detailsSource = findDetailsSource(result, top.candidate);
|
|
8007
8189
|
onNavReplace(
|
|
8008
8190
|
detailsSource
|
|
@@ -8095,6 +8277,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
8095
8277
|
return (
|
|
8096
8278
|
<BuilderSpaceModelsView
|
|
8097
8279
|
attachedModelNames={databaseAttachedBuilderModelNames(sources, source)}
|
|
8280
|
+
modelsQuery={builderModelsQuery}
|
|
8098
8281
|
onOpenModel={(model) => {
|
|
8099
8282
|
const attached = databaseAttachedBuilderSource(sources, source, {
|
|
8100
8283
|
modelName: model.name,
|
|
@@ -8144,7 +8327,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
8144
8327
|
displayName: model.displayName,
|
|
8145
8328
|
}}
|
|
8146
8329
|
canEdit={canEdit}
|
|
8147
|
-
pending={
|
|
8330
|
+
pending={builderAttachPending}
|
|
8148
8331
|
onAddDetails={() =>
|
|
8149
8332
|
onNavPush({
|
|
8150
8333
|
kind: "keyConfirm",
|
|
@@ -8166,7 +8349,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
8166
8349
|
<Button
|
|
8167
8350
|
type="button"
|
|
8168
8351
|
size="sm"
|
|
8169
|
-
disabled={!canEdit ||
|
|
8352
|
+
disabled={!canEdit || builderAttachPending}
|
|
8170
8353
|
onClick={async () => {
|
|
8171
8354
|
try {
|
|
8172
8355
|
await onAttachBuilderSource(model);
|
|
@@ -8181,7 +8364,7 @@ function DatabaseSettingsSourcePanel({
|
|
|
8181
8364
|
}
|
|
8182
8365
|
}}
|
|
8183
8366
|
>
|
|
8184
|
-
{
|
|
8367
|
+
{builderAttachPending ? (
|
|
8185
8368
|
<Spinner className="mr-1.5 size-3.5" />
|
|
8186
8369
|
) : (
|
|
8187
8370
|
<IconPlugConnected className="mr-1.5 size-3.5" />
|
|
@@ -8195,6 +8378,8 @@ function DatabaseSettingsSourcePanel({
|
|
|
8195
8378
|
}
|
|
8196
8379
|
|
|
8197
8380
|
const selectedSource = selectedBuilderSource;
|
|
8381
|
+
const selectedSourceChangeSetsComplete =
|
|
8382
|
+
databaseSourceChangeSetsAreComplete(selectedSource);
|
|
8198
8383
|
const reviewableBuilderChangeSets =
|
|
8199
8384
|
builderReviewableChangeSets(selectedSource);
|
|
8200
8385
|
const outboundChangeSets = reviewableBuilderChangeSets;
|
|
@@ -8408,11 +8593,13 @@ function DatabaseSettingsSourcePanel({
|
|
|
8408
8593
|
<div className="flex items-center justify-between gap-3">
|
|
8409
8594
|
<div className="min-w-0">
|
|
8410
8595
|
<div className="text-sm font-medium">
|
|
8411
|
-
{
|
|
8596
|
+
{selectedSourceChangeSetsComplete &&
|
|
8597
|
+
conflictChangeSets.length > 0
|
|
8412
8598
|
? `${conflictChangeSets.length} change${
|
|
8413
8599
|
conflictChangeSets.length === 1 ? "" : "s"
|
|
8414
8600
|
} need review`
|
|
8415
|
-
:
|
|
8601
|
+
: selectedSourceChangeSetsComplete &&
|
|
8602
|
+
reviewableBuilderChangeSets.length > 0
|
|
8416
8603
|
? `${reviewableBuilderChangeSets.length} change${
|
|
8417
8604
|
reviewableBuilderChangeSets.length === 1 ? "" : "s"
|
|
8418
8605
|
} ready to push`
|
|
@@ -8562,7 +8749,7 @@ function SourcesListView({
|
|
|
8562
8749
|
sources: ContentDatabaseSource[];
|
|
8563
8750
|
builderConfigured: boolean;
|
|
8564
8751
|
builderSpaceLabel: string | null;
|
|
8565
|
-
reviewableCount
|
|
8752
|
+
reviewableCount?: number;
|
|
8566
8753
|
onOpenBuilder: (source?: ContentDatabaseSource) => void;
|
|
8567
8754
|
onOpenNotion: () => void;
|
|
8568
8755
|
onOpenLocalFolder: () => void;
|
|
@@ -9789,12 +9976,13 @@ function SourceDetailsFieldPicker({
|
|
|
9789
9976
|
// is marked; selecting a row opens that model's leaf.
|
|
9790
9977
|
function BuilderSpaceModelsView({
|
|
9791
9978
|
attachedModelNames,
|
|
9979
|
+
modelsQuery,
|
|
9792
9980
|
onOpenModel,
|
|
9793
9981
|
}: {
|
|
9794
9982
|
attachedModelNames: string[];
|
|
9983
|
+
modelsQuery: ReturnType<typeof useBuilderCmsModels>;
|
|
9795
9984
|
onOpenModel: (model: BuilderCmsModelSummary) => void;
|
|
9796
9985
|
}) {
|
|
9797
|
-
const modelsQuery = useBuilderCmsModels(true);
|
|
9798
9986
|
const models = modelsQuery.data?.models ?? [];
|
|
9799
9987
|
const [query, setQuery] = useState("");
|
|
9800
9988
|
|
|
@@ -16362,37 +16550,11 @@ export function applyDatabaseView(
|
|
|
16362
16550
|
sorts: DatabaseSort[],
|
|
16363
16551
|
filterMode: DatabaseFilterMode = "and",
|
|
16364
16552
|
) {
|
|
16365
|
-
|
|
16366
|
-
|
|
16367
|
-
|
|
16368
|
-
|
|
16369
|
-
|
|
16370
|
-
: items;
|
|
16371
|
-
const activeFilters = filters.filter(isActiveFilter);
|
|
16372
|
-
const filtered = activeFilters.length
|
|
16373
|
-
? searched.filter((item) =>
|
|
16374
|
-
databaseItemMatchesFilterTree(
|
|
16375
|
-
item,
|
|
16376
|
-
properties,
|
|
16377
|
-
activeFilters,
|
|
16378
|
-
filterMode,
|
|
16379
|
-
),
|
|
16380
|
-
)
|
|
16381
|
-
: searched;
|
|
16382
|
-
|
|
16383
|
-
if (sorts.length === 0) return filtered;
|
|
16384
|
-
|
|
16385
|
-
return [...filtered].sort((a, b) => {
|
|
16386
|
-
for (const sort of sorts) {
|
|
16387
|
-
const comparison = compareDatabaseSortValues(
|
|
16388
|
-
databaseItemSortValue(a, properties, sort.key),
|
|
16389
|
-
databaseItemSortValue(b, properties, sort.key),
|
|
16390
|
-
);
|
|
16391
|
-
if (comparison !== 0) {
|
|
16392
|
-
return sort.direction === "asc" ? comparison : -comparison;
|
|
16393
|
-
}
|
|
16394
|
-
}
|
|
16395
|
-
return 0;
|
|
16553
|
+
return applyContentDatabaseTableQuery(items, properties, {
|
|
16554
|
+
search: searchQuery,
|
|
16555
|
+
filters,
|
|
16556
|
+
sorts,
|
|
16557
|
+
filterMode,
|
|
16396
16558
|
});
|
|
16397
16559
|
}
|
|
16398
16560
|
|