Jelajahi Sumber

feat: initial support for enum type

Tienson Qin 2 tahun lalu
induk
melakukan
fee8ff393e

+ 6 - 5
src/main/frontend/components/page.cljs

@@ -314,9 +314,9 @@
 
 (rum/defc page-configure-inner <
   {:will-unmount (fn [state]
-                   (let [on-unmount (last (:rum/args state))]
+                   (let [on-unmount (nth (:rum/args state) 1)]
                      (on-unmount)))}
-  [page _on-unmount]
+  [page _on-unmount opts]
   (let [types (:block/type page)
         class? (contains? types "class")
         property? (contains? types "property")]
@@ -326,7 +326,7 @@
      (when class?
        (page-properties page true))
      (if property?
-       (property/property-config (state/get-current-repo) page {})
+       (property/property-config (state/get-current-repo) page opts)
               ;; add new property for normal pages
        (when (and (not class?)
                   (empty? (:block/properties page))
@@ -348,12 +348,13 @@
                                                       (some #{"class" "property"} (:block/type page)))]
                                (str "More info on this " block-type)
                                "Configure")]])
-       (fn [{:keys [_toggle-fn]}]
+       (fn [{:keys [toggle-fn]}]
          (page-configure-inner
           page
           (fn []
             (reset! *configuring? false)
-            (reset! *hover? false))))
+            (reset! *hover? false))
+          {:toggle-fn toggle-fn}))
 
        {:modal-class (util/hiccup->class
                       "origin-top-right.absolute.left-0.mt-2.rounded-md.shadow-lg")}))))

+ 41 - 5
src/main/frontend/components/property.cljs

@@ -92,6 +92,34 @@
             "Click to add classes"
             "Click to select a class")])])))
 
+(rum/defcs enum-select < (rum/local false ::open?)
+  [state *property-schema values]
+  (let [items (map (fn [value] {:label value
+                                :value value})
+                   values)
+        opts {:items items
+              :input-default-placeholder "Update choices"
+              :dropdown? false
+              :close-modal? false
+              :multiple-choices? true
+              :selected-choices values
+              :extract-chosen-fn :value
+              :show-new-when-not-exact-match? true
+              :on-apply (fn [choices]
+                          (swap! *property-schema assoc :enum-values choices))}]
+    (ui/dropdown
+     (fn [{:keys [toggle-fn]}]
+       [:div.enum-values.cursor-pointer.flex.flex-col {:on-click toggle-fn}
+        (if (seq values)
+          (for [value values]
+            [:div.enum-value value])
+          [:div.text-sm
+           "Add choices"])])
+     (fn [{:keys [_toggle-fn]}]
+       (select/select opts))
+     {:modal-class (util/hiccup->class
+                    "origin-top-right.absolute.left-0.rounded-md.shadow-lg.mt-2")})))
+
 (rum/defcs property-config <
   rum/reactive
   (rum/local nil ::property-name)
@@ -145,18 +173,26 @@
                        (let [type (keyword (string/lower-case v))]
                          (swap! *property-schema assoc :type type))))])]
 
-      (when (= :page (:type @*property-schema))
+      (case (:type @*property-schema)
+        :page
         [:div.grid.grid-cols-4.gap-1.items-center.leading-8
          [:label "Specify classes:"]
-         (class-select *property-schema (:classes @*property-schema) (assoc opts :disabled? disabled?))])
+         (class-select *property-schema (:classes @*property-schema) (assoc opts :disabled? disabled?))]
 
-      (when (= :template (:type @*property-schema))
+        :template
         [:div.grid.grid-cols-4.gap-1.items-center.leading-8
          [:label "Specify template:"]
          (class-select *property-schema (:classes @*property-schema)
-                       (assoc opts :multiple-choices? false :disabled? disabled?))])
+                       (assoc opts :multiple-choices? false :disabled? disabled?))]
+
+        :enum
+        [:div.grid.grid-cols-4.gap-1.items-start.leading-8
+         [:label "Enum choices:"]
+         (enum-select *property-schema (:enum-values @*property-schema))]
+
+        nil)
 
-      (when-not (contains? #{:checkbox :default :template} (:type @*property-schema))
+      (when-not (contains? #{:checkbox :default :template :enum} (:type @*property-schema))
         [:div.grid.grid-cols-4.gap-1.items-center.leading-8
          [:label "Multiple values:"]
          (let [many? (boolean (= :many (:cardinality @*property-schema)))]

+ 19 - 16
src/main/frontend/components/property/value.cljs

@@ -21,7 +21,7 @@
 
 (defn- select-type?
   [type]
-  (contains? #{:page :number :url :date} type))
+  (contains? #{:page :number :url :date :enum} type))
 
 (defn exit-edit-property
   []
@@ -330,19 +330,22 @@
 
 (defn- select
   [block property {:keys [multiple-choices? dropdown?] :as opts}]
-  (let [date? (= :date (get-in property [:block/schema :type]))
-        items (->> (model/get-block-property-values (:block/uuid property))
-                   (mapcat (fn [[_id value]]
-                             (if (coll? value)
-                               (map (fn [v] {:value v}) value)
-                               [{:value value}])))
-                   (distinct))
-        items (->> (if date?
-                      (map (fn [m] (let [label (:block/original-name (db/entity [:block/uuid (:value m)]))]
-                                     (when label
-                                       (assoc m :label label)))) items)
-                      items)
-                    (remove nil?))
+  (let [schema (:block/schema property)
+        type (:type schema)
+        items (if (= :enum type)
+                (map (fn [v] {:value v}) (:enum-values schema))
+                (->> (model/get-block-property-values (:block/uuid property))
+                     (mapcat (fn [[_id value]]
+                               (if (coll? value)
+                                 (map (fn [v] {:value v}) value)
+                                 [{:value value}])))
+                     (distinct)))
+        items (->> (if (= :date type)
+                     (map (fn [m] (let [label (:block/original-name (db/entity [:block/uuid (:value m)]))]
+                                    (when label
+                                      (assoc m :label label)))) items)
+                     items)
+                   (remove nil?))
         add-property-f #(add-property! block (:block/original-name property) %)
         on-chosen (fn [chosen]
                     (add-property-f (if (map? chosen) (:value chosen) chosen))
@@ -354,7 +357,7 @@
                      :items items
                      :selected-choices selected-choices
                      :dropdown? dropdown?
-                     :show-new-when-not-exact-match? true
+                     :show-new-when-not-exact-match? (not (contains? #{:enum} type))
                      :input-default-placeholder "Select"
                      :extract-chosen-fn :value
                      :input-opts (fn [_]
@@ -420,7 +423,7 @@
         select-f (fn []
                    [:div.property-select (cond-> {} editing? (assoc :class "h-6"))
                     (case type
-                      (:number :url :date)
+                      (:number :url :date :enum)
                       (select block property select-opts')
 
                       :page

+ 3 - 2
src/main/frontend/handler/db_based/property.cljs

@@ -48,6 +48,7 @@
    :template [:fn
               {:error/message "should has #template"}
               logseq-template?]
+   :enum     some?                      ; the value could be anything such as number, text, url, date, page, image, video, etc.
    ;; internal usage
    :keyword  keyword?
    :map      map?
@@ -56,7 +57,7 @@
    :any      some?})
 
 (def internal-builtin-schema-types #{:keyword :map :coll :any})
-(def user-face-builtin-schema-types [:default :number :date :checkbox :url :page :template])
+(def user-face-builtin-schema-types [:default :number :date :checkbox :url :page :template :enum])
 
 ;; schema -> type, cardinality, object's class
 ;;           min, max -> string length, number range, cardinality size limit
@@ -90,7 +91,7 @@
 
       ;; these types don't need to be translated. :date expects uuid and other
       ;; types usually expect text
-      (:url :date :any)
+      (:enum :url :date :any)
       v-str)))
 
 (defn upsert-property!