mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge branch 'master' into next55
# Conflicts: # electron.js # package-lock.json # package.json # src/public/app/layouts/desktop_layout.js # src/public/app/widgets/note_tree.js # src/services/port.js
This commit is contained in:
commit
c16f7a5e02
@ -41,6 +41,10 @@ Trilium is provided as either desktop application (Linux and Windows) or web app
|
|||||||
* If you want to install Trilium on server, follow [this page](https://github.com/zadam/trilium/wiki/Server-installation).
|
* If you want to install Trilium on server, follow [this page](https://github.com/zadam/trilium/wiki/Server-installation).
|
||||||
* Currently only recent Chrome and Firefox are supported (tested) browsers.
|
* Currently only recent Chrome and Firefox are supported (tested) browsers.
|
||||||
|
|
||||||
|
Trilium is also provided as a Flatpak:
|
||||||
|
|
||||||
|
[<img width="240" src="https://flathub.org/assets/badges/flathub-badge-en.png">](https://flathub.org/apps/details/com.github.zadam.trilium)
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
[See wiki for complete list of documentation pages.](https://github.com/zadam/trilium/wiki/)
|
[See wiki for complete list of documentation pages.](https://github.com/zadam/trilium/wiki/)
|
||||||
|
48
bin/release-flatpack.sh
Executable file
48
bin/release-flatpack.sh
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [[ $# -eq 0 ]] ; then
|
||||||
|
echo "Missing argument of new version"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION=$1
|
||||||
|
|
||||||
|
if ! [[ ${VERSION} =~ ^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{1,2}(-.+)?$ ]] ;
|
||||||
|
then
|
||||||
|
echo "Version ${VERSION} isn't in format X.Y.Z"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
VERSION_DATE=$(git log -1 --format=%aI "v${VERSION}" | cut -c -10)
|
||||||
|
VERSION_COMMIT=$(git rev-list -n 1 "v${VERSION}")
|
||||||
|
|
||||||
|
# expecting the directory at a specific path
|
||||||
|
cd ~/trilium-flathub
|
||||||
|
|
||||||
|
if ! git diff-index --quiet HEAD --; then
|
||||||
|
echo "There are uncommitted changes"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$VERSION" == *"beta"* ]]; then
|
||||||
|
git switch beta
|
||||||
|
else
|
||||||
|
git switch master
|
||||||
|
fi
|
||||||
|
|
||||||
|
git pull
|
||||||
|
|
||||||
|
echo "Updating files with version ${VERSION}, date ${VERSION_DATE} and commit ${VERSION_COMMIT}"
|
||||||
|
|
||||||
|
flatpak-node-generator npm ../trilium/package-lock.json
|
||||||
|
|
||||||
|
xmlstarlet ed --inplace --update "/component/releases/release/@version" --value "${VERSION}" --update "/component/releases/release/@date" --value "${VERSION_DATE}" ./com.github.zadam.trilium.metainfo.xml
|
||||||
|
|
||||||
|
yq --inplace "(.modules[0].sources[0].tag = \"v${VERSION}\") | (.modules[0].sources[0].commit = \"${VERSION_COMMIT}\")" ./com.github.zadam.trilium.yml
|
||||||
|
|
||||||
|
git add ./generated-sources.json
|
||||||
|
git add ./com.github.zadam.trilium.metainfo.xml
|
||||||
|
git add ./com.github.zadam.trilium.yml
|
||||||
|
|
||||||
|
git commit -m "release $VERSION"
|
||||||
|
git push
|
@ -5,8 +5,8 @@ UPDATE note_contents SET content = 'text' WHERE content IS NOT NULL;
|
|||||||
UPDATE note_revisions SET title = 'title';
|
UPDATE note_revisions SET title = 'title';
|
||||||
UPDATE note_revision_contents SET content = 'text' WHERE content IS NOT NULL;
|
UPDATE note_revision_contents SET content = 'text' WHERE content IS NOT NULL;
|
||||||
|
|
||||||
UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'hoistedCssClass', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'hoistedInbox', 'hoistedSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarked', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
|
UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'hoistedCssClass', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'hoistedInbox', 'hoistedSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarked', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
|
||||||
UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'hoistedCssClass', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'hoistedInbox', 'hoistedSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarked', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
|
UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN ('inbox', 'disableVersioning', 'calendarRoot', 'archived', 'excludeFromExport', 'disableInclusion', 'appCss', 'appTheme', 'hidePromotedAttributes', 'readOnly', 'autoReadOnlyDisabled', 'hoistedCssClass', 'cssClass', 'iconClass', 'keyboardShortcut', 'run', 'runOnInstance', 'runAtHour', 'customRequestHandler', 'customResourceProvider', 'widget', 'noteInfoWidgetDisabled', 'linkMapWidgetDisabled', 'noteRevisionsWidgetDisabled', 'whatLinksHereWidgetDisabled', 'similarNotesWidgetDisabled', 'workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor', 'searchHome', 'hoistedInbox', 'hoistedSearchHome', 'sqlConsoleHome', 'datePattern', 'pageSize', 'viewType', 'mapRootNoteId', 'bookmarked', 'bookmarkFolder', 'sorted', 'top', 'fullContentWidth', 'shareHiddenFromTree', 'shareAlias', 'shareOmitDefaultCss', 'shareRoot', 'shareDescription', 'internalLink', 'imageLink', 'relationMapLink', 'includeMapLink', 'runOnNoteCreation', 'runOnNoteTitleChange', 'runOnNoteChange', 'runOnChildNoteCreation', 'runOnAttributeCreation', 'runOnAttributeChange', 'template', 'widget', 'renderNote', 'shareCss', 'shareJs', 'shareFavicon');
|
||||||
UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered';
|
UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL AND prefix != 'recovered';
|
||||||
UPDATE options SET value = 'anonymized' WHERE name IN
|
UPDATE options SET value = 'anonymized' WHERE name IN
|
||||||
('documentId', 'documentSecret', 'encryptedDataKey',
|
('documentId', 'documentSecret', 'encryptedDataKey',
|
||||||
|
@ -2,4 +2,4 @@ SET DIR=%~dp0
|
|||||||
SET TRILIUM_SAFE_MODE=1
|
SET TRILIUM_SAFE_MODE=1
|
||||||
cd %DIR%
|
cd %DIR%
|
||||||
WHERE powershell.exe
|
WHERE powershell.exe
|
||||||
IF %ERRORLEVEL% NEQ 0 (start trilium.exe) ELSE (powershell.exe ./trilium-safe-mode.ps1)
|
IF %ERRORLEVEL% NEQ 0 (start trilium.exe --disable-gpu) ELSE (powershell.exe ./trilium-safe-mode.ps1)
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
Set-Item -Path Env:TRILIUM_SAFE_MODE -Value 1
|
Set-Item -Path Env:TRILIUM_SAFE_MODE -Value 1
|
||||||
./trilium.exe
|
./trilium.exe --disable-gpu
|
||||||
|
@ -3,5 +3,5 @@
|
|||||||
DIR=`dirname "$0"`
|
DIR=`dirname "$0"`
|
||||||
export TRILIUM_SAFE_MODE=1
|
export TRILIUM_SAFE_MODE=1
|
||||||
|
|
||||||
"$DIR/trilium"
|
"$DIR/trilium" --disable-gpu
|
||||||
|
|
||||||
|
BIN
db/demo.zip
BIN
db/demo.zip
Binary file not shown.
@ -1,17 +1,14 @@
|
|||||||
version: '2.1'
|
version: '2.1'
|
||||||
services:
|
services:
|
||||||
trilium:
|
trilium:
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
image: zadam/trilium
|
image: zadam/trilium
|
||||||
restart: always
|
restart: always
|
||||||
environment:
|
environment:
|
||||||
- TRILIUM_DATA_DIR=/data
|
- TRILIUM_DATA_DIR=/home/node/trilium-data
|
||||||
ports:
|
ports:
|
||||||
- "8080:8080"
|
- "8080:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- trilium:/data
|
- trilium:/home/node/trilium-data
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
trilium:
|
trilium:
|
||||||
|
|
||||||
|
@ -326,7 +326,7 @@ parents.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line94">line 94</a>
|
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line95">line 95</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -588,7 +588,7 @@ parents.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line108">line 108</a>
|
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line109">line 109</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1144,7 +1144,7 @@ parents.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line129">line 129</a>
|
<a href="becca_entities_branch.js.html">becca/entities/branch.js</a>, <a href="becca_entities_branch.js.html#line130">line 130</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
@ -978,7 +978,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h4 class="name" id="addAttribute"><span class="type-signature"></span>addAttribute<span class="signature">()</span><span class="type-signature"> → {<a href="Attribute.html">Attribute</a>}</span></h4>
|
<h4 class="name" id="addAttribute"><span class="type-signature"></span>addAttribute<span class="signature">(type, name, value<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {<a href="Attribute.html">Attribute</a>}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Adds a new attribute to this note. The attribute is saved and returned.
|
||||||
|
See addLabel, addRelation for more specific methods.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -988,10 +998,128 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Parameters:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="params">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th>Name</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Type</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Attributes</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<th class="last">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>type</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="attributes">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">attribute type (label / relation)</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>name</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="attributes">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">name of the attribute, not including the leading ~/#</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>value</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="attributes">
|
||||||
|
|
||||||
|
<optional><br>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">value of the attribute - text for labels, target note ID for relations; optional.</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1026,7 +1154,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1077">line 1077</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1086">line 1086</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1163,6 +1291,383 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="addLabel"><span class="type-signature"></span>addLabel<span class="signature">(name, value<span class="signature-attributes">opt</span>)</span><span class="type-signature"> → {<a href="Attribute.html">Attribute</a>}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Adds a new label to this note. The label attribute is saved and returned.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Parameters:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="params">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th>Name</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Type</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Attributes</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<th class="last">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>name</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="attributes">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">name of the label, not including the leading #</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>value</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="attributes">
|
||||||
|
|
||||||
|
<optional><br>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">text value of the label; optional</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1107">line 1107</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Returns:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
Type
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<span class="param-type"><a href="Attribute.html">Attribute</a></span>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 class="name" id="addRelation"><span class="type-signature"></span>addRelation<span class="signature">(name, value)</span><span class="type-signature"> → {<a href="Attribute.html">Attribute</a>}</span></h4>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
Adds a new relation to this note. The relation attribute is saved and
|
||||||
|
returned.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Parameters:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="params">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<th>Name</th>
|
||||||
|
|
||||||
|
|
||||||
|
<th>Type</th>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<th class="last">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>name</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">name of the relation, not including the leading ~</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td class="name"><code>value</code></td>
|
||||||
|
|
||||||
|
|
||||||
|
<td class="type">
|
||||||
|
|
||||||
|
|
||||||
|
<span class="param-type">string</span>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<td class="description last">ID of the target note of the relation</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl class="details">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dt class="tag-source">Source:</dt>
|
||||||
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1120">line 1120</a>
|
||||||
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h5>Returns:</h5>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dl>
|
||||||
|
<dt>
|
||||||
|
Type
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
|
||||||
|
<span class="param-type"><a href="Attribute.html">Attribute</a></span>
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1350,7 +1855,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1179">line 1179</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1205">line 1205</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1550,7 +2055,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1193">line 1193</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1219">line 1219</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1812,7 +2317,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line999">line 999</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1001">line 1001</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1918,7 +2423,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line919">line 919</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line921">line 921</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3097,7 +3602,7 @@
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line714">line 714</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line716">line 716</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6495,7 +7000,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line862">line 862</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line864">line 864</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6597,7 +7102,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line841">line 841</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line843">line 843</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6699,7 +7204,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line810">line 810</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line812">line 812</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6801,7 +7306,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line961">line 961</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line963">line 963</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6997,7 +7502,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line945">line 945</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line947">line 947</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -8476,7 +8981,7 @@ This method can be significantly faster than the getAttribute()
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1020">line 1020</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1022">line 1022</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -9398,7 +9903,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1064">line 1064</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1066">line 1066</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -9578,7 +10083,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1155">line 1155</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1181">line 1181</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -9758,7 +10263,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1163">line 1163</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1189">line 1189</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -9953,7 +10458,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1237">line 1237</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1263">line 1263</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -10185,7 +10690,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1033">line 1033</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1035">line 1035</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -10365,7 +10870,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1139">line 1139</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1165">line 1165</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -10525,7 +11030,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1147">line 1147</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1173">line 1173</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -10767,7 +11272,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1106">line 1106</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1132">line 1132</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -10978,7 +11483,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1122">line 1122</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1148">line 1148</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -11189,7 +11694,7 @@ This is a low level method, for notes and branches use `note.deleteNote()` and '
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1131">line 1131</a>
|
<a href="becca_entities_note.js.html">becca/entities/note.js</a>, <a href="becca_entities_note.js.html#line1157">line 1157</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,21 +98,22 @@ class Branch extends AbstractEntity {
|
|||||||
|
|
||||||
this.becca.childParentToBranch[`${this.noteId}-${this.parentNoteId}`] = this;
|
this.becca.childParentToBranch[`${this.noteId}-${this.parentNoteId}`] = this;
|
||||||
|
|
||||||
|
const childNote = this.childNote;
|
||||||
|
|
||||||
|
if (!childNote.parentBranches.includes(this)) {
|
||||||
|
childNote.parentBranches.push(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.branchId === 'root') {
|
if (this.branchId === 'root') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const childNote = this.childNote;
|
|
||||||
const parentNote = this.parentNote;
|
const parentNote = this.parentNote;
|
||||||
|
|
||||||
if (!childNote.parents.includes(parentNote)) {
|
if (!childNote.parents.includes(parentNote)) {
|
||||||
childNote.parents.push(parentNote);
|
childNote.parents.push(parentNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!childNote.parentBranches.includes(this)) {
|
|
||||||
childNote.parentBranches.push(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!parentNote.children.includes(childNote)) {
|
if (!parentNote.children.includes(childNote)) {
|
||||||
parentNote.children.push(childNote);
|
parentNote.children.push(childNote);
|
||||||
}
|
}
|
||||||
@ -132,9 +133,9 @@ class Branch extends AbstractEntity {
|
|||||||
return this.childNote;
|
return this.childNote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Note} */
|
/** @returns {Note|undefined} - root branch will have undefined parent, all other branches have to have a parent note */
|
||||||
get parentNote() {
|
get parentNote() {
|
||||||
if (!(this.parentNoteId in this.becca.notes)) {
|
if (!(this.parentNoteId in this.becca.notes) && this.parentNoteId !== 'none') {
|
||||||
// entities can come out of order in sync/import, create skeleton which will be filled later
|
// entities can come out of order in sync/import, create skeleton which will be filled later
|
||||||
this.becca.addNote(this.parentNoteId, new Note({noteId: this.parentNoteId}));
|
this.becca.addNote(this.parentNoteId, new Note({noteId: this.parentNoteId}));
|
||||||
}
|
}
|
||||||
|
@ -727,9 +727,11 @@ class Note extends AbstractEntity {
|
|||||||
sortParents() {
|
sortParents() {
|
||||||
this.parentBranches.sort((a, b) =>
|
this.parentBranches.sort((a, b) =>
|
||||||
a.branchId.startsWith('virt-')
|
a.branchId.startsWith('virt-')
|
||||||
|| a.parentNote.hasInheritableOwnedArchivedLabel() ? 1 : -1);
|
|| a.parentNote?.hasInheritableOwnedArchivedLabel() ? 1 : -1);
|
||||||
|
|
||||||
this.parents = this.parentBranches.map(branch => branch.parentNote);
|
this.parents = this.parentBranches
|
||||||
|
.map(branch => branch.parentNote)
|
||||||
|
.filter(note => !!note);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1100,6 +1102,13 @@ class Note extends AbstractEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Adds a new attribute to this note. The attribute is saved and returned.
|
||||||
|
* See addLabel, addRelation for more specific methods.
|
||||||
|
*
|
||||||
|
* @param {string} type - attribute type (label / relation)
|
||||||
|
* @param {string} name - name of the attribute, not including the leading ~/#
|
||||||
|
* @param {string} [value] - value of the attribute - text for labels, target note ID for relations; optional.
|
||||||
|
*
|
||||||
* @return {Attribute}
|
* @return {Attribute}
|
||||||
*/
|
*/
|
||||||
addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
|
addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
|
||||||
@ -1115,10 +1124,27 @@ class Note extends AbstractEntity {
|
|||||||
}).save();
|
}).save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new label to this note. The label attribute is saved and returned.
|
||||||
|
*
|
||||||
|
* @param {string} name - name of the label, not including the leading #
|
||||||
|
* @param {string} [value] - text value of the label; optional
|
||||||
|
*
|
||||||
|
* @return {Attribute}
|
||||||
|
*/
|
||||||
addLabel(name, value = "", isInheritable = false) {
|
addLabel(name, value = "", isInheritable = false) {
|
||||||
return this.addAttribute(LABEL, name, value, isInheritable);
|
return this.addAttribute(LABEL, name, value, isInheritable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new relation to this note. The relation attribute is saved and
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @param {string} name - name of the relation, not including the leading ~
|
||||||
|
* @param {string} value - ID of the target note of the relation
|
||||||
|
*
|
||||||
|
* @return {Attribute}
|
||||||
|
*/
|
||||||
addRelation(name, targetNoteId, isInheritable = false) {
|
addRelation(name, targetNoteId, isInheritable = false) {
|
||||||
return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
|
return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line30">line 30</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -267,7 +267,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line38">line 38</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line39">line 39</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -335,7 +335,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line46">line 46</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line47">line 47</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -403,7 +403,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line52">line 52</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line53">line 53</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -471,7 +471,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line63">line 63</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line64">line 64</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -543,7 +543,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line73">line 73</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line74">line 74</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -611,7 +611,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line59">line 59</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line60">line 60</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -679,7 +679,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line44">line 44</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line45">line 45</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -747,7 +747,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line49">line 49</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line50">line 50</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -815,7 +815,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line41">line 41</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line42">line 42</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -883,7 +883,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line61">line 61</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line62">line 62</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -955,7 +955,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line68">line 68</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line69">line 69</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1103,7 +1103,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line504">line 504</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line505">line 505</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1303,7 +1303,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line238">line 238</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line239">line 239</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1481,7 +1481,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line526">line 526</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line527">line 527</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1589,7 +1589,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line163">line 163</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line164">line 164</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1693,7 +1693,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line146">line 146</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line147">line 147</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1795,7 +1795,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line173">line 173</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line174">line 174</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1897,7 +1897,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line211">line 211</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line212">line 212</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -1999,7 +1999,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line216">line 216</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line217">line 217</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2150,7 +2150,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line566">line 566</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line567">line 567</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2317,7 +2317,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line390">line 390</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line391">line 391</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2472,7 +2472,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line590">line 590</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line591">line 591</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2582,7 +2582,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line717">line 717</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line718">line 718</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2756,7 +2756,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line493">line 493</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line494">line 494</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -2956,7 +2956,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line225">line 225</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line226">line 226</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3134,7 +3134,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line515">line 515</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line516">line 516</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3289,7 +3289,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line560">line 560</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line561">line 561</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3456,7 +3456,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line382">line 382</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line383">line 383</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3611,7 +3611,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line584">line 584</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line585">line 585</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3766,7 +3766,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line572">line 572</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line573">line 573</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -3933,7 +3933,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line458">line 458</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line459">line 459</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4088,7 +4088,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line596">line 596</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line597">line 597</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4194,7 +4194,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line153">line 153</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line154">line 154</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4296,7 +4296,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line138">line 138</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line139">line 139</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4398,7 +4398,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line181">line 181</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line182">line 182</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4500,7 +4500,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line186">line 186</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line187">line 187</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4651,7 +4651,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line578">line 578</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line579">line 579</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4818,7 +4818,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line466">line 466</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line467">line 467</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -4973,7 +4973,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line608">line 608</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line609">line 609</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5143,7 +5143,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line618">line 618</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line619">line 619</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5294,7 +5294,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line602">line 602</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line603">line 603</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5400,7 +5400,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line761">line 761</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line762">line 762</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5513,7 +5513,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line696">line 696</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line697">line 697</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5619,7 +5619,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line706">line 706</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line707">line 707</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5721,7 +5721,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line632">line 632</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line633">line 633</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -5895,7 +5895,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line475">line 475</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line476">line 476</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6001,7 +6001,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line168">line 168</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line169">line 169</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6152,7 +6152,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line542">line 542</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line543">line 543</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6330,7 +6330,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line484">line 484</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line485">line 485</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6485,7 +6485,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line536">line 536</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line537">line 537</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6640,7 +6640,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line548">line 548</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line549">line 549</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6795,7 +6795,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line554">line 554</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line555">line 555</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6903,7 +6903,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line689">line 689</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line690">line 690</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -6987,7 +6987,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line756">line 756</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line757">line 757</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -7093,7 +7093,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line748">line 748</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line749">line 749</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
@ -7199,7 +7199,7 @@ This note's representation is used in note tree and is kept in Froca.</div>
|
|||||||
|
|
||||||
<dt class="tag-source">Source:</dt>
|
<dt class="tag-source">Source:</dt>
|
||||||
<dd class="tag-source"><ul class="dummy"><li>
|
<dd class="tag-source"><ul class="dummy"><li>
|
||||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line111">line 111</a>
|
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line112">line 112</a>
|
||||||
</li></ul></dd>
|
</li></ul></dd>
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import noteAttributeCache from "../services/note_attribute_cache.js";
|
|||||||
import ws from "../services/ws.js";
|
import ws from "../services/ws.js";
|
||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import froca from "../services/froca.js";
|
import froca from "../services/froca.js";
|
||||||
|
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||||
|
|
||||||
const LABEL = 'label';
|
const LABEL = 'label';
|
||||||
const RELATION = 'relation';
|
const RELATION = 'relation';
|
||||||
@ -840,6 +841,10 @@ class NoteShort {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isContentAvailable() {
|
||||||
|
return !this.isProtected || protectedSessionHolder.isProtectedSessionAvailable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NoteShort;
|
export default NoteShort;
|
||||||
|
@ -13,11 +13,12 @@ appIconService.installLocalAppIcon();
|
|||||||
|
|
||||||
require('electron-dl')({ saveAs: true });
|
require('electron-dl')({ saveAs: true });
|
||||||
|
|
||||||
|
// Quit when all windows are closed, except on macOS. There, it's common
|
||||||
|
// for applications and their menu bar to stay active until the user quits
|
||||||
|
// explicitly with Cmd + Q.
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
if (process.platform === 'win32') {
|
if (process.platform !== 'darwin') {
|
||||||
app.exit(0); // attempt to fix the issue when app.quit() won't terminate processes on windows
|
app.quit()
|
||||||
} else {
|
|
||||||
app.quit();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CKEditor 5 (v33.0.0) content styles.
|
* CKEditor 5 (v35.2.1) content styles.
|
||||||
* Generated on Fri, 11 Mar 2022 14:34:26 GMT.
|
* Generated on Fri, 14 Oct 2022 09:47:42 GMT.
|
||||||
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/content-styles.html
|
* For more information, check out https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/content-styles.html
|
||||||
*/
|
*/
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@ -34,6 +34,21 @@
|
|||||||
padding: .15em;
|
padding: .15em;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||||
|
.ck-content blockquote {
|
||||||
|
overflow: hidden;
|
||||||
|
padding-right: 1.5em;
|
||||||
|
padding-left: 1.5em;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 0;
|
||||||
|
font-style: italic;
|
||||||
|
border-left: solid 5px hsl(0, 0%, 80%);
|
||||||
|
}
|
||||||
|
/* ckeditor5-block-quote/theme/blockquote.css */
|
||||||
|
.ck-content[dir="rtl"] blockquote {
|
||||||
|
border-left: 0;
|
||||||
|
border-right: solid 5px hsl(0, 0%, 80%);
|
||||||
|
}
|
||||||
/* ckeditor5-font/theme/fontsize.css */
|
/* ckeditor5-font/theme/fontsize.css */
|
||||||
.ck-content .text-tiny {
|
.ck-content .text-tiny {
|
||||||
font-size: .7em;
|
font-size: .7em;
|
||||||
@ -50,21 +65,6 @@
|
|||||||
.ck-content .text-huge {
|
.ck-content .text-huge {
|
||||||
font-size: 1.8em;
|
font-size: 1.8em;
|
||||||
}
|
}
|
||||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
|
||||||
.ck-content blockquote {
|
|
||||||
overflow: hidden;
|
|
||||||
padding-right: 1.5em;
|
|
||||||
padding-left: 1.5em;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 0;
|
|
||||||
font-style: italic;
|
|
||||||
border-left: solid 5px hsl(0, 0%, 80%);
|
|
||||||
}
|
|
||||||
/* ckeditor5-block-quote/theme/blockquote.css */
|
|
||||||
.ck-content[dir="rtl"] blockquote {
|
|
||||||
border-left: 0;
|
|
||||||
border-right: solid 5px hsl(0, 0%, 80%);
|
|
||||||
}
|
|
||||||
/* ckeditor5-highlight/theme/highlight.css */
|
/* ckeditor5-highlight/theme/highlight.css */
|
||||||
.ck-content .marker-yellow {
|
.ck-content .marker-yellow {
|
||||||
background-color: var(--ck-highlight-marker-yellow);
|
background-color: var(--ck-highlight-marker-yellow);
|
||||||
@ -139,6 +139,20 @@
|
|||||||
font-size: .75em;
|
font-size: .75em;
|
||||||
outline-offset: -1px;
|
outline-offset: -1px;
|
||||||
}
|
}
|
||||||
|
/* ckeditor5-image/theme/imageresize.css */
|
||||||
|
.ck-content .image.image_resized {
|
||||||
|
max-width: 100%;
|
||||||
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
/* ckeditor5-image/theme/imageresize.css */
|
||||||
|
.ck-content .image.image_resized img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
/* ckeditor5-image/theme/imageresize.css */
|
||||||
|
.ck-content .image.image_resized > figcaption {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
/* ckeditor5-image/theme/imagestyle.css */
|
/* ckeditor5-image/theme/imagestyle.css */
|
||||||
.ck-content .image-style-block-align-left,
|
.ck-content .image-style-block-align-left,
|
||||||
.ck-content .image-style-block-align-right {
|
.ck-content .image-style-block-align-right {
|
||||||
@ -200,20 +214,6 @@
|
|||||||
.ck-content .image-inline.image-style-align-right {
|
.ck-content .image-inline.image-style-align-right {
|
||||||
margin-left: var(--ck-inline-image-style-spacing);
|
margin-left: var(--ck-inline-image-style-spacing);
|
||||||
}
|
}
|
||||||
/* ckeditor5-image/theme/imageresize.css */
|
|
||||||
.ck-content .image.image_resized {
|
|
||||||
max-width: 100%;
|
|
||||||
display: block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
/* ckeditor5-image/theme/imageresize.css */
|
|
||||||
.ck-content .image.image_resized img {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
/* ckeditor5-image/theme/imageresize.css */
|
|
||||||
.ck-content .image.image_resized > figcaption {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
/* ckeditor5-language/theme/language.css */
|
/* ckeditor5-language/theme/language.css */
|
||||||
.ck-content span[lang] {
|
.ck-content span[lang] {
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
@ -328,6 +328,18 @@
|
|||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
/* ckeditor5-table/theme/tablecaption.css */
|
||||||
|
.ck-content .table > figcaption {
|
||||||
|
display: table-caption;
|
||||||
|
caption-side: top;
|
||||||
|
word-break: break-word;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--ck-color-table-caption-text);
|
||||||
|
background-color: var(--ck-color-table-caption-background);
|
||||||
|
padding: .6em;
|
||||||
|
font-size: .75em;
|
||||||
|
outline-offset: -1px;
|
||||||
|
}
|
||||||
/* ckeditor5-table/theme/table.css */
|
/* ckeditor5-table/theme/table.css */
|
||||||
.ck-content .table {
|
.ck-content .table {
|
||||||
margin: 0.9em auto;
|
margin: 0.9em auto;
|
||||||
@ -361,17 +373,18 @@
|
|||||||
.ck-content[dir="ltr"] .table th {
|
.ck-content[dir="ltr"] .table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
/* ckeditor5-table/theme/tablecaption.css */
|
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||||
.ck-content .table > figcaption {
|
.ck-content .table .ck-table-resized {
|
||||||
display: table-caption;
|
table-layout: fixed;
|
||||||
caption-side: top;
|
}
|
||||||
word-break: break-word;
|
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||||
text-align: center;
|
.ck-content .table table {
|
||||||
color: var(--ck-color-table-caption-text);
|
overflow: hidden;
|
||||||
background-color: var(--ck-color-table-caption-background);
|
}
|
||||||
padding: .6em;
|
/* ckeditor5-table/theme/tablecolumnresize.css */
|
||||||
font-size: .75em;
|
.ck-content .table td,
|
||||||
outline-offset: -1px;
|
.ck-content .table th {
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
/* ckeditor5-code-block/theme/codeblock.css */
|
/* ckeditor5-code-block/theme/codeblock.css */
|
||||||
.ck-content pre {
|
.ck-content pre {
|
||||||
@ -400,6 +413,42 @@
|
|||||||
background: hsl(0, 0%, 87%);
|
background: hsl(0, 0%, 87%);
|
||||||
border: 0;
|
border: 0;
|
||||||
}
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ol ol {
|
||||||
|
list-style-type: lower-latin;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ol ol ol {
|
||||||
|
list-style-type: lower-roman;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ol ol ol ol {
|
||||||
|
list-style-type: upper-latin;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ol ol ol ol ol {
|
||||||
|
list-style-type: upper-roman;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ul {
|
||||||
|
list-style-type: circle;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ul ul {
|
||||||
|
list-style-type: disc;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ul ul ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
/* ckeditor5-list/theme/liststyles.css */
|
||||||
|
.ck-content ul ul ul ul {
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
/* ckeditor5-mention/theme/mention.css */
|
/* ckeditor5-mention/theme/mention.css */
|
||||||
.ck-content .mention {
|
.ck-content .mention {
|
||||||
background: var(--ck-color-mention-background);
|
background: var(--ck-color-mention-background);
|
||||||
|
4
libraries/ckeditor/ckeditor.js
vendored
4
libraries/ckeditor/ckeditor.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
39
package.json
39
package.json
@ -2,7 +2,7 @@
|
|||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"productName": "Trilium Notes",
|
"productName": "Trilium Notes",
|
||||||
"description": "Trilium Notes",
|
"description": "Trilium Notes",
|
||||||
"version": "0.54.2",
|
"version": "0.55.1",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@ -15,6 +15,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev node ./src/www",
|
"start-server": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev node ./src/www",
|
||||||
"start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev electron --inspect=5858 .",
|
"start-electron": "cross-env TRILIUM_DATA_DIR=./data TRILIUM_ENV=dev electron --inspect=5858 .",
|
||||||
|
"switch-server": "rm -r ./node_modules/better-sqlite3 && npm install",
|
||||||
|
"switch-electron": "rm -r ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild",
|
||||||
"build-backend-docs": "rm -r ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js",
|
"build-backend-docs": "rm -r ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js",
|
||||||
"build-frontend-docs": "rm -r ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js",
|
"build-frontend-docs": "rm -r ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/collapsible_widget.js",
|
||||||
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
|
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
|
||||||
@ -28,41 +30,42 @@
|
|||||||
"@electron/remote": "2.0.8",
|
"@electron/remote": "2.0.8",
|
||||||
"@excalidraw/excalidraw": "0.12.0",
|
"@excalidraw/excalidraw": "0.12.0",
|
||||||
"archiver": "5.3.1",
|
"archiver": "5.3.1",
|
||||||
"async-mutex": "0.3.2",
|
"async-mutex": "0.4.0",
|
||||||
"axios": "0.27.2",
|
"axios": "1.1.2",
|
||||||
"better-sqlite3": "7.4.5",
|
"better-sqlite3": "7.4.5",
|
||||||
"chokidar": "3.5.3",
|
"chokidar": "3.5.3",
|
||||||
"cls-hooked": "4.2.2",
|
"cls-hooked": "4.2.2",
|
||||||
"commonmark": "0.30.0",
|
"commonmark": "0.30.0",
|
||||||
|
"compression": "1.7.4",
|
||||||
"cookie-parser": "1.4.6",
|
"cookie-parser": "1.4.6",
|
||||||
"csurf": "1.11.0",
|
"csurf": "1.11.0",
|
||||||
"dayjs": "1.11.4",
|
"dayjs": "1.11.5",
|
||||||
"dayjs-plugin-utc": "^0.1.2",
|
"dayjs-plugin-utc": "^0.1.2",
|
||||||
"debounce": "^1.2.1",
|
"debounce": "^1.2.1",
|
||||||
"ejs": "3.1.8",
|
"ejs": "3.1.8",
|
||||||
"electron-debug": "3.2.0",
|
"electron-debug": "3.2.0",
|
||||||
"electron-dl": "3.3.1",
|
"electron-dl": "3.4.0",
|
||||||
"electron-window-state": "5.0.3",
|
"electron-window-state": "5.0.3",
|
||||||
"express": "4.18.1",
|
"express": "4.18.2",
|
||||||
"express-partial-content": "1.0.2",
|
"express-partial-content": "1.0.2",
|
||||||
"express-rate-limit": "6.5.1",
|
"express-rate-limit": "6.6.0",
|
||||||
"express-session": "1.17.3",
|
"express-session": "1.17.3",
|
||||||
"fs-extra": "10.1.0",
|
"fs-extra": "10.1.0",
|
||||||
"helmet": "5.1.1",
|
"helmet": "6.0.0",
|
||||||
"html": "1.0.0",
|
"html": "1.0.0",
|
||||||
"html2plaintext": "2.1.4",
|
"html2plaintext": "2.1.4",
|
||||||
"http-proxy-agent": "5.0.0",
|
"http-proxy-agent": "5.0.0",
|
||||||
"https-proxy-agent": "5.0.1",
|
"https-proxy-agent": "5.0.1",
|
||||||
"image-type": "4.1.0",
|
"image-type": "4.1.0",
|
||||||
"ini": "3.0.0",
|
"ini": "3.0.1",
|
||||||
"is-animated": "2.0.2",
|
"is-animated": "2.0.2",
|
||||||
"is-svg": "4.3.2",
|
"is-svg": "4.3.2",
|
||||||
"jimp": "0.16.1",
|
"jimp": "0.16.2",
|
||||||
"joplin-turndown-plugin-gfm": "1.0.12",
|
"joplin-turndown-plugin-gfm": "1.0.12",
|
||||||
"jsdom": "20.0.0",
|
"jsdom": "20.0.1",
|
||||||
"mime-types": "2.1.35",
|
"mime-types": "2.1.35",
|
||||||
"multer": "1.4.5-lts.1",
|
"multer": "1.4.5-lts.1",
|
||||||
"node-abi": "3.24.0",
|
"node-abi": "3.26.0",
|
||||||
"normalize-strings": "1.1.1",
|
"normalize-strings": "1.1.1",
|
||||||
"open": "8.4.0",
|
"open": "8.4.0",
|
||||||
"rand-token": "1.0.1",
|
"rand-token": "1.0.1",
|
||||||
@ -72,9 +75,9 @@
|
|||||||
"rimraf": "3.0.2",
|
"rimraf": "3.0.2",
|
||||||
"safe-compare": "1.1.4",
|
"safe-compare": "1.1.4",
|
||||||
"sanitize-filename": "1.6.3",
|
"sanitize-filename": "1.6.3",
|
||||||
"sanitize-html": "2.7.1",
|
"sanitize-html": "2.7.2",
|
||||||
"sax": "1.2.4",
|
"sax": "1.2.4",
|
||||||
"semver": "7.3.7",
|
"semver": "7.3.8",
|
||||||
"serve-favicon": "2.5.0",
|
"serve-favicon": "2.5.0",
|
||||||
"session-file-store": "1.5.0",
|
"session-file-store": "1.5.0",
|
||||||
"stream-throttle": "0.1.3",
|
"stream-throttle": "0.1.3",
|
||||||
@ -82,17 +85,17 @@
|
|||||||
"tmp": "0.2.1",
|
"tmp": "0.2.1",
|
||||||
"turndown": "7.1.1",
|
"turndown": "7.1.1",
|
||||||
"unescape": "1.0.1",
|
"unescape": "1.0.1",
|
||||||
"ws": "8.8.1",
|
"ws": "8.9.0",
|
||||||
"yauzl": "2.10.0"
|
"yauzl": "2.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "7.0.3",
|
||||||
"electron": "16.2.8",
|
"electron": "16.2.8",
|
||||||
"electron-builder": "23.3.3",
|
"electron-builder": "23.6.0",
|
||||||
"electron-packager": "15.5.1",
|
"electron-packager": "16.0.0",
|
||||||
"electron-rebuild": "3.2.9",
|
"electron-rebuild": "3.2.9",
|
||||||
"esm": "3.2.25",
|
"esm": "3.2.25",
|
||||||
"jasmine": "4.3.0",
|
"jasmine": "4.4.0",
|
||||||
"jsdoc": "3.6.11",
|
"jsdoc": "3.6.11",
|
||||||
"lorem-ipsum": "2.0.8",
|
"lorem-ipsum": "2.0.8",
|
||||||
"rcedit": "3.0.1",
|
"rcedit": "3.0.1",
|
||||||
|
@ -211,6 +211,35 @@ describe("Parser", () => {
|
|||||||
expect(secondSubSub.constructor.name).toEqual("LabelComparisonExp");
|
expect(secondSubSub.constructor.name).toEqual("LabelComparisonExp");
|
||||||
expect(secondSubSub.attributeName).toEqual("third");
|
expect(secondSubSub.attributeName).toEqual("third");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("label sub-expression without explicit operator", () => {
|
||||||
|
const rootExp = parse({
|
||||||
|
fulltextTokens: [],
|
||||||
|
expressionTokens: tokens(["#first", ["#second", "or", "#third"], "#fourth"]),
|
||||||
|
searchContext: new SearchContext()
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(rootExp.constructor.name).toEqual("AndExp");
|
||||||
|
assertIsArchived(rootExp.subExpressions[0]);
|
||||||
|
|
||||||
|
expect(rootExp.subExpressions[1].constructor.name).toEqual("AndExp");
|
||||||
|
const [firstSub, secondSub, thirdSub] = rootExp.subExpressions[1].subExpressions;
|
||||||
|
|
||||||
|
expect(firstSub.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(firstSub.attributeName).toEqual("first");
|
||||||
|
|
||||||
|
expect(secondSub.constructor.name).toEqual("OrExp");
|
||||||
|
const [firstSubSub, secondSubSub] = secondSub.subExpressions;
|
||||||
|
|
||||||
|
expect(firstSubSub.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(firstSubSub.attributeName).toEqual("second");
|
||||||
|
|
||||||
|
expect(secondSubSub.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(secondSubSub.attributeName).toEqual("third");
|
||||||
|
|
||||||
|
expect(thirdSub.constructor.name).toEqual("AttributeExistsExp");
|
||||||
|
expect(thirdSub.attributeName).toEqual("fourth");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Invalid expressions", () => {
|
describe("Invalid expressions", () => {
|
||||||
|
@ -5,6 +5,7 @@ const favicon = require('serve-favicon');
|
|||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
const helmet = require('helmet');
|
const helmet = require('helmet');
|
||||||
const session = require('express-session');
|
const session = require('express-session');
|
||||||
|
const compression = require('compression')
|
||||||
const FileStore = require('session-file-store')(session);
|
const FileStore = require('session-file-store')(session);
|
||||||
const sessionSecret = require('./services/session_secret');
|
const sessionSecret = require('./services/session_secret');
|
||||||
const dataDir = require('./services/data_dir');
|
const dataDir = require('./services/data_dir');
|
||||||
@ -18,6 +19,10 @@ const app = express();
|
|||||||
app.set('views', path.join(__dirname, 'views'));
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
|
|
||||||
|
if (!utils.isElectron()) {
|
||||||
|
app.use(compression()); // HTTP compression
|
||||||
|
}
|
||||||
|
|
||||||
app.use(helmet({
|
app.use(helmet({
|
||||||
hidePoweredBy: false, // errors out in electron
|
hidePoweredBy: false, // errors out in electron
|
||||||
contentSecurityPolicy: false,
|
contentSecurityPolicy: false,
|
||||||
|
@ -27,6 +27,8 @@ class Becca {
|
|||||||
/** @type {Object.<String, EtapiToken>} */
|
/** @type {Object.<String, EtapiToken>} */
|
||||||
this.etapiTokens = {};
|
this.etapiTokens = {};
|
||||||
|
|
||||||
|
this.dirtyNoteSetCache();
|
||||||
|
|
||||||
this.loaded = false;
|
this.loaded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,9 +105,9 @@ class Branch extends AbstractEntity {
|
|||||||
return this.childNote;
|
return this.childNote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {Note} */
|
/** @returns {Note|undefined} - root branch will have undefined parent, all other branches have to have a parent note */
|
||||||
get parentNote() {
|
get parentNote() {
|
||||||
if (!(this.parentNoteId in this.becca.notes)) {
|
if (!(this.parentNoteId in this.becca.notes) && this.parentNoteId !== 'none') {
|
||||||
// entities can come out of order in sync/import, create skeleton which will be filled later
|
// entities can come out of order in sync/import, create skeleton which will be filled later
|
||||||
this.becca.addNote(this.parentNoteId, new Note({noteId: this.parentNoteId}));
|
this.becca.addNote(this.parentNoteId, new Note({noteId: this.parentNoteId}));
|
||||||
}
|
}
|
||||||
|
@ -403,7 +403,7 @@ class Note extends AbstractEntity {
|
|||||||
templateAttributes.push(
|
templateAttributes.push(
|
||||||
...templateNote.__getAttributes(newPath)
|
...templateNote.__getAttributes(newPath)
|
||||||
// template attr is used as a marker for templates, but it's not meant to be inherited
|
// template attr is used as a marker for templates, but it's not meant to be inherited
|
||||||
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
|
.filter(attr => !(attr.type === 'label' && (attr.name === 'template' || attr.name === 'workspacetemplate')))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -698,10 +698,12 @@ class Note extends AbstractEntity {
|
|||||||
// this is done so that non-search & non-archived paths are always explored as first when looking for note path
|
// this is done so that non-search & non-archived paths are always explored as first when looking for note path
|
||||||
sortParents() {
|
sortParents() {
|
||||||
this.parentBranches.sort((a, b) =>
|
this.parentBranches.sort((a, b) =>
|
||||||
a.branchId.startsWith('virt-')
|
a.branchId.startsWith('virt-') // FIXME: search virtual notes appear only in froca so this is probably not necessary
|
||||||
|| a.parentNote.hasInheritableOwnedArchivedLabel() ? 1 : -1);
|
|| a.parentNote?.hasInheritableOwnedArchivedLabel() ? 1 : -1);
|
||||||
|
|
||||||
this.parents = this.parentBranches.map(branch => branch.parentNote);
|
this.parents = this.parentBranches
|
||||||
|
.map(branch => branch.parentNote)
|
||||||
|
.filter(note => !!note);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1072,6 +1074,13 @@ class Note extends AbstractEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Adds a new attribute to this note. The attribute is saved and returned.
|
||||||
|
* See addLabel, addRelation for more specific methods.
|
||||||
|
*
|
||||||
|
* @param {string} type - attribute type (label / relation)
|
||||||
|
* @param {string} name - name of the attribute, not including the leading ~/#
|
||||||
|
* @param {string} [value] - value of the attribute - text for labels, target note ID for relations; optional.
|
||||||
|
*
|
||||||
* @return {Attribute}
|
* @return {Attribute}
|
||||||
*/
|
*/
|
||||||
addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
|
addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
|
||||||
@ -1087,10 +1096,27 @@ class Note extends AbstractEntity {
|
|||||||
}).save();
|
}).save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new label to this note. The label attribute is saved and returned.
|
||||||
|
*
|
||||||
|
* @param {string} name - name of the label, not including the leading #
|
||||||
|
* @param {string} [value] - text value of the label; optional
|
||||||
|
*
|
||||||
|
* @return {Attribute}
|
||||||
|
*/
|
||||||
addLabel(name, value = "", isInheritable = false) {
|
addLabel(name, value = "", isInheritable = false) {
|
||||||
return this.addAttribute(LABEL, name, value, isInheritable);
|
return this.addAttribute(LABEL, name, value, isInheritable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new relation to this note. The relation attribute is saved and
|
||||||
|
* returned.
|
||||||
|
*
|
||||||
|
* @param {string} name - name of the relation, not including the leading ~
|
||||||
|
* @param {string} value - ID of the target note of the relation
|
||||||
|
*
|
||||||
|
* @return {Attribute}
|
||||||
|
*/
|
||||||
addRelation(name, targetNoteId, isInheritable = false) {
|
addRelation(name, targetNoteId, isInheritable = false) {
|
||||||
return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
|
return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
|
||||||
}
|
}
|
||||||
|
@ -281,7 +281,7 @@ async function findSimilarNotes(noteId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function gatherAncestorRewards(note) {
|
function gatherAncestorRewards(note) {
|
||||||
if (ancestorNoteIds.has(note.noteId)) {
|
if (!note || ancestorNoteIds.has(note.noteId)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@ const eu = require("./etapi_utils");
|
|||||||
const passwordEncryptionService = require("../services/password_encryption");
|
const passwordEncryptionService = require("../services/password_encryption");
|
||||||
const etapiTokenService = require("../services/etapi_tokens");
|
const etapiTokenService = require("../services/etapi_tokens");
|
||||||
|
|
||||||
function register(router) {
|
function register(router, loginMiddleware) {
|
||||||
eu.NOT_AUTHENTICATED_ROUTE(router, 'post', '/etapi/auth/login', (req, res, next) => {
|
eu.NOT_AUTHENTICATED_ROUTE(router, 'post', '/etapi/auth/login', loginMiddleware, (req, res, next) => {
|
||||||
const {password, tokenName} = req.body;
|
const {password, tokenName} = req.body;
|
||||||
|
|
||||||
if (!passwordEncryptionService.verifyPassword(password)) {
|
if (!passwordEncryptionService.verifyPassword(password)) {
|
||||||
|
@ -15,6 +15,7 @@ servers:
|
|||||||
- url: http://localhost:8080/etapi
|
- url: http://localhost:8080/etapi
|
||||||
security:
|
security:
|
||||||
- EtapiTokenAuth: []
|
- EtapiTokenAuth: []
|
||||||
|
- EtapiBasicAuth: []
|
||||||
paths:
|
paths:
|
||||||
/create-note:
|
/create-note:
|
||||||
post:
|
post:
|
||||||
@ -228,6 +229,36 @@ paths:
|
|||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/Error'
|
$ref: '#/components/schemas/Error'
|
||||||
|
/notes/{noteId}/content:
|
||||||
|
parameters:
|
||||||
|
- name: noteId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/components/schemas/EntityId'
|
||||||
|
get:
|
||||||
|
description: Returns note content idenfied by its ID
|
||||||
|
operationId: getNoteContent
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: note content response
|
||||||
|
content:
|
||||||
|
text/html:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
put:
|
||||||
|
description: Updates note content idenfied by its ID
|
||||||
|
operationId: putNoteContentById
|
||||||
|
requestBody:
|
||||||
|
description: html content of note
|
||||||
|
required: true
|
||||||
|
content:
|
||||||
|
text/plain:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
'204':
|
||||||
|
description: note content updated
|
||||||
/notes/{noteId}/export:
|
/notes/{noteId}/export:
|
||||||
parameters:
|
parameters:
|
||||||
- name: noteId
|
- name: noteId
|
||||||
@ -602,6 +633,8 @@ paths:
|
|||||||
authToken:
|
authToken:
|
||||||
type: string
|
type: string
|
||||||
example: Bc4bFn0Ffiok_4NpbVCDnFz7B2WU+pdhW8B5Ne3DiR5wXrEyqdjgRIsk=
|
example: Bc4bFn0Ffiok_4NpbVCDnFz7B2WU+pdhW8B5Ne3DiR5wXrEyqdjgRIsk=
|
||||||
|
'429':
|
||||||
|
description: Client IP has been blacklisted because too many requests (possibly failed authentications) were made within a short time frame, try again later
|
||||||
default:
|
default:
|
||||||
description: unexpected error
|
description: unexpected error
|
||||||
content:
|
content:
|
||||||
@ -645,6 +678,14 @@ components:
|
|||||||
type: apiKey
|
type: apiKey
|
||||||
in: header
|
in: header
|
||||||
name: Authorization
|
name: Authorization
|
||||||
|
EtapiBasicAuth:
|
||||||
|
type: http
|
||||||
|
scheme: basic
|
||||||
|
description: >
|
||||||
|
Basic Auth where username is arbitrary string (e.g. "trilium", not checked),
|
||||||
|
username is the ETAPI token.
|
||||||
|
To emphasize, do not use Trilium password here (won't work), only the generated
|
||||||
|
ETAPI token (from Options -> ETAPI)
|
||||||
schemas:
|
schemas:
|
||||||
CreateNoteDef:
|
CreateNoteDef:
|
||||||
type: object
|
type: object
|
||||||
|
@ -66,8 +66,8 @@ function route(router, method, path, routeHandler) {
|
|||||||
router[method](path, checkEtapiAuth, (req, res, next) => processRequest(req, res, routeHandler, next, method, path));
|
router[method](path, checkEtapiAuth, (req, res, next) => processRequest(req, res, routeHandler, next, method, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
function NOT_AUTHENTICATED_ROUTE(router, method, path, routeHandler) {
|
function NOT_AUTHENTICATED_ROUTE(router, method, path, middleware, routeHandler) {
|
||||||
router[method](path, (req, res, next) => processRequest(req, res, routeHandler, next, method, path));
|
router[method](path, ...middleware, (req, res, next) => processRequest(req, res, routeHandler, next, method, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAndCheckNote(noteId) {
|
function getAndCheckNote(noteId) {
|
||||||
|
@ -52,6 +52,12 @@ class Branch {
|
|||||||
get toString() {
|
get toString() {
|
||||||
return `Branch(branchId=${this.branchId})`;
|
return `Branch(branchId=${this.branchId})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get pojo() {
|
||||||
|
const pojo = {...this};
|
||||||
|
delete pojo.froca;
|
||||||
|
return pojo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Branch;
|
export default Branch;
|
||||||
|
@ -4,6 +4,7 @@ import ws from "../services/ws.js";
|
|||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import froca from "../services/froca.js";
|
import froca from "../services/froca.js";
|
||||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||||
|
import cssClassManager from "../services/css_class_manager.js";
|
||||||
|
|
||||||
const LABEL = 'label';
|
const LABEL = 'label';
|
||||||
const RELATION = 'relation';
|
const RELATION = 'relation';
|
||||||
@ -268,7 +269,7 @@ class NoteShort {
|
|||||||
attrArrs.push(
|
attrArrs.push(
|
||||||
templateNote.__getCachedAttributes(newPath)
|
templateNote.__getCachedAttributes(newPath)
|
||||||
// template attr is used as a marker for templates, but it's not meant to be inherited
|
// template attr is used as a marker for templates, but it's not meant to be inherited
|
||||||
.filter(attr => !(attr.type === 'label' && attr.name === 'template'))
|
.filter(attr => !(attr.type === 'label' && (attr.name === 'template' || attr.name === 'workspacetemplate')))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -425,6 +426,11 @@ class NoteShort {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getColorClass() {
|
||||||
|
const color = this.getLabelValue("color");
|
||||||
|
return cssClassManager.createClassForColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
isFolder() {
|
isFolder() {
|
||||||
return this.type === 'search'
|
return this.type === 'search'
|
||||||
|| this.getFilteredChildBranches().length > 0;
|
|| this.getFilteredChildBranches().length > 0;
|
||||||
|
@ -75,6 +75,9 @@ import RelationMapButtons from "../widgets/floating_buttons/relation_map_buttons
|
|||||||
import MermaidExportButton from "../widgets/floating_buttons/mermaid_export_button.js";
|
import MermaidExportButton from "../widgets/floating_buttons/mermaid_export_button.js";
|
||||||
import ShortcutContainer from "../widgets/containers/shortcut_container.js";
|
import ShortcutContainer from "../widgets/containers/shortcut_container.js";
|
||||||
import NoteRevisionsButton from "../widgets/buttons/note_revisions_button.js";
|
import NoteRevisionsButton from "../widgets/buttons/note_revisions_button.js";
|
||||||
|
import EditableCodeButtonsWidget from "../widgets/type_widgets/editable_code_buttons.js";
|
||||||
|
import ApiLogWidget from "../widgets/api_log.js";
|
||||||
|
import HideFloatingButtonsButton from "../widgets/floating_buttons/hide_floating_buttons_button.js";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
constructor(customWidgets) {
|
constructor(customWidgets) {
|
||||||
@ -151,6 +154,7 @@ export default class DesktopLayout {
|
|||||||
.child(new RelationMapButtons())
|
.child(new RelationMapButtons())
|
||||||
.child(new MermaidExportButton())
|
.child(new MermaidExportButton())
|
||||||
.child(new BacklinksWidget())
|
.child(new BacklinksWidget())
|
||||||
|
.child(new HideFloatingButtonsButton())
|
||||||
)
|
)
|
||||||
.child(new MermaidWidget())
|
.child(new MermaidWidget())
|
||||||
.child(
|
.child(
|
||||||
@ -162,6 +166,8 @@ export default class DesktopLayout {
|
|||||||
.child(new SearchResultWidget())
|
.child(new SearchResultWidget())
|
||||||
.child(new SqlResultWidget())
|
.child(new SqlResultWidget())
|
||||||
)
|
)
|
||||||
|
.child(new EditableCodeButtonsWidget())
|
||||||
|
.child(new ApiLogWidget())
|
||||||
.child(new FindWidget())
|
.child(new FindWidget())
|
||||||
.child(
|
.child(
|
||||||
...this.customWidgets.get('node-detail-pane'), // typo, let's keep it for a while as BC
|
...this.customWidgets.get('node-detail-pane'), // typo, let's keep it for a while as BC
|
||||||
|
@ -10,6 +10,7 @@ import ScreenContainer from "../widgets/mobile_widgets/screen_container.js";
|
|||||||
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
|
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
|
||||||
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
|
import ProtectedSessionPasswordDialog from "../widgets/dialogs/protected_session_password.js";
|
||||||
import ConfirmDialog from "../widgets/dialogs/confirm.js";
|
import ConfirmDialog from "../widgets/dialogs/confirm.js";
|
||||||
|
import FilePropertiesWidget from "../widgets/ribbon_widgets/file_properties.js";
|
||||||
|
|
||||||
const MOBILE_CSS = `
|
const MOBILE_CSS = `
|
||||||
<style>
|
<style>
|
||||||
@ -128,7 +129,7 @@ export default class MobileLayout {
|
|||||||
.child(
|
.child(
|
||||||
new NoteDetailWidget()
|
new NoteDetailWidget()
|
||||||
.css('padding', '5px 20px 10px 0')
|
.css('padding', '5px 20px 10px 0')
|
||||||
)
|
).child(new FilePropertiesWidget().css('font-size','smaller'))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.child(new ProtectedSessionPasswordDialog())
|
.child(new ProtectedSessionPasswordDialog())
|
||||||
|
@ -27,7 +27,7 @@ class ContextMenu {
|
|||||||
// in such case we'll position it above click coordinates so it will fit into client
|
// in such case we'll position it above click coordinates so it will fit into client
|
||||||
|
|
||||||
const CONTEXT_MENU_PADDING = 5; // How many pixels to pad context menu from edge of screen
|
const CONTEXT_MENU_PADDING = 5; // How many pixels to pad context menu from edge of screen
|
||||||
const CONTEXT_MENU_OFFSET = 10; // How many pixels to offset context menu by relative to cursor
|
const CONTEXT_MENU_OFFSET = 0; // How many pixels to offset context menu by relative to cursor, see #3157
|
||||||
|
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
const clientWidth = document.documentElement.clientWidth;
|
const clientWidth = document.documentElement.clientWidth;
|
||||||
|
@ -11,7 +11,7 @@ async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
|
|||||||
branchIdsToMove = filterSearchBranches(branchIdsToMove);
|
branchIdsToMove = filterSearchBranches(branchIdsToMove);
|
||||||
|
|
||||||
if (beforeBranchId === 'root') {
|
if (beforeBranchId === 'root') {
|
||||||
alert('Cannot move notes before root note.');
|
toastService.showError('Cannot move notes before root note.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
|
|||||||
const resp = await server.put(`branches/${branchIdToMove}/move-before/${beforeBranchId}`);
|
const resp = await server.put(`branches/${branchIdToMove}/move-before/${beforeBranchId}`);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
|
|||||||
const afterNote = await froca.getBranch(afterBranchId).getNote();
|
const afterNote = await froca.getBranch(afterBranchId).getNote();
|
||||||
|
|
||||||
if (afterNote.noteId === 'root' || afterNote.noteId === hoistedNoteService.getHoistedNoteId()) {
|
if (afterNote.noteId === 'root' || afterNote.noteId === hoistedNoteService.getHoistedNoteId()) {
|
||||||
alert('Cannot move notes after root note.');
|
toastService.showError('Cannot move notes after root note.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
|
|||||||
const resp = await server.put(`branches/${branchIdToMove}/move-after/${afterBranchId}`);
|
const resp = await server.put(`branches/${branchIdToMove}/move-after/${afterBranchId}`);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,13 +62,13 @@ async function moveToParentNote(branchIdsToMove, newParentBranchId) {
|
|||||||
const resp = await server.put(`branches/${branchIdToMove}/move-to/${newParentBranchId}`);
|
const resp = await server.put(`branches/${branchIdToMove}/move-to/${newParentBranchId}`);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteNotes(branchIdsToDelete) {
|
async function deleteNotes(branchIdsToDelete, forceDeleteAllClones = false) {
|
||||||
branchIdsToDelete = filterRootNote(branchIdsToDelete);
|
branchIdsToDelete = filterRootNote(branchIdsToDelete);
|
||||||
|
|
||||||
if (branchIdsToDelete.length === 0) {
|
if (branchIdsToDelete.length === 0) {
|
||||||
@ -83,7 +83,7 @@ async function deleteNotes(branchIdsToDelete) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
({proceed, deleteAllClones, eraseNotes} = await new Promise(res =>
|
({proceed, deleteAllClones, eraseNotes} = await new Promise(res =>
|
||||||
appContext.triggerCommand('showDeleteNotesDialog', {branchIdsToDelete, callback: res})));
|
appContext.triggerCommand('showDeleteNotesDialog', {branchIdsToDelete, callback: res, forceDeleteAllClones})));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!proceed) {
|
if (!proceed) {
|
||||||
@ -130,7 +130,7 @@ async function moveNodeUpInHierarchy(node) {
|
|||||||
const resp = await server.put(`branches/${branchIdToMove}/move-after/${targetBranchId}`);
|
const resp = await server.put(`branches/${branchIdToMove}/move-after/${targetBranchId}`);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +206,7 @@ async function cloneNoteToBranch(childNoteId, parentBranchId, prefix) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,7 +216,7 @@ async function cloneNoteToNote(childNoteId, parentNoteId, prefix) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +225,7 @@ async function cloneNoteAfter(noteId, afterBranchId) {
|
|||||||
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId);
|
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert(resp.message);
|
toastService.showError(resp.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
27
src/public/app/services/css_class_manager.js
Normal file
27
src/public/app/services/css_class_manager.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const registeredClasses = new Set();
|
||||||
|
|
||||||
|
function createClassForColor(color) {
|
||||||
|
if (!color?.trim()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedColorName = color.replace(/[^a-z0-9]/gi, "");
|
||||||
|
|
||||||
|
if (!normalizedColorName.trim()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const className = 'color-' + normalizedColorName;
|
||||||
|
|
||||||
|
if (!registeredClasses.has(className)) {
|
||||||
|
$("head").append(`<style>.${className} { color: ${color} !important; }</style>`);
|
||||||
|
|
||||||
|
registeredClasses.add(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
createClassForColor
|
||||||
|
};
|
@ -179,7 +179,7 @@ export default class Entrypoints extends Component {
|
|||||||
const resp = await server.post("sql/execute/" + note.noteId);
|
const resp = await server.post("sql/execute/" + note.noteId);
|
||||||
|
|
||||||
if (!resp.success) {
|
if (!resp.success) {
|
||||||
alert("Error occurred while executing SQL query: " + resp.message);
|
toastService.showError("Error occurred while executing SQL query: " + resp.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
await appContext.triggerEvent('sqlQueryResults', {ntxId: ntxId, results: resp.results});
|
await appContext.triggerEvent('sqlQueryResults', {ntxId: ntxId, results: resp.results});
|
||||||
|
@ -13,6 +13,7 @@ import appContext from "./app_context.js";
|
|||||||
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js";
|
||||||
import NoteContextCachingWidget from "../widgets/note_context_caching_widget.js";
|
import NoteContextCachingWidget from "../widgets/note_context_caching_widget.js";
|
||||||
import BasicWidget from "../widgets/basic_widget.js";
|
import BasicWidget from "../widgets/basic_widget.js";
|
||||||
|
import SpacedUpdate from "./spaced_update.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main frontend API interface for scripts. It's published in the local "api" object.
|
* This is the main frontend API interface for scripts. It's published in the local "api" object.
|
||||||
@ -594,6 +595,33 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
|
|||||||
* @returns {string} random string
|
* @returns {string} random string
|
||||||
*/
|
*/
|
||||||
this.randomString = utils.randomString;
|
this.randomString = utils.randomString;
|
||||||
|
|
||||||
|
this.logMessages = {};
|
||||||
|
this.logSpacedUpdates = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log given message to the log pane in UI
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
this.log = message => {
|
||||||
|
const {noteId} = this.startNote;
|
||||||
|
|
||||||
|
message = utils.now() + ": " + message;
|
||||||
|
|
||||||
|
console.log(`Script ${noteId}: ${message}`);
|
||||||
|
|
||||||
|
this.logMessages[noteId] = this.logMessages[noteId] || [];
|
||||||
|
this.logSpacedUpdates[noteId] = this.logSpacedUpdates[noteId] || new SpacedUpdate(() => {
|
||||||
|
const messages = this.logMessages[noteId];
|
||||||
|
this.logMessages[noteId] = [];
|
||||||
|
|
||||||
|
appContext.triggerEvent("apiLogMessages", {noteId, messages});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
this.logMessages[noteId].push(message);
|
||||||
|
this.logSpacedUpdates[noteId].scheduleUpdate();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FrontendScriptApi;
|
export default FrontendScriptApi;
|
||||||
|
@ -32,6 +32,9 @@ export async function uploadFiles(parentNoteId, files, options) {
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
timeout: 60 * 60 * 1000,
|
timeout: 60 * 60 * 1000,
|
||||||
|
error: function(xhr) {
|
||||||
|
toastService.showError("Import failed: " + xhr.responseText);
|
||||||
|
},
|
||||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||||
processData: false, // NEEDED, DON'T REMOVE THIS
|
processData: false, // NEEDED, DON'T REMOVE THIS
|
||||||
}));
|
}));
|
||||||
|
@ -162,7 +162,10 @@ async function loadReferenceLinkTitle(noteId, $el) {
|
|||||||
title = note.isDeleted ? `${note.title} (deleted)` : note.title;
|
title = note.isDeleted ? `${note.title} (deleted)` : note.title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$el.addClass(note.getColorClass());
|
||||||
$el.text(title);
|
$el.text(title);
|
||||||
|
|
||||||
|
$el.prepend($("<span>").addClass(note.getIcon()));
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('click', "a", goToLink);
|
$(document).on('click', "a", goToLink);
|
||||||
|
@ -5,7 +5,7 @@ import noteCreateService from './note_create.js';
|
|||||||
import treeService from './tree.js';
|
import treeService from './tree.js';
|
||||||
import froca from "./froca.js";
|
import froca from "./froca.js";
|
||||||
|
|
||||||
// this key needs to have this value so it's hit by the tooltip
|
// this key needs to have this value, so it's hit by the tooltip
|
||||||
const SELECTED_NOTE_PATH_KEY = "data-note-path";
|
const SELECTED_NOTE_PATH_KEY = "data-note-path";
|
||||||
|
|
||||||
const SELECTED_EXTERNAL_LINK_KEY = "data-external-link";
|
const SELECTED_EXTERNAL_LINK_KEY = "data-external-link";
|
||||||
@ -89,6 +89,11 @@ function showRecentNotes($el) {
|
|||||||
$el.setSelectedNotePath("");
|
$el.setSelectedNotePath("");
|
||||||
$el.autocomplete("val", "");
|
$el.autocomplete("val", "");
|
||||||
$el.trigger('focus');
|
$el.trigger('focus');
|
||||||
|
|
||||||
|
// simulate pressing down arrow to trigger autocomplete
|
||||||
|
const e = $.Event('keydown');
|
||||||
|
e.which = 40; // arrow down
|
||||||
|
$el.trigger(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initNoteAutocomplete($el, options) {
|
function initNoteAutocomplete($el, options) {
|
||||||
|
@ -74,7 +74,7 @@ async function getRenderedContent(note, options = {}) {
|
|||||||
const $openButton = $('<button class="file-open btn btn-primary" type="button">Open</button>');
|
const $openButton = $('<button class="file-open btn btn-primary" type="button">Open</button>');
|
||||||
|
|
||||||
$downloadButton.on('click', () => openService.downloadFileNote(note.noteId));
|
$downloadButton.on('click', () => openService.downloadFileNote(note.noteId));
|
||||||
$openButton.on('click', () => openService.openNoteExternally(note.noteId));
|
$openButton.on('click', () => openService.openNoteExternally(note.noteId, note.mime));
|
||||||
|
|
||||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||||
$openButton.toggle(!note.isProtected);
|
$openButton.toggle(!note.isProtected);
|
||||||
|
@ -184,7 +184,7 @@ class NoteContext extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// "readOnly" is a state valid only for text/code notes
|
// "readOnly" is a state valid only for text/code notes
|
||||||
if (!this.note || this.note.type !== 'text' && this.note.type !== 'code') {
|
if (!this.note || (this.note.type !== 'text' && this.note.type !== 'code')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,9 @@ import server from "./server.js";
|
|||||||
function getFileUrl(noteId) {
|
function getFileUrl(noteId) {
|
||||||
return getUrlForDownload("api/notes/" + noteId + "/download");
|
return getUrlForDownload("api/notes/" + noteId + "/download");
|
||||||
}
|
}
|
||||||
|
function getOpenFileUrl(noteId) {
|
||||||
|
return getUrlForDownload("api/notes/" + noteId + "/open");
|
||||||
|
}
|
||||||
|
|
||||||
function download(url) {
|
function download(url) {
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
@ -21,7 +24,7 @@ function downloadFileNote(noteId) {
|
|||||||
download(url);
|
download(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function openNoteExternally(noteId) {
|
async function openNoteExternally(noteId, mime) {
|
||||||
if (utils.isElectron()) {
|
if (utils.isElectron()) {
|
||||||
const resp = await server.post("notes/" + noteId + "/save-to-tmp-dir");
|
const resp = await server.post("notes/" + noteId + "/save-to-tmp-dir");
|
||||||
|
|
||||||
@ -32,10 +35,16 @@ async function openNoteExternally(noteId) {
|
|||||||
// fallback in case there's no default application for this file
|
// fallback in case there's no default application for this file
|
||||||
open(getFileUrl(noteId), {url: true});
|
open(getFileUrl(noteId), {url: true});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// allow browser to handle opening common file
|
||||||
|
if (mime === "application/pdf" || mime.startsWith("image") || mime.startsWith("audio") || mime.startsWith("video")){
|
||||||
|
window.open(getOpenFileUrl(noteId));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
window.location.href = getFileUrl(noteId);
|
window.location.href = getFileUrl(noteId);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadNoteRevision(noteId, noteRevisionId) {
|
function downloadNoteRevision(noteId, noteRevisionId) {
|
||||||
|
@ -45,9 +45,10 @@ export default class RootCommandExecutor extends Component {
|
|||||||
|
|
||||||
openNoteExternallyCommand() {
|
openNoteExternallyCommand() {
|
||||||
const noteId = appContext.tabManager.getActiveContextNoteId();
|
const noteId = appContext.tabManager.getActiveContextNoteId();
|
||||||
|
const mime = appContext.tabManager.getActiveContextNoteMime()
|
||||||
|
|
||||||
if (noteId) {
|
if (noteId) {
|
||||||
openService.openNoteExternally(noteId);
|
openService.openNoteExternally(noteId, mime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +197,12 @@ export default class TabManager extends Component {
|
|||||||
|
|
||||||
return activeNote ? activeNote.type : null;
|
return activeNote ? activeNote.type : null;
|
||||||
}
|
}
|
||||||
|
/** @returns {string|null} */
|
||||||
|
getActiveContextNoteMime() {
|
||||||
|
const activeNote = this.getActiveContextNote();
|
||||||
|
|
||||||
|
return activeNote ? activeNote.mime : null;
|
||||||
|
}
|
||||||
|
|
||||||
async switchToNoteContext(ntxId, notePath) {
|
async switchToNoteContext(ntxId, notePath) {
|
||||||
const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId)
|
const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId)
|
||||||
|
@ -3,6 +3,7 @@ import toastService from "./toast.js";
|
|||||||
import server from "./server.js";
|
import server from "./server.js";
|
||||||
import options from "./options.js";
|
import options from "./options.js";
|
||||||
import frocaUpdater from "./froca_updater.js";
|
import frocaUpdater from "./froca_updater.js";
|
||||||
|
import appContext from "./app_context.js";
|
||||||
|
|
||||||
const messageHandlers = [];
|
const messageHandlers = [];
|
||||||
|
|
||||||
@ -118,6 +119,9 @@ async function handleMessage(event) {
|
|||||||
else if (message.type === 'consistency-checks-failed') {
|
else if (message.type === 'consistency-checks-failed') {
|
||||||
toastService.showError("Consistency checks failed! See logs for details.", 50 * 60000);
|
toastService.showError("Consistency checks failed! See logs for details.", 50 * 60000);
|
||||||
}
|
}
|
||||||
|
else if (message.type === 'api-log-messages') {
|
||||||
|
appContext.triggerEvent("apiLogMessages", {noteId: message.noteId, messages: message.messages});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let entityChangeIdReachedListeners = [];
|
let entityChangeIdReachedListeners = [];
|
||||||
@ -175,7 +179,7 @@ async function consumeFrontendUpdateData() {
|
|||||||
else {
|
else {
|
||||||
console.log("nonProcessedEntityChanges causing the timeout", nonProcessedEntityChanges);
|
console.log("nonProcessedEntityChanges causing the timeout", nonProcessedEntityChanges);
|
||||||
|
|
||||||
alert(`Encountered error "${e.message}", check out the console.`);
|
toastService.showError(`Encountered error "${e.message}", check out the console.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,5 +17,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const toggleMenuButton = document.getElementById('toggleMenuButton');
|
const toggleMenuButton = document.getElementById('toggleMenuButton');
|
||||||
const layout = document.getElementById('layout');
|
const layout = document.getElementById('layout');
|
||||||
|
|
||||||
|
if (toggleMenuButton && layout) {
|
||||||
toggleMenuButton.addEventListener('click', () => layout.classList.toggle('showMenu'));
|
toggleMenuButton.addEventListener('click', () => layout.classList.toggle('showMenu'));
|
||||||
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
75
src/public/app/widgets/api_log.js
Normal file
75
src/public/app/widgets/api_log.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div class="api-log-widget">
|
||||||
|
<style>
|
||||||
|
.api-log-widget {
|
||||||
|
padding: 15px;
|
||||||
|
flex-grow: 1;
|
||||||
|
max-height: 40%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden-api-log {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.api-log-container {
|
||||||
|
overflow: auto;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-api-log-button {
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid var(--button-border-color);
|
||||||
|
background-color: var(--button-background-color);
|
||||||
|
border-radius: var(--button-border-radius);
|
||||||
|
color: var(--button-text-color);
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="bx bx-x close-api-log-button" title="Close"></div>
|
||||||
|
|
||||||
|
<div class="api-log-container"></div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
export default class ApiLogWidget extends NoteContextAwareWidget {
|
||||||
|
isEnabled() {
|
||||||
|
return this.note
|
||||||
|
&& this.note.mime.startsWith('application/javascript;env=')
|
||||||
|
&& super.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
doRender() {
|
||||||
|
this.$widget = $(TPL);
|
||||||
|
this.toggle(false);
|
||||||
|
|
||||||
|
this.$logContainer = this.$widget.find('.api-log-container');
|
||||||
|
this.$closeButton = this.$widget.find(".close-api-log-button");
|
||||||
|
this.$closeButton.on("click", () => this.toggle(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshWithNote(note) {
|
||||||
|
this.$logContainer.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
apiLogMessagesEvent({messages, noteId}) {
|
||||||
|
if (!this.isNote(noteId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toggle(true);
|
||||||
|
|
||||||
|
for (const message of messages) {
|
||||||
|
this.$logContainer.append(message).append($("<br>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle(show) {
|
||||||
|
this.$widget.toggleClass("hidden-api-log", !show);
|
||||||
|
}
|
||||||
|
}
|
@ -207,6 +207,7 @@ const ATTR_HELP = {
|
|||||||
"workspaceIconClass": "defines box icon CSS class which will be used in tab when hoisted to this note",
|
"workspaceIconClass": "defines box icon CSS class which will be used in tab when hoisted to this note",
|
||||||
"workspaceTabBackgroundColor": "CSS color used in the note tab when hoisted to this note",
|
"workspaceTabBackgroundColor": "CSS color used in the note tab when hoisted to this note",
|
||||||
"workspaceCalendarRoot": "Defines per-workspace calendar root",
|
"workspaceCalendarRoot": "Defines per-workspace calendar root",
|
||||||
|
"workspaceTemplate": "This note will appear in the selection of available template when creating new note, but only when hoisted into a workspace containing this template",
|
||||||
"searchHome": "new search notes will be created as children of this note",
|
"searchHome": "new search notes will be created as children of this note",
|
||||||
"hoistedSearchHome": "new search notes will be created as children of this note when hoisted to some ancestor of this note",
|
"hoistedSearchHome": "new search notes will be created as children of this note when hoisted to some ancestor of this note",
|
||||||
"inbox": "default inbox location for new notes",
|
"inbox": "default inbox location for new notes",
|
||||||
@ -218,6 +219,7 @@ const ATTR_HELP = {
|
|||||||
"shareAlias": "define an alias using which the note will be available under https://your_trilium_host/share/[your_alias]",
|
"shareAlias": "define an alias using which the note will be available under https://your_trilium_host/share/[your_alias]",
|
||||||
"shareOmitDefaultCss": "default share page CSS will be omitted. Use when you make extensive styling changes.",
|
"shareOmitDefaultCss": "default share page CSS will be omitted. Use when you make extensive styling changes.",
|
||||||
"shareRoot": "marks note which is served on /share root.",
|
"shareRoot": "marks note which is served on /share root.",
|
||||||
|
"shareDescription": "define text to be added to the HTML meta tag for description",
|
||||||
"shareRaw": "note will be served in its raw format, without HTML wrapper",
|
"shareRaw": "note will be served in its raw format, without HTML wrapper",
|
||||||
"shareDisallowRobotIndexing": `will forbid robot indexing of this note via <code>X-Robots-Tag: noindex</code> header`,
|
"shareDisallowRobotIndexing": `will forbid robot indexing of this note via <code>X-Robots-Tag: noindex</code> header`,
|
||||||
"shareCredentials": "require credentials to access this shared note. Value is expected to be in format 'username:password'. Don't forget to make this inheritable to apply to child-notes/images.",
|
"shareCredentials": "require credentials to access this shared note. Value is expected to be in format 'username:password'. Don't forget to make this inheritable to apply to child-notes/images.",
|
||||||
@ -233,7 +235,9 @@ const ATTR_HELP = {
|
|||||||
|
|
||||||
See <a href="https://github.com/zadam/trilium/wiki/Default-note-title">wiki with details</a>, API docs for <a href="https://zadam.github.io/trilium/backend_api/Note.html">parentNote</a> and <a href="https://day.js.org/docs/en/display/format">now</a> for details.`,
|
See <a href="https://github.com/zadam/trilium/wiki/Default-note-title">wiki with details</a>, API docs for <a href="https://zadam.github.io/trilium/backend_api/Note.html">parentNote</a> and <a href="https://day.js.org/docs/en/display/format">now</a> for details.`,
|
||||||
"template": "This note will appear in the selection of available template when creating new note",
|
"template": "This note will appear in the selection of available template when creating new note",
|
||||||
"toc": "<code>#toc</code> or <code>#toc=show</code> will force the Table of Contents to be shown, <code>#toc=hide</code> will force hiding it. If the label doesn't exist, the global setting is observed"
|
"toc": "<code>#toc</code> or <code>#toc=show</code> will force the Table of Contents to be shown, <code>#toc=hide</code> will force hiding it. If the label doesn't exist, the global setting is observed",
|
||||||
|
"color": "defines color of the note in note tree, links etc. Use any valid CSS color value like 'red' or #a13d5f",
|
||||||
|
"keyboardShortcut": "Defines a keyboard shortcut which will immediately jump to this note. Example: 'ctrl+alt+e'. Requires frontend reload for the change to take effect."
|
||||||
},
|
},
|
||||||
"relation": {
|
"relation": {
|
||||||
"runOnNoteCreation": "executes when note is created on backend",
|
"runOnNoteCreation": "executes when note is created on backend",
|
||||||
|
@ -57,8 +57,10 @@ const TPL = `
|
|||||||
}
|
}
|
||||||
|
|
||||||
.add-new-attribute-button:hover, .save-attributes-button:hover {
|
.add-new-attribute-button:hover, .save-attributes-button:hover {
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--button-border-color);
|
||||||
border-radius: 2px;
|
border-radius: var(--button-border-radius);
|
||||||
|
background: var(--button-background-color);
|
||||||
|
color: var(--button-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.attribute-errors {
|
.attribute-errors {
|
||||||
@ -297,6 +299,12 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
|
if (this.lastUpdatedNoteId !== this.noteId) {
|
||||||
|
// https://github.com/zadam/trilium/issues/3090
|
||||||
|
console.warn("Ignoring blur event because a different note is loaded.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const attributes = this.parseAttributes();
|
const attributes = this.parseAttributes();
|
||||||
|
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
@ -354,6 +362,8 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataChanged() {
|
dataChanged() {
|
||||||
|
this.lastUpdatedNoteId = this.noteId;
|
||||||
|
|
||||||
if (this.lastSavedContent === this.textEditor.getData()) {
|
if (this.lastSavedContent === this.textEditor.getData()) {
|
||||||
this.$saveAttributesButton.fadeOut();
|
this.$saveAttributesButton.fadeOut();
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,28 @@ class BasicWidget extends Component {
|
|||||||
style: ''
|
style: ''
|
||||||
};
|
};
|
||||||
this.classes = [];
|
this.classes = [];
|
||||||
|
|
||||||
|
this.children = [];
|
||||||
|
this.childPositionCounter = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
child(...components) {
|
||||||
|
if (!components) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.child(...components);
|
||||||
|
|
||||||
|
for (const component of components) {
|
||||||
|
if (component.position === undefined) {
|
||||||
|
component.position = this.childPositionCounter;
|
||||||
|
this.childPositionCounter += 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1);
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
id(id) {
|
id(id) {
|
||||||
|
@ -4,6 +4,7 @@ import dateNoteService from "../../services/date_notes.js";
|
|||||||
import server from "../../services/server.js";
|
import server from "../../services/server.js";
|
||||||
import appContext from "../../services/app_context.js";
|
import appContext from "../../services/app_context.js";
|
||||||
import RightDropdownButtonWidget from "./right_dropdown_button.js";
|
import RightDropdownButtonWidget from "./right_dropdown_button.js";
|
||||||
|
import toastService from "../../services/toast.js";
|
||||||
|
|
||||||
const DROPDOWN_TPL = `
|
const DROPDOWN_TPL = `
|
||||||
<div class="calendar-dropdown-widget">
|
<div class="calendar-dropdown-widget">
|
||||||
@ -62,7 +63,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
|
|||||||
this.hideDropdown();
|
this.hideDropdown();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
alert("Cannot find day note");
|
toastService.showError("Cannot find day note");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,4 +49,10 @@ export default class EditButton extends ButtonWidget {
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async noteTypeMimeChangedEvent({noteId}) {
|
||||||
|
if (this.isNote(noteId)) {
|
||||||
|
await this.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,31 @@ const TPL = `
|
|||||||
bottom: -30px;
|
bottom: -30px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.update-to-latest-version-button {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-menu .zoom-buttons a {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid var(--button-border-color);
|
||||||
|
border-radius: var(--button-border-radius);
|
||||||
|
color: var(--button-text-color);
|
||||||
|
background-color: var(--button-background-color);
|
||||||
|
padding: 3px;
|
||||||
|
margin-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-menu .zoom-buttons a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.global-menu .zoom-state {
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<button type="button" data-toggle="dropdown" data-placement="right"
|
<button type="button" data-toggle="dropdown" data-placement="right"
|
||||||
@ -93,10 +115,29 @@ const TPL = `
|
|||||||
<kbd data-command="reloadFrontendApp"></kbd>
|
<kbd data-command="reloadFrontendApp"></kbd>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<span class="zoom-container dropdown-item" style="display: flex; flex-direction: row; justify-content: space-between;">
|
||||||
|
<div>
|
||||||
|
<span class="bx bx-empty"></span>
|
||||||
|
Zoom
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="zoom-buttons">
|
||||||
|
<a data-trigger-command="toggleFullscreen" title="Toggle fullscreen" class="bx bx-expand-alt"></a>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a data-trigger-command="zoomOut" title="Zoom out" class="bx bx-minus"></a>
|
||||||
|
|
||||||
|
<span class="zoom-state"></span>
|
||||||
|
|
||||||
|
<a data-trigger-command="zoomIn" title="Zoom in" class="bx bx-plus"></a>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
|
||||||
<a class="dropdown-item" data-trigger-command="toggleFullscreen">
|
<a class="dropdown-item" data-trigger-command="toggleFullscreen">
|
||||||
<span class="bx bx-empty"></span>
|
<span class="bx bx-empty"></span>
|
||||||
Toggle fullscreen
|
Toggle fullscreen
|
||||||
<kbd data-command="toggleFullscreen"></kbd>
|
<kbd ></kbd>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a class="dropdown-item" data-trigger-command="showHelp">
|
<a class="dropdown-item" data-trigger-command="showHelp">
|
||||||
@ -146,9 +187,13 @@ export default class GlobalMenuWidget extends BasicWidget {
|
|||||||
this.$widget.find(".open-dev-tools-button").toggle(isElectron);
|
this.$widget.find(".open-dev-tools-button").toggle(isElectron);
|
||||||
this.$widget.find(".switch-to-mobile-version-button").toggle(!isElectron);
|
this.$widget.find(".switch-to-mobile-version-button").toggle(!isElectron);
|
||||||
|
|
||||||
|
this.$widget.on('click', '.dropdown-item', e => {
|
||||||
|
if ($(e.target).parent(".zoom-buttons")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.$widget.on('click', '.dropdown-item',
|
this.$widget.find("[data-toggle='dropdown']").dropdown('toggle');
|
||||||
() => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle'));
|
});
|
||||||
|
|
||||||
this.$widget.find(".global-menu-button-update-available").append(
|
this.$widget.find(".global-menu-button-update-available").append(
|
||||||
this.updateAvailableWidget.render()
|
this.updateAvailableWidget.render()
|
||||||
@ -156,11 +201,34 @@ export default class GlobalMenuWidget extends BasicWidget {
|
|||||||
|
|
||||||
this.$updateToLatestVersionButton = this.$widget.find(".update-to-latest-version-button");
|
this.$updateToLatestVersionButton = this.$widget.find(".update-to-latest-version-button");
|
||||||
|
|
||||||
|
if (!utils.isElectron()) {
|
||||||
|
this.$widget.find(".zoom-container").hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$zoomState = this.$widget.find(".zoom-state");
|
||||||
|
this.$widget.on('show.bs.dropdown', () => this.updateZoomState());
|
||||||
|
|
||||||
|
this.$widget.find(".zoom-buttons").on("click",
|
||||||
|
// delay to wait for the actual zoom change
|
||||||
|
() => setTimeout(() => this.updateZoomState(), 300)
|
||||||
|
);
|
||||||
|
|
||||||
this.updateVersionStatus();
|
this.updateVersionStatus();
|
||||||
|
|
||||||
setInterval(() => this.updateVersionStatus(), 8 * 60 * 60 * 1000);
|
setInterval(() => this.updateVersionStatus(), 8 * 60 * 60 * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateZoomState() {
|
||||||
|
if (!utils.isElectron()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const zoomFactor = utils.dynamicRequire('electron').webFrame.getZoomFactor();
|
||||||
|
const zoomPercent = Math.round(zoomFactor * 100);
|
||||||
|
|
||||||
|
this.$zoomState.text(zoomPercent + "%");
|
||||||
|
}
|
||||||
|
|
||||||
async updateVersionStatus() {
|
async updateVersionStatus() {
|
||||||
if (options.get("checkForUpdates") !== 'true') {
|
if (options.get("checkForUpdates") !== 'true') {
|
||||||
return;
|
return;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
import utils from "../../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
|
import branchService from "../../services/branches.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="dropdown note-actions">
|
<div class="dropdown note-actions">
|
||||||
@ -30,6 +31,7 @@ const TPL = `
|
|||||||
<a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a>
|
<a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a>
|
||||||
<a class="dropdown-item import-files-button">Import files</a>
|
<a class="dropdown-item import-files-button">Import files</a>
|
||||||
<a class="dropdown-item export-note-button">Export note</a>
|
<a class="dropdown-item export-note-button">Export note</a>
|
||||||
|
<a class="dropdown-item delete-note-button">Delete note</a>
|
||||||
<a data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button"><kbd data-command="printActiveNote"></kbd> Print note</a>
|
<a data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button"><kbd data-command="printActiveNote"></kbd> Print note</a>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
@ -65,6 +67,15 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
|
|||||||
this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle'));
|
this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle'));
|
||||||
|
|
||||||
this.$openNoteExternallyButton = this.$widget.find(".open-note-externally-button");
|
this.$openNoteExternallyButton = this.$widget.find(".open-note-externally-button");
|
||||||
|
|
||||||
|
this.$deleteNoteButton = this.$widget.find(".delete-note-button");
|
||||||
|
this.$deleteNoteButton.on("click", () => {
|
||||||
|
if (this.note.noteId === 'root') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
branchService.deleteNotes([this.note.getParentBranches()[0].branchId], true);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshWithNote(note) {
|
refreshWithNote(note) {
|
||||||
|
@ -8,7 +8,7 @@ const TPL = `
|
|||||||
height: 21px !important;
|
height: 21px !important;
|
||||||
padding: 0 !important;
|
padding: 0 !important;
|
||||||
|
|
||||||
border-radius: 8px;
|
border-radius: var(--button-border-radius);
|
||||||
transform: scale(0.9);
|
transform: scale(0.9);
|
||||||
border: none;
|
border: none;
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
|
@ -1,33 +1,6 @@
|
|||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
|
|
||||||
export default class Container extends BasicWidget {
|
export default class Container extends BasicWidget {
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.children = [];
|
|
||||||
|
|
||||||
this.positionCounter = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
child(...components) {
|
|
||||||
if (!components) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.child(...components);
|
|
||||||
|
|
||||||
for (const component of components) {
|
|
||||||
if (!component.position) {
|
|
||||||
component.position = this.positionCounter;
|
|
||||||
this.positionCounter += 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.children.sort((a, b) => a.position - b.position < 0 ? -1 : 1);
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(`<div>`);
|
this.$widget = $(`<div>`);
|
||||||
this.renderChildren();
|
this.renderChildren();
|
||||||
|
@ -4,6 +4,7 @@ export default class ScrollingContainer extends Container {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
this.class("scrolling-container");
|
||||||
this.css('overflow', 'auto');
|
this.css('overflow', 'auto');
|
||||||
this.css('position', 'relative');
|
this.css('position', 'relative');
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import BasicWidget from "../basic_widget.js";
|
|||||||
const DELETE_NOTE_BUTTON_CLASS = "confirm-dialog-delete-note";
|
const DELETE_NOTE_BUTTON_CLASS = "confirm-dialog-delete-note";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="confirm-dialog modal mx-auto" tabindex="-1" role="dialog">
|
<div class="confirm-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
|
||||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -97,7 +97,7 @@ export default class DeleteNotesDialog extends BasicWidget {
|
|||||||
|
|
||||||
this.resolve({
|
this.resolve({
|
||||||
proceed: true,
|
proceed: true,
|
||||||
deleteAllClones: this.isDeleteAllClonesChecked(),
|
deleteAllClones: this.forceDeleteAllClones || this.isDeleteAllClonesChecked(),
|
||||||
eraseNotes: this.isEraseNotesChecked()
|
eraseNotes: this.isEraseNotesChecked()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -108,7 +108,7 @@ export default class DeleteNotesDialog extends BasicWidget {
|
|||||||
async renderDeletePreview() {
|
async renderDeletePreview() {
|
||||||
const response = await server.post('delete-notes-preview', {
|
const response = await server.post('delete-notes-preview', {
|
||||||
branchIdsToDelete: this.branchIds,
|
branchIdsToDelete: this.branchIds,
|
||||||
deleteAllClones: this.isDeleteAllClonesChecked()
|
deleteAllClones: this.forceDeleteAllClones || this.isDeleteAllClonesChecked()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$deleteNotesList.empty();
|
this.$deleteNotesList.empty();
|
||||||
@ -143,14 +143,18 @@ export default class DeleteNotesDialog extends BasicWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async showDeleteNotesDialogEvent({branchIdsToDelete, callback}) {
|
async showDeleteNotesDialogEvent({branchIdsToDelete, callback, forceDeleteAllClones}) {
|
||||||
this.branchIds = branchIdsToDelete;
|
this.branchIds = branchIdsToDelete;
|
||||||
|
this.forceDeleteAllClones = forceDeleteAllClones;
|
||||||
|
|
||||||
await this.renderDeletePreview();
|
await this.renderDeletePreview();
|
||||||
|
|
||||||
utils.openDialog(this.$widget);
|
utils.openDialog(this.$widget);
|
||||||
|
|
||||||
this.$deleteAllClones.prop("checked", false);
|
this.$deleteAllClones
|
||||||
|
.prop("checked", !!forceDeleteAllClones)
|
||||||
|
.prop("disabled", !!forceDeleteAllClones);
|
||||||
|
|
||||||
this.$eraseNotes.prop("checked", false);
|
this.$eraseNotes.prop("checked", false);
|
||||||
|
|
||||||
this.resolve = callback;
|
this.resolve = callback;
|
||||||
|
@ -142,7 +142,7 @@ export default class ExportDialog extends BasicWidget {
|
|||||||
|
|
||||||
if (!exportType) {
|
if (!exportType) {
|
||||||
// this shouldn't happen as we always choose default export type
|
// this shouldn't happen as we always choose default export type
|
||||||
alert("Choose export type first please");
|
toastService.showError("Choose export type first please");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ import utils from "../../services/utils.js";
|
|||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="info-dialog modal mx-auto" tabindex="-1" role="dialog">
|
<div class="info-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import server from "../../../services/server.js";
|
import server from "../../../services/server.js";
|
||||||
import dialogService from "../../dialog.js";
|
import dialogService from "../../dialog.js";
|
||||||
|
import toastService from "../../../services/toast.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<h4>ETAPI</h4>
|
<h4>ETAPI</h4>
|
||||||
@ -36,11 +37,11 @@ const TPL = `
|
|||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
font-size: large;
|
font-size: large;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 5px;
|
border-radius: var(--button-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.token-table-button:hover {
|
.token-table-button:hover {
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--button-border-color);
|
||||||
}
|
}
|
||||||
</style>`;
|
</style>`;
|
||||||
|
|
||||||
@ -56,7 +57,7 @@ export default class EtapiOptions {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!tokenName.trim()) {
|
if (!tokenName.trim()) {
|
||||||
alert("Token name can't be empty");
|
toastService.showError("Token name can't be empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ export default class ChangePasswordOptions {
|
|||||||
const options = await server.get('options');
|
const options = await server.get('options');
|
||||||
this.optionsLoaded(options);
|
this.optionsLoaded(options);
|
||||||
|
|
||||||
alert("Password has been reset. Please set new password");
|
toastService.showError("Password has been reset. Please set new password");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ export default class ChangePasswordOptions {
|
|||||||
this.$newPassword2.val('');
|
this.$newPassword2.val('');
|
||||||
|
|
||||||
if (newPassword1 !== newPassword2) {
|
if (newPassword1 !== newPassword2) {
|
||||||
alert("New passwords are not the same.");
|
toastService.showError("New passwords are not the same.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ export default class ChangePasswordOptions {
|
|||||||
'new_password': newPassword1
|
'new_password': newPassword1
|
||||||
}).then(result => {
|
}).then(result => {
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
alert("Password has been changed. Trilium will be reloaded after you press OK.");
|
toastService.showError("Password has been changed. Trilium will be reloaded after you press OK.");
|
||||||
|
|
||||||
// password changed so current protected session is invalid and needs to be cleared
|
// password changed so current protected session is invalid and needs to be cleared
|
||||||
protectedSessionHolder.resetProtectedSession();
|
protectedSessionHolder.resetProtectedSession();
|
||||||
|
@ -2,10 +2,10 @@ import utils from "../../services/utils.js";
|
|||||||
import BasicWidget from "../basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="prompt-dialog modal mx-auto" tabindex="-1" role="dialog">
|
<div class="prompt-dialog modal mx-auto" tabindex="-1" role="dialog" style="z-index: 2000;">
|
||||||
<div class="modal-dialog modal-lg" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<form id="prompt-dialog-form">
|
<form class="prompt-dialog-form">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="prompt-title modal-title mr-auto">Prompt</h5>
|
<h5 class="prompt-title modal-title mr-auto">Prompt</h5>
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ export default class PromptDialog extends BasicWidget {
|
|||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$dialogBody = this.$widget.find(".modal-body");
|
this.$dialogBody = this.$widget.find(".modal-body");
|
||||||
this.$form = this.$widget.find("#prompt-dialog-form");
|
this.$form = this.$widget.find(".prompt-dialog-form");
|
||||||
this.$question = null;
|
this.$question = null;
|
||||||
this.$answer = null;
|
this.$answer = null;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import Container from "../containers/container.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="floating-buttons">
|
<div class="floating-buttons">
|
||||||
@ -16,7 +16,7 @@ const TPL = `
|
|||||||
z-index: 100;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
.floating-buttons-children > * {
|
.floating-buttons-children > *:not(.hidden-int):not(.no-content-hidden) {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,12 +24,16 @@ const TPL = `
|
|||||||
font-size: 130%;
|
font-size: 130%;
|
||||||
padding: 5px 10px 4px 10px;
|
padding: 5px 10px 4px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.floating-buttons.temporarily-hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="floating-buttons-children"></div>
|
<div class="floating-buttons-children"></div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class FloatingButtons extends Container {
|
export default class FloatingButtons extends NoteContextAwareWidget {
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$children = this.$widget.find(".floating-buttons-children");
|
this.$children = this.$widget.find(".floating-buttons-children");
|
||||||
@ -38,4 +42,16 @@ export default class FloatingButtons extends Container {
|
|||||||
this.$children.append(widget.render());
|
this.$children.append(widget.render());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refreshWithNote(note) {
|
||||||
|
this.toggle(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle(show) {
|
||||||
|
this.$widget.toggleClass("temporarily-hidden", !show);
|
||||||
|
}
|
||||||
|
|
||||||
|
hideFloatingButtonsCommand() {
|
||||||
|
this.toggle(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div class="close-floating-buttons">
|
||||||
|
<style>
|
||||||
|
.close-floating-buttons {
|
||||||
|
display: none;
|
||||||
|
margin-left: 5px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* conditionally display close button if there's some other button visible */
|
||||||
|
.floating-buttons *:not(.hidden-int):not(.hidden-no-content) ~ .close-floating-buttons {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-floating-buttons-button {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
color: var(--button-text-color);
|
||||||
|
padding: 6px;
|
||||||
|
border-radius: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-floating-buttons-button:hover {
|
||||||
|
border: 1px solid var(--button-border-color);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button type="button"
|
||||||
|
class="close-floating-buttons-button btn bx bx-x no-print"
|
||||||
|
title="Hide buttons"></button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default class HideFloatingButtonsButton extends NoteContextAwareWidget {
|
||||||
|
doRender() {
|
||||||
|
super.doRender();
|
||||||
|
|
||||||
|
this.$widget = $(TPL);
|
||||||
|
this.$widget.on('click', () => this.triggerCommand('hideFloatingButtons'));
|
||||||
|
this.contentSized();
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,4 @@
|
|||||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
import dialogService from "../dialog.js";
|
|
||||||
import server from "../../services/server.js";
|
|
||||||
import toastService from "../../services/toast.js";
|
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<button type="button"
|
<button type="button"
|
||||||
|
@ -89,17 +89,21 @@ export default class BacklinksWidget extends NoteContextAwareWidget {
|
|||||||
const resp = await server.get(`notes/${this.noteId}/backlink-count`);
|
const resp = await server.get(`notes/${this.noteId}/backlink-count`);
|
||||||
|
|
||||||
if (!resp || !resp.count) {
|
if (!resp || !resp.count) {
|
||||||
this.$ticker.hide();
|
this.toggle(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$ticker.show();
|
this.toggle(true);
|
||||||
this.$count.text(
|
this.$count.text(
|
||||||
`${resp.count} backlink`
|
`${resp.count} backlink`
|
||||||
+ (resp.count === 1 ? '' : 's')
|
+ (resp.count === 1 ? '' : 's')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggle(show) {
|
||||||
|
this.$widget.toggleClass("hidden-no-content", !show);
|
||||||
|
}
|
||||||
|
|
||||||
clearItems() {
|
clearItems() {
|
||||||
this.$items.empty().hide();
|
this.$items.empty().hide();
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
async refresh() {
|
async refresh() {
|
||||||
this.type = await this.getWidgetType();
|
this.type = await this.getWidgetType();
|
||||||
this.mime = this.note ? this.note.mime : null;
|
this.mime = this.note?.mime;
|
||||||
|
|
||||||
if (!(this.type in this.typeWidgets)) {
|
if (!(this.type in this.typeWidgets)) {
|
||||||
const clazz = typeWidgetClasses[this.type];
|
const clazz = typeWidgetClasses[this.type];
|
||||||
@ -279,10 +279,14 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async entitiesReloadedEvent({loadResults}) {
|
async entitiesReloadedEvent({loadResults}) {
|
||||||
if (loadResults.isNoteContentReloaded(this.noteId, this.componentId)
|
// we're detecting note type change on the note_detail level, but triggering the noteTypeMimeChanged
|
||||||
|| (loadResults.isNoteReloaded(this.noteId, this.componentId) && (this.type !== await this.getWidgetType() || this.mime !== this.note.mime))) {
|
// globally, so it gets also to e.g. ribbon components. But this means that the event can be generated multiple
|
||||||
|
// times if the same note is open in several tabs.
|
||||||
|
|
||||||
this.handleEvent('noteTypeMimeChanged', {noteId: this.noteId});
|
if (loadResults.isNoteReloaded(this.noteId, this.componentId)
|
||||||
|
&& (this.type !== await this.getWidgetType() || this.mime !== this.note.mime)) {
|
||||||
|
|
||||||
|
this.triggerEvent('noteTypeMimeChanged', {noteId: this.noteId});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const attrs = loadResults.getAttributes();
|
const attrs = loadResults.getAttributes();
|
||||||
@ -300,7 +304,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
|||||||
if (label || relation) {
|
if (label || relation) {
|
||||||
// probably incorrect event
|
// probably incorrect event
|
||||||
// calling this.refresh() is not enough since the event needs to be propagated to children as well
|
// calling this.refresh() is not enough since the event needs to be propagated to children as well
|
||||||
this.handleEvent('noteTypeMimeChanged', {noteId: this.noteId});
|
this.triggerEvent('noteTypeMimeChanged', {noteId: this.noteId});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import appContext from "../services/app_context.js";
|
|||||||
import keyboardActionsService from "../services/keyboard_actions.js";
|
import keyboardActionsService from "../services/keyboard_actions.js";
|
||||||
import clipboard from "../services/clipboard.js";
|
import clipboard from "../services/clipboard.js";
|
||||||
import protectedSessionService from "../services/protected_session.js";
|
import protectedSessionService from "../services/protected_session.js";
|
||||||
|
import linkService from "../services/link.js";
|
||||||
import syncService from "../services/sync.js";
|
import syncService from "../services/sync.js";
|
||||||
import options from "../services/options.js";
|
import options from "../services/options.js";
|
||||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||||
@ -401,6 +402,18 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
title: node.title
|
title: node.title
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
if (notes.length === 1) {
|
||||||
|
linkService.createNoteLink(notes[0].noteId, {referenceLink: true})
|
||||||
|
.then($link => data.dataTransfer.setData("text/html", $link[0].outerHTML));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Promise.all(notes.map(note => linkService.createNoteLink(note.noteId, {referenceLink: true}))).then(links => {
|
||||||
|
const $list = $("<ul>").append(...links.map($link => $("<li>").append($link)));
|
||||||
|
|
||||||
|
data.dataTransfer.setData("text/html", $list[0].outerHTML);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
data.dataTransfer.setData("text", JSON.stringify(notes));
|
data.dataTransfer.setData("text", JSON.stringify(notes));
|
||||||
return true; // allow dragging to start
|
return true; // allow dragging to start
|
||||||
},
|
},
|
||||||
@ -521,8 +534,6 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
if (isHoistedNote) {
|
if (isHoistedNote) {
|
||||||
const $unhoistButton = $('<span class="tree-item-button unhoist-button bx bx-door-open" title="Unhoist"></span>');
|
const $unhoistButton = $('<span class="tree-item-button unhoist-button bx bx-door-open" title="Unhoist"></span>');
|
||||||
|
|
||||||
$unhoistButton.on('click', () => alert("bebe"));
|
|
||||||
|
|
||||||
$span.append($unhoistButton);
|
$span.append($unhoistButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +681,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
const note = branch.getNoteFromCache();
|
const note = branch.getNoteFromCache();
|
||||||
|
|
||||||
if (!note) {
|
if (!note) {
|
||||||
throw new Error(`Branch "${branch.branchId}" has no note "${branch.noteId}"`);
|
throw new Error(`Branch "${branch.branchId}" has no child note "${branch.noteId}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title;
|
const title = (branch.prefix ? (branch.prefix + " - ") : "") + note.title;
|
||||||
@ -739,6 +750,12 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
extraClasses.push("archived");
|
extraClasses.push("archived");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const colorClass = note.getColorClass();
|
||||||
|
|
||||||
|
if (colorClass) {
|
||||||
|
extraClasses.push(colorClass);
|
||||||
|
}
|
||||||
|
|
||||||
return extraClasses.join(" ");
|
return extraClasses.join(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,7 +963,8 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
if (this.noteContext
|
if (this.noteContext
|
||||||
&& this.noteContext.notePath
|
&& this.noteContext.notePath
|
||||||
&& !this.noteContext.note.isDeleted
|
&& !this.noteContext.note?.isDeleted
|
||||||
|
&& !this.noteContext.notePath.includes("root/hidden")
|
||||||
) {
|
) {
|
||||||
const newActiveNode = await this.getNodeFromPath(this.noteContext.notePath);
|
const newActiveNode = await this.getNodeFromPath(this.noteContext.notePath);
|
||||||
|
|
||||||
@ -1040,7 +1058,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||||||
const noteIdsToReload = new Set();
|
const noteIdsToReload = new Set();
|
||||||
|
|
||||||
for (const ecAttr of loadResults.getAttributes()) {
|
for (const ecAttr of loadResults.getAttributes()) {
|
||||||
if (ecAttr.type === 'label' && ['iconClass', 'cssClass', 'workspace', 'workspaceIconClass', 'archived'].includes(ecAttr.name)) {
|
if (ecAttr.type === 'label' && ['iconClass', 'cssClass', 'workspace', 'workspaceIconClass', 'archived', 'color'].includes(ecAttr.name)) {
|
||||||
if (ecAttr.isInheritable) {
|
if (ecAttr.isInheritable) {
|
||||||
noteIdsToReload.add(ecAttr.noteId);
|
noteIdsToReload.add(ecAttr.noteId);
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,6 @@ export default class NoteWrapperWidget extends FlexContainer {
|
|||||||
.collapsible();
|
.collapsible();
|
||||||
}
|
}
|
||||||
|
|
||||||
doRender() {
|
|
||||||
super.doRender();
|
|
||||||
|
|
||||||
this.$widget.addClass("note-split");
|
|
||||||
}
|
|
||||||
|
|
||||||
setNoteContextEvent({noteContext}) {
|
setNoteContextEvent({noteContext}) {
|
||||||
this.noteContext = noteContext;
|
this.noteContext = noteContext;
|
||||||
|
|
||||||
@ -35,8 +29,14 @@ export default class NoteWrapperWidget extends FlexContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
|
const isHiddenExt = this.isHiddenExt(); // preserve through class reset
|
||||||
|
|
||||||
this.$widget.removeClass();
|
this.$widget.removeClass();
|
||||||
|
|
||||||
|
this.toggleExt(!isHiddenExt);
|
||||||
|
|
||||||
|
this.$widget.addClass("component note-split");
|
||||||
|
|
||||||
const note = this.noteContext?.note;
|
const note = this.noteContext?.note;
|
||||||
if (!note) {
|
if (!note) {
|
||||||
return;
|
return;
|
||||||
|
@ -90,7 +90,7 @@ export default class FilePropertiesWidget extends NoteContextAwareWidget {
|
|||||||
this.$uploadNewRevisionInput = this.$widget.find(".file-upload-new-revision-input");
|
this.$uploadNewRevisionInput = this.$widget.find(".file-upload-new-revision-input");
|
||||||
|
|
||||||
this.$downloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
this.$downloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
||||||
this.$openButton.on('click', () => openService.openNoteExternally(this.noteId));
|
this.$openButton.on('click', () => openService.openNoteExternally(this.noteId, this.note.mime));
|
||||||
|
|
||||||
this.$uploadNewRevisionButton.on("click", () => {
|
this.$uploadNewRevisionButton.on("click", () => {
|
||||||
this.$uploadNewRevisionInput.trigger("click");
|
this.$uploadNewRevisionInput.trigger("click");
|
||||||
|
@ -69,7 +69,7 @@ export default class ImagePropertiesWidget extends NoteContextAwareWidget {
|
|||||||
this.$fileSize = this.$widget.find(".image-filesize");
|
this.$fileSize = this.$widget.find(".image-filesize");
|
||||||
|
|
||||||
this.$openButton = this.$widget.find(".image-open");
|
this.$openButton = this.$widget.find(".image-open");
|
||||||
this.$openButton.on('click', () => openService.openNoteExternally(this.noteId));
|
this.$openButton.on('click', () => openService.openNoteExternally(this.noteId, this.note.mime ));
|
||||||
|
|
||||||
this.$imageDownloadButton = this.$widget.find(".image-download");
|
this.$imageDownloadButton = this.$widget.find(".image-download");
|
||||||
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
this.$imageDownloadButton.on('click', () => openService.downloadFileNote(this.noteId));
|
||||||
|
@ -13,7 +13,7 @@ const TPL = `
|
|||||||
<div style="margin-left: 10px; margin-right: 10px">depth:</div>
|
<div style="margin-left: 10px; margin-right: 10px">depth:</div>
|
||||||
|
|
||||||
<select name="depth" class="form-control d-inline ancestor-depth" style="flex-shrink: 3">
|
<select name="depth" class="form-control d-inline ancestor-depth" style="flex-shrink: 3">
|
||||||
<option value="">doesn't mattter</option>
|
<option value="">doesn't matter</option>
|
||||||
<option value="eq1">is exactly 1 (direct children)</option>
|
<option value="eq1">is exactly 1 (direct children)</option>
|
||||||
<option value="eq2">is exactly 2</option>
|
<option value="eq2">is exactly 2</option>
|
||||||
<option value="eq3">is exactly 3</option>
|
<option value="eq3">is exactly 3</option>
|
||||||
|
@ -16,7 +16,10 @@ const TPL = `
|
|||||||
padding: 0.25rem 0.4rem;
|
padding: 0.25rem 0.4rem;
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
line-height: 0.5;
|
line-height: 0.5;
|
||||||
border-radius: 0.2rem;
|
border: 1px solid var(--button-border-color);
|
||||||
|
border-radius: var(--button-border-radius);
|
||||||
|
background: var(--button-background-color);
|
||||||
|
color: var(--button-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sql-console-result-container {
|
.sql-console-result-container {
|
||||||
|
@ -93,7 +93,7 @@ const TAB_ROW_TPL = `
|
|||||||
|
|
||||||
.note-new-tab:hover {
|
.note-new-tab:hover {
|
||||||
background-color: var(--accented-background-color);
|
background-color: var(--accented-background-color);
|
||||||
border-radius: 5px;
|
border-radius: var(--button-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-row-filler {
|
.tab-row-filler {
|
||||||
|
@ -23,7 +23,7 @@ const TPL = `<div class="toc-widget">
|
|||||||
.toc-widget {
|
.toc-widget {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
contain: none;
|
contain: none;
|
||||||
overflow:auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toc ol {
|
.toc ol {
|
||||||
@ -31,7 +31,15 @@ const TPL = `<div class="toc-widget">
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toc > ol {
|
.toc > ol {
|
||||||
padding-left: 10px;
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc li:hover {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -154,13 +162,7 @@ export default class TocWidget extends CollapsibleWidget {
|
|||||||
//
|
//
|
||||||
|
|
||||||
const headingText = $("<div>").html(m[2]).text();
|
const headingText = $("<div>").html(m[2]).text();
|
||||||
const $li = $('<li style="cursor:pointer">').text(headingText);
|
const $li = $('<li>').text(headingText);
|
||||||
// XXX Do this with CSS? How to inject CSS in doRender?
|
|
||||||
$li.hover(function () {
|
|
||||||
$(this).css("font-weight", "bold");
|
|
||||||
}).mouseout(function () {
|
|
||||||
$(this).css("font-weight", "normal");
|
|
||||||
});
|
|
||||||
$li.on("click", () => this.jumpToHeading(headingIndex));
|
$li.on("click", () => this.jumpToHeading(headingIndex));
|
||||||
$ols[$ols.length - 1].append($li);
|
$ols[$ols.length - 1].append($li);
|
||||||
headingCount = headingIndex;
|
headingCount = headingIndex;
|
||||||
|
@ -23,26 +23,6 @@ const TPL = `
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="note-detail-code-editor"></div>
|
<div class="note-detail-code-editor"></div>
|
||||||
|
|
||||||
<div style="display: flex; justify-content: space-evenly;">
|
|
||||||
<button data-trigger-command="runActiveNote"
|
|
||||||
class="no-print execute-button btn btn-sm">
|
|
||||||
Execute <kbd data-command="runActiveNote"></kbd>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="no-print trilium-api-docs-button btn btn-sm"
|
|
||||||
title="Open Trilium API docs">
|
|
||||||
<span class="bx bx-help-circle"></span>
|
|
||||||
|
|
||||||
API docs
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button class="no-print save-to-note-button btn btn-sm">
|
|
||||||
|
|
||||||
<span class="bx bx-save"></span>
|
|
||||||
Save to note</kbd>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
export default class EditableCodeTypeWidget extends TypeWidget {
|
export default class EditableCodeTypeWidget extends TypeWidget {
|
||||||
@ -50,28 +30,7 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
|||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$openTriliumApiDocsButton = this.$widget.find(".trilium-api-docs-button");
|
|
||||||
this.$openTriliumApiDocsButton.on("click", () => {
|
|
||||||
if (this.note.mime.endsWith("frontend")) {
|
|
||||||
window.open("https://zadam.github.io/trilium/frontend_api/FrontendScriptApi.html", "_blank");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
window.open("https://zadam.github.io/trilium/backend_api/BackendScriptApi.html", "_blank");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$editor = this.$widget.find('.note-detail-code-editor');
|
this.$editor = this.$widget.find('.note-detail-code-editor');
|
||||||
this.$executeButton = this.$widget.find('.execute-button');
|
|
||||||
this.$saveToNoteButton = this.$widget.find('.save-to-note-button');
|
|
||||||
this.$saveToNoteButton.on('click', async () => {
|
|
||||||
const {notePath} = await server.post("special-notes/save-sql-console", {sqlConsoleNoteId: this.noteId});
|
|
||||||
|
|
||||||
await ws.waitForMaxKnownEntityChangeId();
|
|
||||||
|
|
||||||
await appContext.tabManager.getActiveContext().setNote(notePath);
|
|
||||||
|
|
||||||
toastService.showMessage("SQL Console note has been saved into " + await treeService.getNotePathTitle(notePath));
|
|
||||||
});
|
|
||||||
|
|
||||||
keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
|
keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
|
||||||
|
|
||||||
@ -115,18 +74,6 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async doRefresh(note) {
|
async doRefresh(note) {
|
||||||
this.$executeButton.toggle(
|
|
||||||
note.mime.startsWith('application/javascript')
|
|
||||||
|| note.mime === 'text/x-sqlite;schema=trilium'
|
|
||||||
);
|
|
||||||
|
|
||||||
this.$saveToNoteButton.toggle(
|
|
||||||
note.mime === 'text/x-sqlite;schema=trilium'
|
|
||||||
&& !note.getAllNotePaths().find(notePathArr => !notePathArr.includes("hidden"))
|
|
||||||
);
|
|
||||||
|
|
||||||
this.$openTriliumApiDocsButton.toggle(note.mime.startsWith('application/javascript;env='));
|
|
||||||
|
|
||||||
const noteComplement = await this.noteContext.getNoteComplement();
|
const noteComplement = await this.noteContext.getNoteComplement();
|
||||||
|
|
||||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||||
|
96
src/public/app/widgets/type_widgets/editable_code_buttons.js
Normal file
96
src/public/app/widgets/type_widgets/editable_code_buttons.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import server from "../../services/server.js";
|
||||||
|
import ws from "../../services/ws.js";
|
||||||
|
import appContext from "../../services/app_context.js";
|
||||||
|
import toastService from "../../services/toast.js";
|
||||||
|
import treeService from "../../services/tree.js";
|
||||||
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
|
import keyboardActionService from "../../services/keyboard_actions.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div class="editable-code-buttons-widget">
|
||||||
|
<style>
|
||||||
|
.editable-code-buttons-widget {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
padding: 5px;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<button data-trigger-command="runActiveNote"
|
||||||
|
class="no-print execute-button btn btn-sm">
|
||||||
|
<span class="bx bx-run"></span>
|
||||||
|
|
||||||
|
Execute <kbd data-command="runActiveNote"></kbd>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="no-print trilium-api-docs-button btn btn-sm"
|
||||||
|
title="Open Trilium API docs">
|
||||||
|
<span class="bx bx-help-circle"></span>
|
||||||
|
|
||||||
|
API docs
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button class="no-print save-to-note-button btn btn-sm">
|
||||||
|
<span class="bx bx-save"></span>
|
||||||
|
Save to note</kbd>
|
||||||
|
</button>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
export default class EditableCodeButtonsWidget extends NoteContextAwareWidget {
|
||||||
|
isEnabled() {
|
||||||
|
return super.isEnabled()
|
||||||
|
&& this.note
|
||||||
|
&& (this.note.mime.startsWith('application/javascript') || this.note.mime === 'text/x-sqlite;schema=trilium');
|
||||||
|
}
|
||||||
|
|
||||||
|
doRender() {
|
||||||
|
this.$widget = $(TPL);
|
||||||
|
this.$openTriliumApiDocsButton = this.$widget.find(".trilium-api-docs-button");
|
||||||
|
this.$openTriliumApiDocsButton.on("click", () => {
|
||||||
|
if (this.note.mime.endsWith("frontend")) {
|
||||||
|
window.open("https://zadam.github.io/trilium/frontend_api/FrontendScriptApi.html", "_blank");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.open("https://zadam.github.io/trilium/backend_api/BackendScriptApi.html", "_blank");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$executeButton = this.$widget.find('.execute-button');
|
||||||
|
this.$saveToNoteButton = this.$widget.find('.save-to-note-button');
|
||||||
|
this.$saveToNoteButton.on('click', async () => {
|
||||||
|
const {notePath} = await server.post("special-notes/save-sql-console", {sqlConsoleNoteId: this.noteId});
|
||||||
|
|
||||||
|
await ws.waitForMaxKnownEntityChangeId();
|
||||||
|
|
||||||
|
await appContext.tabManager.getActiveContext().setNote(notePath);
|
||||||
|
|
||||||
|
toastService.showMessage("SQL Console note has been saved into " + await treeService.getNotePathTitle(notePath));
|
||||||
|
});
|
||||||
|
|
||||||
|
keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
|
||||||
|
keyboardActionService.updateDisplayedShortcuts(this.$widget);
|
||||||
|
|
||||||
|
super.doRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshWithNote(note) {
|
||||||
|
this.$executeButton.toggle(
|
||||||
|
note.mime.startsWith('application/javascript')
|
||||||
|
|| note.mime === 'text/x-sqlite;schema=trilium'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$saveToNoteButton.toggle(
|
||||||
|
note.mime === 'text/x-sqlite;schema=trilium'
|
||||||
|
&& !note.getAllNotePaths().find(notePathArr => !notePathArr.includes("hidden"))
|
||||||
|
);
|
||||||
|
|
||||||
|
this.$openTriliumApiDocsButton.toggle(note.mime.startsWith('application/javascript;env='));
|
||||||
|
}
|
||||||
|
|
||||||
|
async noteTypeMimeChangedEvent({noteId}) {
|
||||||
|
if (this.isNote(noteId)) {
|
||||||
|
await this.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,8 +63,6 @@ export default class EmptyTypeWidget extends TypeWidget {
|
|||||||
appContext.tabManager.getActiveContext().setNote(suggestion.notePath);
|
appContext.tabManager.getActiveContext().setNote(suggestion.notePath);
|
||||||
});
|
});
|
||||||
|
|
||||||
noteAutocompleteService.showRecentNotes(this.$autoComplete);
|
|
||||||
|
|
||||||
this.$workspaceNotes = this.$widget.find('.workspace-notes');
|
this.$workspaceNotes = this.$widget.find('.workspace-notes');
|
||||||
|
|
||||||
super.doRender();
|
super.doRender();
|
||||||
@ -85,10 +83,8 @@ export default class EmptyTypeWidget extends TypeWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (workspaceNotes.length === 0) {
|
|
||||||
this.$autoComplete
|
this.$autoComplete
|
||||||
.trigger('focus')
|
.trigger('focus')
|
||||||
.trigger('select');
|
.trigger('select');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -53,11 +53,12 @@ const TPL = `
|
|||||||
padding: 5px;
|
padding: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 5px;
|
border-radius: var(--button-border-radius);
|
||||||
|
color: var(--button-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-text-note-button:hover {
|
.edit-text-note-button:hover {
|
||||||
border-color: var(--main-border-color);
|
border-color: var(--button-border-color);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
BIN
src/public/fonts/Montserrat-Regular.ttf
Normal file
BIN
src/public/fonts/Montserrat-Regular.ttf
Normal file
Binary file not shown.
@ -4,8 +4,8 @@
|
|||||||
"theme_color": "DarkGray",
|
"theme_color": "DarkGray",
|
||||||
"background_color": "DarkGray",
|
"background_color": "DarkGray",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"scope": "/",
|
"scope": "./",
|
||||||
"start_url": "/",
|
"start_url": "./",
|
||||||
"icons": [{
|
"icons": [{
|
||||||
"src": "images/app-icons/ios/apple-touch-icon.png",
|
"src": "images/app-icons/ios/apple-touch-icon.png",
|
||||||
"sizes": "180x180",
|
"sizes": "180x180",
|
||||||
|
@ -1,6 +1,13 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: MontserratLight;
|
font-family: Montserrat;
|
||||||
src: url(../fonts/Montserrat-Light.ttf);
|
src: url(../fonts/Montserrat-Light.ttf);
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Montserrat;
|
||||||
|
src: url(../fonts/Montserrat-Regular.ttf);
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@ -102,7 +109,6 @@ button.close:hover {
|
|||||||
|
|
||||||
.icon-action {
|
.icon-action {
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: 3px;
|
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
width: 35px;
|
width: 35px;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
@ -110,6 +116,7 @@ button.close:hover {
|
|||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
color: var(--button-text-color);
|
color: var(--button-text-color);
|
||||||
background: var(--button-background-color);
|
background: var(--button-background-color);
|
||||||
|
border-radius: var(--button-border-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-action:hover:not(.disabled) {
|
.icon-action:hover:not(.disabled) {
|
||||||
@ -740,7 +747,7 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-submenu {
|
.dropdown-submenu {
|
||||||
position:relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-submenu > .dropdown-menu {
|
.dropdown-submenu > .dropdown-menu {
|
||||||
@ -748,6 +755,9 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
|
|||||||
left: 100%;
|
left: 100%;
|
||||||
margin-top: -6px;
|
margin-top: -6px;
|
||||||
min-width: 15rem;
|
min-width: 15rem;
|
||||||
|
/* to make submenu scrollable https://github.com/zadam/trilium/issues/3136 */
|
||||||
|
max-height: 600px;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rotate caret on hover */
|
/* rotate caret on hover */
|
||||||
@ -947,3 +957,13 @@ button.close:hover {
|
|||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
color: currentColor;
|
color: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden-no-content {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reference-link .bx {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
margin-right: 3px;
|
||||||
|
}
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
:root {
|
:root {
|
||||||
--theme-style: dark;
|
--theme-style: dark;
|
||||||
|
|
||||||
--main-font-family: MontserratLight;
|
--main-font-family: Montserrat;
|
||||||
--main-font-size: normal;
|
--main-font-size: normal;
|
||||||
|
|
||||||
--tree-font-family: MontserratLight;
|
--tree-font-family: Montserrat;
|
||||||
--tree-font-size: normal;
|
--tree-font-size: normal;
|
||||||
|
|
||||||
--detail-font-family: MontserratLight;
|
--detail-font-family: Montserrat;
|
||||||
--detail-font-size: normal;
|
--detail-font-size: normal;
|
||||||
|
|
||||||
--monospace-font-family: JetBrainsLight;
|
--monospace-font-family: JetBrainsLight;
|
||||||
|
@ -5,13 +5,13 @@ html {
|
|||||||
/* either light or dark, colored theme with darker tones are also dark, used e.g. for note map node colors */
|
/* either light or dark, colored theme with darker tones are also dark, used e.g. for note map node colors */
|
||||||
--theme-style: light;
|
--theme-style: light;
|
||||||
|
|
||||||
--main-font-family: MontserratLight;
|
--main-font-family: Montserrat;
|
||||||
--main-font-size: normal;
|
--main-font-size: normal;
|
||||||
|
|
||||||
--tree-font-family: MontserratLight;
|
--tree-font-family: Montserrat;
|
||||||
--tree-font-size: normal;
|
--tree-font-size: normal;
|
||||||
|
|
||||||
--detail-font-family: MontserratLight;
|
--detail-font-family: Montserrat;
|
||||||
--detail-font-size: normal;
|
--detail-font-size: normal;
|
||||||
|
|
||||||
--monospace-font-family: JetBrainsLight;
|
--monospace-font-family: JetBrainsLight;
|
||||||
|
@ -194,10 +194,15 @@ function deleteBranch(req) {
|
|||||||
const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes');
|
const taskContext = TaskContext.getInstance(req.query.taskId, 'delete-notes');
|
||||||
|
|
||||||
const deleteId = utils.randomString(10);
|
const deleteId = utils.randomString(10);
|
||||||
const noteDeleted = branch.deleteBranch(deleteId, taskContext);
|
let noteDeleted;
|
||||||
|
|
||||||
if (eraseNotes) {
|
if (eraseNotes) {
|
||||||
|
// erase automatically means deleting all clones + note itself
|
||||||
|
branch.getNote().deleteNote(deleteId, taskContext);
|
||||||
noteService.eraseNotesWithDeleteId(deleteId);
|
noteService.eraseNotesWithDeleteId(deleteId);
|
||||||
|
noteDeleted = true;
|
||||||
|
} else {
|
||||||
|
noteDeleted = branch.deleteBranch(deleteId, taskContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last) {
|
if (last) {
|
||||||
|
@ -48,7 +48,7 @@ function getNeighbors(note, depth) {
|
|||||||
|
|
||||||
const targetNote = relation.getTargetNote();
|
const targetNote = relation.getTargetNote();
|
||||||
|
|
||||||
if (targetNote.hasLabel('excludeFromNoteMap')) {
|
if (!targetNote || targetNote.hasLabel('excludeFromNoteMap')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ function getNeighbors(note, depth) {
|
|||||||
|
|
||||||
const sourceNote = relation.getNote();
|
const sourceNote = relation.getNote();
|
||||||
|
|
||||||
if (sourceNote.hasLabel('excludeFromNoteMap')) {
|
if (!sourceNote || sourceNote.hasLabel('excludeFromNoteMap')) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,7 +299,7 @@ function getBacklinks(req) {
|
|||||||
|
|
||||||
let backlinksWithExcerptCount = 0;
|
let backlinksWithExcerptCount = 0;
|
||||||
|
|
||||||
return backlinks.map(backlink => {
|
return backlinks.filter(note => !note.getNote().hasLabel('excludeFromNoteMap')).map(backlink => {
|
||||||
const sourceNote = backlink.note;
|
const sourceNote = backlink.note;
|
||||||
|
|
||||||
if (sourceNote.type !== 'text' || backlinksWithExcerptCount > 50) {
|
if (sourceNote.type !== 'text' || backlinksWithExcerptCount > 50) {
|
||||||
|
@ -181,6 +181,7 @@ function getRelationMap(req) {
|
|||||||
|
|
||||||
if (def.inverseRelation) {
|
if (def.inverseRelation) {
|
||||||
resp.inverseRelations[relationDefinition.getDefinedName()] = def.inverseRelation;
|
resp.inverseRelations[relationDefinition.getDefinedName()] = def.inverseRelation;
|
||||||
|
resp.inverseRelations[def.inverseRelation] = relationDefinition.getDefinedName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,7 +315,7 @@ function getBacklinkCount(req) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return {
|
return {
|
||||||
count: note.getTargetRelations().length
|
count: note.getTargetRelations().filter(note => !note.getNote().hasLabel('excludeFromNoteMap')).length
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ const log = require('../../services/log');
|
|||||||
const scriptService = require('../../services/script');
|
const scriptService = require('../../services/script');
|
||||||
const searchService = require('../../services/search/services/search');
|
const searchService = require('../../services/search/services/search');
|
||||||
const bulkActionService = require("../../services/bulk_actions");
|
const bulkActionService = require("../../services/bulk_actions");
|
||||||
|
const cls = require("../../services/cls");
|
||||||
const {formatAttrForSearch} = require("../../services/attribute_formatter");
|
const {formatAttrForSearch} = require("../../services/attribute_formatter");
|
||||||
|
|
||||||
function searchFromNoteInt(note) {
|
function searchFromNoteInt(note) {
|
||||||
@ -189,7 +190,9 @@ function getRelatedNotes(req) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function searchTemplates() {
|
function searchTemplates() {
|
||||||
const query = formatAttrForSearch({type: 'label', name: "template"}, false);
|
const query = cls.getHoistedNoteId() === 'root'
|
||||||
|
? '#template'
|
||||||
|
: '#template OR #workspaceTemplate';
|
||||||
|
|
||||||
return searchService.searchNotes(query, {
|
return searchService.searchNotes(query, {
|
||||||
includeArchivedNotes: true,
|
includeArchivedNotes: true,
|
||||||
|
@ -215,7 +215,7 @@ function update(req) {
|
|||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
for (const key in partialRequests) {
|
for (const key in partialRequests) {
|
||||||
if (Date.now() - partialRequests[key].createdAt > 5 * 60 * 1000) {
|
if (Date.now() - partialRequests[key].createdAt > 20 * 60 * 1000) {
|
||||||
log.info(`Cleaning up unfinished partial requests for ${key}`);
|
log.info(`Cleaning up unfinished partial requests for ${key}`);
|
||||||
|
|
||||||
delete partialRequests[key];
|
delete partialRequests[key];
|
||||||
|
@ -10,7 +10,7 @@ function getNotesAndBranchesAndAttributes(noteIds) {
|
|||||||
const collectedBranchIds = new Set();
|
const collectedBranchIds = new Set();
|
||||||
|
|
||||||
function collectEntityIds(note) {
|
function collectEntityIds(note) {
|
||||||
if (collectedNoteIds.has(note.noteId)) {
|
if (!note || collectedNoteIds.has(note.noteId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,6 +97,11 @@ function getNotesAndBranchesAndAttributes(noteIds) {
|
|||||||
for (const attributeId of collectedAttributeIds) {
|
for (const attributeId of collectedAttributeIds) {
|
||||||
const attribute = becca.attributes[attributeId];
|
const attribute = becca.attributes[attributeId];
|
||||||
|
|
||||||
|
if (!attribute) {
|
||||||
|
log.error(`Could not find attribute for attributeId=${attributeId}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
attributes.push({
|
attributes.push({
|
||||||
attributeId: attribute.attributeId,
|
attributeId: attribute.attributeId,
|
||||||
noteId: attribute.noteId,
|
noteId: attribute.noteId,
|
||||||
|
@ -4,7 +4,7 @@ const setupRoute = require('./setup');
|
|||||||
const loginRoute = require('./login');
|
const loginRoute = require('./login');
|
||||||
const indexRoute = require('./index');
|
const indexRoute = require('./index');
|
||||||
const utils = require('../services/utils');
|
const utils = require('../services/utils');
|
||||||
const multer = require('multer')();
|
const multer = require('multer');
|
||||||
|
|
||||||
// API routes
|
// API routes
|
||||||
const treeApiRoute = require('./api/tree');
|
const treeApiRoute = require('./api/tree');
|
||||||
@ -194,8 +194,33 @@ function route(method, path, middleware, routeHandler, resultHandler, transactio
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_ALLOWED_FILE_SIZE_MB = 250;
|
||||||
|
|
||||||
const GET = 'get', POST = 'post', PUT = 'put', PATCH = 'patch', DELETE = 'delete';
|
const GET = 'get', POST = 'post', PUT = 'put', PATCH = 'patch', DELETE = 'delete';
|
||||||
const uploadMiddleware = multer.single('upload');
|
const uploadMiddleware = multer({
|
||||||
|
fileFilter: (req, file, cb) => {
|
||||||
|
// UTF-8 file names are not well decoded by multer/busboy, so we handle the conversion on our side.
|
||||||
|
// See https://github.com/expressjs/multer/pull/1102.
|
||||||
|
file.originalname = Buffer.from(file.originalname, "latin1").toString("utf-8");
|
||||||
|
cb(null, true);
|
||||||
|
},
|
||||||
|
limits: {
|
||||||
|
fileSize: MAX_ALLOWED_FILE_SIZE_MB * 1024 * 1024
|
||||||
|
}
|
||||||
|
}).single('upload');
|
||||||
|
|
||||||
|
const uploadMiddlewareWithErrorHandling = function (req, res, next) {
|
||||||
|
uploadMiddleware(req, res, function (err) {
|
||||||
|
if (err?.code === 'LIMIT_FILE_SIZE') {
|
||||||
|
res.setHeader("Content-Type", "text/plain")
|
||||||
|
.status(400)
|
||||||
|
.send(`Cannot upload file because it excceeded max allowed file size of ${MAX_ALLOWED_FILE_SIZE_MB} MiB`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
function register(app) {
|
function register(app) {
|
||||||
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
route(GET, '/', [auth.checkAuth, csrfMiddleware], indexRoute.index);
|
||||||
@ -253,9 +278,9 @@ function register(app) {
|
|||||||
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
|
apiRoute(PUT, '/api/notes/:noteId/clone-after/:afterBranchId', cloningApiRoute.cloneNoteAfter);
|
||||||
|
|
||||||
route(GET, '/api/notes/:branchId/export/:type/:format/:version/:taskId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch);
|
route(GET, '/api/notes/:branchId/export/:type/:format/:version/:taskId', [auth.checkApiAuthOrElectron], exportRoute.exportBranch);
|
||||||
route(POST, '/api/notes/:parentNoteId/import', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], importRoute.importToBranch, apiResultHandler);
|
route(POST, '/api/notes/:parentNoteId/import', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], importRoute.importToBranch, apiResultHandler);
|
||||||
|
|
||||||
route(PUT, '/api/notes/:noteId/file', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware],
|
route(PUT, '/api/notes/:noteId/file', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware],
|
||||||
filesRoute.updateFile, apiResultHandler);
|
filesRoute.updateFile, apiResultHandler);
|
||||||
|
|
||||||
route(GET, '/api/notes/:noteId/open', [auth.checkApiAuthOrElectron], filesRoute.openFile);
|
route(GET, '/api/notes/:noteId/open', [auth.checkApiAuthOrElectron], filesRoute.openFile);
|
||||||
@ -295,10 +320,10 @@ function register(app) {
|
|||||||
apiRoute(POST, '/api/special-notes/save-search-note', specialNotesRoute.saveSearchNote);
|
apiRoute(POST, '/api/special-notes/save-search-note', specialNotesRoute.saveSearchNote);
|
||||||
apiRoute(POST, '/api/special-notes/shortcuts/:parentNoteId/:type', specialNotesRoute.createShortcut);
|
apiRoute(POST, '/api/special-notes/shortcuts/:parentNoteId/:type', specialNotesRoute.createShortcut);
|
||||||
|
|
||||||
// :filename is not used by trilium, but instead used for "save as" to assign a human readable filename
|
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
|
||||||
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
route(GET, '/api/images/:noteId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
|
||||||
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
|
route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], imageRoute.uploadImage, apiResultHandler);
|
||||||
route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddleware, csrfMiddleware], imageRoute.updateImage, apiResultHandler);
|
route(PUT, '/api/images/:noteId', [auth.checkApiAuthOrElectron, uploadMiddlewareWithErrorHandling, csrfMiddleware], imageRoute.updateImage, apiResultHandler);
|
||||||
|
|
||||||
apiRoute(GET, '/api/recent-changes/:ancestorNoteId', recentChangesApiRoute.getRecentChanges);
|
apiRoute(GET, '/api/recent-changes/:ancestorNoteId', recentChangesApiRoute.getRecentChanges);
|
||||||
|
|
||||||
@ -360,7 +385,7 @@ function register(app) {
|
|||||||
|
|
||||||
// no CSRF since this is called from android app
|
// no CSRF since this is called from android app
|
||||||
route(POST, '/api/sender/login', [], loginApiRoute.token, apiResultHandler);
|
route(POST, '/api/sender/login', [], loginApiRoute.token, apiResultHandler);
|
||||||
route(POST, '/api/sender/image', [auth.checkEtapiToken, uploadMiddleware], senderRoute.uploadImage, apiResultHandler);
|
route(POST, '/api/sender/image', [auth.checkEtapiToken, uploadMiddlewareWithErrorHandling], senderRoute.uploadImage, apiResultHandler);
|
||||||
route(POST, '/api/sender/note', [auth.checkEtapiToken], senderRoute.saveNote, apiResultHandler);
|
route(POST, '/api/sender/note', [auth.checkEtapiToken], senderRoute.saveNote, apiResultHandler);
|
||||||
|
|
||||||
apiRoute(GET, '/api/quick-search/:searchString', searchRoute.quickSearch);
|
apiRoute(GET, '/api/quick-search/:searchString', searchRoute.quickSearch);
|
||||||
@ -410,7 +435,7 @@ function register(app) {
|
|||||||
|
|
||||||
shareRoutes.register(router);
|
shareRoutes.register(router);
|
||||||
|
|
||||||
etapiAuthRoutes.register(router);
|
etapiAuthRoutes.register(router, [loginRateLimiter]);
|
||||||
etapiAppInfoRoutes.register(router);
|
etapiAppInfoRoutes.register(router);
|
||||||
etapiAttributeRoutes.register(router);
|
etapiAttributeRoutes.register(router);
|
||||||
etapiBranchRoutes.register(router);
|
etapiBranchRoutes.register(router);
|
||||||
|
@ -14,6 +14,8 @@ const appInfo = require('./app_info');
|
|||||||
const searchService = require('./search/services/search');
|
const searchService = require('./search/services/search');
|
||||||
const SearchContext = require("./search/search_context");
|
const SearchContext = require("./search/search_context");
|
||||||
const becca = require("../becca/becca");
|
const becca = require("../becca/becca");
|
||||||
|
const ws = require("./ws");
|
||||||
|
const SpacedUpdate = require("./spaced_update");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the main backend API interface for scripts. It's published in the local "api" object.
|
* This is the main backend API interface for scripts. It's published in the local "api" object.
|
||||||
@ -288,12 +290,34 @@ function BackendScriptApi(currentNote, apiParams) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.logMessages = {};
|
||||||
|
this.logSpacedUpdates = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log given message to trilium logs.
|
* Log given message to trilium logs and log pane in UI
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
*/
|
*/
|
||||||
this.log = message => log.info(message);
|
this.log = message => {
|
||||||
|
log.info(message);
|
||||||
|
|
||||||
|
const {noteId} = this.startNote;
|
||||||
|
|
||||||
|
this.logMessages[noteId] = this.logMessages[noteId] || [];
|
||||||
|
this.logSpacedUpdates[noteId] = this.logSpacedUpdates[noteId] || new SpacedUpdate(() => {
|
||||||
|
const messages = this.logMessages[noteId];
|
||||||
|
this.logMessages[noteId] = [];
|
||||||
|
|
||||||
|
ws.sendMessageToAllClients({
|
||||||
|
type: 'api-log-messages',
|
||||||
|
noteId,
|
||||||
|
messages
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
this.logMessages[noteId].push(message);
|
||||||
|
this.logSpacedUpdates[noteId].scheduleUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns root note of the calendar.
|
* Returns root note of the calendar.
|
||||||
|
@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2022-08-07T23:20:59+02:00", buildRevision: "3a07c5fcc059019a2330a3f6ed204eeb5df1539d" };
|
module.exports = { buildDate:"2022-09-21T22:43:34+02:00", buildRevision: "180051d252d254a2543f8192a28e87e134594a38" };
|
||||||
|
@ -30,6 +30,7 @@ module.exports = [
|
|||||||
{ type: 'label', name: 'workspaceIconClass' },
|
{ type: 'label', name: 'workspaceIconClass' },
|
||||||
{ type: 'label', name: 'workspaceTabBackgroundColor' },
|
{ type: 'label', name: 'workspaceTabBackgroundColor' },
|
||||||
{ type: 'label', name: 'workspaceCalendarRoot' },
|
{ type: 'label', name: 'workspaceCalendarRoot' },
|
||||||
|
{ type: 'label', name: 'workspaceTemplate' },
|
||||||
{ type: 'label', name: 'searchHome' },
|
{ type: 'label', name: 'searchHome' },
|
||||||
{ type: 'label', name: 'hoistedInbox' },
|
{ type: 'label', name: 'hoistedInbox' },
|
||||||
{ type: 'label', name: 'hoistedSearchHome' },
|
{ type: 'label', name: 'hoistedSearchHome' },
|
||||||
@ -49,6 +50,7 @@ module.exports = [
|
|||||||
{ type: 'label', name: 'shareAlias' },
|
{ type: 'label', name: 'shareAlias' },
|
||||||
{ type: 'label', name: 'shareOmitDefaultCss' },
|
{ type: 'label', name: 'shareOmitDefaultCss' },
|
||||||
{ type: 'label', name: 'shareRoot' },
|
{ type: 'label', name: 'shareRoot' },
|
||||||
|
{ type: 'label', name: 'shareDescription' },
|
||||||
{ type: 'label', name: 'shareRaw' },
|
{ type: 'label', name: 'shareRaw' },
|
||||||
{ type: 'label', name: 'shareDisallowRobotIndexing' },
|
{ type: 'label', name: 'shareDisallowRobotIndexing' },
|
||||||
{ type: 'label', name: 'shareCredentials' },
|
{ type: 'label', name: 'shareCredentials' },
|
||||||
@ -57,6 +59,7 @@ module.exports = [
|
|||||||
{ type: 'label', name: 'titleTemplate', isDangerous: true },
|
{ type: 'label', name: 'titleTemplate', isDangerous: true },
|
||||||
{ type: 'label', name: 'template' },
|
{ type: 'label', name: 'template' },
|
||||||
{ type: 'label', name: 'toc' },
|
{ type: 'label', name: 'toc' },
|
||||||
|
{ type: 'label', name: 'color' },
|
||||||
|
|
||||||
// relation names
|
// relation names
|
||||||
{ type: 'relation', name: 'internalLink' },
|
{ type: 'relation', name: 'internalLink' },
|
||||||
|
@ -8,14 +8,12 @@ const resourceDir = require('./resource_dir');
|
|||||||
|
|
||||||
const configSampleFilePath = path.resolve(resourceDir.RESOURCE_DIR, "config-sample.ini");
|
const configSampleFilePath = path.resolve(resourceDir.RESOURCE_DIR, "config-sample.ini");
|
||||||
|
|
||||||
const configFilePath = dataDir.TRILIUM_DATA_DIR + '/config.ini';
|
if (!fs.existsSync(dataDir.CONFIG_INI_PATH)) {
|
||||||
|
|
||||||
if (!fs.existsSync(configFilePath)) {
|
|
||||||
const configSample = fs.readFileSync(configSampleFilePath).toString('utf8');
|
const configSample = fs.readFileSync(configSampleFilePath).toString('utf8');
|
||||||
|
|
||||||
fs.writeFileSync(configFilePath, configSample);
|
fs.writeFileSync(dataDir.CONFIG_INI_PATH, configSample);
|
||||||
}
|
}
|
||||||
|
|
||||||
const config = ini.parse(fs.readFileSync(configFilePath, 'utf-8'));
|
const config = ini.parse(fs.readFileSync(dataDir.CONFIG_INI_PATH, 'utf-8'));
|
||||||
|
|
||||||
module.exports = config;
|
module.exports = config;
|
@ -64,11 +64,13 @@ const DOCUMENT_PATH = TRILIUM_DATA_DIR + path.sep + "document.db";
|
|||||||
const BACKUP_DIR = TRILIUM_DATA_DIR + path.sep + "backup";
|
const BACKUP_DIR = TRILIUM_DATA_DIR + path.sep + "backup";
|
||||||
const LOG_DIR = TRILIUM_DATA_DIR + path.sep + "log";
|
const LOG_DIR = TRILIUM_DATA_DIR + path.sep + "log";
|
||||||
const ANONYMIZED_DB_DIR = TRILIUM_DATA_DIR + path.sep + "anonymized-db";
|
const ANONYMIZED_DB_DIR = TRILIUM_DATA_DIR + path.sep + "anonymized-db";
|
||||||
|
const CONFIG_INI_PATH = TRILIUM_DATA_DIR + '/config.ini';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
TRILIUM_DATA_DIR,
|
TRILIUM_DATA_DIR,
|
||||||
DOCUMENT_PATH,
|
DOCUMENT_PATH,
|
||||||
BACKUP_DIR,
|
BACKUP_DIR,
|
||||||
LOG_DIR,
|
LOG_DIR,
|
||||||
ANONYMIZED_DB_DIR
|
ANONYMIZED_DB_DIR,
|
||||||
|
CONFIG_INI_PATH
|
||||||
};
|
};
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user