mirror of
https://github.com/edufeed-org/edufeed-web.git
synced 2025-12-10 00:34:34 +00:00
add edu-feed
This commit is contained in:
parent
570eed0f41
commit
960200d410
11 changed files with 3755 additions and 230 deletions
|
|
@ -1,9 +1,11 @@
|
|||
(ns ied.views
|
||||
(:require
|
||||
[re-frame.core :as re-frame]
|
||||
[cljs.pprint :refer [pprint]]
|
||||
[ied.events :as events]
|
||||
[ied.routes :as routes]
|
||||
[ied.subs :as subs]
|
||||
[ied.nostr :as nostr]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
;; add resource form
|
||||
|
|
@ -47,31 +49,121 @@
|
|||
:on-click #(re-frame/dispatch [::events/convert-amb-and-publish-as-nostr-event (:json-string @s)])}
|
||||
"Publish as Nostr Event"]])))
|
||||
|
||||
(defn add-resosurce-by-uri []
|
||||
(let [uri (reagent/atom {:uri ""})]
|
||||
(fn []
|
||||
[:form {:on-submit (fn [e] (.preventDefault e))}
|
||||
[:label {:for "uri"} "URI: "]
|
||||
[:input {:id "uri"
|
||||
:on-change (fn [e]
|
||||
(swap! uri assoc :uri (-> e .-target .-value)))}]
|
||||
[:button {:class "btn btn-warning"
|
||||
:on-click #(re-frame/dispatch [::events/publish-amb-uri-as-nostr-event (:uri @uri)])}
|
||||
"Publish as Nostr Event"]])))
|
||||
|
||||
;; event data modal
|
||||
(defn event-data-modal []
|
||||
(let [visible? @(re-frame/subscribe [::subs/show-event-data-modal])
|
||||
selected-event @(re-frame/subscribe [::subs/selected-event])]
|
||||
(when visible?
|
||||
[:dialog {:open visible? :class "modal"}
|
||||
[:div {:class "modal-box relative flex flex-col"}
|
||||
[:h3 {:class "text-lg font-bold"} (nostr/get-name-from-metadata-event selected-event)]
|
||||
[:pre (with-out-str (pprint selected-event))]
|
||||
[:p {:class "py-4"} "Press ESC key or click outside to close"]]
|
||||
|
||||
[:form {:on-click #(re-frame/dispatch [::events/toggle-show-event-data-modal])
|
||||
:method "dialog" :class "modal-backdrop"}
|
||||
[:button "close"]]])))
|
||||
|
||||
;; metadata event component
|
||||
(defn metadata-event-component [event]
|
||||
(let [selected-events @(re-frame/subscribe [::subs/selected-events])]
|
||||
[:div
|
||||
{:class "card bg-base-100 w-96 shadow-xl min-h-[620px]"}
|
||||
[:figure
|
||||
[:img
|
||||
{:class "h-48 object-cover"
|
||||
:src
|
||||
(nostr/get-image-from-metadata-event event)
|
||||
:alt ""}]]
|
||||
[:div
|
||||
{:class "card-body"}
|
||||
[:a {:href (nostr/get-d-id-from-event event)
|
||||
:class "card-title hover:underline"}
|
||||
(nostr/get-name-from-metadata-event event)]
|
||||
(doall
|
||||
(for [about (nostr/get-about-names-from-metadata-event event)]
|
||||
[:div {:class "badge badge-primary m-1 truncate "
|
||||
:key about} about]))
|
||||
[:p {:class "break-all"}
|
||||
(nostr/get-description-from-metadata-event event)]
|
||||
[:button {:on-click #(re-frame/dispatch [::events/toggle-show-event-data-modal event])} "Show Event Data"]
|
||||
[:div
|
||||
{:class "card-actions justify-end"}
|
||||
[:div
|
||||
{:class "form-control"}
|
||||
[:label
|
||||
{:class "cursor-pointer label"}
|
||||
[:span {:class "label-text"} ""]
|
||||
[:input
|
||||
{:type "checkbox"
|
||||
:checked (contains? (set (map #(:id %) selected-events)) (:id event))
|
||||
:class "checkbox checkbox-success"
|
||||
:on-change #(re-frame/dispatch [::events/toggle-selected-events event])}]]]]]]))
|
||||
|
||||
;; events
|
||||
(defn events-panel []
|
||||
(let [events (re-frame/subscribe [::subs/events])
|
||||
(let [events @(re-frame/subscribe [::subs/metadata-events])
|
||||
selected-events @(re-frame/subscribe [::subs/selected-events])
|
||||
show-add-event (re-frame/subscribe [::subs/show-add-event])]
|
||||
[:div {:class "border-2 rounded"}
|
||||
[:p {:on-click #(re-frame/dispatch [::events/toggle-show-add-event])}
|
||||
(if @show-add-event "X" "Add Resource!")]
|
||||
(when @show-add-event
|
||||
[add-resource-form])
|
||||
[:p (str "Num of events: " (count @events))]
|
||||
(if (> (count @events) 0)
|
||||
(doall
|
||||
(for [event @events]
|
||||
[:li {:key (:id event)} (get event :content "")
|
||||
[:input {:type "checkbox"
|
||||
:on-click #(re-frame/dispatch [::events/toggle-selected-events event])}]]))
|
||||
[:p (str "Num of events: " (count events))]
|
||||
(if (> (count events) 0)
|
||||
[:div {:class "flex flex-wrap justify-center gap-2"}
|
||||
(doall
|
||||
(for [event events]
|
||||
[:div {:key (:id event)}
|
||||
[metadata-event-component event]]))]
|
||||
[:p "no events there"])
|
||||
[:button {:class "btn"
|
||||
:disabled (not (boolean (seq selected-events)))
|
||||
:on-click #(re-frame/dispatch [::events/add-resources-to-list [{:d "unique-id-1"
|
||||
:name "Test List SC"}
|
||||
selected-events]])}
|
||||
:on-click #(re-frame/dispatch [::events/add-metadata-event-to-list [{:d "unique-id-1"
|
||||
:name "Test List SC"}
|
||||
selected-events]])}
|
||||
"Add To Lists"]]))
|
||||
|
||||
;; event feed component
|
||||
(defn event-feed-component [event]
|
||||
(let [_ () #_(re-frame/dispatch [::events/add-confetti])]
|
||||
[:div
|
||||
{:class "animate-flyIn card bg-base-100 w-64 h-64 shadow-xl border border-white border-w "}
|
||||
[:p (:kind event)]
|
||||
[:figure
|
||||
[:img
|
||||
{:class "h-48 object-contain"
|
||||
:src
|
||||
(nostr/get-image-from-metadata-event event)
|
||||
:alt ""}]]
|
||||
[:div
|
||||
{:class "card-body"}
|
||||
[:button {:on-click #(re-frame/dispatch [::events/toggle-show-event-data-modal event])} "Show Event Data"]]]))
|
||||
|
||||
(defn event-feed-panel []
|
||||
(let [events @(re-frame/subscribe [::subs/feed-events])]
|
||||
[:div {:class ""}
|
||||
[:h1 "Event Feed"]
|
||||
[:p (str "Num of events: " (count events))]
|
||||
(if (> (count events) 0)
|
||||
[:div {:class "flex flex-row gap-2"}
|
||||
(doall
|
||||
(for [event events]
|
||||
[:div {:key (:id event)}
|
||||
[event-feed-component event]]))]
|
||||
[:p "no events there"])]))
|
||||
|
||||
(defmethod routes/panels :event-feed-panel [] [event-feed-panel])
|
||||
|
||||
;; relays
|
||||
(defn add-relay-form
|
||||
[name uri]
|
||||
|
|
@ -95,7 +187,6 @@
|
|||
[:button {:on-click #(re-frame/dispatch [::events/create-websocket {:name (:name @s)
|
||||
:id (random-uuid)
|
||||
:uri (:uri @s)}])}
|
||||
|
||||
"Add Relay"]])))
|
||||
|
||||
(defn relays-panel
|
||||
|
|
@ -126,34 +217,198 @@
|
|||
;(re-frame/dispatch [::events/connect-to-default-relays])
|
||||
)]))
|
||||
|
||||
;; Header
|
||||
;; checkmark
|
||||
(defn checkmark []
|
||||
[:svg
|
||||
{:version "1.1",
|
||||
:class "fa-icon ml-auto mr-2 svelte-1mc5hvj",
|
||||
:width "16",
|
||||
:height "16",
|
||||
:aria-label "",
|
||||
:role "presentation",
|
||||
:viewBox "0 0 1792 1792",
|
||||
; :style "color: black;"
|
||||
}
|
||||
[:path
|
||||
{:d
|
||||
"M1671 566q0 40-28 68l-724 724-136 136q-28 28-68 28t-68-28l-136-136-362-362q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 295 656-657q28-28 68-28t68 28l136 136q28 28 28 68z"}]])
|
||||
|
||||
(defn header []
|
||||
(let [pk (re-frame/subscribe [::subs/pk])]
|
||||
;; Add to lists modal
|
||||
(defn create-list-modal []
|
||||
(let [name (reagent/atom "")
|
||||
visible? @(re-frame/subscribe [::subs/show-create-list-modal])]
|
||||
(when visible?
|
||||
[:dialog {:open visible? :class "modal"}
|
||||
[:div {:class "modal-box relative flex flex-col"}
|
||||
[:h3 {:class "text-lg font-bold"} "Hello!"]
|
||||
[:p {:class "py-4"} "Press ESC key or click outside to close"]
|
||||
[:input
|
||||
{:type "text"
|
||||
:on-change (fn [e] (reset! name (-> e .-target .-value)))
|
||||
:placeholder "List Name"
|
||||
:class "input input-bordered w-full max-w-xs"}]
|
||||
[:button {:class "btn"
|
||||
:on-click #(re-frame/dispatch [::events/create-new-list @name])} "Create New List"]]
|
||||
|
||||
[:form {:on-click #(re-frame/dispatch [::events/toggle-show-create-list-modal])
|
||||
:method "dialog" :class "modal-backdrop"}
|
||||
[:button "close"]]])))
|
||||
|
||||
(defn add-to-lists-modal []
|
||||
(let [selected-list-ids @(re-frame/subscribe [::subs/selected-list-ids])
|
||||
selected-lists @(re-frame/subscribe [::subs/selected-lists])
|
||||
selected-metadata-events @(re-frame/subscribe [::subs/selected-events])
|
||||
visible? @(re-frame/subscribe [::subs/show-lists-modal])
|
||||
lists @(re-frame/subscribe [::subs/lists-of-user])
|
||||
sorted-lists (nostr/sort-lists lists)]
|
||||
(when visible?
|
||||
[:dialog {:open visible? :class "modal"}
|
||||
[:div {:class "modal-box relative flex flex-col"}
|
||||
[:h3 {:class "text-lg font-bold"}
|
||||
"Hello!"]
|
||||
[:p {:class "py-4"}
|
||||
"Press ESC key or click outside to close"]
|
||||
(doall
|
||||
(for [l lists]
|
||||
(let [in-selected-lists (or (and (seq selected-metadata-events)
|
||||
(every? (fn [e] (nostr/list-contains-metadata-event? l e)) selected-metadata-events))
|
||||
(contains? selected-list-ids (:id l)))
|
||||
div-class (str "m-2 flex flex-row items-center rounded border border-solid border-white p-2 "
|
||||
(if in-selected-lists
|
||||
"bg-green-500 text-black"
|
||||
"hover:bg-orange-500 hover:text-black"))]
|
||||
|
||||
[:div {:class div-class
|
||||
:key (nostr/get-list-name l)
|
||||
:on-click #(re-frame/dispatch [::events/toggle-selected-list-ids (:id l)])}
|
||||
[:p {:class "text-xl font-bold"}
|
||||
(nostr/get-list-name l)]
|
||||
(when in-selected-lists
|
||||
[checkmark])])))
|
||||
[:div {:class "flex flex-row"}
|
||||
[:button {:on-click #(re-frame/dispatch [::events/add-metadata-events-to-lists [selected-metadata-events selected-lists]])
|
||||
:class "btn"}
|
||||
"Add Resources To Lists"]
|
||||
[:button {:class "btn ml-auto mr-0"
|
||||
:on-click #(re-frame/dispatch [::events/toggle-show-create-list-modal])}
|
||||
"Create New List"]]]
|
||||
|
||||
[:form {:on-click #(re-frame/dispatch [::events/toggle-show-lists-modal])
|
||||
:method "dialog"
|
||||
:class "modal-backdrop"}
|
||||
[:button
|
||||
"close"]]])))
|
||||
|
||||
;; shopping cart
|
||||
(defn shopping-cart []
|
||||
(let [selected-events @(re-frame/subscribe [::subs/selected-events])]
|
||||
[:div {:class "dropdown dropdown-end"}
|
||||
[:div
|
||||
{:tabIndex "0", :role "button", :class "btn btn-ghost btn-circle"}
|
||||
[:div
|
||||
{:class "indicator"}
|
||||
[:svg
|
||||
{:xmlns "http://www.w3.org/2000/svg",
|
||||
:class "h-5 w-5",
|
||||
:fill "none",
|
||||
:viewBox "0 0 24 24",
|
||||
:stroke "currentColor"}
|
||||
[:path
|
||||
{:stroke-linecap "round",
|
||||
:stroke-linejoin "round",
|
||||
:stroke-width "2",
|
||||
:d
|
||||
"M3 3h2l.4 2M7 13h10l4-8H5.4M7 13L5.4 5M7 13l-2.293 2.293c-.63.63-.184 1.707.707 1.707H17m0 0a2 2 0 100 4 2 2 0 000-4zm-8 2a2 2 0 11-4 0 2 2 0 014 0z"}]]
|
||||
[:span {:class "badge badge-sm indicator-item"} (count selected-events)]]]
|
||||
[:div
|
||||
{:tabIndex "0",
|
||||
:class
|
||||
"card card-compact dropdown-content bg-base-100 z-[1] mt-3 w-52 shadow"}
|
||||
[:div
|
||||
{:class "card-body"}
|
||||
[:span {:class "text-lg font-bold"}
|
||||
(str (count selected-events)
|
||||
" Items")]
|
||||
[:div {:class "card-actions"}
|
||||
[:button {:class "btn"
|
||||
:on-click #(re-frame/dispatch [::events/toggle-show-lists-modal])}
|
||||
"Add To Lists"]]]]]))
|
||||
|
||||
(defn user-menu []
|
||||
(let [pk @(re-frame/subscribe [::subs/pk])]
|
||||
(if pk
|
||||
[:div
|
||||
{:class "dropdown dropdown-end"}
|
||||
[:div
|
||||
{:tabIndex "0",
|
||||
:role "button",
|
||||
:class "btn btn-ghost btn-circle avatar"}
|
||||
[:div
|
||||
{:class "w-10 rounded-full"}
|
||||
[:img
|
||||
{:alt "Tailwind CSS Navbar component",
|
||||
:src
|
||||
"https://img.daisyui.com/images/stock/photo-1534528741775-53994a69daeb.webp"}]]]
|
||||
[:ul
|
||||
{:tabIndex "0",
|
||||
:class
|
||||
"menu menu-sm dropdown-content bg-base-100 rounded-box z-[1] mt-3 w-52 p-2 shadow"}
|
||||
[:li
|
||||
[:a
|
||||
{:on-click #(re-frame/dispatch [::events/navigate [:npub-view :npub (nostr/get-npub-from-pk pk)]])}
|
||||
"Profile"]]
|
||||
[:li [:a {:on-click #(re-frame/dispatch [::events/navigate [:settings]])} "Settings"]]
|
||||
[:li [:a {:on-click #(re-frame/dispatch [::events/navigate [:keys]])} "Keys"]]
|
||||
[:li [:a {:on-click #(re-frame/dispatch [::events/logout])} "Logout"]]]]
|
||||
[:div
|
||||
{:class "dropdown dropdown-end"}
|
||||
[:div {:tabIndex "0", :role "button", :class "btn m-1"} "Login"]
|
||||
[:ul
|
||||
{:tabIndex "0",
|
||||
:class
|
||||
"dropdown-content menu bg-base-100 rounded-box z-[1] w-52 p-2 shadow"}
|
||||
[:li [:a {:on-click #(re-frame/dispatch [::events/create-sk])}
|
||||
"... Anonymously"]]
|
||||
[:li [:a {:on-click #(re-frame/dispatch [::events/login-with-extension])}
|
||||
"... with Extension"]]]])))
|
||||
|
||||
;; Header
|
||||
(defn new-header []
|
||||
(let [selected-events @(re-frame/subscribe [::subs/selected-events])]
|
||||
[:div
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate :home])}
|
||||
"home"]
|
||||
"|"
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate :add-resource])}
|
||||
"add resource"]
|
||||
"|"
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate :about])}
|
||||
"about"]
|
||||
"|"
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate :settings])}
|
||||
"settings"]
|
||||
"|"
|
||||
(if @pk
|
||||
[:a {:on-click #(re-frame/dispatch [::events/logout])} "logout"]
|
||||
[:a {:on-click #(re-frame/dispatch [::events/login-with-extension])} "login"])]))
|
||||
{:class "navbar bg-base-100"}
|
||||
[:div
|
||||
{:class "flex-1"}
|
||||
[:a {:class "btn btn-ghost text-xl"
|
||||
:on-click #(re-frame/dispatch [::events/navigate [:home]])}
|
||||
"edufeed"]
|
||||
[:a {:class "btn btn-circle"
|
||||
:on-click #(re-frame/dispatch [::events/navigate [:event-feed]])} "Event-Feed"]]
|
||||
[:div
|
||||
{:class "flex-none"}
|
||||
|
||||
[:a {:class "btn btn-circle"
|
||||
:on-click #(re-frame/dispatch [::events/navigate [:add-resource]])} "+"]
|
||||
[shopping-cart]
|
||||
[user-menu]]]))
|
||||
|
||||
;; Keys Panel
|
||||
(defn keys-panel []
|
||||
(let [npub @(re-frame/subscribe [::subs/npub])
|
||||
nsec @(re-frame/subscribe [::subs/nsec])] [:div
|
||||
[:h1 "Keys"]
|
||||
[:p (str "Your Npub: " npub)]
|
||||
[:p (str "Your Nsec: " nsec)]]))
|
||||
|
||||
(defmethod routes/panels :keys-panel [] [keys-panel])
|
||||
|
||||
;; Add Resource Panel
|
||||
|
||||
(defn add-resource-panel []
|
||||
[:div
|
||||
[:h1 "Add Resource"]
|
||||
[add-resource-form]
|
||||
[add-resource-by-json]])
|
||||
[add-resource-by-json]
|
||||
[add-resosurce-by-uri]])
|
||||
|
||||
(defmethod routes/panels :add-resource-panel [] [add-resource-panel])
|
||||
|
||||
|
|
@ -167,12 +422,8 @@
|
|||
|
||||
;; Home
|
||||
(defn home-panel []
|
||||
(let [name (re-frame/subscribe [::subs/name])
|
||||
events (re-frame/subscribe [::subs/events])]
|
||||
(let [events (re-frame/subscribe [::subs/events])]
|
||||
[:div
|
||||
[:h1
|
||||
(str "Hello from " @name ". This is the Home Page.")]
|
||||
|
||||
[events-panel]
|
||||
[:p (count @events)]]))
|
||||
|
||||
|
|
@ -183,39 +434,56 @@
|
|||
[:div
|
||||
[:h1 "This is the About Page."]
|
||||
[:div
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate :home])}
|
||||
[:a {:on-click #(re-frame/dispatch [::events/navigate [:home]])}
|
||||
"go to Home Page"]]])
|
||||
|
||||
(defmethod routes/panels :about-panel [] [about-panel])
|
||||
|
||||
;; npub
|
||||
;; Lists
|
||||
(defn list-component [list]
|
||||
(let [pk @(re-frame/subscribe [::subs/pk])
|
||||
ids-in-list (nostr/get-event-ids-from-list list)
|
||||
events-in-list @(re-frame/subscribe [::subs/events-in-list ids-in-list]) ;; TODO should be sorted after appeareande in tags
|
||||
]
|
||||
[:div {:key (:id list)
|
||||
:class "p-2"}
|
||||
[:details
|
||||
{:class "collapse bg-base-200"}
|
||||
[:summary
|
||||
{:class "collapse-title text-xl font-medium"}
|
||||
(nostr/get-list-name list)]
|
||||
[:div {:class "collapse-content"}
|
||||
|
||||
(doall
|
||||
(for [event events-in-list]
|
||||
[:div {:key (:id event)}
|
||||
[metadata-event-component event]
|
||||
(when pk
|
||||
[:button {:class "btn btn-warning"
|
||||
:on-click #(re-frame/dispatch [::events/delete-event-from-list [event list]])}
|
||||
"Delete Resource from List"])]))
|
||||
|
||||
(when pk [:button {:class "btn btn-error"
|
||||
:on-click #(re-frame/dispatch [::events/delete-list list])} "Delete List"])]]]))
|
||||
|
||||
;; npub / Profile
|
||||
(defn npub-view-panel []
|
||||
(let [sockets @(re-frame/subscribe [::subs/sockets])
|
||||
route-params @(re-frame/subscribe [::subs/route-params])
|
||||
lists @(re-frame/subscribe [::subs/lists])
|
||||
lists @(re-frame/subscribe [::subs/lists-for-npub])
|
||||
_ (when (not (seq lists)) (re-frame/dispatch [::events/get-lists-for-npub (:npub route-params)]))
|
||||
missing-events-from-lists @(re-frame/subscribe [::subs/missing-events-from-lists])
|
||||
_ (when (seq missing-events-from-lists) (re-frame/dispatch [::events/query-for-event-ids [sockets missing-events-from-lists]]))]
|
||||
[:div
|
||||
[:h1 (str "Hello Npub: " (:npub route-params))]
|
||||
(if-not (seq lists)
|
||||
[:p "No lists there...yet"]
|
||||
[:div {:class "p-2"} "Got some lists"
|
||||
(doall
|
||||
(for [l lists]
|
||||
[:div {:class "p-2"
|
||||
:key (:id l)}
|
||||
[:li
|
||||
|
||||
[:p (str "ID: " (:id l))]
|
||||
[:p (str "Name: " (first (filter #(= "d" (first %)) (:tags l))))]
|
||||
;; TODO filter tags for already being in events
|
||||
;; for all that are not send a query
|
||||
[:p (str "Tags: " (:tags l))]
|
||||
[:button {:class "btn btn-error"
|
||||
:on-click #(re-frame/dispatch [::events/delete-list l])} "Delete List"]]]))])
|
||||
[:button {:class "btn"
|
||||
:on-click
|
||||
#(re-frame/dispatch [::events/get-lists-for-npub [sockets (:npub route-params)]])} "Load lists"]]))
|
||||
(doall
|
||||
(for [l lists]
|
||||
^{:key (:id l)} [list-component l])))
|
||||
[:button {:class "btn ml-auto mr-0"
|
||||
:on-click #(re-frame/dispatch [::events/toggle-show-create-list-modal])}
|
||||
"Create New List"]]))
|
||||
|
||||
(defmethod routes/panels :npub-view-panel [] [npub-view-panel])
|
||||
|
||||
|
|
@ -223,10 +491,10 @@
|
|||
(defn main-panel []
|
||||
(let [active-panel (re-frame/subscribe [::subs/active-panel])]
|
||||
[:div
|
||||
[header]
|
||||
[new-header]
|
||||
[:div
|
||||
(routes/panels @active-panel)]]))
|
||||
(routes/panels @active-panel)
|
||||
[add-to-lists-modal]
|
||||
[create-list-modal]
|
||||
[event-data-modal]]]))
|
||||
|
||||
(comment
|
||||
|
||||
(.log js/console "Hello World"))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue