@rebasepro/app 0.14.0 → 0.14.1-canary.g7e666eb

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.
@@ -1,4 +1,4 @@
1
- import type { FindParams, FilterValues, LogicalCondition } from "@rebasepro/types";
1
+ import type { FindParams, FilterValues, LogicalCondition, OrderBySpec } from "@rebasepro/types";
2
2
  /**
3
3
  * The one place a collection read's parameters are assembled.
4
4
  *
@@ -23,12 +23,12 @@ export interface CollectionQueryInput<M extends Record<string, unknown>> {
23
23
  logical?: LogicalCondition;
24
24
  /**
25
25
  * Loosened from `FindParams["orderBy"]` on purpose: callers hold the sort
26
- * as a plain `[string, direction]` read off user config or a URL, where the
27
- * column is not statically known. Narrowing it here would push a cast onto
28
- * every call site, which is the kind of friction that sends people back to
29
- * hand-building the object this exists to replace.
26
+ * as plain `[string, direction]` pairs read off user config or a URL, where
27
+ * the columns are not statically known. Narrowing it here would push a cast
28
+ * onto every call site, which is the kind of friction that sends people back
29
+ * to hand-building the object this exists to replace.
30
30
  */
31
- orderBy?: [string, "asc" | "desc"];
31
+ orderBy?: OrderBySpec;
32
32
  limit?: number;
33
33
  offset?: number;
34
34
  page?: number;
package/dist/index.es.js CHANGED
@@ -4,7 +4,7 @@ import { ALL_WHERE_FILTER_OPS, DEFAULT_DATA_SOURCE_KEY, DEFAULT_FILTERABLE_RELAT
4
4
  import { UNRENDERED_SLOTS, resolveAdminCollection } from "@rebasepro/admin-types";
5
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
6
  import { SnackbarProvider as SnackbarProvider$1, useSnackbar } from "notistack";
7
- import { buildRebaseData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, evaluateCondition, getChildViewDeclaringProperties, getChildViewRelationPropertyKeys, getEntityChildViews, getLabelOrConfigFrom, getPrimaryKeys, getSubcollections, isPropertyBuilder, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, stripCollectionPath, wrapAsEntityData, wrapAsSdkData } from "@rebasepro/common";
7
+ import { buildRebaseData, canCreateEntity, canDeleteEntity, canEditEntity, canReadCollection, evaluateCondition, getChildViewDeclaringProperties, getChildViewRelationPropertyKeys, getEntityChildViews, getLabelOrConfigFrom, getPrimaryKeys, getSubcollections, isPropertyBuilder, normalizeOrderBy, resolveStorageFilenameString, resolveStoragePathString, resolveStorageSource, serializeOrderBy, stripCollectionPath, wrapAsEntityData, wrapAsSdkData } from "@rebasepro/common";
8
8
  import { getTitlePropertyKey as getTitlePropertyKey$1, removeInitialAndTrailingSlashes as removeInitialAndTrailingSlashes$1 } from "@rebasepro/app";
9
9
  import { Link, Routes, createBrowserRouter, useBlocker, useLocation } from "react-router";
10
10
  import { generateForeignKeyName, hashString, isArrayValue, isObject, isPlainObject, isRecordValue, mergeDeep, randomString, readStoredJson, slugify, writeStoredJson } from "@rebasepro/utils";
@@ -2859,11 +2859,12 @@ function useDataTableController({ path, collection, scrollRestoration, entitiesD
2859
2859
  return true;
2860
2860
  }, []);
2861
2861
  const sortInternal = useMemo(() => {
2862
- if (sort && fixedFilter && !checkFilterCombination(fixedFilter, sort)) {
2862
+ const keys = normalizeOrderBy(sort);
2863
+ if (keys && fixedFilter && !checkFilterCombination(fixedFilter, keys)) {
2863
2864
  console.warn("Initial sort is not compatible with the force filter. Ignoring initial sort");
2864
2865
  return;
2865
2866
  }
2866
- return sort;
2867
+ return keys;
2867
2868
  }, [sort, fixedFilter]);
2868
2869
  const { filterValues: filterUrl, sortBy: sortUrl } = parseFilterAndSort(location.search);
2869
2870
  const [filterValues, setFilterValues] = React.useState(fixedFilter ?? (updateUrl ? filterUrl : void 0) ?? defaultFilter ?? void 0);
@@ -2900,8 +2901,7 @@ function useDataTableController({ path, collection, scrollRestoration, entitiesD
2900
2901
  });
2901
2902
  }, []);
2902
2903
  const [itemCount, setItemCount] = React.useState(paginationEnabled ? initialItemCount : void 0);
2903
- const sortByProperty = sortBy ? sortBy[0] : void 0;
2904
- const currentSort = sortBy ? sortBy[1] : void 0;
2904
+ const sortKey = sortBy ? serializeOrderBy(sortBy) : void 0;
2905
2905
  const context = useRebaseContext();
2906
2906
  const [rawData, setRawData] = useState(collectionScroll?.data ?? []);
2907
2907
  const onScroll = useCallback(({ scrollOffset }) => {
@@ -2965,7 +2965,7 @@ function useDataTableController({ path, collection, scrollRestoration, entitiesD
2965
2965
  };
2966
2966
  const accessor = dataClient.collection(path);
2967
2967
  const whereParams = filterValues && Object.keys(filterValues).length > 0 ? filterValues : void 0;
2968
- const orderByParams = sortBy ? [String(sortBy[0]), sortBy[1]] : void 0;
2968
+ const orderByParams = sortBy && sortBy.length > 0 ? sortBy.map(([field, direction]) => [String(field), direction]) : void 0;
2969
2969
  let unsubscribe;
2970
2970
  const includeParams = getRelationIncludeParams(collection);
2971
2971
  if (accessor.listen) unsubscribe = accessor.listen(toFindParams({
@@ -2990,8 +2990,7 @@ function useDataTableController({ path, collection, scrollRestoration, entitiesD
2990
2990
  dataClient,
2991
2991
  path,
2992
2992
  itemCount,
2993
- currentSort,
2994
- sortByProperty,
2993
+ sortKey,
2995
2994
  filterValues,
2996
2995
  searchString
2997
2996
  ]);
@@ -3067,9 +3066,9 @@ function useUpdateUrl(filterValues, sortBy, searchString, updateUrl) {
3067
3066
  }
3068
3067
  function encodeFilterAndSort(filterValues, sortBy) {
3069
3068
  const entries = {};
3070
- if (sortBy) {
3071
- entries["__sort"] = encodeURIComponent(sortBy[0]);
3072
- entries["__sort_order"] = encodeURIComponent(sortBy[1]);
3069
+ if (sortBy && sortBy.length > 0) {
3070
+ entries["__sort"] = sortBy.map(([field]) => encodeURIComponent(field)).join(",");
3071
+ entries["__sort_order"] = sortBy.map(([, direction]) => direction).join(",");
3073
3072
  }
3074
3073
  if (filterValues) Object.entries(filterValues).forEach(([key, value]) => {
3075
3074
  if (value) {
@@ -3105,8 +3104,11 @@ function parseFilterAndSort(search) {
3105
3104
  const filterValues = {};
3106
3105
  let sortBy = void 0;
3107
3106
  entries.forEach((value, key) => {
3108
- if (key === "__sort") sortBy = [decodeURIComponent(value), entries.get("__sort_order")];
3109
- else if (key.endsWith("_op")) {
3107
+ if (key === "__sort") {
3108
+ const directions = (entries.get("__sort_order") ?? "").split(",");
3109
+ const keys = value.split(",").map((field) => decodeURIComponent(field).trim()).filter(Boolean).map((field, index) => [field, directions[index] === "desc" ? "desc" : "asc"]);
3110
+ sortBy = keys.length > 0 ? keys : void 0;
3111
+ } else if (key.endsWith("_op")) {
3110
3112
  const field = key.replace("_op", "");
3111
3113
  const filterOp = decodeURIComponent(value);
3112
3114
  const filterValStr = entries.get(`${field}_value`);
@@ -3408,6 +3410,7 @@ var UIStyleGuide = () => {
3408
3410
  children: variant
3409
3411
  }), /* @__PURE__ */ jsxs(Typography, {
3410
3412
  variant,
3413
+ component: "p",
3411
3414
  children: [
3412
3415
  "The quick brown fox jumps over the lazy dog (",
3413
3416
  variant,
@@ -5899,10 +5902,10 @@ function CrmDashboardDemo() {
5899
5902
  children: [
5900
5903
  /* @__PURE__ */ jsxs("div", {
5901
5904
  className: "flex flex-col sm:flex-row sm:items-end justify-between mb-6 gap-4",
5902
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs(Typography, {
5905
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
5903
5906
  variant: "h4",
5904
5907
  className: "tracking-tight",
5905
- children: [getGreeting(), " 👋"]
5908
+ children: getGreeting()
5906
5909
  }), /* @__PURE__ */ jsxs(Typography, {
5907
5910
  variant: "body2",
5908
5911
  color: "secondary",
@@ -7800,6 +7803,7 @@ function UIReferenceView() {
7800
7803
  children: v
7801
7804
  }), /* @__PURE__ */ jsx(Typography, {
7802
7805
  variant: v,
7806
+ component: "p",
7803
7807
  children: "The quick brown fox jumps over the lazy dog"
7804
7808
  })]
7805
7809
  }, v))