Fork me on GitHub
#hyperfiddle
<
2023-10-02
>
Can08:10:54

Hello! I looking at an example specified about table's in Electric. I need to learn how to sort by table cell and how to implement the pagination feature. Does anyone have a code snipped or a basic example that I can study on it? Thanks!

s3dse08:10:50

Sure, here's my current table function. Pagination is still a ToDo. Please be warned: I'm still an electric noob 😉

(e/defn Table [data fields !per-page search? classes &slots]
  (let [!search (atom "")
        search (e/watch !search)
        per-page (e/watch !per-page)
        !items (atom (if (empty? search) (take per-page data) (take per-page (find-data search data))))
        items (e/watch !items)
        !sort-order (atom {:key nil :direction nil})
        sort-order (e/watch !sort-order)]
    (dom/div (dom/props {:class "flex flex-wrap mx-4 my-3 gap-2 justify-start dark:text-gray-300"})
      (when search?
        (ui/input search (e/fn [v] (reset! !search v))
          (dom/props {:type "search" :placeholder "Type to search"
                    :class "border dark:border-moon-700 dark:bg-moon-900 rounded-sm px-2 text-sm"})))
      (when (:controls &slots)
        (e/for [control-fn (:controls &slots)]
          (new control-fn))))

    (dom/table (dom/props {:class (:table classes)})
      (dom/thead (dom/props {:class (:thead classes)})
        (e/for [key (keys fields)]
          (let [sortable (-> fields key :sortable)
                sort-reverse? (= key (:key sort-order))
                th-class (str (when sortable "hover:cursor-pointer ") " " (:th-class (key fields)) " " (:th classes))]
            (println key)
            (dom/th
              (dom/props {:class th-class})
              (when sortable
                (dom/on "click" (e/fn [_]
                                (let [asc? (= "asc" (:direction sort-order))]
                                  (reset! !items (sort-by key (if (and sort-reverse? asc?) > <) items))
                                  (reset! !sort-order (assoc {} :key key :direction (if (and asc? sort-reverse?)
                                                                                      "desc"
                                                                                      "asc")))))))
              (dom/div (dom/props {:class "inline-flex no-wrap gap-1 items-center"})
                (dom/span (dom/text (str (get-in fields [key :label] (name key)))))
                (dom/span (dom/props {:class (cond
                                           (not sortable) ""
                                           (and sort-reverse? (= "asc" (:direction sort-order))) "flex i-mdi-chevron-up"
                                           (and sort-reverse? (= "desc" (:direction sort-order))) "flex i-mdi-chevron-down"
                                           :else "flex i-mdi-sort")})))))))
      (dom/tbody
        (e/for [row items]
          (dom/tr (dom/props {:class (:tr classes)})
            (e/for [[k v] row]
              (let [fmt-key (:formatter (k fields))
                    fmt (if fmt-key (fmt-key formatters) identity)
                    td-class (str (:td classes) " " (:td-class (k fields)))]
                (dom/td
                  (dom/text (fmt v))
                  (dom/props {:class td-class}))))))))))

👀 1
xificurC09:10:23

we have a demo of https://electric-examples-app.fly.dev/user.demo-webview!%57ebview, no pagination or sorting. We have other versions but none ready to demo

s3dse08:10:21

Hi! I'm struggling with the uber jar build. When I include GCP's secret manager API, the creation of the API client crashes at runtime with a weird error message: java.lang.IllegalAccessError: class com.google.iam.v1.TestIamPermissionsRequest tried to access method 'com.google.protobuf.LazyStringArrayList com.google.protobuf.LazyStringArrayList.emptyList()' (com.google.iam.v1.TestIamPermissionsRequest and com.google.protobuf.LazyStringArrayList are in unnamed module of loader 'app') I tried to reproduce this in a non-electric Clojure app and the uber jar is building and running fine. Maybe someone had a similar problem?

s3dse08:10:18

My setup looks like this... in deps.edn:

com.google.cloud/google-cloud-secretmanager {:mvn/version "2.27.0"}
src/prod.clj:
(ns prod
  (:gen-class)
  (:require
   app.myapp
   clojure.string
   app.electric-server-java8-jetty9)
  (:import (com.google.cloud.secretmanager.v1
             SecretManagerServiceClient)))

(def electric-server-config
  {:host "0.0.0.0", :port 8080, :resources-path "public"})

(defn -main [& args] ; run with `clj -M -m prod`
  (when (clojure.string/blank? (System/getProperty "HYPERFIDDLE_ELECTRIC_SERVER_VERSION"))
    (throw (ex-info "HYPERFIDDLE_ELECTRIC_SERVER_VERSION jvm property must be set in prod" {})))
  (let [secret-client (SecretManagerServiceClient/create)])
  (app.electric-server-java8-jetty9/start-server! electric-server-config))
uberjar function in src-build/build.clj:
...
(defn uberjar [{:keys [jar-name version optimize debug verbose]
                :or   {version version, optimize true, debug false, verbose false}}]
  ...
  (println "Building uberjar")
  (b/uber {:class-dir class-dir
           :uber-file (str (or jar-name (default-jar-name {:version version})))
           :basis     basis
           :exclude [#"(?i)^META-INF/license/.*"
                     #"^license/.*"] ;; avoid conflicts with same named licenses
           :main      'prod}))
...

xificurC08:10:28

can you post the whole stacktrace? Preferably in a snippet (Ctrl+Shift+Enter) so it's easier to read this thread

s3dse09:10:48

Exception in thread "main" java.lang.IllegalAccessError: class com.google.iam.v1.TestIamPermissionsRequest tried to access method 'com.google.protobuf.LazyStringArrayList com.google.protobuf.LazyStringArrayList.emptyList()' (com.google.iam.v1.TestIamPermissionsRequest and com.google.protobuf.LazyStringArrayList are in unnamed module of loader 'app')
        at com.google.iam.v1.TestIamPermissionsRequest.<init>(TestIamPermissionsRequest.java:127)
        at com.google.iam.v1.TestIamPermissionsRequest.<clinit>(TestIamPermissionsRequest.java:918)
        at com.google.cloud.secretmanager.v1.stub.GrpcSecretManagerServiceStub.<clinit>(GrpcSecretManagerServiceStub.java:211)
        at com.google.cloud.secretmanager.v1.stub.SecretManagerServiceStubSettings.createStub(SecretManagerServiceStubSettings.java:349)
        at com.google.cloud.secretmanager.v1.SecretManagerServiceClient.<init>(SecretManagerServiceClient.java:180)
        at com.google.cloud.secretmanager.v1.SecretManagerServiceClient.create(SecretManagerServiceClient.java:162)
        at com.google.cloud.secretmanager.v1.SecretManagerServiceClient.create(SecretManagerServiceClient.java:153)
        at prod$_main.invokeStatic(prod.clj:20)
        at prod$_main.doInvoke(prod.clj:17)
        at clojure.lang.RestFn.invoke(RestFn.java:400)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.RestFn.applyTo(RestFn.java:135)
        at prod.main(Unknown Source)

xificurC09:10:19

thanks. I don't see any electric code in the stack trace and haven't seen a similar error to date. Maybe there's a classpath version conflict? E.g. protobuf version mismatch

xificurC09:10:57

if you have a working and non-working repo try to compare the versions of the libraries, maybe some dependent library's version got overridden by non-compatible one

s3dse09:10:07

Thanks for having a look! The electric version that doesn't work: https://github.com/s3dse/electric-starter-app the repro without electric: https://github.com/s3dse/testapp (`clj -T:build ci && java -jar target/net.clojars.s3dse/testapp-0.1.0-SNAPSHOT.jar` ) I checked the dependency tree for different versions of protobuf, but there's only one version mentioned.

xificurC09:10:56

could you post the commands you ran on the electric repo?

xificurC09:10:08

I still think this will be a protobuf version conflict, see https://github.com/protocolbuffers/protobuf/issues/11986

s3dse10:10:18

Sure, I used clojure -X:build uberjar :jar-name "app.jar" :version '"0.1.0"' and java -DHYPERFIDDLE_ELECTRIC_SERVER_VERSION="0.1.0" -jar app.jar

s3dse10:10:36

Yep, thank you for giving it a look. I'll try to dig deeper. I just thought maybe it had to do with the build mechanics, because the exact same version does not reproduce the issue with a plain Clojure app.

xificurC10:10:33

yes, I can reproduce that here, although I'm getting Your default credentials were not found in the plain repo so I can't tell 100% sure

s3dse10:10:11

Yes, that's just telling you that the client was created successfully and your authentication failed.

Dustin Getz10:10:52

conflict is likely with clojurescript/shadow/google closure

xificurC10:10:19

downgrading the secret manager to 2.12.0 doesn't throw this cryptic error

👀 1
xificurC10:10:07

didn't try all versions in between. Definitely weird

s3dse13:10:04

Thanks, with that working version I was able to compare the deps tree. Secret manager 2.15.0 introduced some guava related change. I was able to fix it by pinning guava to a newer version

com.google.guava/guava {:mvn/version "32.1.2-jre"}
@U09FL65DK, @U09K620SG Thank you for your help!!

👍 1
Dustin Getz14:10:43

there's a lot of discussion of the guava conflict in shadow-cljs and other slack channels - just mentioning for next time this comes up

👀 1
Dustin Getz14:10:00

basically i think you want to track down each dependency that transitively loads guava and exclude it for every such dependency, and then let clojurescript dictate the version (or is it shadow)

👍 1