@rebasepro/core 0.0.1-canary.eae7889 → 0.1.0

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.
Files changed (37) hide show
  1. package/dist/components/BootstrapAdminBanner.d.ts +4 -0
  2. package/dist/components/LoginView/LoginView.d.ts +22 -0
  3. package/dist/components/common/useDataTableController.d.ts +3 -3
  4. package/dist/components/index.d.ts +1 -0
  5. package/dist/hooks/data/useRelationSelector.d.ts +2 -2
  6. package/dist/hooks/index.d.ts +1 -0
  7. package/dist/hooks/useCollapsedGroups.d.ts +16 -1
  8. package/dist/hooks/useResolvedComponent.d.ts +47 -0
  9. package/dist/index.es.js +333 -121
  10. package/dist/index.es.js.map +1 -1
  11. package/dist/index.umd.js +330 -118
  12. package/dist/index.umd.js.map +1 -1
  13. package/dist/vitePlugin.d.ts +28 -1
  14. package/dist/vitePlugin.js +42 -0
  15. package/package.json +7 -8
  16. package/src/components/BootstrapAdminBanner.tsx +66 -0
  17. package/src/components/LoginView/LoginView.tsx +73 -42
  18. package/src/components/UserSelectPopover.tsx +8 -34
  19. package/src/components/common/useColumnsIds.tsx +16 -16
  20. package/src/components/common/useDataTableController.tsx +30 -18
  21. package/src/components/index.tsx +1 -1
  22. package/src/core/Rebase.tsx +20 -14
  23. package/src/hooks/data/useRelationSelector.tsx +6 -6
  24. package/src/hooks/index.tsx +1 -0
  25. package/src/hooks/useCollapsedGroups.ts +48 -6
  26. package/src/hooks/useRebaseContext.tsx +11 -6
  27. package/src/hooks/useResolvedComponent.tsx +157 -0
  28. package/src/hooks/useStudioBridge.tsx +2 -1
  29. package/src/locales/de.ts +4 -0
  30. package/src/locales/en.ts +6 -0
  31. package/src/locales/es.ts +4 -0
  32. package/src/locales/fr.ts +4 -0
  33. package/src/locales/hi.ts +4 -0
  34. package/src/locales/it.ts +4 -0
  35. package/src/locales/pt.ts +4 -0
  36. package/src/util/previews.ts +16 -7
  37. package/src/vitePlugin.ts +87 -1
package/dist/index.es.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { c } from "react-compiler-runtime";
3
- import React, { useRef, useEffect, useState, useContext, useCallback, useMemo, createContext, useLayoutEffect } from "react";
3
+ import React, { useRef, useEffect, useState, useContext, useCallback, useMemo, createContext, lazy, useLayoutEffect } from "react";
4
4
  import { ErrorBoundary, Tooltip, Typography, Button, DialogTitle, DialogContent, LoadingButton, DialogActions, Dialog, Paper, IconButton, Container, cls, defaultBorderMixin, iconSize, MenuItem, Menu, Table, TableBody, Chip, CircularProgress, TableRow, TableCell, Checkbox, Avatar, Tabs, Tab, TextField, Select, SelectItem, MultiSelect, MultiSelectItem, BooleanSwitch, SearchBar, Skeleton, Alert, Separator, TableHeader, Popover, CenteredView, iconKeys, coolIconKeys, colorClassesMapping, getColorSchemeForSeed, CHIP_COLORS } from "@rebasepro/ui";
5
5
  import { SnackbarProvider as SnackbarProvider$1, useSnackbar } from "notistack";
6
- import { EntityRelation, EntityReference, Vector, GeoPoint } from "@rebasepro/types";
6
+ import { EntityRelation, isLazyComponentRef, EntityReference, Vector, GeoPoint } from "@rebasepro/types";
7
7
  import { useBlocker, useLocation, Link, createBrowserRouter, RouterProvider, Routes } from "react-router-dom";
8
8
  import { stripCollectionPath, canCreateEntity, canEditEntity, canDeleteEntity, canReadCollection, getSubcollections, buildRebaseData, removeInitialAndTrailingSlashes, resolveStorageFilenameString, resolveStoragePathString, isPropertyBuilder, getLabelOrConfigFrom } from "@rebasepro/common";
9
9
  import { mergeDeep, slugify, hashString, isObject, isPlainObject, randomString } from "@rebasepro/utils";
10
10
  import { deepEqual } from "fast-equals";
11
11
  import { useTranslation as useTranslation$1, initReactI18next, I18nextProvider } from "react-i18next";
12
- import { AlertTriangleIcon, Wand2Icon, Trash2Icon, ChevronDownIcon, SettingsIcon, ChevronsLeftIcon, FolderIcon, UserIcon, TagIcon, ChevronsRightIcon, MoonIcon, SunIcon, SunMoonIcon, PlusIcon, PencilIcon, LogOutIcon, LanguagesIcon, CheckIcon, SearchIcon, XIcon, CircleUserIcon, MailIcon, ArrowLeftIcon, icons } from "lucide-react";
12
+ import { AlertTriangleIcon, Wand2Icon, Trash2Icon, ChevronDownIcon, SettingsIcon, ChevronsLeftIcon, FolderIcon, UserIcon, TagIcon, ChevronsRightIcon, MoonIcon, SunIcon, SunMoonIcon, PlusIcon, PencilIcon, LogOutIcon, LanguagesIcon, CheckIcon, CircleUserIcon, MailIcon, ArrowLeftIcon, icons } from "lucide-react";
13
13
  import i18next from "i18next";
14
14
  import Fuse from "fuse.js";
15
15
  import Compressor from "compressorjs";
@@ -378,6 +378,9 @@ function _temp$7(e) {
378
378
  const useAuthController = () => {
379
379
  return useContext(AuthControllerContext);
380
380
  };
381
+ function useRebaseClient() {
382
+ return useContext(RebaseClientInstanceContext);
383
+ }
381
384
  const useStorageSource = (collection) => {
382
385
  const defaultStorageSource = useContext(StorageSourceContext);
383
386
  if (collection?.overrides?.storageSource) {
@@ -433,6 +436,7 @@ function useInternalUserManagementController() {
433
436
  }
434
437
  const DatabaseAdminContext = React.createContext(void 0);
435
438
  const useRebaseContext = () => {
439
+ const client = useRebaseClient();
436
440
  const authController = useAuthController();
437
441
  const data = useData();
438
442
  const storageSource = useStorageSource();
@@ -455,7 +459,9 @@ const useRebaseContext = () => {
455
459
  analyticsController,
456
460
  userManagement,
457
461
  effectiveRoleController,
458
- databaseAdmin
462
+ databaseAdmin,
463
+ client
464
+ // Client should be provided
459
465
  });
460
466
  React.useEffect(() => {
461
467
  rebaseContextRef.current = {
@@ -469,9 +475,10 @@ const useRebaseContext = () => {
469
475
  analyticsController,
470
476
  userManagement,
471
477
  effectiveRoleController,
472
- databaseAdmin
478
+ databaseAdmin,
479
+ client
473
480
  };
474
- }, [authController, dialogsController, effectiveRoleController, data, databaseAdmin]);
481
+ }, [authController, data, storageSource, snackbarController, userConfigPersistence, dialogsController, customizationController, analyticsController, userManagement, effectiveRoleController, databaseAdmin, client]);
475
482
  return rebaseContextRef.current;
476
483
  };
477
484
  const CACHE = {};
@@ -581,7 +588,7 @@ const DEFAULT_PAGE_SIZE$2 = 10;
581
588
  function useRelationSelector({
582
589
  path,
583
590
  collection,
584
- forceFilter,
591
+ fixedFilter,
585
592
  pageSize = DEFAULT_PAGE_SIZE$2,
586
593
  getLabelFromEntity,
587
594
  getDescriptionFromEntity,
@@ -642,8 +649,8 @@ function useRelationSelector({
642
649
  setError(void 0);
643
650
  setLoading(true);
644
651
  const whereMap = {};
645
- if (forceFilter) {
646
- Object.entries(forceFilter).forEach(([key, value]) => {
652
+ if (fixedFilter) {
653
+ Object.entries(fixedFilter).forEach(([key, value]) => {
647
654
  if (value && Array.isArray(value)) {
648
655
  const [op, val] = value;
649
656
  const postgrestOp = op === "==" ? "eq" : op === "!=" ? "neq" : op === ">" ? "gt" : op === ">=" ? "gte" : op === "<" ? "lt" : op === "<=" ? "lte" : op === "in" ? "in" : op === "not-in" ? "nin" : op === "array-contains" ? "cs" : op === "array-contains-any" ? "csa" : "eq";
@@ -690,7 +697,7 @@ function useRelationSelector({
690
697
  };
691
698
  }
692
699
  unsubscribeRef.current = unsubscribe || null;
693
- }, [dataClient, path, forceFilter, limit, currentSearch, entityToRelationItem, cleanupSubscription, setLoading]);
700
+ }, [dataClient, path, fixedFilter, limit, currentSearch, entityToRelationItem, cleanupSubscription, setLoading]);
694
701
  const search = useCallback((searchString) => {
695
702
  if (searchTimeoutRef.current) {
696
703
  clearTimeout(searchTimeoutRef.current);
@@ -1370,7 +1377,7 @@ function checkLargeLayout(breakpoint = "lg") {
1370
1377
  return window.matchMedia(`(min-width: ${breakpoints[breakpoint] + 1}px)`).matches;
1371
1378
  }
1372
1379
  const STORAGE_KEY_PREFIX = "rebase-collapsed-groups";
1373
- function useCollapsedGroups(groupNames, namespace = "default") {
1380
+ function useCollapsedGroups(groupNames, namespace = "default", defaults) {
1374
1381
  const storageKey = `${STORAGE_KEY_PREFIX}-${namespace}`;
1375
1382
  const [collapsedGroups, setCollapsedGroups] = useState(() => {
1376
1383
  try {
@@ -1400,19 +1407,42 @@ function useCollapsedGroups(groupNames, namespace = "default") {
1400
1407
  });
1401
1408
  }, [groupNames]);
1402
1409
  const isGroupCollapsed = useCallback((name) => {
1403
- return !!collapsedGroups[name];
1404
- }, [collapsedGroups]);
1410
+ if (name in collapsedGroups) {
1411
+ return collapsedGroups[name];
1412
+ }
1413
+ return defaults?.[name] ?? false;
1414
+ }, [collapsedGroups, defaults]);
1405
1415
  const toggleGroupCollapsed = useCallback((name_0) => {
1406
- setCollapsedGroups((prev_0) => ({
1407
- ...prev_0,
1408
- [name_0]: !prev_0[name_0]
1409
- }));
1410
- }, []);
1416
+ setCollapsedGroups((prev_0) => {
1417
+ const currentlyCollapsed = name_0 in prev_0 ? prev_0[name_0] : defaults?.[name_0] ?? false;
1418
+ return {
1419
+ ...prev_0,
1420
+ [name_0]: !currentlyCollapsed
1421
+ };
1422
+ });
1423
+ }, [defaults]);
1411
1424
  return useMemo(() => ({
1412
1425
  isGroupCollapsed,
1413
1426
  toggleGroupCollapsed
1414
1427
  }), [isGroupCollapsed, toggleGroupCollapsed]);
1415
1428
  }
1429
+ function buildCollapsedDefaults(mappings, namespace) {
1430
+ if (!mappings) return {};
1431
+ const result = {};
1432
+ for (const mapping of mappings) {
1433
+ const val = mapping.collapsedByDefault;
1434
+ if (val === void 0) continue;
1435
+ if (typeof val === "boolean") {
1436
+ result[mapping.name] = val;
1437
+ } else {
1438
+ const ns = val[namespace];
1439
+ if (ns !== void 0) {
1440
+ result[mapping.name] = ns;
1441
+ }
1442
+ }
1443
+ }
1444
+ return result;
1445
+ }
1416
1446
  const rebaseLogo = "data:image/png;base64,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";
1417
1447
  function useBrowserTitleAndIcon(name, logo) {
1418
1448
  const $ = c(4);
@@ -2166,8 +2196,58 @@ function useTranslation() {
2166
2196
  t1 = t2;
2167
2197
  return t1;
2168
2198
  }
2169
- function useRebaseClient() {
2170
- return useContext(RebaseClientInstanceContext);
2199
+ const lazyCache = /* @__PURE__ */ new WeakMap();
2200
+ function useResolvedComponent(ref) {
2201
+ const $ = c(2);
2202
+ let t0;
2203
+ let t1;
2204
+ if ($[0] !== ref) {
2205
+ t1 = resolveComponentRef(ref);
2206
+ $[0] = ref;
2207
+ $[1] = t1;
2208
+ } else {
2209
+ t1 = $[1];
2210
+ }
2211
+ t0 = t1;
2212
+ return t0;
2213
+ }
2214
+ function getOrCreateLazy(key, loader) {
2215
+ const cached = lazyCache.get(key);
2216
+ if (cached) return cached;
2217
+ const LazyComponent = lazy(loader);
2218
+ lazyCache.set(key, LazyComponent);
2219
+ return LazyComponent;
2220
+ }
2221
+ function resolveComponentRef(ref) {
2222
+ if (ref == null) return void 0;
2223
+ if (typeof ref === "string") {
2224
+ console.warn(`[Rebase] Encountered a raw string ComponentRef ("${ref}") at runtime. This usually means the Vite transform plugin did not process this file. Ensure the file is inside the configured collectionsDir.`);
2225
+ return void 0;
2226
+ }
2227
+ if (isLazyComponentRef(ref)) {
2228
+ return getOrCreateLazy(ref, () => ref.load());
2229
+ }
2230
+ if (typeof ref === "function") {
2231
+ const fn = ref;
2232
+ if (fn.prototype?.isReactComponent) {
2233
+ return ref;
2234
+ }
2235
+ if ("$$typeof" in fn) {
2236
+ return ref;
2237
+ }
2238
+ if (fn.length > 0) {
2239
+ return ref;
2240
+ }
2241
+ const name = fn.name;
2242
+ if (name && /^[A-Z]/.test(name)) {
2243
+ return ref;
2244
+ }
2245
+ return getOrCreateLazy(fn, ref);
2246
+ }
2247
+ if (typeof ref === "object" && "$$typeof" in ref) {
2248
+ return ref;
2249
+ }
2250
+ return void 0;
2171
2251
  }
2172
2252
  function ErrorTooltip(props) {
2173
2253
  const $ = c(2);
@@ -2334,7 +2414,7 @@ function hideAndExpandKeys(collection, keys) {
2334
2414
  if (key.includes(".")) {
2335
2415
  const rootKey = key.split(".")[0];
2336
2416
  const rootProperty = collection.properties[rootKey];
2337
- if (rootProperty && rootProperty.type === "map" && rootProperty.spreadChildren && rootProperty.properties) {
2417
+ if (rootProperty && rootProperty.type === "map" && rootProperty.ui?.spreadChildren && rootProperty.properties) {
2338
2418
  rootsWithExplicitChildren.add(rootKey);
2339
2419
  }
2340
2420
  }
@@ -2345,9 +2425,9 @@ function hideAndExpandKeys(collection, keys) {
2345
2425
  const property = collection.properties[key];
2346
2426
  if (property) {
2347
2427
  processedPropertyKeys.add(key);
2348
- if (property.hideFromCollection) return [null];
2349
- if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden) return [null];
2350
- if (property.type === "map" && property.spreadChildren && property.properties) {
2428
+ if (property.ui?.hideFromCollection) return [null];
2429
+ if (property.ui?.disabled && typeof property.ui?.disabled === "object" && property.ui?.disabled.hidden) return [null];
2430
+ if (property.type === "map" && property.ui?.spreadChildren && property.properties) {
2351
2431
  if (rootsWithExplicitChildren.has(key)) {
2352
2432
  return [null];
2353
2433
  }
@@ -2357,7 +2437,7 @@ function hideAndExpandKeys(collection, keys) {
2357
2437
  }
2358
2438
  return [{
2359
2439
  key,
2360
- disabled: Boolean(property.disabled) || Boolean(property.readOnly)
2440
+ disabled: Boolean(property.ui?.disabled) || Boolean(property.ui?.readOnly)
2361
2441
  }];
2362
2442
  }
2363
2443
  if (key.includes(".")) {
@@ -2368,11 +2448,11 @@ function hideAndExpandKeys(collection, keys) {
2368
2448
  if (nestedProperty) {
2369
2449
  processedPropertyKeys.add(key);
2370
2450
  processedPropertyKeys.add(rootKey);
2371
- if (nestedProperty.hideFromCollection) return [null];
2372
- if (nestedProperty.disabled && typeof nestedProperty.disabled === "object" && nestedProperty.disabled.hidden) return [null];
2451
+ if (nestedProperty.ui?.hideFromCollection) return [null];
2452
+ if (nestedProperty.ui?.disabled && typeof nestedProperty.ui?.disabled === "object" && nestedProperty.ui?.disabled.hidden) return [null];
2373
2453
  return [{
2374
2454
  key,
2375
- disabled: Boolean(rootProperty.disabled) || Boolean(rootProperty.readOnly) || Boolean(nestedProperty.disabled) || Boolean(nestedProperty.readOnly)
2455
+ disabled: Boolean(rootProperty.ui?.disabled) || Boolean(rootProperty.ui?.readOnly) || Boolean(nestedProperty.ui?.disabled) || Boolean(nestedProperty.ui?.readOnly)
2376
2456
  }];
2377
2457
  }
2378
2458
  }
@@ -2400,9 +2480,9 @@ function hideAndExpandKeys(collection, keys) {
2400
2480
  if (processedPropertyKeys.has(propKey)) continue;
2401
2481
  const property = collection.properties[propKey];
2402
2482
  if (!property) continue;
2403
- if (property.hideFromCollection) continue;
2404
- if (property.disabled && typeof property.disabled === "object" && property.disabled.hidden) continue;
2405
- if (property.type === "map" && property.spreadChildren && property.properties) {
2483
+ if (property.ui?.hideFromCollection) continue;
2484
+ if (property.ui?.disabled && typeof property.ui?.disabled === "object" && property.ui?.disabled.hidden) continue;
2485
+ if (property.type === "map" && property.ui?.spreadChildren && property.properties) {
2406
2486
  const allChildConfigs = getColumnKeysForProperty(property, propKey);
2407
2487
  for (const childConfig of allChildConfigs) {
2408
2488
  if (!processedPropertyKeys.has(childConfig.key)) {
@@ -2413,7 +2493,7 @@ function hideAndExpandKeys(collection, keys) {
2413
2493
  } else {
2414
2494
  result.push({
2415
2495
  key: propKey,
2416
- disabled: Boolean(property.disabled) || Boolean(property.readOnly)
2496
+ disabled: Boolean(property.ui?.disabled) || Boolean(property.ui?.readOnly)
2417
2497
  });
2418
2498
  processedPropertyKeys.add(propKey);
2419
2499
  }
@@ -2436,12 +2516,12 @@ function getDefaultColumnKeys(collection, includeSubCollections) {
2436
2516
  return hideAndExpandKeys(collection, columnIds);
2437
2517
  }
2438
2518
  function getColumnKeysForProperty(property, key, disabled) {
2439
- if (property.type === "map" && property.spreadChildren && property.properties) {
2440
- return Object.entries(property.properties).flatMap(([childKey, childProperty]) => getColumnKeysForProperty(childProperty, `${key}.${childKey}`, disabled || Boolean(property.disabled) || Boolean(property.readOnly)));
2519
+ if (property.type === "map" && property.ui?.spreadChildren && property.properties) {
2520
+ return Object.entries(property.properties).flatMap(([childKey, childProperty]) => getColumnKeysForProperty(childProperty, `${key}.${childKey}`, disabled || Boolean(property.ui?.disabled) || Boolean(property.ui?.readOnly)));
2441
2521
  }
2442
2522
  return [{
2443
2523
  key,
2444
- disabled: disabled || Boolean(property.disabled) || Boolean(property.readOnly)
2524
+ disabled: disabled || Boolean(property.ui?.disabled) || Boolean(property.ui?.readOnly)
2445
2525
  }];
2446
2526
  }
2447
2527
  function getFormFieldKeys(collection) {
@@ -2468,36 +2548,43 @@ function useDataTableController({
2468
2548
  scrollRestoration,
2469
2549
  entitiesDisplayedFirst,
2470
2550
  lastDeleteTimestamp: _lastDeleteTimestamp,
2471
- forceFilter: forceFilterFromProps,
2551
+ fixedFilter: fixedFilterFromProps,
2472
2552
  updateUrl
2473
2553
  }) {
2474
2554
  const {
2475
- filter,
2555
+ defaultFilter,
2476
2556
  sort,
2477
- forceFilter: forceFilterFromCollection
2557
+ fixedFilter: fixedFilterFromCollection
2478
2558
  } = collection;
2479
2559
  const [popupCell, setPopupCell] = React.useState(void 0);
2480
2560
  const dataClient = useData();
2481
- const forceFilter = forceFilterFromProps ?? forceFilterFromCollection;
2561
+ const fixedFilter = fixedFilterFromProps ?? fixedFilterFromCollection;
2482
2562
  const paginationEnabled = collection.pagination === void 0 || Boolean(collection.pagination);
2483
2563
  const pageSize = typeof collection.pagination === "number" ? collection.pagination : DEFAULT_PAGE_SIZE;
2484
- const [searchString, setSearchString] = React.useState();
2564
+ const location = useLocation();
2565
+ const [searchString, setSearchString] = React.useState(() => {
2566
+ if (updateUrl) {
2567
+ const params = new URLSearchParams(location.search);
2568
+ const urlSearch = params.get("search");
2569
+ return urlSearch ? decodeURIComponent(urlSearch) : void 0;
2570
+ }
2571
+ return void 0;
2572
+ });
2485
2573
  const checkFilterCombination = useCallback((filterValues, sortBy) => {
2486
2574
  return true;
2487
2575
  }, []);
2488
2576
  const sortInternal = useMemo(() => {
2489
- if (sort && forceFilter && !checkFilterCombination(forceFilter, sort)) {
2577
+ if (sort && fixedFilter && !checkFilterCombination(fixedFilter, sort)) {
2490
2578
  console.warn("Initial sort is not compatible with the force filter. Ignoring initial sort");
2491
2579
  return void 0;
2492
2580
  }
2493
2581
  return sort;
2494
- }, [sort, forceFilter]);
2495
- const location = useLocation();
2582
+ }, [sort, fixedFilter]);
2496
2583
  const {
2497
2584
  filterValues: filterUrl,
2498
2585
  sortBy: sortUrl
2499
2586
  } = parseFilterAndSort(location.search);
2500
- const [filterValues_0, setFilterValues] = React.useState(forceFilter ?? (updateUrl ? filterUrl : void 0) ?? filter ?? void 0);
2587
+ const [filterValues_0, setFilterValues] = React.useState(fixedFilter ?? (updateUrl ? filterUrl : void 0) ?? defaultFilter ?? void 0);
2501
2588
  const [sortBy_0, setSortBy] = React.useState((updateUrl ? sortUrl : void 0) ?? sortInternal);
2502
2589
  const initialSearchRef = React.useRef(location.search);
2503
2590
  useEffect(() => {
@@ -2511,15 +2598,18 @@ function useDataTableController({
2511
2598
  filterValues: urlFilterValues,
2512
2599
  sortBy: urlSortBy
2513
2600
  } = parseFilterAndSort(location.search);
2514
- if (!forceFilter) {
2601
+ if (!fixedFilter) {
2515
2602
  setFilterValues(urlFilterValues);
2516
2603
  }
2517
- if (urlSortBy && forceFilter && !checkFilterCombination(forceFilter, urlSortBy)) {
2604
+ if (urlSortBy && fixedFilter && !checkFilterCombination(fixedFilter, urlSortBy)) {
2518
2605
  console.warn("URL sort is not compatible with the force filter.");
2519
2606
  } else {
2520
2607
  setSortBy(urlSortBy);
2521
2608
  }
2522
- }, [location.search, updateUrl, forceFilter, checkFilterCombination]);
2609
+ const urlParams = new URLSearchParams(location.search);
2610
+ const urlSearch_0 = urlParams.get("search");
2611
+ setSearchString(urlSearch_0 ? decodeURIComponent(urlSearch_0) : void 0);
2612
+ }, [location.search, updateUrl, fixedFilter, checkFilterCombination]);
2523
2613
  useUpdateUrl(filterValues_0, sortBy_0, searchString, updateUrl);
2524
2614
  const collectionScroll = scrollRestoration?.getCollectionScroll(path, filterValues_0);
2525
2615
  const initialItemCount = collectionScroll?.data.length ?? pageSize;
@@ -2553,9 +2643,9 @@ function useDataTableController({
2553
2643
  const [dataLoading, setDataLoading] = useState(false);
2554
2644
  const [dataLoadingError, setDataLoadingError] = useState();
2555
2645
  const [noMoreToLoad, setNoMoreToLoad] = useState(false);
2556
- const clearFilter = useCallback(() => setFilterValues(forceFilter ?? void 0), [forceFilter]);
2646
+ const clearFilter = useCallback(() => setFilterValues(fixedFilter ?? void 0), [fixedFilter]);
2557
2647
  const updateFilterValues = useCallback((updatedFilter) => {
2558
- if (forceFilter) {
2648
+ if (fixedFilter) {
2559
2649
  console.warn("Filter is not compatible with the force filter. Ignoring filter");
2560
2650
  return;
2561
2651
  }
@@ -2564,7 +2654,7 @@ function useDataTableController({
2564
2654
  } else {
2565
2655
  setFilterValues(updatedFilter);
2566
2656
  }
2567
- }, [forceFilter]);
2657
+ }, [fixedFilter]);
2568
2658
  useEffect(() => {
2569
2659
  setDataLoading(true);
2570
2660
  const onEntitiesUpdate = async (entities) => {
@@ -6041,14 +6131,7 @@ function UserSelectPopover({
6041
6131
  totalFilterable !== 1 ? "s" : ""
6042
6132
  ] })
6043
6133
  ] }),
6044
- /* @__PURE__ */ jsx("div", { className: cls("px-2 py-1.5 border-b shrink-0", defaultBorderMixin), children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
6045
- /* @__PURE__ */ jsx(SearchIcon, { size: "smallest", className: "absolute left-2 top-1/2 -translate-y-1/2 text-text-disabled dark:text-text-disabled-dark pointer-events-none" }),
6046
- /* @__PURE__ */ jsx("input", { ref: inputRef, type: "text", value: searchText, onChange: (e_0) => setSearchText(e_0.target.value), placeholder: "SearchIcon by name, email, or role…", className: cls("w-full pl-7 pr-7 py-1.5 text-xs rounded-md", "bg-surface-100 dark:bg-surface-950 border", defaultBorderMixin, "outline-none focus:ring-1 focus:ring-primary/40", "placeholder-text-disabled dark:placeholder-text-disabled-dark", "text-text-primary dark:text-text-primary-dark") }),
6047
- searchText && /* @__PURE__ */ jsx("button", { onClick: () => {
6048
- setSearchText("");
6049
- inputRef.current?.focus();
6050
- }, className: "absolute right-1.5 top-1/2 -translate-y-1/2 p-0.5 rounded hover:bg-surface-200 dark:hover:bg-surface-700 text-text-disabled", children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest }) })
6051
- ] }) }),
6134
+ /* @__PURE__ */ jsx("div", { className: cls("px-2 py-1.5 border-b shrink-0", defaultBorderMixin), children: /* @__PURE__ */ jsx(SearchBar, { inputRef, size: "smallest", placeholder: "Search by name, email, or role…", onTextSearch: (val) => setSearchText(val ?? "") }) }),
6052
6135
  /* @__PURE__ */ jsxs("div", { ref: listRef, className: "overflow-y-auto overscroll-contain", style: {
6053
6136
  maxHeight: MAX_VISIBLE_ITEMS * ITEM_HEIGHT
6054
6137
  }, children: [
@@ -6336,7 +6419,7 @@ function LoginView(t0) {
6336
6419
  t4 = $[2];
6337
6420
  }
6338
6421
  const caps = t4;
6339
- const isBootstrapMode = needsSetup ?? authController.needsSetup ?? false;
6422
+ const isBootstrapMode = needsSetup ?? ("needsSetup" in authController && !!authController.needsSetup) ?? false;
6340
6423
  const canRegister = registrationEnabled ?? caps.registration ?? false;
6341
6424
  const hasGoogleLogin = googleEnabled ?? caps.googleLogin ?? false;
6342
6425
  const hasPasswordReset = caps.passwordReset ?? !!authController.forgotPassword;
@@ -6422,7 +6505,7 @@ function LoginView(t0) {
6422
6505
  const t8 = fadeIn ? "opacity-100" : "opacity-0";
6423
6506
  let t9;
6424
6507
  if ($[12] !== t8) {
6425
- t9 = cls("relative flex items-center justify-center h-screen w-screen p-4 transition-opacity duration-500 bg-white dark:bg-surface-950", t8);
6508
+ t9 = cls("relative flex items-center justify-center h-screen w-screen p-4 transition-opacity duration-500 bg-white dark:bg-surface-900", t8);
6426
6509
  $[12] = t8;
6427
6510
  $[13] = t9;
6428
6511
  } else {
@@ -6739,42 +6822,60 @@ function LoginButton(t0) {
6739
6822
  }
6740
6823
  return t4;
6741
6824
  }
6825
+ const GoogleIcon = () => {
6826
+ const $ = c(1);
6827
+ let t0;
6828
+ if ($[0] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
6829
+ t0 = /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", width: "20", height: "20", children: [
6830
+ /* @__PURE__ */ jsx("path", { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
6831
+ /* @__PURE__ */ jsx("path", { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
6832
+ /* @__PURE__ */ jsx("path", { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }),
6833
+ /* @__PURE__ */ jsx("path", { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
6834
+ ] });
6835
+ $[0] = t0;
6836
+ } else {
6837
+ t0 = $[0];
6838
+ }
6839
+ return t0;
6840
+ };
6742
6841
  function GoogleLoginButton(t0) {
6743
- const $ = c(7);
6842
+ const $ = c(10);
6744
6843
  const {
6745
6844
  disabled,
6746
6845
  googleClientId,
6747
6846
  authController
6748
6847
  } = t0;
6848
+ const codeClientRef = useRef(null);
6749
6849
  let t1;
6750
6850
  if ($[0] !== authController.googleLogin || $[1] !== googleClientId) {
6751
- t1 = async () => {
6851
+ t1 = () => {
6752
6852
  if (!authController.googleLogin) {
6753
6853
  return;
6754
6854
  }
6755
- try {
6756
- const google = window.google;
6757
- if (!google) {
6758
- console.error("Google Sign-In not loaded");
6759
- return;
6760
- }
6761
- google.accounts.id.initialize({
6762
- client_id: googleClientId,
6763
- callback: async (response) => {
6764
- ;
6765
- try {
6766
- await authController.googleLogin(response.credential);
6767
- } catch (t32) {
6768
- const err_0 = t32;
6769
- console.error("Google login error:", err_0);
6770
- }
6771
- }
6772
- });
6773
- google.accounts.id.prompt();
6774
- } catch (t22) {
6775
- const err = t22;
6776
- console.error("Google login error:", err);
6855
+ const google = window.google;
6856
+ if (!google || codeClientRef.current) {
6857
+ return;
6777
6858
  }
6859
+ codeClientRef.current = google.accounts.oauth2.initCodeClient({
6860
+ client_id: googleClientId,
6861
+ scope: "openid email profile",
6862
+ ux_mode: "popup",
6863
+ callback: async (response) => {
6864
+ if (response.error || !response.code) {
6865
+ console.error("Google login error:", response.error);
6866
+ return;
6867
+ }
6868
+ try {
6869
+ await authController.googleLogin({
6870
+ code: response.code,
6871
+ redirectUri: "postmessage"
6872
+ });
6873
+ } catch (t22) {
6874
+ const err = t22;
6875
+ console.error("Google login error:", err);
6876
+ }
6877
+ }
6878
+ });
6778
6879
  };
6779
6880
  $[0] = authController.googleLogin;
6780
6881
  $[1] = googleClientId;
@@ -6782,32 +6883,46 @@ function GoogleLoginButton(t0) {
6782
6883
  } else {
6783
6884
  t1 = $[2];
6784
6885
  }
6785
- const handleGoogleLogin = t1;
6786
6886
  let t2;
6787
- if ($[3] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
6788
- t2 = /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center w-full gap-3 py-1", children: [
6789
- /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", width: "20", height: "20", children: [
6790
- /* @__PURE__ */ jsx("path", { fill: "#4285F4", d: "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z" }),
6791
- /* @__PURE__ */ jsx("path", { fill: "#34A853", d: "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z" }),
6792
- /* @__PURE__ */ jsx("path", { fill: "#FBBC05", d: "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z" }),
6793
- /* @__PURE__ */ jsx("path", { fill: "#EA4335", d: "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z" })
6794
- ] }),
6795
- /* @__PURE__ */ jsx(Typography, { variant: "button", children: "Continue with Google" })
6796
- ] });
6797
- $[3] = t2;
6887
+ if ($[3] !== authController || $[4] !== googleClientId) {
6888
+ t2 = [googleClientId, authController];
6889
+ $[3] = authController;
6890
+ $[4] = googleClientId;
6891
+ $[5] = t2;
6798
6892
  } else {
6799
- t2 = $[3];
6893
+ t2 = $[5];
6800
6894
  }
6895
+ useEffect(t1, t2);
6801
6896
  let t3;
6802
- if ($[4] !== disabled || $[5] !== handleGoogleLogin) {
6803
- t3 = /* @__PURE__ */ jsx(Button, { disabled, className: "w-full", variant: "outlined", size: "large", onClick: handleGoogleLogin, children: t2 });
6804
- $[4] = disabled;
6805
- $[5] = handleGoogleLogin;
6897
+ if ($[6] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
6898
+ t3 = () => {
6899
+ if (!codeClientRef.current) {
6900
+ console.error("Google Sign-In not loaded");
6901
+ return;
6902
+ }
6903
+ codeClientRef.current.requestCode();
6904
+ };
6806
6905
  $[6] = t3;
6807
6906
  } else {
6808
6907
  t3 = $[6];
6809
6908
  }
6810
- return t3;
6909
+ const handleClick = t3;
6910
+ let t4;
6911
+ if ($[7] === /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel")) {
6912
+ t4 = /* @__PURE__ */ jsx(GoogleIcon, {});
6913
+ $[7] = t4;
6914
+ } else {
6915
+ t4 = $[7];
6916
+ }
6917
+ let t5;
6918
+ if ($[8] !== disabled) {
6919
+ t5 = /* @__PURE__ */ jsx(LoginButton, { disabled, text: "Sign in with Google", icon: t4, onClick: handleClick });
6920
+ $[8] = disabled;
6921
+ $[9] = t5;
6922
+ } else {
6923
+ t5 = $[9];
6924
+ }
6925
+ return t5;
6811
6926
  }
6812
6927
  function LoginForm(t0) {
6813
6928
  const $ = c(67);
@@ -7025,7 +7140,7 @@ function LoginForm(t0) {
7025
7140
  const t22 = authController.authLoading || !email || !password;
7026
7141
  let t23;
7027
7142
  if ($[45] !== authController.authLoading || $[46] !== buttonLabel || $[47] !== t22) {
7028
- t23 = /* @__PURE__ */ jsx(LoadingButton, { type: "submit", variant: "filled", className: "w-full mt-1", size: "large", loading: authController.authLoading, disabled: t22, children: buttonLabel });
7143
+ t23 = /* @__PURE__ */ jsx(LoadingButton, { type: "submit", variant: "filled", color: "primary", className: "w-full mt-1", size: "large", loading: authController.authLoading, disabled: t22, children: buttonLabel });
7029
7144
  $[45] = authController.authLoading;
7030
7145
  $[46] = buttonLabel;
7031
7146
  $[47] = t22;
@@ -7348,6 +7463,58 @@ function RebaseAuth(t0) {
7348
7463
  useLayoutEffect(t1, t2);
7349
7464
  return null;
7350
7465
  }
7466
+ function BootstrapAdminBanner({
7467
+ className
7468
+ }) {
7469
+ const userManagement = useInternalUserManagementController();
7470
+ const {
7471
+ user: loggedInUser
7472
+ } = useAuthController();
7473
+ const {
7474
+ t
7475
+ } = useTranslation();
7476
+ const snackbarController = useSnackbarController();
7477
+ const [bootstrapping, setBootstrapping] = useState(false);
7478
+ if (typeof window !== "undefined" && window.location.hostname !== "localhost" && window.location.hostname !== "127.0.0.1") {
7479
+ return null;
7480
+ }
7481
+ if (!userManagement || !loggedInUser) {
7482
+ return null;
7483
+ }
7484
+ const {
7485
+ users,
7486
+ loading: delegateLoading,
7487
+ bootstrapAdmin,
7488
+ usersError
7489
+ } = userManagement;
7490
+ const hasAdmin = users.some((u) => u.roles?.includes("admin"));
7491
+ if (delegateLoading || hasAdmin || usersError || !bootstrapAdmin) {
7492
+ return null;
7493
+ }
7494
+ const handleBootstrap = async () => {
7495
+ if (!bootstrapAdmin) return;
7496
+ setBootstrapping(true);
7497
+ try {
7498
+ await bootstrapAdmin();
7499
+ snackbarController.open({
7500
+ type: "success",
7501
+ message: t("bootstrap_admin_success") || "Admin successfully created"
7502
+ });
7503
+ window.location.reload();
7504
+ } catch (error) {
7505
+ snackbarController.open({
7506
+ type: "error",
7507
+ message: error instanceof Error ? error.message : t("failed_to_bootstrap_admin") || "Failed to bootstrap admin"
7508
+ });
7509
+ } finally {
7510
+ setBootstrapping(false);
7511
+ }
7512
+ };
7513
+ return /* @__PURE__ */ jsxs("div", { className: `bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 rounded p-4 flex items-center justify-between ${className || ""}`, children: [
7514
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Typography, { variant: "label", className: "text-yellow-800 dark:text-yellow-200", children: t("no_users_or_roles_defined") || "No admins found. Click to add your user as admin." }) }),
7515
+ /* @__PURE__ */ jsx(Button, { onClick: handleBootstrap, disabled: bootstrapping, children: bootstrapping ? /* @__PURE__ */ jsx(CircularProgress, { size: "small" }) : t("add_logged_user_as_admin") || "Add logged user as admin" })
7516
+ ] });
7517
+ }
7351
7518
  const en = {
7352
7519
  // ─── Form actions ────────────────────────────────────────────
7353
7520
  save: "Save",
@@ -7388,6 +7555,7 @@ const en = {
7388
7555
  all_entries_loaded: "All {{count}} entries loaded",
7389
7556
  create_your_first_entry: "Create your first entry",
7390
7557
  no_results_filter_sort: "No results with the applied filter/sort",
7558
+ no_results_search: 'No results found for "{{search}}"',
7391
7559
  add: "Add",
7392
7560
  remove: "Remove",
7393
7561
  multiple_entities: "Multiple entities",
@@ -7791,6 +7959,10 @@ const en = {
7791
7959
  reset_password: "Reset Password",
7792
7960
  reset_password_success: "Password reset successfully",
7793
7961
  reset_password_confirmation: "Are you sure you want to reset this user's password?",
7962
+ /** Permission-denied empty states */
7963
+ no_permission_to_view_users: "You don't have permission to view users",
7964
+ no_permission_to_view_roles: "You don't have permission to view roles",
7965
+ no_permission_description: "Contact an administrator if you need access to this section.",
7794
7966
  error_resetting_password: "Error resetting password",
7795
7967
  /** Editor table-bubble */
7796
7968
  add_row_before: "Add row before",
@@ -8256,6 +8428,7 @@ const es = {
8256
8428
  all_entries_loaded: "Todas las {{count}} entradas cargadas",
8257
8429
  create_your_first_entry: "Crea tu primera entrada",
8258
8430
  no_results_filter_sort: "No hay resultados con el filtro/orden aplicado",
8431
+ no_results_search: 'No se encontraron resultados para "{{search}}"',
8259
8432
  add: "Añadir",
8260
8433
  remove: "Quitar",
8261
8434
  multiple_entities: "Múltiples entidades",
@@ -8335,6 +8508,9 @@ const es = {
8335
8508
  delete_user_confirmation: "¿Estás seguro de que quieres eliminar a este usuario?",
8336
8509
  create_your_users_and_roles: "Crea tus usuarios y roles",
8337
8510
  no_users_or_roles_defined: "No tienes usuarios ni roles. Puedes crear los roles por defecto y añadirte a ti mismo como administrador.",
8511
+ no_permission_to_view_users: "No tienes permisos para ver los usuarios",
8512
+ no_permission_to_view_roles: "No tienes permisos para ver los roles",
8513
+ no_permission_description: "Contacta a un administrador si necesitas acceso a esta sección.",
8338
8514
  save_before_changing_schema: "Debes guardar el documento antes de cambiar el esquema",
8339
8515
  edit_schema_for_this_form: "Editar esquema para este formulario",
8340
8516
  no_permissions_to_edit_collection: "No tienes permisos para editar esta colección",
@@ -9098,6 +9274,7 @@ const de = {
9098
9274
  all_entries_loaded: "Alle {{count}} Einträge geladen",
9099
9275
  create_your_first_entry: "Erstellen Sie Ihren ersten Eintrag",
9100
9276
  no_results_filter_sort: "Keine Ergebnisse mit angewendetem Filter/Sortierung",
9277
+ no_results_search: 'Keine Ergebnisse gefunden für "{{search}}"',
9101
9278
  add: "Hinzufügen",
9102
9279
  remove: "Entfernen",
9103
9280
  multiple_entities: "Mehrere Entitäten",
@@ -9179,6 +9356,9 @@ const de = {
9179
9356
  delete_user_confirmation: "Sind Sie sicher, dass Sie diesen Benutzer löschen möchten?",
9180
9357
  create_your_users_and_roles: "Erstellen Sie Ihre Benutzer und Rollen",
9181
9358
  no_users_or_roles_defined: "Sie haben keine Benutzer oder Rollen definiert. Sie können Standardrollen erstellen und den aktuellen Benutzer als Administrator hinzufügen.",
9359
+ no_permission_to_view_users: "Sie haben keine Berechtigung, Benutzer anzuzeigen",
9360
+ no_permission_to_view_roles: "Sie haben keine Berechtigung, Rollen anzuzeigen",
9361
+ no_permission_description: "Wenden Sie sich an einen Administrator, wenn Sie Zugang zu diesem Bereich benötigen.",
9182
9362
  save_before_changing_schema: "Sie müssen das Dokument speichern, bevor Sie das Schema ändern können",
9183
9363
  edit_schema_for_this_form: "Schema für dieses Formular bearbeiten",
9184
9364
  no_permissions_to_edit_collection: "Sie haben keine Berechtigung, diese Sammlung zu bearbeiten",
@@ -9939,6 +10119,7 @@ const fr = {
9939
10119
  all_entries_loaded: "Toutes les {{count}} entrées chargées",
9940
10120
  create_your_first_entry: "Créez votre première entrée",
9941
10121
  no_results_filter_sort: "Aucun résultat avec le filtre/tri appliqué",
10122
+ no_results_search: 'Aucun résultat trouvé pour "{{search}}"',
9942
10123
  add: "Ajouter",
9943
10124
  remove: "Supprimer",
9944
10125
  multiple_entities: "Entités multiples",
@@ -10020,6 +10201,9 @@ const fr = {
10020
10201
  delete_user_confirmation: "Êtes-vous sûr de vouloir supprimer cet utilisateur ?",
10021
10202
  create_your_users_and_roles: "Créez vos utilisateurs et rôles",
10022
10203
  no_users_or_roles_defined: "Vous n'avez défini aucun utilisateur ni rôle. Vous pouvez créer les rôles par défaut et ajouter l'utilisateur actuel en tant qu'administrateur.",
10204
+ no_permission_to_view_users: "Vous n'avez pas la permission de voir les utilisateurs",
10205
+ no_permission_to_view_roles: "Vous n'avez pas la permission de voir les rôles",
10206
+ no_permission_description: "Contactez un administrateur si vous avez besoin d'accéder à cette section.",
10023
10207
  save_before_changing_schema: "Vous devez enregistrer le document avant de modifier le schéma",
10024
10208
  edit_schema_for_this_form: "Modifier le schéma de ce formulaire",
10025
10209
  no_permissions_to_edit_collection: "Vous n'avez pas l'autorisation de modifier cette collection",
@@ -10780,6 +10964,7 @@ const it = {
10780
10964
  all_entries_loaded: "Tutte le {{count}} voci caricate",
10781
10965
  create_your_first_entry: "Crea la tua prima voce",
10782
10966
  no_results_filter_sort: "Nessun risultato con il filtro/ordinamento applicato",
10967
+ no_results_search: 'Nessun risultato trovato per "{{search}}"',
10783
10968
  add: "Aggiungi",
10784
10969
  remove: "Rimuovi",
10785
10970
  multiple_entities: "Entità multiple",
@@ -10861,6 +11046,9 @@ const it = {
10861
11046
  delete_user_confirmation: "Sei sicuro di voler eliminare questo utente?",
10862
11047
  create_your_users_and_roles: "Crea i tuoi utenti e ruoli",
10863
11048
  no_users_or_roles_defined: "Non hai definito né utenti né ruoli. Puoi creare ruoli predefiniti e aggiungere l'utente corrente come amministratore.",
11049
+ no_permission_to_view_users: "Non hai i permessi per visualizzare gli utenti",
11050
+ no_permission_to_view_roles: "Non hai i permessi per visualizzare i ruoli",
11051
+ no_permission_description: "Contatta un amministratore se hai bisogno di accedere a questa sezione.",
10864
11052
  save_before_changing_schema: "Devi salvare il documento prima di modificare lo schema",
10865
11053
  edit_schema_for_this_form: "Modifica lo schema per questo modulo",
10866
11054
  no_permissions_to_edit_collection: "Non hai i permessi per modificare questa collezione",
@@ -11621,6 +11809,7 @@ const hi = {
11621
11809
  all_entries_loaded: "सभी {{count}} प्रविष्टियाँ लोड हो गईं",
11622
11810
  create_your_first_entry: "अपनी पहली प्रविष्टि बनाएं",
11623
11811
  no_results_filter_sort: "लागू किए गए फ़िल्टर/सॉर्ट के साथ कोई परिणाम नहीं",
11812
+ no_results_search: '"{{search}}" के लिए कोई परिणाम नहीं मिला',
11624
11813
  add: "जोड़ें",
11625
11814
  remove: "हटाएं",
11626
11815
  multiple_entities: "एकाधिक इकाइयां",
@@ -11702,6 +11891,9 @@ const hi = {
11702
11891
  delete_user_confirmation: "क्या आप वाकई इस उपयोगकर्ता को हटाना चाहते हैं?",
11703
11892
  create_your_users_and_roles: "अपने उपयोगकर्ता और भूमिकाएँ बनाएँ",
11704
11893
  no_users_or_roles_defined: "आपके पास कोई उपयोगकर्ता या भूमिका परिभाषित नहीं है। आप डिफ़ॉल्ट भूमिकाएँ बना सकते हैं और वर्तमान उपयोगकर्ता को एडमिन के रूप में जोड़ सकते हैं।",
11894
+ no_permission_to_view_users: "आपको उपयोगकर्ताओं को देखने की अनुमति नहीं है",
11895
+ no_permission_to_view_roles: "आपको भूमिकाओं को देखने की अनुमति नहीं है",
11896
+ no_permission_description: "यदि आपको इस अनुभाग तक पहुँच की आवश्यकता है तो किसी व्यवस्थापक से संपर्क करें।",
11705
11897
  save_before_changing_schema: "स्कीमा बदलने से पहले आपको दस्तावेज़ सहेजना होगा",
11706
11898
  edit_schema_for_this_form: "इस फॉर्म के लिए स्कीमा संपादित करें",
11707
11899
  no_permissions_to_edit_collection: "आपके पास इस संग्रह को संपादित करने की अनुमति नहीं है",
@@ -12462,6 +12654,7 @@ const pt = {
12462
12654
  all_entries_loaded: "Todos os {{count}} registos carregados",
12463
12655
  create_your_first_entry: "Crie o seu primeiro registo",
12464
12656
  no_results_filter_sort: "Sem resultados com o filtro/ordenação aplicado",
12657
+ no_results_search: 'Nenhum resultado encontrado para "{{search}}"',
12465
12658
  add: "Adicionar",
12466
12659
  remove: "Remover",
12467
12660
  multiple_entities: "Múltiplas entidades",
@@ -12543,6 +12736,9 @@ const pt = {
12543
12736
  delete_user_confirmation: "Tem a certeza de que quer eliminar este utilizador?",
12544
12737
  create_your_users_and_roles: "Crie os seus utilizadores e funções",
12545
12738
  no_users_or_roles_defined: "Não tem utilizadores ou funções definidas. Pode criar funções predefinidas e adicionar o utilizador atual como administrador.",
12739
+ no_permission_to_view_users: "Não tem permissão para ver os utilizadores",
12740
+ no_permission_to_view_roles: "Não tem permissão para ver as funções",
12741
+ no_permission_description: "Contacte um administrador se precisar de acesso a esta secção.",
12546
12742
  save_before_changing_schema: "Precisa de guardar o documento antes de alterar o esquema",
12547
12743
  edit_schema_for_this_form: "Editar esquema para este formulário",
12548
12744
  no_permissions_to_edit_collection: "Não tem permissões para editar esta coleção",
@@ -13435,18 +13631,19 @@ function Rebase(props) {
13435
13631
  }
13436
13632
  const ws = client?.ws;
13437
13633
  if (ws && typeof ws.executeSql === "function") {
13634
+ const wsAdmin = ws;
13438
13635
  return {
13439
- executeSql: ws.executeSql.bind(ws),
13440
- fetchAvailableDatabases: ws.fetchAvailableDatabases?.bind(ws),
13441
- fetchAvailableRoles: ws.fetchAvailableRoles?.bind(ws),
13442
- fetchCurrentDatabase: ws.fetchCurrentDatabase?.bind(ws),
13443
- fetchUnmappedTables: ws.fetchUnmappedTables?.bind(ws),
13444
- fetchTableMetadata: ws.fetchTableMetadata?.bind(ws),
13636
+ executeSql: wsAdmin.executeSql.bind(wsAdmin),
13637
+ fetchAvailableDatabases: wsAdmin.fetchAvailableDatabases?.bind(wsAdmin),
13638
+ fetchAvailableRoles: wsAdmin.fetchAvailableRoles?.bind(wsAdmin),
13639
+ fetchCurrentDatabase: wsAdmin.fetchCurrentDatabase?.bind(wsAdmin),
13640
+ fetchUnmappedTables: wsAdmin.fetchUnmappedTables?.bind(wsAdmin),
13641
+ fetchTableMetadata: wsAdmin.fetchTableMetadata?.bind(wsAdmin),
13445
13642
  // Branch admin capabilities
13446
- ...typeof ws.createBranch === "function" ? {
13447
- createBranch: ws.createBranch.bind(ws),
13448
- deleteBranch: ws.deleteBranch.bind(ws),
13449
- listBranches: ws.listBranches.bind(ws)
13643
+ ...typeof wsAdmin.createBranch === "function" ? {
13644
+ createBranch: wsAdmin.createBranch.bind(wsAdmin),
13645
+ deleteBranch: wsAdmin.deleteBranch.bind(wsAdmin),
13646
+ listBranches: wsAdmin.listBranches.bind(wsAdmin)
13450
13647
  } : {}
13451
13648
  };
13452
13649
  }
@@ -13508,7 +13705,9 @@ function RebaseInternal(t0) {
13508
13705
  }
13509
13706
  const childrenResult = t1;
13510
13707
  const plugins = customizationController.plugins;
13511
- if (!loading && plugins && plugins.length > 0) {
13708
+ const authController = context.authController;
13709
+ const authReady = !loading && !authController.authLoading && (Boolean(authController.user) || authController.loginSkipped);
13710
+ if (authReady && plugins && plugins.length > 0) {
13512
13711
  let t2;
13513
13712
  if ($[4] !== context) {
13514
13713
  t2 = {
@@ -14260,7 +14459,7 @@ function getEntityPreviewKeys(authController, targetCollection, fields, previewP
14260
14459
  if (listProperties && listProperties.length > 0) {
14261
14460
  return listProperties;
14262
14461
  } else {
14263
- listProperties = allProperties;
14462
+ listProperties = targetCollection.propertiesOrder || allProperties;
14264
14463
  return listProperties.filter((key) => {
14265
14464
  const prop = targetCollection.properties[key];
14266
14465
  const isIdProp = prop && typeof prop === "object" && "isId" in prop && Boolean(prop.isId);
@@ -14275,16 +14474,24 @@ function getEntityTitlePropertyKey(collection, propertyConfigs) {
14275
14474
  if (collection.titleProperty) {
14276
14475
  return collection.titleProperty;
14277
14476
  }
14278
- for (const key in collection.properties) {
14477
+ const orderToSearch = collection.propertiesOrder || Object.keys(collection.properties);
14478
+ let firstStringCandidate;
14479
+ for (const key of orderToSearch) {
14279
14480
  const property = collection.properties[key];
14280
- if (!isPropertyBuilder(property)) {
14481
+ if (property && !isPropertyBuilder(property)) {
14281
14482
  const prop = property;
14282
- if (prop.type === "string" && !prop.multiline && !prop.markdown && !prop.storage && !prop.isId) {
14283
- return key;
14483
+ if (prop.type === "string" && !prop.ui?.multiline && !prop.ui?.markdown && !prop.storage && !prop.isId) {
14484
+ if (!firstStringCandidate) {
14485
+ firstStringCandidate = key;
14486
+ }
14487
+ const lowerKey = key.toLowerCase();
14488
+ if (["name", "title", "label", "displayname", "username"].includes(lowerKey)) {
14489
+ return key;
14490
+ }
14284
14491
  }
14285
14492
  }
14286
14493
  }
14287
- return void 0;
14494
+ return firstStringCandidate;
14288
14495
  }
14289
14496
  function getColorScheme(enumValues, key) {
14290
14497
  const labelOrConfig = getLabelOrConfigFrom(enumValues, key);
@@ -14476,7 +14683,8 @@ const NOOP_COLLECTION_REGISTRY = {
14476
14683
  getCollection: () => void 0,
14477
14684
  getRawCollection: () => void 0,
14478
14685
  getParentReferencesFromPath: () => [],
14479
- getParentCollectionIds: () => [],
14686
+ getParentCollectionSlugs: () => [],
14687
+ getParentEntityIds: () => [],
14480
14688
  convertIdsToPaths: () => [],
14481
14689
  initialised: false
14482
14690
  };
@@ -14625,6 +14833,7 @@ export {
14625
14833
  AnalyticsContext,
14626
14834
  ApiConfigProvider,
14627
14835
  AuthControllerContext,
14836
+ BootstrapAdminBanner,
14628
14837
  CONTAINER_FULL_WIDTH,
14629
14838
  ConfirmationDialog,
14630
14839
  CustomizationControllerContext,
@@ -14668,6 +14877,7 @@ export {
14668
14877
  UserDisplay,
14669
14878
  UserSelectPopover,
14670
14879
  UserSettingsView,
14880
+ buildCollapsedDefaults,
14671
14881
  buildEnumLabel,
14672
14882
  clearEntityCache,
14673
14883
  createFormexStub,
@@ -14693,6 +14903,7 @@ export {
14693
14903
  printChanged,
14694
14904
  removeEntityFromCache,
14695
14905
  removeEntityFromMemoryCache,
14906
+ resolveComponentRef,
14696
14907
  saveEntityToCache,
14697
14908
  saveEntityToMemoryCache,
14698
14909
  saveEntityWithCallbacks,
@@ -14728,6 +14939,7 @@ export {
14728
14939
  useRebaseRegistry,
14729
14940
  useRebaseRegistryDispatch,
14730
14941
  useRelationSelector,
14942
+ useResolvedComponent,
14731
14943
  useRestoreScroll,
14732
14944
  useScrollRestoration,
14733
14945
  useSlot,