@streamoid/settings 0.10.0 → 0.11.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 +7 -5
- package/dist/index.d.mts +182 -184
- package/dist/index.d.ts +182 -184
- package/dist/index.js +439 -514
- package/dist/index.mjs +442 -517
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,18 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
ALLOCATION_ERROR_CODES: () => ALLOCATION_ERROR_CODES,
|
|
24
|
-
ALLOCATION_NOTE_MAX_LENGTH: () => ALLOCATION_NOTE_MAX_LENGTH,
|
|
25
23
|
APP_KEYS: () => APP_KEYS,
|
|
26
24
|
BillingContent: () => BillingContent,
|
|
27
25
|
BuyCreditsModal: () => BuyCreditsModal,
|
|
28
|
-
CANCEL_REASON_MAX_LENGTH: () => CANCEL_REASON_MAX_LENGTH,
|
|
29
|
-
CancelCreditAllocationModal: () => CancelCreditAllocationModal,
|
|
30
26
|
ConfirmDeleteModal: () => ConfirmDeleteModal,
|
|
31
27
|
ConfirmLeaveModal: () => ConfirmLeaveModal,
|
|
32
28
|
ConnectedAppsContent: () => ConnectedAppsContent,
|
|
33
|
-
|
|
34
|
-
CreditAllocationsView: () => CreditAllocationsView,
|
|
29
|
+
CreditPoolMemberModal: () => CreditPoolMemberModal,
|
|
35
30
|
DEFAULT_PERMISSIONS: () => DEFAULT_PERMISSIONS,
|
|
36
31
|
DEFAULT_USER_LANGUAGE: () => DEFAULT_USER_LANGUAGE,
|
|
37
32
|
ExportDateModal: () => ExportDateModal,
|
|
@@ -44,15 +39,20 @@ __export(index_exports, {
|
|
|
44
39
|
OrganizationMemberModal: () => OrganizationMemberModal,
|
|
45
40
|
OrganizationModal: () => OrganizationModal,
|
|
46
41
|
OrganizationPicker: () => OrganizationPicker,
|
|
42
|
+
POOL_ERROR_CODES: () => POOL_ERROR_CODES,
|
|
43
|
+
POOL_NOTE_MAX_LENGTH: () => POOL_NOTE_MAX_LENGTH,
|
|
47
44
|
PerUserLimitsView: () => PerUserLimitsView,
|
|
48
45
|
ProfileAvatar: () => ProfileAvatar,
|
|
49
46
|
ProfileTab: () => ProfileTab,
|
|
47
|
+
REMOVE_REASON_MAX_LENGTH: () => REMOVE_REASON_MAX_LENGTH,
|
|
50
48
|
ReferralTab: () => ReferralTab,
|
|
49
|
+
RemovePoolMemberModal: () => RemovePoolMemberModal,
|
|
51
50
|
SCOPE_LABELS: () => SCOPE_LABELS,
|
|
52
51
|
ScopeHeader: () => ScopeHeader,
|
|
53
52
|
SettingsAdaptersProvider: () => SettingsAdaptersProvider,
|
|
54
53
|
SettingsContent: () => SettingsContent,
|
|
55
54
|
SettingsTooltip: () => SettingsTooltip,
|
|
55
|
+
SharedCreditsView: () => SharedCreditsView,
|
|
56
56
|
SiconKey: () => SiconKey_default,
|
|
57
57
|
TAB_DESCRIPTIONS: () => TAB_DESCRIPTIONS,
|
|
58
58
|
TAB_LABELS: () => TAB_LABELS,
|
|
@@ -68,28 +68,22 @@ __export(index_exports, {
|
|
|
68
68
|
WorkspaceModal: () => WorkspaceModal,
|
|
69
69
|
WorkspacePicker: () => WorkspacePicker,
|
|
70
70
|
WorkspaceTab: () => WorkspaceTab,
|
|
71
|
-
allocationErrorMessage: () => allocationErrorMessage,
|
|
72
|
-
allocationWorkspaceName: () => allocationWorkspaceName,
|
|
73
71
|
belowUsageReason: () => belowUsageReason,
|
|
74
|
-
|
|
75
|
-
cancelOutcomeSummary: () => cancelOutcomeSummary,
|
|
76
|
-
cancelOutcomeWarning: () => cancelOutcomeWarning,
|
|
77
|
-
cleanAllocationValueInput: () => cleanAllocationValueInput,
|
|
72
|
+
canShowSharedCredits: () => canShowSharedCredits,
|
|
78
73
|
cleanCreditLimitInput: () => cleanCreditLimitInput,
|
|
74
|
+
cleanPoolValueInput: () => cleanPoolValueInput,
|
|
79
75
|
countLabel: () => countLabel,
|
|
80
76
|
creditCycleUnit: () => creditCycleUnit,
|
|
81
|
-
|
|
77
|
+
creditsMeter: () => creditsMeter,
|
|
78
|
+
describeAllowance: () => describeAllowance,
|
|
82
79
|
describeDefaultLimit: () => describeDefaultLimit,
|
|
83
80
|
describeMemberLimit: () => describeMemberLimit,
|
|
84
|
-
findAllocationError: () => findAllocationError,
|
|
85
81
|
findBillingError: () => findBillingError,
|
|
86
|
-
|
|
87
|
-
formatAllocationSplit: () => formatAllocationSplit,
|
|
82
|
+
findPoolError: () => findPoolError,
|
|
88
83
|
formatCreditLimit: () => formatCreditLimit,
|
|
89
84
|
formatCredits: () => formatCredits,
|
|
85
|
+
formatPoolSplit: () => formatPoolSplit,
|
|
90
86
|
groupWorkspaceList: () => groupWorkspaceList,
|
|
91
|
-
initialTransferSummary: () => initialTransferSummary,
|
|
92
|
-
initialTransferWarning: () => initialTransferWarning,
|
|
93
87
|
isLimitBelowUsage: () => isLimitBelowUsage,
|
|
94
88
|
joinMembersWithLimits: () => joinMembersWithLimits,
|
|
95
89
|
lastUsedLabel: () => lastUsedLabel,
|
|
@@ -98,15 +92,20 @@ __export(index_exports, {
|
|
|
98
92
|
loadWorkspaceOrganization: () => loadWorkspaceOrganization,
|
|
99
93
|
memberRoleUpdate: () => memberRoleUpdate,
|
|
100
94
|
minimumCreditLimit: () => minimumCreditLimit,
|
|
95
|
+
poolErrorMessage: () => poolErrorMessage,
|
|
96
|
+
poolWorkspaceName: () => poolWorkspaceName,
|
|
101
97
|
resolveSettingsTabFromPath: () => resolveSettingsTabFromPath,
|
|
102
98
|
roundCredits: () => roundCredits,
|
|
99
|
+
sharedPoolBannerText: () => sharedPoolBannerText,
|
|
103
100
|
useSettingsAdapters: () => useSettingsAdapters,
|
|
104
101
|
useWorkspaceOrganization: () => useWorkspaceOrganization,
|
|
102
|
+
usedByNamesFrom: () => usedByNamesFrom,
|
|
103
|
+
usedByWorkspaceKey: () => usedByWorkspaceKey,
|
|
105
104
|
userLanguageLabel: () => userLanguageLabel,
|
|
106
|
-
validateAllocationText: () => validateAllocationText,
|
|
107
|
-
validateAllocationValue: () => validateAllocationValue,
|
|
108
105
|
validateCreditLimitInput: () => validateCreditLimitInput,
|
|
109
|
-
validateDefaultCreditLimitInput: () => validateDefaultCreditLimitInput
|
|
106
|
+
validateDefaultCreditLimitInput: () => validateDefaultCreditLimitInput,
|
|
107
|
+
validatePoolText: () => validatePoolText,
|
|
108
|
+
validatePoolValue: () => validatePoolValue
|
|
110
109
|
});
|
|
111
110
|
module.exports = __toCommonJS(index_exports);
|
|
112
111
|
|
|
@@ -7215,6 +7214,8 @@ function OrganizationListContent() {
|
|
|
7215
7214
|
const [createOpen, setCreateOpen] = (0, import_react13.useState)(false);
|
|
7216
7215
|
const [managing, setManaging] = (0, import_react13.useState)(null);
|
|
7217
7216
|
const [openingId, setOpeningId] = (0, import_react13.useState)(null);
|
|
7217
|
+
const [joinable, setJoinable] = (0, import_react13.useState)([]);
|
|
7218
|
+
const [joiningId, setJoiningId] = (0, import_react13.useState)(null);
|
|
7218
7219
|
const organizationRef = (0, import_react13.useRef)(organization);
|
|
7219
7220
|
organizationRef.current = organization;
|
|
7220
7221
|
const load = (0, import_react13.useCallback)(async () => {
|
|
@@ -7227,6 +7228,32 @@ function OrganizationListContent() {
|
|
|
7227
7228
|
setLoading(false);
|
|
7228
7229
|
}
|
|
7229
7230
|
}, []);
|
|
7231
|
+
const loadJoinable = (0, import_react13.useCallback)(async () => {
|
|
7232
|
+
const list = organizationRef.current.listJoinable;
|
|
7233
|
+
if (!list || !organizationRef.current.join) return;
|
|
7234
|
+
try {
|
|
7235
|
+
setJoinable(await list());
|
|
7236
|
+
} catch {
|
|
7237
|
+
setJoinable([]);
|
|
7238
|
+
}
|
|
7239
|
+
}, []);
|
|
7240
|
+
(0, import_react13.useEffect)(() => {
|
|
7241
|
+
void loadJoinable();
|
|
7242
|
+
}, [loadJoinable]);
|
|
7243
|
+
const joinOrganization = async (org) => {
|
|
7244
|
+
const join = organizationRef.current.join;
|
|
7245
|
+
if (!join) return;
|
|
7246
|
+
setJoiningId(org._id);
|
|
7247
|
+
try {
|
|
7248
|
+
await join(org._id);
|
|
7249
|
+
toast.success(`Joined "${org.name}". Open it to pick a workspace.`);
|
|
7250
|
+
await Promise.all([load(), loadJoinable()]);
|
|
7251
|
+
} catch (err) {
|
|
7252
|
+
toast.error(errorMessage(err, { method: "POST" }));
|
|
7253
|
+
} finally {
|
|
7254
|
+
setJoiningId(null);
|
|
7255
|
+
}
|
|
7256
|
+
};
|
|
7230
7257
|
(0, import_react13.useEffect)(() => {
|
|
7231
7258
|
void load();
|
|
7232
7259
|
}, [organization.current?.id]);
|
|
@@ -7358,6 +7385,52 @@ function OrganizationListContent() {
|
|
|
7358
7385
|
))
|
|
7359
7386
|
}
|
|
7360
7387
|
),
|
|
7388
|
+
joinable.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T12.spXl }, children: [
|
|
7389
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col min-w-0", style: { gap: T12.spXs }, children: [
|
|
7390
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { style: { margin: 0, color: T12.primary, fontSize: T12.fsLg, fontWeight: 600, lineHeight: T12.lhLg }, children: "Other organizations" }),
|
|
7391
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { style: { margin: 0, color: T12.muted, fontSize: T12.fsSm, lineHeight: T12.lhSm }, children: "Shared organizations at your company that you can join as a member." })
|
|
7392
|
+
] }),
|
|
7393
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
7394
|
+
"div",
|
|
7395
|
+
{
|
|
7396
|
+
className: "flex flex-col w-full",
|
|
7397
|
+
style: {
|
|
7398
|
+
background: T12.surface,
|
|
7399
|
+
border: `1px solid ${T12.borderSubtle}`,
|
|
7400
|
+
borderRadius: T12.r3xl
|
|
7401
|
+
},
|
|
7402
|
+
children: joinable.map((org, index) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
7403
|
+
"div",
|
|
7404
|
+
{
|
|
7405
|
+
className: "flex items-center w-full",
|
|
7406
|
+
style: {
|
|
7407
|
+
gap: T12.spXl,
|
|
7408
|
+
padding: `${T12.spXl} ${T12.sp3xl}`,
|
|
7409
|
+
borderTop: index ? `1px solid ${T12.borderSubtle}` : "none"
|
|
7410
|
+
},
|
|
7411
|
+
children: [
|
|
7412
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ProfileAvatar, { name: org.name, profileImage: org.imageUrl, size: 36, borderRadius: T12.rLg }),
|
|
7413
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col flex-1 min-w-0", children: [
|
|
7414
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "truncate", style: { color: T12.primary, fontSize: T12.fsSm, fontWeight: 500, lineHeight: T12.lhSm }, children: org.name }),
|
|
7415
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "truncate", style: { color: T12.muted, fontSize: T12.fsXs, lineHeight: T12.lhXs }, children: ["Shared", org.domain].filter(Boolean).join(" \xB7 ") })
|
|
7416
|
+
] }),
|
|
7417
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
7418
|
+
import_ui9.ScButton,
|
|
7419
|
+
{
|
|
7420
|
+
text: joiningId === org._id ? "Joining\u2026" : "Join",
|
|
7421
|
+
variant: "secondary",
|
|
7422
|
+
size: "sm",
|
|
7423
|
+
state: joiningId ? "disabled" : "default",
|
|
7424
|
+
onClick: joiningId ? void 0 : () => void joinOrganization(org)
|
|
7425
|
+
}
|
|
7426
|
+
)
|
|
7427
|
+
]
|
|
7428
|
+
},
|
|
7429
|
+
org._id
|
|
7430
|
+
))
|
|
7431
|
+
}
|
|
7432
|
+
)
|
|
7433
|
+
] }),
|
|
7361
7434
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
7362
7435
|
OrganizationModal,
|
|
7363
7436
|
{
|
|
@@ -7958,14 +8031,14 @@ function BuyCreditsModal({
|
|
|
7958
8031
|
const maxCredits = Math.round(
|
|
7959
8032
|
topupConfig.maxAmount / topupConfig.pricePerCredit
|
|
7960
8033
|
);
|
|
7961
|
-
const [
|
|
8034
|
+
const [credits2, setCredits] = (0, import_react15.useState)(minCredits);
|
|
7962
8035
|
const [creditsInput, setCreditsInput] = (0, import_react15.useState)(String(minCredits));
|
|
7963
8036
|
const [priceInput, setPriceInput] = (0, import_react15.useState)(
|
|
7964
8037
|
String(minCredits * topupConfig.pricePerCredit)
|
|
7965
8038
|
);
|
|
7966
8039
|
const [activeField, setActiveField] = (0, import_react15.useState)("credits");
|
|
7967
|
-
const parsedCredits = creditsInput.length ? Number(creditsInput) :
|
|
7968
|
-
const previewCredits = Number.isFinite(parsedCredits) ? parsedCredits :
|
|
8040
|
+
const parsedCredits = creditsInput.length ? Number(creditsInput) : credits2;
|
|
8041
|
+
const previewCredits = Number.isFinite(parsedCredits) ? parsedCredits : credits2;
|
|
7969
8042
|
const pricedCredits = previewCredits > 0 ? previewCredits : 0;
|
|
7970
8043
|
const price = Number(
|
|
7971
8044
|
(pricedCredits * topupConfig.pricePerCredit).toFixed(2)
|
|
@@ -7987,8 +8060,8 @@ function BuyCreditsModal({
|
|
|
7987
8060
|
setCreditsInput(String(derived));
|
|
7988
8061
|
setPriceInput(String(amount));
|
|
7989
8062
|
};
|
|
7990
|
-
const handleDecrement = () => syncFromCredits(Math.max(minCredits,
|
|
7991
|
-
const handleIncrement = () => syncFromCredits(Math.min(maxCredits,
|
|
8063
|
+
const handleDecrement = () => syncFromCredits(Math.max(minCredits, credits2 - STEP));
|
|
8064
|
+
const handleIncrement = () => syncFromCredits(Math.min(maxCredits, credits2 + STEP));
|
|
7992
8065
|
const handleCreditsChange = (value) => {
|
|
7993
8066
|
const raw = value.replace(/[^\d]/g, "");
|
|
7994
8067
|
setCreditsInput(raw);
|
|
@@ -8122,7 +8195,7 @@ function BuyCreditsModal({
|
|
|
8122
8195
|
style: {
|
|
8123
8196
|
width: 24,
|
|
8124
8197
|
height: 24,
|
|
8125
|
-
opacity:
|
|
8198
|
+
opacity: credits2 <= minCredits ? 0.3 : 1,
|
|
8126
8199
|
transition: "opacity 0.15s ease"
|
|
8127
8200
|
},
|
|
8128
8201
|
onClick: handleDecrement,
|
|
@@ -8180,7 +8253,7 @@ function BuyCreditsModal({
|
|
|
8180
8253
|
style: {
|
|
8181
8254
|
width: 24,
|
|
8182
8255
|
height: 24,
|
|
8183
|
-
opacity:
|
|
8256
|
+
opacity: credits2 >= maxCredits ? 0.3 : 1,
|
|
8184
8257
|
transition: "opacity 0.15s ease"
|
|
8185
8258
|
},
|
|
8186
8259
|
onClick: handleIncrement,
|
|
@@ -8312,7 +8385,7 @@ function BuyCreditsModal({
|
|
|
8312
8385
|
pointerEvents: isInvalid ? "none" : "auto",
|
|
8313
8386
|
transition: "opacity 0.2s ease"
|
|
8314
8387
|
},
|
|
8315
|
-
onClick: () => onBuy(
|
|
8388
|
+
onClick: () => onBuy(credits2, price),
|
|
8316
8389
|
children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
8317
8390
|
"span",
|
|
8318
8391
|
{
|
|
@@ -9052,7 +9125,7 @@ function PerUserLimitsView() {
|
|
|
9052
9125
|
] });
|
|
9053
9126
|
}
|
|
9054
9127
|
|
|
9055
|
-
// src/
|
|
9128
|
+
// src/shared-credits-view.tsx
|
|
9056
9129
|
var import_react21 = require("react");
|
|
9057
9130
|
var import_ui15 = require("@streamoid/ui");
|
|
9058
9131
|
|
|
@@ -9301,23 +9374,23 @@ function ConfirmActionModal({
|
|
|
9301
9374
|
);
|
|
9302
9375
|
}
|
|
9303
9376
|
|
|
9304
|
-
// src/credit-
|
|
9377
|
+
// src/credit-pool-modal.tsx
|
|
9305
9378
|
var import_react19 = require("react");
|
|
9306
9379
|
var import_ui13 = require("@streamoid/ui");
|
|
9307
9380
|
var import_icons13 = require("@streamoid/icons");
|
|
9308
9381
|
|
|
9309
|
-
// src/credit-
|
|
9310
|
-
var
|
|
9311
|
-
var
|
|
9312
|
-
function
|
|
9313
|
-
return Boolean(api.
|
|
9382
|
+
// src/credit-pool.ts
|
|
9383
|
+
var POOL_NOTE_MAX_LENGTH = 500;
|
|
9384
|
+
var REMOVE_REASON_MAX_LENGTH = 500;
|
|
9385
|
+
function canShowSharedCredits(api, workspace, organization) {
|
|
9386
|
+
return Boolean(api.fetchCreditPool) && Boolean(workspace?.organizationId || organization?.id);
|
|
9314
9387
|
}
|
|
9315
|
-
function
|
|
9388
|
+
function cleanPoolValueInput(raw) {
|
|
9316
9389
|
const kept = raw.replace(/[^\d.]/g, "");
|
|
9317
9390
|
const dot = kept.indexOf(".");
|
|
9318
9391
|
return dot === -1 ? kept : kept.slice(0, dot + 1) + kept.slice(dot + 1).replace(/\./g, "");
|
|
9319
9392
|
}
|
|
9320
|
-
function
|
|
9393
|
+
function validatePoolValue(mode, raw) {
|
|
9321
9394
|
const trimmed = raw.trim();
|
|
9322
9395
|
if (!trimmed) return { ok: false, reason: mode === "percent" ? "Enter a percentage" : "Enter a number of credits" };
|
|
9323
9396
|
if (!/^\d+(\.\d{1,2})?$/.test(trimmed)) {
|
|
@@ -9326,64 +9399,61 @@ function validateAllocationValue(mode, raw, balance) {
|
|
|
9326
9399
|
const value = Number(trimmed);
|
|
9327
9400
|
if (!(value > 0)) return { ok: false, reason: "Enter a number greater than 0" };
|
|
9328
9401
|
if (mode === "percent" && value > 100) return { ok: false, reason: "A percentage can be at most 100" };
|
|
9329
|
-
if (mode === "fixed" && typeof balance === "number" && Number.isFinite(balance) && value > balance) {
|
|
9330
|
-
return {
|
|
9331
|
-
ok: false,
|
|
9332
|
-
reason: `This workspace has ${formatCredits(balance)} credits available`
|
|
9333
|
-
};
|
|
9334
|
-
}
|
|
9335
9402
|
return { ok: true, value };
|
|
9336
9403
|
}
|
|
9337
|
-
function
|
|
9404
|
+
function validatePoolText(raw, max) {
|
|
9338
9405
|
const value = raw.trim();
|
|
9339
9406
|
if (!value) return { ok: false, reason: "Required" };
|
|
9340
9407
|
if (value.length > max) return { ok: false, reason: `At most ${max} characters` };
|
|
9341
9408
|
return { ok: true, value };
|
|
9342
9409
|
}
|
|
9343
|
-
|
|
9410
|
+
var credits = (value) => `${formatCredits(value)} ${value === 1 ? "credit" : "credits"}`;
|
|
9411
|
+
function formatPoolSplit(split) {
|
|
9344
9412
|
if (split.mode === "percent") return `${formatCredits(split.value)}%`;
|
|
9345
|
-
return
|
|
9413
|
+
return credits(split.value);
|
|
9346
9414
|
}
|
|
9347
|
-
function
|
|
9348
|
-
|
|
9415
|
+
function describeAllowance(member) {
|
|
9416
|
+
const allowance = `${credits(member.allowance)} this cycle`;
|
|
9417
|
+
return member.mode === "percent" ? `${formatPoolSplit(member)} \xB7 ${allowance}` : allowance;
|
|
9349
9418
|
}
|
|
9350
|
-
function
|
|
9351
|
-
const split = formatAllocationSplit(allocation);
|
|
9352
|
-
if (!allocation.recurring) return `${split} once`;
|
|
9353
|
-
return allocation.mode === "percent" ? `${split} of each renewal` : `${split} every renewal`;
|
|
9354
|
-
}
|
|
9355
|
-
function allocationWorkspaceName(name) {
|
|
9419
|
+
function poolWorkspaceName(name) {
|
|
9356
9420
|
return name?.trim() || "Unknown workspace";
|
|
9357
9421
|
}
|
|
9358
|
-
function
|
|
9359
|
-
const
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9373
|
-
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
"
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
]
|
|
9385
|
-
|
|
9386
|
-
|
|
9422
|
+
function sharedPoolBannerText(pool) {
|
|
9423
|
+
const sponsor = pool.sponsorName?.trim() || "another workspace";
|
|
9424
|
+
return `Credits shared by ${sponsor}: ${formatCredits(pool.remaining)} of ${formatCredits(pool.allowance)} left this cycle`;
|
|
9425
|
+
}
|
|
9426
|
+
function creditsMeter({
|
|
9427
|
+
availableCredits,
|
|
9428
|
+
totalCredits,
|
|
9429
|
+
sharedPool
|
|
9430
|
+
}) {
|
|
9431
|
+
if (sharedPool) {
|
|
9432
|
+
const used2 = Math.max(0, sharedPool.used);
|
|
9433
|
+
const remaining = Math.max(0, sharedPool.remaining);
|
|
9434
|
+
const progressPct2 = sharedPool.allowance > 0 ? Math.min(100, Math.round(used2 / sharedPool.allowance * 100)) : 100;
|
|
9435
|
+
return { used: used2, remaining, progressPct: progressPct2, remainingPct: 100 - progressPct2 };
|
|
9436
|
+
}
|
|
9437
|
+
const used = availableCredits != null && totalCredits != null ? Math.max(0, totalCredits - availableCredits) : null;
|
|
9438
|
+
const progressPct = used != null && totalCredits != null && totalCredits > 0 ? Math.min(100, Math.round(used / totalCredits * 100)) : 0;
|
|
9439
|
+
return { used, remaining: availableCredits, progressPct, remainingPct: 100 - progressPct };
|
|
9440
|
+
}
|
|
9441
|
+
function usedByWorkspaceKey(log, currentWorkspaceId) {
|
|
9442
|
+
const usedBy = log.meta?.usedBy;
|
|
9443
|
+
if (typeof usedBy !== "string" || !usedBy) return null;
|
|
9444
|
+
return usedBy.toLowerCase() === String(currentWorkspaceId ?? "").toLowerCase() ? null : usedBy;
|
|
9445
|
+
}
|
|
9446
|
+
function usedByNamesFrom(pool) {
|
|
9447
|
+
const names = {};
|
|
9448
|
+
for (const member of [...pool?.formerMembers ?? [], ...pool?.members ?? []]) {
|
|
9449
|
+
const name = member.memberWorkspaceName?.trim();
|
|
9450
|
+
if (name && member.memberWorkspaceKey) names[member.memberWorkspaceKey.toLowerCase()] = name;
|
|
9451
|
+
}
|
|
9452
|
+
return names;
|
|
9453
|
+
}
|
|
9454
|
+
var POOL_ERROR_CODES = ["SPONSOR_ON_FREE_PLAN", "POOL_NOT_ALLOWED"];
|
|
9455
|
+
function findPoolError(failure) {
|
|
9456
|
+
const error = findBillingError(failure, POOL_ERROR_CODES);
|
|
9387
9457
|
if (!error) return null;
|
|
9388
9458
|
const status = error.status;
|
|
9389
9459
|
const message = [status?.message, error.error, error.message].find(
|
|
@@ -9392,29 +9462,18 @@ function findAllocationError(failure) {
|
|
|
9392
9462
|
const details = error.details && typeof error.details === "object" ? error.details : {};
|
|
9393
9463
|
return { code: error.code, details, message: message ?? null };
|
|
9394
9464
|
}
|
|
9395
|
-
|
|
9396
|
-
|
|
9397
|
-
const found = findAllocationError(failure);
|
|
9465
|
+
function poolErrorMessage(failure) {
|
|
9466
|
+
const found = findPoolError(failure);
|
|
9398
9467
|
if (!found) return null;
|
|
9399
9468
|
switch (found.code) {
|
|
9400
|
-
case "
|
|
9401
|
-
const balance = num(found.details.currentBalance);
|
|
9402
|
-
const required = num(found.details.requiredCredits);
|
|
9403
|
-
if (balance !== null && required !== null) {
|
|
9404
|
-
return `Not enough credits: this would send ${formatCredits(required)} now, but the workspace has ${formatCredits(balance)}.`;
|
|
9405
|
-
}
|
|
9406
|
-
return "This workspace doesn't have enough credits to send that now.";
|
|
9407
|
-
}
|
|
9408
|
-
case "SOURCE_ON_FREE_PLAN":
|
|
9469
|
+
case "SPONSOR_ON_FREE_PLAN":
|
|
9409
9470
|
return "A workspace on the free plan can't share credits. Upgrade this workspace's plan first.";
|
|
9410
|
-
case "
|
|
9411
|
-
return found.message ? found.message.replace(/\.?$/, ".") : "
|
|
9412
|
-
case "TARGET_PLAN_CHANGE_FAILED":
|
|
9413
|
-
return found.details.allocationId ? "The target workspace moved to the Custom plan, but its plan details weren't saved. Cancel this allocation to move it back to free." : "Couldn't move the target workspace to the Custom plan, so nothing was transferred. Try again.";
|
|
9471
|
+
case "POOL_NOT_ALLOWED":
|
|
9472
|
+
return found.message ? found.message.replace(/\.?$/, ".") : "Credits can't be shared with that workspace.";
|
|
9414
9473
|
}
|
|
9415
9474
|
}
|
|
9416
9475
|
|
|
9417
|
-
// src/credit-
|
|
9476
|
+
// src/credit-pool-modal.tsx
|
|
9418
9477
|
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
9419
9478
|
var MODAL_T = {
|
|
9420
9479
|
primary: "var(--alias-text---icons-primary)",
|
|
@@ -9447,7 +9506,7 @@ var modalBodyText = {
|
|
|
9447
9506
|
fontSize: T16.fsSm,
|
|
9448
9507
|
lineHeight: T16.lhSm
|
|
9449
9508
|
};
|
|
9450
|
-
function
|
|
9509
|
+
function PoolModalShell({
|
|
9451
9510
|
title,
|
|
9452
9511
|
busy,
|
|
9453
9512
|
onClose,
|
|
@@ -9548,7 +9607,7 @@ function AllocationModalShell({
|
|
|
9548
9607
|
}
|
|
9549
9608
|
);
|
|
9550
9609
|
}
|
|
9551
|
-
function
|
|
9610
|
+
function PoolWarning({ children }) {
|
|
9552
9611
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9553
9612
|
"div",
|
|
9554
9613
|
{
|
|
@@ -9567,68 +9626,55 @@ function AllocationWarning({ children }) {
|
|
|
9567
9626
|
);
|
|
9568
9627
|
}
|
|
9569
9628
|
var fieldLabel = { ...modalBodyText, fontWeight: 500, color: T16.primary };
|
|
9570
|
-
function
|
|
9629
|
+
function CreditPoolMemberModal(props) {
|
|
9571
9630
|
const { toast } = useSettingsAdapters();
|
|
9572
|
-
const editing = props.kind === "edit" ? props.
|
|
9573
|
-
const [
|
|
9574
|
-
const [mode, setMode] = (0, import_react19.useState)(editing?.mode ?? "
|
|
9631
|
+
const editing = props.kind === "edit" ? props.member : null;
|
|
9632
|
+
const [memberId, setMemberId] = (0, import_react19.useState)("");
|
|
9633
|
+
const [mode, setMode] = (0, import_react19.useState)(editing?.mode ?? "percent");
|
|
9575
9634
|
const [raw, setRaw] = (0, import_react19.useState)(editing ? String(editing.value) : "");
|
|
9576
|
-
const [recurring, setRecurring] = (0, import_react19.useState)(editing?.recurring ?? true);
|
|
9577
9635
|
const [note, setNote] = (0, import_react19.useState)("");
|
|
9578
9636
|
const [touched, setTouched] = (0, import_react19.useState)(false);
|
|
9579
9637
|
const [saving, setSaving] = (0, import_react19.useState)(false);
|
|
9580
9638
|
const [serverError, setServerError] = (0, import_react19.useState)(null);
|
|
9581
9639
|
(0, import_react19.useEffect)(() => {
|
|
9582
9640
|
setServerError(null);
|
|
9583
|
-
}, [
|
|
9584
|
-
const
|
|
9585
|
-
const
|
|
9586
|
-
const
|
|
9587
|
-
const
|
|
9588
|
-
const changed = !editing || splitChanged || recurring !== editing.recurring;
|
|
9589
|
-
const valid = value.ok && (props.kind === "edit" || Boolean(targetId) && noteCheck.ok);
|
|
9641
|
+
}, [memberId, mode, raw, note]);
|
|
9642
|
+
const value = validatePoolValue(mode, raw);
|
|
9643
|
+
const noteCheck = validatePoolText(note, POOL_NOTE_MAX_LENGTH);
|
|
9644
|
+
const changed = !editing || mode !== editing.mode || !value.ok || value.value !== editing.value;
|
|
9645
|
+
const valid = value.ok && (props.kind === "edit" || Boolean(memberId) && noteCheck.ok);
|
|
9590
9646
|
const canSave = !saving && changed && valid;
|
|
9591
9647
|
const valueHint = touched && !value.ok ? value.reason : null;
|
|
9592
|
-
const percentNow = props.kind === "create" && mode === "percent" && value.ok && balance !== null ? Math.floor(roundCredits(balance * value.value / 100) * 100) / 100 : null;
|
|
9593
9648
|
const handleSave = async () => {
|
|
9594
9649
|
if (!canSave || !value.ok) return;
|
|
9595
9650
|
setSaving(true);
|
|
9596
9651
|
try {
|
|
9597
|
-
if (props.kind === "
|
|
9598
|
-
const
|
|
9599
|
-
|
|
9652
|
+
if (props.kind === "add") {
|
|
9653
|
+
const added = await props.onSave({
|
|
9654
|
+
memberWorkspaceId: memberId,
|
|
9600
9655
|
mode,
|
|
9601
9656
|
value: value.value,
|
|
9602
|
-
recurring,
|
|
9603
9657
|
note: noteCheck.ok ? noteCheck.value : ""
|
|
9604
9658
|
});
|
|
9605
|
-
|
|
9606
|
-
if (warning) toast.error(warning);
|
|
9607
|
-
else {
|
|
9608
|
-
const sent = initialTransferSummary(created);
|
|
9609
|
-
toast.success(sent ? `Allocation created. ${sent}.` : "Allocation created");
|
|
9610
|
-
}
|
|
9659
|
+
toast.success(`Credits shared. ${describeAllowance(added)}.`);
|
|
9611
9660
|
} else {
|
|
9612
|
-
await props.onSave(
|
|
9613
|
-
|
|
9614
|
-
);
|
|
9615
|
-
toast.success("Allocation updated. Applies from the next renewal.");
|
|
9661
|
+
const updated = await props.onSave({ mode, value: value.value });
|
|
9662
|
+
toast.success(`Share updated. ${describeAllowance(updated)}.`);
|
|
9616
9663
|
}
|
|
9617
9664
|
props.onSaved();
|
|
9618
9665
|
props.onClose();
|
|
9619
9666
|
} catch (err) {
|
|
9620
|
-
const message =
|
|
9667
|
+
const message = poolErrorMessage(err);
|
|
9621
9668
|
if (message) setServerError(message);
|
|
9622
|
-
else toast.error(errorMessage(err, { method: props.kind === "
|
|
9623
|
-
if (findAllocationError(err)?.details.allocationId) props.onSaved();
|
|
9669
|
+
else toast.error(errorMessage(err, { method: props.kind === "add" ? "POST" : "PATCH" }));
|
|
9624
9670
|
setSaving(false);
|
|
9625
9671
|
}
|
|
9626
9672
|
};
|
|
9627
|
-
const
|
|
9673
|
+
const candidateOptions = props.kind === "add" ? props.candidates.map((candidate) => ({ id: candidate.id, label: candidate.name })) : [];
|
|
9628
9674
|
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
9629
|
-
|
|
9675
|
+
PoolModalShell,
|
|
9630
9676
|
{
|
|
9631
|
-
title: props.kind === "
|
|
9677
|
+
title: props.kind === "add" ? "Share credits" : "Edit shared credits",
|
|
9632
9678
|
busy: saving,
|
|
9633
9679
|
onClose: props.onClose,
|
|
9634
9680
|
footer: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
@@ -9645,7 +9691,7 @@ function CreditAllocationModal(props) {
|
|
|
9645
9691
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9646
9692
|
import_ui13.ScButton,
|
|
9647
9693
|
{
|
|
9648
|
-
text: props.kind === "
|
|
9694
|
+
text: props.kind === "add" ? "Share credits" : "Save",
|
|
9649
9695
|
variant: "primary",
|
|
9650
9696
|
size: "md",
|
|
9651
9697
|
state: canSave ? "default" : "disabled",
|
|
@@ -9655,29 +9701,29 @@ function CreditAllocationModal(props) {
|
|
|
9655
9701
|
] }),
|
|
9656
9702
|
children: [
|
|
9657
9703
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T16.spXs }, children: [
|
|
9658
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "
|
|
9659
|
-
props.kind === "
|
|
9704
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "Share with" }),
|
|
9705
|
+
props.kind === "add" ? candidateOptions.length ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9660
9706
|
import_ui13.ScSelect,
|
|
9661
9707
|
{
|
|
9662
|
-
value:
|
|
9663
|
-
onChange:
|
|
9664
|
-
options:
|
|
9708
|
+
value: memberId,
|
|
9709
|
+
onChange: setMemberId,
|
|
9710
|
+
options: candidateOptions,
|
|
9665
9711
|
placeholder: "Choose a workspace",
|
|
9666
9712
|
disabled: saving
|
|
9667
9713
|
}
|
|
9668
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { ...modalBodyText, color: T16.muted }, children: "There are no other workspaces in this organization to
|
|
9714
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { ...modalBodyText, color: T16.muted }, children: "There are no other workspaces in this organization to share credits with." }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { ...modalBodyText, color: T16.primary }, children: props.memberName })
|
|
9669
9715
|
] }),
|
|
9670
9716
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T16.spMd }, children: [
|
|
9671
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "How much" }),
|
|
9717
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "How much, each billing cycle" }),
|
|
9672
9718
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center", style: { gap: T16.sp3xl }, children: [
|
|
9673
9719
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9674
9720
|
import_ui13.ScPairtext,
|
|
9675
9721
|
{
|
|
9676
9722
|
type: "radio",
|
|
9677
|
-
content: "
|
|
9678
|
-
checked: mode === "
|
|
9723
|
+
content: "Percentage",
|
|
9724
|
+
checked: mode === "percent",
|
|
9679
9725
|
onChange: () => {
|
|
9680
|
-
if (!saving) setMode("
|
|
9726
|
+
if (!saving) setMode("percent");
|
|
9681
9727
|
}
|
|
9682
9728
|
}
|
|
9683
9729
|
),
|
|
@@ -9685,10 +9731,10 @@ function CreditAllocationModal(props) {
|
|
|
9685
9731
|
import_ui13.ScPairtext,
|
|
9686
9732
|
{
|
|
9687
9733
|
type: "radio",
|
|
9688
|
-
content: "
|
|
9689
|
-
checked: mode === "
|
|
9734
|
+
content: "Fixed credits",
|
|
9735
|
+
checked: mode === "fixed",
|
|
9690
9736
|
onChange: () => {
|
|
9691
|
-
if (!saving) setMode("
|
|
9737
|
+
if (!saving) setMode("fixed");
|
|
9692
9738
|
}
|
|
9693
9739
|
}
|
|
9694
9740
|
)
|
|
@@ -9716,7 +9762,7 @@ function CreditAllocationModal(props) {
|
|
|
9716
9762
|
value: raw,
|
|
9717
9763
|
disabled: saving,
|
|
9718
9764
|
onChange: (e) => {
|
|
9719
|
-
setRaw(
|
|
9765
|
+
setRaw(cleanPoolValueInput(e.target.value));
|
|
9720
9766
|
setTouched(true);
|
|
9721
9767
|
},
|
|
9722
9768
|
className: "flex-1 min-w-0",
|
|
@@ -9734,39 +9780,18 @@ function CreditAllocationModal(props) {
|
|
|
9734
9780
|
]
|
|
9735
9781
|
}
|
|
9736
9782
|
),
|
|
9737
|
-
valueHint ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: valueHint }) :
|
|
9738
|
-
|
|
9739
|
-
|
|
9740
|
-
|
|
9741
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "Repeat on every renewal" }),
|
|
9742
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { ...modalBodyText, color: T16.muted }, children: mode === "percent" ? "Also send this share of each renewal grant this workspace receives." : "Also send these credits out of each renewal grant this workspace receives." })
|
|
9743
|
-
] }),
|
|
9744
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: { display: "inline-flex", width: 41, height: 25, alignItems: "center", flexShrink: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9745
|
-
import_ui13.ScToggleSwitch,
|
|
9746
|
-
{
|
|
9747
|
-
checked: recurring,
|
|
9748
|
-
disabled: saving,
|
|
9749
|
-
onToggle: (next) => setRecurring(next),
|
|
9750
|
-
role: "switch",
|
|
9751
|
-
"aria-checked": recurring,
|
|
9752
|
-
"aria-label": "Repeat on every renewal",
|
|
9753
|
-
tabIndex: 0,
|
|
9754
|
-
onKeyDown: (event) => {
|
|
9755
|
-
if ((event.key === " " || event.key === "Enter") && !saving) {
|
|
9756
|
-
event.preventDefault();
|
|
9757
|
-
setRecurring(!recurring);
|
|
9758
|
-
}
|
|
9759
|
-
}
|
|
9760
|
-
}
|
|
9761
|
-
) })
|
|
9783
|
+
valueHint ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: valueHint }) : /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { style: { ...modalBodyText, color: T16.tertiary }, children: [
|
|
9784
|
+
mode === "percent" ? "A share of this workspace's plan credits for each billing cycle. Credits stay with this workspace; the other workspace spends them up to this share." : "Credits the other workspace may spend each billing cycle. Credits stay with this workspace until spent.",
|
|
9785
|
+
editing ? " Applies immediately." : ""
|
|
9786
|
+
] })
|
|
9762
9787
|
] }),
|
|
9763
|
-
props.kind === "
|
|
9788
|
+
props.kind === "add" && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col w-full", style: { gap: T16.spXs }, children: [
|
|
9764
9789
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { style: fieldLabel, children: "Note" }),
|
|
9765
9790
|
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
9766
9791
|
import_ui13.ScTextArea,
|
|
9767
9792
|
{
|
|
9768
9793
|
value: note,
|
|
9769
|
-
maxLength:
|
|
9794
|
+
maxLength: POOL_NOTE_MAX_LENGTH,
|
|
9770
9795
|
placeholder: "Why are these credits being shared?",
|
|
9771
9796
|
disabled: saving,
|
|
9772
9797
|
onChange: (e) => setNote(e.target.value),
|
|
@@ -9778,117 +9803,57 @@ function CreditAllocationModal(props) {
|
|
|
9778
9803
|
"Required. ",
|
|
9779
9804
|
note.trim().length,
|
|
9780
9805
|
"/",
|
|
9781
|
-
|
|
9806
|
+
POOL_NOTE_MAX_LENGTH
|
|
9782
9807
|
] })
|
|
9783
9808
|
] }),
|
|
9784
|
-
props.kind === "
|
|
9809
|
+
props.kind === "add" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(PoolWarning, { children: "While it spends shared credits, the other workspace uses only this workspace's credits, not its own." }),
|
|
9785
9810
|
serverError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("span", { role: "alert", style: { ...modalBodyText, color: T16.error }, children: serverError })
|
|
9786
9811
|
]
|
|
9787
9812
|
}
|
|
9788
9813
|
);
|
|
9789
9814
|
}
|
|
9790
9815
|
|
|
9791
|
-
// src/
|
|
9816
|
+
// src/remove-pool-member-modal.tsx
|
|
9792
9817
|
var import_react20 = require("react");
|
|
9793
9818
|
var import_ui14 = require("@streamoid/ui");
|
|
9794
9819
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
9795
|
-
function
|
|
9796
|
-
|
|
9797
|
-
|
|
9798
|
-
|
|
9820
|
+
function RemovePoolMemberModal({
|
|
9821
|
+
member,
|
|
9822
|
+
memberName,
|
|
9823
|
+
sponsorName,
|
|
9824
|
+
onRemove,
|
|
9799
9825
|
onClose,
|
|
9800
|
-
|
|
9826
|
+
onRemoved
|
|
9801
9827
|
}) {
|
|
9802
9828
|
const { toast } = useSettingsAdapters();
|
|
9803
9829
|
const [reason, setReason] = (0, import_react20.useState)("");
|
|
9804
9830
|
const [saving, setSaving] = (0, import_react20.useState)(false);
|
|
9805
|
-
const
|
|
9806
|
-
const check = validateAllocationText(reason, CANCEL_REASON_MAX_LENGTH);
|
|
9831
|
+
const check = validatePoolText(reason, REMOVE_REASON_MAX_LENGTH);
|
|
9807
9832
|
const canConfirm = !saving && check.ok;
|
|
9808
9833
|
const handleConfirm = async () => {
|
|
9809
9834
|
if (!canConfirm || !check.ok) return;
|
|
9810
9835
|
setSaving(true);
|
|
9811
9836
|
try {
|
|
9812
|
-
|
|
9813
|
-
|
|
9814
|
-
|
|
9815
|
-
targetName
|
|
9816
|
-
);
|
|
9817
|
-
onCanceled({ planNotRestored: Boolean(warning) });
|
|
9818
|
-
if (warning) {
|
|
9819
|
-
setOutcome({ warning, error: result.error });
|
|
9820
|
-
setSaving(false);
|
|
9821
|
-
return;
|
|
9822
|
-
}
|
|
9823
|
-
toast.success(cancelOutcomeSummary(result, targetName));
|
|
9837
|
+
await onRemove(check.value);
|
|
9838
|
+
toast.success(`${memberName} can no longer spend ${sponsorName}'s credits`);
|
|
9839
|
+
onRemoved();
|
|
9824
9840
|
onClose();
|
|
9825
9841
|
} catch (err) {
|
|
9826
9842
|
toast.error(errorMessage(err, { method: "DELETE" }));
|
|
9827
9843
|
setSaving(false);
|
|
9828
9844
|
}
|
|
9829
9845
|
};
|
|
9830
|
-
const copyId = () => {
|
|
9831
|
-
const id = allocation.targetWorkspaceKey;
|
|
9832
|
-
const clipboard = typeof navigator !== "undefined" ? navigator.clipboard : void 0;
|
|
9833
|
-
if (!clipboard) {
|
|
9834
|
-
toast.error("Couldn't copy. Select the ID and copy it instead.");
|
|
9835
|
-
return;
|
|
9836
|
-
}
|
|
9837
|
-
clipboard.writeText(id).then(
|
|
9838
|
-
() => toast.success("Workspace ID copied"),
|
|
9839
|
-
() => toast.error("Couldn't copy. Select the ID and copy it instead.")
|
|
9840
|
-
);
|
|
9841
|
-
};
|
|
9842
|
-
if (outcome) {
|
|
9843
|
-
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
9844
|
-
AllocationModalShell,
|
|
9845
|
-
{
|
|
9846
|
-
title: "Target plan not restored",
|
|
9847
|
-
busy: false,
|
|
9848
|
-
onClose,
|
|
9849
|
-
footer: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui14.ScButton, { text: "Got it", variant: "primary", size: "md", onClick: onClose }),
|
|
9850
|
-
children: [
|
|
9851
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(AllocationWarning, { children: outcome.warning }),
|
|
9852
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col w-full", style: { gap: MODAL_T.spXs }, children: [
|
|
9853
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { ...modalBodyText, fontWeight: 500, color: MODAL_T.primary }, children: "Workspace ID" }),
|
|
9854
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex items-center w-full", style: { gap: MODAL_T.spXl }, children: [
|
|
9855
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
9856
|
-
"code",
|
|
9857
|
-
{
|
|
9858
|
-
className: "flex-1 min-w-0 truncate",
|
|
9859
|
-
style: {
|
|
9860
|
-
...modalBodyText,
|
|
9861
|
-
color: MODAL_T.primary,
|
|
9862
|
-
background: MODAL_T.fillPlus,
|
|
9863
|
-
borderRadius: MODAL_T.r3xl,
|
|
9864
|
-
padding: `${MODAL_T.spXl} ${MODAL_T.sp3xl}`,
|
|
9865
|
-
userSelect: "all"
|
|
9866
|
-
},
|
|
9867
|
-
children: allocation.targetWorkspaceKey
|
|
9868
|
-
}
|
|
9869
|
-
),
|
|
9870
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui14.ScButton, { text: "Copy", variant: "secondary", size: "sm", onClick: copyId })
|
|
9871
|
-
] })
|
|
9872
|
-
] }),
|
|
9873
|
-
outcome.error && /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { ...modalBodyText, color: MODAL_T.muted }, children: [
|
|
9874
|
-
"Details: ",
|
|
9875
|
-
outcome.error
|
|
9876
|
-
] })
|
|
9877
|
-
]
|
|
9878
|
-
}
|
|
9879
|
-
);
|
|
9880
|
-
}
|
|
9881
9846
|
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
9882
|
-
|
|
9847
|
+
PoolModalShell,
|
|
9883
9848
|
{
|
|
9884
|
-
title: "
|
|
9849
|
+
title: "Stop sharing credits",
|
|
9885
9850
|
busy: saving,
|
|
9886
9851
|
onClose,
|
|
9887
9852
|
footer: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_jsx_runtime26.Fragment, { children: [
|
|
9888
9853
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
9889
9854
|
import_ui14.ScButton,
|
|
9890
9855
|
{
|
|
9891
|
-
text: "Keep
|
|
9856
|
+
text: "Keep sharing",
|
|
9892
9857
|
variant: "secondary",
|
|
9893
9858
|
size: "md",
|
|
9894
9859
|
state: saving ? "disabled" : "default",
|
|
@@ -9898,7 +9863,7 @@ function CancelCreditAllocationModal({
|
|
|
9898
9863
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
9899
9864
|
import_ui14.ScButton,
|
|
9900
9865
|
{
|
|
9901
|
-
text: "
|
|
9866
|
+
text: "Stop sharing",
|
|
9902
9867
|
variant: "error",
|
|
9903
9868
|
size: "md",
|
|
9904
9869
|
state: canConfirm ? "default" : "disabled",
|
|
@@ -9908,16 +9873,18 @@ function CancelCreditAllocationModal({
|
|
|
9908
9873
|
] }),
|
|
9909
9874
|
children: [
|
|
9910
9875
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { ...modalBodyText, color: MODAL_T.primary }, children: [
|
|
9911
|
-
"
|
|
9912
|
-
|
|
9913
|
-
"
|
|
9914
|
-
|
|
9915
|
-
"
|
|
9876
|
+
"This stops ",
|
|
9877
|
+
memberName,
|
|
9878
|
+
" spending ",
|
|
9879
|
+
sponsorName,
|
|
9880
|
+
"'s credits immediately."
|
|
9916
9881
|
] }),
|
|
9917
9882
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { style: { ...modalBodyText, color: MODAL_T.tertiary }, children: [
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
|
|
9883
|
+
"It had ",
|
|
9884
|
+
describeAllowance(member),
|
|
9885
|
+
" and has used ",
|
|
9886
|
+
formatCredits(member.used),
|
|
9887
|
+
". Credits it already spent are not returned; anything it runs from now uses its own credits."
|
|
9921
9888
|
] }),
|
|
9922
9889
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { className: "flex flex-col w-full", style: { gap: MODAL_T.spXs }, children: [
|
|
9923
9890
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { style: { ...modalBodyText, fontWeight: 500, color: MODAL_T.primary }, children: "Reason" }),
|
|
@@ -9925,8 +9892,8 @@ function CancelCreditAllocationModal({
|
|
|
9925
9892
|
import_ui14.ScTextArea,
|
|
9926
9893
|
{
|
|
9927
9894
|
value: reason,
|
|
9928
|
-
maxLength:
|
|
9929
|
-
placeholder: "Why is this
|
|
9895
|
+
maxLength: REMOVE_REASON_MAX_LENGTH,
|
|
9896
|
+
placeholder: "Why is this workspace no longer sharing these credits?",
|
|
9930
9897
|
disabled: saving,
|
|
9931
9898
|
onChange: (e) => setReason(e.target.value),
|
|
9932
9899
|
rows: 3,
|
|
@@ -9940,16 +9907,13 @@ function CancelCreditAllocationModal({
|
|
|
9940
9907
|
);
|
|
9941
9908
|
}
|
|
9942
9909
|
|
|
9943
|
-
// src/
|
|
9910
|
+
// src/shared-credits-view.tsx
|
|
9944
9911
|
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
9945
9912
|
var T17 = {
|
|
9946
9913
|
primary: "var(--alias-text---icons-primary)",
|
|
9947
9914
|
muted: "var(--alias-text---icons-muted)",
|
|
9948
9915
|
tertiary: "var(--alias-text---icons-tertiary)",
|
|
9949
9916
|
warning: "var(--alias-text---icons-warning)",
|
|
9950
|
-
success: "var(--alias-text---icons-success)",
|
|
9951
|
-
warningFill: "var(--alias-fill-warning-soft)",
|
|
9952
|
-
warningBorder: "var(--alias-border-warning)",
|
|
9953
9917
|
fillPlus: "var(--alias-fill-neutral-neutralplus)",
|
|
9954
9918
|
surfaceBase: "var(--alias-surface-base)",
|
|
9955
9919
|
borderSubtle: "var(--alias-border-subtle)",
|
|
@@ -9963,9 +9927,7 @@ var T17 = {
|
|
|
9963
9927
|
r3xl: "var(--radius-3xl)",
|
|
9964
9928
|
rFull: "var(--radius-full)"
|
|
9965
9929
|
};
|
|
9966
|
-
var
|
|
9967
|
-
var TRANSFER_COLUMNS = "120px 170px minmax(200px, 1fr) 120px";
|
|
9968
|
-
var TRANSFERS_PAGE = 20;
|
|
9930
|
+
var MEMBER_COLUMNS2 = "minmax(220px, 1fr) 220px 110px 110px 150px";
|
|
9969
9931
|
var cellText2 = {
|
|
9970
9932
|
fontFamily: T17.font,
|
|
9971
9933
|
fontSize: T17.fsSm,
|
|
@@ -9987,138 +9949,67 @@ var tableHeader = (columns, labels) => /* @__PURE__ */ (0, import_jsx_runtime27.
|
|
|
9987
9949
|
children: labels.map((label) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: label }, label))
|
|
9988
9950
|
}
|
|
9989
9951
|
);
|
|
9990
|
-
function
|
|
9991
|
-
|
|
9992
|
-
"span",
|
|
9993
|
-
{
|
|
9994
|
-
className: "inline-flex items-center shrink-0",
|
|
9995
|
-
style: {
|
|
9996
|
-
...cellText2,
|
|
9997
|
-
fontSize: 12,
|
|
9998
|
-
padding: "0 8px",
|
|
9999
|
-
height: 22,
|
|
10000
|
-
borderRadius: T17.rFull,
|
|
10001
|
-
color: tone === "warning" ? T17.primary : T17.muted,
|
|
10002
|
-
background: tone === "warning" ? T17.warningFill : T17.fillPlus,
|
|
10003
|
-
border: tone === "warning" ? `1px solid ${T17.warningBorder}` : "1px solid transparent"
|
|
10004
|
-
},
|
|
10005
|
-
children: text2
|
|
10006
|
-
}
|
|
10007
|
-
);
|
|
10008
|
-
}
|
|
10009
|
-
function GivingRow({
|
|
10010
|
-
allocation,
|
|
10011
|
-
planNotRestored,
|
|
9952
|
+
function MemberRow2({
|
|
9953
|
+
member,
|
|
10012
9954
|
onEdit,
|
|
10013
|
-
|
|
9955
|
+
onRemove
|
|
10014
9956
|
}) {
|
|
10015
|
-
const
|
|
10016
|
-
const sent = initialTransferSummary(allocation);
|
|
10017
|
-
const active = allocation.status === "active";
|
|
9957
|
+
const spent = member.remaining <= 0;
|
|
10018
9958
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
10019
9959
|
"div",
|
|
10020
9960
|
{
|
|
10021
9961
|
style: {
|
|
10022
9962
|
borderBottom: `1px solid ${T17.borderSubtle}`,
|
|
10023
9963
|
display: "grid",
|
|
10024
|
-
gridTemplateColumns:
|
|
9964
|
+
gridTemplateColumns: MEMBER_COLUMNS2,
|
|
10025
9965
|
alignItems: "center",
|
|
10026
9966
|
padding: `10px ${T17.sp3xl}`,
|
|
10027
9967
|
gap: 24
|
|
10028
9968
|
},
|
|
10029
9969
|
children: [
|
|
10030
9970
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col min-w-0", style: { gap: 2 }, children: [
|
|
10031
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", style: { ...cellText2, fontWeight: 500 }, children:
|
|
10032
|
-
|
|
10033
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { text: "First transfer failed", tone: "warning" }) }),
|
|
10034
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: T17.muted }, children: failed })
|
|
10035
|
-
] }) : sent ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: T17.muted }, children: sent }) : null,
|
|
10036
|
-
allocation.note && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", title: allocation.note, style: { ...cellText2, color: T17.tertiary }, children: allocation.note })
|
|
10037
|
-
] }),
|
|
10038
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: cellText2, children: formatAllocationSplit(allocation) }),
|
|
10039
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: cellText2, children: formatAllocationRepeat(allocation.recurring) }),
|
|
10040
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap items-center", style: { gap: 6 }, children: [
|
|
10041
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { text: active ? "Active" : "Canceled", tone: "neutral" }),
|
|
10042
|
-
planNotRestored && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Badge, { text: "Plan not restored", tone: "warning" })
|
|
9971
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", style: { ...cellText2, fontWeight: 500 }, children: poolWorkspaceName(member.memberWorkspaceName) }),
|
|
9972
|
+
member.note && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", title: member.note, style: { ...cellText2, color: T17.tertiary }, children: member.note })
|
|
10043
9973
|
] }),
|
|
10044
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style:
|
|
9974
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: cellText2, children: describeAllowance(member) }),
|
|
9975
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: cellText2, children: formatCredits(member.used) }),
|
|
9976
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: spent ? T17.warning : T17.primary }, children: formatCredits(member.remaining) }),
|
|
10045
9977
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center", style: { gap: 8 }, children: [
|
|
10046
|
-
|
|
10047
|
-
|
|
10048
|
-
] })
|
|
10049
|
-
]
|
|
10050
|
-
}
|
|
10051
|
-
);
|
|
10052
|
-
}
|
|
10053
|
-
function TransferRow({ transfer }) {
|
|
10054
|
-
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
10055
|
-
"div",
|
|
10056
|
-
{
|
|
10057
|
-
style: {
|
|
10058
|
-
borderBottom: `1px solid ${T17.borderSubtle}`,
|
|
10059
|
-
display: "grid",
|
|
10060
|
-
gridTemplateColumns: TRANSFER_COLUMNS,
|
|
10061
|
-
alignItems: "center",
|
|
10062
|
-
padding: `8px ${T17.sp3xl}`,
|
|
10063
|
-
gap: 24
|
|
10064
|
-
},
|
|
10065
|
-
children: [
|
|
10066
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: T17.muted }, children: formatDate2(transfer.createdAt) }),
|
|
10067
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { style: cellText2, children: [
|
|
10068
|
-
transfer.direction === "sent" ? "Sent" : "Received",
|
|
10069
|
-
" \xB7",
|
|
10070
|
-
" ",
|
|
10071
|
-
transfer.kind === "initial" ? "Initial" : "Renewal"
|
|
10072
|
-
] }),
|
|
10073
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "truncate", style: cellText2, children: transfer.counterpartWorkspaceName ?? (transfer.counterpartWorkspaceId ? "Unknown workspace" : "\u2014") }),
|
|
10074
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { style: { ...cellText2, color: transfer.direction === "received" ? T17.success : T17.primary }, children: [
|
|
10075
|
-
transfer.direction === "received" ? "+" : "\u2212",
|
|
10076
|
-
formatCredits(transfer.credits)
|
|
9978
|
+
onEdit && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui15.ScButton, { text: "Edit", variant: "secondary", size: "sm", onClick: onEdit }),
|
|
9979
|
+
onRemove && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui15.ScButton, { text: "Remove", variant: "secondary", size: "sm", onClick: onRemove })
|
|
10077
9980
|
] })
|
|
10078
9981
|
]
|
|
10079
9982
|
}
|
|
10080
9983
|
);
|
|
10081
9984
|
}
|
|
10082
|
-
function
|
|
9985
|
+
function SharedCreditsView() {
|
|
10083
9986
|
const { api, workspace, toast } = useSettingsAdapters();
|
|
10084
9987
|
const workspaceId = workspace.current?.id ?? null;
|
|
9988
|
+
const workspaceName = workspace.current?.name?.trim() || "this workspace";
|
|
10085
9989
|
const [data, setData] = (0, import_react21.useState)(null);
|
|
10086
9990
|
const [loading, setLoading] = (0, import_react21.useState)(true);
|
|
10087
9991
|
const [failed, setFailed] = (0, import_react21.useState)(false);
|
|
10088
|
-
const [
|
|
10089
|
-
const [
|
|
10090
|
-
const [transfersTotal, setTransfersTotal] = (0, import_react21.useState)(0);
|
|
10091
|
-
const [transfersPage, setTransfersPage] = (0, import_react21.useState)(0);
|
|
10092
|
-
const [transfersFailed, setTransfersFailed] = (0, import_react21.useState)(false);
|
|
10093
|
-
const [loadingMore, setLoadingMore] = (0, import_react21.useState)(false);
|
|
10094
|
-
const [creating, setCreating] = (0, import_react21.useState)(false);
|
|
9992
|
+
const [candidates, setCandidates] = (0, import_react21.useState)([]);
|
|
9993
|
+
const [adding, setAdding] = (0, import_react21.useState)(false);
|
|
10095
9994
|
const [editing, setEditing] = (0, import_react21.useState)(null);
|
|
10096
|
-
const [
|
|
10097
|
-
const [planNotRestored, setPlanNotRestored] = (0, import_react21.useState)(() => /* @__PURE__ */ new Set());
|
|
9995
|
+
const [removing, setRemoving] = (0, import_react21.useState)(null);
|
|
10098
9996
|
const latestLoad = (0, import_react21.useRef)(0);
|
|
10099
9997
|
const load = (0, import_react21.useCallback)(
|
|
10100
9998
|
async ({ refresh = false } = {}) => {
|
|
10101
9999
|
const loadId = ++latestLoad.current;
|
|
10102
|
-
if (!api.
|
|
10000
|
+
if (!api.fetchCreditPool) {
|
|
10103
10001
|
setLoading(false);
|
|
10104
10002
|
setFailed(true);
|
|
10105
10003
|
return;
|
|
10106
10004
|
}
|
|
10107
|
-
const
|
|
10108
|
-
api.fetchCreditAllocations().catch(() => null),
|
|
10109
|
-
api.fetchCreditTransfers ? api.fetchCreditTransfers({ page: 1, limit: TRANSFERS_PAGE }).catch(() => null) : Promise.resolve(null)
|
|
10110
|
-
]);
|
|
10005
|
+
const next = await api.fetchCreditPool().catch(() => null);
|
|
10111
10006
|
if (loadId !== latestLoad.current) return;
|
|
10112
10007
|
if (refresh && !next) {
|
|
10113
|
-
toast.error("Couldn't refresh
|
|
10008
|
+
toast.error("Couldn't refresh shared credits. Reopen this page to see the latest.");
|
|
10114
10009
|
return;
|
|
10115
10010
|
}
|
|
10116
10011
|
setFailed(!next);
|
|
10117
10012
|
setData(next);
|
|
10118
|
-
setTransfersFailed(Boolean(api.fetchCreditTransfers) && !page);
|
|
10119
|
-
setTransfers(page?.transfers ?? []);
|
|
10120
|
-
setTransfersTotal(page?.total ?? 0);
|
|
10121
|
-
setTransfersPage(page ? 1 : 0);
|
|
10122
10013
|
setLoading(false);
|
|
10123
10014
|
},
|
|
10124
10015
|
[api, toast]
|
|
@@ -10127,11 +10018,9 @@ function CreditAllocationsView() {
|
|
|
10127
10018
|
setLoading(true);
|
|
10128
10019
|
setFailed(false);
|
|
10129
10020
|
setData(null);
|
|
10130
|
-
|
|
10131
|
-
setCreating(false);
|
|
10021
|
+
setAdding(false);
|
|
10132
10022
|
setEditing(null);
|
|
10133
|
-
|
|
10134
|
-
setPlanNotRestored(/* @__PURE__ */ new Set());
|
|
10023
|
+
setRemoving(null);
|
|
10135
10024
|
void load();
|
|
10136
10025
|
}, [workspaceId]);
|
|
10137
10026
|
(0, import_react21.useEffect)(
|
|
@@ -10141,36 +10030,21 @@ function CreditAllocationsView() {
|
|
|
10141
10030
|
[]
|
|
10142
10031
|
);
|
|
10143
10032
|
const canManage = Boolean(data?.canManage);
|
|
10144
|
-
const
|
|
10145
|
-
const
|
|
10146
|
-
|
|
10147
|
-
|
|
10148
|
-
|
|
10033
|
+
const sponsor = data?.sponsor ?? null;
|
|
10034
|
+
const canAdd = canManage && !sponsor && Boolean(api.addCreditPoolMember);
|
|
10035
|
+
const openAdd = async () => {
|
|
10036
|
+
if (!api.fetchCreditPoolCandidates) {
|
|
10037
|
+
setCandidates([]);
|
|
10038
|
+
setAdding(true);
|
|
10149
10039
|
return;
|
|
10150
10040
|
}
|
|
10151
10041
|
try {
|
|
10152
|
-
|
|
10153
|
-
|
|
10042
|
+
setCandidates(await api.fetchCreditPoolCandidates());
|
|
10043
|
+
setAdding(true);
|
|
10154
10044
|
} catch {
|
|
10155
10045
|
toast.error("Couldn't load this organization's workspaces. Try again.");
|
|
10156
10046
|
}
|
|
10157
10047
|
};
|
|
10158
|
-
const loadMoreTransfers = async () => {
|
|
10159
|
-
if (!api.fetchCreditTransfers || loadingMore) return;
|
|
10160
|
-
const loadId = latestLoad.current;
|
|
10161
|
-
setLoadingMore(true);
|
|
10162
|
-
try {
|
|
10163
|
-
const page = await api.fetchCreditTransfers({ page: transfersPage + 1, limit: TRANSFERS_PAGE });
|
|
10164
|
-
if (loadId !== latestLoad.current) return;
|
|
10165
|
-
setTransfers((prev) => [...prev, ...page.transfers]);
|
|
10166
|
-
setTransfersTotal(page.total);
|
|
10167
|
-
setTransfersPage(transfersPage + 1);
|
|
10168
|
-
} catch {
|
|
10169
|
-
toast.error("Couldn't load more transfers. Try again.");
|
|
10170
|
-
} finally {
|
|
10171
|
-
setLoadingMore(false);
|
|
10172
|
-
}
|
|
10173
|
-
};
|
|
10174
10048
|
if (loading) {
|
|
10175
10049
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10176
10050
|
"div",
|
|
@@ -10193,9 +10067,7 @@ function CreditAllocationsView() {
|
|
|
10193
10067
|
}
|
|
10194
10068
|
);
|
|
10195
10069
|
}
|
|
10196
|
-
const
|
|
10197
|
-
const sponsor = data?.receiving.find((a) => a.status === "active") ?? null;
|
|
10198
|
-
const balance = typeof workspace.current?.availableCredits === "number" ? workspace.current.availableCredits : null;
|
|
10070
|
+
const members = data?.members ?? [];
|
|
10199
10071
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col flex-1 min-h-0 w-full overflow-y-auto", style: { gap: 16 }, children: [
|
|
10200
10072
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-start justify-between shrink-0 w-full", style: { gap: 12 }, children: [
|
|
10201
10073
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col min-w-0", style: { gap: 4 }, children: [
|
|
@@ -10203,12 +10075,12 @@ function CreditAllocationsView() {
|
|
|
10203
10075
|
"span",
|
|
10204
10076
|
{
|
|
10205
10077
|
style: { fontFamily: T17.font, fontSize: T17.fsXl, fontWeight: 500, lineHeight: T17.lhXl, color: T17.primary },
|
|
10206
|
-
children: "
|
|
10078
|
+
children: "Shared credits"
|
|
10207
10079
|
}
|
|
10208
10080
|
),
|
|
10209
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: T17.muted }, children: canManage ? "
|
|
10081
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, color: T17.muted }, children: canManage ? "Let other workspaces in your organization spend this workspace's credits, up to a share each billing cycle. The credits stay here." : "Workspaces in this organization that spend this workspace's credits. Only organization admins can change them." })
|
|
10210
10082
|
] }),
|
|
10211
|
-
|
|
10083
|
+
canAdd && !failed && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui15.ScButton, { text: "Share credits", variant: "primary", size: "md", onClick: () => void openAdd() })
|
|
10212
10084
|
] }),
|
|
10213
10085
|
sponsor && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
10214
10086
|
"div",
|
|
@@ -10222,103 +10094,74 @@ function CreditAllocationsView() {
|
|
|
10222
10094
|
borderRadius: T17.r3xl
|
|
10223
10095
|
},
|
|
10224
10096
|
children: [
|
|
10225
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
|
|
10097
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, fontWeight: 500 }, children: sharedPoolBannerText({
|
|
10098
|
+
sponsorName: poolWorkspaceName(sponsor.sponsorWorkspaceName),
|
|
10099
|
+
allowance: sponsor.allowance,
|
|
10100
|
+
remaining: sponsor.remaining
|
|
10101
|
+
}) }),
|
|
10229
10102
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { style: { ...cellText2, color: T17.muted }, children: [
|
|
10230
|
-
"
|
|
10231
|
-
|
|
10103
|
+
"This workspace spends ",
|
|
10104
|
+
poolWorkspaceName(sponsor.sponsorWorkspaceName),
|
|
10105
|
+
"'s credits, not its own",
|
|
10106
|
+
sponsor.cycle?.end ? `, until its allowance starts again on ${formatDate2(sponsor.cycle.end)}` : "",
|
|
10232
10107
|
"."
|
|
10233
10108
|
] })
|
|
10234
10109
|
]
|
|
10235
10110
|
}
|
|
10236
10111
|
),
|
|
10237
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col shrink-0 w-full", style: { gap: 8 }, children: [
|
|
10238
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, fontWeight: 500 }, children: "
|
|
10112
|
+
!sponsor && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col shrink-0 w-full", style: { gap: 8 }, children: [
|
|
10113
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { style: { ...cellText2, fontWeight: 500 }, children: "Shared with" }),
|
|
10239
10114
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10240
10115
|
MemberListFrame,
|
|
10241
10116
|
{
|
|
10242
10117
|
grow: "cap",
|
|
10243
10118
|
maxHeight: 420,
|
|
10244
|
-
contentMinWidth:
|
|
10245
|
-
header: tableHeader(
|
|
10246
|
-
isEmpty: failed ||
|
|
10247
|
-
emptyText: failed ? "Couldn't load
|
|
10248
|
-
children:
|
|
10249
|
-
|
|
10119
|
+
contentMinWidth: 860,
|
|
10120
|
+
header: tableHeader(MEMBER_COLUMNS2, ["Workspace", "Allowance", "Used", "Remaining", "Actions"]),
|
|
10121
|
+
isEmpty: failed || members.length === 0,
|
|
10122
|
+
emptyText: failed ? "Couldn't load shared credits. Try again later." : "This workspace doesn't share its credits with any other workspace.",
|
|
10123
|
+
children: members.map((member) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10124
|
+
MemberRow2,
|
|
10250
10125
|
{
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
onCancel: canManage && api.cancelCreditAllocation ? () => setCanceling(allocation) : void 0
|
|
10126
|
+
member,
|
|
10127
|
+
onEdit: canManage && api.updateCreditPoolMember ? () => setEditing(member) : void 0,
|
|
10128
|
+
onRemove: canManage && api.removeCreditPoolMember ? () => setRemoving(member) : void 0
|
|
10255
10129
|
},
|
|
10256
|
-
|
|
10130
|
+
member._id
|
|
10257
10131
|
))
|
|
10258
10132
|
}
|
|
10259
10133
|
)
|
|
10260
10134
|
] }),
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10264
|
-
MemberListFrame,
|
|
10265
|
-
{
|
|
10266
|
-
grow: "cap",
|
|
10267
|
-
maxHeight: 420,
|
|
10268
|
-
contentMinWidth: 680,
|
|
10269
|
-
header: tableHeader(TRANSFER_COLUMNS, ["Date", "Type", "Workspace", "Credits"]),
|
|
10270
|
-
isEmpty: transfersFailed || transfers.length === 0,
|
|
10271
|
-
emptyText: transfersFailed ? "Couldn't load transfers. Try again later." : "No transfers yet",
|
|
10272
|
-
children: transfers.map((transfer) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(TransferRow, { transfer }, transfer.id))
|
|
10273
|
-
}
|
|
10274
|
-
),
|
|
10275
|
-
transfers.length < transfersTotal && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10276
|
-
import_ui15.ScButton,
|
|
10277
|
-
{
|
|
10278
|
-
text: loadingMore ? "Loading\u2026" : "Load more",
|
|
10279
|
-
variant: "secondary",
|
|
10280
|
-
size: "sm",
|
|
10281
|
-
state: loadingMore ? "disabled" : "default",
|
|
10282
|
-
onClick: loadingMore ? void 0 : () => void loadMoreTransfers()
|
|
10283
|
-
}
|
|
10284
|
-
) })
|
|
10285
|
-
] }),
|
|
10286
|
-
creating && api.createCreditAllocation && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10287
|
-
CreditAllocationModal,
|
|
10135
|
+
adding && api.addCreditPoolMember && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10136
|
+
CreditPoolMemberModal,
|
|
10288
10137
|
{
|
|
10289
|
-
kind: "
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
onClose: () => setCreating(false),
|
|
10138
|
+
kind: "add",
|
|
10139
|
+
candidates,
|
|
10140
|
+
onSave: (input) => api.addCreditPoolMember(input),
|
|
10141
|
+
onClose: () => setAdding(false),
|
|
10294
10142
|
onSaved: () => void load({ refresh: true })
|
|
10295
10143
|
}
|
|
10296
10144
|
),
|
|
10297
|
-
editing && api.
|
|
10298
|
-
|
|
10145
|
+
editing && api.updateCreditPoolMember && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10146
|
+
CreditPoolMemberModal,
|
|
10299
10147
|
{
|
|
10300
10148
|
kind: "edit",
|
|
10301
|
-
|
|
10302
|
-
|
|
10303
|
-
onSave: (patch) => api.
|
|
10149
|
+
member: editing,
|
|
10150
|
+
memberName: poolWorkspaceName(editing.memberWorkspaceName),
|
|
10151
|
+
onSave: (patch) => api.updateCreditPoolMember(editing._id, patch),
|
|
10304
10152
|
onClose: () => setEditing(null),
|
|
10305
10153
|
onSaved: () => void load({ refresh: true })
|
|
10306
10154
|
}
|
|
10307
10155
|
),
|
|
10308
|
-
|
|
10309
|
-
|
|
10156
|
+
removing && api.removeCreditPoolMember && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
10157
|
+
RemovePoolMemberModal,
|
|
10310
10158
|
{
|
|
10311
|
-
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10315
|
-
|
|
10316
|
-
|
|
10317
|
-
const id = canceling._id;
|
|
10318
|
-
setPlanNotRestored((prev) => new Set(prev).add(id));
|
|
10319
|
-
}
|
|
10320
|
-
void load({ refresh: true });
|
|
10321
|
-
}
|
|
10159
|
+
member: removing,
|
|
10160
|
+
memberName: poolWorkspaceName(removing.memberWorkspaceName),
|
|
10161
|
+
sponsorName: workspaceName,
|
|
10162
|
+
onRemove: (reason) => api.removeCreditPoolMember(removing._id, reason),
|
|
10163
|
+
onClose: () => setRemoving(null),
|
|
10164
|
+
onRemoved: () => void load({ refresh: true })
|
|
10322
10165
|
}
|
|
10323
10166
|
)
|
|
10324
10167
|
] });
|
|
@@ -11208,8 +11051,11 @@ function InvoiceHistoryTable({
|
|
|
11208
11051
|
function UsageLogsTable({
|
|
11209
11052
|
logs,
|
|
11210
11053
|
userMap,
|
|
11211
|
-
loading
|
|
11054
|
+
loading,
|
|
11055
|
+
currentWorkspaceId = null,
|
|
11056
|
+
usedByNames = {}
|
|
11212
11057
|
}) {
|
|
11058
|
+
const showWorkspace = logs.some((log) => usedByWorkspaceKey(log, currentWorkspaceId));
|
|
11213
11059
|
if (loading) {
|
|
11214
11060
|
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11215
11061
|
"div",
|
|
@@ -11286,6 +11132,14 @@ function UsageLogsTable({
|
|
|
11286
11132
|
style: { flexShrink: 0, width: "7.5rem" }
|
|
11287
11133
|
}
|
|
11288
11134
|
),
|
|
11135
|
+
showWorkspace && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11136
|
+
import_ui16.ScHeader,
|
|
11137
|
+
{
|
|
11138
|
+
text: "Workspace",
|
|
11139
|
+
state: "none",
|
|
11140
|
+
style: { flexShrink: 0, width: "9rem" }
|
|
11141
|
+
}
|
|
11142
|
+
),
|
|
11289
11143
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11290
11144
|
import_ui16.ScHeader,
|
|
11291
11145
|
{
|
|
@@ -11332,6 +11186,8 @@ function UsageLogsTable({
|
|
|
11332
11186
|
logs.map((log) => {
|
|
11333
11187
|
const userName = log.triggeredByUserId ? userMap[log.triggeredByUserId] || "Unknown" : "System";
|
|
11334
11188
|
const app = log.service?.serviceGroupName || "\u2014";
|
|
11189
|
+
const usedBy = usedByWorkspaceKey(log, currentWorkspaceId);
|
|
11190
|
+
const workspaceLabel2 = usedBy ? `Used by ${usedByNames[usedBy.toLowerCase()] ?? "another workspace"}` : "This workspace";
|
|
11335
11191
|
const activity = log.type === "return" ? "Returned Credits" : log.meta?.info || "Credit usage";
|
|
11336
11192
|
const isPositive = log.type === "return" || log.type === "add";
|
|
11337
11193
|
const signedAmount = `${isPositive ? "+" : "-"}${log.amount}`;
|
|
@@ -11361,6 +11217,18 @@ function UsageLogsTable({
|
|
|
11361
11217
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { ...rowCellRegular, flex: 1 }, children: app }),
|
|
11362
11218
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { ...rowCellRegular, flex: 1 }, children: activity }),
|
|
11363
11219
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { ...rowCellRegular, width: "7.5rem" }, children: userName }),
|
|
11220
|
+
showWorkspace && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11221
|
+
"div",
|
|
11222
|
+
{
|
|
11223
|
+
style: {
|
|
11224
|
+
...rowCellRegular,
|
|
11225
|
+
width: "9rem",
|
|
11226
|
+
color: usedBy ? "var(--alias-text---icons-primary, #f5f5f5)" : "var(--alias-text---icons-muted)"
|
|
11227
|
+
},
|
|
11228
|
+
title: workspaceLabel2,
|
|
11229
|
+
children: workspaceLabel2
|
|
11230
|
+
}
|
|
11231
|
+
),
|
|
11364
11232
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { style: { ...rowCellRegular, width: "7.5rem" }, children: formatDate3(log.createdAt) }),
|
|
11365
11233
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11366
11234
|
"div",
|
|
@@ -11429,8 +11297,8 @@ function BillingContent({
|
|
|
11429
11297
|
onShowPlansChange,
|
|
11430
11298
|
showPerUserLimits: showPerUserLimitsProp,
|
|
11431
11299
|
onShowPerUserLimitsChange,
|
|
11432
|
-
|
|
11433
|
-
|
|
11300
|
+
showSharedCredits: showSharedCreditsProp,
|
|
11301
|
+
onShowSharedCreditsChange
|
|
11434
11302
|
} = {}) {
|
|
11435
11303
|
const { auth, workspace, organization, api, toast, navigation } = useSettingsAdapters();
|
|
11436
11304
|
const user = auth.user;
|
|
@@ -11455,21 +11323,23 @@ function BillingContent({
|
|
|
11455
11323
|
if (onShowPerUserLimitsChange) onShowPerUserLimitsChange(next);
|
|
11456
11324
|
else setShowPerUserLimitsInternal(next);
|
|
11457
11325
|
};
|
|
11458
|
-
const
|
|
11326
|
+
const canShareCredits = canShowSharedCredits(
|
|
11459
11327
|
api,
|
|
11460
11328
|
workspace.current,
|
|
11461
11329
|
organization?.current
|
|
11462
11330
|
);
|
|
11463
|
-
const [
|
|
11464
|
-
const
|
|
11465
|
-
const
|
|
11466
|
-
if (
|
|
11467
|
-
else
|
|
11331
|
+
const [showSharedCreditsInternal, setShowSharedCreditsInternal] = (0, import_react22.useState)(false);
|
|
11332
|
+
const showSharedCredits = (showSharedCreditsProp ?? showSharedCreditsInternal) && canShareCredits;
|
|
11333
|
+
const setShowSharedCredits = (next) => {
|
|
11334
|
+
if (onShowSharedCreditsChange) onShowSharedCreditsChange(next);
|
|
11335
|
+
else setShowSharedCreditsInternal(next);
|
|
11468
11336
|
};
|
|
11469
11337
|
const [showExportModal, setShowExportModal] = (0, import_react22.useState)(false);
|
|
11470
11338
|
const [showBuyCreditsModal, setShowBuyCreditsModal] = (0, import_react22.useState)(false);
|
|
11471
11339
|
const [subscription, setSubscription] = (0, import_react22.useState)(null);
|
|
11472
11340
|
const [availableCredits, setAvailableCredits] = (0, import_react22.useState)(null);
|
|
11341
|
+
const [sharedPool, setSharedPool] = (0, import_react22.useState)(null);
|
|
11342
|
+
const [usedByNames, setUsedByNames] = (0, import_react22.useState)({});
|
|
11473
11343
|
const [products, setProducts] = (0, import_react22.useState)([]);
|
|
11474
11344
|
const [invoices, setInvoices] = (0, import_react22.useState)([]);
|
|
11475
11345
|
const [totalCredits, setTotalCredits] = (0, import_react22.useState)(null);
|
|
@@ -11520,6 +11390,7 @@ function BillingContent({
|
|
|
11520
11390
|
if (subRes?.data) setSubscription(subRes.data);
|
|
11521
11391
|
if (creditsRes?.availableCredits != null)
|
|
11522
11392
|
setAvailableCredits(creditsRes.availableCredits);
|
|
11393
|
+
setSharedPool(creditsRes?.sharedPool ?? null);
|
|
11523
11394
|
if (productsRes?.data) {
|
|
11524
11395
|
const normalizedWorkspaceCountry = workspace.current?.country?.trim().toUpperCase();
|
|
11525
11396
|
const targetCurrency = normalizedWorkspaceCountry === "IN" ? "inr" : "usd";
|
|
@@ -11568,7 +11439,12 @@ function BillingContent({
|
|
|
11568
11439
|
);
|
|
11569
11440
|
} else if (api.fetchUsageLogs) {
|
|
11570
11441
|
const res = await api.fetchUsageLogs();
|
|
11571
|
-
|
|
11442
|
+
const logs = res.data?.length ? res.data : [];
|
|
11443
|
+
setUsageLogs(logs);
|
|
11444
|
+
if (api.fetchCreditPool && logs.some((log) => usedByWorkspaceKey(log, workspaceId))) {
|
|
11445
|
+
const pool = await api.fetchCreditPool().catch(() => null);
|
|
11446
|
+
setUsedByNames(usedByNamesFrom(pool));
|
|
11447
|
+
}
|
|
11572
11448
|
} else {
|
|
11573
11449
|
setUsageLogs([]);
|
|
11574
11450
|
}
|
|
@@ -11579,7 +11455,7 @@ function BillingContent({
|
|
|
11579
11455
|
setLoadingTable(false);
|
|
11580
11456
|
}
|
|
11581
11457
|
},
|
|
11582
|
-
[api]
|
|
11458
|
+
[api, workspaceId]
|
|
11583
11459
|
);
|
|
11584
11460
|
const handlePlanAction = (0, import_react22.useCallback)(
|
|
11585
11461
|
async ({ productId, priceId, planName: planName2 }) => {
|
|
@@ -11737,10 +11613,13 @@ function BillingContent({
|
|
|
11737
11613
|
);
|
|
11738
11614
|
const scheduledDowngradeText = subscription?.downgradeScheduled && subscription.plan?.name ? `Downgrades to ${subscription.plan.name}${scheduledDowngradeDateLabel ? ` ${scheduledDowngradeDateLabel}` : ""}` : void 0;
|
|
11739
11615
|
const isPlanDetailsLoading = !billingOverviewLoaded || loadingBilling || subscription?.plan == null || !planName || planName === "-" || !planAmount || currentPlanCredits == null;
|
|
11740
|
-
const
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11616
|
+
const {
|
|
11617
|
+
used: usedCredits,
|
|
11618
|
+
remaining: remainingCredits,
|
|
11619
|
+
progressPct,
|
|
11620
|
+
remainingPct
|
|
11621
|
+
} = creditsMeter({ availableCredits, totalCredits, sharedPool });
|
|
11622
|
+
const usageText = usedCredits != null ? formatCredits2(usedCredits) : remainingCredits != null ? `${formatCredits2(remainingCredits)} available` : customPlanCredits != null ? `${formatCredits2(customPlanCredits)} credits` : "\u2014";
|
|
11744
11623
|
const handleExport = async (startDate, endDate) => {
|
|
11745
11624
|
const end = new Date(endDate);
|
|
11746
11625
|
end.setHours(23, 59, 59, 999);
|
|
@@ -11817,7 +11696,7 @@ function BillingContent({
|
|
|
11817
11696
|
function fmtFilename(d) {
|
|
11818
11697
|
return d.toISOString().slice(0, 10);
|
|
11819
11698
|
}
|
|
11820
|
-
async function handleBuyCredits(
|
|
11699
|
+
async function handleBuyCredits(credits2, price) {
|
|
11821
11700
|
if (!workspaceId) {
|
|
11822
11701
|
toast.error("Missing workspace details for credit top-up");
|
|
11823
11702
|
return;
|
|
@@ -11829,14 +11708,14 @@ function BillingContent({
|
|
|
11829
11708
|
"Buy credits confirmed",
|
|
11830
11709
|
{
|
|
11831
11710
|
action: "confirm_buy_credits",
|
|
11832
|
-
additionalInfo: `${
|
|
11711
|
+
additionalInfo: `${credits2}:${price}`
|
|
11833
11712
|
}
|
|
11834
11713
|
);
|
|
11835
11714
|
try {
|
|
11836
11715
|
const topupCurrency = workspace.current?.country?.trim().toUpperCase() === "IN" ? "inr" : "usd";
|
|
11837
11716
|
const res = await api.buyCredits({
|
|
11838
11717
|
serviceName: DEFAULT_TOPUP_SERVICE,
|
|
11839
|
-
credits,
|
|
11718
|
+
credits: credits2,
|
|
11840
11719
|
unitAmount: price,
|
|
11841
11720
|
itemCount: 1,
|
|
11842
11721
|
currency: topupCurrency,
|
|
@@ -11854,7 +11733,7 @@ function BillingContent({
|
|
|
11854
11733
|
setAvailableCredits(payloadData.availableCredits);
|
|
11855
11734
|
} else {
|
|
11856
11735
|
setAvailableCredits(
|
|
11857
|
-
(prev) => typeof prev === "number" ? prev +
|
|
11736
|
+
(prev) => typeof prev === "number" ? prev + credits2 : prev
|
|
11858
11737
|
);
|
|
11859
11738
|
}
|
|
11860
11739
|
toast.success("Top-up created");
|
|
@@ -11924,13 +11803,13 @@ function BillingContent({
|
|
|
11924
11803
|
}
|
|
11925
11804
|
) });
|
|
11926
11805
|
}
|
|
11927
|
-
if (
|
|
11928
|
-
const
|
|
11929
|
-
!
|
|
11930
|
-
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11806
|
+
if (showSharedCredits) {
|
|
11807
|
+
const sharedCreditsView = /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col flex-1 h-full min-h-0 min-w-0 w-full", style: { gap: 16 }, children: [
|
|
11808
|
+
!onShowSharedCreditsChange && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(BackToBilling, { onClick: () => setShowSharedCredits(false) }),
|
|
11809
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SharedCreditsView, {})
|
|
11931
11810
|
] });
|
|
11932
|
-
if (embedded) return
|
|
11933
|
-
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex-1 h-full min-h-0 min-w-0 relative", children:
|
|
11811
|
+
if (embedded) return sharedCreditsView;
|
|
11812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { className: "flex-1 h-full min-h-0 min-w-0 relative", children: sharedCreditsView });
|
|
11934
11813
|
}
|
|
11935
11814
|
if (showPerUserLimits) {
|
|
11936
11815
|
const limitsView = /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-col flex-1 h-full min-h-0 min-w-0 w-full", style: { gap: 16 }, children: [
|
|
@@ -11997,7 +11876,7 @@ function BillingContent({
|
|
|
11997
11876
|
{
|
|
11998
11877
|
usageLabel: "Credits used",
|
|
11999
11878
|
usageText,
|
|
12000
|
-
remainingText:
|
|
11879
|
+
remainingText: remainingCredits != null ? `${formatCredits2(remainingCredits)} (${remainingPct}%) Remaining` : `${remainingPct}% Remaining`,
|
|
12001
11880
|
buyButtonText: "Buy credits",
|
|
12002
11881
|
buyButtonState: isFreePlan ? "disabled" : "default",
|
|
12003
11882
|
buyButtonHoverText: isFreePlan ? "Pro plan required" : void 0,
|
|
@@ -12017,6 +11896,50 @@ function BillingContent({
|
|
|
12017
11896
|
]
|
|
12018
11897
|
}
|
|
12019
11898
|
),
|
|
11899
|
+
sharedPool ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
11900
|
+
"div",
|
|
11901
|
+
{
|
|
11902
|
+
role: "status",
|
|
11903
|
+
className: "flex flex-col shrink-0 w-full",
|
|
11904
|
+
style: {
|
|
11905
|
+
gap: 4,
|
|
11906
|
+
padding: 16,
|
|
11907
|
+
backgroundColor: "var(--alias-surface-base)",
|
|
11908
|
+
border: "1px solid var(--alias-border-subtle)",
|
|
11909
|
+
borderRadius: "var(--radius-3xl)"
|
|
11910
|
+
},
|
|
11911
|
+
children: [
|
|
11912
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
11913
|
+
"span",
|
|
11914
|
+
{
|
|
11915
|
+
style: {
|
|
11916
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
11917
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
11918
|
+
fontWeight: 500,
|
|
11919
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
11920
|
+
color: "var(--alias-text---icons-primary)"
|
|
11921
|
+
},
|
|
11922
|
+
children: sharedPoolBannerText(sharedPool)
|
|
11923
|
+
}
|
|
11924
|
+
),
|
|
11925
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
11926
|
+
"span",
|
|
11927
|
+
{
|
|
11928
|
+
style: {
|
|
11929
|
+
fontFamily: "var(--font-family-font-family-body)",
|
|
11930
|
+
fontSize: "var(--font-size-font-size-sm)",
|
|
11931
|
+
lineHeight: "var(--line-height-line-height-sm)",
|
|
11932
|
+
color: "var(--alias-text---icons-muted)"
|
|
11933
|
+
},
|
|
11934
|
+
children: [
|
|
11935
|
+
"This workspace spends these shared credits, not its own; credits bought here can't be used while it does.",
|
|
11936
|
+
sharedPool.cycleEnd ? ` The allowance starts again on ${formatDate3(sharedPool.cycleEnd)}.` : ""
|
|
11937
|
+
]
|
|
11938
|
+
}
|
|
11939
|
+
)
|
|
11940
|
+
]
|
|
11941
|
+
}
|
|
11942
|
+
) : null,
|
|
12020
11943
|
usage ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
12021
11944
|
"div",
|
|
12022
11945
|
{
|
|
@@ -12090,7 +12013,7 @@ function BillingContent({
|
|
|
12090
12013
|
]
|
|
12091
12014
|
}
|
|
12092
12015
|
) : null,
|
|
12093
|
-
|
|
12016
|
+
canShareCredits ? /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
12094
12017
|
"div",
|
|
12095
12018
|
{
|
|
12096
12019
|
className: "flex items-center justify-between shrink-0 w-full",
|
|
@@ -12113,7 +12036,7 @@ function BillingContent({
|
|
|
12113
12036
|
lineHeight: "var(--line-height-line-height-sm)",
|
|
12114
12037
|
color: "var(--alias-text---icons-primary)"
|
|
12115
12038
|
},
|
|
12116
|
-
children: "
|
|
12039
|
+
children: "Shared credits"
|
|
12117
12040
|
}
|
|
12118
12041
|
),
|
|
12119
12042
|
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -12125,7 +12048,7 @@ function BillingContent({
|
|
|
12125
12048
|
lineHeight: "var(--line-height-line-height-sm)",
|
|
12126
12049
|
color: "var(--alias-text---icons-muted)"
|
|
12127
12050
|
},
|
|
12128
|
-
children: "
|
|
12051
|
+
children: "Let other workspaces in your organization spend this workspace's credits"
|
|
12129
12052
|
}
|
|
12130
12053
|
)
|
|
12131
12054
|
] }),
|
|
@@ -12135,7 +12058,7 @@ function BillingContent({
|
|
|
12135
12058
|
text: "Manage",
|
|
12136
12059
|
variant: "secondary",
|
|
12137
12060
|
size: "md",
|
|
12138
|
-
onClick: () =>
|
|
12061
|
+
onClick: () => setShowSharedCredits(true)
|
|
12139
12062
|
}
|
|
12140
12063
|
)
|
|
12141
12064
|
]
|
|
@@ -12185,7 +12108,9 @@ function BillingContent({
|
|
|
12185
12108
|
{
|
|
12186
12109
|
logs: usageLogs,
|
|
12187
12110
|
userMap,
|
|
12188
|
-
loading: loadingTable
|
|
12111
|
+
loading: loadingTable,
|
|
12112
|
+
currentWorkspaceId: workspaceId,
|
|
12113
|
+
usedByNames
|
|
12189
12114
|
}
|
|
12190
12115
|
),
|
|
12191
12116
|
showExportModal && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
@@ -12204,8 +12129,8 @@ function BillingContent({
|
|
|
12204
12129
|
workspace.current?.country
|
|
12205
12130
|
),
|
|
12206
12131
|
onClose: () => setShowBuyCreditsModal(false),
|
|
12207
|
-
onBuy: (
|
|
12208
|
-
handleBuyCredits(
|
|
12132
|
+
onBuy: (credits2, price) => {
|
|
12133
|
+
handleBuyCredits(credits2, price);
|
|
12209
12134
|
}
|
|
12210
12135
|
}
|
|
12211
12136
|
)
|
|
@@ -14853,20 +14778,20 @@ function SettingsContentInner({
|
|
|
14853
14778
|
const isBillingPlans = activeTab === "billing" && isWorkspaceAdmin && billingShowPlans;
|
|
14854
14779
|
const [billingShowPerUserLimits, setBillingShowPerUserLimits] = (0, import_react26.useState)(false);
|
|
14855
14780
|
const isBillingPerUserLimits = activeTab === "billing" && isWorkspaceAdmin && billingShowPerUserLimits && !billingShowPlans;
|
|
14856
|
-
const [
|
|
14857
|
-
const
|
|
14858
|
-
const isBillingSubView = isBillingPlans || isBillingPerUserLimits ||
|
|
14781
|
+
const [billingShowSharedCredits, setBillingShowSharedCredits] = (0, import_react26.useState)(false);
|
|
14782
|
+
const isBillingSharedCredits = activeTab === "billing" && isWorkspaceAdmin && billingShowSharedCredits && !billingShowPlans && !billingShowPerUserLimits;
|
|
14783
|
+
const isBillingSubView = isBillingPlans || isBillingPerUserLimits || isBillingSharedCredits;
|
|
14859
14784
|
(0, import_react26.useEffect)(() => {
|
|
14860
14785
|
if (activeTab !== "billing" || !isWorkspaceAdmin) {
|
|
14861
14786
|
setBillingShowPlans(false);
|
|
14862
14787
|
setBillingShowPerUserLimits(false);
|
|
14863
|
-
|
|
14788
|
+
setBillingShowSharedCredits(false);
|
|
14864
14789
|
}
|
|
14865
14790
|
}, [activeTab, isWorkspaceAdmin]);
|
|
14866
14791
|
(0, import_react26.useEffect)(() => {
|
|
14867
14792
|
setBillingShowPlans(false);
|
|
14868
14793
|
setBillingShowPerUserLimits(false);
|
|
14869
|
-
|
|
14794
|
+
setBillingShowSharedCredits(false);
|
|
14870
14795
|
}, [workspaceId]);
|
|
14871
14796
|
(0, import_react26.useEffect)(() => {
|
|
14872
14797
|
if (!onClose) return;
|
|
@@ -14881,15 +14806,15 @@ function SettingsContentInner({
|
|
|
14881
14806
|
setBillingShowPerUserLimits(false);
|
|
14882
14807
|
return;
|
|
14883
14808
|
}
|
|
14884
|
-
if (
|
|
14885
|
-
|
|
14809
|
+
if (billingShowSharedCredits) {
|
|
14810
|
+
setBillingShowSharedCredits(false);
|
|
14886
14811
|
return;
|
|
14887
14812
|
}
|
|
14888
14813
|
onClose();
|
|
14889
14814
|
};
|
|
14890
14815
|
document.addEventListener("keydown", handleKeyDown);
|
|
14891
14816
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
14892
|
-
}, [onClose, billingShowPlans, billingShowPerUserLimits,
|
|
14817
|
+
}, [onClose, billingShowPlans, billingShowPerUserLimits, billingShowSharedCredits]);
|
|
14893
14818
|
const [localWorkspaces, setLocalWorkspaces] = (0, import_react26.useState)(null);
|
|
14894
14819
|
const [wsModalOpen, setWsModalOpen] = (0, import_react26.useState)(false);
|
|
14895
14820
|
const [wsModalMode, setWsModalMode] = (0, import_react26.useState)("create");
|
|
@@ -15210,7 +15135,7 @@ function SettingsContentInner({
|
|
|
15210
15135
|
if (isBillingSubView) {
|
|
15211
15136
|
setBillingShowPlans(false);
|
|
15212
15137
|
setBillingShowPerUserLimits(false);
|
|
15213
|
-
|
|
15138
|
+
setBillingShowSharedCredits(false);
|
|
15214
15139
|
return;
|
|
15215
15140
|
}
|
|
15216
15141
|
if (onBack) onBack();
|
|
@@ -15313,7 +15238,7 @@ function SettingsContentInner({
|
|
|
15313
15238
|
}
|
|
15314
15239
|
)
|
|
15315
15240
|
] }),
|
|
15316
|
-
|
|
15241
|
+
isBillingSharedCredits && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
15317
15242
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_icons17.SiconRight, { className: "w-6 h-6 shrink-0", color: "var(--alias-text---icons-primary)" }),
|
|
15318
15243
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
15319
15244
|
"span",
|
|
@@ -15325,7 +15250,7 @@ function SettingsContentInner({
|
|
|
15325
15250
|
lineHeight: "var(--line-height-line-height-xl)",
|
|
15326
15251
|
color: "var(--alias-text---icons-primary)"
|
|
15327
15252
|
},
|
|
15328
|
-
children: "
|
|
15253
|
+
children: "Shared credits"
|
|
15329
15254
|
}
|
|
15330
15255
|
)
|
|
15331
15256
|
] })
|
|
@@ -15538,7 +15463,7 @@ function SettingsContentInner({
|
|
|
15538
15463
|
setBillingShowPlans(open);
|
|
15539
15464
|
if (open) {
|
|
15540
15465
|
setBillingShowPerUserLimits(false);
|
|
15541
|
-
|
|
15466
|
+
setBillingShowSharedCredits(false);
|
|
15542
15467
|
}
|
|
15543
15468
|
},
|
|
15544
15469
|
showPerUserLimits: billingShowPerUserLimits,
|
|
@@ -15546,12 +15471,12 @@ function SettingsContentInner({
|
|
|
15546
15471
|
setBillingShowPerUserLimits(open);
|
|
15547
15472
|
if (open) {
|
|
15548
15473
|
setBillingShowPlans(false);
|
|
15549
|
-
|
|
15474
|
+
setBillingShowSharedCredits(false);
|
|
15550
15475
|
}
|
|
15551
15476
|
},
|
|
15552
|
-
|
|
15553
|
-
|
|
15554
|
-
|
|
15477
|
+
showSharedCredits: billingShowSharedCredits,
|
|
15478
|
+
onShowSharedCreditsChange: (open) => {
|
|
15479
|
+
setBillingShowSharedCredits(open);
|
|
15555
15480
|
if (open) {
|
|
15556
15481
|
setBillingShowPlans(false);
|
|
15557
15482
|
setBillingShowPerUserLimits(false);
|