mirror of
https://github.com/logseq/logseq.git
synced 2026-05-27 14:14:24 +00:00
fix: property date type UX
This commit is contained in:
@@ -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)])))
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user