@elevasis/ui 1.3.0 → 1.3.1
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/CoreAuthKitInner-3J4RVQO6.js +43 -0
- package/dist/api/index.d.ts +7 -31
- package/dist/api/index.js +2 -1
- package/dist/auth/context.d.ts +23 -5
- package/dist/auth/index.d.ts +37 -34
- package/dist/auth/index.js +4 -5
- package/dist/{chunk-FDCVFCOQ.js → chunk-2JBWPFHF.js} +23 -20
- package/dist/{chunk-OLD3NQLI.js → chunk-72HOBFMP.js} +13 -17
- package/dist/{chunk-BZTA7IIL.js → chunk-A3MCANC6.js} +295 -1
- package/dist/chunk-FWZJH3TL.js +13 -0
- package/dist/{chunk-EZMRFWZQ.js → chunk-JBFFCZI4.js} +1 -1
- package/dist/chunk-JGJSZ3UE.js +47 -0
- package/dist/{chunk-4KAG5U7A.js → chunk-L2CM2CUA.js} +0 -2
- package/dist/{chunk-QQOLC46E.js → chunk-NEK6JKPW.js} +1 -1
- package/dist/{chunk-SITSZUFW.js → chunk-PVVQTENF.js} +1 -1
- package/dist/{chunk-PCBXNHKY.js → chunk-TZPAA4RC.js} +3 -2
- package/dist/{chunk-FLJXZ7YC.js → chunk-UMXDDEAG.js} +1 -3
- package/dist/{chunk-BWCC6ZJC.js → chunk-XLV6LYN2.js} +15 -60
- package/dist/hooks/index.d.ts +2629 -2
- package/dist/hooks/index.js +5 -2
- package/dist/hooks/published.d.ts +2629 -2
- package/dist/hooks/published.js +4 -1
- package/dist/index.d.ts +427 -162
- package/dist/index.js +13 -13
- package/dist/initialization/index.js +3 -3
- package/dist/organization/index.js +3 -3
- package/dist/profile/index.js +1 -1
- package/dist/provider/index.d.ts +5 -17
- package/dist/provider/index.js +6 -7
- package/dist/provider/published.d.ts +4 -16
- package/dist/provider/published.js +5 -6
- package/dist/supabase/index.js +2 -47
- package/package.json +3 -3
- package/dist/CoreAuthKitInner-KM72EYJS.js +0 -19
- package/dist/api/hooks/useApiClient.d.ts +0 -54
- package/dist/api/hooks/useApiClient.d.ts.map +0 -1
- package/dist/api/hooks/useApiClient.js +0 -185
- package/dist/chunk-NIAVTSMB.js +0 -21
- package/dist/chunk-QSVZP2NU.js +0 -214
- /package/dist/{chunk-Q47SPRY7.js → chunk-TYV5NJV2.js} +0 -0
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { useSupabase } from './chunk-JGJSZ3UE.js';
|
|
1
2
|
import { UuidSchema, ResourceTypeSchema, NonEmptyStringSchema, OriginResourceTypeSchema } from './chunk-BLO4SISK.js';
|
|
3
|
+
import { useNotificationAdapter } from './chunk-TIRMFDM4.js';
|
|
4
|
+
import { useStableAccessToken } from './chunk-FWZJH3TL.js';
|
|
2
5
|
import { useElevasisServices } from './chunk-KA7LO7U5.js';
|
|
3
6
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
4
7
|
import { z } from 'zod';
|
|
8
|
+
import { useCallback, useState, useEffect, useMemo, useId, useRef } from 'react';
|
|
5
9
|
|
|
6
10
|
// src/hooks/executions/queryKeys.ts
|
|
7
11
|
var executionsKeys = {
|
|
@@ -658,6 +662,43 @@ function useExecutionHealth({ timeRange }) {
|
|
|
658
662
|
// 30s monitoring stale time
|
|
659
663
|
});
|
|
660
664
|
}
|
|
665
|
+
function useErrorNotification() {
|
|
666
|
+
const adapter = useNotificationAdapter();
|
|
667
|
+
return useCallback(
|
|
668
|
+
(error) => {
|
|
669
|
+
adapter.apiError(error);
|
|
670
|
+
},
|
|
671
|
+
[adapter]
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
function useSuccessNotification() {
|
|
675
|
+
const adapter = useNotificationAdapter();
|
|
676
|
+
return useCallback((title, message) => adapter.success(title, message), [adapter]);
|
|
677
|
+
}
|
|
678
|
+
function useWarningNotification() {
|
|
679
|
+
const adapter = useNotificationAdapter();
|
|
680
|
+
return useCallback((title, message) => adapter.warning(title, message), [adapter]);
|
|
681
|
+
}
|
|
682
|
+
function useBatchDelete(tableName, invalidateQueryKeys) {
|
|
683
|
+
const supabase = useSupabase();
|
|
684
|
+
const queryClient = useQueryClient();
|
|
685
|
+
const adapter = useNotificationAdapter();
|
|
686
|
+
return useMutation({
|
|
687
|
+
mutationFn: async (ids) => {
|
|
688
|
+
if (ids.length === 0) return;
|
|
689
|
+
const { error } = await supabase.from(tableName).delete().in("id", ids);
|
|
690
|
+
if (error) throw error;
|
|
691
|
+
},
|
|
692
|
+
onSuccess: () => {
|
|
693
|
+
for (const key of invalidateQueryKeys) {
|
|
694
|
+
queryClient.invalidateQueries({ queryKey: key });
|
|
695
|
+
}
|
|
696
|
+
},
|
|
697
|
+
onError: (err) => {
|
|
698
|
+
adapter.apiError(err);
|
|
699
|
+
}
|
|
700
|
+
});
|
|
701
|
+
}
|
|
661
702
|
|
|
662
703
|
// src/hooks/observability/queryKeys.ts
|
|
663
704
|
var observabilityKeys = {
|
|
@@ -1063,5 +1104,258 @@ function useDeleteSchedule() {
|
|
|
1063
1104
|
}
|
|
1064
1105
|
});
|
|
1065
1106
|
}
|
|
1107
|
+
function usePaginationState(pageSize, resetDeps, total) {
|
|
1108
|
+
const [page, setPage] = useState(1);
|
|
1109
|
+
useEffect(() => {
|
|
1110
|
+
if (resetDeps) {
|
|
1111
|
+
setPage(1);
|
|
1112
|
+
}
|
|
1113
|
+
}, resetDeps ?? []);
|
|
1114
|
+
useEffect(() => {
|
|
1115
|
+
if (total === void 0) return;
|
|
1116
|
+
const lastPage = Math.max(1, Math.ceil(total / pageSize));
|
|
1117
|
+
if (page > lastPage) {
|
|
1118
|
+
setPage(lastPage);
|
|
1119
|
+
}
|
|
1120
|
+
}, [total, pageSize]);
|
|
1121
|
+
return useMemo(
|
|
1122
|
+
() => ({
|
|
1123
|
+
page,
|
|
1124
|
+
setPage,
|
|
1125
|
+
offset: (page - 1) * pageSize,
|
|
1126
|
+
totalPages: (total2) => Math.ceil(total2 / pageSize)
|
|
1127
|
+
}),
|
|
1128
|
+
[page, pageSize]
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
function useTableSelection(items, allItems) {
|
|
1132
|
+
const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
|
|
1133
|
+
const pageIds = useMemo(() => new Set(items.map((i) => i.id)), [items]);
|
|
1134
|
+
useEffect(() => {
|
|
1135
|
+
setSelectedIds((prev) => {
|
|
1136
|
+
const validIds = allItems ? new Set(allItems.map((i) => i.id)) : pageIds;
|
|
1137
|
+
const next = new Set([...prev].filter((id) => validIds.has(id)));
|
|
1138
|
+
return next.size === prev.size ? prev : next;
|
|
1139
|
+
});
|
|
1140
|
+
}, [allItems, pageIds]);
|
|
1141
|
+
const toggle = useCallback((id) => {
|
|
1142
|
+
setSelectedIds((prev) => {
|
|
1143
|
+
const next = new Set(prev);
|
|
1144
|
+
if (next.has(id)) next.delete(id);
|
|
1145
|
+
else next.add(id);
|
|
1146
|
+
return next;
|
|
1147
|
+
});
|
|
1148
|
+
}, []);
|
|
1149
|
+
const togglePage = useCallback(() => {
|
|
1150
|
+
setSelectedIds((prev) => {
|
|
1151
|
+
const allPageSelected = items.every((i) => prev.has(i.id));
|
|
1152
|
+
const next = new Set(prev);
|
|
1153
|
+
if (allPageSelected) {
|
|
1154
|
+
for (const item of items) next.delete(item.id);
|
|
1155
|
+
} else {
|
|
1156
|
+
for (const item of items) next.add(item.id);
|
|
1157
|
+
}
|
|
1158
|
+
return next;
|
|
1159
|
+
});
|
|
1160
|
+
}, [items]);
|
|
1161
|
+
const clear = useCallback(() => setSelectedIds(/* @__PURE__ */ new Set()), []);
|
|
1162
|
+
const isPageAllSelected = items.length > 0 && items.every((i) => selectedIds.has(i.id));
|
|
1163
|
+
const isPagePartiallySelected = !isPageAllSelected && items.some((i) => selectedIds.has(i.id));
|
|
1164
|
+
return {
|
|
1165
|
+
selectedIds,
|
|
1166
|
+
toggle,
|
|
1167
|
+
togglePage,
|
|
1168
|
+
clear,
|
|
1169
|
+
isPageAllSelected,
|
|
1170
|
+
isPagePartiallySelected,
|
|
1171
|
+
selectedCount: selectedIds.size,
|
|
1172
|
+
isSelected: (id) => selectedIds.has(id)
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
function useTableSort(defaultColumn, defaultDirection = "desc") {
|
|
1176
|
+
const [sort, setSort] = useState({ column: defaultColumn, direction: defaultDirection });
|
|
1177
|
+
const toggleSort = useCallback((column) => {
|
|
1178
|
+
setSort((prev) => {
|
|
1179
|
+
if (prev.column === column) {
|
|
1180
|
+
return { column, direction: prev.direction === "asc" ? "desc" : "asc" };
|
|
1181
|
+
}
|
|
1182
|
+
return { column, direction: "desc" };
|
|
1183
|
+
});
|
|
1184
|
+
}, []);
|
|
1185
|
+
return { sort, toggleSort };
|
|
1186
|
+
}
|
|
1187
|
+
function sortData(data, sort, accessors) {
|
|
1188
|
+
const accessor = accessors[sort.column];
|
|
1189
|
+
if (!accessor) return data;
|
|
1190
|
+
return [...data].sort((a, b) => {
|
|
1191
|
+
const aVal = accessor(a);
|
|
1192
|
+
const bVal = accessor(b);
|
|
1193
|
+
if (aVal == null && bVal == null) return 0;
|
|
1194
|
+
if (aVal == null) return 1;
|
|
1195
|
+
if (bVal == null) return -1;
|
|
1196
|
+
let comparison = 0;
|
|
1197
|
+
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
1198
|
+
comparison = aVal.localeCompare(bVal);
|
|
1199
|
+
} else if (typeof aVal === "number" && typeof bVal === "number") {
|
|
1200
|
+
comparison = aVal - bVal;
|
|
1201
|
+
} else {
|
|
1202
|
+
comparison = String(aVal).localeCompare(String(bVal));
|
|
1203
|
+
}
|
|
1204
|
+
return sort.direction === "asc" ? comparison : -comparison;
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
function useSortedData(data, defaultColumn, accessors, defaultDirection = "desc") {
|
|
1208
|
+
const { sort, toggleSort } = useTableSort(defaultColumn, defaultDirection);
|
|
1209
|
+
const sorted = useMemo(() => sortData(data, sort, accessors), [data, sort, accessors]);
|
|
1210
|
+
return { sorted, sort, toggleSort };
|
|
1211
|
+
}
|
|
1212
|
+
function createUseFeatureAccess({
|
|
1213
|
+
useInitialization,
|
|
1214
|
+
useOrganization,
|
|
1215
|
+
optInFeatures = [],
|
|
1216
|
+
getCoursesByGroup = () => []
|
|
1217
|
+
}) {
|
|
1218
|
+
return function useFeatureAccess() {
|
|
1219
|
+
const { profile, organizationReady } = useInitialization();
|
|
1220
|
+
const { currentMembership } = useOrganization();
|
|
1221
|
+
const { orgConfig, membershipConfig } = useMemo(() => {
|
|
1222
|
+
const organizationConfig = currentMembership?.organization?.config;
|
|
1223
|
+
const memberConfig = currentMembership?.config;
|
|
1224
|
+
return { orgConfig: organizationConfig, membershipConfig: memberConfig };
|
|
1225
|
+
}, [currentMembership]);
|
|
1226
|
+
const userConfig = profile?.config;
|
|
1227
|
+
const checkFeature = useCallback(
|
|
1228
|
+
(featureKey) => {
|
|
1229
|
+
const key = featureKey;
|
|
1230
|
+
const orgValue = orgConfig?.features?.[key];
|
|
1231
|
+
if (!profile?.is_platform_admin) {
|
|
1232
|
+
const membershipValue = membershipConfig?.features?.[key];
|
|
1233
|
+
if (membershipValue === false) return { allowed: false, restrictedBy: "membership" };
|
|
1234
|
+
if (membershipValue === true) return { allowed: true, restrictedBy: null };
|
|
1235
|
+
}
|
|
1236
|
+
if (optInFeatures.includes(featureKey)) {
|
|
1237
|
+
return orgValue === true ? { allowed: true, restrictedBy: null } : { allowed: false, restrictedBy: "org" };
|
|
1238
|
+
}
|
|
1239
|
+
return orgValue === false ? { allowed: false, restrictedBy: "org" } : { allowed: true, restrictedBy: null };
|
|
1240
|
+
},
|
|
1241
|
+
[profile?.is_platform_admin, membershipConfig, orgConfig]
|
|
1242
|
+
);
|
|
1243
|
+
const hasFeature = useCallback((featureKey) => checkFeature(featureKey).allowed, [checkFeature]);
|
|
1244
|
+
const hasTrainingAccess = useCallback(() => {
|
|
1245
|
+
if (profile?.is_platform_admin) return true;
|
|
1246
|
+
return userConfig?.training?.enabled ?? true;
|
|
1247
|
+
}, [profile?.is_platform_admin, userConfig?.training?.enabled]);
|
|
1248
|
+
const getAllowedCourses = useCallback(() => {
|
|
1249
|
+
if (userConfig?.training?.allowed_courses?.length) {
|
|
1250
|
+
return userConfig.training.allowed_courses;
|
|
1251
|
+
}
|
|
1252
|
+
return null;
|
|
1253
|
+
}, [userConfig?.training?.allowed_courses]);
|
|
1254
|
+
const getResolvedCourseAccess = useCallback(() => {
|
|
1255
|
+
if (profile?.is_platform_admin) return null;
|
|
1256
|
+
const orgGroups = orgConfig?.training?.allowed_course_groups ?? [];
|
|
1257
|
+
const userGroups = userConfig?.training?.allowed_course_groups ?? [];
|
|
1258
|
+
const userCourses = userConfig?.training?.allowed_courses ?? [];
|
|
1259
|
+
if (!orgGroups.length && !userGroups.length && !userCourses.length) return null;
|
|
1260
|
+
const foundationCourses = getCoursesByGroup("foundation");
|
|
1261
|
+
const orgCourseSlugs = orgGroups.flatMap(getCoursesByGroup);
|
|
1262
|
+
const userGroupCourseSlugs = userGroups.flatMap(getCoursesByGroup);
|
|
1263
|
+
return [.../* @__PURE__ */ new Set([...foundationCourses, ...orgCourseSlugs, ...userGroupCourseSlugs, ...userCourses])];
|
|
1264
|
+
}, [
|
|
1265
|
+
profile?.is_platform_admin,
|
|
1266
|
+
orgConfig?.training?.allowed_course_groups,
|
|
1267
|
+
userConfig?.training?.allowed_course_groups,
|
|
1268
|
+
userConfig?.training?.allowed_courses
|
|
1269
|
+
]);
|
|
1270
|
+
const hasAccessToCourse = useCallback(
|
|
1271
|
+
(courseSlug) => {
|
|
1272
|
+
const resolved = getResolvedCourseAccess();
|
|
1273
|
+
if (resolved === null) return true;
|
|
1274
|
+
return resolved.includes(courseSlug);
|
|
1275
|
+
},
|
|
1276
|
+
[getResolvedCourseAccess]
|
|
1277
|
+
);
|
|
1278
|
+
const getEnabledGroups = useCallback(() => {
|
|
1279
|
+
const orgGroups = orgConfig?.training?.allowed_course_groups ?? [];
|
|
1280
|
+
const userGroups = userConfig?.training?.allowed_course_groups ?? [];
|
|
1281
|
+
return [.../* @__PURE__ */ new Set(["foundation", ...orgGroups, ...userGroups])];
|
|
1282
|
+
}, [orgConfig?.training?.allowed_course_groups, userConfig?.training?.allowed_course_groups]);
|
|
1283
|
+
return {
|
|
1284
|
+
orgConfig,
|
|
1285
|
+
membershipConfig,
|
|
1286
|
+
userConfig,
|
|
1287
|
+
hasFeature,
|
|
1288
|
+
checkFeature,
|
|
1289
|
+
hasTrainingAccess,
|
|
1290
|
+
getAllowedCourses,
|
|
1291
|
+
getResolvedCourseAccess,
|
|
1292
|
+
hasAccessToCourse,
|
|
1293
|
+
getEnabledGroups,
|
|
1294
|
+
isReady: organizationReady
|
|
1295
|
+
};
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
function useSSEConnection({
|
|
1299
|
+
manager,
|
|
1300
|
+
connectionKey,
|
|
1301
|
+
url,
|
|
1302
|
+
enabled = true,
|
|
1303
|
+
headers,
|
|
1304
|
+
onmessage,
|
|
1305
|
+
onopen,
|
|
1306
|
+
onerror,
|
|
1307
|
+
onclose
|
|
1308
|
+
}) {
|
|
1309
|
+
const [connected, setConnected] = useState(false);
|
|
1310
|
+
const [error, setError] = useState(null);
|
|
1311
|
+
const getAccessToken = useStableAccessToken();
|
|
1312
|
+
const subscriberId = useId();
|
|
1313
|
+
const onmessageRef = useRef(onmessage);
|
|
1314
|
+
const onopenRef = useRef(onopen);
|
|
1315
|
+
const onerrorRef = useRef(onerror);
|
|
1316
|
+
const oncloseRef = useRef(onclose);
|
|
1317
|
+
const headersRef = useRef(headers);
|
|
1318
|
+
onmessageRef.current = onmessage;
|
|
1319
|
+
onopenRef.current = onopen;
|
|
1320
|
+
onerrorRef.current = onerror;
|
|
1321
|
+
oncloseRef.current = onclose;
|
|
1322
|
+
headersRef.current = headers;
|
|
1323
|
+
useEffect(() => {
|
|
1324
|
+
if (!enabled) return;
|
|
1325
|
+
const unsubscribe = manager.subscribe(connectionKey, subscriberId, {
|
|
1326
|
+
url,
|
|
1327
|
+
getToken: getAccessToken,
|
|
1328
|
+
headers: headersRef.current ?? {},
|
|
1329
|
+
onopen(response) {
|
|
1330
|
+
if (response.ok) {
|
|
1331
|
+
setConnected(true);
|
|
1332
|
+
setError(null);
|
|
1333
|
+
}
|
|
1334
|
+
const customError = onopenRef.current?.(response);
|
|
1335
|
+
if (customError) setError(customError);
|
|
1336
|
+
},
|
|
1337
|
+
onmessage(event) {
|
|
1338
|
+
if (!event.data || event.data.trim() === "") return;
|
|
1339
|
+
onmessageRef.current(event.data);
|
|
1340
|
+
},
|
|
1341
|
+
onerror(err) {
|
|
1342
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
1343
|
+
setConnected(false);
|
|
1344
|
+
setError(msg);
|
|
1345
|
+
onerrorRef.current?.(err instanceof Error ? err : new Error(msg));
|
|
1346
|
+
},
|
|
1347
|
+
onclose() {
|
|
1348
|
+
setConnected(false);
|
|
1349
|
+
oncloseRef.current?.();
|
|
1350
|
+
}
|
|
1351
|
+
});
|
|
1352
|
+
return () => {
|
|
1353
|
+
unsubscribe();
|
|
1354
|
+
setConnected(false);
|
|
1355
|
+
setError(null);
|
|
1356
|
+
};
|
|
1357
|
+
}, [enabled, connectionKey, url, subscriberId, getAccessToken, manager]);
|
|
1358
|
+
return { connected, error };
|
|
1359
|
+
}
|
|
1066
1360
|
|
|
1067
|
-
export { OperationsService, executionsKeys, observabilityKeys, scheduleKeys, useActivities, useActivityTrend, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutions, useGetExecutionHistory, useGetSchedule, useListSchedules, usePauseSchedule, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useTopFailingResources, useUnresolveError, useUpdateAnchor, useUpdateSchedule };
|
|
1361
|
+
export { OperationsService, createUseFeatureAccess, executionsKeys, observabilityKeys, scheduleKeys, sortData, useActivities, useActivityTrend, useBatchDelete, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutions, useGetExecutionHistory, useGetSchedule, useListSchedules, usePaginationState, usePauseSchedule, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useSSEConnection, useSortedData, useSuccessNotification, useTableSelection, useTableSort, useTopFailingResources, useUnresolveError, useUpdateAnchor, useUpdateSchedule, useWarningNotification };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
2
|
+
import { useRef, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
function useStableAccessToken() {
|
|
5
|
+
const { getAccessToken } = useAuthContext();
|
|
6
|
+
const getAccessTokenRef = useRef(getAccessToken);
|
|
7
|
+
getAccessTokenRef.current = getAccessToken;
|
|
8
|
+
return useCallback(() => {
|
|
9
|
+
return getAccessTokenRef.current();
|
|
10
|
+
}, []);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { useStableAccessToken };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useUserProfile } from './chunk-
|
|
1
|
+
import { useUserProfile } from './chunk-L2CM2CUA.js';
|
|
2
2
|
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
3
3
|
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
4
4
|
import { Button, Loader, Menu, Text, Badge } from '@mantine/core';
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
2
|
+
import { createClient } from '@supabase/supabase-js';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
|
|
5
|
+
function getSupabaseConfig() {
|
|
6
|
+
const url = import.meta.env?.VITE_SUPABASE_URL;
|
|
7
|
+
const anonKey = import.meta.env?.VITE_SUPABASE_ANON_KEY;
|
|
8
|
+
if (!url || !anonKey) {
|
|
9
|
+
throw new Error("Missing Supabase environment variables (VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY)");
|
|
10
|
+
}
|
|
11
|
+
return { url, anonKey };
|
|
12
|
+
}
|
|
13
|
+
var _supabase = null;
|
|
14
|
+
function getSupabaseClient() {
|
|
15
|
+
if (!_supabase) {
|
|
16
|
+
const { url, anonKey } = getSupabaseConfig();
|
|
17
|
+
_supabase = createClient(url, anonKey);
|
|
18
|
+
}
|
|
19
|
+
return _supabase;
|
|
20
|
+
}
|
|
21
|
+
var useSupabase = () => {
|
|
22
|
+
const { getAccessToken } = useAuthContext();
|
|
23
|
+
const { url, anonKey } = getSupabaseConfig();
|
|
24
|
+
return useMemo(
|
|
25
|
+
() => createClient(url, anonKey, {
|
|
26
|
+
global: {
|
|
27
|
+
headers: {
|
|
28
|
+
// Additional headers if needed
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
accessToken: async () => {
|
|
32
|
+
try {
|
|
33
|
+
const token = await getAccessToken();
|
|
34
|
+
if (!token) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return token;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}),
|
|
43
|
+
[getAccessToken, url, anonKey]
|
|
44
|
+
);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { getSupabaseClient, useSupabase };
|
|
@@ -135,8 +135,6 @@ function useProfile() {
|
|
|
135
135
|
}
|
|
136
136
|
function ProfileProvider({ children }) {
|
|
137
137
|
const value = useUserProfile();
|
|
138
|
-
if (!value.loading && value.profile) console.log("[ProfileProvider] ready, profile:", value.profile.id);
|
|
139
|
-
if (!value.loading && value.error) console.log("[ProfileProvider] error:", value.error.message);
|
|
140
138
|
return createElement(ProfileContext.Provider, { value }, children);
|
|
141
139
|
}
|
|
142
140
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { useProfile } from './chunk-L2CM2CUA.js';
|
|
1
2
|
import { useOrganization } from './chunk-DD3CCMCZ.js';
|
|
2
|
-
import { useProfile } from './chunk-4KAG5U7A.js';
|
|
3
3
|
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
4
4
|
import { createContext, useContext, useMemo, useCallback, createElement } from 'react';
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ElevasisCoreProvider } from './chunk-
|
|
1
|
+
import { ElevasisCoreProvider } from './chunk-72HOBFMP.js';
|
|
2
2
|
import { getErrorInfo, formatErrorMessage, getErrorTitle } from './chunk-4VGWQ5AN.js';
|
|
3
3
|
import { useMemo, useEffect } from 'react';
|
|
4
4
|
import { Tooltip, Text, Tabs, Table, Stack, SimpleGrid, Select, Combobox, SegmentedControl, ScrollArea, Paper, Popover, Notification, Modal, Menu, Input, HoverCard, Group, Grid, Flex, Code, Divider, Card, Button, Accordion, createTheme, mergeThemeOverrides, MantineProvider } from '@mantine/core';
|
|
@@ -1401,10 +1401,11 @@ var mantineNotificationAdapter = {
|
|
|
1401
1401
|
},
|
|
1402
1402
|
apiError(error) {
|
|
1403
1403
|
const { message, code, requestId, fields, retryAfter } = getErrorInfo(error);
|
|
1404
|
+
const hasFields = fields && Object.keys(fields).length > 0;
|
|
1404
1405
|
notifications.show({
|
|
1405
1406
|
title: getErrorTitle(code),
|
|
1406
1407
|
message: formatErrorMessage(message, requestId, fields, retryAfter),
|
|
1407
|
-
autoClose: retryAfter ? retryAfter * 1e3 : 5e3,
|
|
1408
|
+
autoClose: retryAfter ? retryAfter * 1e3 : hasFields ? 8e3 : 5e3,
|
|
1408
1409
|
color: "red",
|
|
1409
1410
|
position: "top-right"
|
|
1410
1411
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import { useProfile } from './chunk-L2CM2CUA.js';
|
|
1
2
|
import { OrganizationContext } from './chunk-DD3CCMCZ.js';
|
|
2
|
-
import { useProfile } from './chunk-4KAG5U7A.js';
|
|
3
3
|
import { useElevasisServices } from './chunk-KA7LO7U5.js';
|
|
4
4
|
import { useAuthContext } from './chunk-7PLEQFHO.js';
|
|
5
5
|
import { useState, useRef, useEffect, useCallback, createElement } from 'react';
|
|
@@ -54,7 +54,6 @@ function OrganizationProvider({ children }) {
|
|
|
54
54
|
if (!selected && data.length > 0) {
|
|
55
55
|
selected = data[0];
|
|
56
56
|
}
|
|
57
|
-
console.log("[OrgProvider] selected:", selected?.organization?.workos_org_id ?? "none");
|
|
58
57
|
if (selected) {
|
|
59
58
|
applyMembership(selected);
|
|
60
59
|
}
|
|
@@ -108,7 +107,6 @@ function OrganizationProvider({ children }) {
|
|
|
108
107
|
applyMembership
|
|
109
108
|
]);
|
|
110
109
|
useEffect(() => {
|
|
111
|
-
console.log("[OrgProvider] gate:", { userId: !!user?.id, profileLoaded, initialized: hasInitializedRef.current });
|
|
112
110
|
if (!user?.id || !profileLoaded || hasInitializedRef.current) return;
|
|
113
111
|
fetchAndInitialize();
|
|
114
112
|
}, [user?.id, profileLoaded, fetchAndInitialize]);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { APIClientError } from './chunk-4VGWQ5AN.js';
|
|
2
|
+
import { OrganizationContext } from './chunk-DD3CCMCZ.js';
|
|
2
3
|
import { createContext, useContext, useMemo, useCallback } from 'react';
|
|
3
4
|
import { jsx } from 'react/jsx-runtime';
|
|
4
5
|
|
|
@@ -54,7 +55,6 @@ function buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleRespon
|
|
|
54
55
|
try {
|
|
55
56
|
const token = await getAccessToken();
|
|
56
57
|
const organizationId = getOrganizationId();
|
|
57
|
-
if (organizationId) console.log("[apiRequest]", endpoint, "org:", organizationId);
|
|
58
58
|
const headers = {
|
|
59
59
|
...options.body ? { "Content-Type": "application/json" } : {},
|
|
60
60
|
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
@@ -74,7 +74,8 @@ function buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleRespon
|
|
|
74
74
|
if (response.status === 204) {
|
|
75
75
|
return void 0;
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
const data = await response.json();
|
|
78
|
+
return data;
|
|
78
79
|
} catch (error) {
|
|
79
80
|
if (error instanceof Error && error.message.includes("No access token")) {
|
|
80
81
|
const headers = {
|
|
@@ -101,7 +102,10 @@ function buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleRespon
|
|
|
101
102
|
};
|
|
102
103
|
}
|
|
103
104
|
function useApiClient(apiUrl) {
|
|
104
|
-
const { getAccessToken, getOrganizationId, isOrganizationReady, onError } = useApiClientContext();
|
|
105
|
+
const { getAccessToken, getOrganizationId, isOrganizationReady: contextOrgReady, onError } = useApiClientContext();
|
|
106
|
+
const orgCtx = useContext(OrganizationContext);
|
|
107
|
+
const orgReady = orgCtx ? !!orgCtx.currentWorkOSOrganizationId && !orgCtx.isInitializing && !orgCtx.isOrgRefreshing : contextOrgReady;
|
|
108
|
+
const orgInitializing = orgCtx ? orgCtx.isInitializing || orgCtx.isOrgRefreshing : false;
|
|
105
109
|
const handleResponseError = useCallback(
|
|
106
110
|
async (endpoint, response, options) => {
|
|
107
111
|
const errorData = await response.json().catch(() => ({
|
|
@@ -132,71 +136,22 @@ function useApiClient(apiUrl) {
|
|
|
132
136
|
);
|
|
133
137
|
const deferredApiRequest = useCallback(
|
|
134
138
|
async (endpoint, options = {}) => {
|
|
135
|
-
if (
|
|
139
|
+
if (orgInitializing) {
|
|
140
|
+
throw new Error("Organization context is still initializing. Please wait.");
|
|
141
|
+
}
|
|
142
|
+
if (!orgReady) {
|
|
136
143
|
throw new Error("No organization selected. Please select an organization.");
|
|
137
144
|
}
|
|
138
145
|
return apiRequest(endpoint, options);
|
|
139
146
|
},
|
|
140
|
-
[apiRequest,
|
|
147
|
+
[apiRequest, orgInitializing, orgReady]
|
|
141
148
|
);
|
|
142
149
|
return {
|
|
143
150
|
apiRequest,
|
|
144
151
|
deferredApiRequest,
|
|
145
|
-
isOrganizationReady,
|
|
146
|
-
isInitializing:
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function createUseApiClient(useOrganizations, apiUrl) {
|
|
150
|
-
return function useApiClientCompat() {
|
|
151
|
-
const { getAccessToken, getOrganizationId, isOrganizationReady, onError } = useApiClientContext();
|
|
152
|
-
const { isInitializing, isOrgRefreshing } = useOrganizations();
|
|
153
|
-
const handleResponseError = useCallback(
|
|
154
|
-
async (endpoint, response, options) => {
|
|
155
|
-
const errorData = await response.json().catch(() => ({
|
|
156
|
-
error: `HTTP ${response.status}`,
|
|
157
|
-
code: "INTERNAL_SERVER_ERROR"
|
|
158
|
-
}));
|
|
159
|
-
if (response.status >= 500 && onError) {
|
|
160
|
-
onError(endpoint, new Error(errorData.error), {
|
|
161
|
-
method: options.method || "GET",
|
|
162
|
-
statusCode: response.status,
|
|
163
|
-
requestId: errorData.requestId
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
throw new APIClientError(
|
|
167
|
-
errorData.error,
|
|
168
|
-
errorData.code,
|
|
169
|
-
response.status,
|
|
170
|
-
errorData.requestId,
|
|
171
|
-
errorData.fields,
|
|
172
|
-
errorData.retryAfter
|
|
173
|
-
);
|
|
174
|
-
},
|
|
175
|
-
[onError]
|
|
176
|
-
);
|
|
177
|
-
const apiRequest = useCallback(
|
|
178
|
-
(endpoint, options = {}) => buildApiRequest(getAccessToken, getOrganizationId, apiUrl, handleResponseError)(endpoint, options),
|
|
179
|
-
[getAccessToken, getOrganizationId, handleResponseError]
|
|
180
|
-
);
|
|
181
|
-
const deferredApiRequest = useCallback(
|
|
182
|
-
async (endpoint, options = {}) => {
|
|
183
|
-
if (isInitializing || isOrgRefreshing) {
|
|
184
|
-
throw new Error("Organization context is still initializing. Please wait.");
|
|
185
|
-
}
|
|
186
|
-
if (!isOrganizationReady) {
|
|
187
|
-
throw new Error("No organization selected. Please select an organization.");
|
|
188
|
-
}
|
|
189
|
-
return apiRequest(endpoint, options);
|
|
190
|
-
},
|
|
191
|
-
[apiRequest, isInitializing, isOrgRefreshing, isOrganizationReady]
|
|
192
|
-
);
|
|
193
|
-
return {
|
|
194
|
-
apiRequest,
|
|
195
|
-
deferredApiRequest,
|
|
196
|
-
isOrganizationReady,
|
|
197
|
-
isInitializing: isInitializing || isOrgRefreshing
|
|
198
|
-
};
|
|
152
|
+
isOrganizationReady: orgReady,
|
|
153
|
+
isInitializing: orgInitializing
|
|
199
154
|
};
|
|
200
155
|
}
|
|
201
156
|
|
|
202
|
-
export { ApiClientProvider,
|
|
157
|
+
export { ApiClientProvider, useApiClient, useApiClientContext };
|