From cc769225f9cbbdcd2fd5790c62f37814326ffcb9 Mon Sep 17 00:00:00 2001 From: Tienson Qin Date: Mon, 3 Jul 2023 17:53:23 +0800 Subject: [PATCH] fix: property date type UX --- src/main/frontend/components/property.cljs | 137 ++++++++++++--------- src/main/frontend/db/model.cljs | 19 ++- src/main/frontend/db/react.cljs | 9 +- src/main/frontend/handler/property.cljs | 49 ++++---- src/main/frontend/search.cljs | 5 +- 5 files changed, 127 insertions(+), 92 deletions(-) diff --git a/src/main/frontend/components/property.cljs b/src/main/frontend/components/property.cljs index ce84af8353..0a88fd637e 100644 --- a/src/main/frontend/components/property.cljs +++ b/src/main/frontend/components/property.cljs @@ -16,7 +16,9 @@ [frontend.components.search.highlight :as highlight] [frontend.components.svg :as svg] [frontend.modules.shortcut.core :as shortcut] - [medley.core :as medley])) + [medley.core :as medley] + [cljs-time.coerce :as tc] + [frontend.date :as date])) (rum/defcs property-config < rum/static @@ -86,21 +88,67 @@ (defn- exit-edit-property [*property-key *property-value] - (reset! *property-key nil) - (reset! *property-value nil) + (when *property-key (reset! *property-key nil)) + (when *property-value (reset! *property-value nil)) (property-handler/set-editing-new-property! nil)) (defn- add-property! [block *property-key *property-value] (let [repo (state/get-current-repo)] - (when (and @*property-key @*property-value) + (when @*property-key (property-handler/add-property! repo block @*property-key @*property-value)) (exit-edit-property *property-key *property-value))) -(rum/defcs property-key-input < rum/reactive +(rum/defc date-picker + [block property value] + (let [value' (when-not (string/blank? value) + (tc/to-local-date value)) + text (if value' + (str value') + "Pick a date")] + (ui/button + text + :icon "calendar" + :intent "border-link" + :on-click (fn [] + (state/set-modal! + #(ui/datepicker value' {:on-change (fn [_e date] + (let [repo (state/get-current-repo)] + (property-handler/add-property! repo block + (:block/name property) + date) + (exit-edit-property nil nil) + (state/close-modal!)))})))))) + +(rum/defc property-scalar-value + [block property value {:keys [editor-on-click inline-text]}] + (let [property (when property + (if (map? property) + property + (db/entity [:block/name (util/page-name-sanity-lc property)])))] + (case (:type (:block/schema property)) + :date + (date-picker block property value) + + :checkbox + (ui/checkbox {:checked value + :on-change (fn [_e] + (let [repo (state/get-current-repo)] + (property-handler/add-property! repo block + (:block/name property) + (boolean (not value))) + (exit-edit-property nil nil)))}) + ;; :object + ;; default and others + [:div.flex.flex-1 + (when editor-on-click {:on-click editor-on-click}) + (when-not (string/blank? (str value)) + (inline-text {} :markdown (str value)))]))) + +(rum/defcs property-input < rum/reactive (rum/local true ::search?) shortcut/disable-all-shortcuts - [state entity *property-key *property-value] + [state entity *property-key *property-value block-components-m] (let [*search? (::search? state) entity-properties (->> (keys (:block/properties entity)) (map #(:block/original-name (db/entity [:block/uuid %]))) @@ -124,23 +172,27 @@ (list "Tab" "Enter") (do - (util/stop e) + (when (= (util/ekey e) "Tab") + (util/stop e)) + (reset! *property-key (util/evalue e)) (reset! *search? false) (.focus (js/document.getElementById "add-property-value"))) nil))}] - [:input#add-property-value.form-input.simple-input.block.col-span-1.focus:outline-none - {:placeholder "Value" - :on-change #(reset! *property-value (util/evalue %)) - :on-key-down (fn [e] - (case (util/ekey e) - "Enter" - (do - (add-property! entity *property-key *property-value) - (reset! *search? false)) + (property-scalar-value entity @*property-key @*property-value {:editor-on-click (fn [e] + (case (util/ekey e) + "Enter" + (do + (add-property! entity *property-key *property-value) + (reset! *search? false)) - nil))}] + nil)) + :inline-text (:inline-text block-components-m)}) + ;; [:input#add-property-value.form-input.simple-input.block.col-span-1.focus:outline-none + ;; {:placeholder "Value" + ;; :on-change #(reset! *property-value (util/evalue %)) + ;; :on-key-down }] [:a.close {:on-mouse-down #(exit-edit-property *property-key *property-value)} svg/close]] @@ -163,14 +215,15 @@ state :on-hide (fn [] (property-handler/set-editing-new-property! nil)) - :node (js/document.getElementById "edit-new-property")))) - [state repo block edit-input-id properties new-property?] + :node (js/document.getElementById "edit-new-property") + :outside? false))) + [state repo block edit-input-id properties new-property? block-components-m] (let [*property-key (::property-key state) *property-value (::property-value state)] (cond new-property? [:div#edit-new-property - (property-key-input block *property-key *property-value)] + (property-input block *property-key *property-value block-components-m)] (seq properties) [:a {:title "Add another property" @@ -180,8 +233,7 @@ (reset! *property-value nil))} [:div.block {:style {:height 20 :width 20}} - [:a.add-button-link.block {:title "Add another value" - :style {:margin-left -4}} + [:a.add-button-link.block {:style {:margin-left -4}} (ui/icon "circle-plus")]]]))) (rum/defcs property-key < (rum/local false ::show-close?) @@ -203,28 +255,6 @@ (property-handler/remove-property! repo block (:block/uuid property)))} (ui/icon "x")]])])) -(rum/defc property-scalar-value - [block property value {:keys [editor-on-click inline-text]}] - (case (:type (:block/schema property)) - :date - (ui/button - (or value "Empty") - :icon :calendar) - - :checkbox - (ui/checkbox {:checked value - :on-change (fn [_e] - (let [repo (state/get-current-repo)] - (property-handler/add-property! repo block - (:block/name property) - (boolean (not value)))))}) - ;; :object - ;; default and others - [:div.flex.flex-1 - (when editor-on-click {:on-click editor-on-click}) - (when-not (string/blank? (str value)) - (inline-text {} :markdown (str value)))])) - (rum/defcs multiple-value-item < (rum/local false ::show-close?) [state entity property item dom-id' editor-id' {:keys [edit-fn page-cp inline-text]}] (let [*show-close? (::show-close? state) @@ -232,15 +262,8 @@ block (when object? (db/pull [:block/uuid item]))] [:div.flex.flex-1.flex-row {:on-mouse-over #(reset! *show-close? true) :on-mouse-out #(reset! *show-close? false)} - [:div.flex.flex-1.property-value-content - {:id dom-id' - :on-click (fn [] - ;; (edit-fn editor-id' dom-id' item) - )} - (if block - ;; TODO: page/block - (str block) - (inline-text {} :markdown (str item)))] + (property-scalar-value entity property item {:editor-on-click edit-fn + :inline-text inline-text}) (when @*show-close? [:a.close.fade-in {:title "Delete this value" @@ -278,7 +301,7 @@ v' (if (seq v') v' [""]) editor-id' (str editor-id (count v')) new-editing? (state/sub [:editor/editing? editor-id'])] - [:div.flex.flex-1.flex-col + [:div.flex.flex-1.flex-col.pl-1 [:div.flex.flex-1.flex-col (for [[idx item] (medley/indexed v')] (let [dom-id' (str dom-id "-" idx) @@ -302,7 +325,7 @@ [:div.block {:style {:height 20 :width 20}} [:a.add-button-link.block {:title "Add another value" - :style {:margin-left -4}} + :style {:margin-left -8}} (ui/icon "circle-plus")]]]]))] (when new-editing? (editor-box editor-args editor-id' {}))]) @@ -328,7 +351,7 @@ (for [[prop-uuid-or-built-in-prop v] properties] (if (uuid? prop-uuid-or-built-in-prop) (when-let [property (db/sub-block (:db/id (db/entity [:block/uuid prop-uuid-or-built-in-prop])))] - [:div.grid.grid-cols-4.gap-1 + [:div.grid.grid-cols-4.gap-1.items-center [:div.property-key.col-span-1 (property-key block property)] [:div.property-value.col-span-3 @@ -338,4 +361,4 @@ [:div [:a.mr-2 (str prop-uuid-or-built-in-prop)] [:span v]]))]) - (new-property repo block edit-input-id properties new-property?)]))) + (new-property repo block edit-input-id properties new-property? block-components-m)]))) diff --git a/src/main/frontend/db/model.cljs b/src/main/frontend/db/model.cljs index edb111e1a5..aff1ddb5da 100644 --- a/src/main/frontend/db/model.cljs +++ b/src/main/frontend/db/model.cljs @@ -1160,7 +1160,7 @@ independent of format as format specific heading characters are stripped" [(get m :template) e])) (into {})))) -(defn get-all-properties +(defn file-based-get-all-properties [] (let [db (conn/get-db) properties (d/q @@ -1172,12 +1172,21 @@ independent of format as format specific heading characters are stripped" (->> (map keys properties) (apply concat) distinct - (map (fn [k] - (if (uuid? k) - (:block/original-name (d/entity db [:block/uuid k])) - k))) sort))) +(defn db-based-get-all-properties + [] + (let [db (conn/get-db) + ids (->> (d/datoms db :aevt :block/schema) + (map :e))] + (map #(:block/original-name (db-utils/entity %)) ids))) + +(defn get-all-properties + [] + (if (react/db-graph?) + (db-based-get-all-properties) + (file-based-get-all-properties))) + (defn- property-value-for-refs-and-text "Given a property value's refs and full text, determines the value to autocomplete" diff --git a/src/main/frontend/db/react.cljs b/src/main/frontend/db/react.cljs index 463fb65126..ebc0891ce3 100644 --- a/src/main/frontend/db/react.cljs +++ b/src/main/frontend/db/react.cljs @@ -371,8 +371,7 @@ (recur)) chan)) -(comment - (defn db-graph? - "Whether the current graph is db-only" - [] - (= "db" (sub-key-value :db/type)))) +(defn db-graph? + "Whether the current graph is db-only" + [] + (= "db" (sub-key-value :db/type))) diff --git a/src/main/frontend/handler/property.cljs b/src/main/frontend/handler/property.cljs index e6a8874886..3f3df902b5 100644 --- a/src/main/frontend/handler/property.cljs +++ b/src/main/frontend/handler/property.cljs @@ -27,7 +27,9 @@ (def builtin-schema-types {:default string? ; default, might be mixed with refs, tags :number number? - :date inst? + :date [:fn + {:error/message "should be a date"} + date-str?] :checkbox boolean? :url [:fn {:error/message "should be a URL"} @@ -70,7 +72,8 @@ (defn convert-property-input-string [schema-type v-str] - (if (string? v-str) + (if (boolean? v-str) + v-str (case schema-type :default v-str @@ -85,34 +88,32 @@ (uuid v-str) :date - (js/Date. v-str) + (js/Date. v-str) ; inst :url - v-str) - v-str)) + v-str))) (defn add-property! [repo block k-name v] - (prn :debug " add-property! " {:k k-name - :v v}) - (let [property (db/pull repo '[*] [:block/name (gp-util/page-name-sanity-lc k-name)]) - property-uuid (or (:block/uuid property) (random-uuid)) - {:keys [type cardinality]} (:block/schema property) - multiple-values? (= cardinality :many) - infer-schema (when-not type (infer-schema-from-input-string v)) - property-type (or type infer-schema :default) - schema (get builtin-schema-types property-type) - properties (:block/properties block) - value (get properties property-uuid)] - (when-not (and multiple-values? (string/blank? (str v))) - (let [v* (try - (convert-property-input-string property-type v) - (catch :default e - (notification/show! (str e) :error false) - nil))] - (when (some? v*) + (when v + (let [property (db/pull repo '[*] [:block/name (gp-util/page-name-sanity-lc k-name)]) + property-uuid (or (:block/uuid property) (random-uuid)) + {:keys [type cardinality]} (:block/schema property) + multiple-values? (= cardinality :many) + infer-schema (when-not type (infer-schema-from-input-string v)) + property-type (or type infer-schema :default) + schema (get builtin-schema-types property-type) + properties (:block/properties block) + value (get properties property-uuid)] + (when-not (and multiple-values? (string/blank? (str v))) + (let [v* (try + (convert-property-input-string property-type v) + (catch :default e + (notification/show! (str e) :error false) + nil))] + (defonce debug-v v*) (when-not (contains? (if (set? value) value #{value}) v*) - (if-let [msg (me/humanize (mu/explain-data schema v))] + (if-let [msg (me/humanize (mu/explain-data schema v*))] (let [msg' (str "\"" k-name "\"" " " (if (coll? msg) (first msg) msg))] (notification/show! msg' :warning)) (do diff --git a/src/main/frontend/search.cljs b/src/main/frontend/search.cljs index ac970e820b..c6912ec2a7 100644 --- a/src/main/frontend/search.cljs +++ b/src/main/frontend/search.cljs @@ -186,7 +186,10 @@ (->> (db-model/get-all-properties) (remove (property-edit/hidden-properties)) ;; Complete full keyword except the ':' - (map #(subs (str %) 1)))) + (map (fn [property] + (if (keyword? property) + (subs (str property) 1) + property))))) (defn property-search ([q]