Merge branch 'feat/db' into refactor/boolean-not-ref-type

pull/11451/head
Tienson Qin 2024-08-03 04:48:54 +08:00
commit ea0a26e744
22 changed files with 193 additions and 341 deletions

View File

@ -150,23 +150,23 @@
:hide? true
:view-context :page
:public? true}}
:logseq.property/table-sorting {:schema
:logseq.property.table/sorting {:schema
{:type :coll
:hide? true
:public? false}}
:logseq.property/table-filters {:schema
:logseq.property.table/filters {:schema
{:type :coll
:hide? true
:public? false}}
:logseq.property/table-hidden-columns {:schema
:logseq.property.table/hidden-columns {:schema
{:type :keyword
:cardinality :many
:hide? true
:public? false}}
:logseq.property/table-ordered-columns {:schema
:logseq.property.table/ordered-columns {:schema
{:type :coll
:hide? true
:public? false}}
@ -201,7 +201,7 @@
(def logseq-property-namespaces
#{"logseq.property" "logseq.property.tldraw" "logseq.property.pdf" "logseq.task"
"logseq.property.linked-references" "logseq.property.asset"})
"logseq.property.linked-references" "logseq.property.asset" "logseq.property.table"})
(defn logseq-property?
"Determines if keyword is a logseq property"

View File

@ -2,7 +2,7 @@
"Main datascript schemas for the Logseq app"
(:require [clojure.set :as set]))
(def version 10)
(def version 11)
;; A page is a special block, a page can corresponds to multiple files with the same ":block/name".
(def ^:large-vars/data-var schema
{:db/ident {:db/unique :db.unique/identity}

View File

@ -107,7 +107,7 @@
(assoc :db/valueType :db.type/ref))))))
(defn build-new-class
"Build a standard new class so that it is is consistent across contexts"
"Build a standard new class so that it is consistent across contexts"
[block]
{:pre [(qualified-keyword? (:db/ident block))]}
(block-with-timestamps

View File

@ -11,7 +11,6 @@
type logseq doesnt' support yet
* schema.org assumes no cardinality. For now, only :node properties are given a :cardinality :many"
(:require [logseq.outliner.cli :as outliner-cli]
[logseq.common.util :as common-util]
[logseq.db.frontend.property :as db-property]
[clojure.string :as string]
[clojure.edn :as edn]
@ -77,8 +76,8 @@
{"schema:Integer" :number
"schema:Float" :number
"schema:Number" :number
"schema:Text_Class" :default
"schema:URL_Class" :url
"schema:Text" :default
"schema:URL" :url
"schema:Boolean" :checkbox
"schema:Date" :date})
@ -158,11 +157,11 @@
(defn- get-vector-conflicts
"Given a seq of tuples returns a seq of tuples that conflict i.e. their first element
has a case insensitive conflict/duplicate with another. An example conflict:
[[\"schema:businessFunction\" :property] [\"schema:BusinessFunction\" :class]]"
has a case sensitive conflict/duplicate with another. An example conflict:
[[\"schema:status\" :property] [\"schema:status\" :node]]"
[tuples-seq]
(->> tuples-seq
(group-by (comp common-util/page-name-sanity-lc first))
(group-by first)
(filter #(> (count (val %)) 1))
vals))
@ -190,7 +189,8 @@
(if verbose
(println "Renaming the following properties because they have names that conflict with Logseq's built in pages"
(keys renamed-properties) "\n")
(println "Renaming" (count renamed-properties) "properties due to page name conflicts"))
(when (pos? (count renamed-properties))
(println "Renaming" (count renamed-properties) "properties due to page name conflicts")))
renamed-properties))
(defn- detect-id-conflicts-and-get-renamed-classes
@ -219,7 +219,8 @@
(if verbose
(println "Renaming the following classes because they have property names that conflict with Logseq's case insensitive :block/name:"
(keys renamed-classes) "\n")
(println "Renaming" (count renamed-classes) "classes due to page name conflicts"))
(when (pos? (count renamed-classes))
(println "Renaming" (count renamed-classes) "classes due to page name conflicts")))
renamed-classes))
(defn- get-all-properties [schema-data {:keys [verbose]}]
@ -308,7 +309,7 @@
select-class-ids
(if (:subset options)
["schema:Person" "schema:CreativeWorkSeries" "schema:Organization"
"schema:Movie" "schema:CreativeWork" "schema:Thing"]
"schema:Movie" "schema:CreativeWork" "schema:Thing" "schema:Comment"]
(keys class-map))
class-to-properties (get-class-to-properties select-class-ids all-properties)
select-properties (set (mapcat val class-to-properties))

View File

@ -384,7 +384,7 @@ button.menu:focus {
.menu-link {
@apply text-popover-foreground/75 select-none hover:text-popover-foreground/100;
@apply text-sm px-2 py-1.5 mx-1 hover:rounded transition-opacity duration-150;
@apply text-sm px-2 py-1.5 hover:rounded transition-opacity duration-150;
}
.menu-separator {

View File

@ -204,6 +204,24 @@
&.as-heading {
@apply flex flex-1;
h1& {
.ui__icon.ti svg {
@apply w-8 h-7;
}
}
h2& {
.ui__icon.ti svg {
@apply w-7 h-6;
}
}
h3& {
.ui__icon.ti svg {
@apply w-5 h-5;
}
}
}
&:has(.dsl-query), &:has(.embed-page) {

View File

@ -545,7 +545,7 @@
{:drop (fn [_e files]
(when-let [id (state/get-edit-input-id)]
(let [format (:block/format (state/get-edit-block))]
(editor-handler/upload-asset id files format editor-handler/*asset-uploading? true))))})
(editor-handler/upload-asset! id files format editor-handler/*asset-uploading? true))))})
(common-handler/listen-to-scroll! element)
(when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar
(set! (.. element -scrollTop) 0)))
@ -555,10 +555,10 @@
(dnd/unsubscribe! el :upload-files))
state)}
[{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
(not config/publishing?)
(= :home route-name))
(not config/publishing?)
(= :home route-name))
margin-less-pages? (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)]
[:div#main-container.cp__sidebar-main-layout.flex-1.flex
{:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}

View File

@ -482,124 +482,6 @@
(util/stop e)
(on-submit command @input-value pos)))])))))
(rum/defc absolute-modal < rum/static
[cp modal-name set-default-width? {:keys [top left rect]}]
(let [MAX-HEIGHT 700
MAX-HEIGHT' 600
MAX-WIDTH 600
SM-MAX-WIDTH 300
Y-BOUNDARY-HEIGHT 150
vw-width js/window.innerWidth
vw-height js/window.innerHeight
vw-max-width (- vw-width (:left rect))
vw-max-height (- vw-height (:top rect))
vw-max-height' (:top rect)
sm? (< vw-width 415)
max-height (min (- vw-max-height 20) MAX-HEIGHT)
max-height' (min (- vw-max-height' 70) MAX-HEIGHT')
max-width (if sm? SM-MAX-WIDTH (min (max 400 (/ vw-max-width 2)) MAX-WIDTH))
offset-top 24
to-max-height (cond-> (if (and (seq rect) (> vw-height max-height))
(let [delta-height (- vw-height (+ (:top rect) top offset-top))]
(if (< delta-height max-height)
(- (max (* 2 offset-top) delta-height) 16)
max-height))
max-height)
(= modal-name "commands")
(min 500))
right-sidebar? (:ui/sidebar-open? @state/state)
editing-key (state/get-edit-input-id)
*el (rum/use-ref nil)
y-overflow-vh? (or (< to-max-height Y-BOUNDARY-HEIGHT)
(> (- max-height' to-max-height) Y-BOUNDARY-HEIGHT))
to-max-height (if y-overflow-vh? max-height' to-max-height)
pos-rect (when (and (seq rect) editing-key)
(:rect (cursor/get-caret-pos (state/get-input))))
y-diff (when pos-rect (- (:height pos-rect) (:height rect)))
style (merge
{:top (+ top offset-top (if (int? y-diff) y-diff 0))
:max-height to-max-height
:max-width 700
;; TODO: auto responsive fixed size
:width "fit-content"
:z-index 11}
(when set-default-width?
{:width max-width})
(if (<= vw-max-width (+ left (if set-default-width? max-width 500)))
{:right 0}
{:left 0}))]
(rum/use-effect!
(fn []
(when-let [^js/HTMLElement cnt
(and right-sidebar? editing-key
(js/document.querySelector "#main-content-container"))]
(when (.contains cnt (js/document.querySelector (str "#" editing-key)))
(let [el (rum/deref *el)
ofx (- (.-scrollWidth cnt) (.-clientWidth cnt))]
(when (> ofx 0)
(set! (.-transform (.-style el))
(util/format "translate(-%spx, %s)" (+ ofx 20) (if y-overflow-vh? "calc(-100% - 2rem)" 0))))))))
[right-sidebar? editing-key y-overflow-vh?])
;; HACK: close when click outside for classic editing models (popup)
(rum/use-effect!
(fn []
(let [^js cnt js/document.body
handle (fn [^js e]
(when-not (some->> (.-target e) (.contains (rum/deref *el)))
(state/clear-editor-action!)))]
(.addEventListener cnt "click" handle false)
#(.removeEventListener cnt "click" handle)))
[])
[:div.absolute.rounded-md.shadow-lg.absolute-modal
{:ref *el
:data-modal-name modal-name
:class (if y-overflow-vh? "is-overflow-vh-y" "")
:on-pointer-down (fn [e]
(.stopPropagation e))
:on-key-down (fn [^js e]
(case (.-key e)
"Escape"
(do (state/clear-editor-action!)
(some-> (state/get-input)
(.focus)))
:dune)
(util/stop-propagation e))
:style style}
cp]))
(rum/defc transition-cp < rum/reactive
[cp modal-name set-default-width?]
(when-let [pos (:pos (state/sub :editor/action-data))]
(ui/css-transition
{:class-names "fade"
:timeout {:enter 500
:exit 300}}
(absolute-modal cp modal-name set-default-width? pos))))
(rum/defc image-uploader < rum/reactive
[id format]
[:div.image-uploader
[:input
{:id "upload-file"
:type "file"
:on-change (fn [e]
(let [files (.-files (.-target e))]
(editor-handler/upload-asset id files format editor-handler/*asset-uploading? false)))
:hidden true}]
#_:clj-kondo/ignore
(when-let [uploading? (util/react editor-handler/*asset-uploading?)]
(let [processing (util/react editor-handler/*asset-uploading-process)]
(transition-cp
[:div.flex.flex-row.align-center.rounded-md.shadow-sm.bg-base-2.px-1.py-1
(ui/loading
(util/format "Uploading %s%" (util/format "%2d" processing)))]
"upload-file"
false)))])
(defn- set-up-key-down!
[state format]
(mixins/on-key-down
@ -694,146 +576,98 @@
[:span {:id (str "mock-text_" idx)
:key idx} c])))])
(rum/defc animated-modal < rum/reactive
[modal-name component set-default-width?]
(when-let [pos (:pos (state/get-editor-action-data))]
(ui/css-transition
{:key modal-name
:class-names {:enter "origin-top-left opacity-0 transform scale-95"
:enter-done "origin-top-left transition opacity-100 transform scale-100"
:exit "origin-top-left transition opacity-0 transform scale-95"}
:timeout {:enter 0
:exit 150}}
(fn [_]
(absolute-modal
component
modal-name
set-default-width?
pos)))))
(defn- exist-editor-commands-popup?
[]
(some->> (shui-popup/get-popups)
(some #(some-> % (:id) (str) (string/starts-with? ":editor.commands")))))
;; TODO: [WIP]
(rum/defc shui-modals
(defn- open-editor-popup!
[id content opts]
(let [{:keys [left top rect]} (cursor/get-caret-pos (state/get-input))
pos [(+ left (:left rect) -20) (+ top (:top rect) 20)]
{:keys [root-props content-props]} opts]
(shui/popup-show!
pos content
(merge
{:id (keyword :editor.commands id)
:align :start
:root-props (merge {:onOpenChange #(when-not % (state/clear-editor-action!))} root-props)
:content-props (merge {:onOpenAutoFocus #(.preventDefault %)
:onCloseAutoFocus #(.preventDefault %)
:data-editor-popup-ref (name id)} content-props)
:force-popover? true}
(dissoc opts :root-props :content-props)))))
(rum/defc shui-editor-popups
[id format action _data]
(rum/use-effect!
(fn []
(let [{:keys [left top rect]} (cursor/get-caret-pos (state/get-input))
pos [(+ left (:left rect) -20) (+ top (:top rect) 20)]]
(let [pid (case action
:commands
(shui/popup-show! pos
(commands id format)
{:id :editor.commands/commands
:align :start
:root-props {:onOpenChange
#(when-not %
(when (= :commands (state/get-editor-action))
(state/clear-editor-action!)))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:onCloseAutoFocus #(.preventDefault %)
:withoutAnimation true
:data-editor-popup-ref "commands"}
:force-popover? true})
(let [pid (case action
:commands
(open-editor-popup! :commands
(commands id format)
{:content-props {:withoutAnimation false}})
:block-commands
(shui/popup-show! pos
(block-commands id format)
{:id :editor.commands/block-commands
:align :start
:root-props {:onOpenChange
#(when-not %
(when (= :block-commands (state/get-editor-action))
(state/clear-editor-action!)))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:onCloseAutoFocus #(.preventDefault %)
:withoutAnimation true
:data-editor-popup-ref "commands"}
:force-popover? true})
:block-commands
(open-editor-popup! :block-commands
(block-commands id format)
{:content-props {:withoutAnimation true}})
(:block-search :page-search :page-search-hashtag)
(shui/popup-show!
pos (if (= :block-search action)
(block-search id format)
(page-search id format))
{:id :editor.commands/block-search
:align :start
:root-props {:onOpenChange
#(when-not %
(when (contains?
#{:block-search :page-search :page-search-hashtag}
(state/get-editor-action))
(state/clear-editor-action!)))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:onCloseAutoFocus #(.preventDefault %)
:data-editor-popup-ref (name action)}
:force-popover? true})
(:block-search :page-search :page-search-hashtag)
(open-editor-popup! action
(if (= :block-search action)
(block-search id format)
(page-search id format))
{:root-props {:onOpenChange
#(when-not %
(when (contains?
#{:block-search :page-search :page-search-hashtag}
(state/get-editor-action))
(state/clear-editor-action!)))}})
:datepicker
(shui/popup-show!
pos (datetime-comp/date-picker id format nil)
{:id :editor.commands/datepicker
:align :start
:root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:data-editor-popup-ref "datepicker"}
:force-popover? true})
:datepicker
(open-editor-popup! :datepicker
(datetime-comp/date-picker id format nil) {})
:input
(shui/popup-show!
pos (input id
(fn [command m]
(editor-handler/handle-command-input command id format m))
(fn []
(editor-handler/handle-command-input-close id)))
{:id :editor.commands/input
:align :start
:root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:onCloseAutoFocus #(.preventDefault %)
:data-editor-popup-ref "input"}})
:input
(open-editor-popup! :input
(input id
(fn [command m]
(editor-handler/handle-command-input command id format m))
(fn []
(editor-handler/handle-command-input-close id))) {})
:select-code-block-mode
(shui/popup-show!
pos (code-block-mode-picker id format)
{:id :editor.commands/code-block-mode-picker
:align :start
:root-props {:onOpenChange #(when-not % (state/clear-editor-action!))}
:content-props {:onOpenAutoFocus #(.preventDefault %)
:data-editor-popup-ref "code-block-mode-picker"}
:force-popover? true})
:select-code-block-mode
(open-editor-popup! :code-block-mode-picker
(code-block-mode-picker id format) {})
;; TODO: try remove local model state
false)]
#(when pid
(shui/popup-hide! pid)))))
:template-search
(open-editor-popup! :template-search
(template-search id format) {})
(:property-search :property-value-search)
(open-editor-popup! action
(if (= :property-search action)
(property-search id) (property-value-search id))
{})
:zotero
(open-editor-popup! :zotero
(zotero/zotero-search id) {})
;; TODO: try remove local model state
false)]
#(when pid
(shui/popup-hide! pid))))
[action])
[:<>])
(rum/defc modals < rum/reactive
"React to atom changes, find and render the correct modal"
(rum/defc command-popups <
rum/reactive
"React to atom changes, find and render the correct popup"
[id format]
(let [action (state/sub :editor/action)]
[:<>
(shui-modals id format action nil)
(cond
(= :template-search action)
(animated-modal "template-search" (template-search id format) true)
(= :property-search action)
(animated-modal "property-search" (property-search id) true)
(= :property-value-search action)
(animated-modal "property-value-search" (property-value-search id) true)
(= :zotero action)
(animated-modal "zotero-search" (zotero/zotero-search id) false)
:else
nil)]))
(shui-editor-popups id format action nil)))
(defn- editor-on-hide
[state value* type e]
@ -916,9 +750,5 @@
[:div.editor-inner.flex.flex-1 {:class (if block "block-editor" "non-block-editor")}
(ui/ls-textarea opts)
(mock-textarea content)
(modals id format)
(when format
(image-uploader id format))]))
(command-popups id format)]))

View File

@ -73,7 +73,7 @@ pre {
.ui__popover-content, .ui__dropdown-menu-content {
&[data-editor-popup-ref] {
@apply p-1 w-72;
@apply p-1.5 w-72;
&[data-side=top] {
position: relative;
@ -82,7 +82,7 @@ pre {
}
&[data-editor-popup-ref=commands] {
@apply px-1 py-1 w-72;
@apply w-72;
&[data-side=top] {
max-height: min(calc(var(--radix-popover-content-available-height) - 60px), 460px);
@ -96,7 +96,7 @@ pre {
&[data-editor-popup-ref=page-search],
&[data-editor-popup-ref=block-search],
&[data-editor-popup-ref=page-search-hashtag] {
@apply px-1 py-1 w-full sm:w-128;
@apply w-full sm:w-128;
}
&[data-editor-popup-ref=datepicker] {

View File

@ -40,7 +40,7 @@
(when class
(ui/checkbox {:class class
:style {:margin-right 5}
:value checked?
:checked checked?
:on-pointer-down (fn [e]
(util/stop-propagation e))
:on-change (fn [_e]

View File

@ -70,14 +70,16 @@
(if (and (= :default (get-in property [:block/schema :type]))
(not (db-property/many? property)))
(p/let [existing-value (get block (:db/ident property))
new-block-id (when-not existing-value (db/new-block-id))
_ (when-not existing-value
existing-value? (and (some? existing-value)
(not= (:db/ident existing-value) :logseq.property/empty-placeholder))
new-block-id (when-not existing-value? (db/new-block-id))
_ (when-not existing-value?
(db-property-handler/create-property-text-block!
(:db/id block)
(:db/id property)
value
{:new-block-id new-block-id}))]
(or existing-value (db/entity [:block/uuid new-block-id])))
(if existing-value? existing-value (db/entity [:block/uuid new-block-id])))
(p/let [new-block-id (db/new-block-id)
_ (db-property-handler/create-property-text-block!
(:db/id block)

View File

@ -16,27 +16,15 @@
.ui__dropdown-menu-content {
&.repos-list {
@apply px-2 pb-[210px] relative overflow-hidden;
@apply min-w-[280px] sm:max-w-[320px] max-h-[66vh];
&.no-repos {
@apply pb-[180px];
}
&[data-mode=db] {
@apply pb-[114px];
&.no-repos {
@apply pb-[109px];
}
}
@apply px-2 relative overflow-hidden;
@apply min-w-[280px] sm:max-w-[320px];
.ui__dropdown-menu-item {
@apply overflow-hidden overflow-ellipsis;
}
.cp__repos-list-wrap {
@apply max-h-96 overflow-scroll m-[-8px] px-2 pb-6;
@apply max-h-80 overflow-scroll mx-[-8px] px-2 pb-2;
}
}
}
@ -64,8 +52,7 @@
}
.cp__repos-quick-actions {
@apply absolute left-[1px] right-[1px] bottom-[1px] bg-gray-01 px-2 py-3 border-t
flex flex-col rounded-b overflow-hidden;
@apply -mx-2 bg-gray-01 px-2 pb-1.5 pt-3 border-t flex flex-col rounded-b overflow-hidden;
.ui__button {
@apply w-full !py-4 !justify-start opacity-70 font-medium hover:opacity-90

View File

@ -95,7 +95,7 @@
[block property]
(let [type (get-in property [:block/schema :type])
many? (= :db.cardinality/many (get property :db/cardinality))
ref-types (into db-property-type/value-ref-property-types #{:entity})
ref-types (into db-property-type/ref-property-types #{:entity})
number-type? (= :number type)
v (get block (:db/ident property))
v' (if many? v [v])
@ -871,13 +871,13 @@
(fn [sorting]
(set-sorting! sorting)
(p/let [entity (or entity (create-view!))]
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-sorting sorting)))
(property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/sorting sorting)))
:set-filters!
(fn [filters]
(let [filters (table-filters->persist-state filters)]
(set-filters! filters)
(p/let [entity (or entity (create-view!))]
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-filters filters))))
(property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/filters filters))))
:set-visible-columns!
(fn [columns]
(let [hidden-columns (vec (keep (fn [[column visible?]]
@ -885,24 +885,24 @@
column)) columns))]
(set-visible-columns! columns)
(p/let [entity (or entity (create-view!))]
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-hidden-columns hidden-columns))))
(property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/hidden-columns hidden-columns))))
:set-ordered-columns!
(fn [ordered-columns]
(let [ids (vec (remove #{:select} ordered-columns))]
(set-ordered-columns! ordered-columns)
(p/let [entity (or entity (create-view!))]
(property-handler/set-block-property! repo (:db/id entity) :logseq.property/table-ordered-columns ids))))}))
(property-handler/set-block-property! repo (:db/id entity) :logseq.property.table/ordered-columns ids))))}))
(rum/defc view-inner < rum/static
[view-entity {:keys [data set-data! columns add-new-object! create-view! title-key] :as option}]
(let [[input set-input!] (rum/use-state "")
sorting (:logseq.property/table-sorting view-entity)
sorting (:logseq.property.table/sorting view-entity)
[sorting set-sorting!] (rum/use-state (or sorting [{:id :block/updated-at, :asc? false}]))
filters (:logseq.property/table-filters view-entity)
filters (:logseq.property.table/filters view-entity)
[filters set-filters!] (rum/use-state (or filters []))
hidden-columns (:logseq.property/table-hidden-columns view-entity)
hidden-columns (:logseq.property.table/hidden-columns view-entity)
[visible-columns set-visible-columns!] (rum/use-state (zipmap hidden-columns (repeat false)))
ordered-columns (vec (concat [:select] (:logseq.property/table-ordered-columns view-entity)))
ordered-columns (vec (concat [:select] (:logseq.property.table/ordered-columns view-entity)))
[ordered-columns set-ordered-columns!] (rum/use-state ordered-columns)
{:keys [set-sorting! set-filters! set-visible-columns! set-ordered-columns!]}
(db-set-table-state! view-entity {:set-sorting! set-sorting!

View File

@ -1535,7 +1535,7 @@
(path/get-relative-path current-file-fpath file-path))
file-path))
(defn upload-asset
(defn upload-asset!
"Paste asset and insert link to current editing block"
[id ^js files format uploading? drop-or-paste?]
(let [repo (state/get-current-repo)]

View File

@ -56,7 +56,6 @@
[frontend.handler.user :as user-handler]
[frontend.handler.property.util :as pu]
[frontend.handler.db-based.property.util :as db-pu]
[frontend.handler.file-based.property.util :as property-util]
[frontend.handler.property :as property-handler]
[frontend.handler.file-based.nfs :as nfs-handler]
[frontend.handler.code :as code-handler]
@ -846,19 +845,6 @@
(defmethod handle :graph/save-db-to-disk [[_ _opts]]
(persist-db/export-current-graph! {:succ-notification? true}))
(defmethod handle :search/transact-data [[_ repo data]]
(let [file-based? (config/local-file-based-graph? repo)
data' (cond-> data
file-based?
;; remove built-in properties from content
(update :blocks-to-add
(fn [blocks]
(map #(update % :content
(fn [content]
(property-util/remove-built-in-properties (get % :format :markdown) content)))
blocks))))]
(search/transact-blocks! repo data')))
(defmethod handle :class/configure [[_ page]]
(shui/dialog-open!
#(vector :<>

View File

@ -220,7 +220,7 @@
files (.-files clipboard-data)]
(when-let [file (first files)]
(when-let [block (state/get-edit-block)]
(editor-handler/upload-asset id #js[file] (:block/format block)
(editor-handler/upload-asset! id #js[file] (:block/format block)
editor-handler/*asset-uploading? true)))
(util/stop e))))

View File

@ -252,10 +252,18 @@
(js/window.apis.addListener channel listener)))
(defn- normalize-plugin-metadata
[metadata]
(cond-> metadata
(not (string? (:author metadata)))
(assoc :author (or (get-in metadata [:author :name]) ""))))
(defn register-plugin
[plugin-metadata]
(when-let [pid (keyword (:id plugin-metadata))]
(swap! state/state update-in [:plugin/installed-plugins] assoc pid plugin-metadata)))
(some->> plugin-metadata
(normalize-plugin-metadata)
(swap! state/state update-in [:plugin/installed-plugins] assoc pid))))
(defn host-mounted!
[]

View File

@ -106,11 +106,6 @@
(when-let [engine (get-engine repo)]
(protocol/remove-db! engine)))
(defn transact-blocks!
[repo data]
(when-let [engine (get-engine repo)]
(protocol/transact-blocks! engine data)))
(defn get-unlinked-refs
"Get matched result from search first, and then filter by worker db"
[eid]

View File

@ -72,6 +72,26 @@
datoms)]
(concat schema-tx-data value-tx-data)))
(defn- update-table-properties
[conn _search-db]
(let [old-new-props {:logseq.property/table-sorting :logseq.property.table/sorting
:logseq.property/table-filters :logseq.property.table/filters
:logseq.property/table-ordered-columns :logseq.property.table/ordered-columns
:logseq.property/table-hidden-columns :logseq.property.table/hidden-columns}
props-tx (mapv (fn [[old new]]
{:db/id (:db/id (d/entity @conn old))
:db/ident new})
old-new-props)]
;; Property changes need to be in their own tx for subsequent uses of properties to take effect
(ldb/transact! conn props-tx {:db-migrate? true})
(mapcat (fn [[old new]]
(->> (d/q '[:find ?b ?prop-v :in $ ?prop :where [?b ?prop ?prop-v]] @conn old)
(mapcat (fn [[id prop-value]]
[[:db/retract id old]
[:db/add id new prop-value]]))))
old-new-props)))
(def schema-version->updates
[[3 {:properties [:logseq.property/table-sorting :logseq.property/table-filters
:logseq.property/table-hidden-columns :logseq.property/table-ordered-columns]
@ -88,7 +108,8 @@
[7 {:fix replace-original-name-content-with-title}]
[8 {:fix replace-object-and-page-type-with-node}]
[9 {:fix update-task-ident}]
[10 {:fix property-checkbox-type-non-ref}]])
[10 {:fix update-table-properties}]
[11 {:fix property-checkbox-type-non-ref}]])
(let [max-schema-version (apply max (map first schema-version->updates))]
(assert (<= db-schema/version max-schema-version))

View File

@ -85,7 +85,7 @@
(if (> t1 t2)
(merge-update-ops update-op2 update-op1)
(let [{av-coll1 :av-coll block-uuid :block-uuid} (last update-op1)
{av-coll2 :av-coll} (last update-op1)]
{av-coll2 :av-coll} (last update-op2)]
[:update t2
{:block-uuid block-uuid
:av-coll (concat av-coll1 av-coll2)}]))))

View File

@ -241,7 +241,7 @@
reset
[state/preferred-pasting-file? (constantly true)
;; paste-file-if-exists mocks below
editor-handler/upload-asset (fn [_id file & _]
editor-handler/upload-asset! (fn [_id file & _]
(reset! pasted-file file))
util/stop (constantly nil)
state/get-edit-block (constantly {})]

View File

@ -12,28 +12,32 @@
(deftest get-block
(with-redefs [state/get-current-repo (constantly test-helper/test-db)]
(db/transact! test-helper/test-db
[{:db/id 10000
:block/uuid #uuid "4406f839-6410-43b5-87db-25e9b8f54cc0"
:block/title "1"}
{:db/id 10001
:block/uuid #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
:block/title "2"}
{:db/id 10002
:block/uuid #uuid "adae3006-f03e-4814-a1f5-f17f15b86556"
:block/parent 10001
:block/title "3"}
{:db/id 10003
:block/uuid #uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d"
:block/parent 10002
:block/title "4"}])
[{:db/id 10000
:block/uuid #uuid "4406f839-6410-43b5-87db-25e9b8f54cc0"
:block/title "1"}
{:db/id 10001
:block/uuid #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
:block/title "2"}
{:db/id 10002
:block/uuid #uuid "adae3006-f03e-4814-a1f5-f17f15b86556"
:block/parent 10001
:block/title "3"}
{:db/id 10003
:block/uuid #uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d"
:block/parent 10002
:block/title "4"}])
(is (= (:title (bean/->clj (api-block/get_block 10000 #js {}))) "1"))
(is (= (:title (bean/->clj (api-block/get_block "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
(is (= (:title (bean/->clj (api-block/get_block #uuid "d9b7b45f-267f-4794-9569-f43d1ce77172" #js {}))) "2"))
(is (= {:id 10001, :title "2", :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172", :children [["uuid" "adae3006-f03e-4814-a1f5-f17f15b86556"]]}
(select-keys (js->clj (api-block/get_block 10001 #js {:includeChildren false}) :keywordize-keys true)
[:id :title :uuid :children])))
(is (= {:title "2", :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172", :id 10001, :children [{:title "3", :parent {:id 10001}, :uuid "adae3006-f03e-4814-a1f5-f17f15b86556", :id 10002, :level 1, :children [{:title "4", :parent {:id 10002}, :uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d", :id 10003, :level 2, :children []}]}]}
(js->clj (api-block/get_block 10001 #js {:includeChildren true}) :keywordize-keys true)))))
(select-keys (js->clj (api-block/get_block 10001 #js {:includeChildren false}) :keywordize-keys true)
[:id :title :uuid :children])))
;; NOTE: `content` key is to be compatible with old APIs
(is (= {:id 10001, :title "2", :content "2" :uuid "d9b7b45f-267f-4794-9569-f43d1ce77172"
:children [{:id 10002 :title "3", :content "3"
:parent {:id 10001}, :uuid "adae3006-f03e-4814-a1f5-f17f15b86556", :level 1,
:children [{:id 10003, :title "4", :content "4" :parent {:id 10002}, :uuid "0c3053c3-2dab-4769-badd-14ce16d8ba8d", :level 2, :children []}]}]}
(js->clj (api-block/get_block 10001 #js {:includeChildren true}) :keywordize-keys true)))))
#_(cljs.test/run-tests)