Demo
There are two ways of usage the Weekly Pages:
Option A: Via plugin Full House Templates
could be used with the Days plugin (the calendar in the sidebar in demo)
nice UI for selecting templates
written in javascript, so it is easy to adapt to your case
doesn’t work on mobile
Setup instructions are here
Option B: Without a plugin
works on mobile
build with Logseq features only
written in clojure, so it is hard to adapt to your own needs
Let’s concentrate on Option B here
- To prepare the queries create anywhere in Logseq (ex: in «Queries» page) the following queries. I’ll use 2 queries for
#podcast
and#diary
records. But you can setup your own ones:reference:: #podcast #+BEGIN_QUERY ... #+END_QUERY
Fill the body of queries with the same one code. Insert it betweenreference:: #diary #+BEGIN_QUERY ... #+END_QUERY
#+BEGIN_QUERY
and#+END_QUERY
with replacing the «…»:{ :inputs [:current-page :current-block] :query [:find (pull ?b [*]) :in $ ?week ?self % :where [?page :block/name ?week] (get-week ?page ?weekStart ?weekEnd) (between ?b ?weekStart ?weekEnd) [?self :block/page ?self-page] (tagged-with-property ?b ?self :reference) ] :rules [ [(get-week ?block ?start ?end) [?block :block/properties ?props] [(get ?props :week-start) ?start] [(get ?props :week-end) ?end] ], [(tagged-with-property ?block ?props-block ?prop) [?props-block :block/properties-text-values ?props] [(get ?props ?prop) ?tag] [(subs ?tag 1) ?tag-name] [?block :block/refs ?ref] [?ref :block/name ?name] [(= ?name ?tag-name)] ] ] }
- Create template anywhere in Logseq (ex: in «Templates» page):
- template:: weekly page template-including-parent:: false - - #+BEGIN_QUERY { :query [ :find ?cp ?cb-uuid :in $ ?cp ?cb :where [?cb :block/uuid ?cb-uuid] ] :inputs [:current-page :current-block] :result-transform (fn [[page-name block-uuid]] (def weekStartsFrom (get (js->clj (call-api "get_user_configs")) "preferredStartOfWeek")) (def zerosToWidth (fn [num width] (let [ num-s (str num) zeros (repeat (- width (count num-s)) "0") ] (clojure.string/join (concat zeros num-s)) ) )) (def parseWeek (fn [isoWeek] (let [ regex (re-pattern "^(\\d{4}).*?(?:w|W)(\\d+)$") [_ year weekn] (re-matches regex (str isoWeek)) ] [(int year) (int weekn)] ) )) ;; source: [](https://discuss.logseq.com/t/add-query-input-or-function-day-of-week/18361/12) (def days {0 "Saturday" 1 "Sunday" 2 "Monday" 3 "Tuesday" 4 "Wednesday" 5 "Thursday" 6 "Friday"}) (def weekDayN (fn [date] (def month (quot (mod date 10000) 100)) (def month6 (quot (- month 8) 6)) (def year6 (+ (quot date 10000) month6)) (def yearnum (mod year6 100)) (def century (quot year6 100)) (def d (mod (+ (mod date 100) (quot (* 13 (inc (- month (* month6 12)))) 5) yearnum (quot yearnum 4) (quot century 4) (* 5 century)) 7)) d )) (def weekDay (fn [date] (get days (weekDayN date)) )) ;; naming and algorithm according to [ISO week date](https://www.wikiwand.com/en/ISO_week_date#Algorithms) ;; day of week: 1..7 for Monday..Sunday (def dow-mon (fn [date] (def wd (- (weekDayN date) 1)) (if (<= wd 0) (+ wd 7) wd) )) ;; day of week: 1..7 for Sunday..Saturday (def dow-sun (fn [date] (def wd (weekDayN date)) (if (= wd 0) 7 wd) )) ;; day of week: 1..7 for Saturday..Friday (def dow-sat (fn [date] (+ 1 (weekDayN date)) )) (def dow (case weekStartsFrom 5 dow-sat 6 dow-sun dow-mon )) (def first-week-belongs-to-prev-year (fn [dow-1st-jan] (case weekStartsFrom 5 (= dow-1st-jan 7) ;; is Fri 6 (or (= dow-1st-jan 6) (= dow-1st-jan 7)) ;; is Fri/Sat (or (= dow-1st-jan 5) (= dow-1st-jan 6) (= dow-1st-jan 7)) ;; is Fri/Sat/Sun ) )) ;; day of year: ;; 1..365 or 366 ;; -6..0 when shifts to the previous year ;; weekn: 1-52 or 53 (def doy (fn [year weekn] (let [ dow-1st-jan (dow (str year "0101")) week (if (first-week-belongs-to-prev-year dow-1st-jan) (+ weekn 1) weekn) days-1st-week (+ 1 (- 7 dow-1st-jan)) days-for-weeks (* (- week 2) 7) doy (+ days-1st-week days-for-weeks 1) ] doy ) )) (def leap? (fn [year] (or (= 0 (mod year 400)) (and (= 0 (mod year 4)) (not (= 0 (mod year 100)) ) ) ) )) ;; Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec (def doys-common [0 31 59 90 120 151 181 212 243 273 304 334]) (def doys-leap [0 31 60 91 121 152 182 213 244 274 305 335]) (def dateFromOrdinal (fn [year doy] (if (< doy 1) [(dec year) 12 (+ 31 doy)] ;; December of the prev year (let [ doys (if (leap? year) doys-leap doys-common) index (->> doys (map-indexed vector) (filter (fn [[i x]] (< x doy) ) ) last first ) month (inc index) day (- doy (get doys index)) ] (if (and (= month 12) (> day 31)) [(inc year) 1 (- day 31)] ;; January of the next year [year month day] ) ) ) )) (def weekDates (fn [year weekn] (if (= year 0) [nil nil] (let [ doy (doy year weekn) [year1 month1 day1] (dateFromOrdinal year doy) [year2 month2 day2] (dateFromOrdinal year (+ doy 6)) ] [ (clojure.string/join [year1 (zerosToWidth month1 2) (zerosToWidth day1 2)]) (clojure.string/join [year2 (zerosToWidth month2 2) (zerosToWidth day2 2)]) ] ) ) )) (let [ [year weekn] (parseWeek page-name) ] (when (not (= year 0)) (let [ [weekStart weekEnd] (weekDates year weekn) uuid (-> (call-api "get_page_blocks_tree" page-name) js->clj first (get "uuid") ) ] (call-api "upsert_block_property" uuid "week-start" (int weekStart)) (call-api "upsert_block_property" uuid "week-end" (int weekEnd)) (call-api "remove_block" block-uuid) ) ) ) ) } #+END_QUERY - Overview heading:: true - INSERT HERE embed ref to #diary query - INSERT HERE embed ref to #podcast query
- Copy reference to both of queries via right clicking on corresponding bullet and selecting «Copy block embed»:
…and insert them under «Overview» heading. It should look like:... - Overview heading:: true - {{embed ((666cd068-133c-4b30-9df4-1dd8a94179cb))}} - {{embed ((666cd1b2-f50d-4d88-859b-04f2f9e2efb2))}}
- Use this template on every weekly page to setup it.
Notes
- Week start & end dates based on ISO 8601.
- Embedding used to achieve the same looks for every week page.
- Every query has
reference
property for easy configuration. - Value of reference property is a tag. This is intentional: to auto rename the value with renaming whole reference tag.
- Currently there is no way in Logseq to avoid copying of query body. Please vote for this feature here and like this comment.
Enjoy!
PS And there is…