@firecms/core 3.0.0-canary.51 → 3.0.0-canary.53
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/dist/components/{EntityCollectionTable/internal → common}/default_entity_actions.d.ts +1 -1
- package/dist/components/common/index.d.ts +1 -0
- package/dist/index.es.js +2802 -2847
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +5 -5
- package/dist/index.umd.js.map +1 -1
- package/dist/types/navigation.d.ts +2 -2
- package/dist/util/icon_synonyms.d.ts +0 -94
- package/dist/util/resolutions.d.ts +8 -4
- package/package.json +16 -16
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +526 -531
- package/src/components/{EntityCollectionTable/internal → common}/default_entity_actions.tsx +2 -2
- package/src/components/common/index.ts +1 -0
- package/src/components/common/useColumnsIds.tsx +10 -2
- package/src/core/EntitySidePanel.tsx +1 -1
- package/src/core/FireCMS.tsx +0 -1
- package/src/form/EntityForm.tsx +1 -2
- package/src/form/field_bindings/SelectFieldBinding.tsx +4 -1
- package/src/hooks/useBuildNavigationController.tsx +0 -1
- package/src/hooks/useResolvedNavigationFrom.tsx +1 -1
- package/src/internal/useBuildSideEntityController.tsx +3 -2
- package/src/preview/components/EnumValuesChip.tsx +1 -1
- package/src/preview/property_previews/NumberPropertyPreview.tsx +1 -0
- package/src/types/navigation.ts +1 -2
- package/src/util/enums.ts +1 -1
- package/src/util/icon_synonyms.ts +0 -94
- package/src/util/resolutions.ts +26 -7
|
@@ -66,11 +66,7 @@ import {
|
|
|
66
66
|
} from "../common";
|
|
67
67
|
import { PopupFormField } from "../EntityCollectionTable/internal/popup_field/PopupFormField";
|
|
68
68
|
import { GetPropertyForProps } from "../EntityCollectionTable/EntityCollectionTableProps";
|
|
69
|
-
import {
|
|
70
|
-
copyEntityAction,
|
|
71
|
-
deleteEntityAction,
|
|
72
|
-
editEntityAction
|
|
73
|
-
} from "../EntityCollectionTable/internal/default_entity_actions";
|
|
69
|
+
import { copyEntityAction, deleteEntityAction, editEntityAction } from "../common/default_entity_actions";
|
|
74
70
|
import { DeleteEntityDialog } from "../DeleteEntityDialog";
|
|
75
71
|
import { useAnalyticsController } from "../../hooks/useAnalyticsController";
|
|
76
72
|
import { useSelectionController } from "./useSelectionController";
|
|
@@ -134,560 +130,559 @@ export const EntityCollectionView = React.memo(
|
|
|
134
130
|
}: EntityCollectionViewProps<M>
|
|
135
131
|
) {
|
|
136
132
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
133
|
+
const context = useFireCMSContext();
|
|
134
|
+
const fullPath = fullPathProp ?? collectionProp.path;
|
|
135
|
+
const dataSource = useDataSource(collectionProp);
|
|
136
|
+
const navigation = useNavigationController();
|
|
137
|
+
const sideEntityController = useSideEntityController();
|
|
138
|
+
const authController = useAuthController();
|
|
139
|
+
const userConfigPersistence = useUserConfigurationPersistence();
|
|
140
|
+
const analyticsController = useAnalyticsController();
|
|
141
|
+
const customizationController = useCustomizationController();
|
|
142
|
+
|
|
143
|
+
const containerRef = React.useRef<HTMLDivElement>(null);
|
|
144
|
+
|
|
145
|
+
const collection = useMemo(() => {
|
|
146
|
+
const userOverride = userConfigPersistence?.getCollectionConfig<M>(fullPath);
|
|
147
|
+
return (userOverride ? mergeDeep(collectionProp, userOverride) : collectionProp) as EntityCollection<M>;
|
|
148
|
+
}, [collectionProp, fullPath, userConfigPersistence?.getCollectionConfig]);
|
|
149
|
+
|
|
150
|
+
const collectionRef = React.useRef(collection);
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
collectionRef.current = collection;
|
|
153
|
+
}, [collection]);
|
|
154
|
+
|
|
155
|
+
const canCreateEntities = canCreateEntity(collection, authController, fullPath, null);
|
|
156
|
+
const [selectedNavigationEntity, setSelectedNavigationEntity] = useState<Entity<M> | undefined>(undefined);
|
|
157
|
+
const [deleteEntityClicked, setDeleteEntityClicked] = React.useState<Entity<M> | Entity<M>[] | undefined>(undefined);
|
|
158
|
+
|
|
159
|
+
const [lastDeleteTimestamp, setLastDeleteTimestamp] = React.useState<number>(0);
|
|
160
|
+
|
|
161
|
+
// number of entities in the collection
|
|
162
|
+
const [docsCount, setDocsCount] = useState<number>(0);
|
|
163
|
+
|
|
164
|
+
const unselectNavigatedEntity = useCallback(() => {
|
|
165
|
+
const currentSelection = selectedNavigationEntity;
|
|
166
|
+
setTimeout(() => {
|
|
167
|
+
if (currentSelection === selectedNavigationEntity)
|
|
168
|
+
setSelectedNavigationEntity(undefined);
|
|
169
|
+
}, 2400);
|
|
170
|
+
}, [selectedNavigationEntity]);
|
|
171
|
+
|
|
172
|
+
const checkInlineEditing = useCallback((entity?: Entity<any>): boolean => {
|
|
173
|
+
const collection = collectionRef.current;
|
|
174
|
+
if (!canEditEntity(collection, authController, fullPath, entity ?? null)) {
|
|
175
|
+
return false;
|
|
176
|
+
}
|
|
177
|
+
return collection.inlineEditing === undefined || collection.inlineEditing;
|
|
178
|
+
}, [authController, fullPath]);
|
|
154
179
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
collectionRef.current = collection;
|
|
158
|
-
}, [collection]);
|
|
159
|
-
|
|
160
|
-
const canCreateEntities = canCreateEntity(collection, authController, fullPath, null);
|
|
161
|
-
const [selectedNavigationEntity, setSelectedNavigationEntity] = useState<Entity<M> | undefined>(undefined);
|
|
162
|
-
const [deleteEntityClicked, setDeleteEntityClicked] = React.useState<Entity<M> | Entity<M>[] | undefined>(undefined);
|
|
163
|
-
|
|
164
|
-
const [lastDeleteTimestamp, setLastDeleteTimestamp] = React.useState<number>(0);
|
|
165
|
-
|
|
166
|
-
// number of entities in the collection
|
|
167
|
-
const [docsCount, setDocsCount] = useState<number>(0);
|
|
168
|
-
|
|
169
|
-
const unselectNavigatedEntity = useCallback(() => {
|
|
170
|
-
const currentSelection = selectedNavigationEntity;
|
|
171
|
-
setTimeout(() => {
|
|
172
|
-
if (currentSelection === selectedNavigationEntity)
|
|
173
|
-
setSelectedNavigationEntity(undefined);
|
|
174
|
-
}, 2400);
|
|
175
|
-
}, [selectedNavigationEntity]);
|
|
176
|
-
|
|
177
|
-
const checkInlineEditing = useCallback((entity?: Entity<any>): boolean => {
|
|
178
|
-
const collection = collectionRef.current;
|
|
179
|
-
if (!canEditEntity(collection, authController, fullPath, entity ?? null)) {
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
return collection.inlineEditing === undefined || collection.inlineEditing;
|
|
183
|
-
}, [authController, fullPath]);
|
|
180
|
+
const selectionEnabled = collection.selectionEnabled === undefined || collection.selectionEnabled;
|
|
181
|
+
const hoverRow = !checkInlineEditing();
|
|
184
182
|
|
|
185
|
-
|
|
186
|
-
const hoverRow = !checkInlineEditing();
|
|
183
|
+
const [popOverOpen, setPopOverOpen] = useState(false);
|
|
187
184
|
|
|
188
|
-
|
|
185
|
+
const selectionController = useSelectionController<M>();
|
|
186
|
+
const usedSelectionController = collection.selectionController ?? selectionController;
|
|
187
|
+
const {
|
|
188
|
+
selectedEntities,
|
|
189
|
+
isEntitySelected,
|
|
190
|
+
setSelectedEntities
|
|
191
|
+
} = usedSelectionController;
|
|
189
192
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
selectedEntities,
|
|
194
|
-
isEntitySelected,
|
|
195
|
-
setSelectedEntities
|
|
196
|
-
} = usedSelectionController;
|
|
193
|
+
useEffect(() => {
|
|
194
|
+
setDeleteEntityClicked(undefined);
|
|
195
|
+
}, [selectedEntities]);
|
|
197
196
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}, [selectedEntities]);
|
|
201
|
-
|
|
202
|
-
const tableController = useDataSourceEntityCollectionTableController<M>({
|
|
203
|
-
fullPath,
|
|
204
|
-
collection,
|
|
205
|
-
lastDeleteTimestamp
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
const tableKey = React.useRef<string>(Math.random().toString(36));
|
|
209
|
-
const popupCell = tableController.popupCell;
|
|
210
|
-
|
|
211
|
-
const onPopupClose = useCallback(() => {
|
|
212
|
-
tableController.setPopupCell?.(undefined);
|
|
213
|
-
}, [tableController.setPopupCell]);
|
|
214
|
-
|
|
215
|
-
const onEntityClick = useCallback((clickedEntity: Entity<M>) => {
|
|
216
|
-
console.log("Entity clicked", clickedEntity)
|
|
217
|
-
const collection = collectionRef.current;
|
|
218
|
-
setSelectedNavigationEntity(clickedEntity);
|
|
219
|
-
analyticsController.onAnalyticsEvent?.("edit_entity_clicked", {
|
|
220
|
-
path: clickedEntity.path,
|
|
221
|
-
entityId: clickedEntity.id
|
|
222
|
-
});
|
|
223
|
-
return sideEntityController.open({
|
|
224
|
-
entityId: clickedEntity.id,
|
|
225
|
-
path: clickedEntity.path,
|
|
197
|
+
const tableController = useDataSourceEntityCollectionTableController<M>({
|
|
198
|
+
fullPath,
|
|
226
199
|
collection,
|
|
227
|
-
|
|
228
|
-
onClose: unselectNavigatedEntity,
|
|
200
|
+
lastDeleteTimestamp
|
|
229
201
|
});
|
|
230
|
-
}, [unselectNavigatedEntity, sideEntityController]);
|
|
231
202
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
203
|
+
const tableKey = React.useRef<string>(Math.random().toString(36));
|
|
204
|
+
const popupCell = tableController.popupCell;
|
|
205
|
+
|
|
206
|
+
const onPopupClose = useCallback(() => {
|
|
207
|
+
tableController.setPopupCell?.(undefined);
|
|
208
|
+
}, [tableController.setPopupCell]);
|
|
209
|
+
|
|
210
|
+
const onEntityClick = useCallback((clickedEntity: Entity<M>) => {
|
|
211
|
+
console.log("Entity clicked", clickedEntity)
|
|
212
|
+
const collection = collectionRef.current;
|
|
213
|
+
setSelectedNavigationEntity(clickedEntity);
|
|
214
|
+
analyticsController.onAnalyticsEvent?.("edit_entity_clicked", {
|
|
215
|
+
path: clickedEntity.path,
|
|
216
|
+
entityId: clickedEntity.id
|
|
217
|
+
});
|
|
218
|
+
return sideEntityController.open({
|
|
219
|
+
entityId: clickedEntity.id,
|
|
220
|
+
path: clickedEntity.path,
|
|
221
|
+
collection,
|
|
222
|
+
updateUrl: true,
|
|
223
|
+
onClose: unselectNavigatedEntity,
|
|
224
|
+
});
|
|
225
|
+
}, [unselectNavigatedEntity, sideEntityController]);
|
|
226
|
+
|
|
227
|
+
const onNewClick = useCallback(() => {
|
|
228
|
+
|
|
229
|
+
const collection = collectionRef.current;
|
|
230
|
+
analyticsController.onAnalyticsEvent?.("new_entity_click", {
|
|
231
|
+
path: fullPath
|
|
232
|
+
});
|
|
233
|
+
sideEntityController.open({
|
|
234
|
+
path: fullPath,
|
|
235
|
+
collection,
|
|
236
|
+
updateUrl: true,
|
|
237
|
+
onClose: unselectNavigatedEntity,
|
|
238
|
+
});
|
|
239
|
+
}, [fullPath, sideEntityController]);
|
|
240
|
+
|
|
241
|
+
const onMultipleDeleteClick = () => {
|
|
242
|
+
analyticsController.onAnalyticsEvent?.("multiple_delete_dialog_open", {
|
|
243
|
+
path: fullPath
|
|
244
|
+
});
|
|
245
|
+
setDeleteEntityClicked(selectedEntities);
|
|
246
|
+
};
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
const internalOnEntityDelete = (_path: string, entity: Entity<M>) => {
|
|
249
|
+
analyticsController.onAnalyticsEvent?.("single_entity_deleted", {
|
|
250
|
+
path: fullPath
|
|
251
|
+
});
|
|
252
|
+
setSelectedEntities((selectedEntities) => selectedEntities.filter((e) => e.id !== entity.id));
|
|
253
|
+
setLastDeleteTimestamp(Date.now());
|
|
254
|
+
};
|
|
252
255
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
const internalOnMultipleEntitiesDelete = (_path: string, entities: Entity<M>[]) => {
|
|
257
|
+
analyticsController.onAnalyticsEvent?.("multiple_entities_deleted", {
|
|
258
|
+
path: fullPath
|
|
259
|
+
});
|
|
260
|
+
setSelectedEntities([]);
|
|
261
|
+
setDeleteEntityClicked(undefined);
|
|
262
|
+
setLastDeleteTimestamp(Date.now());
|
|
263
|
+
};
|
|
260
264
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
setDeleteEntityClicked(undefined);
|
|
267
|
-
setLastDeleteTimestamp(Date.now());
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
let AddColumnComponent: React.ComponentType<{
|
|
271
|
-
fullPath: string,
|
|
272
|
-
parentCollectionIds: string[],
|
|
273
|
-
collection: EntityCollection;
|
|
274
|
-
}> | undefined
|
|
275
|
-
|
|
276
|
-
// we are only using the first plugin that implements this
|
|
277
|
-
if (customizationController?.plugins) {
|
|
278
|
-
AddColumnComponent = customizationController.plugins.find(plugin => plugin.collectionView?.AddColumnComponent)?.collectionView?.AddColumnComponent;
|
|
279
|
-
}
|
|
265
|
+
let AddColumnComponent: React.ComponentType<{
|
|
266
|
+
fullPath: string,
|
|
267
|
+
parentCollectionIds: string[],
|
|
268
|
+
collection: EntityCollection;
|
|
269
|
+
}> | undefined
|
|
280
270
|
|
|
281
|
-
|
|
282
|
-
if (
|
|
283
|
-
|
|
284
|
-
const updatedConfig = mergeDeep(currentStoredConfig, partialCollection);
|
|
285
|
-
userConfigPersistence.onCollectionModified(path, updatedConfig);
|
|
271
|
+
// we are only using the first plugin that implements this
|
|
272
|
+
if (customizationController?.plugins) {
|
|
273
|
+
AddColumnComponent = customizationController.plugins.find(plugin => plugin.collectionView?.AddColumnComponent)?.collectionView?.AddColumnComponent;
|
|
286
274
|
}
|
|
287
|
-
}, [userConfigPersistence]);
|
|
288
|
-
|
|
289
|
-
const onColumnResize = useCallback(({
|
|
290
|
-
width,
|
|
291
|
-
key
|
|
292
|
-
}: OnColumnResizeParams) => {
|
|
293
|
-
|
|
294
|
-
const collection = collectionRef.current;
|
|
295
|
-
// Only for property columns
|
|
296
|
-
if (!getPropertyInPath(collection.properties, key)) return;
|
|
297
|
-
const localCollection = buildPropertyWidthOverwrite(key, width);
|
|
298
|
-
onCollectionModifiedForUser(fullPath, localCollection);
|
|
299
|
-
}, [onCollectionModifiedForUser, fullPath]);
|
|
300
|
-
|
|
301
|
-
const onSizeChanged = useCallback((size: CollectionSize) => {
|
|
302
|
-
if (userConfigPersistence)
|
|
303
|
-
onCollectionModifiedForUser(fullPath, { defaultSize: size })
|
|
304
|
-
}, [onCollectionModifiedForUser, fullPath, userConfigPersistence]);
|
|
305
|
-
|
|
306
|
-
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
307
|
-
|
|
308
|
-
const uniqueFieldValidator: UniqueFieldValidator = useCallback(
|
|
309
|
-
({
|
|
310
|
-
name,
|
|
311
|
-
value,
|
|
312
|
-
property,
|
|
313
|
-
entityId
|
|
314
|
-
}) => dataSource.checkUniqueField(fullPath, name, value, entityId),
|
|
315
|
-
[fullPath]);
|
|
316
|
-
|
|
317
|
-
const onValueChange: OnCellValueChange<any, any> = ({
|
|
318
|
-
value,
|
|
319
|
-
propertyKey,
|
|
320
|
-
onValueUpdated,
|
|
321
|
-
setError,
|
|
322
|
-
data: entity,
|
|
323
|
-
}) => {
|
|
324
|
-
|
|
325
|
-
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
326
|
-
|
|
327
|
-
const saveProps: SaveEntityProps = {
|
|
328
|
-
path: fullPath,
|
|
329
|
-
entityId: entity.id,
|
|
330
|
-
values: updatedValues,
|
|
331
|
-
previousValues: entity.values,
|
|
332
|
-
collection,
|
|
333
|
-
status: "existing"
|
|
334
|
-
};
|
|
335
275
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
onSaveSuccess: () => {
|
|
342
|
-
setError(undefined);
|
|
343
|
-
onValueUpdated();
|
|
344
|
-
},
|
|
345
|
-
onSaveFailure: (e: Error) => {
|
|
346
|
-
console.error("Save failure");
|
|
347
|
-
console.error(e);
|
|
348
|
-
setError(e);
|
|
276
|
+
const onCollectionModifiedForUser = useCallback((path: string, partialCollection: PartialEntityCollection<M>) => {
|
|
277
|
+
if (userConfigPersistence) {
|
|
278
|
+
const currentStoredConfig = userConfigPersistence.getCollectionConfig(path);
|
|
279
|
+
const updatedConfig = mergeDeep(currentStoredConfig, partialCollection);
|
|
280
|
+
userConfigPersistence.onCollectionModified(path, updatedConfig);
|
|
349
281
|
}
|
|
350
|
-
});
|
|
282
|
+
}, [userConfigPersistence]);
|
|
283
|
+
|
|
284
|
+
const onColumnResize = useCallback(({
|
|
285
|
+
width,
|
|
286
|
+
key
|
|
287
|
+
}: OnColumnResizeParams) => {
|
|
288
|
+
|
|
289
|
+
const collection = collectionRef.current;
|
|
290
|
+
// Only for property columns
|
|
291
|
+
if (!getPropertyInPath(collection.properties, key)) return;
|
|
292
|
+
const localCollection = buildPropertyWidthOverwrite(key, width);
|
|
293
|
+
onCollectionModifiedForUser(fullPath, localCollection);
|
|
294
|
+
}, [onCollectionModifiedForUser, fullPath]);
|
|
295
|
+
|
|
296
|
+
const onSizeChanged = useCallback((size: CollectionSize) => {
|
|
297
|
+
if (userConfigPersistence)
|
|
298
|
+
onCollectionModifiedForUser(fullPath, { defaultSize: size })
|
|
299
|
+
}, [onCollectionModifiedForUser, fullPath, userConfigPersistence]);
|
|
300
|
+
|
|
301
|
+
const createEnabled = canCreateEntity(collection, authController, fullPath, null);
|
|
302
|
+
|
|
303
|
+
const uniqueFieldValidator: UniqueFieldValidator = useCallback(
|
|
304
|
+
({
|
|
305
|
+
name,
|
|
306
|
+
value,
|
|
307
|
+
property,
|
|
308
|
+
entityId
|
|
309
|
+
}) => dataSource.checkUniqueField(fullPath, name, value, entityId),
|
|
310
|
+
[fullPath]);
|
|
311
|
+
|
|
312
|
+
const onValueChange: OnCellValueChange<any, any> = ({
|
|
313
|
+
value,
|
|
314
|
+
propertyKey,
|
|
315
|
+
onValueUpdated,
|
|
316
|
+
setError,
|
|
317
|
+
data: entity,
|
|
318
|
+
}) => {
|
|
319
|
+
|
|
320
|
+
const updatedValues = setIn({ ...entity.values }, propertyKey, value);
|
|
321
|
+
|
|
322
|
+
const saveProps: SaveEntityProps = {
|
|
323
|
+
path: fullPath,
|
|
324
|
+
entityId: entity.id,
|
|
325
|
+
values: updatedValues,
|
|
326
|
+
previousValues: entity.values,
|
|
327
|
+
collection,
|
|
328
|
+
status: "existing"
|
|
329
|
+
};
|
|
351
330
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
// we might not find the property in the collection if combining property builders and map spread
|
|
368
|
-
if (!propertyOrBuilder) {
|
|
369
|
-
// these 2 properties are coming from the resolved collection with default values
|
|
370
|
-
propertyOrBuilder = getPropertyInPath<M>(resolvedCollection.properties, propertyKey);
|
|
371
|
-
}
|
|
331
|
+
return saveEntityWithCallbacks({
|
|
332
|
+
...saveProps,
|
|
333
|
+
collection,
|
|
334
|
+
dataSource,
|
|
335
|
+
context,
|
|
336
|
+
onSaveSuccess: () => {
|
|
337
|
+
setError(undefined);
|
|
338
|
+
onValueUpdated();
|
|
339
|
+
},
|
|
340
|
+
onSaveFailure: (e: Error) => {
|
|
341
|
+
console.error("Save failure");
|
|
342
|
+
console.error(e);
|
|
343
|
+
setError(e);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
372
346
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const resolvedFullPath = navigation.resolveAliasesFrom(fullPath);
|
|
350
|
+
const resolvedCollection = useMemo(() => resolveCollection<M>({
|
|
351
|
+
collection,
|
|
376
352
|
path: fullPath,
|
|
377
|
-
values: entity.values,
|
|
378
|
-
entityId: entity.id,
|
|
379
353
|
fields: customizationController.propertyConfigs
|
|
380
|
-
});
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
<Button color={"primary"}
|
|
394
|
-
variant={"outlined"}
|
|
395
|
-
startIcon={<KeyboardTabIcon size={"small"}/>}
|
|
396
|
-
onClick={(event: any) => {
|
|
397
|
-
event.stopPropagation();
|
|
398
|
-
sideEntityController.open({
|
|
399
|
-
path: fullPath,
|
|
400
|
-
entityId: entity.id,
|
|
401
|
-
selectedSubPath: subcollection.id ?? subcollection.path,
|
|
402
|
-
collection,
|
|
403
|
-
updateUrl: true,
|
|
404
|
-
});
|
|
405
|
-
}}>
|
|
406
|
-
{subcollection.name}
|
|
407
|
-
</Button>
|
|
408
|
-
)
|
|
409
|
-
};
|
|
410
|
-
}) ?? [];
|
|
411
|
-
|
|
412
|
-
const collectionGroupParentCollections: AdditionalFieldDelegate<M, any>[] = collection.collectionGroup
|
|
413
|
-
? [{
|
|
414
|
-
key: COLLECTION_GROUP_PARENT_ID,
|
|
415
|
-
name: "Parent entities",
|
|
416
|
-
width: 260,
|
|
417
|
-
dependencies: [],
|
|
418
|
-
Builder: ({ entity }) => {
|
|
419
|
-
const collectionsWithPath = navigation.getParentReferencesFromPath(entity.path);
|
|
420
|
-
return (
|
|
421
|
-
<>
|
|
422
|
-
{collectionsWithPath.map((reference) => {
|
|
423
|
-
return (
|
|
424
|
-
<ReferencePreview
|
|
425
|
-
key={reference.path + "/" + reference.id}
|
|
426
|
-
reference={reference}
|
|
427
|
-
size={"tiny"}/>
|
|
428
|
-
);
|
|
429
|
-
})}
|
|
430
|
-
</>
|
|
431
|
-
);
|
|
432
|
-
}
|
|
433
|
-
}]
|
|
434
|
-
: [];
|
|
435
|
-
|
|
436
|
-
return [
|
|
437
|
-
...(collection.additionalFields ?? []),
|
|
438
|
-
...subcollectionColumns,
|
|
439
|
-
...collectionGroupParentCollections
|
|
440
|
-
];
|
|
441
|
-
}, [collection, fullPath, sideEntityController]);
|
|
442
|
-
|
|
443
|
-
const updateLastDeleteTimestamp = useCallback(() => {
|
|
444
|
-
setLastDeleteTimestamp(Date.now());
|
|
445
|
-
}, []);
|
|
446
|
-
|
|
447
|
-
const largeLayout = useLargeLayout();
|
|
448
|
-
|
|
449
|
-
const getActionsForEntity = ({
|
|
450
|
-
entity,
|
|
451
|
-
customEntityActions
|
|
452
|
-
}: {
|
|
453
|
-
entity?: Entity<M>,
|
|
454
|
-
customEntityActions?: EntityAction[]
|
|
455
|
-
}): EntityAction[] => {
|
|
456
|
-
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
457
|
-
const actions: EntityAction[] = [editEntityAction];
|
|
458
|
-
if (createEnabled)
|
|
459
|
-
actions.push(copyEntityAction);
|
|
460
|
-
if (deleteEnabled)
|
|
461
|
-
actions.push(deleteEntityAction);
|
|
462
|
-
if (customEntityActions)
|
|
463
|
-
actions.push(...customEntityActions);
|
|
464
|
-
return actions;
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
const getIdColumnWidth = () => {
|
|
468
|
-
const entityActions = getActionsForEntity({});
|
|
469
|
-
const collapsedActions = entityActions.filter(a => a.collapsed !== false);
|
|
470
|
-
const uncollapsedActions = entityActions.filter(a => a.collapsed === false);
|
|
471
|
-
const actionsWidth = uncollapsedActions.length * (largeLayout ? 40 : 30);
|
|
472
|
-
return (largeLayout ? (80 + actionsWidth) : (70 + actionsWidth)) + (collapsedActions.length > 0 ? (largeLayout ? 40 : 30) : 0);
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
const tableRowActionsBuilder = ({
|
|
476
|
-
entity,
|
|
477
|
-
size,
|
|
478
|
-
width,
|
|
479
|
-
frozen
|
|
480
|
-
}: {
|
|
481
|
-
entity: Entity<any>,
|
|
482
|
-
size: CollectionSize,
|
|
483
|
-
width: number,
|
|
484
|
-
frozen?: boolean
|
|
485
|
-
}) => {
|
|
486
|
-
|
|
487
|
-
const isSelected = isEntitySelected(entity);
|
|
488
|
-
|
|
489
|
-
const actions = getActionsForEntity({
|
|
490
|
-
entity,
|
|
491
|
-
customEntityActions: collection.entityActions
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
return (
|
|
495
|
-
<EntityCollectionRowActions
|
|
496
|
-
entity={entity}
|
|
497
|
-
width={width}
|
|
498
|
-
frozen={frozen}
|
|
499
|
-
isSelected={isSelected}
|
|
500
|
-
selectionEnabled={selectionEnabled}
|
|
501
|
-
size={size}
|
|
502
|
-
highlightEntity={setSelectedNavigationEntity}
|
|
503
|
-
unhighlightEntity={unselectNavigatedEntity}
|
|
504
|
-
collection={collection}
|
|
505
|
-
fullPath={fullPath}
|
|
506
|
-
actions={actions}
|
|
507
|
-
hideId={collection?.hideIdFromCollection}
|
|
508
|
-
onCollectionChange={updateLastDeleteTimestamp}
|
|
509
|
-
selectionController={usedSelectionController}
|
|
510
|
-
/>
|
|
511
|
-
);
|
|
354
|
+
}), [collection, fullPath]);
|
|
355
|
+
|
|
356
|
+
const getPropertyFor = useCallback(({
|
|
357
|
+
propertyKey,
|
|
358
|
+
entity
|
|
359
|
+
}: GetPropertyForProps<M>) => {
|
|
360
|
+
let propertyOrBuilder: PropertyOrBuilder<any, M> | undefined = getPropertyInPath<M>(collection.properties, propertyKey);
|
|
361
|
+
|
|
362
|
+
// we might not find the property in the collection if combining property builders and map spread
|
|
363
|
+
if (!propertyOrBuilder) {
|
|
364
|
+
// these 2 properties are coming from the resolved collection with default values
|
|
365
|
+
propertyOrBuilder = getPropertyInPath<M>(resolvedCollection.properties, propertyKey);
|
|
366
|
+
}
|
|
512
367
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
368
|
+
return resolveProperty({
|
|
369
|
+
propertyKey,
|
|
370
|
+
propertyOrBuilder,
|
|
371
|
+
path: fullPath,
|
|
372
|
+
values: entity.values,
|
|
373
|
+
entityId: entity.id,
|
|
374
|
+
fields: customizationController.propertyConfigs
|
|
375
|
+
});
|
|
376
|
+
}, [collection.properties, customizationController.propertyConfigs, fullPath, resolvedCollection.properties]);
|
|
377
|
+
|
|
378
|
+
const displayedColumnIds = useColumnIds(resolvedCollection, true);
|
|
379
|
+
|
|
380
|
+
const additionalFields = useMemo(() => {
|
|
381
|
+
const subcollectionColumns: AdditionalFieldDelegate<M, any>[] = collection.subcollections?.map((subcollection) => {
|
|
382
|
+
return {
|
|
383
|
+
key: getSubcollectionColumnId(subcollection),
|
|
384
|
+
name: subcollection.name,
|
|
385
|
+
width: 200,
|
|
386
|
+
dependencies: [],
|
|
387
|
+
Builder: ({ entity }) => (
|
|
388
|
+
<Button color={"primary"}
|
|
389
|
+
variant={"outlined"}
|
|
390
|
+
startIcon={<KeyboardTabIcon size={"small"}/>}
|
|
391
|
+
onClick={(event: any) => {
|
|
392
|
+
event.stopPropagation();
|
|
393
|
+
sideEntityController.open({
|
|
394
|
+
path: fullPath,
|
|
395
|
+
entityId: entity.id,
|
|
396
|
+
selectedSubPath: subcollection.id ?? subcollection.path,
|
|
397
|
+
collection,
|
|
398
|
+
updateUrl: true,
|
|
399
|
+
});
|
|
400
|
+
}}>
|
|
401
|
+
{subcollection.name}
|
|
402
|
+
</Button>
|
|
403
|
+
)
|
|
404
|
+
};
|
|
405
|
+
}) ?? [];
|
|
406
|
+
|
|
407
|
+
const collectionGroupParentCollections: AdditionalFieldDelegate<M, any>[] = collection.collectionGroup
|
|
408
|
+
? [{
|
|
409
|
+
key: COLLECTION_GROUP_PARENT_ID,
|
|
410
|
+
name: "Parent entities",
|
|
411
|
+
width: 260,
|
|
412
|
+
dependencies: [],
|
|
413
|
+
Builder: ({ entity }) => {
|
|
414
|
+
const collectionsWithPath = navigation.getParentReferencesFromPath(entity.path);
|
|
415
|
+
return (
|
|
416
|
+
<div className={"flex flex-col gap-2 w-full"}>
|
|
417
|
+
{collectionsWithPath.map((reference) => {
|
|
418
|
+
return (
|
|
419
|
+
<ReferencePreview
|
|
420
|
+
key={reference.path + "/" + reference.id}
|
|
421
|
+
reference={reference}
|
|
422
|
+
size={"tiny"}/>
|
|
423
|
+
);
|
|
424
|
+
})}
|
|
425
|
+
</div>
|
|
426
|
+
);
|
|
527
427
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
return <>
|
|
562
|
-
{customizationController.plugins.filter(plugin => plugin.collectionView?.HeaderAction)
|
|
563
|
-
.map((plugin, i) => {
|
|
564
|
-
const HeaderAction = plugin.collectionView!.HeaderAction!;
|
|
565
|
-
return <HeaderAction
|
|
566
|
-
onHover={onHover}
|
|
567
|
-
key={`plugin_header_action_${i}`}
|
|
568
|
-
propertyKey={propertyKey}
|
|
569
|
-
property={property}
|
|
570
|
-
fullPath={fullPath}
|
|
571
|
-
collection={collection}
|
|
572
|
-
parentCollectionIds={parentCollectionIds ?? []}/>;
|
|
573
|
-
})}
|
|
574
|
-
</>;
|
|
575
|
-
}, [customizationController.plugins, fullPath, parentCollectionIds]);
|
|
576
|
-
|
|
577
|
-
const addColumnComponentInternal = AddColumnComponent
|
|
578
|
-
? function () {
|
|
579
|
-
if (typeof AddColumnComponent === "function")
|
|
580
|
-
return <AddColumnComponent fullPath={fullPath}
|
|
581
|
-
parentCollectionIds={parentCollectionIds ?? []}
|
|
582
|
-
collection={collection}/>;
|
|
583
|
-
return null;
|
|
584
|
-
}
|
|
585
|
-
: undefined;
|
|
586
|
-
|
|
587
|
-
const {
|
|
588
|
-
textSearchLoading,
|
|
589
|
-
textSearchInitialised,
|
|
590
|
-
onTextSearchClick,
|
|
591
|
-
textSearchEnabled
|
|
592
|
-
} = useTableSearchHelper({
|
|
593
|
-
collection,
|
|
594
|
-
fullPath: resolvedFullPath,
|
|
595
|
-
parentCollectionIds
|
|
596
|
-
});
|
|
428
|
+
}]
|
|
429
|
+
: [];
|
|
430
|
+
|
|
431
|
+
return [
|
|
432
|
+
...(collection.additionalFields ?? []),
|
|
433
|
+
...subcollectionColumns,
|
|
434
|
+
...collectionGroupParentCollections
|
|
435
|
+
];
|
|
436
|
+
}, [collection, fullPath, sideEntityController]);
|
|
437
|
+
|
|
438
|
+
const updateLastDeleteTimestamp = useCallback(() => {
|
|
439
|
+
setLastDeleteTimestamp(Date.now());
|
|
440
|
+
}, []);
|
|
441
|
+
|
|
442
|
+
const largeLayout = useLargeLayout();
|
|
443
|
+
|
|
444
|
+
const getActionsForEntity = ({
|
|
445
|
+
entity,
|
|
446
|
+
customEntityActions
|
|
447
|
+
}: {
|
|
448
|
+
entity?: Entity<M>,
|
|
449
|
+
customEntityActions?: EntityAction[]
|
|
450
|
+
}): EntityAction[] => {
|
|
451
|
+
const deleteEnabled = entity ? canDeleteEntity(collection, authController, fullPath, entity) : true;
|
|
452
|
+
const actions: EntityAction[] = [editEntityAction];
|
|
453
|
+
if (createEnabled)
|
|
454
|
+
actions.push(copyEntityAction);
|
|
455
|
+
if (deleteEnabled)
|
|
456
|
+
actions.push(deleteEntityAction);
|
|
457
|
+
if (customEntityActions)
|
|
458
|
+
actions.push(...customEntityActions);
|
|
459
|
+
return actions;
|
|
460
|
+
};
|
|
597
461
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
462
|
+
const getIdColumnWidth = () => {
|
|
463
|
+
const entityActions = getActionsForEntity({});
|
|
464
|
+
const collapsedActions = entityActions.filter(a => a.collapsed !== false);
|
|
465
|
+
const uncollapsedActions = entityActions.filter(a => a.collapsed === false);
|
|
466
|
+
const actionsWidth = uncollapsedActions.length * (largeLayout ? 40 : 30);
|
|
467
|
+
return (largeLayout ? (80 + actionsWidth) : (70 + actionsWidth)) + (collapsedActions.length > 0 ? (largeLayout ? 40 : 30) : 0);
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
const tableRowActionsBuilder = ({
|
|
471
|
+
entity,
|
|
472
|
+
size,
|
|
473
|
+
width,
|
|
474
|
+
frozen
|
|
475
|
+
}: {
|
|
476
|
+
entity: Entity<any>,
|
|
477
|
+
size: CollectionSize,
|
|
478
|
+
width: number,
|
|
479
|
+
frozen?: boolean
|
|
480
|
+
}) => {
|
|
481
|
+
|
|
482
|
+
const isSelected = isEntitySelected(entity);
|
|
483
|
+
|
|
484
|
+
const actions = getActionsForEntity({
|
|
485
|
+
entity,
|
|
486
|
+
customEntityActions: collection.entityActions
|
|
487
|
+
});
|
|
488
|
+
|
|
489
|
+
return (
|
|
490
|
+
<EntityCollectionRowActions
|
|
491
|
+
entity={entity}
|
|
492
|
+
width={width}
|
|
493
|
+
frozen={frozen}
|
|
494
|
+
isSelected={isSelected}
|
|
495
|
+
selectionEnabled={selectionEnabled}
|
|
496
|
+
size={size}
|
|
497
|
+
highlightEntity={setSelectedNavigationEntity}
|
|
498
|
+
unhighlightEntity={unselectNavigatedEntity}
|
|
624
499
|
collection={collection}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
500
|
+
fullPath={fullPath}
|
|
501
|
+
actions={actions}
|
|
502
|
+
hideId={collection?.hideIdFromCollection}
|
|
503
|
+
onCollectionChange={updateLastDeleteTimestamp}
|
|
628
504
|
selectionController={usedSelectionController}
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
505
|
+
/>
|
|
506
|
+
);
|
|
507
|
+
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
const title = <Popover
|
|
511
|
+
open={popOverOpen}
|
|
512
|
+
onOpenChange={setPopOverOpen}
|
|
513
|
+
enabled={Boolean(collection.description)}
|
|
514
|
+
trigger={<div className="flex flex-col items-start">
|
|
515
|
+
<Typography
|
|
516
|
+
variant={"subtitle1"}
|
|
517
|
+
className={`leading-none truncate max-w-[160px] lg:max-w-[240px] ${collection.description ? "cursor-pointer" : "cursor-auto"}`}
|
|
518
|
+
onClick={collection.description
|
|
519
|
+
? (e) => {
|
|
520
|
+
setPopOverOpen(true);
|
|
521
|
+
e.stopPropagation();
|
|
522
|
+
}
|
|
523
|
+
: undefined}>
|
|
524
|
+
{`${collection.name}`}
|
|
525
|
+
</Typography>
|
|
526
|
+
|
|
527
|
+
<EntitiesCount
|
|
528
|
+
fullPath={fullPath}
|
|
632
529
|
collection={collection}
|
|
530
|
+
filter={tableController.filterValues}
|
|
531
|
+
sortBy={tableController.sortBy}
|
|
532
|
+
onCountChange={setDocsCount}
|
|
533
|
+
/>
|
|
534
|
+
|
|
535
|
+
</div>}
|
|
536
|
+
>
|
|
537
|
+
|
|
538
|
+
{collection.description && <div className="m-4 text-gray-900 dark:text-white">
|
|
539
|
+
<Markdown source={collection.description}/>
|
|
540
|
+
</div>}
|
|
541
|
+
|
|
542
|
+
</Popover>;
|
|
543
|
+
|
|
544
|
+
const buildAdditionalHeaderWidget = useCallback(({
|
|
545
|
+
property,
|
|
546
|
+
propertyKey,
|
|
547
|
+
onHover
|
|
548
|
+
}: {
|
|
549
|
+
property: ResolvedProperty,
|
|
550
|
+
propertyKey: string,
|
|
551
|
+
onHover: boolean
|
|
552
|
+
}) => {
|
|
553
|
+
const collection = collectionRef.current;
|
|
554
|
+
if (!customizationController.plugins)
|
|
555
|
+
return null;
|
|
556
|
+
return <>
|
|
557
|
+
{customizationController.plugins.filter(plugin => plugin.collectionView?.HeaderAction)
|
|
558
|
+
.map((plugin, i) => {
|
|
559
|
+
const HeaderAction = plugin.collectionView!.HeaderAction!;
|
|
560
|
+
return <HeaderAction
|
|
561
|
+
onHover={onHover}
|
|
562
|
+
key={`plugin_header_action_${i}`}
|
|
563
|
+
propertyKey={propertyKey}
|
|
564
|
+
property={property}
|
|
565
|
+
fullPath={fullPath}
|
|
566
|
+
collection={collection}
|
|
567
|
+
parentCollectionIds={parentCollectionIds ?? []}/>;
|
|
568
|
+
})}
|
|
569
|
+
</>;
|
|
570
|
+
}, [customizationController.plugins, fullPath, parentCollectionIds]);
|
|
571
|
+
|
|
572
|
+
const addColumnComponentInternal = AddColumnComponent
|
|
573
|
+
? function () {
|
|
574
|
+
if (typeof AddColumnComponent === "function")
|
|
575
|
+
return <AddColumnComponent fullPath={fullPath}
|
|
576
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
577
|
+
collection={collection}/>;
|
|
578
|
+
return null;
|
|
579
|
+
}
|
|
580
|
+
: undefined;
|
|
581
|
+
|
|
582
|
+
const {
|
|
583
|
+
textSearchLoading,
|
|
584
|
+
textSearchInitialised,
|
|
585
|
+
onTextSearchClick,
|
|
586
|
+
textSearchEnabled
|
|
587
|
+
} = useTableSearchHelper({
|
|
588
|
+
collection,
|
|
589
|
+
fullPath: resolvedFullPath,
|
|
590
|
+
parentCollectionIds
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
return (
|
|
594
|
+
<div className={cn("overflow-hidden h-full w-full rounded-md", className)}
|
|
595
|
+
ref={containerRef}>
|
|
596
|
+
<EntityCollectionTable
|
|
597
|
+
key={`collection_table_${fullPath}`}
|
|
598
|
+
additionalFields={additionalFields}
|
|
633
599
|
tableController={tableController}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
600
|
+
enablePopupIcon={true}
|
|
601
|
+
displayedColumnIds={displayedColumnIds}
|
|
602
|
+
onSizeChanged={onSizeChanged}
|
|
603
|
+
onEntityClick={onEntityClick}
|
|
604
|
+
onColumnResize={onColumnResize}
|
|
605
|
+
onValueChange={onValueChange}
|
|
606
|
+
tableRowActionsBuilder={tableRowActionsBuilder}
|
|
607
|
+
uniqueFieldValidator={uniqueFieldValidator}
|
|
608
|
+
title={title}
|
|
638
609
|
selectionController={usedSelectionController}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
?
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
610
|
+
highlightedEntities={selectedNavigationEntity ? [selectedNavigationEntity] : []}
|
|
611
|
+
defaultSize={collection.defaultSize}
|
|
612
|
+
properties={resolvedCollection.properties}
|
|
613
|
+
getPropertyFor={getPropertyFor}
|
|
614
|
+
onTextSearchClick={textSearchInitialised ? undefined : onTextSearchClick}
|
|
615
|
+
textSearchLoading={textSearchLoading}
|
|
616
|
+
textSearchEnabled={textSearchEnabled}
|
|
617
|
+
actionsStart={<EntityCollectionViewStartActions
|
|
618
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
619
|
+
collection={collection}
|
|
620
|
+
tableController={tableController}
|
|
621
|
+
path={fullPath}
|
|
622
|
+
relativePath={collection.path}
|
|
623
|
+
selectionController={usedSelectionController}
|
|
624
|
+
collectionEntitiesCount={docsCount}/>}
|
|
625
|
+
actions={<EntityCollectionViewActions
|
|
626
|
+
parentCollectionIds={parentCollectionIds ?? []}
|
|
627
|
+
collection={collection}
|
|
628
|
+
tableController={tableController}
|
|
629
|
+
onMultipleDeleteClick={onMultipleDeleteClick}
|
|
630
|
+
onNewClick={onNewClick}
|
|
631
|
+
path={fullPath}
|
|
632
|
+
relativePath={collection.path}
|
|
633
|
+
selectionController={usedSelectionController}
|
|
634
|
+
selectionEnabled={selectionEnabled}
|
|
635
|
+
collectionEntitiesCount={docsCount}
|
|
636
|
+
/>}
|
|
637
|
+
emptyComponent={canCreateEntities && tableController.filterValues === undefined && tableController.sortBy === undefined
|
|
638
|
+
? <div className="flex flex-col items-center justify-center">
|
|
639
|
+
<Typography variant={"subtitle2"}>So empty...</Typography>
|
|
640
|
+
<Button
|
|
641
|
+
color={"primary"}
|
|
642
|
+
variant={"outlined"}
|
|
643
|
+
onClick={onNewClick}
|
|
644
|
+
className="mt-4"
|
|
645
|
+
>
|
|
646
|
+
<AddIcon/>
|
|
647
|
+
Create your first entity
|
|
648
|
+
</Button>
|
|
649
|
+
</div>
|
|
650
|
+
: <Typography variant={"label"}>No results with the applied filter/sort</Typography>
|
|
651
|
+
}
|
|
652
|
+
hoverRow={hoverRow}
|
|
653
|
+
inlineEditing={checkInlineEditing()}
|
|
654
|
+
AdditionalHeaderWidget={buildAdditionalHeaderWidget}
|
|
655
|
+
AddColumnComponent={addColumnComponentInternal}
|
|
656
|
+
getIdColumnWidth={getIdColumnWidth}
|
|
657
|
+
additionalIDHeaderWidget={<EntityIdHeaderWidget
|
|
658
|
+
path={fullPath}
|
|
659
|
+
collection={collection}/>}
|
|
660
|
+
/>
|
|
661
|
+
|
|
662
|
+
<PopupFormField
|
|
663
|
+
key={`popup_form_${popupCell?.propertyKey}_${popupCell?.entity?.id}`}
|
|
664
|
+
open={Boolean(popupCell)}
|
|
665
|
+
onClose={onPopupClose}
|
|
666
|
+
cellRect={popupCell?.cellRect}
|
|
667
|
+
propertyKey={popupCell?.propertyKey}
|
|
685
668
|
collection={collection}
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
669
|
+
entity={popupCell?.entity}
|
|
670
|
+
tableKey={tableKey.current}
|
|
671
|
+
customFieldValidator={uniqueFieldValidator}
|
|
672
|
+
path={resolvedFullPath}
|
|
673
|
+
onCellValueChange={onValueChange}
|
|
674
|
+
container={containerRef.current}/>
|
|
675
|
+
|
|
676
|
+
{deleteEntityClicked &&
|
|
677
|
+
<DeleteEntityDialog
|
|
678
|
+
entityOrEntitiesToDelete={deleteEntityClicked}
|
|
679
|
+
path={fullPath}
|
|
680
|
+
collection={collection}
|
|
681
|
+
callbacks={collection.callbacks}
|
|
682
|
+
open={Boolean(deleteEntityClicked)}
|
|
683
|
+
onEntityDelete={internalOnEntityDelete}
|
|
684
|
+
onMultipleEntitiesDelete={internalOnMultipleEntitiesDelete}
|
|
685
|
+
onClose={() => setDeleteEntityClicked(undefined)}/>}
|
|
691
686
|
|
|
692
687
|
</div>
|
|
693
688
|
);
|