Browse Source

fix(regression): specify node tags

Tienson Qin 1 year ago
parent
commit
80737d624c

+ 29 - 105
src/main/frontend/components/property.cljs

@@ -14,10 +14,8 @@
             [frontend.db :as db]
             [frontend.db :as db]
             [frontend.db-mixins :as db-mixins]
             [frontend.db-mixins :as db-mixins]
             [frontend.db.async :as db-async]
             [frontend.db.async :as db-async]
-            [frontend.db.model :as model]
             [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.db-based.property :as db-property-handler]
             [frontend.handler.notification :as notification]
             [frontend.handler.notification :as notification]
-            [frontend.handler.page :as page-handler]
             [frontend.handler.route :as route-handler]
             [frontend.handler.route :as route-handler]
             [frontend.mixins :as mixins]
             [frontend.mixins :as mixins]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.modules.shortcut.core :as shortcut]
@@ -34,80 +32,6 @@
             [promesa.core :as p]
             [promesa.core :as p]
             [rum.core :as rum]))
             [rum.core :as rum]))
 
 
-(defn- <create-class-if-not-exists!
-  [value]
-  (when (string? value)
-    (let [page-name (string/trim value)]
-      (when-not (string/blank? page-name)
-        (p/let [page (page-handler/<create-class! page-name {:redirect? false
-                                                             :create-first-block? false})]
-          (:block/uuid page))))))
-
-(rum/defc class-select
-  [property {:keys [multiple-choices? disabled? default-open? no-class? on-hide]
-             :or {multiple-choices? true}}]
-  (let [*ref (rum/use-ref nil)]
-    (rum/use-effect!
-     (fn []
-       (when default-open?
-         (some-> (rum/deref *ref)
-                 (.click))))
-     [default-open?])
-    (let [schema-classes (:property/schema.classes property)]
-      [:div.flex.flex-1.col-span-3
-       (let [content-fn
-             (fn [{:keys [id]}]
-               (let [toggle-fn #(do
-                                  (when (fn? on-hide) (on-hide))
-                                  (shui/popup-hide! id))
-                     classes (model/get-all-classes (state/get-current-repo) {:except-root-class? true})
-                     options (map (fn [class]
-                                    {:label (:block/title class)
-                                     :value (:block/uuid class)})
-                                  classes)
-                     options (if no-class?
-                               (cons {:label "Skip choosing tag"
-                                      :value :no-tag}
-                                     options)
-                               options)
-                     opts {:items options
-                           :input-default-placeholder (if multiple-choices? "Choose tags" "Choose tag")
-                           :dropdown? false
-                           :close-modal? false
-                           :multiple-choices? multiple-choices?
-                           :selected-choices (map :block/uuid schema-classes)
-                           :extract-fn :label
-                           :extract-chosen-fn :value
-                           :show-new-when-not-exact-match? true
-                           :input-opts {:on-key-down
-                                        (fn [e]
-                                          (case (util/ekey e)
-                                            "Escape"
-                                            (do
-                                              (util/stop e)
-                                              (toggle-fn))
-                                            nil))}
-                           :on-chosen (fn [value select?]
-                                        (if (= value :no-tag)
-                                          (toggle-fn)
-                                          (p/let [result (<create-class-if-not-exists! value)
-                                                 value' (or result value)
-                                                 tx-data [[(if select? :db/add :db/retract) (:db/id property) :property/schema.classes [:block/uuid value']]]
-                                                 _ (db/transact! (state/get-current-repo) tx-data {:outliner-op :update-property})]
-                                           (when-not multiple-choices? (toggle-fn)))))}]
-
-                 (select/select opts)))]
-
-         [:div.flex.flex-1.cursor-pointer
-          {:ref *ref
-           :on-click (if disabled?
-                       (constantly nil)
-                       #(shui/popup-show! (.-target %) content-fn))}
-          (if (seq schema-classes)
-            [:div.flex.flex-1.flex-row.items-center.flex-wrap.gap-2
-             (for [class schema-classes]
-               [:a.text-sm (str "#" (:block/title class))])]
-            (pv/property-empty-btn-value))])])))
 
 
 (defn- property-type-label
 (defn- property-type-label
   [property-type]
   [property-type]
@@ -366,25 +290,25 @@
   (rum/local false ::show-class-select?)
   (rum/local false ::show-class-select?)
   (rum/local {} ::property-schema)
   (rum/local {} ::property-schema)
   (mixins/event-mixin
   (mixins/event-mixin
-    (fn [state]
-      (mixins/hide-when-esc-or-outside
-        state
-        :on-hide (fn [_state _e type]
-                   (when (= type :esc)
-                     (shui/popup-hide!)
-                     (shui/dialog-close!)
-                     (when-let [^js input (state/get-input)]
-                       (.focus input)))))))
+   (fn [state]
+     (mixins/hide-when-esc-or-outside
+      state
+      :on-hide (fn [_state _e type]
+                 (when (= type :esc)
+                   (shui/popup-hide!)
+                   (shui/dialog-close!)
+                   (when-let [^js input (state/get-input)]
+                     (.focus input)))))))
   {:init (fn [state]
   {:init (fn [state]
            (state/set-editor-action! :property-input)
            (state/set-editor-action! :property-input)
            (assoc state ::property (or (:*property (last (:rum/args state)))
            (assoc state ::property (or (:*property (last (:rum/args state)))
-                                     (atom nil))))
+                                       (atom nil))))
    :will-unmount (fn [state]
    :will-unmount (fn [state]
                    (let [args (:rum/args state)
                    (let [args (:rum/args state)
                          *property-key (second args)
                          *property-key (second args)
                          {:keys [original-block edit-original-block]} (last args)
                          {:keys [original-block edit-original-block]} (last args)
                          editing-default-property? (and original-block (state/get-edit-block)
                          editing-default-property? (and original-block (state/get-edit-block)
-                                                     (not= (:db/id original-block) (:db/id (state/get-edit-block))))]
+                                                        (not= (:db/id original-block) (:db/id (state/get-edit-block))))]
                      (when *property-key (reset! *property-key nil))
                      (when *property-key (reset! *property-key nil))
                      (when (and original-block edit-original-block)
                      (when (and original-block edit-original-block)
                        (edit-original-block {:editing-default-property? editing-default-property?})))
                        (edit-original-block {:editing-default-property? editing-default-property?})))
@@ -398,14 +322,14 @@
         *show-class-select? (::show-class-select? state)
         *show-class-select? (::show-class-select? state)
         *property-schema (::property-schema state)
         *property-schema (::property-schema state)
         existing-tag-alias (->> db-property/db-attribute-properties
         existing-tag-alias (->> db-property/db-attribute-properties
-                             (map db-property/built-in-properties)
-                             (keep #(when (get block (:attribute %)) (:title %)))
-                             set)
+                                (map db-property/built-in-properties)
+                                (keep #(when (get block (:attribute %)) (:title %)))
+                                set)
         exclude-properties (fn [m]
         exclude-properties (fn [m]
                              (or (and (not page?) (contains? existing-tag-alias (:block/title m)))
                              (or (and (not page?) (contains? existing-tag-alias (:block/title m)))
                                ;; Filters out properties from being in wrong :view-context
                                ;; Filters out properties from being in wrong :view-context
-                               (and (not page?) (= :page (get-in m [:block/schema :view-context])))
-                               (and page? (= :block (get-in m [:block/schema :view-context])))))
+                                 (and (not page?) (= :page (get-in m [:block/schema :view-context])))
+                                 (and page? (= :block (get-in m [:block/schema :view-context])))))
         property (rum/react *property)
         property (rum/react *property)
         property-key (rum/react *property-key)]
         property-key (rum/react *property-key)]
     [:div.ls-property-input.flex.flex-1.flex-row.items-center.flex-wrap.gap-1
     [:div.ls-property-input.flex.flex-1.flex-row.items-center.flex-wrap.gap-1
@@ -422,20 +346,20 @@
            (cond
            (cond
              @*show-new-property-config?
              @*show-new-property-config?
              (property-type-select property (merge opts
              (property-type-select property (merge opts
-                                              {:*property *property
-                                               :*property-name *property-key
-                                               :*property-schema *property-schema
-                                               :default-open? true
-                                               :block block
-                                               :*show-new-property-config? *show-new-property-config?
-                                               :*show-class-select? *show-class-select?}))
+                                                   {:*property *property
+                                                    :*property-name *property-key
+                                                    :*property-schema *property-schema
+                                                    :default-open? true
+                                                    :block block
+                                                    :*show-new-property-config? *show-new-property-config?
+                                                    :*show-class-select? *show-class-select?}))
 
 
              (and property @*show-class-select?)
              (and property @*show-class-select?)
-             (class-select property (assoc opts
-                                      :on-hide #(reset! *show-class-select? false)
-                                      :multiple-choices? false
-                                      :default-open? true
-                                      :no-class? true))
+             (property-config/class-select property (assoc opts
+                                                           :on-hide #(reset! *show-class-select? false)
+                                                           :multiple-choices? false
+                                                           :default-open? true
+                                                           :no-class? true))
 
 
              :else
              :else
              (when (and property (not class-schema?))
              (when (and property (not class-schema?))
@@ -446,7 +370,7 @@
                          (fn [e]
                          (fn [e]
                            ;; `Backspace` to close property popup and back to editing the current block
                            ;; `Backspace` to close property popup and back to editing the current block
                            (when (and (= (util/ekey e) "Backspace")
                            (when (and (= (util/ekey e) "Backspace")
-                                   (= "" (.-value (.-target e))))
+                                      (= "" (.-value (.-target e))))
                              (util/stop e)
                              (util/stop e)
                              (shui/popup-hide!)))}]
                              (shui/popup-hide!)))}]
          (property-select exclude-properties {:on-chosen on-chosen
          (property-select exclude-properties {:on-chosen on-chosen

+ 103 - 6
src/main/frontend/components/property/config.cljs

@@ -21,7 +21,13 @@
             [promesa.core :as p]
             [promesa.core :as p]
             [goog.dom :as gdom]
             [goog.dom :as gdom]
             [rum.core :as rum]
             [rum.core :as rum]
-            [frontend.db-mixins :as db-mixins]))
+            [frontend.db-mixins :as db-mixins]
+            [frontend.components.property.value :as pv]
+            [frontend.components.select :as select]
+            [frontend.db.model :as model]
+            [frontend.handler.page :as page-handler]
+            [frontend.ui :as ui]
+            [frontend.components.svg :as svg]))
 
 
 (defn- re-init-commands!
 (defn- re-init-commands!
   "Update commands after task status and priority's closed values has been changed"
   "Update commands after task status and priority's closed values has been changed"
@@ -64,6 +70,81 @@
         (:db/id property)
         (:db/id property)
         :logseq.property/description description))))
         :logseq.property/description description))))
 
 
+(defn- <create-class-if-not-exists!
+  [value]
+  (when (string? value)
+    (let [page-name (string/trim value)]
+      (when-not (string/blank? page-name)
+        (p/let [page (page-handler/<create-class! page-name {:redirect? false
+                                                             :create-first-block? false})]
+          (:block/uuid page))))))
+
+(rum/defc class-select
+  [property {:keys [multiple-choices? disabled? default-open? no-class? on-hide]
+             :or {multiple-choices? true}}]
+  (let [*ref (rum/use-ref nil)]
+    (rum/use-effect!
+     (fn []
+       (when default-open?
+         (some-> (rum/deref *ref)
+                 (.click))))
+     [default-open?])
+    (let [schema-classes (:property/schema.classes property)]
+      [:div.flex.flex-1.col-span-3
+       (let [content-fn
+             (fn [{:keys [id]}]
+               (let [toggle-fn #(do
+                                  (when (fn? on-hide) (on-hide))
+                                  (shui/popup-hide! id))
+                     classes (model/get-all-classes (state/get-current-repo) {:except-root-class? true})
+                     options (map (fn [class]
+                                    {:label (:block/title class)
+                                     :value (:block/uuid class)})
+                                  classes)
+                     options (if no-class?
+                               (cons {:label "Skip choosing tag"
+                                      :value :no-tag}
+                                     options)
+                               options)
+                     opts {:items options
+                           :input-default-placeholder (if multiple-choices? "Choose tags" "Choose tag")
+                           :dropdown? false
+                           :close-modal? false
+                           :multiple-choices? multiple-choices?
+                           :selected-choices (map :block/uuid schema-classes)
+                           :extract-fn :label
+                           :extract-chosen-fn :value
+                           :show-new-when-not-exact-match? true
+                           :input-opts {:on-key-down
+                                        (fn [e]
+                                          (case (util/ekey e)
+                                            "Escape"
+                                            (do
+                                              (util/stop e)
+                                              (toggle-fn))
+                                            nil))}
+                           :on-chosen (fn [value select?]
+                                        (if (= value :no-tag)
+                                          (toggle-fn)
+                                          (p/let [result (<create-class-if-not-exists! value)
+                                                 value' (or result value)
+                                                 tx-data [[(if select? :db/add :db/retract) (:db/id property) :property/schema.classes [:block/uuid value']]]
+                                                 _ (db/transact! (state/get-current-repo) tx-data {:outliner-op :update-property})]
+                                           (when-not multiple-choices? (toggle-fn)))))}]
+
+                 (select/select opts)))]
+
+         [:div.flex.flex-1.cursor-pointer
+          {:ref *ref
+           :on-click (if disabled?
+                       (constantly nil)
+                       #(shui/popup-show! (.-target %) content-fn))}
+          (if (seq schema-classes)
+            [:div.flex.flex-1.flex-row.items-center.flex-wrap.gap-2
+             (for [class schema-classes]
+               [:a.text-sm (str "#" (:block/title class))])]
+            (pv/property-empty-btn-value))])])))
+
 (rum/defc name-edit-pane
 (rum/defc name-edit-pane
   [property {:keys [set-sub-open! disabled?]}]
   [property {:keys [set-sub-open! disabled?]}]
   (let [*form-data (rum/use-ref {:icon (:logseq.property/icon property)
   (let [*form-data (rum/use-ref {:icon (:logseq.property/icon property)
@@ -201,7 +282,8 @@
       [:div.inner-wrap
       [:div.inner-wrap
        {:class (util/classnames [{:disabled disabled?}])}
        {:class (util/classnames [{:disabled disabled?}])}
        [:strong
        [:strong
-        (some-> icon (name) (shui/tabler-icon))
+        (some-> icon (name) (shui/tabler-icon {:size 14
+                                               :style {:margin-top "-1"}}))
         [:span title]]
         [:span title]]
        (if (fn? desc) (desc)
        (if (fn? desc) (desc)
          (if (boolean? toggle-checked?)
          (if (boolean? toggle-checked?)
@@ -403,16 +485,31 @@
         built-in? (ldb/built-in? property)
         built-in? (ldb/built-in? property)
         disabled? (or built-in? config/publishing?)]
         disabled? (or built-in? config/publishing?)]
     [:<>
     [:<>
-     (dropdown-editor-menuitem {:icon :edit :title "Property name" :desc [:span.flex.items-center.gap-1 icon title]
+     (dropdown-editor-menuitem {:icon :pencil :title "Property name" :desc [:span.flex.items-center.gap-1 icon title]
                                 :submenu-content (fn [ops] (name-edit-pane property (assoc ops :disabled? disabled?)))})
                                 :submenu-content (fn [ops] (name-edit-pane property (assoc ops :disabled? disabled?)))})
      (let [disabled? (or (ldb/built-in? property) (and property-type (seq values)))]
      (let [disabled? (or (ldb/built-in? property) (and property-type (seq values)))]
        (dropdown-editor-menuitem {:icon :hash
        (dropdown-editor-menuitem {:icon :hash
                                   :title "Property type"
                                   :title "Property type"
-                                  :desc (str property-type-label')
+                                  :desc (if disabled?
+                                          (ui/tippy {:html        [:div.w-96
+                                                                   "The type of this property is locked once you start using it. This is to make sure all your existing information stays correct if the property type is changed later. To unlock, all uses of a property must be deleted."]
+                                                     :class       "tippy-hover ml-2"
+                                                     :interactive true
+                                                     :disabled    false}
+                                                    (str property-type-label'))
+                                          (str property-type-label'))
                                   :disabled? disabled?
                                   :disabled? disabled?
                                   :submenu-content (fn [ops]
                                   :submenu-content (fn [ops]
                                                      (property-type-sub-pane property ops))}))
                                                      (property-type-sub-pane property ops))}))
 
 
+     (when (= property-type :node)
+       (dropdown-editor-menuitem {:icon :hash
+                                  :title "Specify node tags"
+                                  :desc ""
+                                  :submenu-content (fn [_ops]
+                                                     [:div.px-4
+                                                      (class-select property {:default-open? false})])}))
+
      (when enable-closed-values? (empty? (:property/schema.classes property))
      (when enable-closed-values? (empty? (:property/schema.classes property))
            (let [values (:property/closed-values property)]
            (let [values (:property/closed-values property)]
              (dropdown-editor-menuitem {:icon :list :title "Available choices"
              (dropdown-editor-menuitem {:icon :list :title "Available choices"
@@ -448,8 +545,8 @@
 
 
      (when owner-block
      (when owner-block
        (dropdown-editor-menuitem
        (dropdown-editor-menuitem
-        {:id :remove-property :icon :square-x :title "Delete property" :desc "" :disabled? false
-         :item-props {:class "opacity-60 focus:opacity-100 focus:!text-red-rx-09"
+        {:id :remove-property :icon :x :title "Remove property" :desc "" :disabled? false
+         :item-props {:class "opacity-60 focus:!text-red-rx-09 focus:opacity-100"
                       :on-select (fn [^js e]
                       :on-select (fn [^js e]
                                    (util/stop e)
                                    (util/stop e)
                                    (-> (p/do!
                                    (-> (p/do!