@datum-cloud/activity-ui 0.7.0 → 0.7.1-dev.0ada97a

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.
@@ -47,6 +47,16 @@ export interface ActivityFeedProps {
47
47
  loadMoreThreshold?: number;
48
48
  /** Handler called when user wants to create a policy (for empty state) */
49
49
  onCreatePolicy?: () => void;
50
+ /**
51
+ * Whether to probe ActivityPolicies to decide between the "No Policies"
52
+ * and "No activities found" empty states (default: false).
53
+ *
54
+ * ActivityPolicy is a Platform-scope resource. Tenant-scoped clients
55
+ * (Project, Organization, User) cannot list it and always receive a 403,
56
+ * so leave this off in tenant UIs. Enable it only in platform-operator
57
+ * UIs that have access to the Platform scope.
58
+ */
59
+ checkPolicies?: boolean;
50
60
  /** Enable real-time streaming (default: false) */
51
61
  enableStreaming?: boolean;
52
62
  /** Callback invoked when the effective time range is resolved */
@@ -67,5 +77,5 @@ export interface ActivityFeedProps {
67
77
  * ActivityFeed displays a chronological list of activities with filtering and pagination.
68
78
  * Supports optional real-time streaming of new activities.
69
79
  */
70
- export declare function ActivityFeed({ client, initialFilters, initialTimeRange, pageSize, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact, variant, resourceUid, showFilters, hiddenFilters, className, infiniteScroll, loadMoreThreshold, onCreatePolicy, enableStreaming, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }: ActivityFeedProps): import("react/jsx-runtime").JSX.Element;
80
+ export declare function ActivityFeed({ client, initialFilters, initialTimeRange, pageSize, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact, variant, resourceUid, showFilters, hiddenFilters, className, infiniteScroll, loadMoreThreshold, onCreatePolicy, checkPolicies, enableStreaming, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }: ActivityFeedProps): import("react/jsx-runtime").JSX.Element;
71
81
  //# sourceMappingURL=ActivityFeed.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ActivityFeed.d.ts","sourceRoot":"","sources":["../../src/components/ActivityFeed.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,mBAAmB,IAAI,WAAW,EAClC,SAAS,EACV,MAAM,0BAA0B,CAAC;AAYlC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAoBlD,MAAM,WAAW,iBAAiB;IAChC,0BAA0B;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,8BAA8B;IAC9B,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAClD,yDAAyD;IACzD,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,uDAAuD;IACvD,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,wEAAwE;IACxE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iDAAiD;IACjD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC/C,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IACzC,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,KAAK,CACjB,eAAe,GACf,YAAY,GACZ,WAAW,GACX,oBAAoB,GACpB,cAAc,GACd,cAAc,CACjB,CAAC;IACF,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,kDAAkD;IAClD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,0BAA0B,CAAC,EAAE,0BAA0B,CAAC;IACxD,4DAA4D;IAC5D,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;CACxE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,cAA0C,EAC1C,gBAAsC,EACtC,QAAa,EACb,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,OAAe,EACf,OAAgB,EAChB,WAAW,EACX,WAAkB,EAClB,aAAkB,EAClB,SAAc,EACd,cAAqB,EACrB,iBAAuB,EACvB,cAAc,EACd,eAAuB,EACvB,0BAA0B,EAC1B,cAAc,EACd,SAAS,EACT,eAAe,EAAE,mBAAmB,GACrC,EAAE,iBAAiB,2CAygBnB"}
1
+ {"version":3,"file":"ActivityFeed.d.ts","sourceRoot":"","sources":["../../src/components/ActivityFeed.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,QAAQ,EACR,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,0BAA0B,EAC1B,cAAc,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,mBAAmB,IAAI,WAAW,EAClC,SAAS,EACV,MAAM,0BAA0B,CAAC;AAYlC,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAoBlD,MAAM,WAAW,iBAAiB;IAChC,0BAA0B;IAC1B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,8BAA8B;IAC9B,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,SAAS,CAAC;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4FAA4F;IAC5F,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAClD,yDAAyD;IACzD,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,uDAAuD;IACvD,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;IACxC,wEAAwE;IACxE,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,iDAAiD;IACjD,eAAe,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC/C,iEAAiE;IACjE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;IACzC,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4FAA4F;IAC5F,aAAa,CAAC,EAAE,KAAK,CACjB,eAAe,GACf,YAAY,GACZ,WAAW,GACX,oBAAoB,GACpB,cAAc,GACd,cAAc,CACjB,CAAC;IACF,2BAA2B;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6CAA6C;IAC7C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,0EAA0E;IAC1E,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,0BAA0B,CAAC,EAAE,0BAA0B,CAAC;IACxD,4DAA4D;IAC5D,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2FAA2F;IAC3F,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;CACxE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,cAA0C,EAC1C,gBAAsC,EACtC,QAAa,EACb,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,OAAe,EACf,OAAgB,EAChB,WAAW,EACX,WAAkB,EAClB,aAAkB,EAClB,SAAc,EACd,cAAqB,EACrB,iBAAuB,EACvB,cAAc,EACd,aAAqB,EACrB,eAAuB,EACvB,0BAA0B,EAC1B,cAAc,EACd,SAAS,EACT,eAAe,EAAE,mBAAmB,GACrC,EAAE,iBAAiB,2CAihBnB"}
package/dist/index.esm.js CHANGED
@@ -10562,7 +10562,7 @@ function getActorInitials(name) {
10562
10562
  * Get Tailwind classes for actor avatar based on actor type
10563
10563
  */
10564
10564
  function getActorAvatarClasses(actorType, compact) {
10565
- const baseClasses = cn("rounded-full flex items-center justify-center shrink-0 font-semibold", compact ? "w-5 h-5 text-1xs" : "w-6 h-6 text-1xs");
10565
+ const baseClasses = cn("rounded-full flex items-center justify-center shrink-0 font-semibold", compact ? "w-5 h-5 text-2xs" : "w-6 h-6 text-2xs");
10566
10566
  switch (actorType) {
10567
10567
  case "user":
10568
10568
  return cn(baseClasses, "bg-primary text-primary-foreground");
@@ -11297,7 +11297,7 @@ function groupActivitiesByDay(activities) {
11297
11297
  * ActivityFeed displays a chronological list of activities with filtering and pagination.
11298
11298
  * Supports optional real-time streaming of new activities.
11299
11299
  */
11300
- function ActivityFeed({ client, initialFilters = { changeSource: "human" }, initialTimeRange = { start: "now-7d" }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, variant = "feed", resourceUid, showFilters = true, hiddenFilters = [], className = "", infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
11300
+ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, initialTimeRange = { start: "now-7d" }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, variant = "feed", resourceUid, showFilters = true, hiddenFilters = [], className = "", infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, checkPolicies = false, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
11301
11301
  // Merge resourceUid into initial filters if provided
11302
11302
  const mergedInitialFilters = {
11303
11303
  ...initialFilters,
@@ -11316,12 +11316,19 @@ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, init
11316
11316
  const loadMoreTriggerRef = useRef(null);
11317
11317
  // Store the latest loadMore function in a ref to avoid observer re-subscription
11318
11318
  const loadMoreRef = useRef(loadMore);
11319
- // Track whether policies exist in the system
11319
+ // Track whether policies exist in the system. Null means unknown: neither
11320
+ // empty state is shown, so tenants never see the policy prompt.
11320
11321
  const [hasPolicies, setHasPolicies] = useState(null);
11321
- const [policiesLoading, setPoliciesLoading] = useState(true);
11322
- // Check for policies on mount
11322
+ const [policiesLoading, setPoliciesLoading] = useState(checkPolicies);
11323
+ // Check for policies on mount, but only when the host opts in. Tenant
11324
+ // clients cannot list the Platform-scope ActivityPolicy resource.
11323
11325
  useEffect(() => {
11324
- const checkPolicies = async () => {
11326
+ if (!checkPolicies) {
11327
+ setHasPolicies(null);
11328
+ setPoliciesLoading(false);
11329
+ return;
11330
+ }
11331
+ const probePolicies = async () => {
11325
11332
  try {
11326
11333
  const policyList = await client.listPolicies();
11327
11334
  setHasPolicies((policyList.items?.length ?? 0) > 0);
@@ -11334,8 +11341,8 @@ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, init
11334
11341
  setPoliciesLoading(false);
11335
11342
  }
11336
11343
  };
11337
- checkPolicies();
11338
- }, [client]);
11344
+ probePolicies();
11345
+ }, [client, checkPolicies]);
11339
11346
  // Auto-execute on mount
11340
11347
  useEffect(() => {
11341
11348
  refresh();
@@ -15369,7 +15376,9 @@ function serializeActivityFilters(filters, timeRange, streamingEnabled = true) {
15369
15376
  if (!streamingEnabled) {
15370
15377
  params.set('streaming', 'false');
15371
15378
  }
15372
- if (filters.changeSource && filters.changeSource !== 'human') {
15379
+ // Written even when it matches a default: the default differs between
15380
+ // pages, so an omitted value can't be read back as the one chosen.
15381
+ if (filters.changeSource) {
15373
15382
  params.set('changeSource', filters.changeSource);
15374
15383
  }
15375
15384
  if (filters.actorNames && filters.actorNames.length > 0) {
@@ -15433,12 +15442,11 @@ function serializeEventFilters(filters, timeRange, streamingEnabled = true) {
15433
15442
  function parseActivityFilters(searchParams) {
15434
15443
  const filters = {};
15435
15444
  const changeSource = searchParams.get('changeSource');
15445
+ // Left unset when absent so the caller's default applies. Filling in
15446
+ // 'human' here overrode pages that default to 'all'.
15436
15447
  if (changeSource === 'human' || changeSource === 'system' || changeSource === 'all') {
15437
15448
  filters.changeSource = changeSource;
15438
15449
  }
15439
- else {
15440
- filters.changeSource = 'human';
15441
- }
15442
15450
  const actorNames = searchParams.get('actorNames');
15443
15451
  if (actorNames) {
15444
15452
  filters.actorNames = actorNames.split(',').filter(Boolean);