Open alieralex opened 3 days ago
i don't have an API key set up to really test it, but the generated code is looking alright; see if this approach is workable
import reflex as rx
from reflex.components.props import PropsBase
from reflex.utils.imports import ImportVar
def _drive_picker_callback_signature(data: rx.Var[dict]) -> tuple[rx.Var[dict]]:
return (data,)
class DrivePicker(PropsBase):
client_id: str | rx.Var[str]
developer_key: str | rx.Var[str]
view_id: str | rx.Var[str]
callback_function: rx.EventChain | rx.Var[rx.EventChain]
def __init__(self, **kwargs):
callback_function = kwargs.pop("callback_function", None)
if callback_function is not None:
kwargs["callback_function"] = rx.EventChain(
events=[
rx.event.call_event_handler(
callback_function, _drive_picker_callback_signature
),
],
args_spec=_drive_picker_callback_signature,
)
return super().__init__(**kwargs)
@property
def open_picker(self) -> rx.Var:
return rx.Var(
f"() => openPicker({rx.Var.create(self)})",
_var_type=rx.EventChain,
_var_data=rx.vars.VarData(
imports={
"react-google-drive-picker": ImportVar(
tag="useDrivePicker", is_default=True
)
},
hooks=[
"const [openPicker, authResponse] = useDrivePicker();",
],
),
)
class State(rx.State):
"""The app state."""
def callback(self, data):
print(data)
def index() -> rx.Component:
picker = DrivePicker(
client_id="foo",
developer_key="bar",
view_id="DOCS",
callback_function=State.callback,
)
return rx.container(
rx.color_mode.button(position="top-right"),
rx.vstack(
rx.button("Open Picker", on_click=picker.open_picker),
),
rx.logo(),
)
app = rx.App()
app.add_page(index)
(yes, some of this is undocumented)
Generates code that sort of looks like the example usage on npm
export function Button_76aae5a36aab9ba3fddbfcfafe8ab3f8() {
const [openPicker, authResponse] = useDrivePicker();
const [addEvents, connectErrors] = useContext(EventLoopContext);
const on_click_53f7d2f543ac6d4f299618cdf5a3cccd = useCallback(
() =>
openPicker({
["clientId"]: "foo",
["developerKey"]: "bar",
["viewId"]: "DOCS",
["callbackFunction"]: (_data) =>
addEvents(
[
Event(
"reflex___state____state.repro_picker___repro_picker____state.callback",
{ ["data"]: _data },
{}
),
],
[_data],
{}
),
}),
[addEvents, Event, openPicker, authResponse]
);
return (
<RadixThemesButton onClick={on_click_53f7d2f543ac6d4f299618cdf5a3cccd}>
{"Open Picker"}
</RadixThemesButton>
);
}
Thanks Masen,
I’ll try it a little later today!
Alex Osborne Supercog.ai 510-592-4578
On Mon, Nov 25, 2024 at 12:51 PM Masen Furer @.***> wrote:
i don't have an API key set up to really test it, but the generated code is looking alright; see if this approach is workable
import reflex as rxfrom reflex.components.props import PropsBasefrom reflex.utils.imports import ImportVar
def _drive_picker_callback_signature(data: rx.Var[dict]) -> tuple[rx.Var[dict]]: return (data,)
class DrivePicker(PropsBase): client_id: str | rx.Var[str] developer_key: str | rx.Var[str] view_id: str | rx.Var[str] callback_function: rx.EventChain | rx.Var[rx.EventChain]
def __init__(self, **kwargs): callback_function = kwargs.pop("callback_function", None) if callback_function is not None: kwargs["callback_function"] = rx.EventChain( events=[ rx.event.call_event_handler( callback_function, _drive_picker_callback_signature ), ], args_spec=_drive_picker_callback_signature, ) return super().__init__(**kwargs) @property def open_picker(self) -> rx.Var: return rx.Var( f"() => openPicker({rx.Var.create(self)})", _var_type=rx.EventChain, _var_data=rx.vars.VarData( imports={ "react-google-drive-picker": ImportVar( tag="useDrivePicker", is_default=True ) }, hooks=[ "const [openPicker, authResponse] = useDrivePicker();", ], ), )
class State(rx.State): """The app state."""
def callback(self, data): print(data)
def index() -> rx.Component: picker = DrivePicker( client_id="foo", developer_key="bar", view_id="DOCS", callback_function=State.callback, ) return rx.container( rx.color_mode.button(position="top-right"), rx.vstack( rx.button("Open Picker", on_click=picker.open_picker), ), rx.logo(), )
app = rx.App()app.add_page(index)
(yes, some of this is undocumented)
Generates code that sort of looks like the example usage on npm
export function Button_76aae5a36aab9ba3fddbfcfafe8ab3f8() { const [openPicker, authResponse] = useDrivePicker(); const [addEvents, connectErrors] = useContext(EventLoopContext);
const on_click_53f7d2f543ac6d4f299618cdf5a3cccd = useCallback( () => openPicker({
["developerKey"]: "bar", ["viewId"]: "DOCS", ["callbackFunction"]: (_data) => addEvents( [ Event( "reflex___state____state.repro_picker___repro_picker____state.callback", { ["data"]: _data }, {} ), ], [_data], {} ), }), [addEvents, Event, openPicker, authResponse]
);
return (
{"Open Picker"} );}
— Reply to this email directly, view it on GitHub https://github.com/reflex-dev/reflex/issues/4435#issuecomment-2499006752, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABZEWVQONXA6RB4R5NPWKCT2COEURAVCNFSM6AAAAABSOVMQPKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIOJZGAYDMNZVGI . You are receiving this because you authored the thread.Message ID: @.***>
Hi Masen,
Again thanks for your reply and approach. Your approach uses a google picker react component, and we have spent significant time developing our own for complete flexibility with the Google Picker API. I was wondering if you would be willing to support that approach?
I explored sending my own events but ran into problems. We are running reflex 0.5.9. But it looks like maybe you could help us there. In my current implementation I have created a hidden button, and in my javascript picker callback I am finding this button and calling button.click(). This works for the first time after a reset, but fails on subsequent times.
But if there is a way in my javascript code, running reflex 0.5.9 that I could send an event with data to my state function that will handle the picker data, that would be preferable. I just haven't been able to get that to work. Alternatively if you can suggest how I can get handlerButton.click(); to wor consistently then that is all tested and in place.
Here is javascript where I pass data in local storage and click the button:
const eventDetail = {{
type: eventType,
payload: payload,
timestamp: new Date().toISOString()
}};
localStorage.setItem('picker_event',
JSON.stringify(eventDetail));
const handlerButton =
document.getElementById('folder_select_handler'); if (handlerButton) {{ // Add small delay to ensure event handler is bound await new Promise(resolve => setTimeout(resolve, 100)); handlerButton.click(); }} else {{ this.error('Could not find handler button'); }}
I hope you had a happy thanksgiving and look forward to your response.
Thanks,
Alex Osborne Cofounder Supercog.ai 510-592-4578
On Mon, Nov 25, 2024 at 12:51 PM Masen Furer @.***> wrote:
i don't have an API key set up to really test it, but the generated code is looking alright; see if this approach is workable
import reflex as rxfrom reflex.components.props import PropsBasefrom reflex.utils.imports import ImportVar
def _drive_picker_callback_signature(data: rx.Var[dict]) -> tuple[rx.Var[dict]]: return (data,)
class DrivePicker(PropsBase): client_id: str | rx.Var[str] developer_key: str | rx.Var[str] view_id: str | rx.Var[str] callback_function: rx.EventChain | rx.Var[rx.EventChain]
def __init__(self, **kwargs): callback_function = kwargs.pop("callback_function", None) if callback_function is not None: kwargs["callback_function"] = rx.EventChain( events=[ rx.event.call_event_handler( callback_function, _drive_picker_callback_signature ), ], args_spec=_drive_picker_callback_signature, ) return super().__init__(**kwargs) @property def open_picker(self) -> rx.Var: return rx.Var( f"() => openPicker({rx.Var.create(self)})", _var_type=rx.EventChain, _var_data=rx.vars.VarData( imports={ "react-google-drive-picker": ImportVar( tag="useDrivePicker", is_default=True ) }, hooks=[ "const [openPicker, authResponse] = useDrivePicker();", ], ), )
class State(rx.State): """The app state."""
def callback(self, data): print(data)
def index() -> rx.Component: picker = DrivePicker( client_id="foo", developer_key="bar", view_id="DOCS", callback_function=State.callback, ) return rx.container( rx.color_mode.button(position="top-right"), rx.vstack( rx.button("Open Picker", on_click=picker.open_picker), ), rx.logo(), )
app = rx.App()app.add_page(index)
(yes, some of this is undocumented)
Generates code that sort of looks like the example usage on npm
export function Button_76aae5a36aab9ba3fddbfcfafe8ab3f8() { const [openPicker, authResponse] = useDrivePicker(); const [addEvents, connectErrors] = useContext(EventLoopContext);
const on_click_53f7d2f543ac6d4f299618cdf5a3cccd = useCallback( () => openPicker({
["developerKey"]: "bar", ["viewId"]: "DOCS", ["callbackFunction"]: (_data) => addEvents( [ Event( "reflex___state____state.repro_picker___repro_picker____state.callback", { ["data"]: _data }, {} ), ], [_data], {} ), }), [addEvents, Event, openPicker, authResponse]
);
return (
{"Open Picker"} );}
— Reply to this email directly, view it on GitHub https://c58RN04.na1.hs-sales-engage.com/Ctc/T5+23284/c58RN04/Jll2-6qcW7Y8-PT6lZ3nFW7XGty718fxV4VQD-JS7Pby8gW8jQSb-6c1HV1W2_1JyP18Z2m6W26XRD34pJzq5W2jDmTr98DNt3N8DV1CxZZf3lW6h7ZDl6GcfXLW4pSGKF1sT2vCW47yRsH2hzYDcVmCgfd47cNScW1p7Mm85c61v6W3dvXcg9k7mrPW2fM0Dz8c3cXCW7wsjHn2qdKq4W1c7dFW5JtymHV1DP145Rhmw9VFB-TR3Pl-S-W8XkFT48MK5XnN6slRmpW1nPgW1YZzDv7MrpdXW8ktPgP95tl_hW3Z6plg7WB6b1W2mqbdX5LzYPSW42q-Jy7yRSdPW74ZdK64DxrMpf6M-tBl04, or unsubscribe https://c58RN04.na1.hs-sales-engage.com/Ctc/T5+23284/c58RN04/Jks4YGXpW69t95C6lZ3pPN5qK_8nfxSXlW5wTv2N7HByDtW8l81xF5XWrbZW2XxCJb4sPRXnW6dZMjk3Nb1CMW3H0WYV6KxrKwVTQSLQ7fbl9JW1Q3rym8G_d_YW2PPGTs3f-wkhVZqQ-g3FVMmtW25p4hj6nwthmW8Yx3r93N4j0gVrjmkL1GdnqdM3TBkzrxn0FW10d4rw5SF1dbW5dJWcS1Mfj-nW9m3bmp5RxK5cW2sBKJm3Zb6KcW2KtcSm92Q0mBW65JxTn8bzfTJW68dttR8sS2LyW1QmSck8Brbz9N5-bktKfLK8BVQncd68L5m3XW8W5pff7rlT7yN63569H-h4C2W4TCV7L5THWFrW1_KX7R6tZM1LW8Ygtth8WxMW-V48GMg5tJpNJW4jbBc2103TwWN3kTNRkPQNqBW4HYGK-1cVJf8VBr7hL1FvjjtW4zkC1X3K7JKqW6ZHgZw3pjDTcf89kzgR04 . You are receiving this because you authored the thread.Message ID: @.***>
-- Alex Osborne 510-592-4578
We are trying to implement a callback to reflex to both update the frontend state and make a request to the backend when a user successfully completes a google file picker. Our flow is as follows:
Ideally we could pass self.picker_callback into the javascript code so that it can be called when the google picker succeeds. We can't find a way to do that and as far as we know there is no way to tie a reflex state function to our script.
Specifics (please complete the following information):
We have tried a lot of paths to solve this including reflex EventHandler.. no luck so far.