@streamoid/settings 0.13.0 → 0.15.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/dist/index.d.mts +312 -7
- package/dist/index.d.ts +312 -7
- package/dist/index.js +700 -75
- package/dist/index.mjs +699 -73
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -7676,6 +7676,7 @@ import {
|
|
|
7676
7676
|
useEffect as useEffect18,
|
|
7677
7677
|
useCallback as useCallback8,
|
|
7678
7678
|
useMemo as useMemo4,
|
|
7679
|
+
useReducer,
|
|
7679
7680
|
useRef as useRef10
|
|
7680
7681
|
} from "react";
|
|
7681
7682
|
import {
|
|
@@ -7826,7 +7827,10 @@ function formatDateRange(date) {
|
|
|
7826
7827
|
function ExportDateModal({
|
|
7827
7828
|
title,
|
|
7828
7829
|
onClose,
|
|
7829
|
-
onExport
|
|
7830
|
+
onExport,
|
|
7831
|
+
busy = false,
|
|
7832
|
+
busyText,
|
|
7833
|
+
notice = null
|
|
7830
7834
|
}) {
|
|
7831
7835
|
useOverlayOpen(true, onClose);
|
|
7832
7836
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -7913,6 +7917,7 @@ function ExportDateModal({
|
|
|
7913
7917
|
[rangeStart, rangeEnd, isFuture]
|
|
7914
7918
|
);
|
|
7915
7919
|
const handleExport = () => {
|
|
7920
|
+
if (busy) return;
|
|
7916
7921
|
if (rangeStart && rangeEnd) onExport(rangeStart, rangeEnd);
|
|
7917
7922
|
};
|
|
7918
7923
|
const getCellVisuals = (cell, idx) => {
|
|
@@ -8134,24 +8139,42 @@ function ExportDateModal({
|
|
|
8134
8139
|
borderTop: "1px solid var(--alias-border-subtle)"
|
|
8135
8140
|
},
|
|
8136
8141
|
children: [
|
|
8137
|
-
/* @__PURE__ */
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8142
|
+
/* @__PURE__ */ jsxs18("div", { className: "flex-1 min-w-0 flex flex-col", children: [
|
|
8143
|
+
/* @__PURE__ */ jsx21(
|
|
8144
|
+
"p",
|
|
8145
|
+
{
|
|
8146
|
+
className: "min-w-0 truncate",
|
|
8147
|
+
style: {
|
|
8148
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
8149
|
+
fontSize: "var(--font-size-font-size-md)",
|
|
8150
|
+
fontWeight: 400,
|
|
8151
|
+
lineHeight: "var(--line-height-line-height-md)",
|
|
8152
|
+
color: "var(--alias-text---icons-primary)"
|
|
8153
|
+
},
|
|
8154
|
+
"aria-live": "polite",
|
|
8155
|
+
children: busy && busyText ? busyText : rangeStart && rangeEnd ? `${formatDateRange(rangeStart)} - ${formatDateRange(rangeEnd)}` : rangeStart ? `${formatDateRange(rangeStart)} - Select end date` : "Select date range"
|
|
8156
|
+
}
|
|
8157
|
+
),
|
|
8158
|
+
notice && !busy && /* @__PURE__ */ jsx21(
|
|
8159
|
+
"p",
|
|
8160
|
+
{
|
|
8161
|
+
role: "alert",
|
|
8162
|
+
style: {
|
|
8163
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
8164
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
8165
|
+
fontWeight: 400,
|
|
8166
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
8167
|
+
color: "var(--alias-text---icons-error)"
|
|
8168
|
+
},
|
|
8169
|
+
children: notice
|
|
8170
|
+
}
|
|
8171
|
+
)
|
|
8172
|
+
] }),
|
|
8151
8173
|
/* @__PURE__ */ jsx21(
|
|
8152
8174
|
"div",
|
|
8153
8175
|
{
|
|
8154
|
-
className: `flex items-center justify-center shrink-0 ${rangeStart && rangeEnd ? "cursor-pointer" : "opacity-50 cursor-not-allowed"}`,
|
|
8176
|
+
className: `flex items-center justify-center shrink-0 ${rangeStart && rangeEnd && !busy ? "cursor-pointer" : "opacity-50 cursor-not-allowed"}`,
|
|
8177
|
+
"aria-disabled": busy || !(rangeStart && rangeEnd),
|
|
8155
8178
|
style: {
|
|
8156
8179
|
backgroundColor: "var(--alias-text---icons-primary)",
|
|
8157
8180
|
borderRadius: "var(--radius-xl)",
|
|
@@ -8169,7 +8192,7 @@ function ExportDateModal({
|
|
|
8169
8192
|
lineHeight: "var(--line-height-line-height-sm)",
|
|
8170
8193
|
color: "var(--alias-text---icons-inverse)"
|
|
8171
8194
|
},
|
|
8172
|
-
children: "Export"
|
|
8195
|
+
children: busy ? "Exporting\u2026" : "Export"
|
|
8173
8196
|
}
|
|
8174
8197
|
)
|
|
8175
8198
|
}
|
|
@@ -10523,6 +10546,261 @@ function SharedCreditsView() {
|
|
|
10523
10546
|
] });
|
|
10524
10547
|
}
|
|
10525
10548
|
|
|
10549
|
+
// src/entitlement.ts
|
|
10550
|
+
function parseBillingEntitlement(value) {
|
|
10551
|
+
if (!value || typeof value !== "object") return null;
|
|
10552
|
+
const raw = value;
|
|
10553
|
+
if (typeof raw.paid !== "boolean") return null;
|
|
10554
|
+
const source = raw.source === "plan" || raw.source === "pool" ? raw.source : null;
|
|
10555
|
+
const entitlement = { paid: raw.paid, source };
|
|
10556
|
+
if (typeof raw.sponsorWorkspaceId === "string") entitlement.sponsorWorkspaceId = raw.sponsorWorkspaceId;
|
|
10557
|
+
if (typeof raw.sponsorName === "string") entitlement.sponsorName = raw.sponsorName;
|
|
10558
|
+
if (typeof raw.endsAt === "string" || raw.endsAt === null) entitlement.endsAt = raw.endsAt;
|
|
10559
|
+
return entitlement;
|
|
10560
|
+
}
|
|
10561
|
+
function entitlementFromBody(body) {
|
|
10562
|
+
if (!body || typeof body !== "object") return null;
|
|
10563
|
+
return parseBillingEntitlement(body.entitlement);
|
|
10564
|
+
}
|
|
10565
|
+
function entitlementFromFailure(failure) {
|
|
10566
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10567
|
+
const visit = (value, depth) => {
|
|
10568
|
+
if (depth > 4 || value == null || typeof value !== "object" || seen.has(value)) return null;
|
|
10569
|
+
seen.add(value);
|
|
10570
|
+
const found = entitlementFromBody(value);
|
|
10571
|
+
if (found) return found;
|
|
10572
|
+
const error = value;
|
|
10573
|
+
const response = error.response;
|
|
10574
|
+
for (const child of [error.body, error.data, response?.data, error.cause]) {
|
|
10575
|
+
const nested = visit(child, depth + 1);
|
|
10576
|
+
if (nested) return nested;
|
|
10577
|
+
}
|
|
10578
|
+
return null;
|
|
10579
|
+
};
|
|
10580
|
+
return visit(failure, 0);
|
|
10581
|
+
}
|
|
10582
|
+
function isPaidPlan(subscription) {
|
|
10583
|
+
const amount = subscription?.plan?.amount;
|
|
10584
|
+
return amount != null && amount > 0;
|
|
10585
|
+
}
|
|
10586
|
+
function hasPaidFeatures({
|
|
10587
|
+
entitlement,
|
|
10588
|
+
subscription
|
|
10589
|
+
}) {
|
|
10590
|
+
return entitlement ? entitlement.paid : isPaidPlan(subscription);
|
|
10591
|
+
}
|
|
10592
|
+
function isSponsoredEntitlement(entitlement) {
|
|
10593
|
+
return entitlement?.source === "pool" && entitlement.paid;
|
|
10594
|
+
}
|
|
10595
|
+
function sponsoredCreditsText(entitlement) {
|
|
10596
|
+
const sponsor = entitlement.sponsorName?.trim() || "another workspace";
|
|
10597
|
+
const ends = entitlement.endsAt ? ` Sharing ends on ${formatPoolEndsAt(entitlement.endsAt)}.` : "";
|
|
10598
|
+
return `Credits shared by ${sponsor}.${ends}`;
|
|
10599
|
+
}
|
|
10600
|
+
async function loadCurrentPlan(fetchCurrentPlan) {
|
|
10601
|
+
let response;
|
|
10602
|
+
try {
|
|
10603
|
+
response = await fetchCurrentPlan();
|
|
10604
|
+
} catch (failure) {
|
|
10605
|
+
const entitlement2 = entitlementFromFailure(failure);
|
|
10606
|
+
if (!entitlement2) throw failure;
|
|
10607
|
+
return { subscription: null, entitlement: entitlement2, paid: entitlement2.paid };
|
|
10608
|
+
}
|
|
10609
|
+
const subscription = response?.data ?? null;
|
|
10610
|
+
const entitlement = entitlementFromBody(response);
|
|
10611
|
+
return { subscription, entitlement, paid: hasPaidFeatures({ entitlement, subscription }) };
|
|
10612
|
+
}
|
|
10613
|
+
|
|
10614
|
+
// src/usage-logs.ts
|
|
10615
|
+
var USAGE_LOGS_PAGE_SIZE = 50;
|
|
10616
|
+
var USAGE_LOGS_EXPORT_BATCH_SIZE = 100;
|
|
10617
|
+
var USAGE_LOGS_EXPORT_MAX_ROWS = 2e4;
|
|
10618
|
+
var USAGE_LOGS_EXPORT_EXTRA_REQUESTS = 10;
|
|
10619
|
+
function rowsOf(res) {
|
|
10620
|
+
return Array.isArray(res?.data) ? res.data : [];
|
|
10621
|
+
}
|
|
10622
|
+
function sliceUsageLogsPage(all, page, pageSize = USAGE_LOGS_PAGE_SIZE) {
|
|
10623
|
+
const total = all.length;
|
|
10624
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
10625
|
+
const safePage = Math.min(Math.max(1, Math.floor(page) || 1), totalPages);
|
|
10626
|
+
return {
|
|
10627
|
+
rows: all.slice((safePage - 1) * pageSize, safePage * pageSize),
|
|
10628
|
+
page: safePage,
|
|
10629
|
+
totalPages,
|
|
10630
|
+
total,
|
|
10631
|
+
unpaged: all
|
|
10632
|
+
};
|
|
10633
|
+
}
|
|
10634
|
+
function usageLogsPage(res, page, pageSize = USAGE_LOGS_PAGE_SIZE) {
|
|
10635
|
+
const data = rowsOf(res);
|
|
10636
|
+
const pagination = res?.pagination;
|
|
10637
|
+
if (!pagination || !Number.isFinite(pagination.total)) {
|
|
10638
|
+
return sliceUsageLogsPage(data, page, pageSize);
|
|
10639
|
+
}
|
|
10640
|
+
const total = Math.max(0, pagination.total);
|
|
10641
|
+
const limit = pagination.limit > 0 ? pagination.limit : pageSize;
|
|
10642
|
+
const totalPages = Math.max(
|
|
10643
|
+
1,
|
|
10644
|
+
pagination.totalPages > 0 ? pagination.totalPages : Math.ceil(total / limit)
|
|
10645
|
+
);
|
|
10646
|
+
return {
|
|
10647
|
+
rows: data.slice(0, pageSize),
|
|
10648
|
+
page: pagination.page > 0 ? pagination.page : page,
|
|
10649
|
+
totalPages,
|
|
10650
|
+
total,
|
|
10651
|
+
unpaged: null
|
|
10652
|
+
};
|
|
10653
|
+
}
|
|
10654
|
+
var EMPTY_USAGE_LOGS_PAGE = {
|
|
10655
|
+
rows: [],
|
|
10656
|
+
page: 1,
|
|
10657
|
+
totalPages: 1,
|
|
10658
|
+
total: 0,
|
|
10659
|
+
unpaged: null
|
|
10660
|
+
};
|
|
10661
|
+
var INITIAL_USAGE_LOGS_STATE = {
|
|
10662
|
+
logs: EMPTY_USAGE_LOGS_PAGE,
|
|
10663
|
+
requestedPage: 1,
|
|
10664
|
+
loading: false,
|
|
10665
|
+
error: null
|
|
10666
|
+
};
|
|
10667
|
+
function usageLogsReducer(state, action) {
|
|
10668
|
+
switch (action.type) {
|
|
10669
|
+
case "request":
|
|
10670
|
+
return { ...state, requestedPage: action.page, loading: true, error: null };
|
|
10671
|
+
case "loaded":
|
|
10672
|
+
return {
|
|
10673
|
+
logs: action.logs,
|
|
10674
|
+
requestedPage: action.logs.page,
|
|
10675
|
+
loading: false,
|
|
10676
|
+
error: null
|
|
10677
|
+
};
|
|
10678
|
+
case "failed":
|
|
10679
|
+
return { ...state, loading: false, error: action.error };
|
|
10680
|
+
case "turn": {
|
|
10681
|
+
if (!state.logs.unpaged || state.error) return state;
|
|
10682
|
+
const logs = sliceUsageLogsPage(state.logs.unpaged, action.page);
|
|
10683
|
+
return { ...state, logs, requestedPage: logs.page };
|
|
10684
|
+
}
|
|
10685
|
+
case "reset":
|
|
10686
|
+
return INITIAL_USAGE_LOGS_STATE;
|
|
10687
|
+
}
|
|
10688
|
+
}
|
|
10689
|
+
function usageLogsSpentByOthers(logs, workspaceId) {
|
|
10690
|
+
return (logs.unpaged ?? logs.rows).some(
|
|
10691
|
+
(log) => usedByWorkspaceKey(log, workspaceId) !== null
|
|
10692
|
+
);
|
|
10693
|
+
}
|
|
10694
|
+
function createUsedByNamesLoader(save) {
|
|
10695
|
+
let savedFor = null;
|
|
10696
|
+
let inFlight = null;
|
|
10697
|
+
return {
|
|
10698
|
+
async load(workspaceId, fetchCreditPool) {
|
|
10699
|
+
if (savedFor === workspaceId || inFlight?.workspaceId === workspaceId) {
|
|
10700
|
+
return;
|
|
10701
|
+
}
|
|
10702
|
+
const lookup = { workspaceId };
|
|
10703
|
+
inFlight = lookup;
|
|
10704
|
+
try {
|
|
10705
|
+
const pool = await fetchCreditPool();
|
|
10706
|
+
if (inFlight !== lookup) return;
|
|
10707
|
+
if (save(workspaceId, usedByNamesFrom(pool))) savedFor = workspaceId;
|
|
10708
|
+
} catch {
|
|
10709
|
+
} finally {
|
|
10710
|
+
if (inFlight === lookup) inFlight = null;
|
|
10711
|
+
}
|
|
10712
|
+
},
|
|
10713
|
+
reset() {
|
|
10714
|
+
savedFor = null;
|
|
10715
|
+
inFlight = null;
|
|
10716
|
+
}
|
|
10717
|
+
};
|
|
10718
|
+
}
|
|
10719
|
+
function usageLogsExportFileName(start, end) {
|
|
10720
|
+
return `usage_logs_${toLocalDateInput(start)}_${toLocalDateInput(end)}.csv`;
|
|
10721
|
+
}
|
|
10722
|
+
function usageLogsDateRange(start, end) {
|
|
10723
|
+
const from = new Date(start);
|
|
10724
|
+
from.setHours(0, 0, 0, 0);
|
|
10725
|
+
const to = new Date(end);
|
|
10726
|
+
to.setHours(23, 59, 59, 999);
|
|
10727
|
+
return { startDate: from.toISOString(), endDate: to.toISOString() };
|
|
10728
|
+
}
|
|
10729
|
+
async function fetchUsageLogsInRange(fetchUsageLogs, range, {
|
|
10730
|
+
batchSize = USAGE_LOGS_EXPORT_BATCH_SIZE,
|
|
10731
|
+
maxRows = USAGE_LOGS_EXPORT_MAX_ROWS,
|
|
10732
|
+
maxRequests,
|
|
10733
|
+
onProgress,
|
|
10734
|
+
signal
|
|
10735
|
+
} = {}) {
|
|
10736
|
+
const first = await fetchUsageLogs({ ...range, page: 1, limit: batchSize });
|
|
10737
|
+
if (signal?.aborted) return { status: "cancelled" };
|
|
10738
|
+
if (!first?.pagination || !Number.isFinite(first.pagination.total)) {
|
|
10739
|
+
const from = Date.parse(range.startDate);
|
|
10740
|
+
const to = Date.parse(range.endDate);
|
|
10741
|
+
const rows2 = rowsOf(first).filter((row) => {
|
|
10742
|
+
const at = Date.parse(row.createdAt);
|
|
10743
|
+
return at >= from && at <= to;
|
|
10744
|
+
});
|
|
10745
|
+
if (rows2.length > maxRows) return { status: "too-large", total: rows2.length };
|
|
10746
|
+
onProgress?.(rows2.length, rows2.length);
|
|
10747
|
+
return { status: "ok", rows: rows2, total: rows2.length };
|
|
10748
|
+
}
|
|
10749
|
+
let total = Math.max(0, first.pagination.total);
|
|
10750
|
+
if (total > maxRows) return { status: "too-large", total };
|
|
10751
|
+
const limit = first.pagination.limit > 0 ? first.pagination.limit : batchSize;
|
|
10752
|
+
const requestCap = maxRequests ?? Math.ceil(maxRows / limit) + USAGE_LOGS_EXPORT_EXTRA_REQUESTS;
|
|
10753
|
+
const seen = /* @__PURE__ */ new Set();
|
|
10754
|
+
const rows = [];
|
|
10755
|
+
const add = (batch) => {
|
|
10756
|
+
for (const row of batch) {
|
|
10757
|
+
if (rows.length >= maxRows) return;
|
|
10758
|
+
if (seen.has(row._id)) continue;
|
|
10759
|
+
seen.add(row._id);
|
|
10760
|
+
rows.push(row);
|
|
10761
|
+
}
|
|
10762
|
+
};
|
|
10763
|
+
const hasNextAfter = (pagination, page) => typeof pagination?.hasNextPage === "boolean" ? pagination.hasNextPage : page * limit < total;
|
|
10764
|
+
add(rowsOf(first));
|
|
10765
|
+
onProgress?.(rows.length, total);
|
|
10766
|
+
let hasNext = hasNextAfter(first.pagination, 1);
|
|
10767
|
+
let requests = 1;
|
|
10768
|
+
for (let page = 2; hasNext && rows.length < total; page++) {
|
|
10769
|
+
if (requests >= requestCap) {
|
|
10770
|
+
return { status: "incomplete", fetched: rows.length, total };
|
|
10771
|
+
}
|
|
10772
|
+
if (signal?.aborted) return { status: "cancelled" };
|
|
10773
|
+
const res = await fetchUsageLogs({ ...range, page, limit });
|
|
10774
|
+
requests++;
|
|
10775
|
+
if (signal?.aborted) return { status: "cancelled" };
|
|
10776
|
+
if (res?.pagination && Number.isFinite(res.pagination.total)) {
|
|
10777
|
+
total = Math.max(0, res.pagination.total);
|
|
10778
|
+
if (total > maxRows) return { status: "too-large", total };
|
|
10779
|
+
}
|
|
10780
|
+
const batch = rowsOf(res);
|
|
10781
|
+
if (batch.length === 0) break;
|
|
10782
|
+
add(batch);
|
|
10783
|
+
onProgress?.(rows.length, total);
|
|
10784
|
+
hasNext = hasNextAfter(res?.pagination, page);
|
|
10785
|
+
}
|
|
10786
|
+
return { status: "ok", rows, total };
|
|
10787
|
+
}
|
|
10788
|
+
function usageLogsCsvRows(logs, userMap, formatDate5) {
|
|
10789
|
+
return [
|
|
10790
|
+
["Date", "Type", "Credits", "Service", "User ID"],
|
|
10791
|
+
...logs.map((log) => [
|
|
10792
|
+
formatDate5(log.createdAt),
|
|
10793
|
+
log.type,
|
|
10794
|
+
log.amount.toLocaleString("en-US"),
|
|
10795
|
+
log.service?.serviceGroupName ?? log.meta?.info ?? "",
|
|
10796
|
+
log.triggeredByUserId != null ? userMap[log.triggeredByUserId] ?? log.triggeredByUserId : ""
|
|
10797
|
+
])
|
|
10798
|
+
];
|
|
10799
|
+
}
|
|
10800
|
+
function toCsv(rows) {
|
|
10801
|
+
return rows.map((r) => r.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(",")).join("\n");
|
|
10802
|
+
}
|
|
10803
|
+
|
|
10526
10804
|
// src/billing-content.tsx
|
|
10527
10805
|
import { Fragment as Fragment11, jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
10528
10806
|
var DEFAULT_TOPUP_SERVICE = "catalogix";
|
|
@@ -11408,6 +11686,8 @@ function UsageLogsTable({
|
|
|
11408
11686
|
logs,
|
|
11409
11687
|
userMap,
|
|
11410
11688
|
loading,
|
|
11689
|
+
error = null,
|
|
11690
|
+
onRetry,
|
|
11411
11691
|
currentWorkspaceId = null,
|
|
11412
11692
|
usedByNames = {}
|
|
11413
11693
|
}) {
|
|
@@ -11438,6 +11718,50 @@ function UsageLogsTable({
|
|
|
11438
11718
|
}
|
|
11439
11719
|
);
|
|
11440
11720
|
}
|
|
11721
|
+
if (error) {
|
|
11722
|
+
return /* @__PURE__ */ jsxs26(
|
|
11723
|
+
"div",
|
|
11724
|
+
{
|
|
11725
|
+
role: "alert",
|
|
11726
|
+
className: "flex flex-col items-center justify-center w-full",
|
|
11727
|
+
style: {
|
|
11728
|
+
backgroundColor: "var(--alias-surface-base)",
|
|
11729
|
+
borderRadius: "var(--radius-3xl)",
|
|
11730
|
+
border: "1px solid var(--alias-border-subtle)",
|
|
11731
|
+
padding: "var(--spacing-6xl)",
|
|
11732
|
+
gap: "var(--spacing-md)"
|
|
11733
|
+
},
|
|
11734
|
+
children: [
|
|
11735
|
+
/* @__PURE__ */ jsxs26(
|
|
11736
|
+
"span",
|
|
11737
|
+
{
|
|
11738
|
+
style: {
|
|
11739
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
11740
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
11741
|
+
fontWeight: 400,
|
|
11742
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
11743
|
+
color: "var(--alias-text---icons-muted)",
|
|
11744
|
+
textAlign: "center"
|
|
11745
|
+
},
|
|
11746
|
+
children: [
|
|
11747
|
+
"Couldn't load usage logs. ",
|
|
11748
|
+
error
|
|
11749
|
+
]
|
|
11750
|
+
}
|
|
11751
|
+
),
|
|
11752
|
+
onRetry && /* @__PURE__ */ jsx29(
|
|
11753
|
+
ScButton14,
|
|
11754
|
+
{
|
|
11755
|
+
text: "Try again",
|
|
11756
|
+
variant: "tertiary",
|
|
11757
|
+
size: "sm",
|
|
11758
|
+
onClick: onRetry
|
|
11759
|
+
}
|
|
11760
|
+
)
|
|
11761
|
+
]
|
|
11762
|
+
}
|
|
11763
|
+
);
|
|
11764
|
+
}
|
|
11441
11765
|
return /* @__PURE__ */ jsxs26(
|
|
11442
11766
|
"div",
|
|
11443
11767
|
{
|
|
@@ -11613,6 +11937,71 @@ function UsageLogsTable({
|
|
|
11613
11937
|
}
|
|
11614
11938
|
);
|
|
11615
11939
|
}
|
|
11940
|
+
function UsageLogsPager({
|
|
11941
|
+
page,
|
|
11942
|
+
totalPages,
|
|
11943
|
+
total,
|
|
11944
|
+
loading = false,
|
|
11945
|
+
onPageChange
|
|
11946
|
+
}) {
|
|
11947
|
+
if (total <= 0) return null;
|
|
11948
|
+
const canPrevious = !loading && page > 1;
|
|
11949
|
+
const canNext = !loading && page < totalPages;
|
|
11950
|
+
return /* @__PURE__ */ jsxs26(
|
|
11951
|
+
"div",
|
|
11952
|
+
{
|
|
11953
|
+
className: "flex items-center justify-between shrink-0 w-full",
|
|
11954
|
+
style: { gap: "var(--spacing-md)" },
|
|
11955
|
+
children: [
|
|
11956
|
+
/* @__PURE__ */ jsxs26(
|
|
11957
|
+
"span",
|
|
11958
|
+
{
|
|
11959
|
+
style: {
|
|
11960
|
+
color: "var(--alias-text---icons-muted)",
|
|
11961
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
11962
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
11963
|
+
lineHeight: "var(--line-height-line-height-sm)"
|
|
11964
|
+
},
|
|
11965
|
+
children: [
|
|
11966
|
+
"Page ",
|
|
11967
|
+
page.toLocaleString("en-US"),
|
|
11968
|
+
" of",
|
|
11969
|
+
" ",
|
|
11970
|
+
totalPages.toLocaleString("en-US"),
|
|
11971
|
+
" \xB7",
|
|
11972
|
+
" ",
|
|
11973
|
+
total.toLocaleString("en-US"),
|
|
11974
|
+
" ",
|
|
11975
|
+
total === 1 ? "log" : "logs"
|
|
11976
|
+
]
|
|
11977
|
+
}
|
|
11978
|
+
),
|
|
11979
|
+
totalPages > 1 && /* @__PURE__ */ jsxs26("div", { className: "flex items-center", style: { gap: "var(--spacing-md)" }, children: [
|
|
11980
|
+
/* @__PURE__ */ jsx29(
|
|
11981
|
+
ScButton14,
|
|
11982
|
+
{
|
|
11983
|
+
text: "Previous",
|
|
11984
|
+
variant: "tertiary",
|
|
11985
|
+
size: "sm",
|
|
11986
|
+
state: canPrevious ? "default" : "disabled",
|
|
11987
|
+
onClick: canPrevious ? () => onPageChange(page - 1) : void 0
|
|
11988
|
+
}
|
|
11989
|
+
),
|
|
11990
|
+
/* @__PURE__ */ jsx29(
|
|
11991
|
+
ScButton14,
|
|
11992
|
+
{
|
|
11993
|
+
text: "Next",
|
|
11994
|
+
variant: "tertiary",
|
|
11995
|
+
size: "sm",
|
|
11996
|
+
state: canNext ? "default" : "disabled",
|
|
11997
|
+
onClick: canNext ? () => onPageChange(page + 1) : void 0
|
|
11998
|
+
}
|
|
11999
|
+
)
|
|
12000
|
+
] })
|
|
12001
|
+
]
|
|
12002
|
+
}
|
|
12003
|
+
);
|
|
12004
|
+
}
|
|
11616
12005
|
function BackToBilling({ onClick }) {
|
|
11617
12006
|
return /* @__PURE__ */ jsxs26(
|
|
11618
12007
|
"div",
|
|
@@ -11654,7 +12043,8 @@ function BillingContent({
|
|
|
11654
12043
|
showPerUserLimits: showPerUserLimitsProp,
|
|
11655
12044
|
onShowPerUserLimitsChange,
|
|
11656
12045
|
showSharedCredits: showSharedCreditsProp,
|
|
11657
|
-
onShowSharedCreditsChange
|
|
12046
|
+
onShowSharedCreditsChange,
|
|
12047
|
+
onEntitlementChange
|
|
11658
12048
|
} = {}) {
|
|
11659
12049
|
const { auth, workspace, organization, api, toast, navigation } = useSettingsAdapters();
|
|
11660
12050
|
const user = auth.user;
|
|
@@ -11691,15 +12081,38 @@ function BillingContent({
|
|
|
11691
12081
|
else setShowSharedCreditsInternal(next);
|
|
11692
12082
|
};
|
|
11693
12083
|
const [showExportModal, setShowExportModal] = useState21(false);
|
|
12084
|
+
const [exportProgress, setExportProgress] = useState21(null);
|
|
12085
|
+
const [exportNotice, setExportNotice] = useState21(null);
|
|
12086
|
+
const exportAbortRef = useRef10(null);
|
|
11694
12087
|
const [showBuyCreditsModal, setShowBuyCreditsModal] = useState21(false);
|
|
11695
12088
|
const [subscription, setSubscription] = useState21(null);
|
|
12089
|
+
const [entitlement, setEntitlement] = useState21(
|
|
12090
|
+
null
|
|
12091
|
+
);
|
|
11696
12092
|
const [availableCredits, setAvailableCredits] = useState21(null);
|
|
11697
12093
|
const [sharedPool, setSharedPool] = useState21(null);
|
|
11698
12094
|
const [usedByNames, setUsedByNames] = useState21({});
|
|
11699
12095
|
const [products, setProducts] = useState21([]);
|
|
11700
12096
|
const [invoices, setInvoices] = useState21([]);
|
|
11701
12097
|
const [totalCredits, setTotalCredits] = useState21(null);
|
|
11702
|
-
const [
|
|
12098
|
+
const [usageLogsState, dispatchUsageLogs] = useReducer(
|
|
12099
|
+
usageLogsReducer,
|
|
12100
|
+
INITIAL_USAGE_LOGS_STATE
|
|
12101
|
+
);
|
|
12102
|
+
const {
|
|
12103
|
+
logs: usageLogs,
|
|
12104
|
+
loading: loadingUsageLogs,
|
|
12105
|
+
error: usageLogsError
|
|
12106
|
+
} = usageLogsState;
|
|
12107
|
+
const usageLogsRequestRef = useRef10(0);
|
|
12108
|
+
const workspaceIdRef = useRef10(workspaceId);
|
|
12109
|
+
workspaceIdRef.current = workspaceId;
|
|
12110
|
+
const loadUsedByNamesRef = useRef10(null);
|
|
12111
|
+
loadUsedByNamesRef.current ??= createUsedByNamesLoader((forWorkspace, names) => {
|
|
12112
|
+
if (forWorkspace !== workspaceIdRef.current) return false;
|
|
12113
|
+
setUsedByNames(names);
|
|
12114
|
+
return true;
|
|
12115
|
+
});
|
|
11703
12116
|
const [userMap, setUserMap] = useState21({});
|
|
11704
12117
|
const [customPlanCredits, setCustomPlanCredits] = useState21(
|
|
11705
12118
|
null
|
|
@@ -11738,12 +12151,15 @@ function BillingContent({
|
|
|
11738
12151
|
try {
|
|
11739
12152
|
console.log("calling Billing apis");
|
|
11740
12153
|
const [subRes, creditsRes, productsRes, customRes] = await Promise.all([
|
|
11741
|
-
|
|
12154
|
+
// A sponsored workspace with no subscription of its own gets a 404
|
|
12155
|
+
// that carries its entitlement: loadCurrentPlan answers it, not throws.
|
|
12156
|
+
loadCurrentPlan(api.fetchCurrentPlan).catch(() => null),
|
|
11742
12157
|
api.fetchAvailableCredits().catch(() => null),
|
|
11743
12158
|
api.fetchPlans().catch(() => null),
|
|
11744
12159
|
api.getCustomCreditInfo?.().catch(() => null) ?? Promise.resolve(null)
|
|
11745
12160
|
]);
|
|
11746
|
-
if (subRes?.
|
|
12161
|
+
if (subRes?.subscription) setSubscription(subRes.subscription);
|
|
12162
|
+
if (subRes) setEntitlement(subRes.entitlement);
|
|
11747
12163
|
if (creditsRes?.availableCredits != null)
|
|
11748
12164
|
setAvailableCredits(creditsRes.availableCredits);
|
|
11749
12165
|
setSharedPool(creditsRes?.sharedPool ?? null);
|
|
@@ -11780,8 +12196,68 @@ function BillingContent({
|
|
|
11780
12196
|
} catch {
|
|
11781
12197
|
}
|
|
11782
12198
|
}, [api]);
|
|
12199
|
+
const ensureUsedByNames = useCallback8(
|
|
12200
|
+
(logs) => {
|
|
12201
|
+
const fetchCreditPool = api.fetchCreditPool;
|
|
12202
|
+
if (!fetchCreditPool || !workspaceId || !usageLogsSpentByOthers(logs, workspaceId)) {
|
|
12203
|
+
return;
|
|
12204
|
+
}
|
|
12205
|
+
void loadUsedByNamesRef.current?.load(
|
|
12206
|
+
workspaceId,
|
|
12207
|
+
() => fetchCreditPool.call(api)
|
|
12208
|
+
);
|
|
12209
|
+
},
|
|
12210
|
+
[api, workspaceId]
|
|
12211
|
+
);
|
|
12212
|
+
const loadUsageLogsPage = useCallback8(
|
|
12213
|
+
async (page) => {
|
|
12214
|
+
const request = ++usageLogsRequestRef.current;
|
|
12215
|
+
if (!api.fetchUsageLogs) {
|
|
12216
|
+
dispatchUsageLogs({ type: "loaded", logs: EMPTY_USAGE_LOGS_PAGE });
|
|
12217
|
+
return;
|
|
12218
|
+
}
|
|
12219
|
+
dispatchUsageLogs({ type: "request", page });
|
|
12220
|
+
try {
|
|
12221
|
+
const res = await api.fetchUsageLogs({
|
|
12222
|
+
page,
|
|
12223
|
+
limit: USAGE_LOGS_PAGE_SIZE
|
|
12224
|
+
});
|
|
12225
|
+
if (request !== usageLogsRequestRef.current) return;
|
|
12226
|
+
const next = usageLogsPage(res, page);
|
|
12227
|
+
dispatchUsageLogs({ type: "loaded", logs: next });
|
|
12228
|
+
ensureUsedByNames(next);
|
|
12229
|
+
} catch (err) {
|
|
12230
|
+
if (request !== usageLogsRequestRef.current) return;
|
|
12231
|
+
dispatchUsageLogs({
|
|
12232
|
+
type: "failed",
|
|
12233
|
+
error: errorMessage(err, { method: "GET" })
|
|
12234
|
+
});
|
|
12235
|
+
}
|
|
12236
|
+
},
|
|
12237
|
+
[api, ensureUsedByNames]
|
|
12238
|
+
);
|
|
12239
|
+
const goToUsageLogsPage = useCallback8(
|
|
12240
|
+
(page) => {
|
|
12241
|
+
if (usageLogs.unpaged && !usageLogsError) {
|
|
12242
|
+
dispatchUsageLogs({ type: "turn", page });
|
|
12243
|
+
ensureUsedByNames(usageLogs);
|
|
12244
|
+
return;
|
|
12245
|
+
}
|
|
12246
|
+
void loadUsageLogsPage(page);
|
|
12247
|
+
},
|
|
12248
|
+
[usageLogs, usageLogsError, loadUsageLogsPage, ensureUsedByNames]
|
|
12249
|
+
);
|
|
12250
|
+
useEffect18(() => {
|
|
12251
|
+
if (!loadingUsageLogs && !usageLogsError && usageLogs.unpaged === null && usageLogs.rows.length === 0 && usageLogs.total > 0 && usageLogs.page > usageLogs.totalPages) {
|
|
12252
|
+
void loadUsageLogsPage(usageLogs.totalPages);
|
|
12253
|
+
}
|
|
12254
|
+
}, [usageLogs, loadingUsageLogs, usageLogsError, loadUsageLogsPage]);
|
|
11783
12255
|
const fetchTableData = useCallback8(
|
|
11784
12256
|
async (tab) => {
|
|
12257
|
+
if (tab === "usage") {
|
|
12258
|
+
await loadUsageLogsPage(1);
|
|
12259
|
+
return;
|
|
12260
|
+
}
|
|
11785
12261
|
setLoadingTable(true);
|
|
11786
12262
|
try {
|
|
11787
12263
|
if (tab === "invoice") {
|
|
@@ -11793,25 +12269,14 @@ function BillingContent({
|
|
|
11793
12269
|
(item) => item.expiresAt && item.expiresAt.split("T")[0] > today
|
|
11794
12270
|
).reduce((total, item) => total + item.amount, 0)
|
|
11795
12271
|
);
|
|
11796
|
-
} else if (api.fetchUsageLogs) {
|
|
11797
|
-
const res = await api.fetchUsageLogs();
|
|
11798
|
-
const logs = res.data?.length ? res.data : [];
|
|
11799
|
-
setUsageLogs(logs);
|
|
11800
|
-
if (api.fetchCreditPool && logs.some((log) => usedByWorkspaceKey(log, workspaceId))) {
|
|
11801
|
-
const pool = await api.fetchCreditPool().catch(() => null);
|
|
11802
|
-
setUsedByNames(usedByNamesFrom(pool));
|
|
11803
|
-
}
|
|
11804
|
-
} else {
|
|
11805
|
-
setUsageLogs([]);
|
|
11806
12272
|
}
|
|
11807
12273
|
} catch {
|
|
11808
|
-
|
|
11809
|
-
else setUsageLogs([]);
|
|
12274
|
+
setInvoices([]);
|
|
11810
12275
|
} finally {
|
|
11811
12276
|
setLoadingTable(false);
|
|
11812
12277
|
}
|
|
11813
12278
|
},
|
|
11814
|
-
[api,
|
|
12279
|
+
[api, loadUsageLogsPage]
|
|
11815
12280
|
);
|
|
11816
12281
|
const handlePlanAction = useCallback8(
|
|
11817
12282
|
async ({ productId, priceId, planName: planName2 }) => {
|
|
@@ -11913,10 +12378,15 @@ function BillingContent({
|
|
|
11913
12378
|
setInitialFetchTriggered(false);
|
|
11914
12379
|
setBillingOverviewLoaded(false);
|
|
11915
12380
|
setSubscription(null);
|
|
12381
|
+
setEntitlement(null);
|
|
11916
12382
|
setAvailableCredits(null);
|
|
11917
12383
|
setProducts([]);
|
|
11918
12384
|
setTotalCredits(null);
|
|
11919
12385
|
setCustomPlanCredits(null);
|
|
12386
|
+
usageLogsRequestRef.current++;
|
|
12387
|
+
dispatchUsageLogs({ type: "reset" });
|
|
12388
|
+
loadUsedByNamesRef.current?.reset();
|
|
12389
|
+
setUsedByNames({});
|
|
11920
12390
|
}, [workspaceId]);
|
|
11921
12391
|
useEffect18(() => {
|
|
11922
12392
|
setInitialFetchTriggered(true);
|
|
@@ -11968,7 +12438,16 @@ function BillingContent({
|
|
|
11968
12438
|
subscription?.scheduledDowngradeEffectiveDate
|
|
11969
12439
|
);
|
|
11970
12440
|
const scheduledDowngradeText = subscription?.downgradeScheduled && subscription.plan?.name ? `Downgrades to ${subscription.plan.name}${scheduledDowngradeDateLabel ? ` ${scheduledDowngradeDateLabel}` : ""}` : void 0;
|
|
11971
|
-
const
|
|
12441
|
+
const sponsored = isSponsoredEntitlement(entitlement);
|
|
12442
|
+
const sponsoredWithoutPlan = sponsored && billingOverviewLoaded && !loadingBilling && subscription == null;
|
|
12443
|
+
const isPlanDetailsLoading = sponsoredWithoutPlan ? false : !billingOverviewLoaded || loadingBilling || subscription?.plan == null || !planName || planName === "-" || !planAmount || currentPlanCredits == null;
|
|
12444
|
+
const paidFeatures = hasPaidFeatures({ entitlement, subscription });
|
|
12445
|
+
const onEntitlementChangeRef = useRef10(onEntitlementChange);
|
|
12446
|
+
onEntitlementChangeRef.current = onEntitlementChange;
|
|
12447
|
+
useEffect18(() => {
|
|
12448
|
+
if (!billingOverviewLoaded) return;
|
|
12449
|
+
onEntitlementChangeRef.current?.({ entitlement, paid: paidFeatures });
|
|
12450
|
+
}, [billingOverviewLoaded, entitlement, paidFeatures]);
|
|
11972
12451
|
const {
|
|
11973
12452
|
used: usedCredits,
|
|
11974
12453
|
remaining: remainingCredits,
|
|
@@ -12010,35 +12489,74 @@ function BillingContent({
|
|
|
12010
12489
|
toast.success(`Opened ${successCount} invoice PDF(s).`);
|
|
12011
12490
|
}
|
|
12012
12491
|
} else {
|
|
12013
|
-
|
|
12014
|
-
|
|
12015
|
-
|
|
12492
|
+
await exportUsageLogs(startDate, endDate);
|
|
12493
|
+
}
|
|
12494
|
+
};
|
|
12495
|
+
const closeExportModal = () => {
|
|
12496
|
+
exportAbortRef.current?.abort();
|
|
12497
|
+
exportAbortRef.current = null;
|
|
12498
|
+
setExportProgress(null);
|
|
12499
|
+
setExportNotice(null);
|
|
12500
|
+
setShowExportModal(false);
|
|
12501
|
+
};
|
|
12502
|
+
useEffect18(() => () => exportAbortRef.current?.abort(), []);
|
|
12503
|
+
const exportUsageLogs = async (startDate, endDate) => {
|
|
12504
|
+
if (!api.fetchUsageLogs) {
|
|
12505
|
+
toast.info?.("Usage logs are not available in this workspace.");
|
|
12506
|
+
closeExportModal();
|
|
12507
|
+
return;
|
|
12508
|
+
}
|
|
12509
|
+
exportAbortRef.current?.abort();
|
|
12510
|
+
const controller = new AbortController();
|
|
12511
|
+
exportAbortRef.current = controller;
|
|
12512
|
+
setExportNotice(null);
|
|
12513
|
+
setExportProgress({ fetched: 0, total: 0 });
|
|
12514
|
+
const range = usageLogsDateRange(startDate, endDate);
|
|
12515
|
+
try {
|
|
12516
|
+
const result = await fetchUsageLogsInRange(api.fetchUsageLogs, range, {
|
|
12517
|
+
signal: controller.signal,
|
|
12518
|
+
onProgress: (fetched, total) => {
|
|
12519
|
+
if (!controller.signal.aborted) setExportProgress({ fetched, total });
|
|
12520
|
+
}
|
|
12016
12521
|
});
|
|
12017
|
-
if (
|
|
12522
|
+
if (result.status === "cancelled" || controller.signal.aborted) return;
|
|
12523
|
+
if (result.status === "too-large") {
|
|
12524
|
+
setExportNotice(
|
|
12525
|
+
`${result.total.toLocaleString("en-US")} logs in this range; an export holds up to ${USAGE_LOGS_EXPORT_MAX_ROWS.toLocaleString("en-US")}. Choose a shorter range.`
|
|
12526
|
+
);
|
|
12527
|
+
return;
|
|
12528
|
+
}
|
|
12529
|
+
if (result.status === "incomplete") {
|
|
12530
|
+
setExportNotice(
|
|
12531
|
+
"Usage logs kept changing while exporting, so some were missed. Try again."
|
|
12532
|
+
);
|
|
12533
|
+
return;
|
|
12534
|
+
}
|
|
12535
|
+
if (result.rows.length === 0) {
|
|
12018
12536
|
toast.info?.("No usage logs found in the selected date range.");
|
|
12019
|
-
|
|
12537
|
+
closeExportModal();
|
|
12020
12538
|
return;
|
|
12021
12539
|
}
|
|
12022
|
-
const headers = ["Date", "Type", "Credits", "Service", "User ID"];
|
|
12023
|
-
const rows = filtered.map((log) => [
|
|
12024
|
-
formatDate3(log.createdAt),
|
|
12025
|
-
log.type,
|
|
12026
|
-
log.amount.toLocaleString("en-US"),
|
|
12027
|
-
log.service?.serviceGroupName ?? log.meta?.info ?? "",
|
|
12028
|
-
log.triggeredByUserId != null ? userMap[log.triggeredByUserId] ?? log.triggeredByUserId : ""
|
|
12029
|
-
]);
|
|
12030
12540
|
downloadCsv(
|
|
12031
|
-
|
|
12032
|
-
|
|
12541
|
+
usageLogsCsvRows(result.rows, userMap, formatDate3),
|
|
12542
|
+
usageLogsExportFileName(startDate, endDate)
|
|
12033
12543
|
);
|
|
12034
|
-
toast.success(`Exported ${
|
|
12035
|
-
|
|
12544
|
+
toast.success(`Exported ${result.rows.length.toLocaleString("en-US")} log(s).`);
|
|
12545
|
+
closeExportModal();
|
|
12546
|
+
} catch (err) {
|
|
12547
|
+
if (controller.signal.aborted) return;
|
|
12548
|
+
setExportNotice(
|
|
12549
|
+
`Couldn't export usage logs. ${errorMessage(err, { method: "GET" })}`
|
|
12550
|
+
);
|
|
12551
|
+
} finally {
|
|
12552
|
+
if (exportAbortRef.current === controller) {
|
|
12553
|
+
exportAbortRef.current = null;
|
|
12554
|
+
setExportProgress(null);
|
|
12555
|
+
}
|
|
12036
12556
|
}
|
|
12037
12557
|
};
|
|
12038
12558
|
function downloadCsv(rows, filename) {
|
|
12039
|
-
const csv = rows
|
|
12040
|
-
(r) => r.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(",")
|
|
12041
|
-
).join("\n");
|
|
12559
|
+
const csv = toCsv(rows);
|
|
12042
12560
|
const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
|
|
12043
12561
|
const url = URL.createObjectURL(blob);
|
|
12044
12562
|
const a = document.createElement("a");
|
|
@@ -12049,9 +12567,6 @@ function BillingContent({
|
|
|
12049
12567
|
document.body.removeChild(a);
|
|
12050
12568
|
URL.revokeObjectURL(url);
|
|
12051
12569
|
}
|
|
12052
|
-
function fmtFilename(d) {
|
|
12053
|
-
return d.toISOString().slice(0, 10);
|
|
12054
|
-
}
|
|
12055
12570
|
async function handleBuyCredits(credits2, price) {
|
|
12056
12571
|
if (!workspaceId) {
|
|
12057
12572
|
toast.error("Missing workspace details for credit top-up");
|
|
@@ -12205,9 +12720,9 @@ function BillingContent({
|
|
|
12205
12720
|
/* @__PURE__ */ jsx29(
|
|
12206
12721
|
ScPlanDetailsCard,
|
|
12207
12722
|
{
|
|
12208
|
-
planName,
|
|
12209
|
-
planCredits: planCreditsText,
|
|
12210
|
-
planPrice: planAmount,
|
|
12723
|
+
planName: sponsoredWithoutPlan ? "Free" : planName,
|
|
12724
|
+
planCredits: sponsoredWithoutPlan ? "Shared credits" : planCreditsText,
|
|
12725
|
+
planPrice: sponsoredWithoutPlan ? `${workspace.current?.country?.trim().toUpperCase() === "IN" ? "\u20B9" : "$"}0.00 / month` : planAmount,
|
|
12211
12726
|
badgeText: "Active",
|
|
12212
12727
|
badgeSubText: scheduledDowngradeText,
|
|
12213
12728
|
currentPlanLabel: "Current plan",
|
|
@@ -12296,6 +12811,50 @@ function BillingContent({
|
|
|
12296
12811
|
)
|
|
12297
12812
|
]
|
|
12298
12813
|
}
|
|
12814
|
+
) : sponsored && entitlement ? (
|
|
12815
|
+
// Billing says a pool entitles it, but the balance carried no
|
|
12816
|
+
// allowance (an older credits answer, or it failed): say whose.
|
|
12817
|
+
/* @__PURE__ */ jsxs26(
|
|
12818
|
+
"div",
|
|
12819
|
+
{
|
|
12820
|
+
role: "status",
|
|
12821
|
+
className: "flex flex-col shrink-0 w-full",
|
|
12822
|
+
style: {
|
|
12823
|
+
gap: 4,
|
|
12824
|
+
padding: 16,
|
|
12825
|
+
backgroundColor: "var(--alias-surface-base)",
|
|
12826
|
+
border: "1px solid var(--alias-border-subtle)",
|
|
12827
|
+
borderRadius: "var(--radius-3xl)"
|
|
12828
|
+
},
|
|
12829
|
+
children: [
|
|
12830
|
+
/* @__PURE__ */ jsx29(
|
|
12831
|
+
"span",
|
|
12832
|
+
{
|
|
12833
|
+
style: {
|
|
12834
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
12835
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
12836
|
+
fontWeight: 500,
|
|
12837
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
12838
|
+
color: "var(--alias-text---icons-primary)"
|
|
12839
|
+
},
|
|
12840
|
+
children: sponsoredCreditsText(entitlement)
|
|
12841
|
+
}
|
|
12842
|
+
),
|
|
12843
|
+
/* @__PURE__ */ jsx29(
|
|
12844
|
+
"span",
|
|
12845
|
+
{
|
|
12846
|
+
style: {
|
|
12847
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
12848
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
12849
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
12850
|
+
color: "var(--alias-text---icons-muted)"
|
|
12851
|
+
},
|
|
12852
|
+
children: ownCreditsFirstText()
|
|
12853
|
+
}
|
|
12854
|
+
)
|
|
12855
|
+
]
|
|
12856
|
+
}
|
|
12857
|
+
)
|
|
12299
12858
|
) : null,
|
|
12300
12859
|
usage ? /* @__PURE__ */ jsxs26(
|
|
12301
12860
|
"div",
|
|
@@ -12460,22 +13019,39 @@ function BillingContent({
|
|
|
12460
13019
|
loading: loadingTable,
|
|
12461
13020
|
workspaceCountry: workspace.current?.country
|
|
12462
13021
|
}
|
|
12463
|
-
) : /* @__PURE__ */
|
|
12464
|
-
|
|
12465
|
-
|
|
12466
|
-
|
|
12467
|
-
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
|
|
12472
|
-
|
|
13022
|
+
) : /* @__PURE__ */ jsxs26(Fragment11, { children: [
|
|
13023
|
+
/* @__PURE__ */ jsx29(
|
|
13024
|
+
UsageLogsTable,
|
|
13025
|
+
{
|
|
13026
|
+
logs: usageLogs.rows,
|
|
13027
|
+
userMap,
|
|
13028
|
+
loading: loadingUsageLogs,
|
|
13029
|
+
error: usageLogsError,
|
|
13030
|
+
onRetry: () => void loadUsageLogsPage(usageLogsState.requestedPage),
|
|
13031
|
+
currentWorkspaceId: workspaceId,
|
|
13032
|
+
usedByNames
|
|
13033
|
+
}
|
|
13034
|
+
),
|
|
13035
|
+
!usageLogsError && /* @__PURE__ */ jsx29(
|
|
13036
|
+
UsageLogsPager,
|
|
13037
|
+
{
|
|
13038
|
+
page: usageLogs.page,
|
|
13039
|
+
totalPages: usageLogs.totalPages,
|
|
13040
|
+
total: usageLogs.total,
|
|
13041
|
+
loading: loadingUsageLogs,
|
|
13042
|
+
onPageChange: goToUsageLogsPage
|
|
13043
|
+
}
|
|
13044
|
+
)
|
|
13045
|
+
] }),
|
|
12473
13046
|
showExportModal && /* @__PURE__ */ jsx29(
|
|
12474
13047
|
ExportDateModal,
|
|
12475
13048
|
{
|
|
12476
13049
|
title: activeTab === "invoice" ? "Export invoices" : "Export log",
|
|
12477
|
-
onClose:
|
|
12478
|
-
onExport: handleExport
|
|
13050
|
+
onClose: closeExportModal,
|
|
13051
|
+
onExport: handleExport,
|
|
13052
|
+
busy: exportProgress !== null,
|
|
13053
|
+
busyText: exportProgress && exportProgress.total > 0 ? `Fetched ${exportProgress.fetched.toLocaleString("en-US")} of ${exportProgress.total.toLocaleString("en-US")} logs\u2026` : "Fetching logs\u2026",
|
|
13054
|
+
notice: exportNotice
|
|
12479
13055
|
}
|
|
12480
13056
|
),
|
|
12481
13057
|
showBuyCreditsModal && /* @__PURE__ */ jsx29(
|
|
@@ -16676,6 +17252,30 @@ function OrganizationPicker({
|
|
|
16676
17252
|
);
|
|
16677
17253
|
}
|
|
16678
17254
|
|
|
17255
|
+
// src/use-billing-entitlement.ts
|
|
17256
|
+
import { useEffect as useEffect22, useRef as useRef12, useState as useState28 } from "react";
|
|
17257
|
+
function useBillingEntitlement(fetchCurrentPlan, key) {
|
|
17258
|
+
const fetchRef = useRef12(fetchCurrentPlan);
|
|
17259
|
+
fetchRef.current = fetchCurrentPlan;
|
|
17260
|
+
const [state, setState] = useState28(null);
|
|
17261
|
+
const [loading, setLoading] = useState28(false);
|
|
17262
|
+
useEffect22(() => {
|
|
17263
|
+
const fetch2 = fetchRef.current;
|
|
17264
|
+
setState(null);
|
|
17265
|
+
if (!key || !fetch2) {
|
|
17266
|
+
setLoading(false);
|
|
17267
|
+
return;
|
|
17268
|
+
}
|
|
17269
|
+
let live = true;
|
|
17270
|
+
setLoading(true);
|
|
17271
|
+
loadCurrentPlan(fetch2).then((next) => live && setState(next)).catch(() => live && setState(null)).finally(() => live && setLoading(false));
|
|
17272
|
+
return () => {
|
|
17273
|
+
live = false;
|
|
17274
|
+
};
|
|
17275
|
+
}, [key]);
|
|
17276
|
+
return { state, loading };
|
|
17277
|
+
}
|
|
17278
|
+
|
|
16679
17279
|
// src/administration-navigation.ts
|
|
16680
17280
|
var normalizedBase = (base) => base.replace(/\/$/, "");
|
|
16681
17281
|
var returnKey = (base, entryKey) => `streamoid:settings:return:${base}:${entryKey}`;
|
|
@@ -16822,7 +17422,9 @@ export {
|
|
|
16822
17422
|
CreditPoolMemberModal,
|
|
16823
17423
|
DEFAULT_PERMISSIONS,
|
|
16824
17424
|
DEFAULT_USER_LANGUAGE,
|
|
17425
|
+
EMPTY_USAGE_LOGS_PAGE,
|
|
16825
17426
|
ExportDateModal,
|
|
17427
|
+
INITIAL_USAGE_LOGS_STATE,
|
|
16826
17428
|
InviteUpdateModal,
|
|
16827
17429
|
MemberCreditLimitModal,
|
|
16828
17430
|
MemberListFrame,
|
|
@@ -16855,7 +17457,12 @@ export {
|
|
|
16855
17457
|
TeamsContent,
|
|
16856
17458
|
TokensContent,
|
|
16857
17459
|
URL_TO_TAB,
|
|
17460
|
+
USAGE_LOGS_EXPORT_BATCH_SIZE,
|
|
17461
|
+
USAGE_LOGS_EXPORT_EXTRA_REQUESTS,
|
|
17462
|
+
USAGE_LOGS_EXPORT_MAX_ROWS,
|
|
17463
|
+
USAGE_LOGS_PAGE_SIZE,
|
|
16858
17464
|
USER_LANGUAGES,
|
|
17465
|
+
UsageLogsPager,
|
|
16859
17466
|
WORKSPACE_LIST_PAGE_SIZE,
|
|
16860
17467
|
WorkspaceGeneralTab,
|
|
16861
17468
|
WorkspaceListTab,
|
|
@@ -16867,13 +17474,17 @@ export {
|
|
|
16867
17474
|
cleanCreditLimitInput,
|
|
16868
17475
|
cleanPoolValueInput,
|
|
16869
17476
|
countLabel,
|
|
17477
|
+
createUsedByNamesLoader,
|
|
16870
17478
|
creditCycleUnit,
|
|
16871
17479
|
creditsMeter,
|
|
16872
17480
|
deriveWorkspaceInvitePermission,
|
|
16873
17481
|
describeAllowance,
|
|
16874
17482
|
describeDefaultLimit,
|
|
16875
17483
|
describeMemberLimit,
|
|
17484
|
+
entitlementFromBody,
|
|
17485
|
+
entitlementFromFailure,
|
|
16876
17486
|
expiryChoiceFor,
|
|
17487
|
+
fetchUsageLogsInRange,
|
|
16877
17488
|
findBillingError,
|
|
16878
17489
|
findPoolError,
|
|
16879
17490
|
formatCreditLimit,
|
|
@@ -16881,16 +17492,21 @@ export {
|
|
|
16881
17492
|
formatPoolEndsAt,
|
|
16882
17493
|
formatPoolSplit,
|
|
16883
17494
|
groupWorkspaceList,
|
|
17495
|
+
hasPaidFeatures,
|
|
16884
17496
|
isLimitBelowUsage,
|
|
17497
|
+
isPaidPlan,
|
|
17498
|
+
isSponsoredEntitlement,
|
|
16885
17499
|
joinMembersWithLimits,
|
|
16886
17500
|
lastUsedLabel,
|
|
16887
17501
|
limitBelowUsageUsed,
|
|
16888
17502
|
limitSourceLabel,
|
|
17503
|
+
loadCurrentPlan,
|
|
16889
17504
|
loadWorkspaceOrganization,
|
|
16890
17505
|
memberRoleUpdate,
|
|
16891
17506
|
minPoolEndDate,
|
|
16892
17507
|
minimumCreditLimit,
|
|
16893
17508
|
ownCreditsFirstText,
|
|
17509
|
+
parseBillingEntitlement,
|
|
16894
17510
|
pausedOwnCreditsText,
|
|
16895
17511
|
poolEndsAtFrom,
|
|
16896
17512
|
poolErrorMessage,
|
|
@@ -16903,7 +17519,17 @@ export {
|
|
|
16903
17519
|
settingsReturnTarget,
|
|
16904
17520
|
sharedPoolBannerText,
|
|
16905
17521
|
sharedPoolEndsText,
|
|
17522
|
+
sliceUsageLogsPage,
|
|
17523
|
+
sponsoredCreditsText,
|
|
17524
|
+
toCsv,
|
|
16906
17525
|
toLocalDateInput,
|
|
17526
|
+
usageLogsCsvRows,
|
|
17527
|
+
usageLogsDateRange,
|
|
17528
|
+
usageLogsExportFileName,
|
|
17529
|
+
usageLogsPage,
|
|
17530
|
+
usageLogsReducer,
|
|
17531
|
+
usageLogsSpentByOthers,
|
|
17532
|
+
useBillingEntitlement,
|
|
16907
17533
|
useSettingsAdapters,
|
|
16908
17534
|
useWorkspaceInvitePermission,
|
|
16909
17535
|
useWorkspaceOrganization,
|