mirror of
https://github.com/logseq/logseq.git
synced 2026-04-27 23:54:55 +00:00
150 lines
4.9 KiB
Clojure
150 lines
4.9 KiB
Clojure
(ns frontend.components.plugins-settings
|
|
(:require [rum.core :as rum]
|
|
[frontend.util :as util]
|
|
[frontend.ui :as ui]
|
|
[frontend.handler.plugin :as plugin-handler]
|
|
[cljs-bean.core :as bean]
|
|
[goog.functions :refer [debounce]]))
|
|
|
|
(defn- dom-purify
|
|
[html opts]
|
|
(try
|
|
(js-invoke js/DOMPurify "sanitize" html (bean/->js opts))
|
|
(catch js/Error e
|
|
(js/console.warn e) html)))
|
|
|
|
(rum/defc html-content
|
|
[html]
|
|
[:div.html-content.pl-1.flex-1.text-sm
|
|
{:dangerouslySetInnerHTML {:__html (dom-purify html nil)}}])
|
|
|
|
(rum/defc edit-settings-file
|
|
[pid {:keys [class]}]
|
|
[:a.text-sm.hover:underline
|
|
{:class class
|
|
:on-click #(plugin-handler/open-settings-file-in-default-app! pid)}
|
|
"Edit settings.json"])
|
|
|
|
(rum/defc render-item-input
|
|
[val {:keys [key type title default description inputAs]} update-setting!]
|
|
|
|
[:div.desc-item.as-input
|
|
{:data-key key :key key}
|
|
[:h2 [:code key] (ui/icon "caret-right") [:strong title]]
|
|
|
|
[:label.form-control
|
|
(html-content description)
|
|
|
|
(let [input-as (util/safe-lower-case (or inputAs (name type)))
|
|
input-as (if (= input-as "string") :text (keyword input-as))]
|
|
[(if (= input-as :textarea) :textarea :input)
|
|
{:class (util/classnames [{:form-input (not (contains? #{:color :range} input-as))}])
|
|
:type (name input-as)
|
|
:defaultValue (or val default)
|
|
:on-key-down #(.stopPropagation %)
|
|
:on-change (debounce #(update-setting! key (util/evalue %)) 1000)}])]])
|
|
|
|
(rum/defc render-item-toggle
|
|
[val {:keys [key title description default]} update-setting!]
|
|
|
|
(let [val (if (boolean? val) val (boolean default))]
|
|
[:div.desc-item.as-toggle
|
|
{:data-key key}
|
|
[:h2 [:code key] (ui/icon "caret-right") [:strong title]]
|
|
|
|
[:label.form-control
|
|
(ui/checkbox {:checked val
|
|
:on-change #(update-setting! key (not val))})
|
|
(html-content description)]]))
|
|
|
|
(rum/defc render-item-enum
|
|
[val {:keys [key title description default enumChoices enumPicker]} update-setting!]
|
|
|
|
(let [val (or val default)
|
|
vals (into #{} (if (sequential? val) val [val]))
|
|
options (map (fn [v] {:label v :value v
|
|
:selected (contains? vals v)}) enumChoices)
|
|
picker (keyword enumPicker)]
|
|
[:div.desc-item.as-enum
|
|
{:data-key key}
|
|
[:h2 [:code key] (ui/icon "caret-right") [:strong title]]
|
|
|
|
[:div.form-control
|
|
[(if (contains? #{:radio :checkbox} picker) :div.wrap :label.wrap)
|
|
(html-content description)
|
|
|
|
(case picker
|
|
:radio (ui/radio-list options #(update-setting! key %) nil)
|
|
:checkbox (ui/checkbox-list options #(update-setting! key %) nil)
|
|
;; select
|
|
(ui/select options (fn [_ value ] (update-setting! key value))))
|
|
]]]))
|
|
|
|
(rum/defc render-item-object
|
|
[_val {:keys [key title description _default]} pid]
|
|
|
|
[:div.desc-item.as-object
|
|
{:data-key key}
|
|
[:h2 [:code key] (ui/icon "caret-right") [:strong title]]
|
|
|
|
[:div.form-control
|
|
(html-content description)
|
|
[:div.pl-1 (edit-settings-file pid nil)]]])
|
|
|
|
(rum/defc render-item-heading
|
|
[{:keys [key title description]}]
|
|
|
|
[:div.heading-item
|
|
{:data-key key}
|
|
[:h2 title]
|
|
(html-content description)])
|
|
|
|
(rum/defc render-item-not-handled
|
|
[s]
|
|
[:p.text-red-500 (str "#Not Handled# " s)])
|
|
|
|
(rum/defc settings-container
|
|
[schema ^js pl]
|
|
(let [^js plugin-settings (.-settings pl)
|
|
pid (.-id pl)
|
|
[settings, set-settings] (rum/use-state (bean/->clj (.toJSON plugin-settings)))
|
|
update-setting! (fn [k v] (.set plugin-settings (name k) (bean/->js v)))]
|
|
|
|
(rum/use-effect!
|
|
(fn []
|
|
(let [on-change (fn [^js s]
|
|
(when-let [s (bean/->clj s)]
|
|
(set-settings s)))]
|
|
(.on plugin-settings "change" on-change)
|
|
#(.off plugin-settings "change" on-change)))
|
|
[pid])
|
|
|
|
(if (seq schema)
|
|
[:<>
|
|
[:h2.text-xl.px-2.pt-1.opacity-90 "ID: " pid]
|
|
[:div.cp__plugins-settings-inner
|
|
;; settings.json
|
|
[:span.edit-file
|
|
(edit-settings-file pid nil)]
|
|
|
|
;; render items
|
|
(for [desc schema
|
|
:let [key (:key desc)
|
|
val (get settings (keyword key))
|
|
type (keyword (:type desc))
|
|
desc (update desc :description #(plugin-handler/markdown-to-html %))]]
|
|
|
|
(rum/with-key
|
|
(condp contains? type
|
|
#{:string :number} (render-item-input val desc update-setting!)
|
|
#{:boolean} (render-item-toggle val desc update-setting!)
|
|
#{:enum} (render-item-enum val desc update-setting!)
|
|
#{:object} (render-item-object val desc pid)
|
|
#{:heading} (render-item-heading desc)
|
|
|
|
(render-item-not-handled key))
|
|
key))]]
|
|
|
|
;; no settings
|
|
[:h2.font-bold.text-lg.py-4.warning "No Settings Schema!"])))
|