├── .github
└── workflows
│ └── publish.yml
├── LICENSE
├── README.md
├── icon.png
├── index.html
├── index.js
├── package.json
└── style.css
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Build plugin
2 |
3 | on:
4 | push:
5 | # Sequence of patterns matched against refs/tags
6 | tags:
7 | - '*' # Push events to matching any tag format, i.e. 1.0, 20.15.10
8 |
9 | env:
10 | PLUGIN_NAME: ${{ github.event.repository.name }}
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Use Node.js
19 | uses: actions/setup-node@v1
20 | with:
21 | node-version: '16.x' # You might need to adjust this value to your own version
22 | - name: Build
23 | id: build
24 | run: |
25 | mkdir ${{ env.PLUGIN_NAME }}
26 | cp LICENSE README.md package.json index.html index.js style.css icon.png ${{ env.PLUGIN_NAME }}
27 | zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }}
28 | ls
29 | echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)"
30 | - name: Create Release
31 | uses: ncipollo/release-action@v1
32 | id: create_release
33 | env:
34 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35 | VERSION: ${{ github.ref }}
36 | with:
37 | allowUpdates: true
38 | draft: false
39 | prerelease: false
40 |
41 | - name: Upload zip file
42 | id: upload_zip
43 | uses: actions/upload-release-asset@v1
44 | env:
45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46 | with:
47 | upload_url: ${{ steps.create_release.outputs.upload_url }}
48 | asset_path: ./${{ env.PLUGIN_NAME }}.zip
49 | asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip
50 | asset_content_type: application/zip
51 |
52 | - name: Upload package.json
53 | id: upload_metadata
54 | uses: actions/upload-release-asset@v1
55 | env:
56 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57 | with:
58 | upload_url: ${{ steps.create_release.outputs.upload_url }}
59 | asset_path: ./package.json
60 | asset_name: package.json
61 | asset_content_type: application/json
62 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 adxsoft
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # Logseq Query Builder Plugin
3 |
4 | * builds advanced logseq queries from [Simple Commands](#simple-commands) contained in a logseq code block.
5 | * Choosing **Advanced Query Builder** in the code blocks menu (right click on block's bullet)
6 | * will generate an advanced query in a **new** child block
7 | * You can alter the code block and generate another query which will add another new child block.
8 | * In this way you can experiment with generating multiple advanced queries.
9 | ## Detailed Documentation
10 |
11 | Can be found [here](https://github.com/adxsoft/docs-logseq-query-builder-plugin)
12 |
13 | ### Do not use tabs in commands
14 | *Note. as this code also supports the web site at https://adxsoft.github.io/logseqadvancedquerybuilder/ the use of tabs for indentation of the simple commands is not possible*
15 | So for consistency between the online tool and the plugin you can use any number of leading spaces but the indentations must be consistent. I would suggest either two or four spaces is a good indentation value.
16 |
17 | ## Installation
18 | ### Preparation
19 | * Click the 3 dots in the righthand corner and go to **Settings**.
20 | * Go to **Advanced** and enable **Plug-in system**.
21 | * Restart the application.
22 | * Click 3 dots and go to Plugins (or `Esc t p`).
23 |
24 | ### Install plugin from the Marketplace (recommended)
25 | * Click the `Marketplace` button and then click `Plugins`.
26 | * Find the plugin and click `Install`.
27 |
28 | ### Install plugin manually
29 | * Click the green Code button above and download the zip
30 | * Unzip it into a folder
31 | * Click `Load unpacked plugin`, and select the folder where the plugin code was unzipped
32 |
33 |
34 | ## Technical Information
35 | * Originally the online tool was developed using pyscript and redeveloped in javascript.
36 | * To ensure consistency between the online tool and the plugin the javascript code is shared.
37 | * A variable called **_mode_** is set to _logseq-plugin_, _website_ or _local_.
38 | * All modes use index.js as common code
39 | * **mode _logseq-plugin_**
40 | * will operate as a logseq plugin
41 | * has its own _index.html_ and _package.json_ file
42 | * files are contained in the _plugin-dist_ folder
43 | * **mode _website_**
44 | * will operate as the online tool
45 | * has its own _index.html_ and _package.json_ file
46 | * files are contained in the _website-dist_ folder
47 | * **mode _local_**
48 | * will operate locally
49 | * has its own _index.html_ and _package.json_ file
50 | * files are contained in the main folder
51 | * has a _index.test.js_ file which is used for unit testing with the Jest Testing Library - the index.test.js file is contained in the repository for the online tool at
52 |
53 |
54 | ## Releases
55 | - v0.1
56 | - Original release - Dec 30th 2022
57 | - v0.7
58 | - First release to the logseq marketplace 23rd Feb 2023
59 |
--------------------------------------------------------------------------------
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/adxsoft/logseq-query-builder-plugin/6c06ce596118776478bb118f256d354ece3b1af3/icon.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 | Logseq Advanced Query Builder
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | // logseq-advanced-query-builder v0.1 Dec 23rd 2022
2 |
3 | // set mode of execution at end of this script
4 | // note each mode has its own index.html and package.json files
5 | // index.js is common to each mode and
6 | // copied from main to to dist folders before any deployments
7 |
8 | // 'local' mode for desktop testing with Jest Test framework
9 | // - located in the main folder
10 | // 'logseq-plugin' for operating as a plugin within logseq
11 | // - located in the plugin-dist folder
12 | // 'website' for operating as a online website
13 | // - located in the website-dist folder
14 |
15 | // Deployment
16 | // copy index.js to deploy folder
17 | // WARNING:
18 | // 1. do not copy package.json or index.html to
19 | // deployment folders (plugin-dist and website-dist)
20 | // as the main package.json is configured for jest testing
21 | // 2. do not copy main README.md to
22 | // deployment folders (plugin-dist and docs-dist)
23 | // as they are specific to each deployment domain
24 |
25 | // Dictionary of query lines data
26 | var querylineDict = {
27 | 'common-querylines': {
28 | 'start':
29 | {
30 | 'name': 'start',
31 | 'useincommands': ['common'],
32 | 'segment': 'start',
33 | 'datalog': '#+BEGIN_QUERY',
34 | 'comment': ''
35 | },
36 | 'open':
37 | {
38 | 'name': 'open',
39 | 'useincommands': ['common'],
40 | 'segment': 'open',
41 | 'datalog': '{',
42 | 'comment': ''
43 | },
44 | 'title':
45 | {
46 | 'name': 'title',
47 | 'useincommands': ['common'],
48 | 'segment': 'title',
49 | 'datalog': ':title [:b "$$ARG1"]',
50 | 'comment': ''
51 | },
52 | 'findblocks':
53 | {
54 | 'name': 'findblocks',
55 | 'useincommands': ['common'],
56 | 'segment': 'query',
57 | 'datalog': ':query [:find (pull ?block [*])',
58 | 'comment': 'Get every block into variable ?block'
59 | },
60 | 'daterange':
61 | {
62 | 'name': 'daterange',
63 | 'useincommands': ['common'],
64 | 'segment': 'in',
65 | 'datalog': ':in $ ?startdate ?enddate',
66 | 'comment': 'give query the ?startdate variable and the ?enddate variable (set by :inputs)'
67 | },
68 | 'where':
69 | {
70 | 'name': 'where',
71 | 'useincommands': ['common'],
72 | 'segment': 'where',
73 | 'datalog': ':where',
74 | 'comment': 'filter command'
75 | },
76 | 'tasks_are':
77 | {
78 | 'name': 'tasks_are',
79 | 'useincommands': ['common'],
80 | 'segment': 'filters',
81 | 'datalog': '[(contains? #{"$$ARG1"} ?marker)]',
82 | 'comment': 'Select block if it has one or more tasks (TODO or DONE etc)'
83 | },
84 | 'not_tasks_are':
85 | {
86 | 'name': 'not_tasks_are',
87 | 'useincommands': ['common'],
88 | 'segment': 'filters',
89 | 'datalog': '(not [(contains? #{"$$ARG1"} ?marker)])',
90 | 'comment': 'Exclude block if it has one or more tasks'
91 | },
92 | 'pagelinks_are':
93 | {
94 | 'name': 'pagelinks_are',
95 | 'useincommands': ['common'],
96 | 'segment': 'filters',
97 | 'datalog': '[?block :block/path-refs [:block/name "$$ARG1"]]',
98 | 'comment': 'Select block if it has one or more links to other pages'
99 | },
100 | 'not_pagelinks_are':
101 | {
102 | 'name': 'not_pagelinks_are',
103 | 'useincommands': ['common'],
104 | 'segment': 'filters',
105 | 'datalog': '(not [?block :block/path-refs [:block/name "$$ARG1"]])',
106 | 'comment': 'Exclude block if it has one or more links to other pages'
107 | },
108 | 'scheduledbetween':
109 | {
110 | 'name': 'scheduledbetween',
111 | 'useincommands': ['common'],
112 | 'segment': 'inputs',
113 | 'datalog': ':inputs [$$ARG1]',
114 | 'comment': 'set the input values for a date range for example could be\n :today :365d-after'
115 | },
116 | 'journalfrom':
117 | {
118 | 'name': 'journalfrom',
119 | 'useincommands': ['common'],
120 | 'segment': 'filters',
121 | 'datalog': '[(>= ?journaldate ?startdate)]',
122 | 'comment': 'Select if journaldate greater than start date'
123 | },
124 | 'journalto':
125 | {
126 | 'name': 'journalto',
127 | 'useincommands': ['common'],
128 | 'segment': 'filters',
129 | 'datalog': '[(<= ?journaldate ?enddate)]',
130 | 'comment': 'Select if journalddate less than end date'
131 | },
132 | 'journalsbetween':
133 | {
134 | 'name': 'journalsbetween',
135 | 'useincommands': ['common'],
136 | 'segment': 'inputs',
137 | 'datalog': ':inputs [$$ARG1]',
138 | 'comment': 'set the input values for a date range for example could be\n :today :365d-after'
139 | },
140 | 'breadcrumb_show_false':
141 | {
142 | 'name': 'breadcrumb_show_false',
143 | 'useincommands': ['common'],
144 | 'segment': 'options',
145 | 'datalog': ':breadcrumb-show? false',
146 | 'comment': 'Suppress breadcrumbs view'
147 | },
148 | 'breadcrumb_show_true':
149 | {
150 | 'name': 'breadcrumb_show_true',
151 | 'useincommands': ['common'],
152 | 'segment': 'options',
153 | 'datalog': ':breadcrumb-show? true',
154 | 'comment': 'Show breadcrumbs above each block'
155 | },
156 | 'collapse_false':
157 | {
158 | 'name': 'collapse_false',
159 | 'useincommands': ['common'],
160 | 'segment': 'options',
161 | 'datalog': ':collapsed? false',
162 | 'comment': 'Toggle collapse or fold'
163 | },
164 | 'collapse_true':
165 | {
166 | 'name': 'collapse_true',
167 | 'useincommands': ['common'],
168 | 'segment': 'options',
169 | 'datalog': ':collapsed? true',
170 | 'comment': 'Toggle collapse or fold'
171 | },
172 | 'closefind':
173 | {
174 | 'name': 'closefind',
175 | 'useincommands': ['common'],
176 | 'segment': 'closefind',
177 | 'datalog': ']',
178 | 'comment': ''
179 | },
180 | 'closequery':
181 | {
182 | 'name': 'closequery',
183 | 'useincommands': ['common'],
184 | 'segment': 'closequery',
185 | 'datalog': '}',
186 | 'comment': ''
187 | },
188 | 'end':
189 | {
190 | 'name': 'end',
191 | 'useincommands': ['common'],
192 | 'segment': 'end',
193 | 'datalog': '#+END_QUERY',
194 | 'comment': ''
195 | },
196 | },
197 | 'blocks-querylines': {
198 | 'blockcontent':
199 | {
200 | 'name': 'blockcontent',
201 | 'useincommands': ['blocks'],
202 | 'segment': 'filters',
203 | 'datalog': '[?block :block/content ?blockcontent]',
204 | 'comment': 'get block content into variable ?blockcontent'
205 | },
206 | 'page':
207 | {
208 | 'name': 'page',
209 | 'useincommands': ['blocks'],
210 | 'segment': 'filters',
211 | 'datalog': '[?block :block/page ?page]',
212 | 'comment': 'get page (special type of block) into variable ?page (used later)'
213 | },
214 | 'pagename':
215 | {
216 | 'name': 'pagename',
217 | 'useincommands': ['blocks'],
218 | 'segment': 'filters',
219 | 'datalog': '[?page :block/name ?pagename]',
220 | 'comment': 'get page name (lowercase) from the page block into variable ?pagename'
221 | },
222 | 'marker':
223 | {
224 | 'name': 'marker',
225 | 'useincommands': ['blocks'],
226 | 'segment': 'filters',
227 | 'datalog': '[?block :block/marker ?marker]',
228 | 'comment': 'get block marker (TODO LATER ETC) into variable ?marker'
229 | },
230 | 'scheduled':
231 | {
232 | 'name': 'scheduled',
233 | 'useincommands': ['blocks'],
234 | 'segment': 'filters',
235 | 'datalog': '[?block :block/scheduled ?scheduleddate]',
236 | 'comment': 'get scheduled date in the block into variable ?scheduleddate'
237 | },
238 | 'scheduledfrom':
239 | {
240 | 'name': 'scheduledfrom',
241 | 'useincommands': ['blocks'],
242 | 'segment': 'filters',
243 | 'datalog': '[(>= ?scheduleddate ?startdate)]',
244 | 'comment': 'Select if scheduleddate greater than start date'
245 | },
246 | 'scheduledto':
247 | {
248 | 'name': 'scheduledto',
249 | 'useincommands': ['blocks'],
250 | 'segment': 'filters',
251 | 'datalog': '[(<= ?scheduleddate ?enddate)]',
252 | 'comment': 'Select if scheduleddate less than end date'
253 | },
254 | 'deadline':
255 | {
256 | 'name': 'deadline',
257 | 'useincommands': ['blocks'],
258 | 'segment': 'filters',
259 | 'datalog': '[?block :block/deadline ?deadlinedate]',
260 | 'comment': 'get deadline date in the block into variable ?date'
261 | },
262 | 'deadlinefrom':
263 | {
264 | 'name': 'deadlinefrom',
265 | 'useincommands': ['blocks'],
266 | 'segment': 'filters',
267 | 'datalog': '[(>= ?deadlinedate ?startdate)]',
268 | 'comment': 'Select if deadlinedate greater than start date'
269 | },
270 | 'deadlineto':
271 | {
272 | 'name': 'deadlineto',
273 | 'useincommands': ['blocks'],
274 | 'segment': 'filters',
275 | 'datalog': '[(<= ?deadlinedate ?enddate)]',
276 | 'comment': 'Select if deadlinedate less than end date'
277 | },
278 | 'pagename_is':
279 | {
280 | 'name': 'pagename_is',
281 | 'useincommands': ['blocks'],
282 | 'segment': 'filters',
283 | 'datalog': '[?block :block/name "$$ARG1"]',
284 | 'comment': 'Select specific page from the page special block\nPresence of :block/name in a blocks means \nit is a block that has the page attributes'
285 | },
286 | 'not_pagename_is':
287 | {
288 | 'name': 'not_pagename_is',
289 | 'useincommands': ['blocks'],
290 | 'segment': 'filters',
291 | 'datalog': '(not [?block :block/name "$$ARG1"])',
292 | 'comment': 'Exclude specific page from the page special block'
293 | },
294 | 'page_is_journal':
295 | {
296 | 'name': 'page_is_journal',
297 | 'useincommands': ['blocks'],
298 | 'segment': 'filters',
299 | 'datalog': '[?page :block/journal? true]',
300 | 'comment': 'Select block if its belongs to a journal page'
301 | },
302 | 'not_page_is_journal':
303 | {
304 | 'name': 'not_page_is_journal',
305 | 'useincommands': ['blocks'],
306 | 'segment': 'filters',
307 | 'datalog': '[?page :block/journal? false]',
308 | 'comment': 'Exclude block if its belongs to a journal page'
309 | },
310 | 'journal_date':
311 | {
312 | 'name': 'journal_date',
313 | 'useincommands': ['blocks'],
314 | 'segment': 'filters',
315 | 'datalog': '[?page :block/journal-day ?journaldate]',
316 | 'comment': 'get journal date into variable ?journaldate'
317 | },
318 | 'block_properties_are':
319 | {
320 | 'name': 'block_properties_are',
321 | 'useincommands': ['blocks'],
322 | 'segment': 'filters',
323 | 'datalog': '(property ?block :$$ARG1 $$ARG2)',
324 | 'comment': 'Select if block has a single property (arg1) with value arg2'
325 | },
326 | 'not_block_properties_are':
327 | {
328 | 'name': 'not_block_properties_are',
329 | 'useincommands': ['blocks'],
330 | 'segment': 'filters',
331 | 'datalog': '(not (property ?block :$$ARG1 $$ARG2))',
332 | 'comment': 'Exclude if block has a single property (arg1) with value arg2'
333 | },
334 | 'blocktags_are':
335 | {
336 | 'name': 'blocktags_are',
337 | 'useincommands': ['blocks'],
338 | 'segment': 'filters',
339 | 'datalog': '(page-ref ?block "$$ARG1")',
340 | 'comment': 'Select block if it has a specific tag or page link'
341 | },
342 | 'not_blocktags_are':
343 | {
344 | 'name': 'not_blocktags_are',
345 | 'useincommands': ['blocks'],
346 | 'segment': 'filters',
347 | 'datalog': '(not (page-ref ?block "$$ARG1"))',
348 | 'comment': 'Exclude block if it has a specific tag or page link'
349 | },
350 | 'page_properties_are':
351 | {
352 | 'name': 'page_properties_are',
353 | 'useincommands': ['blocks'],
354 | 'segment': 'filters',
355 | 'datalog': '(page-property ?page :$$ARG1 $$ARG2)',
356 | 'comment': 'Select block if the page it belongs to\nhas a page property (arg1) with value arg2'
357 | },
358 | 'not_page_properties_are':
359 | {
360 | 'name': 'not_page_properties_are',
361 | 'useincommands': ['blocks'],
362 | 'segment': 'filters',
363 | 'datalog': '(not (page-property ?page :$$ARG1 $$ARG2))',
364 | 'comment': 'Exclude block if the page it belongs to\nhas a page property (arg1) with value arg2'
365 | },
366 | 'pagetags_are':
367 | {
368 | 'name': 'pagetags_are',
369 | 'useincommands': ['blocks'],
370 | 'segment': 'filters',
371 | 'datalog': '(page-tags ?page #{"$$ARG1"})',
372 | 'comment': 'Select block if the page it belongs to\nhas a one or more page tags'
373 | },
374 | 'not_pagetags_are':
375 | {
376 | 'name': 'not_pagetags_are',
377 | 'useincommands': ['blocks'],
378 | 'segment': 'filters',
379 | 'datalog': '(not (page-tags ?page #{"$$ARG1"}))',
380 | 'comment': 'Exclude block if the page it belongs to\nhas one or more page tags'
381 | },
382 | 'namespace':
383 | {
384 | 'name': 'namespace',
385 | 'useincommands': ['blocks'],
386 | 'segment': 'filters',
387 | 'datalog': '(namespace ?page "$$ARG1")',
388 | 'comment': 'Select block if the page it belongs to is within namespace arg1'
389 | },
390 | 'not_namespace':
391 | {
392 | 'name': 'not_namespace_blocks',
393 | 'useincommands': ['blocks'],
394 | 'segment': 'filters',
395 | 'datalog': '(not (namespace ?page "$$ARG1"))',
396 | 'comment': 'Exclude block if the page it belongs to is within namespace arg1'
397 | },
398 | 'arg_blockcontent_startswith':
399 | {
400 | 'name': 'arg_blockcontent_startswith',
401 | 'useincommands': ['blocks'],
402 | 'segment': 'filters',
403 | 'datalog': '[(clojure.string/starts-with? ?blockcontent "$$ARG1")]',
404 | 'comment': 'Select if block content starts with arg1'
405 | },
406 | 'arg_blockcontent_endswith':
407 | {
408 | 'name': 'arg_blockcontent_endswith',
409 | 'useincommands': ['blocks'],
410 | 'segment': 'filters',
411 | 'datalog': '[(clojure.string/ends-with? ?blockcontent "$$ARG1")]',
412 | 'comment': 'Select if block content ends with arg1'
413 | },
414 | 'arg_blockcontent_contains':
415 | {
416 | 'name': 'arg_blockcontent_contains',
417 | 'useincommands': ['blocks'],
418 | 'segment': 'filters',
419 | 'datalog': '[(clojure.string/includes? ?blockcontent "$$ARG1")]',
420 | 'comment': 'Select if block content contains arg1'
421 | },
422 | 'not_arg_blockcontent_startswith':
423 | {
424 | 'name': 'not_arg_blockcontent_startswith',
425 | 'useincommands': ['blocks'],
426 | 'segment': 'filters',
427 | 'datalog': '(not [(clojure.string/starts-with? ?blockcontent "$$ARG1")])',
428 | 'comment': 'Exclude if block content starts with arg1'
429 | },
430 | 'not_arg_blockcontent_endswith':
431 | {
432 | 'name': 'not_arg_blockcontent_endswith',
433 | 'useincommands': ['blocks'],
434 | 'segment': 'filters',
435 | 'datalog': '(not [(clojure.string/ends-with? ?blockcontent "$$ARG1")])',
436 | 'comment': 'Exclude if block content ends with arg1'
437 | },
438 | 'not_arg_blockcontent_contains':
439 | {
440 | 'name': 'not_arg_blockcontent_contains',
441 | 'useincommands': ['blocks'],
442 | 'segment': 'filters',
443 | 'datalog': '(not [(clojure.string/includes? ?blockcontent "$$ARG1")])',
444 | 'comment': 'Exclude if block content contains arg1'
445 | },
446 | 'scheduledbetween':
447 | {
448 | 'name': 'scheduledbetween',
449 | 'useincommands': ['blocks'],
450 | 'segment': 'inputs',
451 | 'datalog': ':inputs [$$ARG1]',
452 | 'comment': 'set the input values for a date range for example could be\n :today :365d-after'
453 | },
454 | 'deadlinebetween':
455 | {
456 | 'name': 'deadlinebetween',
457 | 'useincommands': ['blocks'],
458 | 'segment': 'inputs',
459 | 'datalog': ':inputs [$$ARG1]',
460 | 'comment': 'set the input values for a date range for example could be\n :today :365d-after'
461 | },
462 | },
463 | 'pages-querylines': {
464 | 'original-pagename':
465 | {
466 | 'name': 'original-pagename',
467 | 'useincommands': ['pages'],
468 | 'segment': 'filters',
469 | 'datalog': '[?block :block/original-name ?originalpagename]',
470 | 'comment': 'get original page name (case sensitive) into variable ?originalpagename',
471 | },
472 | 'pagename':
473 | {
474 | 'name': 'pagename',
475 | 'useincommands': ['pages'],
476 | 'segment': 'filters',
477 | 'datalog': '[?block :block/name ?pagename]',
478 | 'comment': 'get page name (lowercase) from the special page block into variable ?pagename',
479 | },
480 | 'pagename_is':
481 | {
482 | 'name': 'pagename_is',
483 | 'useincommands': ['pages'],
484 | 'segment': 'filters',
485 | 'datalog': '[?block :block/name "$$ARG1"]',
486 | 'comment': 'Select specific page using the :block/name\nwhich is only present in special blocks that\nhave the page attributes'
487 | },
488 | 'not_pagename_is':
489 | {
490 | 'name': 'not_pagename_is',
491 | 'useincommands': ['pages'],
492 | 'segment': 'filters',
493 | 'datalog': '(not [?block :block/name "$$ARG1"])',
494 | 'comment': 'Exclude specific page using the :block/name\nwhich is only present in special blocks that\nhave the page attributes'
495 | },
496 | 'page_is_journal':
497 | {
498 | 'name': 'page_is_journal',
499 | 'useincommands': ['pages'],
500 | 'segment': 'filters',
501 | 'datalog': '[?block :block/journal? true]',
502 | 'comment': 'Select block if it belonhs to a a journal'
503 | },
504 | 'not_page_is_journal':
505 | {
506 | 'name': 'not_page_is_journal',
507 | 'useincommands': ['pages'],
508 | 'segment': 'filters',
509 | 'datalog': '[?block :block/journal? false]',
510 | 'comment': 'Exclude block if it belonhs to a a journal'
511 | },
512 | 'journal_date':
513 | {
514 | 'name': 'journal_date',
515 | 'useincommands': ['pages'],
516 | 'segment': 'filters',
517 | 'datalog': '[?block :block/journal-day ?journaldate]',
518 | 'comment': 'get journal date into variable ?journaldate'
519 | },
520 | 'page_properties_are':
521 | {
522 | 'name': 'page_properties_are',
523 | 'useincommands': ['pages'],
524 | 'segment': 'filters',
525 | 'datalog': '(page-property ?block :$$ARG1 $$ARG2)',
526 | 'comment': 'Select if block is a special page blockand has a single property (arg1) with value arg2'
527 | },
528 | 'not_page_properties_are':
529 | {
530 | 'name': 'not_page_properties_are',
531 | 'useincommands': ['pages'],
532 | 'segment': 'filters',
533 | 'datalog': '(not (page-property ?block :$$ARG1 $$ARG2))',
534 | 'comment': 'Exclude if block is a special page blockand has a single property (arg1) with value arg2'
535 | },
536 | 'block_properties_are':
537 | {
538 | 'name': 'block_properties_are',
539 | 'useincommands': ['pages'],
540 | 'segment': 'filters',
541 | 'datalog': '(page-property ?block :$$ARG1 $$ARG2)',
542 | 'comment': 'Select if block has a single property (arg1) with value arg2'
543 | },
544 | 'not_block_properties_are':
545 | {
546 | 'name': 'not_block_properties_are',
547 | 'useincommands': ['pages'],
548 | 'segment': 'filters',
549 | 'datalog': '(not (property ?block :$$ARG1 $$ARG2))',
550 | 'comment': 'Exclude if block has a single property (arg1) with value arg2'
551 | },
552 | 'pagetags_are':
553 | {
554 | 'name': 'pagetags_are',
555 | 'useincommands': ['pages'],
556 | 'segment': 'filters',
557 | 'datalog': '(page-tags ?block #{"$$ARG1"})',
558 | 'comment': 'Select special page block with one or more page tags'
559 | },
560 | 'not_pagetags_are':
561 | {
562 | 'name': 'not_pagetags_are',
563 | 'useincommands': ['pages'],
564 | 'segment': 'filters',
565 | 'datalog': '(not (page-tags ?block #{"$$ARG1"}))',
566 | 'comment': 'Exclude special page block with one or more page tags'
567 | },
568 | 'blocktags_are':
569 | {
570 | 'name': 'blocktags_are',
571 | 'useincommands': ['blocks'],
572 | 'segment': 'filters',
573 | 'datalog': '(page-tags ?block #{"$$ARG1"})',
574 | 'comment': 'Select block if the page it belongs to\nhas a specific page tag or page link'
575 | },
576 | 'not_blocktags_are':
577 | {
578 | 'name': 'not_blocktags_are',
579 | 'useincommands': ['blocks'],
580 | 'segment': 'filters',
581 | 'datalog': '(not (page-tags ?block #{"$$ARG1"}))',
582 | 'comment': 'Exclude block if the page it belongs to\nhas a specific page tag or page link'
583 | },
584 | 'namespace':
585 | {
586 | 'name': 'namespace_pages',
587 | 'useincommands': ['pages'],
588 | 'segment': 'filters',
589 | 'datalog': '(namespace ?block "$$ARG1")',
590 | 'comment': 'Select if special page block is within namespace arg1'
591 | },
592 | 'not_namespace':
593 | {
594 | 'name': 'not_namespace_pages',
595 | 'useincommands': ['pages'],
596 | 'segment': 'filters',
597 | 'datalog': '(not (namespace ?block "$$ARG1"))',
598 | 'comment': 'Select if special page block is within namespace arg1'
599 | },
600 | 'arg_pagename_startswith':
601 | {
602 | 'name': 'arg_pagename_startswith',
603 | 'useincommands': ['pages'],
604 | 'segment': 'filters',
605 | 'datalog': '[(clojure.string/starts-with? ?pagename "$$ARG1")]',
606 | 'comment': 'Select if page title starts with arg1'
607 | },
608 | 'arg_pagename_endswith':
609 | {
610 | 'name': 'arg_pagename_endswith',
611 | 'useincommands': ['pages'],
612 | 'segment': 'filters',
613 | 'datalog': '[(clojure.string/ends-with? ?pagename "$$ARG1")]',
614 | 'comment': 'Select if page title ends with arg1'
615 | },
616 | 'arg_pagename_contains':
617 | {
618 | 'name': 'arg_pagename_contains',
619 | 'useincommands': ['common'],
620 | 'segment': 'filters',
621 | 'datalog': '[(clojure.string/includes? ?pagename "$$ARG1")]',
622 | 'comment': 'Select if page title contains arg1'
623 | },
624 | 'not_arg_pagename_startswith':
625 | {
626 | 'name': 'not_arg_pagename_startswith',
627 | 'useincommands': ['common'],
628 | 'segment': 'filters',
629 | 'datalog': '(not [(clojure.string/starts-with? ?pagename "$$ARG1")])',
630 | 'comment': 'Exclude if page title ends with arg1'
631 | },
632 | 'not_arg_pagename_endswith':
633 | {
634 | 'name': 'not_arg_pagename_endswith',
635 | 'useincommands': ['pages'],
636 | 'segment': 'filters',
637 | 'datalog': '(not [(clojure.string/ends-with? ?pagename "$$ARG1")])',
638 | 'comment': 'Exclude if page title ends with arg1'
639 | },
640 | 'not_arg_pagename_contains':
641 | {
642 | 'name': 'not_arg_pagename_contains',
643 | 'useincommands': ['pages'],
644 | 'segment': 'filters',
645 | 'datalog': '(not [(clojure.string/includes? ?pagename "$$ARG1")])',
646 | 'comment': 'Exclude if page title contains arg1'
647 | },
648 | }
649 | }
650 |
651 | // Dictionary of query builder commands
652 | var commandsDict = {
653 | "blocks": {
654 | "querylines": [
655 | "findblocks",
656 | "where",
657 | "blockcontent",
658 | "page",
659 | "pagename",
660 | ],
661 | "description": "select logseq blocks by wildcards"
662 | },
663 | "blockproperties": {
664 | "querylines": [
665 | ],
666 | "description": "select blocks by property values"
667 | },
668 | "blocktags": {
669 | "querylines": [
670 | ],
671 | "description": "select blocks by tag"
672 | },
673 | "deadline": {
674 | "querylines": [
675 | "deadline"
676 | ],
677 | "description": "select blocks that have a deadline"
678 | },
679 | "deadlinebetween": {
680 | "querylines": [
681 | "deadline",
682 | "deadlinefrom",
683 | "deadlineto",
684 | "daterange"
685 | ],
686 | "description": "select blocks that have a deadline in a date range"
687 | },
688 | "journalsbetween": {
689 | "querylines": [
690 | "journal_date",
691 | "journalfrom",
692 | "journalto",
693 | "daterange"
694 | ],
695 | "description": "only select journal pages in a date range"
696 | },
697 | "journalonly": {
698 | "querylines": [
699 | "page_is_journal"
700 | ],
701 | "description": "only select journal pages"
702 | },
703 | "namespace": {
704 | "querylines": [
705 | ],
706 | "description": "select pages or blocks within a namespace"
707 | },
708 | "pages": {
709 | "querylines": [
710 | "findblocks",
711 | "where",
712 | "pagename",
713 | ],
714 | "description": "select pages by wildcards"
715 | },
716 | "pageproperties": {
717 | "querylines": [
718 | ],
719 | "description": "select pages by page properties"
720 | },
721 | "pagetags": {
722 | "querylines": [
723 | "not_page_is_journal"
724 | ],
725 | "description": "select pages by tag"
726 | },
727 | "pagelinks": {
728 | "querylines": [
729 | ],
730 | "description": "select any blocks that has links to pages"
731 | },
732 | "tasks": {
733 | "querylines": [
734 | 'marker',
735 | ],
736 | "description": "select blocks that have tasks present"
737 | },
738 | "scheduled": {
739 | "querylines": [
740 | "scheduled"
741 | ],
742 | "description": "select blocks that are scheduled"
743 | },
744 | "scheduledbetween": {
745 | "querylines": [
746 | "scheduled",
747 | "scheduledfrom",
748 | "scheduledto",
749 | "daterange"
750 | ],
751 | "description": "select blocks that are scheduled in a date range"
752 | },
753 | "collapse": {
754 | "querylines": [
755 | "collapse_true"
756 | ],
757 | "description": "collapse found blocks"
758 | },
759 | "expand": {
760 | "querylines": [
761 | "collapse_false"
762 | ],
763 | "description": "expand found blocks"
764 | },
765 | "showbreadcrumb": {
766 | "querylines": [
767 | "breadcrumb_show_true"
768 | ],
769 | "description": "show breadcrumb for found blocks"
770 | },
771 | "hidebreadcrumb": {
772 | "querylines": [
773 | "breadcrumb_show_false"
774 | ],
775 | "description": "hide breadcrumb for found blocks"
776 | },
777 | }
778 |
779 | // Local tests cases for automated test suite
780 | var QueryTestCases = [
781 |
782 | // test 1
783 | `title: pages command - select all pages
784 | - pages
785 | - *
786 | #+BEGIN_QUERY
787 | {
788 | :title [:b "pages command - select all pages"]
789 | :query [:find (pull ?block [*])
790 | :where
791 | [?block :block/name ?pagename]
792 | ]
793 | }
794 | #+END_QUERY
795 | `,
796 |
797 | // test 2
798 | `title: pages command - specific pages
799 | - pages
800 | - testpage001
801 | - testpage002
802 | #+BEGIN_QUERY
803 | {
804 | :title [:b "pages command - specific pages"]
805 | :query [:find (pull ?block [*])
806 | :where
807 | [?block :block/name ?pagename]
808 | ( or
809 | [?block :block/name "testpage001"]
810 | [?block :block/name "testpage002"]
811 | )
812 | ]
813 | }
814 | #+END_QUERY
815 | `,
816 |
817 | // test 3
818 | `title: pages command - pages by wildcards
819 | - pages
820 | - testpage00*
821 | #+BEGIN_QUERY
822 | {
823 | :title [:b "pages command - pages by wildcards"]
824 | :query [:find (pull ?block [*])
825 | :where
826 | [?block :block/name ?pagename]
827 | [(clojure.string/starts-with? ?pagename "testpage00")]
828 | ]
829 | }
830 | #+END_QUERY
831 | `,
832 |
833 | // test 4
834 | `title: pages command - pages by wildcards
835 | - pages
836 | - *002
837 | #+BEGIN_QUERY
838 | {
839 | :title [:b "pages command - pages by wildcards"]
840 | :query [:find (pull ?block [*])
841 | :where
842 | [?block :block/name ?pagename]
843 | [(clojure.string/ends-with? ?pagename "002")]
844 | ]
845 | }
846 | #+END_QUERY
847 | `,
848 |
849 | // test 5
850 | `title: pages command - pages by wildcards
851 | - pages
852 | - *page00*
853 | #+BEGIN_QUERY
854 | {
855 | :title [:b "pages command - pages by wildcards"]
856 | :query [:find (pull ?block [*])
857 | :where
858 | [?block :block/name ?pagename]
859 | [(clojure.string/includes? ?pagename "page00")]
860 | ]
861 | }
862 | #+END_QUERY
863 | `,
864 |
865 | // test 6
866 | `title: pages command - ignore pages (including wildcards)
867 | - pages
868 | - not testpage*
869 | - not Queries*
870 | #+BEGIN_QUERY
871 | {
872 | :title [:b "pages command - ignore pages (including wildcards)"]
873 | :query [:find (pull ?block [*])
874 | :where
875 | [?block :block/name ?pagename]
876 | (not [(clojure.string/starts-with? ?pagename "testpage")])
877 | (not [(clojure.string/starts-with? ?pagename "Queries")])
878 | ]
879 | }
880 | #+END_QUERY
881 | `,
882 |
883 | // test 7
884 | `title: blocks command - ignore blocks using wildcards
885 | - blocks
886 | - not And sir dare view*
887 | - not *here leave merit enjoy forth.
888 | - not *roof gutters*
889 | #+BEGIN_QUERY
890 | {
891 | :title [:b "blocks command - ignore blocks using wildcards"]
892 | :query [:find (pull ?block [*])
893 | :where
894 | [?block :block/content ?blockcontent]
895 | [?block :block/page ?page]
896 | [?page :block/name ?pagename]
897 | (not [(clojure.string/ends-with? ?blockcontent "And sir dare view")])
898 | (not [(clojure.string/starts-with? ?blockcontent "here leave merit enjoy forth.")])
899 | (not [(clojure.string/includes? ?blockcontent "roof gutters")])
900 | ]
901 | }
902 | #+END_QUERY
903 | `,
904 |
905 | // test 8
906 | `title: blocktags - select and exclude block level tags
907 | - blocks
908 | - *
909 | - blocktags
910 | - tagA
911 | - tagD
912 | - not tagB
913 | #+BEGIN_QUERY
914 | {
915 | :title [:b "blocktags - select and exclude block level tags"]
916 | :query [:find (pull ?block [*])
917 | :where
918 | [?block :block/content ?blockcontent]
919 | [?block :block/page ?page]
920 | [?page :block/name ?pagename]
921 | ( or
922 | (page-ref ?block "taga")
923 | (page-ref ?block "tagd")
924 | )
925 | (not (page-ref ?block "tagb"))
926 | ]
927 | }
928 | #+END_QUERY
929 | `,
930 | `title: blocktags and pages don't mix
931 | - pages
932 | - testpage00*
933 | - blocktags
934 | - tagA
935 | - not tagB
936 | #+BEGIN_QUERY
937 |
938 | ;; **ERROR: blocktags not valid with pages command use blocks command instead
939 |
940 | {
941 | :title [:b "blocktags and pages don't mix"]
942 | :query [:find (pull ?block [*])
943 | :where
944 | [?block :block/name ?pagename]
945 | [(clojure.string/starts-with? ?pagename "testpage00")]
946 | ]
947 | }
948 | #+END_QUERY
949 | `,
950 |
951 | // test 10
952 | `title: pagetags - page level tags
953 | - pages
954 | - testpage*
955 | - pagetags
956 | - classA
957 | #+BEGIN_QUERY
958 | {
959 | :title [:b "pagetags - page level tags"]
960 | :query [:find (pull ?block [*])
961 | :where
962 | [?block :block/name ?pagename]
963 | [(clojure.string/starts-with? ?pagename "testpage")]
964 | [?block :block/journal? false]
965 | (page-tags ?block #{"classa"})
966 | ]
967 | }
968 | #+END_QUERY
969 | `,
970 |
971 | // test 11
972 | `title: pagetags and pages
973 | - pages
974 | - *dynamics*
975 | - pagetags
976 | - classB
977 | #+BEGIN_QUERY
978 | {
979 | :title [:b "pagetags and pages"]
980 | :query [:find (pull ?block [*])
981 | :where
982 | [?block :block/name ?pagename]
983 | [(clojure.string/includes? ?pagename "dynamics")]
984 | [?block :block/journal? false]
985 | (page-tags ?block #{"classb"})
986 | ]
987 | }
988 | #+END_QUERY
989 | `,
990 |
991 | // test 12
992 | `title: select and exclude task types
993 | - tasks
994 | - TODO
995 | - not DOING
996 | #+BEGIN_QUERY
997 | ;; WARNING: Must have 'pages' command or 'blocks' Command
998 | ;; otherwise the query cannot get any information
999 | ;; Inserting a blocks command for you
1000 |
1001 | {
1002 | :title [:b "select and exclude task types"]
1003 | :query [:find (pull ?block [*])
1004 | :where
1005 | [?block :block/content ?blockcontent]
1006 | [?block :block/page ?page]
1007 | [?page :block/name ?pagename]
1008 | [?block :block/marker ?marker]
1009 | [(contains? #{"TODO"} ?marker)]
1010 | (not [(contains? #{"DOING"} ?marker)])
1011 | ]
1012 | }
1013 | #+END_QUERY
1014 | `,
1015 |
1016 | `title: select and exclude task types
1017 | - pages
1018 | - testpage00*
1019 | - tasks
1020 | - TODO
1021 | - not DOING
1022 | #+BEGIN_QUERY
1023 |
1024 | ;; **ERROR: tasks not valid with pages command use blocks command instead
1025 |
1026 | {
1027 | :title [:b "select and exclude task types"]
1028 | :query [:find (pull ?block [*])
1029 | :where
1030 | [?block :block/name ?pagename]
1031 | [(clojure.string/starts-with? ?pagename "testpage00")]
1032 | ]
1033 | }
1034 | #+END_QUERY
1035 | `,
1036 |
1037 | // test 14
1038 | `title: select and exclude pages with page properties
1039 | - pages
1040 | - *
1041 | - pageproperties
1042 | - pagetype, "p-major"
1043 | - pagetype, "p-minor"
1044 | - not pagetype, "p-advanced"
1045 | #+BEGIN_QUERY
1046 | {
1047 | :title [:b "select and exclude pages with page properties"]
1048 | :query [:find (pull ?block [*])
1049 | :where
1050 | [?block :block/name ?pagename]
1051 | ( or
1052 | (page-property ?block :pagetype "p-major")
1053 | (page-property ?block :pagetype "p-minor")
1054 | )
1055 | (not (page-property ?block :pagetype "p-advanced"))
1056 | ]
1057 | }
1058 | #+END_QUERY
1059 | `,
1060 |
1061 | // test 15
1062 | `title: select and exclude blocks with block properties
1063 | - blocks
1064 | - *
1065 | - blockproperties
1066 | - category, "b-thriller"
1067 | - category, "b-western"
1068 | - grade, "b-fiction"
1069 | #+BEGIN_QUERY
1070 | {
1071 | :title [:b "select and exclude blocks with block properties"]
1072 | :query [:find (pull ?block [*])
1073 | :where
1074 | [?block :block/content ?blockcontent]
1075 | [?block :block/page ?page]
1076 | [?page :block/name ?pagename]
1077 | ( or
1078 | (property ?block :category "b-thriller")
1079 | (property ?block :category "b-western")
1080 | (property ?block :grade "b-fiction")
1081 | )
1082 | ]
1083 | }
1084 | #+END_QUERY
1085 | `,
1086 |
1087 | // test 16
1088 | `title: only search pages in specific namespace
1089 | - pages
1090 | - *
1091 | - namespace
1092 | - physics
1093 | #+BEGIN_QUERY
1094 | {
1095 | :title [:b "only search pages in specific namespace"]
1096 | :query [:find (pull ?block [*])
1097 | :where
1098 | [?block :block/name ?pagename]
1099 | (namespace ?block "physics")
1100 | ]
1101 | }
1102 | #+END_QUERY
1103 | `,
1104 |
1105 | // test 17
1106 | `title: find block properties in a namespace
1107 | - blocks
1108 | - *
1109 | - namespace
1110 | - tech/python
1111 | - blockproperties
1112 | - grade, "b-fiction"
1113 | #+BEGIN_QUERY
1114 | {
1115 | :title [:b "find block properties in a namespace"]
1116 | :query [:find (pull ?block [*])
1117 | :where
1118 | [?block :block/content ?blockcontent]
1119 | [?block :block/page ?page]
1120 | [?page :block/name ?pagename]
1121 | (namespace ?page "tech/python")
1122 | (property ?block :grade "b-fiction")
1123 | ]
1124 | }
1125 | #+END_QUERY
1126 | `,
1127 |
1128 | // test 18
1129 | `title: find scheduled blocks in a namespace
1130 | - blocks
1131 | - *
1132 | - namespace
1133 | - physics
1134 | - scheduled
1135 | #+BEGIN_QUERY
1136 | {
1137 | :title [:b "find scheduled blocks in a namespace"]
1138 | :query [:find (pull ?block [*])
1139 | :where
1140 | [?block :block/content ?blockcontent]
1141 | [?block :block/page ?page]
1142 | [?page :block/name ?pagename]
1143 | (namespace ?page "physics")
1144 | [?block :block/scheduled ?scheduleddate]
1145 | ]
1146 | }
1147 | #+END_QUERY
1148 | `,
1149 |
1150 | // test 19
1151 | `title: scheduled - find scheduled blocks in a date range
1152 | - blocks
1153 | - *
1154 | - scheduledbetween
1155 | - :720d-before :700d-after
1156 | #+BEGIN_QUERY
1157 | {
1158 | :title [:b "scheduled - find scheduled blocks in a date range"]
1159 | :query [:find (pull ?block [*])
1160 | :in $ ?startdate ?enddate
1161 | :where
1162 | [?block :block/content ?blockcontent]
1163 | [?block :block/page ?page]
1164 | [?page :block/name ?pagename]
1165 | [?block :block/scheduled ?scheduleddate]
1166 | [(>= ?scheduleddate ?startdate)]
1167 | [(<= ?scheduleddate ?enddate)]
1168 | ]
1169 | :inputs [:720d-before :700d-after]
1170 | }
1171 | #+END_QUERY
1172 | `,
1173 |
1174 | // test 20
1175 | `title: find blocks with deadlines
1176 | - blocks
1177 | - *
1178 | - deadline
1179 | #+BEGIN_QUERY
1180 | {
1181 | :title [:b "find blocks with deadlines"]
1182 | :query [:find (pull ?block [*])
1183 | :where
1184 | [?block :block/content ?blockcontent]
1185 | [?block :block/page ?page]
1186 | [?page :block/name ?pagename]
1187 | [?block :block/deadline ?deadlinedate]
1188 | ]
1189 | }
1190 | #+END_QUERY
1191 | `,
1192 |
1193 | // test 21
1194 | `title: find blocks with deadlines in a date range
1195 | - blocks
1196 | - *
1197 | - deadlinebetween
1198 | - :120d-before :30d-after
1199 | #+BEGIN_QUERY
1200 | {
1201 | :title [:b "find blocks with deadlines in a date range"]
1202 | :query [:find (pull ?block [*])
1203 | :in $ ?startdate ?enddate
1204 | :where
1205 | [?block :block/content ?blockcontent]
1206 | [?block :block/page ?page]
1207 | [?page :block/name ?pagename]
1208 | [?block :block/deadline ?deadlinedate]
1209 | [(>= ?deadlinedate ?startdate)]
1210 | [(<= ?deadlinedate ?enddate)]
1211 | ]
1212 | :inputs [:120d-before :30d-after]
1213 | }
1214 | #+END_QUERY
1215 | `,
1216 |
1217 | // test 22
1218 | `title: find journals
1219 | - pages
1220 | - *
1221 | - journalonly
1222 | #+BEGIN_QUERY
1223 | {
1224 | :title [:b "find journals"]
1225 | :query [:find (pull ?block [*])
1226 | :where
1227 | [?block :block/name ?pagename]
1228 | [?block :block/journal? true]
1229 | ]
1230 | }
1231 | #+END_QUERY
1232 | `,
1233 |
1234 | // test 23
1235 | `title: find journal in a date range
1236 | - pages
1237 | - *
1238 | - journalsbetween
1239 | - :today :30d-after
1240 | #+BEGIN_QUERY
1241 | {
1242 | :title [:b "find journal in a date range"]
1243 | :query [:find (pull ?block [*])
1244 | :in $ ?startdate ?enddate
1245 | :where
1246 | [?block :block/name ?pagename]
1247 | [?block :block/journal-day ?journaldate]
1248 | [(>= ?journaldate ?startdate)]
1249 | [(<= ?journaldate ?enddate)]
1250 | ]
1251 | :inputs [:today :30d-after]
1252 | }
1253 | #+END_QUERY
1254 | `,
1255 |
1256 | // test 24
1257 | `title: find journals between dates
1258 | - blocks
1259 | - *
1260 | - journalsbetween
1261 | - :30d-before :today
1262 | #+BEGIN_QUERY
1263 | {
1264 | :title [:b "find journals between dates"]
1265 | :query [:find (pull ?block [*])
1266 | :in $ ?startdate ?enddate
1267 | :where
1268 | [?block :block/content ?blockcontent]
1269 | [?block :block/page ?page]
1270 | [?page :block/name ?pagename]
1271 | [?page :block/journal-day ?journaldate]
1272 | [(>= ?journaldate ?startdate)]
1273 | [(<= ?journaldate ?enddate)]
1274 | ]
1275 | :inputs [:30d-before :today]
1276 | }
1277 | #+END_QUERY
1278 | `,
1279 |
1280 | // test 25
1281 | `title: collapse results
1282 | - pages
1283 | - testpage00*
1284 | - collapse
1285 | #+BEGIN_QUERY
1286 | {
1287 | :title [:b "collapse results"]
1288 | :query [:find (pull ?block [*])
1289 | :where
1290 | [?block :block/name ?pagename]
1291 | [(clojure.string/starts-with? ?pagename "testpage00")]
1292 | ]
1293 | :collapsed? true
1294 | }
1295 | #+END_QUERY
1296 | `,
1297 |
1298 | // test 26
1299 | `title: expand results
1300 | - pages
1301 | - testpage00*
1302 | - expand
1303 | #+BEGIN_QUERY
1304 | {
1305 | :title [:b "expand results"]
1306 | :query [:find (pull ?block [*])
1307 | :where
1308 | [?block :block/name ?pagename]
1309 | [(clojure.string/starts-with? ?pagename "testpage00")]
1310 | ]
1311 | :collapsed? false
1312 | }
1313 | #+END_QUERY
1314 | `,
1315 |
1316 | // test 27
1317 | `title: show breadcrumbs
1318 | - pages
1319 | - testpage00*
1320 | - showbreadcrumb
1321 | #+BEGIN_QUERY
1322 | {
1323 | :title [:b "show breadcrumbs"]
1324 | :query [:find (pull ?block [*])
1325 | :where
1326 | [?block :block/name ?pagename]
1327 | [(clojure.string/starts-with? ?pagename "testpage00")]
1328 | ]
1329 | :breadcrumb-show? true
1330 | }
1331 | #+END_QUERY
1332 | `,
1333 |
1334 | // test 28
1335 | `title: hide breadcrumbs
1336 | - pages
1337 | - testpage00*
1338 | - hidebreadcrumb
1339 | #+BEGIN_QUERY
1340 | {
1341 | :title [:b "hide breadcrumbs"]
1342 | :query [:find (pull ?block [*])
1343 | :where
1344 | [?block :block/name ?pagename]
1345 | [(clojure.string/starts-with? ?pagename "testpage00")]
1346 | ]
1347 | :breadcrumb-show? false
1348 | }
1349 | #+END_QUERY
1350 | `,
1351 |
1352 | // test 29
1353 | `title: find journal in a date range using blocks
1354 | - blocks
1355 | - *
1356 | - journalsbetween
1357 | - :today :30d-after
1358 | #+BEGIN_QUERY
1359 | {
1360 | :title [:b "find journal in a date range using blocks"]
1361 | :query [:find (pull ?block [*])
1362 | :in $ ?startdate ?enddate
1363 | :where
1364 | [?block :block/content ?blockcontent]
1365 | [?block :block/page ?page]
1366 | [?page :block/name ?pagename]
1367 | [?page :block/journal-day ?journaldate]
1368 | [(>= ?journaldate ?startdate)]
1369 | [(<= ?journaldate ?enddate)]
1370 | ]
1371 | :inputs [:today :30d-after]
1372 | }
1373 | #+END_QUERY
1374 | `,
1375 | // test 30
1376 | `title: All blocks - test access to parent pages tags, journal
1377 | - blocks
1378 | - *
1379 | - tasks
1380 | - TODO
1381 | - pagetags
1382 | - classC
1383 | #+BEGIN_QUERY
1384 | {
1385 | :title [:b "All blocks - test access to parent pages tags, journal"]
1386 | :query [:find (pull ?block [*])
1387 | :where
1388 | [?block :block/content ?blockcontent]
1389 | [?block :block/page ?page]
1390 | [?page :block/name ?pagename]
1391 | [?block :block/marker ?marker]
1392 | [(contains? #{"TODO"} ?marker)]
1393 | [?page :block/journal? false]
1394 | (page-tags ?page #{"classc"})
1395 | ]
1396 | }
1397 | #+END_QUERY
1398 | `,
1399 | // test 31
1400 | `title: Pages only - Access page properties
1401 | - pages
1402 | - *
1403 | - pageproperties
1404 | - pagetype, "p-minor"
1405 | #+BEGIN_QUERY
1406 | {
1407 | :title [:b "Pages only - Access page properties"]
1408 | :query [:find (pull ?block [*])
1409 | :where
1410 | [?block :block/name ?pagename]
1411 | (page-property ?block :pagetype "p-minor")
1412 | ]
1413 | }
1414 | #+END_QUERY
1415 | `,
1416 | // test 32
1417 | `title: Pages only - access multiple property values
1418 | - pages
1419 | - *
1420 | - pageproperties
1421 | - pagetype, "p-minor"
1422 | - pagetype, "p-major"
1423 | #+BEGIN_QUERY
1424 | {
1425 | :title [:b "Pages only - access multiple property values"]
1426 | :query [:find (pull ?block [*])
1427 | :where
1428 | [?block :block/name ?pagename]
1429 | ( or
1430 | (page-property ?block :pagetype "p-minor")
1431 | (page-property ?block :pagetype "p-major")
1432 | )
1433 | ]
1434 | }
1435 | #+END_QUERY
1436 | `,
1437 | // test 33
1438 | `title: Page blocks only - pagetags
1439 | - pages
1440 | - *
1441 | - pagetags
1442 | - classC
1443 | #+BEGIN_QUERY
1444 | {
1445 | :title [:b "Page blocks only - pagetags"]
1446 | :query [:find (pull ?block [*])
1447 | :where
1448 | [?block :block/name ?pagename]
1449 | [?block :block/journal? false]
1450 | (page-tags ?block #{"classc"})
1451 | ]
1452 | }
1453 | #+END_QUERY
1454 | `,
1455 | // test 34
1456 | `title: Pages only - select all pages
1457 | - pages
1458 | - *
1459 | #+BEGIN_QUERY
1460 | {
1461 | :title [:b "Pages only - select all pages"]
1462 | :query [:find (pull ?block [*])
1463 | :where
1464 | [?block :block/name ?pagename]
1465 | ]
1466 | }
1467 | #+END_QUERY
1468 | `,
1469 | // test 35
1470 | `title: pages command - specific pages
1471 | - pages
1472 | - testpage001
1473 | - testpage002
1474 | #+BEGIN_QUERY
1475 | {
1476 | :title [:b "pages command - specific pages"]
1477 | :query [:find (pull ?block [*])
1478 | :where
1479 | [?block :block/name ?pagename]
1480 | ( or
1481 | [?block :block/name "testpage001"]
1482 | [?block :block/name "testpage002"]
1483 | )
1484 | ]
1485 | }
1486 | #+END_QUERY
1487 | `,
1488 | // test 36
1489 | `title: pages command - pages by wildcards
1490 | - pages
1491 | - testpage00*
1492 | #+BEGIN_QUERY
1493 | {
1494 | :title [:b "pages command - pages by wildcards"]
1495 | :query [:find (pull ?block [*])
1496 | :where
1497 | [?block :block/name ?pagename]
1498 | [(clojure.string/starts-with? ?pagename "testpage00")]
1499 | ]
1500 | }
1501 | #+END_QUERY
1502 | `,
1503 | // test 37
1504 | `title: pages command - pages by wildcards
1505 | - pages
1506 | - *002
1507 | #+BEGIN_QUERY
1508 | {
1509 | :title [:b "pages command - pages by wildcards"]
1510 | :query [:find (pull ?block [*])
1511 | :where
1512 | [?block :block/name ?pagename]
1513 | [(clojure.string/ends-with? ?pagename "002")]
1514 | ]
1515 | }
1516 | #+END_QUERY
1517 | `,
1518 | // test 38
1519 | `title: journalsbetween defaulting to blocks retrieval
1520 | - journalsbetween
1521 | - :today :30d-after
1522 | #+BEGIN_QUERY
1523 | ;; WARNING: Must have 'pages' command or 'blocks' Command
1524 | ;; otherwise the query cannot get any information
1525 | ;; Inserting a blocks command for you
1526 |
1527 | {
1528 | :title [:b "journalsbetween defaulting to blocks retrieval"]
1529 | :query [:find (pull ?block [*])
1530 | :in $ ?startdate ?enddate
1531 | :where
1532 | [?block :block/content ?blockcontent]
1533 | [?block :block/page ?page]
1534 | [?page :block/name ?pagename]
1535 | [?page :block/journal-day ?journaldate]
1536 | [(>= ?journaldate ?startdate)]
1537 | [(<= ?journaldate ?enddate)]
1538 | ]
1539 | :inputs [:today :30d-after]
1540 | }
1541 | #+END_QUERY
1542 | `,
1543 | // test 39
1544 | `title: journalsbetween using pages retrieval
1545 | - pages
1546 | - *
1547 | - journalsbetween
1548 | - :today :30d-after
1549 | #+BEGIN_QUERY
1550 | {
1551 | :title [:b "journalsbetween using pages retrieval"]
1552 | :query [:find (pull ?block [*])
1553 | :in $ ?startdate ?enddate
1554 | :where
1555 | [?block :block/name ?pagename]
1556 | [?block :block/journal-day ?journaldate]
1557 | [(>= ?journaldate ?startdate)]
1558 | [(<= ?journaldate ?enddate)]
1559 | ]
1560 | :inputs [:today :30d-after]
1561 | }
1562 | #+END_QUERY
1563 | `,
1564 | // test 40
1565 | `title: page property combinations using and and or
1566 | - pages
1567 | - *
1568 | - pageproperties
1569 | - pagecategory, "p-minor"
1570 | - or pagecategory, "p-minimum"
1571 | - and pagetype, "p-type1"
1572 | #+BEGIN_QUERY
1573 | {
1574 | :title [:b "page property combinations using and and or"]
1575 | :query [:find (pull ?block [*])
1576 | :where
1577 | [?block :block/name ?pagename]
1578 | ( or
1579 | (page-property ?block :pagecategory "p-minor")
1580 | (page-property ?block :pagecategory "p-minimum")
1581 | )
1582 | (page-property ?block :pagetype "p-type1")
1583 | ]
1584 | }
1585 | #+END_QUERY
1586 | `,
1587 | // test 41
1588 | `title: page tag combinations using and and or
1589 | - pages
1590 | - *
1591 | - pagetags
1592 | - classA
1593 | - or classB
1594 | - and classH
1595 | #+BEGIN_QUERY
1596 | {
1597 | :title [:b "page tag combinations using and and or"]
1598 | :query [:find (pull ?block [*])
1599 | :where
1600 | [?block :block/name ?pagename]
1601 | [?block :block/journal? false]
1602 | ( or
1603 | (page-tags ?block #{"classa"})
1604 | (page-tags ?block #{"classb"})
1605 | )
1606 | (page-tags ?block #{"classh"})
1607 | ]
1608 | }
1609 | #+END_QUERY
1610 | `,
1611 | // test 42
1612 | `title: block property combinations using and and or
1613 | - blocks
1614 | - *
1615 | - blockproperties
1616 | - category, "b-fiction"
1617 | - or grade, "b-western"
1618 | - and category, "b-travel"
1619 | #+BEGIN_QUERY
1620 | {
1621 | :title [:b "block property combinations using and and or"]
1622 | :query [:find (pull ?block [*])
1623 | :where
1624 | [?block :block/content ?blockcontent]
1625 | [?block :block/page ?page]
1626 | [?page :block/name ?pagename]
1627 | ( or
1628 | (property ?block :category "b-fiction")
1629 | (property ?block :grade "b-western")
1630 | )
1631 | (property ?block :category "b-travel")
1632 | ]
1633 | }
1634 | #+END_QUERY
1635 | `,
1636 | // test 43
1637 | `title: block tag combinations using and and or
1638 | - blocks
1639 | - *
1640 | - blocktags
1641 | - tagA
1642 | - or tagB
1643 | - and tagD
1644 | #+BEGIN_QUERY
1645 | {
1646 | :title [:b "block tag combinations using and and or"]
1647 | :query [:find (pull ?block [*])
1648 | :where
1649 | [?block :block/content ?blockcontent]
1650 | [?block :block/page ?page]
1651 | [?page :block/name ?pagename]
1652 | ( or
1653 | (page-ref ?block "taga")
1654 | (page-ref ?block "tagb")
1655 | )
1656 | (page-ref ?block "tagd")
1657 | ]
1658 | }
1659 | #+END_QUERY
1660 | `,
1661 | // test 44
1662 | `title: task and or combintions
1663 | - blocks
1664 | - *
1665 | - tasks
1666 | - TODO
1667 | - and WAITING
1668 | - or LATER
1669 | - not DOING
1670 | #+BEGIN_QUERY
1671 | {
1672 | :title [:b "task and or combintions"]
1673 | :query [:find (pull ?block [*])
1674 | :where
1675 | [?block :block/content ?blockcontent]
1676 | [?block :block/page ?page]
1677 | [?page :block/name ?pagename]
1678 | [?block :block/marker ?marker]
1679 | ( or
1680 | [(contains? #{"TODO"} ?marker)]
1681 | [(contains? #{"LATER"} ?marker)]
1682 | )
1683 | [(contains? #{"WAITING"} ?marker)]
1684 | (not [(contains? #{"DOING"} ?marker)])
1685 | ]
1686 | }
1687 | #+END_QUERY
1688 | `,
1689 | // test 45
1690 | `title: select blocks with links to pages
1691 | - blocks
1692 | - *
1693 | - pagelinks
1694 | - gardening
1695 | - vegetables
1696 | - not turnips
1697 | #+BEGIN_QUERY
1698 | {
1699 | :title [:b "select blocks with links to pages"]
1700 | :query [:find (pull ?block [*])
1701 | :where
1702 | [?block :block/content ?blockcontent]
1703 | [?block :block/page ?page]
1704 | [?page :block/name ?pagename]
1705 | ( or
1706 | [?block :block/path-refs [:block/name "gardening"]]
1707 | [?block :block/path-refs [:block/name "vegetables"]]
1708 | )
1709 | (not [?block :block/path-refs [:block/name "turnips"]])
1710 | ]
1711 | }
1712 | #+END_QUERY
1713 | `,
1714 | // test 46
1715 | `title: select blocks with links to journals
1716 | - blocks
1717 | - *
1718 | - pagelinks
1719 | - Dec 25th, 2022
1720 | - Jan 1st, 2019
1721 | #+BEGIN_QUERY
1722 | {
1723 | :title [:b "select blocks with links to journals"]
1724 | :query [:find (pull ?block [*])
1725 | :where
1726 | [?block :block/content ?blockcontent]
1727 | [?block :block/page ?page]
1728 | [?page :block/name ?pagename]
1729 | ( or
1730 | [?block :block/path-refs [:block/name "dec 25th, 2022"]]
1731 | [?block :block/path-refs [:block/name "jan 1st, 2019"]]
1732 | )
1733 | ]
1734 | }
1735 | #+END_QUERY
1736 | `
1737 |
1738 | ]
1739 |
1740 | function test_queryDBRead(section, key) {
1741 | try {
1742 | read1 = querylineDict[section][key]['name']
1743 | read2 = querylineDict[section][key]['segment']
1744 | read3 = querylineDict[section][key]['segment']
1745 | read4 = querylineDict[section][key]['datalog']
1746 | read5 = querylineDict[section][key]['comment']
1747 | // return read1
1748 | return read1 + '\n' + read2 + '\n' + read3 + '\n' + read4 + '\n' + read5 + '\n'
1749 |
1750 | } catch {
1751 | return "Failed"
1752 | }
1753 | }
1754 |
1755 |
1756 |
1757 |
1758 | function add(num1, num2) {
1759 | return num1 + num2
1760 | }
1761 |
1762 |
1763 | // ========= global variables
1764 |
1765 | // ---query structure
1766 | var query_template = {
1767 | "start": [],
1768 | "errors": [],
1769 | "open": [],
1770 | "title": [],
1771 | "query": [],
1772 | "in": [],
1773 | "where": [],
1774 | "filters": [],
1775 | "closefind": [],
1776 | "inputs": [],
1777 | "view": [],
1778 | "options": [],
1779 | "closequery": [],
1780 | "end": []
1781 | }
1782 |
1783 | var codeblock = false
1784 | var mode = "javascript"
1785 | query = query_template
1786 | querygroup = "pages-querylines"
1787 | querylineDBDict = {}
1788 | showcommandcomments = false
1789 |
1790 | // =========== FUNCTIONS ================
1791 |
1792 | function initialiseQuery() {
1793 | query = query_template;
1794 | for (key of Object.keys(query)) {
1795 | query[key] = []
1796 | }
1797 | return query;
1798 | }
1799 |
1800 | function initialisteQueryLineDict() {
1801 | var tempDict;
1802 | tempDict = {};
1803 | tempDict["pages-querylines"] = querylineDict["pages-querylines"];
1804 | tempDict["blocks-querylines"] = querylineDict["blocks-querylines"];
1805 |
1806 | for (const [commonqueryline, value] of Object.entries(querylineDict['common-querylines'])) {
1807 | tempDict["pages-querylines"][commonqueryline] = querylineDict["common-querylines"][commonqueryline];
1808 | tempDict["blocks-querylines"][commonqueryline] = querylineDict["common-querylines"][commonqueryline];
1809 | }
1810 | return tempDict;
1811 | }
1812 |
1813 |
1814 |
1815 | function getQueryLineSegment(querylinekey) {
1816 | var errormsg, errortext;
1817 |
1818 | try {
1819 | return ["ok", querylineDBDict[querygroup][querylinekey]["segment"]];
1820 | } catch (e) {
1821 | errortext = querylinekey + " segment value not found in QueryDB\n";
1822 | errormsg = ";; **ERROR: " + errortext + "\n";
1823 | return ["error", errormsg];
1824 | }
1825 | }
1826 |
1827 |
1828 | function getQueryLine(querylinekey, querysegment) {
1829 | var errormsg;
1830 |
1831 | try {
1832 | if (showcommandcomments === true) {
1833 | var comment = getQueryLineComment(querylinekey)
1834 | if (comment != '') {
1835 | if (!query[querysegment].includes('\n' + comment)) {
1836 | query[querysegment].push("\n" + getQueryLineComment(querylinekey));
1837 | }
1838 | }
1839 | }
1840 |
1841 | return querylineDBDict[querygroup][querylinekey]["datalog"];
1842 | } catch (e) {
1843 | errormsg = "\n---- COMMAND ERROR ----\n";
1844 | errormsg += querylinekey + " not found in QueryDB or invalid usage\n";
1845 |
1846 | if (querygroup === "pages-querylines") {
1847 | errormsg += querylinekey + " invalid within a 'pages' command query";
1848 | }
1849 |
1850 | if (querygroup === "blocks-querylines") {
1851 | errormsg += querylinekey + " invalid within a 'blocks' command query";
1852 | }
1853 |
1854 | errormsg += "\n----------------------\n";
1855 | return errormsg;
1856 | }
1857 | }
1858 |
1859 | function getQueryLineComment(querylinekey) {
1860 | var comment, separator;
1861 | separator = ''
1862 | try {
1863 | comment = querylineDBDict[querygroup][querylinekey]["comment"];
1864 | if (comment == '') {
1865 | return ''
1866 | }
1867 | return separator + ";; ---- " + comment;
1868 | } catch (e) {
1869 | return querylinekey + " not found in queryline Dictionary";
1870 | }
1871 | }
1872 |
1873 | function getCommandQueryLineKeys(command) {
1874 | var commandlist;
1875 |
1876 | if (command === null) {
1877 | return null;
1878 | }
1879 |
1880 | try {
1881 | commandlist = commandsDict[command]["querylines"];
1882 | } catch (e) {
1883 | return null;
1884 | }
1885 |
1886 | return commandlist;
1887 | }
1888 |
1889 |
1890 | function processCommand(command, commandLinesDict) {
1891 | var commandline, commandvalidity, negativecommandlines, originalcommandlines, positivecommandlines, queryline, querylinekeys, querysegment, querysegmentdata, querysegmentresponse;
1892 | commandvalidity = checkCommandValid(command);
1893 |
1894 | if (commandvalidity[0] === false) {
1895 | query["errors"].push(commandvalidity[1]);
1896 | return;
1897 | }
1898 |
1899 | querylinekeys = getCommandQueryLineKeys(command);
1900 |
1901 | if (querylinekeys === null) {
1902 | return [command + " is not a valid command"];
1903 | }
1904 |
1905 | for (value of querylinekeys) {
1906 | querysegmentresponse = getQueryLineSegment(value);
1907 |
1908 | querysegmentdata = querysegmentresponse[1];
1909 |
1910 | if (querysegmentresponse[0] === "error") {
1911 | query["errors"].push(querysegmentdata);
1912 | continue;
1913 | }
1914 |
1915 | querysegment = querysegmentdata;
1916 | queryline = getQueryLine(value, querysegment);
1917 |
1918 | if (query[querysegment].includes(queryline)) {
1919 | continue;
1920 | }
1921 |
1922 | query[querysegment].push(queryline);
1923 | }
1924 |
1925 | // sort the argument lines by positive and negative
1926 | positivecommandlines = [];
1927 | negativecommandlines = [];
1928 | originalcommandlines = commandLinesDict[command]["commandlines"].slice(1);
1929 |
1930 |
1931 | for (commandline of originalcommandlines) {
1932 | if (commandline.trim().substring(2).startsWith("not ") || commandline.trim().substring(2).startsWith("and ")) {
1933 | commandline = commandline.replace("and ", "");
1934 | negativecommandlines.push(commandline);
1935 | } else {
1936 | if (commandline.trim().substring(2).startsWith("or ")) {
1937 | commandline = commandline.replace("or ", "");
1938 | positivecommandlines.push(commandline);
1939 | } else {
1940 | positivecommandlines.push(commandline);
1941 | }
1942 | }
1943 | }
1944 |
1945 | if (positivecommandlines.length > 0) {
1946 | processCommandLines("include", command, positivecommandlines);
1947 | }
1948 |
1949 | if (negativecommandlines.length > 0) {
1950 | processCommandLines("exclude", command, negativecommandlines);
1951 | }
1952 |
1953 | return;
1954 | }
1955 |
1956 | function checkCommandValid(command) {
1957 | var commandvalidity, errormessage;
1958 | commandvalidity = true;
1959 | errormessage = "";
1960 |
1961 | if (querygroup === "pages-querylines") {
1962 | if (command === "blocktags") {
1963 | commandvalidity = false;
1964 | errormessage = "\n;; **ERROR: " + command + " not valid with pages command use blocks command instead\n";
1965 | } else {
1966 | if (command === "tasks" || command === "pagelinks") {
1967 | commandvalidity = false;
1968 | errormessage = "\n;; **ERROR: " + command + " not valid with pages command use blocks command instead\n";
1969 | }
1970 | }
1971 | } else {
1972 | if (querygroup === "blocks-querylines") {
1973 | if ([].includes(command)) {
1974 | commandvalidity = false;
1975 | }
1976 | }
1977 | }
1978 |
1979 | return [commandvalidity, errormessage];
1980 | }
1981 |
1982 | function addQueryLines(command, prefix, querylinekey, arg) {
1983 | var arg1, arg2, args, querysegment, querysegmentdata, querysegmentresponse, updatedqueryline;
1984 | querysegment = getQueryLineSegment(querylinekey);
1985 | querysegmentresponse = getQueryLineSegment(querylinekey)[0];
1986 | querysegmentdata = getQueryLineSegment(querylinekey)[1];
1987 |
1988 | if (querysegmentresponse === "error") {
1989 | query["errors"].push(querysegmentdata);
1990 | return;
1991 | }
1992 |
1993 | querysegment = querysegmentdata;
1994 | if (command == 'pagelinks') {
1995 | args = []
1996 | args.push(arg)
1997 | } else {
1998 | args = arg.split(",");
1999 | }
2000 |
2001 | if (args.length === 1) {
2002 | querylinekey = prefix + querylinekey;
2003 | updatedqueryline = getQueryLine(querylinekey, querysegment).replace("$$ARG1", arg);
2004 |
2005 | if (!query[querysegment].includes(updatedqueryline)) {
2006 | query[querysegment].push(updatedqueryline);
2007 | }
2008 | } else {
2009 | if (args.length === 2) {
2010 | arg1 = args[0].trim();
2011 | arg2 = args[1].trim();
2012 | querylinekey = prefix + querylinekey;
2013 | updatedqueryline = getQueryLine(querylinekey, querysegment).replace("$$ARG1", arg1);
2014 | updatedqueryline = updatedqueryline.replace("$$ARG2", arg2);
2015 |
2016 | if (!query[querysegment].includes(updatedqueryline)) {
2017 | query[querysegment].push(updatedqueryline);
2018 | }
2019 | } else {
2020 | query[querysegment].push(command + " => Invalid line => " + arg);
2021 | }
2022 | }
2023 | }
2024 |
2025 | function processCommandLines(action, command, commandlines) {
2026 | var arg, args, firstline, lastline, prefix;
2027 |
2028 | if (commandlines === []) {
2029 | return;
2030 | }
2031 |
2032 | firstline = "";
2033 | lastline = "";
2034 |
2035 | if (["pages", "blocks", "blocktags", "pagetags", "pagelinks", "tasks", "pageproperties", "blockproperties", "namespace"].includes(command)) {
2036 | if (commandlines.length > 1) {
2037 | if (action === "include") {
2038 | firstline = "( or ";
2039 | lastline = ")";
2040 | }
2041 | }
2042 | }
2043 |
2044 | if (firstline !== "") {
2045 | query["filters"].push(firstline);
2046 | }
2047 |
2048 | for (arg of commandlines) {
2049 | arg = arg.trim().substring(2);
2050 |
2051 | if (arg === "") {
2052 | continue;
2053 | }
2054 |
2055 | if (arg === "*") {
2056 | continue;
2057 | }
2058 |
2059 | prefix = "";
2060 |
2061 | if (arg.startsWith("not ")) {
2062 | prefix = "not_";
2063 | arg = arg.substring(prefix.length);
2064 | }
2065 |
2066 | if (command === "pages") {
2067 | if (arg[0] !== "*" && arg[arg.length - 1] === "*") {
2068 | addQueryLines(command, prefix, "arg_pagename_startswith", arg.substring(0, arg.length - 1));
2069 | continue;
2070 | }
2071 |
2072 | if (arg[0] === "*" && arg[arg.length - 1] !== "*") {
2073 | addQueryLines(command, prefix, "arg_pagename_endswith", arg.substring(1));
2074 | continue;
2075 | }
2076 |
2077 | if (arg[0] === "*" && arg[arg.length - 1] === "*") {
2078 | addQueryLines(command, prefix, "arg_pagename_contains", arg.substring(1, arg.length - 1));
2079 | continue;
2080 | }
2081 |
2082 | addQueryLines(command, prefix, "pagename_is", arg);
2083 | }
2084 |
2085 | if (command === "blocks") {
2086 | if (arg[0] !== "*" && arg[arg.length - 1] === "*") {
2087 | addQueryLines(command, prefix, "arg_blockcontent_startswith", arg.substring(0, arg.length - 1));
2088 | continue;
2089 | }
2090 |
2091 | if (arg[0] === "*" && arg[arg.length - 1] !== "*") {
2092 | addQueryLines(command, prefix, "arg_blockcontent_endswith", arg.substring(1));
2093 | continue;
2094 | }
2095 |
2096 | if (arg[0] === "*" && arg[arg.length - 1] === "*") {
2097 | addQueryLines(command, prefix, "arg_blockcontent_contains", arg.substring(1, arg.length - 1));
2098 | continue;
2099 | }
2100 | }
2101 |
2102 | if (command === "pagetags") {
2103 | args = arg.split();
2104 |
2105 | for (arg of args) {
2106 | addQueryLines(command, prefix, "pagetags_are", arg.toLowerCase());
2107 | }
2108 | }
2109 |
2110 | if (command === "blocktags") {
2111 | args = arg.split();
2112 |
2113 | for (arg of args) {
2114 | addQueryLines(command, prefix, "blocktags_are", arg.toLowerCase());
2115 | }
2116 | }
2117 |
2118 | if (command === "pageproperties") {
2119 | addQueryLines(command, prefix, "page_properties_are", arg);
2120 | }
2121 |
2122 | if (command === "blockproperties") {
2123 | addQueryLines(command, prefix, "block_properties_are", arg);
2124 | }
2125 |
2126 | if (command === "pagelinks") {
2127 | args = arg.split();
2128 |
2129 | for (arg of args) {
2130 | addQueryLines(command, prefix, "pagelinks_are", arg.toLowerCase());
2131 | }
2132 | }
2133 | if (command === "tasks") {
2134 | addQueryLines(command, prefix, "tasks_are", arg);
2135 | }
2136 |
2137 | if (command === "namespace") {
2138 | addQueryLines(command, prefix, "namespace", arg);
2139 | }
2140 |
2141 | if (command === "scheduled") {
2142 | addQueryLines(command, prefix, "scheduled", arg);
2143 | }
2144 |
2145 | if (command === "scheduledbetween") {
2146 | addQueryLines(command, prefix, "scheduledbetween", arg);
2147 | }
2148 |
2149 | if (command === "deadline") {
2150 | addQueryLines(command, prefix, "deadline", arg);
2151 | }
2152 |
2153 | if (command === "deadlinebetween") {
2154 | addQueryLines(command, prefix, "deadlinebetween", arg);
2155 | }
2156 |
2157 | if (command === "journalonly") {
2158 | addQueryLines(command, prefix, "page_is_journal", arg);
2159 | }
2160 |
2161 | if (command === "journalsbetween") {
2162 | addQueryLines(command, prefix, "journalsbetween", arg);
2163 | }
2164 |
2165 | if (command === "daterange") {
2166 | addQueryLines(command, prefix, "daterange", arg);
2167 | }
2168 |
2169 | if (command === "collapse") {
2170 | addQueryLines(command, prefix, "collapse", arg);
2171 | }
2172 |
2173 | if (command === "collapse") {
2174 | addQueryLines(command, prefix, "expand", arg);
2175 | }
2176 | }
2177 |
2178 | if (lastline !== "") {
2179 | query["filters"].push(lastline);
2180 | }
2181 |
2182 | return;
2183 | }
2184 |
2185 | function insertQueryLineIntoSegment(key) {
2186 | var querysegment, querysegmentdata, querysegmentresponse;
2187 | querysegmentresponse = getQueryLineSegment(key)[0];
2188 | querysegmentdata = getQueryLineSegment(key)[1];
2189 |
2190 | if (querysegmentresponse === "error") {
2191 | query["errors"].push(querysegmentdata);
2192 | return;
2193 | }
2194 |
2195 | querysegment = querysegmentdata;
2196 | query[key].push(getQueryLine(key, querysegment));
2197 | }
2198 |
2199 | function checkUsingPagesorBlocks(commandlines) {
2200 | var blocksfound, commandline, pagesfound
2201 | pagesfound = false;
2202 | blocksfound = false;
2203 |
2204 | for (commandline of commandlines) {
2205 |
2206 | commandline = commandline.trim();
2207 |
2208 | if (commandline.startsWith("- pages")) {
2209 | pagesfound = true;
2210 | }
2211 |
2212 | if (commandline.startsWith("- blocks")) {
2213 | blocksfound = true;
2214 | }
2215 | }
2216 |
2217 | if (pagesfound === true && blocksfound === false) {
2218 | querygroup = "pages-querylines";
2219 | return;
2220 | }
2221 |
2222 | if (blocksfound === true && pagesfound === false) {
2223 | querygroup = "blocks-querylines";
2224 | return;
2225 | }
2226 |
2227 | if (pagesfound === false && blocksfound === false) {
2228 | query["errors"].push(";; WARNING: Must have 'pages' command or 'blocks' Command\n;; otherwise the query cannot get any information\n;; Inserting a blocks command for you\n");
2229 | insertBlocksCommand(commandlines);
2230 | blocksfound = true;
2231 | querygroup = "blocks-querylines";
2232 | return;
2233 | }
2234 |
2235 | if (pagesfound && blocksfound) {
2236 | query["errors"].push(";; ERROR: Cannot have 'pages' command and 'blocks' command together in a command list\n\n");
2237 | return;
2238 | }
2239 | }
2240 |
2241 | function insertBlocksCommand(commandlines) {
2242 | if (commandlines.length > 0) {
2243 | if (commandlines[0].indexOf("title:") > -1) {
2244 | commandlines.splice(1, 0, " - *");
2245 | commandlines.splice(1, 0, "- blocks");
2246 | }
2247 | } else {
2248 | commandlines.splice(0, 0, "- blocks\n - *\n");
2249 | }
2250 | return;
2251 | }
2252 |
2253 | function validCommand(command) {
2254 | try {
2255 | if (commandsDict[command]) {
2256 | return true;
2257 | } else {
2258 | return false
2259 | }
2260 | } catch (e) {
2261 | return false;
2262 | }
2263 | }
2264 |
2265 | function processCommandList(commandlists) {
2266 | var commandLinesDict, commandlines, commandname, currentcommand, fields, query;
2267 | query = initialiseQuery();
2268 | commandlines = commandlists.split("\n");
2269 | checkUsingPagesorBlocks(commandlines);
2270 | currentcommand = "";
2271 | commandLinesDict = {};
2272 |
2273 | for (line of commandlines) {
2274 |
2275 | if (line === "" || line.startsWith(";;")) {
2276 | continue;
2277 | }
2278 |
2279 | if (line.trim().startsWith("title:")) {
2280 | query["title"].push(getQueryLine("title", "title").replace("$$ARG1", line.split(":")[1].trim()));
2281 | continue;
2282 | }
2283 |
2284 | if (line.trim().startsWith("option:")) {
2285 | var option = line.split(":")[1].trim()
2286 | if (option == "includecomments") {
2287 | setshowcommandcomments(true)
2288 | } else {
2289 | query['errors'].push(
2290 | ";; WARNING: '" + line + "' is not valid option. \n;; Valid options: includecomments")
2291 | }
2292 | continue;
2293 | }
2294 |
2295 | if (line.startsWith("- ")) {
2296 | fields = line.split(" ");
2297 | commandname = fields[1];
2298 |
2299 | if (validCommand(commandname)) {
2300 | commandLinesDict[commandname] = {};
2301 |
2302 | if (currentcommand === "" || line !== currentcommand) {
2303 | currentcommand = commandname;
2304 | commandLinesDict[commandname]["commandlines"] = [];
2305 | commandLinesDict[commandname]["commandlines"].push(line);
2306 | continue;
2307 | }
2308 | } else {
2309 | query["errors"].push(";; WARNING: '" + line + "' is not valid command.\n;; Either a mispelt command or no leading dash");
2310 | // continue;
2311 | }
2312 | } else {
2313 | if (line.startsWith(" ") && line.trim().startsWith("- ")) {
2314 | if (currentcommand === "") {
2315 | query["errors"].push(";; ERROR: '" + line + "' is a command argument but does not have a parent command\n;; Either a command is missing (or invalid) or this should be an argument line");
2316 | } else {
2317 | if (validCommand(commandname)) {
2318 | commandLinesDict[commandname]["commandlines"].push(line);
2319 | } else {
2320 | query["errors"].push(";; ERROR: '" + line + "' is a command argument but does not have a parent command\n;; Either a command is missing (or invalid) or this should be an argument line");
2321 | }
2322 | }
2323 | } else {
2324 | if (line.includes("title ")) {
2325 | query["errors"].push(";; WARNING: title line should start with title:");
2326 | } else {
2327 | if (!line.trim().startsWith("- ") && !(line.indexOf("title:") > -1)) {
2328 | query["errors"].push(";; WARNING: " + line + " has no leading hypen eg '- pages'");
2329 | }
2330 | }
2331 | }
2332 | }
2333 | }
2334 |
2335 | insertQueryLineIntoSegment("start");
2336 | insertQueryLineIntoSegment("open");
2337 | insertQueryLineIntoSegment("where");
2338 | insertQueryLineIntoSegment("closefind");
2339 | insertQueryLineIntoSegment("closequery");
2340 | insertQueryLineIntoSegment("end");
2341 |
2342 | for (command in commandLinesDict) {
2343 | processCommand(command, commandLinesDict);
2344 | }
2345 |
2346 | query["closefind"] = [getQueryLine("closefind", "closefind")];
2347 | query["closequery"] = [getQueryLine("closequery", "closequery")];
2348 | query["end"] = [getQueryLine("end", "end")];
2349 | return;
2350 | }
2351 |
2352 |
2353 | function constructQuery() {
2354 | var advancedquery;
2355 | advancedquery = "";
2356 |
2357 | for (const [key, value] of Object.entries(query)) {
2358 | for (let j = 0; j < query[key].length; j++) {
2359 | queryline = query[key][j]
2360 | advancedquery += queryline + "\n";
2361 | }
2362 | }
2363 | return advancedquery;
2364 | }
2365 |
2366 | function printGeneratedAdvancedQuery(advancedquery) {
2367 | var msg, prefix, suffix;
2368 |
2369 | if (codeblock) {
2370 | prefix = "```clojure\n";
2371 | suffix = "```";
2372 | } else {
2373 | prefix = "";
2374 | suffix = "";
2375 | }
2376 |
2377 | if (mode === "website") {
2378 | // msg = prefix + advancedquery.replace("\n", "
") + suffix;
2379 | msg = prefix + advancedquery + suffix;
2380 | websitePrintToDiv('advanced_query', msg)
2381 | } else {
2382 | console.log("----------------------------");
2383 | console.log("Logseq Advanced Query");
2384 | console.log("----------------------------");
2385 | console.log(prefix + advancedquery + suffix);
2386 | }
2387 | }
2388 |
2389 |
2390 | // global value functions
2391 | function getquerygroup() {
2392 | return querygroup
2393 | }
2394 |
2395 | function setquerygroup(value) {
2396 | querygroup = value
2397 | }
2398 |
2399 | function getshowcommandcomments() {
2400 | return showcommandcomments
2401 | }
2402 |
2403 | function setshowcommandcomments(value) {
2404 | showcommandcomments = value
2405 | }
2406 |
2407 | function getcodeblock() {
2408 | return codeblock
2409 | }
2410 |
2411 | function setcodeblock(value) {
2412 | codeblock = value
2413 | }
2414 |
2415 | function getquerylineDBDict() {
2416 | return querylineDBDict
2417 | }
2418 |
2419 | function setquerylineDBDict(value) {
2420 | querylineDBDict = value
2421 | }
2422 |
2423 | // Test queryTestDB works
2424 | function test_queryTestDBRead() {
2425 | testcases = QueryTestCases
2426 | return testcases[0];
2427 | }
2428 |
2429 | function getquerytestcases() {
2430 | return QueryTestCases
2431 | }
2432 |
2433 | function removeLastGeneratedQuery(content) {
2434 | let lines = content.split("\n")
2435 | let newcontent = ''
2436 | for (const line of lines) {
2437 | if (line.startsWith('#+BEGIN_QUERY')) {
2438 | break
2439 | }
2440 | newcontent += line + '\n'
2441 | }
2442 | return newcontent
2443 | }
2444 |
2445 | function showErrors() {
2446 | msg = 'QB: Errors Found - check built query'
2447 | if (query["errors"].length > 0) {
2448 | for (errormsg of query["errors"]) {
2449 | msg += errormsg + '\n'
2450 | }
2451 | return msg
2452 | } else {
2453 | return "QB: Query Built OK"
2454 | }
2455 | }
2456 |
2457 |
2458 | function main() {
2459 |
2460 | logseq.Editor.registerBlockContextMenuItem(
2461 | 'Advanced Query Builder',
2462 | async (e) => {
2463 | const block = await logseq.Editor.getBlock(e.uuid)
2464 | content = block.content
2465 | content = removeLastGeneratedQuery(content)
2466 | commands = content.replaceAll(/```/g, '')
2467 | showcommandcomments = false;
2468 | querygroup = "blocks-querylines";
2469 | codeblock = false;
2470 | // query = initialiseQuery();
2471 | // querylineDBDict = initialisteQueryLineDict();
2472 | // querygroup = "pages-querylines"
2473 | // logseq.App.showMsg(
2474 | // commands,
2475 | // )
2476 | setquerylineDBDict(initialisteQueryLineDict())
2477 | console.log("\ncommands\n" + commands);
2478 | console.log("\ncontent\n" + content);
2479 | initialiseQuery()
2480 | processCommandList(commands)
2481 | advancedquery = constructQuery()
2482 |
2483 | // Currently will add a child block with the generated query
2484 | // user can right click on the query and remove it or leave it there
2485 | // IDEA: Maybe always remove the last query so how do I do that
2486 | // remove any children blocks
2487 | // TODO: Returns undefined for the child uuid????? Mayne just let user insert a new child for each query execution
2488 | // if (block.children.length > 0) {
2489 | // for (let child of block.children) {
2490 | // await logseq.Editor.removeBlock(child.uuid);
2491 | // }
2492 | // }
2493 |
2494 |
2495 | // place the advanced query in a child of the current block (that has the commands in it)
2496 | await logseq.Editor.insertBlock(e.uuid, advancedquery, { sibling: false })
2497 |
2498 | logseq.App.showMsg(
2499 | showErrors()
2500 | )
2501 | })
2502 |
2503 | } // end main
2504 |
2505 | // ======== website functions
2506 |
2507 | function websiteInitialise() {
2508 |
2509 | if (mode != "website") {
2510 | return
2511 | }
2512 |
2513 | // connect the generate advanced query button
2514 | generate_query_button = document.getElementById('generate_query_button')
2515 | generate_query_button.addEventListener("click", websiteQueryBuild)
2516 |
2517 | // connect the Clear Commands button
2518 | clear_commands_button = document.getElementById('clear_commands_button')
2519 | clear_commands_button.addEventListener("click", websiteClearCommands)
2520 |
2521 | // connect the Examples button
2522 | examples_options = document.getElementById('command_examples')
2523 | examples_options.addEventListener("input", websiteChooseExample)
2524 | examples_options.value = "" // set to first option
2525 |
2526 | // connect the Command Comments Checkbox
2527 | command_comments_checkbox = document.getElementById(
2528 | 'command_comments_checkbox')
2529 | command_comments_checkbox.addEventListener("click", websiteCommandComments)
2530 | command_comments_checkbox.checked = false
2531 |
2532 | commands_input = document.getElementById('commands_input')
2533 | commands_input.value = ''
2534 |
2535 | // connect the Code Block Output Checkbox
2536 | codeblock_checkbox = document.getElementById(
2537 | 'codeblock_checkbox')
2538 | codeblock_checkbox.addEventListener("click", websiteCodeBlock)
2539 | codeblock_checkbox.checked = false
2540 |
2541 | }
2542 |
2543 | function websiteClearCommands(event) {
2544 | if (mode != "website") {
2545 | return
2546 | }
2547 |
2548 | // # hide copy to clipboard button
2549 | websitePrintToDiv('print_output', 'Clear Commands Button Pressed')
2550 | commands_input = document.getElementById('commands_input')
2551 | commands_input.value = ''
2552 | }
2553 |
2554 |
2555 | function websiteCommandComments(event) {
2556 | if (mode != "website") {
2557 | return
2558 | }
2559 | if (document.getElementById('command_comments_checkbox').checked == true) {
2560 | setshowcommandcomments(true)
2561 | } else {
2562 | setshowcommandcomments(false)
2563 | }
2564 | }
2565 |
2566 |
2567 | function websiteCodeBlock(event) {
2568 | // TODO: Check this works re global codeblock variable
2569 | if (mode != "website") {
2570 | return
2571 | }
2572 | if (document.getElementById('codeblock_checkbox').checked == true) {
2573 | codeblock = true
2574 | } else {
2575 | codeblock = false
2576 | }
2577 | }
2578 |
2579 |
2580 | function websiteChooseExample(event) {
2581 | if (mode != "website") {
2582 | return
2583 | }
2584 | // get selected Example and fill the commands Input Text Area
2585 | examples_options = document.getElementById('command_examples')
2586 | if (examples_options.value != "Choose Example..") {
2587 | advanced_query_text = document.getElementById('advanced_query')
2588 | advanced_query_text.textContent = ''
2589 | websitePrintToDiv('print_output',
2590 | "Example selected .. now press 'Generate Advanced Query' button")
2591 |
2592 | document.getElementById(
2593 | 'commands_input').value = examples_options.value
2594 | // console.log('value is ', examples_options.value)
2595 | }
2596 | }
2597 |
2598 | function websiteAdvancedQueryText(event) {
2599 | if (mode != "website") {
2600 | return
2601 | }
2602 | }
2603 |
2604 | function websitePrintToDiv(divname, text) {
2605 | if (mode != "website") {
2606 | return
2607 | }
2608 | document.getElementById(divname).innerText = text
2609 | }
2610 |
2611 |
2612 | function websiteQueryBuild(event) {
2613 | if (mode != "website") {
2614 | return
2615 | }
2616 |
2617 | // # hide copy to clipboard button
2618 | copy_button = document.getElementById('copy')
2619 | copy_button.setAttribute("hidden", "hidden")
2620 |
2621 | websitePrintToDiv('print_output', 'Processing Commands ..')
2622 |
2623 | commands_input = document.getElementById('commands_input')
2624 | if (!commands_input) {
2625 | websitePrintToDiv('print_output', 'Bug: Element is None')
2626 | return
2627 | }
2628 | processCommandList(commands_input.value)
2629 | advancedquery = constructQuery()
2630 | printGeneratedAdvancedQuery(advancedquery)
2631 |
2632 | // show copy to clipboard button
2633 | var copy_button = document.getElementById('copy')
2634 | hidden = copy_button.getAttribute("hidden")
2635 | copy_button.removeAttribute("hidden")
2636 |
2637 | websitePrintToDiv('print_output',
2638 | "Advanced Query Generated!\n- Tick 'Include Query Comments' if desired\n- Tick 'Copy as code block' if desired\nClick 'Copy Query to Clipboard")
2639 |
2640 | return
2641 | }
2642 |
2643 |
2644 |
2645 | // MAIN ENTRY POINT
2646 |
2647 | // *******************************
2648 | // LOCAL MODE TESTING WITH JEST TESTING
2649 | // (Comment out WEBSITE MODE section below and PLUGIN MODE section above)
2650 | // (Uncomment this section for local testing with JEST)
2651 | // *******************************
2652 | // var mode = "local"
2653 | // module.exports = {
2654 | // //querygroup,
2655 | // //showcommandcomments,
2656 | // getquerygroup,
2657 | // setquerygroup,
2658 | // getshowcommandcomments,
2659 | // setshowcommandcomments,
2660 | // getcodeblock,
2661 | // setcodeblock,
2662 | // getquerylineDBDict,
2663 | // setquerylineDBDict,
2664 | // getquerytestcases,
2665 | // add,
2666 | // test_queryDBRead,
2667 | // test_queryTestDBRead,
2668 | // addQueryLines,
2669 | // checkCommandValid,
2670 | // checkUsingPagesorBlocks,
2671 | // constructQuery,
2672 | // getCommandQueryLineKeys,
2673 | // getQueryLine,
2674 | // getQueryLineComment,
2675 | // getQueryLineSegment,
2676 | // initialiseQuery,
2677 | // initialisteQueryLineDict,
2678 | // insertBlocksCommand,
2679 | // insertQueryLineIntoSegment,
2680 | // printGeneratedAdvancedQuery,
2681 | // processCommand,
2682 | // processCommandLines,
2683 | // processCommandList,
2684 | // removeLastGeneratedQuery,
2685 | // validCommand
2686 | // }
2687 | // *******************************
2688 |
2689 | // *******************************
2690 | // LOGSEQ WEBSITE MODE
2691 | // (Comment out LOCAL MODE section above and PLUGIN mode section below and uncomment this section)
2692 | // *******************************
2693 | // mode = "website"
2694 | // *******************************
2695 |
2696 |
2697 | // *******************************
2698 | // LOGSEQ PLUGIN MODE
2699 | // (Comment out LOCAL MODE section above and WEBSITE section above and uncomment this section)
2700 | // *******************************
2701 | mode = "logseq-plugin"
2702 | // *******************************
2703 |
2704 | // MAIN STARTING POINT
2705 | if (mode == "logseq-plugin") {
2706 | console.log('logseq-advanced-query-builder plugin loaded')
2707 | logseq.ready(main).catch(console.error)
2708 | }
2709 | if (mode == "local") {
2710 | console.log('logseq-advanced-query-builder code running locally')
2711 | querygroup = "";
2712 | codeblock = false;
2713 | query = initialiseQuery();
2714 | querylineDBDict = initialisteQueryLineDict();
2715 | }
2716 | if (mode == "website") {
2717 | console.log('logseq-advanced-query-builder code running in browser')
2718 | querygroup = "";
2719 | codeblock = false;
2720 | query = initialiseQuery();
2721 | querylineDBDict = initialisteQueryLineDict();
2722 | websiteInitialise()
2723 | }
2724 |
2725 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "logseq-query-builder-plugin",
3 | "version": "0.4",
4 | "main": "index.html",
5 | "logseq": {
6 | "id": "logseq-query-builder-plugin",
7 | "title": "logseq-query-builder",
8 | "icon": "./icon.png"
9 | }
10 | }
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | /* theme colors */
2 |
3 | :root {
4 |
5 |
6 | /* Dark theme */
7 | --dark-bg: #00384d;
8 | --dark-fg: #b0e1f4c3;
9 |
10 | /* Light theme */
11 | --light-bg: #d1f0f995;
12 | --light-fg: rgb(59, 44, 44);
13 |
14 | /* Defaults
15 |
16 | For a dark theme use these lines
17 | --current-bg: var(--dark-bg);
18 | --current-fg: var(--dark-fg);
19 |
20 | For a light theme use these lines
21 | --current-bg: var(--light-bg);
22 | --current-fg: var(--light-fg);
23 |
24 | */
25 |
26 | --current-bg: var(--light-bg);
27 | --current-fg: var(--light-fg);
28 | }
29 |
30 |
31 | /* clear all padding, margins */
32 | * {
33 | padding: 0;
34 | margin: 0;
35 | box-sizing: border-box;
36 | }
37 |
38 | html {
39 | font-size: 14px;
40 | }
41 |
42 | body {
43 | padding: 1rem;
44 | font-family: 'Roboto', sans-serif;
45 | background-color: var(--current-bg);
46 | color: var(--current-fg);
47 | }
48 |
49 | a {
50 | background-color: var(--current-bg);
51 | color: var(--current-fg);
52 |
53 | }
54 |
55 |
56 | .title {
57 | margin-bottom: 2rem;
58 | font-size: 2rem;
59 | }
60 |
61 | h3 {
62 | font-family: 'Roboto', sans-serif;
63 | font-size: 1.1rem;
64 | color: var(--current-fg);
65 | }
66 |
67 | h5 {
68 | font-family: 'Roboto', sans-serif;
69 | font-size: 0.9rem;
70 | color: var(--current-fg);
71 | }
72 |
73 |
74 | hr {
75 | margin: 1rem 0;
76 | }
77 |
78 | /* Details/Summary Indentation levels */
79 |
80 | .level1 {
81 | /* list-style: disc; */
82 | background-color: var(--current-bg);
83 | color: var(--current-fg);
84 | padding: rem;
85 | font-size: 1rem;
86 | cursor: pointer;
87 | }
88 |
89 | .level2 {
90 | /* list-style: disc; */
91 | background-color: var(--current-bg);
92 | color: var(--current-fg);
93 | padding: rem;
94 | font-size: 1rem;
95 | cursor: pointer;
96 | margin-left: 1rem;
97 | }
98 |
99 | .level3 {
100 | /* list-style: disc; */
101 | background-color: var(--current-bg);
102 | color: var(--current-fg);
103 | padding: rem;
104 | font-size: 2rem;
105 | cursor: pointer;
106 | margin-left: 1rem;
107 | }
108 |
109 | .details-content {
110 | background-color: var(--current-bg);
111 | color: var(--current-fg);
112 | padding: 1rem;
113 | font-size: 0.8rem;
114 | overflow-wrap: break-word;
115 | cursor: pointer;
116 | }
117 |
118 | button {
119 | font-size: 0.9rem;
120 | padding: 3px 3px;
121 | background-color: rgb(215, 210, 206);
122 | border-radius: 6px;
123 | }
124 |
125 | select {
126 | font-size: 0.8rem;
127 | padding: 1px 1px;
128 | width: 25rem;
129 | background-color: #00384d;
130 | color: white;
131 | text-align: center;
132 | }
133 |
134 | textarea {
135 | color: rgb(7, 7, 0);
136 | width: 25rem;
137 | background-color: rgb(243, 239, 136);
138 | font-size: 0.8rem;
139 | font-weight: bold;
140 | font-family: 'Courier New', Courier, monospace;
141 | padding: 1px 1px;
142 | text-align: left;
143 | }
144 |
145 | .generatedquery {
146 | color: black;
147 | width: 25rem;
148 | background-color: rgb(203, 241, 165);
149 | font-size: 0.8rem;
150 | font-weight: bold;
151 | font-family: 'Courier New', Courier, monospace;
152 | text-align: left;
153 | }
154 |
155 |
156 |
157 | .checkbox {
158 | font-size: 0.8rem;
159 | }
160 |
161 | .statusbar {
162 | font-size: 0.9rem;
163 | padding: 4px 1px;
164 | background-color: var(--current-bg);
165 | color: var(--current-fg);
166 |
167 | text-align: left;
168 | border: 1;
169 |
170 | }
171 |
172 | blockquote {
173 | background-color: var(--current-bg);
174 | color: var(--current-fg);
175 | text-align: left;
176 | }
177 |
178 | table {
179 | background-color: var(--current-bg);
180 | color: var(--current-fg);
181 | border-collapse: collapse;
182 | border: 1px solid var(--current-fg);
183 | }
184 |
185 | th {
186 | padding: 2px;
187 | font-size: 1.8rem;
188 | border: 1px solid var(--current-fg);
189 | }
190 |
191 | td {
192 | padding: 2px;
193 | font-size: 0.8rem;
194 | border: 1px solid var(--current-fg);
195 | }
196 |
197 | /* zebra striping tbody tr:nth-child(odd) {
198 | background-color: var(--current-bg);
199 | color: var(--current-fg);
200 |
201 | }
202 |
203 | tbody tr:nth-child(even) {
204 | background-color: var(--current-bg);
205 | color: var(--current-fg);
206 | } */
207 |
208 | ul {
209 | list-style-type: disc !important;
210 | padding-left: 1em;
211 | }
--------------------------------------------------------------------------------