@rebasepro/studio 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ApiExplorer-pYMZflL3.js → ApiExplorer-CCtczj3F.js} +15 -28
- package/dist/ApiExplorer-CCtczj3F.js.map +1 -0
- package/dist/ApiKeysView-B66TdzhH.js +1738 -0
- package/dist/ApiKeysView-B66TdzhH.js.map +1 -0
- package/dist/BackupsView-DmSMzAbT.js +368 -0
- package/dist/BackupsView-DmSMzAbT.js.map +1 -0
- package/dist/{BranchesView-D6Sz1a5f.js → BranchesView-DP1a87E-.js} +12 -8
- package/dist/BranchesView-DP1a87E-.js.map +1 -0
- package/dist/{CronJobsView-7hjgSYId.js → CronJobsView-TDErHTuK.js} +126 -60
- package/dist/CronJobsView-TDErHTuK.js.map +1 -0
- package/dist/{JSEditor-qiuwmcvk.js → JSEditor-B59pwg4c.js} +120 -74
- package/dist/JSEditor-B59pwg4c.js.map +1 -0
- package/dist/{LogsExplorer-Xq8K4oo6.js → LogsExplorer-BKM4yfP8.js} +48 -22
- package/dist/LogsExplorer-BKM4yfP8.js.map +1 -0
- package/dist/{RLSEditor-Djh43lBE.js → RLSEditor-BlLLV6xs.js} +237 -77
- package/dist/RLSEditor-BlLLV6xs.js.map +1 -0
- package/dist/{SQLEditor-TBw_K6CW.js → SQLEditor-1An7w0j6.js} +369 -294
- package/dist/SQLEditor-1An7w0j6.js.map +1 -0
- package/dist/{SchemaVisualizer-DtDzIUNy.js → SchemaVisualizer-DCLVfA5t.js} +20 -24
- package/dist/SchemaVisualizer-DCLVfA5t.js.map +1 -0
- package/dist/{StorageView-CMG1DOVX.js → StorageView-CbsHuCBf.js} +355 -225
- package/dist/StorageView-CbsHuCBf.js.map +1 -0
- package/dist/components/ApiExplorer/TryItPanel.d.ts +6 -1
- package/dist/components/ApiKeys/CreateApiKeyDialog.d.ts +21 -2
- package/dist/components/ApiKeys/scope-words.d.ts +37 -0
- package/dist/components/ApiKeys/scopes.d.ts +113 -0
- package/dist/components/AuthSimulationSelector.d.ts +5 -1
- package/dist/components/LogsExplorer/useLogTail.d.ts +9 -0
- package/dist/components/RLSEditor/policyListing.d.ts +44 -0
- package/dist/components/SchemaVisualizer/schema-visualizer.utils.d.ts +0 -1
- package/dist/components/SchemaVisualizer/useSchemaGraph.d.ts +6 -0
- package/dist/components/load-failure.d.ts +1 -1
- package/dist/components/useRunAsUsers.d.ts +25 -0
- package/dist/index.es.js +11 -11
- package/dist/{load-failure-C6OMJSGC.js → load-failure-Bd8lFIO7.js} +2 -2
- package/dist/load-failure-Bd8lFIO7.js.map +1 -0
- package/dist/useRunAsUsers-CLaAtXt6.js +122 -0
- package/dist/useRunAsUsers-CLaAtXt6.js.map +1 -0
- package/dist/utils/sql_utils.d.ts +90 -49
- package/package.json +9 -9
- package/dist/ApiExplorer-pYMZflL3.js.map +0 -1
- package/dist/ApiKeysView-qLSs47tw.js +0 -1239
- package/dist/ApiKeysView-qLSs47tw.js.map +0 -1
- package/dist/AuthSimulationSelector-BewmhMBw.js +0 -56
- package/dist/AuthSimulationSelector-BewmhMBw.js.map +0 -1
- package/dist/BackupsView-DYTAD6aW.js +0 -253
- package/dist/BackupsView-DYTAD6aW.js.map +0 -1
- package/dist/BranchesView-D6Sz1a5f.js.map +0 -1
- package/dist/CronJobsView-7hjgSYId.js.map +0 -1
- package/dist/JSEditor-qiuwmcvk.js.map +0 -1
- package/dist/LogsExplorer-Xq8K4oo6.js.map +0 -1
- package/dist/RLSEditor-Djh43lBE.js.map +0 -1
- package/dist/SQLEditor-TBw_K6CW.js.map +0 -1
- package/dist/SchemaVisualizer-DtDzIUNy.js.map +0 -1
- package/dist/StorageView-CMG1DOVX.js.map +0 -1
- package/dist/components/ApiKeys/permissions.d.ts +0 -66
- package/dist/load-failure-C6OMJSGC.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { n as AuthSimulationSelector, t as useRunAsUsers } from "./useRunAsUsers-CLaAtXt6.js";
|
|
2
2
|
import { ErrorView, IconForView, useApiConfig, useModeController, useRebaseClient, useRebaseContext, useSnackbarController, useStudioCollectionRegistry, useStudioSidePanelController, useTranslation } from "@rebasepro/app";
|
|
3
3
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { Button, Chip, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, IconButton, Menu, MenuItem, MoreVerticalIcon, PencilIcon, PlayIcon, PlusIcon, ResizablePanels, SaveIcon, Tab, Tabs, TerminalIcon, TextField, Tooltip, Trash2Icon, Typography, VirtualTable, XIcon, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
|
|
@@ -6,7 +6,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
import { ALL_WHERE_FILTER_OPS } from "@rebasepro/types";
|
|
7
7
|
import { toSnakeCase } from "@rebasepro/utils";
|
|
8
8
|
import { Highlight, themes } from "prism-react-renderer";
|
|
9
|
-
import { createRebaseClient } from "@rebasepro/client";
|
|
9
|
+
import { createMemoryStorage, createRebaseClient } from "@rebasepro/client";
|
|
10
10
|
import Editor from "@monaco-editor/react";
|
|
11
11
|
//#region src/components/JSEditor/JSMonacoEditor.tsx
|
|
12
12
|
/**
|
|
@@ -138,8 +138,27 @@ interface AdminUser {
|
|
|
138
138
|
updatedAt: string;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
interface ListUsersOptions {
|
|
142
|
+
search?: string;
|
|
143
|
+
/** Page size. The server's default is 25. */
|
|
144
|
+
limit?: number;
|
|
145
|
+
offset?: number;
|
|
146
|
+
orderBy?: string;
|
|
147
|
+
orderDir?: "asc" | "desc";
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** One page of users, and \`total\`: how many match in all. */
|
|
151
|
+
interface UsersPage {
|
|
152
|
+
users: AdminUser[];
|
|
153
|
+
total: number;
|
|
154
|
+
limit: number;
|
|
155
|
+
offset: number;
|
|
156
|
+
}
|
|
157
|
+
|
|
141
158
|
interface RebaseCMS {
|
|
142
|
-
|
|
159
|
+
/** One page of users (25 unless \`limit\` says otherwise) and the total. */
|
|
160
|
+
listUsers(options?: ListUsersOptions): Promise<UsersPage>;
|
|
161
|
+
listUsersPaginated(options?: ListUsersOptions): Promise<UsersPage>;
|
|
143
162
|
getUser(userId: string): Promise<{ user: AdminUser }>;
|
|
144
163
|
createUser(data: { email: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
|
|
145
164
|
updateUser(userId: string, data: { email?: string; displayName?: string; password?: string; roles?: string[] }): Promise<{ user: AdminUser }>;
|
|
@@ -200,8 +219,8 @@ type RebaseData = {
|
|
|
200
219
|
* // Auth
|
|
201
220
|
* const session = client.auth.getSession();
|
|
202
221
|
*
|
|
203
|
-
* // Admin
|
|
204
|
-
* const { users } = await client.admin.listUsers();
|
|
222
|
+
* // Admin: one page of users, and how many there are
|
|
223
|
+
* const { users, total } = await client.admin.listUsers({ limit: 50 });
|
|
205
224
|
*
|
|
206
225
|
* // Custom endpoint
|
|
207
226
|
* const result = await client.call("/my-endpoint", { myData: 123 });
|
|
@@ -221,12 +240,16 @@ interface RebaseClient {
|
|
|
221
240
|
[collectionSlug: string]: unknown;
|
|
222
241
|
}
|
|
223
242
|
|
|
224
|
-
/**
|
|
243
|
+
/**
|
|
244
|
+
* The client for this run: your own, one that runs every request as the user
|
|
245
|
+
* picked in "Run as" (it holds no session, so \`client.auth.getSession()\` is null),
|
|
246
|
+
* or an unauthenticated one under "No Auth".
|
|
247
|
+
*/
|
|
225
248
|
declare const client: RebaseClient;
|
|
226
249
|
|
|
227
250
|
/** Execution context with user and collection information. */
|
|
228
251
|
interface JSEditorContext {
|
|
229
|
-
/** The user the script
|
|
252
|
+
/** The user the script runs as: the one picked in "Run as", or you. \`null\` under "No Auth". */
|
|
230
253
|
user: {
|
|
231
254
|
uid: string;
|
|
232
255
|
displayName: string | null;
|
|
@@ -359,15 +382,20 @@ var QUICK_REFERENCE = [
|
|
|
359
382
|
code: "const result = await client.data.collection(\"COLLECTION\")\n .where(\"field\", \">\", value)\n .orderBy(\"field\", \"desc\")\n .limit(10)\n .find();\nreturn result;",
|
|
360
383
|
description: "Chained query builder"
|
|
361
384
|
},
|
|
385
|
+
{
|
|
386
|
+
label: "Who am I",
|
|
387
|
+
code: "return context.user;",
|
|
388
|
+
description: "The user this script runs as, or null under No Auth"
|
|
389
|
+
},
|
|
362
390
|
{
|
|
363
391
|
label: "Auth: Current session",
|
|
364
392
|
code: "const session = client.auth.getSession();\nreturn session;",
|
|
365
|
-
description: "
|
|
393
|
+
description: "The session this client holds: yours, or none under Run as and No Auth"
|
|
366
394
|
},
|
|
367
395
|
{
|
|
368
396
|
label: "Admin: List users",
|
|
369
|
-
code: "
|
|
370
|
-
description: "
|
|
397
|
+
code: "// One page: raise limit or page with offset while users.length < total\nconst { users, total } = await client.admin.listUsers({ limit: 50, offset: 0 });\nreturn { users, total };",
|
|
398
|
+
description: "A page of users, and how many there are in all"
|
|
371
399
|
},
|
|
372
400
|
{
|
|
373
401
|
label: "Custom endpoint",
|
|
@@ -618,6 +646,7 @@ function CollectionItem({ collection, onInsertCode }) {
|
|
|
618
646
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
619
647
|
title: "Insert find() snippet",
|
|
620
648
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
649
|
+
"aria-label": "Insert find() snippet",
|
|
621
650
|
size: "smallest",
|
|
622
651
|
className: "opacity-0 group-hover:opacity-100 text-text-disabled hover:text-primary transition-all",
|
|
623
652
|
onClick: (e) => {
|
|
@@ -690,12 +719,12 @@ var STORAGE_PREFIX = "rebase_js_";
|
|
|
690
719
|
* new user did be a 404 — a placeholder presented as working code. `slug` is
|
|
691
720
|
* the project's first collection when one is known.
|
|
692
721
|
*/
|
|
693
|
-
var makeDefaultCode = (slug) => `// Available: client (RebaseClient)
|
|
722
|
+
var makeDefaultCode = (slug) => `// Available: client (RebaseClient), context
|
|
694
723
|
// Press Cmd+Enter (Ctrl+Enter) to run
|
|
695
724
|
//
|
|
696
725
|
// Examples:
|
|
697
|
-
// const users = await client.admin.listUsers();
|
|
698
|
-
// const
|
|
726
|
+
// const { users, total } = await client.admin.listUsers({ limit: 50, offset: 0 }); // one page of total
|
|
727
|
+
// const me = context.user; // who this script runs as ("Run as"), null under No Auth
|
|
699
728
|
${slug ? `
|
|
700
729
|
const result = await client.data.collection(${JSON.stringify(slug)}).find({ limit: 10 });
|
|
701
730
|
return result;
|
|
@@ -704,9 +733,24 @@ return result;
|
|
|
704
733
|
// const result = await client.data.collection("posts").find({ limit: 10 });
|
|
705
734
|
// return result;
|
|
706
735
|
|
|
707
|
-
return
|
|
736
|
+
return context.user;
|
|
708
737
|
`}`;
|
|
709
738
|
var DEFAULT_CODE = makeDefaultCode();
|
|
739
|
+
/**
|
|
740
|
+
* The auth of a client built for one run: its own, in memory, and empty.
|
|
741
|
+
*
|
|
742
|
+
* The SDK's default auth restores the session the app saved in `localStorage`,
|
|
743
|
+
* sends its token on every request and keeps refreshing it. A run under "No
|
|
744
|
+
* Auth" or as another user must do none of that: it would go out as the
|
|
745
|
+
* signed-in user, and `client.auth` would describe the wrong person.
|
|
746
|
+
*/
|
|
747
|
+
function runOnlyAuth() {
|
|
748
|
+
return {
|
|
749
|
+
storage: createMemoryStorage(),
|
|
750
|
+
persistSession: false,
|
|
751
|
+
autoRefresh: false
|
|
752
|
+
};
|
|
753
|
+
}
|
|
710
754
|
function loadFromStorage(key, fallback) {
|
|
711
755
|
try {
|
|
712
756
|
const raw = localStorage.getItem(STORAGE_PREFIX + key);
|
|
@@ -727,14 +771,22 @@ function formatJSON(value) {
|
|
|
727
771
|
return String(value);
|
|
728
772
|
}
|
|
729
773
|
}
|
|
774
|
+
/** The script without its comments: a collection named in one is not where rows came from. */
|
|
775
|
+
function withoutComments(code) {
|
|
776
|
+
return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/[^\n]*/g, "");
|
|
777
|
+
}
|
|
730
778
|
/**
|
|
731
|
-
* Given the raw SDK result, try to detect which
|
|
779
|
+
* Given the raw SDK result, try to detect which collection its rows belong to.
|
|
732
780
|
* JS SDK results typically come back as `{ data: [{ id, values }] }` or plain arrays.
|
|
733
|
-
* The heuristic:
|
|
734
|
-
*
|
|
781
|
+
* The heuristic: the executed code, outside its comments, names exactly one
|
|
782
|
+
* collection — `collection("<slug>")` or `client.data.<slug>` — and the result has
|
|
783
|
+
* rows with an "id" column. A script naming two could have returned either's
|
|
784
|
+
* rows, and an action on a row would open the other collection's row with the
|
|
785
|
+
* same id, so it gets none.
|
|
735
786
|
*/
|
|
736
|
-
function detectCollectionsInResult(
|
|
787
|
+
function detectCollectionsInResult(executedCode, resultValue, collections) {
|
|
737
788
|
if (!resultValue || !collections?.length) return [];
|
|
789
|
+
const code = withoutComments(executedCode);
|
|
738
790
|
const mentionedSlugs = /* @__PURE__ */ new Set();
|
|
739
791
|
const collectionCallRegex = /\.collection\(["']([^"']+)["']\)/g;
|
|
740
792
|
let m;
|
|
@@ -748,7 +800,7 @@ function detectCollectionsInResult(code, resultValue, collections) {
|
|
|
748
800
|
"update",
|
|
749
801
|
"delete"
|
|
750
802
|
].includes(m[1])) mentionedSlugs.add(m[1]);
|
|
751
|
-
if (mentionedSlugs.size
|
|
803
|
+
if (mentionedSlugs.size !== 1) return [];
|
|
752
804
|
let rows = [];
|
|
753
805
|
const rv = resultValue;
|
|
754
806
|
if (rv?.data && Array.isArray(rv.data)) rows = rv.data;
|
|
@@ -839,27 +891,7 @@ function JSEditor() {
|
|
|
839
891
|
} : tab);
|
|
840
892
|
});
|
|
841
893
|
}, [firstSlug]);
|
|
842
|
-
const users =
|
|
843
|
-
const managed = [];
|
|
844
|
-
if (currentUser) managed.push({
|
|
845
|
-
uid: currentUser.uid,
|
|
846
|
-
displayName: currentUser.displayName,
|
|
847
|
-
email: currentUser.email,
|
|
848
|
-
photoURL: currentUser.photoURL,
|
|
849
|
-
roles: currentUser.roles
|
|
850
|
-
});
|
|
851
|
-
return managed;
|
|
852
|
-
}, [currentUser]);
|
|
853
|
-
const currentSelectableUser = useMemo(() => {
|
|
854
|
-
if (!currentUser) return null;
|
|
855
|
-
return {
|
|
856
|
-
uid: currentUser.uid,
|
|
857
|
-
displayName: currentUser.displayName,
|
|
858
|
-
email: currentUser.email,
|
|
859
|
-
photoURL: currentUser.photoURL,
|
|
860
|
-
roles: currentUser.roles
|
|
861
|
-
};
|
|
862
|
-
}, [currentUser]);
|
|
894
|
+
const { users, currentUser: currentSelectableUser, loading: usersLoading, onSearchTextChange: onUserSearchTextChange, totalCount: userTotalCount } = useRunAsUsers();
|
|
863
895
|
useEffect(() => {
|
|
864
896
|
saveToStorage("tabs", tabs);
|
|
865
897
|
}, [tabs]);
|
|
@@ -918,29 +950,32 @@ function JSEditor() {
|
|
|
918
950
|
const apiUrl = apiConfig?.apiUrl;
|
|
919
951
|
const getAuthToken = apiConfig?.getAuthToken;
|
|
920
952
|
if (!apiUrl) throw new Error("API URL not configured. Make sure apiUrl is set.");
|
|
921
|
-
if (authMode === "none")
|
|
922
|
-
client
|
|
953
|
+
if (authMode === "none") {
|
|
954
|
+
const client = createRebaseClient({
|
|
923
955
|
baseUrl: apiUrl,
|
|
924
|
-
|
|
925
|
-
})
|
|
926
|
-
isScoped: true
|
|
927
|
-
};
|
|
928
|
-
if (!selectedUser || currentUser && selectedUser.uid === currentUser.uid) {
|
|
929
|
-
if (!rebaseClient) throw new Error("Application client is not initialized.");
|
|
956
|
+
auth: runOnlyAuth()
|
|
957
|
+
});
|
|
930
958
|
return {
|
|
931
|
-
client
|
|
932
|
-
|
|
959
|
+
client,
|
|
960
|
+
release: () => client.close()
|
|
933
961
|
};
|
|
934
962
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
963
|
+
if (!selectedUser || currentUser && selectedUser.uid === currentUser.uid) {
|
|
964
|
+
if (!rebaseClient) throw new Error("Application client is not initialized.");
|
|
965
|
+
return { client: rebaseClient };
|
|
966
|
+
}
|
|
967
|
+
const token = getAuthToken ? await getAuthToken() ?? void 0 : void 0;
|
|
968
|
+
if (!getAuthToken || !token) throw new Error("No auth token available. Please sign in first.");
|
|
969
|
+
const client = createRebaseClient({
|
|
970
|
+
baseUrl: apiUrl,
|
|
971
|
+
token,
|
|
972
|
+
impersonate: selectedUser.uid,
|
|
973
|
+
auth: runOnlyAuth()
|
|
974
|
+
});
|
|
975
|
+
client.setAuthTokenGetter(getAuthToken);
|
|
938
976
|
return {
|
|
939
|
-
client
|
|
940
|
-
|
|
941
|
-
token
|
|
942
|
-
}),
|
|
943
|
-
isScoped: true
|
|
977
|
+
client,
|
|
978
|
+
release: () => client.close()
|
|
944
979
|
};
|
|
945
980
|
}, [
|
|
946
981
|
apiConfig,
|
|
@@ -959,7 +994,8 @@ function JSEditor() {
|
|
|
959
994
|
});
|
|
960
995
|
const consoleEntries = [];
|
|
961
996
|
const startTime = performance.now();
|
|
962
|
-
let
|
|
997
|
+
let release;
|
|
998
|
+
const ranAsSignedInUser = authMode !== "none" && (!selectedUser || selectedUser.uid === currentUser?.uid);
|
|
963
999
|
const originalConsole = {
|
|
964
1000
|
log: console.log,
|
|
965
1001
|
warn: console.warn,
|
|
@@ -979,10 +1015,11 @@ function JSEditor() {
|
|
|
979
1015
|
console.warn = captureConsole("warn");
|
|
980
1016
|
console.error = captureConsole("error");
|
|
981
1017
|
console.info = captureConsole("info");
|
|
982
|
-
const
|
|
983
|
-
|
|
1018
|
+
const built = await buildClient();
|
|
1019
|
+
release = built.release;
|
|
1020
|
+
const client = built.client;
|
|
984
1021
|
const context = {
|
|
985
|
-
user: selectedUser ?? (currentUser ? {
|
|
1022
|
+
user: authMode === "none" ? null : selectedUser ?? (currentUser ? {
|
|
986
1023
|
uid: currentUser.uid,
|
|
987
1024
|
displayName: currentUser.displayName,
|
|
988
1025
|
email: currentUser.email,
|
|
@@ -997,7 +1034,9 @@ function JSEditor() {
|
|
|
997
1034
|
value,
|
|
998
1035
|
console: consoleEntries,
|
|
999
1036
|
duration,
|
|
1000
|
-
timestamp: Date.now()
|
|
1037
|
+
timestamp: Date.now(),
|
|
1038
|
+
code,
|
|
1039
|
+
ranAsSignedInUser
|
|
1001
1040
|
});
|
|
1002
1041
|
const resultObj = value;
|
|
1003
1042
|
if (resultObj?.data && Array.isArray(resultObj.data)) setResultView("table");
|
|
@@ -1010,7 +1049,9 @@ function JSEditor() {
|
|
|
1010
1049
|
console: consoleEntries,
|
|
1011
1050
|
duration,
|
|
1012
1051
|
error: err instanceof Error ? err.message : String(err),
|
|
1013
|
-
timestamp: Date.now()
|
|
1052
|
+
timestamp: Date.now(),
|
|
1053
|
+
code,
|
|
1054
|
+
ranAsSignedInUser
|
|
1014
1055
|
});
|
|
1015
1056
|
setResultView("json");
|
|
1016
1057
|
} finally {
|
|
@@ -1019,11 +1060,12 @@ function JSEditor() {
|
|
|
1019
1060
|
console.error = originalConsole.error;
|
|
1020
1061
|
console.info = originalConsole.info;
|
|
1021
1062
|
setIsRunning(false);
|
|
1022
|
-
|
|
1063
|
+
release?.();
|
|
1023
1064
|
}
|
|
1024
1065
|
}, [
|
|
1025
1066
|
activeTab?.code,
|
|
1026
1067
|
buildClient,
|
|
1068
|
+
authMode,
|
|
1027
1069
|
selectedUser,
|
|
1028
1070
|
currentUser,
|
|
1029
1071
|
collectionInfos
|
|
@@ -1092,13 +1134,9 @@ function JSEditor() {
|
|
|
1092
1134
|
};
|
|
1093
1135
|
}, [result]);
|
|
1094
1136
|
const matchedCollections = useMemo(() => {
|
|
1095
|
-
if (!result?.value || result.error) return [];
|
|
1096
|
-
return detectCollectionsInResult(
|
|
1097
|
-
}, [
|
|
1098
|
-
result,
|
|
1099
|
-
activeTab?.code,
|
|
1100
|
-
collectionRegistry?.collections
|
|
1101
|
-
]);
|
|
1137
|
+
if (!result?.value || result.error || !result.ranAsSignedInUser) return [];
|
|
1138
|
+
return detectCollectionsInResult(result.code, result.value, collectionRegistry?.collections ?? []);
|
|
1139
|
+
}, [result, collectionRegistry?.collections]);
|
|
1102
1140
|
const getRowEntityActions = useCallback((rowData) => {
|
|
1103
1141
|
if (!rowData || matchedCollections.length === 0) return [];
|
|
1104
1142
|
return matchedCollections.filter((mc) => rowData[mc.pkColumn] != null).map((mc) => ({
|
|
@@ -1216,6 +1254,7 @@ function JSEditor() {
|
|
|
1216
1254
|
/* @__PURE__ */ jsx(Tooltip, {
|
|
1217
1255
|
title: "Save as snippet",
|
|
1218
1256
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
1257
|
+
"aria-label": "Save as snippet",
|
|
1219
1258
|
size: "small",
|
|
1220
1259
|
onClick: () => {
|
|
1221
1260
|
setSnippetName("");
|
|
@@ -1228,6 +1267,7 @@ function JSEditor() {
|
|
|
1228
1267
|
result?.value != null && /* @__PURE__ */ jsx(Tooltip, {
|
|
1229
1268
|
title: "Export result as JSON",
|
|
1230
1269
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
1270
|
+
"aria-label": "Export result as JSON",
|
|
1231
1271
|
size: "small",
|
|
1232
1272
|
onClick: exportResult,
|
|
1233
1273
|
children: /* @__PURE__ */ jsx(DownloadIcon, { size: iconSize.smallest })
|
|
@@ -1265,7 +1305,9 @@ function JSEditor() {
|
|
|
1265
1305
|
selectedUser,
|
|
1266
1306
|
setSelectedUser,
|
|
1267
1307
|
users,
|
|
1268
|
-
loading:
|
|
1308
|
+
loading: usersLoading,
|
|
1309
|
+
onUserSearchTextChange,
|
|
1310
|
+
userTotalCount,
|
|
1269
1311
|
currentUser: currentSelectableUser
|
|
1270
1312
|
})
|
|
1271
1313
|
}), /* @__PURE__ */ jsx("div", {
|
|
@@ -1429,6 +1471,10 @@ function JSEditor() {
|
|
|
1429
1471
|
id: String(ra.entityId)
|
|
1430
1472
|
}),
|
|
1431
1473
|
children: /* @__PURE__ */ jsx(IconButton, {
|
|
1474
|
+
"aria-label": t("studio_sql_edit_entity", {
|
|
1475
|
+
name: ra.collection.collection.name,
|
|
1476
|
+
id: String(ra.entityId)
|
|
1477
|
+
}),
|
|
1432
1478
|
size: "small",
|
|
1433
1479
|
className: "text-surface-400 dark:text-surface-500 hover:text-surface-600 dark:hover:text-surface-300",
|
|
1434
1480
|
onClick: (e) => {
|
|
@@ -1627,4 +1673,4 @@ function JSONHighlight({ value }) {
|
|
|
1627
1673
|
//#endregion
|
|
1628
1674
|
export { JSEditor };
|
|
1629
1675
|
|
|
1630
|
-
//# sourceMappingURL=JSEditor-
|
|
1676
|
+
//# sourceMappingURL=JSEditor-B59pwg4c.js.map
|