Open oliviertassinari opened 3 months ago
The Blob should be an easy fix
diff --git a/packages/toolpad-studio-runtime/src/jsBrowserRuntime.tsx b/packages/toolpad-studio-runtime/src/jsBrowserRuntime.tsx
index 7e2a92fb3..4f90baacf 100644
--- a/packages/toolpad-studio-runtime/src/jsBrowserRuntime.tsx
+++ b/packages/toolpad-studio-runtime/src/jsBrowserRuntime.tsx
@@ -32,7 +32,7 @@ function createBrowserRuntime(): JsRuntime {
(() => {
// See https://tc39.es/ecma262/multipage/global-object.html#sec-global-object
const ecmaGlobals = new Set([ 'globalThis', 'Infinity', 'NaN', 'undefined', 'eval', 'isFinite', 'isNaN', 'parseFloat', 'parseInt', 'decodeURI', 'decodeURIComponent', 'encodeURI', 'encodeURIComponent', 'AggregateError', 'Array', 'ArrayBuffer', 'BigInt', 'BigInt64Array', 'BigUint64Array', 'Boolean', 'DataView', 'Date', 'Error', 'EvalError', 'FinalizationRegistry', 'Float32Array', 'Float64Array', 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Number', 'Object', 'Promise', 'Proxy', 'RangeError', 'ReferenceError', 'RegExp', 'Set', 'SharedArrayBuffer', 'String', 'Symbol', 'SyntaxError', 'TypeError', 'Uint8Array', 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'URIError', 'WeakMap', 'WeakRef', 'WeakSet', 'Atomics', 'JSON', 'Math', 'Reflect' ]);
- const allowedDomGlobals = new Set([ 'setTimeout', 'console', 'URL', 'URLSearchParams', 'Intl' ])
+ const allowedDomGlobals = new Set([ 'setTimeout', 'console', 'URL', 'URLSearchParams', 'Intl', 'Blob' ])
// NOTE: This is by no means intended to be a secure way to hide DOM globals
const globalThis = new Proxy(window.__SCOPE, {
Your code will fail likely on the document
access. I don't think we should allow users to update the dom directly, it will for sure mess with our rendering and state management.
edit:
Perhaps we need to build a "initiate download" action? It would take a bindable input for content and inputs for type and name. Using this binding on a button will initiate a download for said content
Your code will fail likely on the document access
Correct, it fails. From https://stackoverflow.com/questions/19327749/javascript-blob-filename-without-link, all the permutations seem to require access to the DOM.
Perhaps we need to build a "initiate download" action?
We could build this, though, I would expect that there are cases where developers need to run custom JavaScript logic, so we might as do the most generic and cheaper approach first: a new API, Retool-like.
Another benchmark: https://docs.appsmith.com/reference/appsmith-framework/widget-actions/download
Ok for me. Perhaps to avoid interfering with builtins we could add a global toolpad
namespace that holds custom utilities?
interface ToolpadGlobal {
download(data: URL | Blob | string | ..., fileName?: string)
}
declare global {
var toolpad: ToolpadGlobal
}
To be used as
toolpad.download(new Blob([textarea.value], { type: 'text/csv' }), 'file.csv')
👍
In the end, I built the tool without the download button https://github.com/mui/mui-private/pull/538. We will see if Tina uses this or prefers the CLI. If a community member faces the same problem, and fixes this, we can then update Toolpad, it can save her a bit of time, but it's still cheaper for engineers to not spend time on this 😄
Summary
I think we need an helper to download files.
Similar to https://docs.retool.com/queries/reference/libraries/utils#method-downloadFile (https://community.retool.com/t/utils-downloadfile-downloads-empty-pdf/4642 for more context)
Examples
I tried to create a "download" button with this onClick handler:
which works when I use it in my console; but doesn't in Toolpad because of the way the sandboxing works. If fails with
You can see https://github.com/mui/mui-private/pull/538 for a reproduction and use case. Now, it's not that important for the use case I'm trying to solve here, so I'm adding the waiting for upvotes label, better be lazy.