@colixsystems/widget-sdk 0.213.0 → 0.214.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.
- package/README.md +10 -2
- package/dist/contract.cjs +35 -4
- package/dist/contract.js +35 -4
- package/dist/index.d.ts +23 -1
- package/dist/index.js +1 -0
- package/dist/index.native.js +1 -0
- package/dist/stats-hooks.js +22 -3
- package/package.json +1 -1
- package/src/contract.js +35 -4
package/README.md
CHANGED
|
@@ -83,7 +83,15 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
83
83
|
|
|
84
84
|
## Status
|
|
85
85
|
|
|
86
|
-
`v0.
|
|
86
|
+
`v0.214.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
87
|
+
|
|
88
|
+
### What's new in 0.214.0 (contract 1.173.0)
|
|
89
|
+
|
|
90
|
+
**Who is behind a figure — `useActiveUsers({ within, group_id, limit, offset })`.** One page of the users seen within `within` — `"online"` (default; the app open in the last two minutes), `"day"` (since midnight in the workspace's time zone), `"week"` or `"month"` (the last 7 / 30 days) — most recently seen first, as `[{ id, name, last_active_at, last_platform }]` with `total` for paging. Same gate as `useUserActivity` (`users.activity:*` plus the "View user activity" permission); pass `null` to read nothing.
|
|
91
|
+
|
|
92
|
+
**"Who joined" — `useUsers({ joined_since, sort: "newest" })`.** The admin user list narrows to users created since `joined_since` (a `YYYY-MM-DD` date read in the workspace's time zone, or an ISO instant) and lists them newest first. Join dates are admin data, so a caller with only the directory view gets the plain list.
|
|
93
|
+
|
|
94
|
+
**Reminding several — `remind(id, message, { refetch: false })`.** `useInactiveUsers`' `remind` re-reads the page after each reminder; pass `{ refetch: false }` while sending a batch and call `refetch()` once at the end.
|
|
87
95
|
|
|
88
96
|
### What's new in 0.213.0 (contract 1.172.0)
|
|
89
97
|
|
|
@@ -246,7 +254,7 @@ Like the `loading` scope, `alert` styles an SDK component rather than a widget's
|
|
|
246
254
|
|
|
247
255
|
**An app's user totals for its own admins — `useUserStats({ days, group_id })`.** Active and deactivated users, new users per day (7 / 30 days) or week (90 days) with the previous period's total beside them, users in no group, empty groups, and invite figures. Totals only — never a list of people. Needs `users.read:*` and the viewer's admin user access (else `error.code === "FORBIDDEN"`); `stats.invites` is null unless the widget also declares `users.write:*` and the viewer holds it.
|
|
248
256
|
|
|
249
|
-
**User activity — `useUserActivity({ days, group_id })` and `useInactiveUsers({ inactive_days, group_id, limit, offset })`.** For a workspace that records user activity: who is online now, active in the last day / week / month, never active, active users per day or week, the web / iOS / Android split and the active share per group — and a page of the users not seen recently, never-seen first. Needs `users.activity:*` and the viewer's "View user activity" permission (else `error.code === "FORBIDDEN"`); when the workspace does not record activity, `error.reason === "ACTIVITY_DISABLED"` — show that, not zeros. Before user activity is offered to the workspace at all, `error.reason` is `"ACTIVITY_UNAVAILABLE"`: hide the section, as for `FORBIDDEN`. `useInactiveUsers` also returns `remind(userId, { title, body })`, which notifies one of them and records when (each row carries `last_reminded_at`). Days follow the workspace's time zone (`period.time_zone`).
|
|
257
|
+
**User activity — `useUserActivity({ days, group_id })` and `useInactiveUsers({ inactive_days, group_id, limit, offset })`.** For a workspace that records user activity: who is online now, active in the last day / week / month, never active, active users per day or week, the web / iOS / Android split and the active share per group — and a page of the users not seen recently, never-seen first. Needs `users.activity:*` and the viewer's "View user activity" permission (else `error.code === "FORBIDDEN"`); when the workspace does not record activity, `error.reason === "ACTIVITY_DISABLED"` — show that, not zeros. Before user activity is offered to the workspace at all, `error.reason` is `"ACTIVITY_UNAVAILABLE"`: hide the section, as for `FORBIDDEN`. `useInactiveUsers` also returns `remind(userId, { title, body })`, which notifies one of them and records when (each row carries `last_reminded_at`); pass `{ refetch: false }` as a third argument when reminding several, then call `refetch()` once. Days follow the workspace's time zone (`period.time_zone`).
|
|
250
258
|
|
|
251
259
|
**Linter fix.** A widget that uses `useGroups` or `useUsers` is no longer refused for a write it never makes: `StyleSheet.create(...)` and an event subscription's bare `remove()` (an `AppState` listener, say) are not user or group writes.
|
|
252
260
|
|
package/dist/contract.cjs
CHANGED
|
@@ -1960,7 +1960,9 @@ const HOOKS = [
|
|
|
1960
1960
|
"Returns { users, loading, error, refetch, invite, deactivate, " +
|
|
1961
1961
|
"reactivate, remove, sendPasswordReset, update }. " +
|
|
1962
1962
|
"list returns the { data, meta } envelope verbatim — the hook unwraps " +
|
|
1963
|
-
"res.data; rows are snake_case (is_active, …).
|
|
1963
|
+
"res.data; rows are snake_case (is_active, created_at, …). For an admin, " +
|
|
1964
|
+
"query { joined_since, sort: \"newest\" } lists who joined since a date " +
|
|
1965
|
+
"(read in the workspace's time zone), newest first. Reads need users.read:* " +
|
|
1964
1966
|
"scope; edit-style mutations (invite/deactivate/reactivate/" +
|
|
1965
1967
|
"sendPasswordReset/update) need users.write:*, and the destructive remove() " +
|
|
1966
1968
|
"additionally needs users.delete:* (SC-902). The `invite` call accepts " +
|
|
@@ -2082,6 +2084,30 @@ const HOOKS = [
|
|
|
2082
2084
|
requiredContextSlice: ["directory.users"],
|
|
2083
2085
|
scopes: ["users.activity:*"],
|
|
2084
2086
|
},
|
|
2087
|
+
// sc-11066 — who was seen in a window, behind users.activity.
|
|
2088
|
+
{
|
|
2089
|
+
name: "useActiveUsers",
|
|
2090
|
+
signature: "useActiveUsers({ within, group_id, limit, offset } | null)",
|
|
2091
|
+
optionalArgs: ["within", "group_id", "limit", "offset"],
|
|
2092
|
+
description:
|
|
2093
|
+
"One page of users seen within `within`: \"online\" (default; the app " +
|
|
2094
|
+
"open in the last two minutes), \"day\" (since midnight in the " +
|
|
2095
|
+
"workspace's time zone), \"week\" or \"month\" (the last 7 / 30 days), " +
|
|
2096
|
+
"most recently seen first: `users` = [{ id, name, last_active_at, " +
|
|
2097
|
+
"last_platform }], `total` for paging. Use it to show WHO is behind an " +
|
|
2098
|
+
"online or active figure. Same gate and errors as useUserActivity; null " +
|
|
2099
|
+
"reads nothing.",
|
|
2100
|
+
returnShape: {
|
|
2101
|
+
users: "Array<{ id, name, last_active_at, last_platform }>",
|
|
2102
|
+
total: "number | null",
|
|
2103
|
+
loading: "boolean",
|
|
2104
|
+
fetching: "boolean",
|
|
2105
|
+
error: "DirectoryError | null",
|
|
2106
|
+
refetch: "() => Promise<void>",
|
|
2107
|
+
},
|
|
2108
|
+
requiredContextSlice: ["directory.users"],
|
|
2109
|
+
scopes: ["users.activity:*"],
|
|
2110
|
+
},
|
|
2085
2111
|
{
|
|
2086
2112
|
name: "useInactiveUsers",
|
|
2087
2113
|
signature: "useInactiveUsers({ inactive_days, group_id, limit, offset } | null)",
|
|
@@ -2091,7 +2117,8 @@ const HOOKS = [
|
|
|
2091
2117
|
"never-seen first, then least recently seen: `users` = [{ id, name, " +
|
|
2092
2118
|
"last_active_at, last_reminded_at }] (last_active_at null = never seen " +
|
|
2093
2119
|
"since recording began), `total` for paging. `remind(id, { title, body })` " +
|
|
2094
|
-
"notifies one of them, records when (last_reminded_at) and re-reads
|
|
2120
|
+
"notifies one of them, records when (last_reminded_at) and re-reads; " +
|
|
2121
|
+
"pass `{ refetch: false }` third to skip the re-read in a batch. " +
|
|
2095
2122
|
"Same gate and errors as useUserActivity; null reads nothing.",
|
|
2096
2123
|
returnShape: {
|
|
2097
2124
|
users: "Array<{ id, name, last_active_at, last_reminded_at }>",
|
|
@@ -2100,7 +2127,7 @@ const HOOKS = [
|
|
|
2100
2127
|
fetching: "boolean",
|
|
2101
2128
|
error: "DirectoryError | null",
|
|
2102
2129
|
refetch: "() => Promise<void>",
|
|
2103
|
-
remind: "(id, { title, body }) => Promise<void>",
|
|
2130
|
+
remind: "(id, { title, body }, { refetch? }) => Promise<void>",
|
|
2104
2131
|
},
|
|
2105
2132
|
requiredContextSlice: ["directory.users"],
|
|
2106
2133
|
scopes: ["users.activity:*"],
|
|
@@ -5640,7 +5667,11 @@ const CONTRACT = deepFreeze({
|
|
|
5640
5667
|
// and cancel labels, `tone` "default" | "destructive", `busy`). No new
|
|
5641
5668
|
// theme scope: the panel reads `modal`, the actions `button` and
|
|
5642
5669
|
// `destructive`. `Button` forwards a ref to its pressable.
|
|
5643
|
-
|
|
5670
|
+
// 1.173.0: additive (sc-11066) — `useActiveUsers(query)` lists who was
|
|
5671
|
+
// seen online / today / in 7 or 30 days through the new
|
|
5672
|
+
// `ctx.directory.users.active`; `useUsers` takes `joined_since` and
|
|
5673
|
+
// `sort: "newest"` for an admin's "who joined" list.
|
|
5674
|
+
version: "1.173.0",
|
|
5644
5675
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
5645
5676
|
hooks: HOOKS,
|
|
5646
5677
|
primitives: PRIMITIVES,
|
package/dist/contract.js
CHANGED
|
@@ -1960,7 +1960,9 @@ const HOOKS = [
|
|
|
1960
1960
|
"Returns { users, loading, error, refetch, invite, deactivate, " +
|
|
1961
1961
|
"reactivate, remove, sendPasswordReset, update }. " +
|
|
1962
1962
|
"list returns the { data, meta } envelope verbatim — the hook unwraps " +
|
|
1963
|
-
"res.data; rows are snake_case (is_active, …).
|
|
1963
|
+
"res.data; rows are snake_case (is_active, created_at, …). For an admin, " +
|
|
1964
|
+
"query { joined_since, sort: \"newest\" } lists who joined since a date " +
|
|
1965
|
+
"(read in the workspace's time zone), newest first. Reads need users.read:* " +
|
|
1964
1966
|
"scope; edit-style mutations (invite/deactivate/reactivate/" +
|
|
1965
1967
|
"sendPasswordReset/update) need users.write:*, and the destructive remove() " +
|
|
1966
1968
|
"additionally needs users.delete:* (SC-902). The `invite` call accepts " +
|
|
@@ -2082,6 +2084,30 @@ const HOOKS = [
|
|
|
2082
2084
|
requiredContextSlice: ["directory.users"],
|
|
2083
2085
|
scopes: ["users.activity:*"],
|
|
2084
2086
|
},
|
|
2087
|
+
// sc-11066 — who was seen in a window, behind users.activity.
|
|
2088
|
+
{
|
|
2089
|
+
name: "useActiveUsers",
|
|
2090
|
+
signature: "useActiveUsers({ within, group_id, limit, offset } | null)",
|
|
2091
|
+
optionalArgs: ["within", "group_id", "limit", "offset"],
|
|
2092
|
+
description:
|
|
2093
|
+
"One page of users seen within `within`: \"online\" (default; the app " +
|
|
2094
|
+
"open in the last two minutes), \"day\" (since midnight in the " +
|
|
2095
|
+
"workspace's time zone), \"week\" or \"month\" (the last 7 / 30 days), " +
|
|
2096
|
+
"most recently seen first: `users` = [{ id, name, last_active_at, " +
|
|
2097
|
+
"last_platform }], `total` for paging. Use it to show WHO is behind an " +
|
|
2098
|
+
"online or active figure. Same gate and errors as useUserActivity; null " +
|
|
2099
|
+
"reads nothing.",
|
|
2100
|
+
returnShape: {
|
|
2101
|
+
users: "Array<{ id, name, last_active_at, last_platform }>",
|
|
2102
|
+
total: "number | null",
|
|
2103
|
+
loading: "boolean",
|
|
2104
|
+
fetching: "boolean",
|
|
2105
|
+
error: "DirectoryError | null",
|
|
2106
|
+
refetch: "() => Promise<void>",
|
|
2107
|
+
},
|
|
2108
|
+
requiredContextSlice: ["directory.users"],
|
|
2109
|
+
scopes: ["users.activity:*"],
|
|
2110
|
+
},
|
|
2085
2111
|
{
|
|
2086
2112
|
name: "useInactiveUsers",
|
|
2087
2113
|
signature: "useInactiveUsers({ inactive_days, group_id, limit, offset } | null)",
|
|
@@ -2091,7 +2117,8 @@ const HOOKS = [
|
|
|
2091
2117
|
"never-seen first, then least recently seen: `users` = [{ id, name, " +
|
|
2092
2118
|
"last_active_at, last_reminded_at }] (last_active_at null = never seen " +
|
|
2093
2119
|
"since recording began), `total` for paging. `remind(id, { title, body })` " +
|
|
2094
|
-
"notifies one of them, records when (last_reminded_at) and re-reads
|
|
2120
|
+
"notifies one of them, records when (last_reminded_at) and re-reads; " +
|
|
2121
|
+
"pass `{ refetch: false }` third to skip the re-read in a batch. " +
|
|
2095
2122
|
"Same gate and errors as useUserActivity; null reads nothing.",
|
|
2096
2123
|
returnShape: {
|
|
2097
2124
|
users: "Array<{ id, name, last_active_at, last_reminded_at }>",
|
|
@@ -2100,7 +2127,7 @@ const HOOKS = [
|
|
|
2100
2127
|
fetching: "boolean",
|
|
2101
2128
|
error: "DirectoryError | null",
|
|
2102
2129
|
refetch: "() => Promise<void>",
|
|
2103
|
-
remind: "(id, { title, body }) => Promise<void>",
|
|
2130
|
+
remind: "(id, { title, body }, { refetch? }) => Promise<void>",
|
|
2104
2131
|
},
|
|
2105
2132
|
requiredContextSlice: ["directory.users"],
|
|
2106
2133
|
scopes: ["users.activity:*"],
|
|
@@ -5636,7 +5663,11 @@ const CONTRACT = deepFreeze({
|
|
|
5636
5663
|
// and cancel labels, `tone` "default" | "destructive", `busy`). No new
|
|
5637
5664
|
// theme scope: the panel reads `modal`, the actions `button` and
|
|
5638
5665
|
// `destructive`. `Button` forwards a ref to its pressable.
|
|
5639
|
-
|
|
5666
|
+
// 1.173.0: additive (sc-11066) — `useActiveUsers(query)` lists who was
|
|
5667
|
+
// seen online / today / in 7 or 30 days through the new
|
|
5668
|
+
// `ctx.directory.users.active`; `useUsers` takes `joined_since` and
|
|
5669
|
+
// `sort: "newest"` for an admin's "who joined" list.
|
|
5670
|
+
version: "1.173.0",
|
|
5640
5671
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
5641
5672
|
hooks: HOOKS,
|
|
5642
5673
|
primitives: PRIMITIVES,
|
package/dist/index.d.ts
CHANGED
|
@@ -1107,6 +1107,21 @@ export function useUserActivity(query?: { days?: 7 | 30 | 90; group_id?: string
|
|
|
1107
1107
|
refetch(): Promise<void>;
|
|
1108
1108
|
};
|
|
1109
1109
|
|
|
1110
|
+
/** Users seen within `within` (default "online"), most recently seen first. */
|
|
1111
|
+
export function useActiveUsers(query?: {
|
|
1112
|
+
within?: "online" | "day" | "week" | "month";
|
|
1113
|
+
group_id?: string;
|
|
1114
|
+
limit?: number;
|
|
1115
|
+
offset?: number;
|
|
1116
|
+
} | null): {
|
|
1117
|
+
users: Array<{ id: string; name: string; last_active_at: string; last_platform: "web" | "ios" | "android" | "unknown" }>;
|
|
1118
|
+
total: number | null;
|
|
1119
|
+
loading: boolean;
|
|
1120
|
+
fetching: boolean;
|
|
1121
|
+
error: Error | null;
|
|
1122
|
+
refetch(): Promise<void>;
|
|
1123
|
+
};
|
|
1124
|
+
|
|
1110
1125
|
/** Users not seen for `inactive_days` (default 30), never-seen first. */
|
|
1111
1126
|
export function useInactiveUsers(query?: {
|
|
1112
1127
|
inactive_days?: number;
|
|
@@ -1121,7 +1136,8 @@ export function useInactiveUsers(query?: {
|
|
|
1121
1136
|
error: Error | null;
|
|
1122
1137
|
refetch(): Promise<void>;
|
|
1123
1138
|
/** Notify one user, record when, then re-read the page. */
|
|
1124
|
-
|
|
1139
|
+
/** `{ refetch: false }` skips re-reading the page, for a batch that reads once. */
|
|
1140
|
+
remind(id: string, message: { title: string; body: string }, options?: { refetch?: boolean }): Promise<void>;
|
|
1125
1141
|
};
|
|
1126
1142
|
|
|
1127
1143
|
/** One record's online members, as `useOnlineMembers` reports them. */
|
|
@@ -2743,6 +2759,12 @@ export interface UsersQuery {
|
|
|
2743
2759
|
is_active?: boolean;
|
|
2744
2760
|
/** Restrict to members of one app-user group — the `id` of a `useGroups()` row. */
|
|
2745
2761
|
group_id?: string;
|
|
2762
|
+
/** Admin view only: users created since this date (workspace time zone) or instant. */
|
|
2763
|
+
joined_since?: string;
|
|
2764
|
+
/** Admin view only: "newest" lists the most recently created first. */
|
|
2765
|
+
sort?: "name" | "newest";
|
|
2766
|
+
/** "real" leaves out preview and store-review accounts; an in-app admin always gets "real". */
|
|
2767
|
+
audience?: "all" | "real" | "preview";
|
|
2746
2768
|
limit?: number;
|
|
2747
2769
|
offset?: number;
|
|
2748
2770
|
}
|
package/dist/index.js
CHANGED
|
@@ -127,6 +127,7 @@ export { useDatastoreFigure } from "./datastore-figure.js";
|
|
|
127
127
|
export {
|
|
128
128
|
useUserStats,
|
|
129
129
|
useUserActivity,
|
|
130
|
+
useActiveUsers,
|
|
130
131
|
useInactiveUsers,
|
|
131
132
|
} from "./stats-hooks.js";
|
|
132
133
|
// sc-11025 — one source, bound to how each platform says the app is in front.
|
package/dist/index.native.js
CHANGED
package/dist/stats-hooks.js
CHANGED
|
@@ -108,13 +108,32 @@ export function useUserActivity(query) {
|
|
|
108
108
|
return { ...state, activity: data };
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* sc-11066 — one page of users seen within `within` ("online" — the last two
|
|
113
|
+
* minutes — "day", "week" or "month"), most recently seen first. `query`:
|
|
114
|
+
* `{ within?, group_id?, limit?, offset? }`. Returns `{ users, total, loading,
|
|
115
|
+
* fetching, error, refetch }`; each user is `{ id, name, last_active_at,
|
|
116
|
+
* last_platform }`. Same gate as useUserActivity; null reads nothing.
|
|
117
|
+
*/
|
|
118
|
+
export function useActiveUsers(query) {
|
|
119
|
+
const users = useUsersNamespace("useActiveUsers", "active");
|
|
120
|
+
const key = query === null ? null : serialize(query);
|
|
121
|
+
const { data, ...state } = useKeyedRead(() => users.active(query), "active-users", key, toDirectoryError);
|
|
122
|
+
return {
|
|
123
|
+
...state,
|
|
124
|
+
users: data && Array.isArray(data.data) ? data.data : [],
|
|
125
|
+
total: data && data.meta && Number.isFinite(data.meta.total) ? data.meta.total : null,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
111
129
|
/**
|
|
112
130
|
* sc-10691 — one page of users not seen for `inactive_days` (default 30),
|
|
113
131
|
* never-seen first. `query`: `{ inactive_days?, group_id?, limit?, offset? }`.
|
|
114
132
|
* Returns `{ users, total, loading, fetching, error, refetch, remind }`; each
|
|
115
133
|
* user is `{ id, name, last_active_at, last_reminded_at }` (last_active_at
|
|
116
134
|
* null when never seen). `remind(id, { title, body })` notifies one and
|
|
117
|
-
* re-reads the page
|
|
135
|
+
* re-reads the page; `{ refetch: false }` as a third argument skips the
|
|
136
|
+
* re-read, so a batch reads once at the end. Same gate as useUserActivity.
|
|
118
137
|
*/
|
|
119
138
|
export function useInactiveUsers(query) {
|
|
120
139
|
const users = useUsersNamespace("useInactiveUsers", "inactive");
|
|
@@ -122,7 +141,7 @@ export function useInactiveUsers(query) {
|
|
|
122
141
|
const { data, ...state } = useKeyedRead(() => users.inactive(query), "inactive", key, toDirectoryError);
|
|
123
142
|
const { refetch } = state;
|
|
124
143
|
const remind = useCallback(
|
|
125
|
-
async (id, message) => {
|
|
144
|
+
async (id, message, { refetch: reread = true } = {}) => {
|
|
126
145
|
if (typeof users.remind !== "function") {
|
|
127
146
|
throw new Error("useInactiveUsers: host did not inject ctx.directory.users.remind");
|
|
128
147
|
}
|
|
@@ -131,7 +150,7 @@ export function useInactiveUsers(query) {
|
|
|
131
150
|
} catch (err) {
|
|
132
151
|
throw toDirectoryError(err);
|
|
133
152
|
}
|
|
134
|
-
await refetch();
|
|
153
|
+
if (reread) await refetch();
|
|
135
154
|
},
|
|
136
155
|
[users, refetch],
|
|
137
156
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.214.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|
package/src/contract.js
CHANGED
|
@@ -1960,7 +1960,9 @@ const HOOKS = [
|
|
|
1960
1960
|
"Returns { users, loading, error, refetch, invite, deactivate, " +
|
|
1961
1961
|
"reactivate, remove, sendPasswordReset, update }. " +
|
|
1962
1962
|
"list returns the { data, meta } envelope verbatim — the hook unwraps " +
|
|
1963
|
-
"res.data; rows are snake_case (is_active, …).
|
|
1963
|
+
"res.data; rows are snake_case (is_active, created_at, …). For an admin, " +
|
|
1964
|
+
"query { joined_since, sort: \"newest\" } lists who joined since a date " +
|
|
1965
|
+
"(read in the workspace's time zone), newest first. Reads need users.read:* " +
|
|
1964
1966
|
"scope; edit-style mutations (invite/deactivate/reactivate/" +
|
|
1965
1967
|
"sendPasswordReset/update) need users.write:*, and the destructive remove() " +
|
|
1966
1968
|
"additionally needs users.delete:* (SC-902). The `invite` call accepts " +
|
|
@@ -2082,6 +2084,30 @@ const HOOKS = [
|
|
|
2082
2084
|
requiredContextSlice: ["directory.users"],
|
|
2083
2085
|
scopes: ["users.activity:*"],
|
|
2084
2086
|
},
|
|
2087
|
+
// sc-11066 — who was seen in a window, behind users.activity.
|
|
2088
|
+
{
|
|
2089
|
+
name: "useActiveUsers",
|
|
2090
|
+
signature: "useActiveUsers({ within, group_id, limit, offset } | null)",
|
|
2091
|
+
optionalArgs: ["within", "group_id", "limit", "offset"],
|
|
2092
|
+
description:
|
|
2093
|
+
"One page of users seen within `within`: \"online\" (default; the app " +
|
|
2094
|
+
"open in the last two minutes), \"day\" (since midnight in the " +
|
|
2095
|
+
"workspace's time zone), \"week\" or \"month\" (the last 7 / 30 days), " +
|
|
2096
|
+
"most recently seen first: `users` = [{ id, name, last_active_at, " +
|
|
2097
|
+
"last_platform }], `total` for paging. Use it to show WHO is behind an " +
|
|
2098
|
+
"online or active figure. Same gate and errors as useUserActivity; null " +
|
|
2099
|
+
"reads nothing.",
|
|
2100
|
+
returnShape: {
|
|
2101
|
+
users: "Array<{ id, name, last_active_at, last_platform }>",
|
|
2102
|
+
total: "number | null",
|
|
2103
|
+
loading: "boolean",
|
|
2104
|
+
fetching: "boolean",
|
|
2105
|
+
error: "DirectoryError | null",
|
|
2106
|
+
refetch: "() => Promise<void>",
|
|
2107
|
+
},
|
|
2108
|
+
requiredContextSlice: ["directory.users"],
|
|
2109
|
+
scopes: ["users.activity:*"],
|
|
2110
|
+
},
|
|
2085
2111
|
{
|
|
2086
2112
|
name: "useInactiveUsers",
|
|
2087
2113
|
signature: "useInactiveUsers({ inactive_days, group_id, limit, offset } | null)",
|
|
@@ -2091,7 +2117,8 @@ const HOOKS = [
|
|
|
2091
2117
|
"never-seen first, then least recently seen: `users` = [{ id, name, " +
|
|
2092
2118
|
"last_active_at, last_reminded_at }] (last_active_at null = never seen " +
|
|
2093
2119
|
"since recording began), `total` for paging. `remind(id, { title, body })` " +
|
|
2094
|
-
"notifies one of them, records when (last_reminded_at) and re-reads
|
|
2120
|
+
"notifies one of them, records when (last_reminded_at) and re-reads; " +
|
|
2121
|
+
"pass `{ refetch: false }` third to skip the re-read in a batch. " +
|
|
2095
2122
|
"Same gate and errors as useUserActivity; null reads nothing.",
|
|
2096
2123
|
returnShape: {
|
|
2097
2124
|
users: "Array<{ id, name, last_active_at, last_reminded_at }>",
|
|
@@ -2100,7 +2127,7 @@ const HOOKS = [
|
|
|
2100
2127
|
fetching: "boolean",
|
|
2101
2128
|
error: "DirectoryError | null",
|
|
2102
2129
|
refetch: "() => Promise<void>",
|
|
2103
|
-
remind: "(id, { title, body }) => Promise<void>",
|
|
2130
|
+
remind: "(id, { title, body }, { refetch? }) => Promise<void>",
|
|
2104
2131
|
},
|
|
2105
2132
|
requiredContextSlice: ["directory.users"],
|
|
2106
2133
|
scopes: ["users.activity:*"],
|
|
@@ -5636,7 +5663,11 @@ const CONTRACT = deepFreeze({
|
|
|
5636
5663
|
// and cancel labels, `tone` "default" | "destructive", `busy`). No new
|
|
5637
5664
|
// theme scope: the panel reads `modal`, the actions `button` and
|
|
5638
5665
|
// `destructive`. `Button` forwards a ref to its pressable.
|
|
5639
|
-
|
|
5666
|
+
// 1.173.0: additive (sc-11066) — `useActiveUsers(query)` lists who was
|
|
5667
|
+
// seen online / today / in 7 or 30 days through the new
|
|
5668
|
+
// `ctx.directory.users.active`; `useUsers` takes `joined_since` and
|
|
5669
|
+
// `sort: "newest"` for an admin's "who joined" list.
|
|
5670
|
+
version: "1.173.0",
|
|
5640
5671
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
5641
5672
|
hooks: HOOKS,
|
|
5642
5673
|
primitives: PRIMITIVES,
|