diff --git a/deps/db/src/logseq/db/frontend/property.cljs b/deps/db/src/logseq/db/frontend/property.cljs index bdac5dafe3..77289729b6 100644 --- a/deps/db/src/logseq/db/frontend/property.cljs +++ b/deps/db/src/logseq/db/frontend/property.cljs @@ -390,6 +390,10 @@ {:title "Reschedule property" :schema {:type :property :hide? true}} + :logseq.task/recur-status-property + {:title "Recur status property" + :schema {:type :property + :hide? true}} ;; TODO: Add more props :Assignee, :Estimate, :Cycle, :Project diff --git a/deps/outliner/src/logseq/outliner/property.cljs b/deps/outliner/src/logseq/outliner/property.cljs index 9fc533e84d..99b0a10b0c 100644 --- a/deps/outliner/src/logseq/outliner/property.cljs +++ b/deps/outliner/src/logseq/outliner/property.cljs @@ -448,6 +448,16 @@ :all-classes all-classes ; block own classes + parent classes :classes-properties all-properties})) +(defn ^:api get-block-full-properties + "Get block's full properties including its own and classes' properties" + [db eid] + (let [block (d/entity db eid)] + (->> + (concat + (map (fn [ident] (d/entity db ident)) (keys (:block/properties block))) + (:classes-properties (get-block-classes-properties db eid))) + (common-util/distinct-by :db/id)))) + (defn- property-with-position? [db property-id block position] (let [property (d/entity db property-id) diff --git a/src/main/frontend/components/property/value.cljs b/src/main/frontend/components/property/value.cljs index ff432afaa3..6ebeead7ab 100644 --- a/src/main/frontend/components/property/value.cljs +++ b/src/main/frontend/components/property/value.cljs @@ -228,43 +228,48 @@ (property-value block (db/entity :logseq.task/repeated?) (assoc opts :on-checked-change (fn [value] - (db-property-handler/set-block-property! (:db/id block) - :logseq.task/reschedule-property - (if value (:db/id property) nil)))))] + (if value + (db-property-handler/set-block-property! (:db/id block) + :logseq.task/reschedule-property + (:db/id property)) + (db-property-handler/remove-block-property! (:db/id block) + :logseq.task/reschedule-property)))))] [:div "Set as repeated task"]]] [:div.flex.flex-row.gap-2 [:div.flex.text-muted-foreground.mr-4 "Every"] - ;; recur frequency + ;; recur frequency [:div.w-6 (property-value block (db/entity :logseq.task/recur-frequency) opts)] - ;; recur unit + ;; recur unit [:div.w-20 (property-value block (db/entity :logseq.task/recur-unit) opts)]] - [:div.flex.flex-col.gap-2 - [:div.text-muted-foreground - "When"] - [:div.flex.flex-col.gap-1 - [:div.flex.flex-row.gap-2 - ;; property select - "Status" - - [:div.text-muted-foreground - "is"] - - ;; value select - "Done"] - + (let [properties (->> + (outliner-property/get-block-full-properties (db/get-db) (:db/id block)) + (filter (fn [property] + (and (not (ldb/built-in? property)) + (>= (count (:property/closed-values property)) 2)))) + (concat [(db/entity :logseq.task/status)]) + (util/distinct-by :db/id)) + property-id (:db/id (:logseq.task/recur-status-property block))] [:div.flex.flex-col.gap-2 - [:div.flex.flex-row.gap-2 - ;; property select - [:div.text-muted-foreground - "Update it to"] - - ;; value select - "Todo"]]]]])) + [:div.text-muted-foreground + "Reschedule on:"] + (shui/select + (cond-> + {:on-value-change (fn [v] + (db-property-handler/set-block-property! (:db/id block) + :logseq.task/recur-status-property + v))} + property-id + (assoc :default-value property-id)) + (shui/select-trigger + (shui/select-value {:placeholder "Select a property"})) + (shui/select-content + (map (fn [choice] + (shui/select-item {:value (:db/id choice)} (:block/title choice))) properties)))])])) (rum/defcs calendar-inner < rum/reactive db-mixins/query (rum/local (str "calendar-inner-" (js/Date.now)) ::identity) diff --git a/src/main/frontend/worker/commands.cljs b/src/main/frontend/worker/commands.cljs index 7acd3b853c..b72a23bfe9 100644 --- a/src/main/frontend/worker/commands.cljs +++ b/src/main/frontend/worker/commands.cljs @@ -16,41 +16,80 @@ {:title "Repeated task" :entity-conditions [{:property :logseq.task/repeated? :value true}] - :tx-conditions [{:property :logseq.task/status - :value :logseq.task/status.done}] + :tx-conditions [{:property :status + :value :done}] :actions [[:reschedule] - [:set-property :logseq.task/status :logseq.task/status.todo]]}]])) + [:set-property :status :todo]]}]])) + +(defn- get-property + [entity property] + (if (= property :status) + (or + (:db/ident (:logseq.task/recur-status-property entity)) + :logseq.task/status) + property)) + +(defn- get-value + [entity property value] + (cond + (and (= property :status) (= value :done)) + (or + (let [p (:logseq.task/recur-status-property entity) + choices (:property/closed-values p) + checkbox? (= :checkbox (get-in p [:block/schema :type]))] + (if checkbox? + true + (some (fn [choice] + (when (:logseq.property/choice-checkbox-state choice) + (:db/id choice))) choices))) + :logseq.task/status.done) + (and (= property :status) (= value :todo)) + (or + (let [p (:logseq.task/recur-status-property entity) + choices (:property/closed-values p) + checkbox? (= :checkbox (get-in p [:block/schema :type]))] + (if checkbox? + false + (some (fn [choice] + (when (false? (:logseq.property/choice-checkbox-state choice)) + (:db/id choice))) choices))) + :logseq.task/status.todo) + :else + value)) (defn sastify-condition? "Whether entity or updated datoms satisfy the `condition`" [db entity {:keys [property value]} datoms] - (when-let [property-entity (d/entity db property)] - (let [value-matches? (fn [datom-value] - (let [ref? (contains? db-property-type/all-ref-property-types (:type (:block/schema property-entity))) - db-value (cond - ;; entity-conditions - (nil? datom-value) - (get entity property) - ;; tx-conditions - ref? - (d/entity db datom-value) - :else - datom-value)] - (cond - (qualified-keyword? value) - (and (map? db-value) (= value (:db/ident db-value))) + (let [property' (get-property entity property) + value (get-value entity property value)] + (when-let [property-entity (d/entity db property')] + (let [value-matches? (fn [datom-value] + (let [ref? (contains? db-property-type/all-ref-property-types (:type (:block/schema property-entity))) + db-value (cond + ;; entity-conditions + (nil? datom-value) + (get entity property') + ;; tx-conditions + ref? + (d/entity db datom-value) + :else + datom-value)] + (cond + (qualified-keyword? value) + (and (map? db-value) (= value (:db/ident db-value))) - ref? - (or - (and (uuid? value) (= (:block/uuid db-value) value)) - (= value (db-property/property-value-content db-value))) + ref? + (or + (and (uuid? value) (= (:block/uuid db-value) value)) + (= value (db-property/property-value-content db-value)) + (= value (:db/id db-value))) - :else - (= db-value value))))] - (if (seq datoms) - (some (fn [d] (and (value-matches? (:v d)) (:added d))) - (filter (fn [d] (= property (:a d))) datoms)) - (value-matches? nil))))) + :else + (= db-value value))))] + (if (seq datoms) + (some (fn [d] (and (value-matches? (:v d)) (:added d))) + (filter (fn [d] (= property' (:a d))) datoms)) + (value-matches? nil)))))) (defmulti handle-command (fn [action-id & _others] action-id)) @@ -79,7 +118,9 @@ (:tx-data create-journal-page)))))) (defmethod handle-command :set-property [_ _db entity property value] - [[:db/add (:db/id entity) property value]]) + (let [property' (get-property entity property) + value' (get-value entity property value)] + [[:db/add (:db/id entity) property' value']])) (defn execute-command "Build tx-data" diff --git a/src/main/frontend/worker/db/migrate.cljs b/src/main/frontend/worker/db/migrate.cljs index 2c516a95a2..b8183a5a21 100644 --- a/src/main/frontend/worker/db/migrate.cljs +++ b/src/main/frontend/worker/db/migrate.cljs @@ -534,7 +534,8 @@ [50 {:properties [:logseq.user/name :logseq.user/email :logseq.user/avatar]}] [51 {:classes [:logseq.class/Property :logseq.class/Tag :logseq.class/Page :logseq.class/Whiteboard]}] [52 {:fix replace-block-type-with-tags}] - [53 {:properties [:logseq.task/scheduled :logseq.task/recur-frequency :logseq.task/recur-unit :logseq.task/repeated? :logseq.task/reschedule-property] + [53 {:properties [:logseq.task/scheduled :logseq.task/recur-frequency :logseq.task/recur-unit :logseq.task/repeated? + :logseq.task/reschedule-property :logseq.task/recur-status-property] :fix add-scheduled-to-task}] [54 {:properties [:logseq.property/choice-checkbox-state :logseq.property/checkbox-display-properties]}]])