Fork me on GitHub
#hyperfiddle
<
2023-02-26
>
Ben Sless07:02:36

Do you think electric would be a good fit for building something like forum software? How do logins and permissions work in electric?

👀 2
tatut07:02:19

afaict, permissions would work like in any web software, your server side calls should only access what the current user is allowed to do

👍 4
tatut07:02:22

I don’t see why you couldn’t build a form in electric, but… even every reader will need a websocket connection and therefore resources from the server. I would wager that if a forum is publicly browsable, it is much easier to cache unauthenticated pages with a traditional full page server side rendering solution.

tatut08:02:01

I don’t know the internals that well, but it seems it would be difficult to cache the WS messaging in any meaningful way

Dustin Getz12:02:47

not a good fit yet, need SSR and “resumable” rendering, all of which are naturally done from signals based rendering approaches as proven by Solid.js which is dominating SSR benchmarks right now

Dustin Getz12:02:11

however even though it can be done, “website” type apps is not our current focus today; Electric today is for ultra dynamic stateful apps like google docs or webflow or IDE

Dustin Getz12:02:00

like we want to rebuild datascript in electric clojure so we can make the query engine network transparent, slice the indexes so they are partially client side so that “last mile” filtering happens on the client - offline first datascript! that’s what the kind of thing electric clojure is intended to make possible

nice 4
clojure-spin 2
Dustin Getz12:02:18

on the other hand, if you tried to build a forum with electric today, the client/server boundary can be refactored and moved around at will, so you could choose to preload the page in one message and then not load anything else until you navigate

Dustin Getz12:02:56

so in theory you could probably make it work, even release the websocket when not needed, or use cloud flare durable objects (edge network for websockets with durable state) - lots of possible ways to scale this

tatut12:02:49

Interesting, is there a way to release and restart the ws?

tatut12:02:39

Would you serialize some representation of the state to ”resume” from?

Ben Sless12:02:55

I've done a bit of hacking on DS, would be happy to lend a hand with that

🤝 2
Dustin Getz14:02:51

No good way to restart the WS today (it reboots the page if you do, both client and server). We already did a first POC of resyncing state on reconnect, but hit a design flaw in the wire protocol preventing us from doing it efficiently. Maybe next iteration? historically we do a major revision about every 3 months

Dave Mays09:03:54

Interesting about possibly rewriting Datascript in Electric. I'm sure other things (like Electric itself) are higher priority but I'm curious if this has been started? Offline first datascript sounds pretty cool. I've also come across Asami which could be interesting as it also runs in browser.

Dustin Getz09:03:14

we did some early analysis work, it could be POCed in a couple days

nakkaya15:02:53

What would be the idiomatic way to update a table in a page, without redrawing/reloading the whole page. I have a table in a page, rows are fetched from the db and table is build, I am trying to add delete functionality, a button deletes the item from the db and removes the row.

(dom/tbody
     (e/for [[id fname lname dob] (e/server
                                   (->> (db/patients (e/client (user.)))
                                        (map #(vector (str (:patients/id %))
                                                      (:patients/first_name %)
                                                      (:patients/last_name %)
                                                      (str (:patients/date_of_birth %))))))]
       (dom/tr
        (dom/props {:id id})
        (dom/td
         (dom/props {:rowspan "1", :colspan "1"})
         (dom/text fname))
        (dom/td
         (dom/props {:rowspan "1", :colspan "1"})
         (dom/text lname))
        (dom/td
         (dom/props {:rowspan "1", :colspan "1"})
         (dom/text dob))
        (dom/td
         (dom/props {:rowspan "1", :colspan "1" :align "right"})
         (h/Button. "Delete" "btn btn-sm btn-outline-secondary"
                    (e/fn [_]
                      ;;(e/server (db/patient-delete id))
                      ;; (-> js/document
                      ;;     (.getElementById id)
                      ;;     (.remove))
                      ))))))

nakkaya16:02:24

I did see that I had separate question about that I tried to follow that and wrapped the snippet in a try catch and e/wrap the db calls but I got no output no error. So if I understood the example correctly, atom changes which triggers the watch so any code within the scope of that watch is rerun?

Dustin Getz17:02:38

changing the atom causes the watch to update, which causes any expressions that depend on the watch to update (but not the whole scope, it is fine-grained updates based on a reactivity graph)

vincent17:02:07

I want to make a component that displays the k,v pairs of a map atom as an html table

vincent17:02:13

so far i did

vincent17:02:32

(e/defn AtomTable [map-atom]
  (e/client
    (dom/div
      (dom/table
        (e/for [[k v] map-atom]
          (dom/tr
            (dom/td
              (dom/text k v))))))))

tatut17:02:52

Did you e/watch the atom to get the valua?

👍 1
vincent17:02:18

um, yes i have that

vincent17:02:54

#(:clj (defonce !users (atom (list))))
(e/def users (e/server (reverse (e/watch !users))))

vincent17:02:24

for examlpe, although want 2 generalize

tatut17:02:03

fwiw, this works for me

(e/defn AtomTable [val]
  (e/client
   (dom/table
    (e/for [[k v] val]
      (dom/tr
       (dom/td (dom/text k))
       (dom/td (dom/text v)))))))

(e/defn Other []
  (let [atom-map (atom {:foo 42})
        atom-map-value (e/watch atom-map)]
    (AtomTable. atom-map-value)))

tatut17:02:42

I can call AtomTable from another component and it renders ok

vincent17:02:11

thanks i had an error in an unrelated swap! that was wrecking the component 😅

👍 1
vincent17:02:21

actually, not sure :thinking_face: can you define the atom outside the component as clj and still watch it? i'm getting 'n is not a function' :thinking_face:

vincent18:02:18

ok probably just a typo somewhere.

vincent18:02:42

gonna go pour cold water on my head

Dustin Getz18:02:20

make sure to watch the atom from the same place it is defined at

vincent18:02:49

i define it on the server, then i want the ui component to ppulate a table of it... hmm

xificurC18:02:51

watch on the server, use the watched value on the client

vincent18:02:25

e/for it on the server?

vincent18:02:33

and then pass the resultant table to the client?

vincent18:02:56

oh i see i can destructure on server x)

vincent19:02:31

I guess my question is, can I display all the server atoms to the client in real-time?

vincent17:02:51

not sure what i'm missing 😅

vincent19:02:31

I guess my question is, can I display all the server atoms to the client in real-time?

vincent22:02:53

if i want to output to both js console and clojure sys out can i do so in the same e/defn?

vincent22:02:23

(e/client (.log js/console "stuff')) ?

vincent23:02:42

okay i got some of the stuff working, it was very nonobvious what was not right x)

Dustin Getz23:02:07

any ideas how could we improve the tutorials? what document do we need to write that would have gotten you what you need quicker?

vincent01:03:55

no idea. the way i was doing it was wrong and the example was right x)

vincent01:03:26

i don't mind the learning curve. it is factored into the cost of taking on a new framework always. in this case, it is very profitable because i only need to learn it once to be productive many times. i looked at a basic example and went as far as i could writing code myself.

vincent01:03:28

but when it didn't work as expected, i had to turn to the examples again. i think a side-by-side page of the code and the demos would be lovely and probably helpful. a big game changer for me was creating the AtomTable component and being able to live introspect changing values on the page while working / recompiling. a peek into the "db" of the app. i think those sorts of things will help people grok faster.

👀 2
Dustin Getz03:03:47

do you have code for AtomTable that we should include in a tutorial? send me some scraps of what you have and i'll think about how to include it

Dustin Getz03:03:01

ty for the feedback & ideas, keep it coming