mirror of
https://github.com/zadam/trilium.git
synced 2025-11-02 19:36:12 +01:00
Compare commits
43 Commits
v0.35.2
...
v0.36.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fda219d070 | ||
|
|
2be1aca2f3 | ||
|
|
1b318d6a30 | ||
|
|
22c4859d42 | ||
|
|
80a6361cf1 | ||
|
|
8439effeeb | ||
|
|
fafab95a07 | ||
|
|
24c8e8fc2b | ||
|
|
1923bf7dda | ||
|
|
2ee94a3a69 | ||
|
|
2fb3a3eff9 | ||
|
|
bcbbf4dc3e | ||
|
|
7dc793920f | ||
|
|
0b43eceb2d | ||
|
|
85f736139b | ||
|
|
98a6670cb4 | ||
|
|
c9432990b7 | ||
|
|
9ad521822d | ||
|
|
824fb08511 | ||
|
|
cc4c15daf0 | ||
|
|
7718778013 | ||
|
|
a25260353d | ||
|
|
c1e8a4b384 | ||
|
|
3f2229d9e1 | ||
|
|
8561227622 | ||
|
|
8859e2ac40 | ||
|
|
7423b2f4fd | ||
|
|
d23e9f1bc4 | ||
|
|
516277a478 | ||
|
|
cbc7710d81 | ||
|
|
ea71e96f72 | ||
|
|
59d1cb1833 | ||
|
|
7c54ba63ce | ||
|
|
5892b5b851 | ||
|
|
02eb737b9d | ||
|
|
144e75da9e | ||
|
|
8d14a0d687 | ||
|
|
dec2c218f7 | ||
|
|
dd147a7209 | ||
|
|
c3fabcb666 | ||
|
|
35e825b376 | ||
|
|
334a38c493 | ||
|
|
8ec01c73cd |
15
.gitpod.dockerfile
Normal file
15
.gitpod.dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
FROM gitpod/workspace-full
|
||||
|
||||
RUN sudo apt-get update \
|
||||
&& sudo apt-get install -yq --no-install-recommends \
|
||||
libpng16-16 \
|
||||
libpng-dev \
|
||||
pkg-config \
|
||||
autoconf \
|
||||
libtool \
|
||||
build-essential \
|
||||
nasm \
|
||||
libx11-dev \
|
||||
libxkbfile-dev \
|
||||
&& sudo rm -rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
image:
|
||||
file: .gitpod.dockerfile
|
||||
|
||||
tasks:
|
||||
- before: nvm install 10 && nvm use 10
|
||||
init: npm install
|
||||
command: npm run start
|
||||
command: npm run start-server
|
||||
|
||||
ports:
|
||||
- port: 8080
|
||||
onOpen: open-preview
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM node:12.10.0-alpine
|
||||
FROM node:12.12.0-alpine
|
||||
|
||||
# Create app directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
@@ -46,5 +46,5 @@ Use a browser based dev environment
|
||||
Or clone locally and run
|
||||
```
|
||||
npm install
|
||||
npm run start
|
||||
npm run start-server
|
||||
```
|
||||
@@ -1,20 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUILD_DIR=./dist/trilium-linux-x64
|
||||
rm -rf $BUILD_DIR
|
||||
SRC_DIR=./dist/trilium-linux-x64-src
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
./bin/copy-trilium.sh $SRC_DIR
|
||||
fi
|
||||
|
||||
echo "Copying required linux-x64 binaries"
|
||||
|
||||
rm -r node_modules/sqlite3/lib/binding/*
|
||||
rm -r node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
|
||||
cp -r bin/deps/linux-x64/sqlite/* node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/linux-x64/image/pngquant node_modules/pngquant-bin/vendor/
|
||||
cp -r bin/deps/linux-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/linux-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/linux-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
|
||||
# rebuild binaries for image operations (pngquant ...)
|
||||
npm rebuild
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
|
||||
|
||||
./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=linux --arch=x64 --overwrite
|
||||
BUILD_DIR=./dist/trilium-linux-x64
|
||||
rm -rf $BUILD_DIR
|
||||
|
||||
mv "./dist/Trilium Notes-linux-x64" $BUILD_DIR
|
||||
|
||||
@@ -29,3 +35,7 @@ VERSION=`jq -r ".version" package.json`
|
||||
cd dist
|
||||
|
||||
tar cJf trilium-linux-x64-${VERSION}.tar.xz trilium-linux-x64
|
||||
|
||||
cd ..
|
||||
|
||||
bin/build-debian.sh
|
||||
@@ -1,27 +1,36 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SRC_DIR=./dist/trilium-mac-x64-src
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
./bin/copy-trilium.sh $SRC_DIR
|
||||
fi
|
||||
|
||||
echo "Copying required mac binaries"
|
||||
|
||||
rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/mozjpeg/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/keyboard-layout/build/Release/*
|
||||
|
||||
cp -r bin/deps/mac-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/mac-x64/image/cjpeg $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/mac-x64/image/pngquant $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/mac-x64/image/gifsicle $SRC_DIR/node_modules/giflossy/vendor/
|
||||
cp bin/deps/mac-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
cp bin/deps/mac-x64/keyboard-layout-manager.node $SRC_DIR/node_modules/keyboard-layout/build/Release/
|
||||
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
|
||||
|
||||
BUILD_DIR=./dist/trilium-mac-x64
|
||||
rm -rf $BUILD_DIR
|
||||
|
||||
echo "Copying required mac binaries"
|
||||
|
||||
rm -r node_modules/sqlite3/lib/binding/*
|
||||
rm -r node_modules/mozjpeg/vendor/*
|
||||
rm -r node_modules/pngquant-bin/vendor/*
|
||||
rm -r node_modules/giflossy/vendor/*
|
||||
|
||||
cp -r bin/deps/mac-x64/sqlite/* node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/mac-x64/image/cjpeg node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/mac-x64/image/pngquant node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/mac-x64/image/gifsicle node_modules/giflossy/vendor/
|
||||
|
||||
./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=darwin --arch=x64 --overwrite --icon=images/app-icons/mac/icon.icns
|
||||
|
||||
# Mac build has by default useless directory level
|
||||
mv "./dist/Trilium Notes-darwin-x64" $BUILD_DIR
|
||||
|
||||
./bin/reset-local.sh
|
||||
|
||||
echo "Zipping mac x64 electron distribution..."
|
||||
|
||||
VERSION=`jq -r ".version" package.json`
|
||||
|
||||
@@ -1,40 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=12.10.0
|
||||
NODE_VERSION=12.12.0
|
||||
|
||||
rm -r $PKG_DIR
|
||||
mkdir $PKG_DIR
|
||||
cd $PKG_DIR
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
./bin/copy-trilium.sh $PKG_DIR
|
||||
fi
|
||||
|
||||
cd dist
|
||||
wget https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
tar xvfJ node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
rm node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
|
||||
mv node-v${NODE_VERSION}-linux-x64 node
|
||||
|
||||
cp -r ../../node_modules/ ./
|
||||
cp -r ../../images/ ./
|
||||
cp -r ../../libraries/ ./
|
||||
cp -r ../../src/ ./
|
||||
cp -r ../../db/ ./
|
||||
cp -r ../../package.json ./
|
||||
cp -r ../../package-lock.json ./
|
||||
cp -r ../../README.md ./
|
||||
cp -r ../../LICENSE ./
|
||||
cp -r ../../config-sample.ini ./
|
||||
|
||||
rm -r ./node_modules/electron*
|
||||
|
||||
rm -r ./node_modules/sqlite3/lib/binding/*
|
||||
|
||||
cp -r ../../bin/deps/linux-x64/sqlite/node* ./node_modules/sqlite3/lib/binding/
|
||||
|
||||
printf "#!/bin/sh\n./node/bin/node src/www" > trilium.sh
|
||||
chmod 755 trilium.sh
|
||||
|
||||
cd ..
|
||||
|
||||
VERSION=`jq -r ".version" ../package.json`
|
||||
mv dist/node-v${NODE_VERSION}-linux-x64 $PKG_DIR/node
|
||||
|
||||
rm -r $PKG_DIR/node_modules/electron*
|
||||
|
||||
rm -r $PKG_DIR/node_modules/sqlite3/lib/binding/*
|
||||
|
||||
cp -r ./bin/deps/linux-x64/sqlite/node* $PKG_DIR/node_modules/sqlite3/lib/binding/
|
||||
|
||||
printf "#!/bin/sh\n./node/bin/node src/www" > $PKG_DIR/trilium.sh
|
||||
chmod 755 $PKG_DIR/trilium.sh
|
||||
|
||||
VERSION=`jq -r ".version" package.json`
|
||||
|
||||
cd dist
|
||||
|
||||
tar cJf trilium-linux-x64-server-${VERSION}.tar.xz trilium-linux-x64-server
|
||||
|
||||
@@ -1,29 +1,38 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BUILD_DIR=./dist/trilium-windows-x64
|
||||
rm -rf $BUILD_DIR
|
||||
SRC_DIR=./dist/trilium-windows-x64-src
|
||||
|
||||
if [ "$1" != "DONTCOPY" ]
|
||||
then
|
||||
./bin/copy-trilium.sh $SRC_DIR
|
||||
fi
|
||||
|
||||
echo "Copying required windows binaries"
|
||||
|
||||
rm -r node_modules/sqlite3/lib/binding/*
|
||||
rm -r node_modules/mozjpeg/vendor/*
|
||||
rm -r node_modules/pngquant-bin/vendor/*
|
||||
rm -r node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/sqlite3/lib/binding/*
|
||||
rm -r $SRC_DIR/node_modules/mozjpeg/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/pngquant-bin/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/giflossy/vendor/*
|
||||
rm -r $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/*
|
||||
rm -r $SRC_DIR/node_modules/keyboard-layout/build/Release/*
|
||||
|
||||
cp -r bin/deps/win-x64/sqlite/* node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/win-x64/image/cjpeg.exe node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/win-x64/image/pngquant.exe node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/win-x64/image/gifsicle.exe node_modules/giflossy/vendor/
|
||||
cp -r bin/deps/win-x64/sqlite/* $SRC_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/win-x64/image/cjpeg.exe $SRC_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/win-x64/image/pngquant.exe $SRC_DIR/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/win-x64/image/gifsicle.exe $SRC_DIR/node_modules/giflossy/vendor/
|
||||
cp bin/deps/win-x64/spellchecker/* $SRC_DIR/node_modules/@felixrieseberg/spellchecker/build/Release/
|
||||
cp bin/deps/win-x64/keyboard-layout-manager.node $SRC_DIR/node_modules/keyboard-layout/build/Release/
|
||||
|
||||
./node_modules/.bin/electron-packager . --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico
|
||||
./node_modules/.bin/electron-packager $SRC_DIR --asar --out=dist --executable-name=trilium --platform=win32 --arch=x64 --overwrite --icon=images/app-icons/win/icon.ico
|
||||
|
||||
BUILD_DIR=./dist/trilium-windows-x64
|
||||
rm -rf $BUILD_DIR
|
||||
|
||||
mv "./dist/Trilium Notes-win32-x64" $BUILD_DIR
|
||||
|
||||
# removing software WebGL binaries because they are pretty huge and not necessary
|
||||
rm -r $BUILD_DIR/swiftshader
|
||||
|
||||
./bin/reset-local.sh
|
||||
|
||||
echo "Zipping windows x64 electron distribution..."
|
||||
VERSION=`jq -r ".version" package.json`
|
||||
|
||||
|
||||
24
bin/build.sh
24
bin/build.sh
@@ -1,21 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
rm -r node_modules
|
||||
|
||||
npm install
|
||||
|
||||
echo "Deleting existing builds"
|
||||
|
||||
rm -r dist/*
|
||||
|
||||
bin/build-win-x64.sh
|
||||
SRC_DIR=dist/trilium-src
|
||||
|
||||
bin/build-mac-x64.sh
|
||||
bin/copy-trilium.sh $SRC_DIR
|
||||
|
||||
# building X64 linux as the last so electron-rebuild will prepare X64 binaries for local development
|
||||
bin/build-linux-x64.sh
|
||||
# we'll just copy the same SRC dir to all the builds so we don't have to do npm install in each separately
|
||||
cp -r $SRC_DIR ./dist/trilium-linux-x64-src
|
||||
cp -r $SRC_DIR ./dist/trilium-linux-x64-server
|
||||
cp -r $SRC_DIR ./dist/trilium-windows-x64-src
|
||||
cp -r $SRC_DIR ./dist/trilium-mac-x64-src
|
||||
|
||||
# this needs to be run after linux build
|
||||
bin/build-debian.sh
|
||||
bin/build-win-x64.sh DONTCOPY
|
||||
|
||||
bin/build-server.sh
|
||||
bin/build-mac-x64.sh DONTCOPY
|
||||
|
||||
bin/build-linux-x64.sh DONTCOPY
|
||||
|
||||
bin/build-server.sh DONTCOPY
|
||||
|
||||
32
bin/copy-trilium.sh
Executable file
32
bin/copy-trilium.sh
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
if [[ $# -eq 0 ]] ; then
|
||||
echo "Missing argument of target directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DIR=$1
|
||||
|
||||
rm -rf $DIR
|
||||
mkdir $DIR
|
||||
|
||||
echo "Copying Trilium to build directory $DIR"
|
||||
|
||||
cp -r images $DIR/
|
||||
cp -r libraries $DIR/
|
||||
cp -r src $DIR/
|
||||
cp -r db $DIR/
|
||||
cp -r package.json $DIR/
|
||||
cp -r package-lock.json $DIR/
|
||||
cp -r README.md $DIR/
|
||||
cp -r LICENSE $DIR/
|
||||
cp -r config-sample.ini $DIR/
|
||||
cp -r electron.js $DIR/
|
||||
|
||||
# run in subshell (so we return to original dir)
|
||||
(cd $DIR && npm install --only=prod)
|
||||
|
||||
rm -r $DIR/node_modules/cld/deps
|
||||
|
||||
find $DIR/libraries -name "*.map" -type f -delete
|
||||
find $DIR/libraries -name "hunspell.lib" -type f -delete
|
||||
BIN
bin/deps/linux-x64/spellchecker/hunspell.a
Normal file
BIN
bin/deps/linux-x64/spellchecker/hunspell.a
Normal file
Binary file not shown.
BIN
bin/deps/linux-x64/spellchecker/spellchecker.node
Normal file
BIN
bin/deps/linux-x64/spellchecker/spellchecker.node
Normal file
Binary file not shown.
BIN
bin/deps/mac-x64/keyboard-layout-manager.node
Normal file
BIN
bin/deps/mac-x64/keyboard-layout-manager.node
Normal file
Binary file not shown.
BIN
bin/deps/mac-x64/spellchecker/hunspell.a
Normal file
BIN
bin/deps/mac-x64/spellchecker/hunspell.a
Normal file
Binary file not shown.
BIN
bin/deps/mac-x64/spellchecker/spellchecker.node
Normal file
BIN
bin/deps/mac-x64/spellchecker/spellchecker.node
Normal file
Binary file not shown.
BIN
bin/deps/win-x64/keyboard-layout-manager.node
Executable file
BIN
bin/deps/win-x64/keyboard-layout-manager.node
Executable file
Binary file not shown.
BIN
bin/deps/win-x64/spellchecker/hunspell.lib
Executable file
BIN
bin/deps/win-x64/spellchecker/hunspell.lib
Executable file
Binary file not shown.
BIN
bin/deps/win-x64/spellchecker/spellchecker.lib
Executable file
BIN
bin/deps/win-x64/spellchecker/spellchecker.lib
Executable file
Binary file not shown.
BIN
bin/deps/win-x64/spellchecker/spellchecker.node
Executable file
BIN
bin/deps/win-x64/spellchecker/spellchecker.node
Executable file
Binary file not shown.
@@ -1,3 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
./node_modules/.bin/electron-rebuild --arch=x64
|
||||
BIN
db/demo.tar
BIN
db/demo.tar
Binary file not shown.
5
db/migrations/0146__add_spell_check_options.sql
Normal file
5
db/migrations/0146__add_spell_check_options.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
INSERT INTO options (name, value, utcDateCreated, utcDateModified, isSynced)
|
||||
VALUES ('spellCheckEnabled', 'true', '2018-07-29T18:31:00.874Z', '2018-07-29T18:31:00.874Z', 0);
|
||||
|
||||
INSERT INTO options (name, value, utcDateCreated, utcDateModified, isSynced)
|
||||
VALUES ('spellCheckLanguageCode', 'en-US', '2018-07-29T18:31:00.874Z', '2018-07-29T18:31:00.874Z', 0);
|
||||
@@ -396,7 +396,7 @@ the backend.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line310">line 310</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line312">line 312</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1533,7 +1533,7 @@ the backend.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line315">line 315</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line317">line 317</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1997,7 +1997,7 @@ the backend.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line239">line 239</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line241">line 241</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2765,7 +2765,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line258">line 258</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line260">line 260</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3418,7 +3418,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line230">line 230</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line232">line 232</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3596,7 +3596,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line249">line 249</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line251">line 251</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3751,7 +3751,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line267">line 267</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line269">line 269</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3901,7 +3901,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line222">line 222</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line224">line 224</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4427,7 +4427,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line287">line 287</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line289">line 289</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4560,7 +4560,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line274">line 274</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line276">line 276</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4935,7 +4935,7 @@ transactional by default.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line300">line 300</a>
|
||||
<a href="services_backend_script_api.js.html">services/backend_script_api.js</a>, <a href="services_backend_script_api.js.html#line302">line 302</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -237,9 +237,11 @@ function BackendScriptApi(currentNote, apiParams) {
|
||||
* @returns {Promise<{note: Note, branch: Branch}>} object contains newly created entities note and branch
|
||||
*/
|
||||
this.createNoteAndRefresh = async function(parentNoteId, title, content, extraOptions) {
|
||||
await noteService.createNote(parentNoteId, title, content, extraOptions);
|
||||
const ret = await noteService.createNote(parentNoteId, title, content, extraOptions);
|
||||
|
||||
ws.refreshTree();
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -343,7 +345,8 @@ function BackendScriptApi(currentNote, apiParams) {
|
||||
this.getAppInfo = () => appInfo
|
||||
}
|
||||
|
||||
module.exports = BackendScriptApi;</code></pre>
|
||||
module.exports = BackendScriptApi;
|
||||
</code></pre>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -131,6 +131,116 @@
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="$container"><span class="type-signature"></span>$container<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h5 class="subsection-title">Properties:</h5>
|
||||
|
||||
|
||||
|
||||
<table class="props">
|
||||
<thead>
|
||||
<tr>
|
||||
|
||||
<th>Name</th>
|
||||
|
||||
|
||||
<th>Type</th>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<th class="last">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr>
|
||||
|
||||
<td class="name"><code>container</code></td>
|
||||
|
||||
|
||||
<td class="type">
|
||||
|
||||
|
||||
<span class="param-type">jQuery</span>
|
||||
|
||||
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<td class="description last">of all the rendered script content</td>
|
||||
</tr>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
|
||||
|
||||
<dl class="details">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line23">line 23</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h4 class="name" id="currentNote"><span class="type-signature"></span>currentNote<span class="type-signature"></span></h4>
|
||||
|
||||
|
||||
@@ -223,7 +333,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line25">line 25</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line28">line 28</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -336,7 +446,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line27">line 27</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line30">line 30</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -442,7 +552,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line36">line 36</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line39">line 39</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -552,7 +662,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line23">line 23</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line26">line 26</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -661,7 +771,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line33">line 33</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line36">line 36</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -790,7 +900,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line61">line 61</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line64">line 64</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -945,7 +1055,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line45">line 45</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line48">line 48</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1100,7 +1210,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line80">line 80</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line83">line 83</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1280,7 +1390,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line269">line 269</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line272">line 272</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1413,7 +1523,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line229">line 229</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line232">line 232</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1519,7 +1629,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line275">line 275</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line278">line 278</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1625,7 +1735,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line281">line 281</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line284">line 284</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1784,7 +1894,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line332">line 332</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line335">line 335</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1891,7 +2001,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line222">line 222</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line225">line 225</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2046,7 +2156,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line341">line 341</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line344">line 344</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2202,7 +2312,7 @@ if some action needs to happen on only one specific instance.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line190">line 190</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line193">line 193</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2403,7 +2513,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line202">line 202</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line205">line 205</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2509,7 +2619,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line323">line 323</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line326">line 326</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2664,7 +2774,7 @@ otherwise (by e.g. createNoteLink())
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line350">line 350</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line353">line 353</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2773,7 +2883,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line296">line 296</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line299">line 299</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2928,7 +3038,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line304">line 304</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line307">line 307</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3061,7 +3171,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line236">line 236</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line239">line 239</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3167,7 +3277,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line315">line 315</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line318">line 318</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3255,7 +3365,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line260">line 260</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line263">line 263</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3406,7 +3516,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line208">line 208</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line211">line 211</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3539,7 +3649,7 @@ note.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line214">line 214</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line217">line 217</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3700,7 +3810,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line130">line 130</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line133">line 133</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3860,7 +3970,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line178">line 178</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line181">line 181</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4016,7 +4126,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line160">line 160</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line163">line 163</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4167,7 +4277,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line310">line 310</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line313">line 313</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4304,7 +4414,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line252">line 252</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line255">line 255</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4441,7 +4551,7 @@ Internally this serializes the anonymous function into string and sends it to ba
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line244">line 244</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line247">line 247</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,10 @@
|
||||
|
||||
<h2><span class="attribs"><span class="type-signature"></span></span>NoteShort<span class="signature">()</span><span class="type-signature"></span></h2>
|
||||
|
||||
<div class="class-description">This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
<div class="class-description">FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
|
||||
Attribute cache should be limited to "transaction".
|
||||
|
||||
This note's representation is used in note tree and is kept in TreeCache.</div>
|
||||
|
||||
|
||||
</header>
|
||||
@@ -93,7 +96,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line13">line 13</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line16">line 16</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -183,7 +186,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line26">line 26</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line29">line 29</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -241,7 +244,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line28">line 28</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line31">line 31</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -299,7 +302,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line20">line 20</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line23">line 23</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -357,7 +360,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line24">line 24</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line27">line 27</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -415,7 +418,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line16">line 16</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line19">line 19</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -473,7 +476,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line18">line 18</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line21">line 21</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -531,7 +534,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line22">line 22</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line25">line 25</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -679,7 +682,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line166">line 166</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>
|
||||
|
||||
|
||||
@@ -846,7 +849,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line106">line 106</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line109">line 109</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1020,7 +1023,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line177">line 177</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line180">line 180</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1126,7 +1129,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line57">line 57</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>
|
||||
|
||||
|
||||
@@ -1228,7 +1231,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line71">line 71</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>
|
||||
|
||||
|
||||
@@ -1330,7 +1333,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line93">line 93</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line96">line 96</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1432,7 +1435,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line98">line 98</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line101">line 101</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1583,7 +1586,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line199">line 199</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line202">line 202</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1750,7 +1753,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line132">line 132</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line135">line 135</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -1917,7 +1920,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line124">line 124</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line127">line 127</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2072,7 +2075,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line214">line 214</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2178,7 +2181,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line83">line 83</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line86">line 86</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2280,7 +2283,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line88">line 88</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line91">line 91</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2431,7 +2434,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line205">line 205</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line208">line 208</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2598,7 +2601,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line148">line 148</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line151">line 151</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2765,7 +2768,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line140">line 140</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line143">line 143</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -2920,7 +2923,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line223">line 223</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>
|
||||
|
||||
|
||||
@@ -3090,7 +3093,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line233">line 233</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line236">line 236</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3241,7 +3244,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line217">line 217</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line220">line 220</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3351,7 +3354,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line257">line 257</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line260">line 260</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3525,7 +3528,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line157">line 157</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line160">line 160</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3631,7 +3634,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line65">line 65</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line68">line 68</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3782,7 +3785,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line187">line 187</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line190">line 190</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -3937,7 +3940,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line193">line 193</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line196">line 196</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4048,7 +4051,7 @@ Cache is note instance scoped.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line248">line 248</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line251">line 251</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
@@ -4132,7 +4135,7 @@ Cache is note instance scoped.
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<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#line32">line 32</a>
|
||||
<a href="entities_note_short.js.html">entities/note_short.js</a>, <a href="entities_note_short.js.html#line35">line 35</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@ const RELATION = 'relation';
|
||||
const RELATION_DEFINITION = 'relation-definition';
|
||||
|
||||
/**
|
||||
* FIXME: rethink how attributes are cached in Note entities since they are long lived inside the cache.
|
||||
* Attribute cache should be limited to "transaction".
|
||||
*
|
||||
* This note's representation is used in note tree and is kept in TreeCache.
|
||||
*/
|
||||
class NoteShort {
|
||||
|
||||
@@ -303,7 +303,7 @@
|
||||
|
||||
<dt class="tag-source">Source:</dt>
|
||||
<dd class="tag-source"><ul class="dummy"><li>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line67">line 67</a>
|
||||
<a href="services_frontend_script_api.js.html">services/frontend_script_api.js</a>, <a href="services_frontend_script_api.js.html#line70">line 70</a>
|
||||
</li></ul></dd>
|
||||
|
||||
|
||||
|
||||
@@ -44,9 +44,12 @@ import StandardWidget from '../widgets/standard_widget.js';
|
||||
* @constructor
|
||||
* @hideconstructor
|
||||
*/
|
||||
function FrontendScriptApi(startNote, currentNote, originEntity = null, tabContext = null) {
|
||||
function FrontendScriptApi(startNote, currentNote, originEntity = null, tabContext = null, $container = null) {
|
||||
const $pluginButtons = $("#plugin-buttons");
|
||||
|
||||
/** @property {jQuery} container of all the rendered script content */
|
||||
this.$container = $container;
|
||||
|
||||
/** @property {object} note where script started executing */
|
||||
this.startNote = startNote;
|
||||
/** @property {object} note where script is currently executing */
|
||||
@@ -322,7 +325,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
|
||||
* @return {boolean} returns true if the original note is still loaded, false if user switched to another
|
||||
*/
|
||||
this.isNoteStillActive = () => {
|
||||
return this.originEntity.noteId === tabContext.noteId;
|
||||
return tabContext.note && this.originEntity.noteId === tabContext.note.noteId;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
46
electron.js
46
electron.js
@@ -1,6 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
const {app, globalShortcut, BrowserWindow} = require('electron');
|
||||
const path = require('path');
|
||||
const log = require('./src/services/log');
|
||||
const sqlInit = require('./src/services/sql_init');
|
||||
@@ -10,10 +10,6 @@ const port = require('./src/services/port');
|
||||
const env = require('./src/services/env');
|
||||
const appIconService = require('./src/services/app_icon');
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
const contextMenu = require('electron-context-menu');
|
||||
|
||||
const app = electron.app;
|
||||
const globalShortcut = electron.globalShortcut;
|
||||
|
||||
// Adds debug features like hotkeys for triggering dev tools and reload
|
||||
require('electron-debug')();
|
||||
@@ -25,25 +21,25 @@ let mainWindow;
|
||||
|
||||
require('electron-dl')({ saveAs: true });
|
||||
|
||||
contextMenu({
|
||||
menu: (actions, params, browserWindow) => [
|
||||
actions.cut(),
|
||||
actions.copy(),
|
||||
actions.copyLink(),
|
||||
actions.paste(),
|
||||
{
|
||||
label: 'Search DuckDuckGo for “{selection}”',
|
||||
// Only show it when right-clicking text
|
||||
visible: params.selectionText.trim().length > 0,
|
||||
click: () => {
|
||||
const {shell} = require('electron');
|
||||
|
||||
shell.openExternal(`https://duckduckgo.com?q=${encodeURIComponent(params.selectionText)}`);
|
||||
}
|
||||
},
|
||||
actions.inspect()
|
||||
]
|
||||
});
|
||||
// contextMenu({
|
||||
// menu: (actions, params, browserWindow) => [
|
||||
// actions.cut(),
|
||||
// actions.copy(),
|
||||
// actions.copyLink(),
|
||||
// actions.paste(),
|
||||
// {
|
||||
// label: 'Search DuckDuckGo for “{selection}”',
|
||||
// // Only show it when right-clicking text
|
||||
// visible: params.selectionText.trim().length > 0,
|
||||
// click: () => {
|
||||
// const {shell} = require('electron');
|
||||
//
|
||||
// shell.openExternal(`https://duckduckgo.com?q=${encodeURIComponent(params.selectionText)}`);
|
||||
// }
|
||||
// },
|
||||
// actions.inspect()
|
||||
// ]
|
||||
// });
|
||||
|
||||
function onClosed() {
|
||||
// Dereference the window
|
||||
@@ -66,7 +62,7 @@ async function createMainWindow() {
|
||||
defaultHeight: 800
|
||||
});
|
||||
|
||||
const win = new electron.BrowserWindow({
|
||||
const win = new BrowserWindow({
|
||||
x: mainWindowState.x,
|
||||
y: mainWindowState.y,
|
||||
width: mainWindowState.width,
|
||||
|
||||
4367
package-lock.json
generated
4367
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.35.2",
|
||||
"version": "0.36.0-beta",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -17,8 +17,7 @@
|
||||
"start-electron": "TRILIUM_ENV=dev electron . --disable-gpu",
|
||||
"build-backend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/entities/*.js src/services/backend_script_api.js",
|
||||
"build-frontend-docs": "./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/javascripts/entities/*.js src/public/javascripts/services/frontend_script_api.js",
|
||||
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs"
|
||||
},
|
||||
"dependencies": {
|
||||
"async-mutex": "0.1.4",
|
||||
@@ -31,20 +30,20 @@
|
||||
"dayjs": "1.8.16",
|
||||
"debug": "4.1.1",
|
||||
"ejs": "2.7.1",
|
||||
"electron-context-menu": "0.15.0",
|
||||
"electron-debug": "3.0.1",
|
||||
"electron-dl": "1.14.0",
|
||||
"electron-find": "1.0.6",
|
||||
"electron-spellchecker": "2.2.0",
|
||||
"electron-window-state": "5.0.3",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.16.2",
|
||||
"express-session": "1.17.0",
|
||||
"file-type": "12.3.0",
|
||||
"fs-extra": "8.1.0",
|
||||
"helmet": "3.21.1",
|
||||
"html": "1.0.0",
|
||||
"html2plaintext": "2.1.2",
|
||||
"http-proxy-agent": "^2.1.0",
|
||||
"https-proxy-agent": "^2.2.2",
|
||||
"http-proxy-agent": "2.1.0",
|
||||
"https-proxy-agent": "3.0.0",
|
||||
"image-type": "4.1.0",
|
||||
"imagemin": "7.0.0",
|
||||
"imagemin-giflossy": "5.1.10",
|
||||
@@ -70,7 +69,7 @@
|
||||
"simple-node-logger": "18.12.23",
|
||||
"sqlite": "3.0.3",
|
||||
"sqlite3": "4.1.0",
|
||||
"string-similarity": "^3.0.0",
|
||||
"string-similarity": "3.0.0",
|
||||
"tar-stream": "2.1.0",
|
||||
"turndown": "5.0.3",
|
||||
"turndown-plugin-gfm": "1.0.2",
|
||||
@@ -85,7 +84,7 @@
|
||||
"electron-installer-debian": "2.0.1",
|
||||
"electron-packager": "14.0.6",
|
||||
"electron-rebuild": "1.8.6",
|
||||
"jsdoc": "^3.6.3",
|
||||
"jsdoc": "3.6.3",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"xo": "0.25.3"
|
||||
},
|
||||
|
||||
@@ -88,7 +88,10 @@ app.use((req, res, next) => {
|
||||
|
||||
// error handler
|
||||
app.use((err, req, res, next) => {
|
||||
if (err && err.message && err.message.includes("Invalid package")) {
|
||||
if (err && err.message && (
|
||||
err.message.includes("Invalid package")
|
||||
|| (err.message.includes("Router not found for request") && err.message.includes("node_modules"))
|
||||
)) {
|
||||
// electron 6 outputs a lot of such errors which do not seem important
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -29,6 +29,7 @@ import macInit from './services/mac_init.js';
|
||||
import cssLoader from './services/css_loader.js';
|
||||
import dateNoteService from './services/date_notes.js';
|
||||
import sidebarService from './services/sidebar.js';
|
||||
import importService from './services/import.js';
|
||||
|
||||
window.glob.isDesktop = utils.isDesktop;
|
||||
window.glob.isMobile = utils.isMobile;
|
||||
@@ -177,3 +178,7 @@ entrypoints.registerEntrypoints();
|
||||
noteTooltipService.setupGlobalTooltip();
|
||||
|
||||
noteAutocompleteService.init();
|
||||
|
||||
if (utils.isElectron()) {
|
||||
import("./services/spell_check.js").then(spellCheckService => spellCheckService.initSpellCheck());
|
||||
}
|
||||
@@ -1,16 +1,11 @@
|
||||
import treeService from '../services/tree.js';
|
||||
import utils from '../services/utils.js';
|
||||
import treeUtils from "../services/tree_utils.js";
|
||||
import server from "../services/server.js";
|
||||
import infoService from "../services/info.js";
|
||||
import ws from "../services/ws.js";
|
||||
import importService from "../services/import.js";
|
||||
|
||||
const $dialog = $("#import-dialog");
|
||||
const $form = $("#import-form");
|
||||
const $noteTitle = $dialog.find(".import-note-title");
|
||||
const $fileUploadInput = $("#import-file-upload-input");
|
||||
const $importProgressCountWrapper = $("#import-progress-count-wrapper");
|
||||
const $importProgressCount = $("#import-progress-count");
|
||||
const $importButton = $("#import-button");
|
||||
const $safeImportCheckbox = $("#safe-import-checkbox");
|
||||
const $shrinkImagesCheckbox = $("#shrink-images-checkbox");
|
||||
@@ -18,16 +13,11 @@ const $textImportedAsTextCheckbox = $("#text-imported-as-text-checkbox");
|
||||
const $codeImportedAsCodeCheckbox = $("#code-imported-as-code-checkbox");
|
||||
const $explodeArchivesCheckbox = $("#explode-archives-checkbox");
|
||||
|
||||
let importId;
|
||||
let importIntoNoteId = null;
|
||||
let parentNoteId = null;
|
||||
|
||||
export async function showDialog(node) {
|
||||
utils.closeActiveDialog();
|
||||
|
||||
// each opening of the dialog resets the importId so we don't associate it with previous imports anymore
|
||||
importId = '';
|
||||
$importProgressCountWrapper.hide();
|
||||
$importProgressCount.text('0');
|
||||
$fileUploadInput.val('').change(); // to trigger Import button disabling listener below
|
||||
|
||||
$safeImportCheckbox.prop("checked", true);
|
||||
@@ -38,9 +28,9 @@ export async function showDialog(node) {
|
||||
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
importIntoNoteId = node.data.noteId;
|
||||
parentNoteId = node.data.noteId;
|
||||
|
||||
$noteTitle.text(await treeUtils.getNoteTitle(importIntoNoteId));
|
||||
$noteTitle.text(await treeUtils.getNoteTitle(parentNoteId));
|
||||
|
||||
$dialog.modal();
|
||||
}
|
||||
@@ -49,18 +39,14 @@ $form.submit(() => {
|
||||
// disabling so that import is not triggered again.
|
||||
$importButton.attr("disabled", "disabled");
|
||||
|
||||
importIntoNote(importIntoNoteId);
|
||||
importIntoNote(parentNoteId);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
async function importIntoNote(importNoteId) {
|
||||
async function importIntoNote(parentNoteId) {
|
||||
const files = Array.from($fileUploadInput[0].files); // shallow copy since we're resetting the upload button below
|
||||
|
||||
// we generate it here (and not on opening) for the case when you try to import multiple times from the same
|
||||
// dialog (which shouldn't happen, but still ...)
|
||||
importId = utils.randomString(10);
|
||||
|
||||
const options = {
|
||||
safeImport: boolToString($safeImportCheckbox),
|
||||
shrinkImages: boolToString($shrinkImagesCheckbox),
|
||||
@@ -69,73 +55,15 @@ async function importIntoNote(importNoteId) {
|
||||
explodeArchives: boolToString($explodeArchivesCheckbox)
|
||||
};
|
||||
|
||||
await uploadFiles(importNoteId, files, options);
|
||||
|
||||
$dialog.modal('hide');
|
||||
}
|
||||
|
||||
export async function uploadFiles(importNoteId, files, options) {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
let noteId;
|
||||
|
||||
for (const file of files) {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', file);
|
||||
formData.append('importId', importId);
|
||||
|
||||
for (const key in options) {
|
||||
formData.append(key, options[key]);
|
||||
}
|
||||
|
||||
({noteId} = await $.ajax({
|
||||
url: baseApiUrl + 'notes/' + importNoteId + '/import',
|
||||
headers: server.getHeaders(),
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
timeout: 60 * 60 * 1000,
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false, // NEEDED, DON'T REMOVE THIS
|
||||
}));
|
||||
}
|
||||
|
||||
infoService.showMessage("Import finished successfully.");
|
||||
|
||||
await treeService.reloadNote(importNoteId);
|
||||
|
||||
if (noteId) {
|
||||
const node = await treeService.activateNote(noteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
await importService.uploadFiles(parentNoteId, files, options);
|
||||
}
|
||||
|
||||
function boolToString($el) {
|
||||
return $el.is(":checked") ? "true" : "false";
|
||||
}
|
||||
|
||||
ws.subscribeToMessages(async message => {
|
||||
if (message.type === 'import-error') {
|
||||
infoService.showError(message.message);
|
||||
$dialog.modal('hide');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!message.importId || message.importId !== importId) {
|
||||
// incoming messages must correspond to this import instance
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'import-progress-count') {
|
||||
$importProgressCountWrapper.slideDown();
|
||||
|
||||
$importProgressCount.text(message.progressCount);
|
||||
}
|
||||
});
|
||||
|
||||
$fileUploadInput.change(() => {
|
||||
if ($fileUploadInput.val()) {
|
||||
$importButton.removeAttr("disabled");
|
||||
|
||||
@@ -62,14 +62,4 @@ $list.on('change', () => {
|
||||
else {
|
||||
$content.text("Preview isn't available for this note type.");
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', "a[data-action='note-revision']", event => {
|
||||
const linkEl = $(event.target);
|
||||
const noteId = linkEl.attr('data-note-path');
|
||||
const noteRevisionId = linkEl.attr('data-note-revision-id');
|
||||
|
||||
showNoteRevisionsDialog(noteId, noteRevisionId);
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
@@ -19,8 +19,7 @@ export async function showDialog() {
|
||||
import('./options/appearance.js'),
|
||||
import('./options/code_notes.js'),
|
||||
import('./options/change_password.js'),
|
||||
import('./options/note_revisions.js'),
|
||||
import('./options/protected_session.js'),
|
||||
import('./options/other.js'),
|
||||
import('./options/sidebar.js'),
|
||||
import('./options/sync.js'),
|
||||
]))
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class NoteRevisionsOptions {
|
||||
constructor() {
|
||||
this.$form = $("#note-revision-snapshot-time-interval-form");
|
||||
this.$timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
||||
|
||||
this.$form.submit(() => {
|
||||
const opts = { 'noteRevisionSnapshotTimeInterval': this.$timeInterval.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
|
||||
}
|
||||
}
|
||||
54
src/public/javascripts/dialogs/options/other.js
Normal file
54
src/public/javascripts/dialogs/options/other.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import optionsService from "../../services/options.js";
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class ProtectedSessionOptions {
|
||||
constructor() {
|
||||
this.$spellCheckEnabled = $("#spell-check-enabled");
|
||||
this.$spellCheckLanguageCode = $("#spell-check-language-code");
|
||||
|
||||
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||
this.$noteRevisionsTimeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
|
||||
|
||||
this.$spellCheckEnabled.change(() => {
|
||||
const opts = { 'spellCheckEnabled': this.$spellCheckEnabled.is(":checked") ? "true" : "false" };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$spellCheckLanguageCode.change(() => {
|
||||
const opts = { 'spellCheckLanguageCode': this.$spellCheckLanguageCode.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$protectedSessionTimeout.change(() => {
|
||||
const protectedSessionTimeout = this.$protectedSessionTimeout.val();
|
||||
|
||||
server.put('options', { 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
|
||||
optionsService.reloadOptions();
|
||||
|
||||
infoService.showMessage("Options change have been saved.");
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
this.$noteRevisionsTimeInterval.change(() => {
|
||||
const opts = { 'noteRevisionSnapshotTimeInterval': this.$noteRevisionsTimeInterval.val() };
|
||||
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$spellCheckEnabled.prop("checked", options['spellCheckEnabled'] === 'true');
|
||||
this.$spellCheckLanguageCode.val(options['spellCheckLanguageCode']);
|
||||
|
||||
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
|
||||
this.$noteRevisionsTimeInterval.val(options['noteRevisionSnapshotTimeInterval']);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import optionsService from "../../services/options.js";
|
||||
import server from "../../services/server.js";
|
||||
import infoService from "../../services/info.js";
|
||||
|
||||
export default class ProtectedSessionOptions {
|
||||
constructor() {
|
||||
this.$form = $("#protected-session-timeout-form");
|
||||
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||
|
||||
this.$form.submit(() => this.save());
|
||||
}
|
||||
|
||||
optionsLoaded(options) {
|
||||
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
|
||||
}
|
||||
|
||||
save() {
|
||||
const protectedSessionTimeout = this.$protectedSessionTimeout.val();
|
||||
|
||||
server.put('options', { 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
|
||||
optionsService.reloadOptions();
|
||||
|
||||
infoService.showMessage("Options change have been saved.");
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@ async function getAndExecuteBundle(noteId, originEntity = null) {
|
||||
return await executeBundle(bundle, originEntity);
|
||||
}
|
||||
|
||||
async function executeBundle(bundle, originEntity, tabContext) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, tabContext);
|
||||
async function executeBundle(bundle, originEntity, tabContext, $container) {
|
||||
const apiContext = await ScriptContext(bundle.noteId, bundle.allNoteIds, originEntity, tabContext, $container);
|
||||
|
||||
try {
|
||||
return await (function () {
|
||||
|
||||
@@ -30,9 +30,9 @@ const dragAndDropSetup = {
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||
|
||||
const importDialog = await import('../dialogs/import.js');
|
||||
const importService = await import('./import.js');
|
||||
|
||||
importDialog.uploadFiles(node.data.noteId, files, {
|
||||
importService.uploadFiles(node.data.noteId, files, {
|
||||
safeImport: true,
|
||||
shrinkImages: true,
|
||||
textImportedAsText: true,
|
||||
|
||||
@@ -172,6 +172,19 @@ function registerEntrypoints() {
|
||||
utils.bindGlobalShortcut('ctrl+-', zoomService.decreaseZoomFactor);
|
||||
utils.bindGlobalShortcut('ctrl+=', zoomService.increaseZoomFactor);
|
||||
}
|
||||
|
||||
$(document).on('click', "a[data-action='note-revision']", async event => {
|
||||
const linkEl = $(event.target);
|
||||
const noteId = linkEl.attr('data-note-path');
|
||||
const noteRevisionId = linkEl.attr('data-note-revision-id');
|
||||
|
||||
const attributesDialog = await import("../dialogs/note_revisions.js");
|
||||
|
||||
attributesDialog.showNoteRevisionsDialog(noteId, noteRevisionId);
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -16,9 +16,12 @@ import StandardWidget from '../widgets/standard_widget.js';
|
||||
* @constructor
|
||||
* @hideconstructor
|
||||
*/
|
||||
function FrontendScriptApi(startNote, currentNote, originEntity = null, tabContext = null) {
|
||||
function FrontendScriptApi(startNote, currentNote, originEntity = null, tabContext = null, $container = null) {
|
||||
const $pluginButtons = $("#plugin-buttons");
|
||||
|
||||
/** @property {jQuery} container of all the rendered script content */
|
||||
this.$container = $container;
|
||||
|
||||
/** @property {object} note where script started executing */
|
||||
this.startNote = startNote;
|
||||
/** @property {object} note where script is currently executing */
|
||||
|
||||
66
src/public/javascripts/services/import.js
Normal file
66
src/public/javascripts/services/import.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import infoService from "./info.js";
|
||||
import treeService from "./tree.js";
|
||||
import server from "./server.js";
|
||||
import ws from "./ws.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
export async function uploadFiles(parentNoteId, files, options) {
|
||||
if (files.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importId = utils.randomString(10);
|
||||
let noteId;
|
||||
let counter = 0;
|
||||
|
||||
for (const file of files) {
|
||||
counter++;
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('upload', file);
|
||||
formData.append('importId', importId);
|
||||
formData.append('last', counter === files.length ? "true" : "false");
|
||||
|
||||
for (const key in options) {
|
||||
formData.append(key, options[key]);
|
||||
}
|
||||
|
||||
({noteId} = await $.ajax({
|
||||
url: baseApiUrl + 'notes/' + parentNoteId + '/import',
|
||||
headers: server.getHeaders(),
|
||||
data: formData,
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
timeout: 60 * 60 * 1000,
|
||||
contentType: false, // NEEDED, DON'T REMOVE THIS
|
||||
processData: false, // NEEDED, DON'T REMOVE THIS
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
ws.subscribeToMessages(async message => {
|
||||
if (message.type === 'import-error') {
|
||||
infoService.showError(message.message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (message.type === 'import-progress-count') {
|
||||
infoService.showMessage("Import in progress: " + message.progressCount, 1000);
|
||||
}
|
||||
|
||||
if (message.type === 'import-succeeded') {
|
||||
infoService.showMessage("Import finished successfully.", 5000);
|
||||
|
||||
await treeService.reloadNote(message.parentNoteId);
|
||||
|
||||
if (message.importedNoteId) {
|
||||
const node = await treeService.activateNote(message.importedNoteId);
|
||||
|
||||
node.setExpanded(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
uploadFiles
|
||||
}
|
||||
@@ -1,13 +1,13 @@
|
||||
import ws from "./ws.js";
|
||||
import utils from "./utils.js";
|
||||
|
||||
function showMessage(message) {
|
||||
function showMessage(message, delay = 3000) {
|
||||
console.debug(utils.now(), "message: ", message);
|
||||
|
||||
$.notify({
|
||||
icon: 'jam jam-check',
|
||||
message: message
|
||||
}, getNotifySettings('success', 3000));
|
||||
}, getNotifySettings('success', delay));
|
||||
}
|
||||
|
||||
function showAndLogError(message, delay = 10000) {
|
||||
|
||||
@@ -14,20 +14,24 @@ function getNotePathFromUrl(url) {
|
||||
}
|
||||
}
|
||||
|
||||
async function createNoteLink(notePath, noteTitle = null) {
|
||||
async function createNoteLink(notePath, noteTitle = null, tooltip = true) {
|
||||
if (!noteTitle) {
|
||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
||||
|
||||
noteTitle = await treeUtils.getNoteTitle(noteId);
|
||||
}
|
||||
|
||||
const noteLink = $("<a>", {
|
||||
const $noteLink = $("<a>", {
|
||||
href: 'javascript:',
|
||||
text: noteTitle
|
||||
}).attr('data-action', 'note')
|
||||
.attr('data-note-path', notePath);
|
||||
|
||||
return noteLink;
|
||||
if (!tooltip) {
|
||||
$noteLink.addClass("no-tooltip-preview");
|
||||
}
|
||||
|
||||
return $noteLink;
|
||||
}
|
||||
|
||||
async function createNoteLinkWithPath(notePath, noteTitle = null) {
|
||||
@@ -113,7 +117,7 @@ function addTextToEditor(text) {
|
||||
}
|
||||
}
|
||||
|
||||
function tabContextMenu(e) {
|
||||
function newTabContextMenu(e) {
|
||||
const $link = $(e.target);
|
||||
|
||||
const notePath = getNotePathFromLink($link);
|
||||
@@ -138,9 +142,9 @@ function tabContextMenu(e) {
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('contextmenu', '.note-detail-text a', tabContextMenu);
|
||||
$(document).on('contextmenu', "a[data-action='note']", tabContextMenu);
|
||||
$(document).on('contextmenu', ".note-detail-render a", tabContextMenu);
|
||||
$(document).on('contextmenu', '.note-detail-text a', newTabContextMenu);
|
||||
$(document).on('contextmenu', "a[data-action='note']", newTabContextMenu);
|
||||
$(document).on('contextmenu', ".note-detail-render a", newTabContextMenu);
|
||||
|
||||
// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
|
||||
// of opening the link in new window/tab
|
||||
@@ -159,6 +163,7 @@ $(document).on('mousedown', '.note-detail-text a', function (e) {
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('mousedown', '.note-detail-book a', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-render a', goToLink);
|
||||
$(document).on('mousedown', '.note-detail-text.ck-read-only a', goToLink);
|
||||
$(document).on('mousedown', 'span.ck-button__label', e => {
|
||||
|
||||
@@ -345,9 +345,9 @@ $tabContentsContainer.on("drop", async e => {
|
||||
|
||||
const files = [...e.originalEvent.dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
|
||||
|
||||
const importDialog = await import("../dialogs/import.js");
|
||||
const importService = await import("./import.js");
|
||||
|
||||
importDialog.uploadFiles(activeNote.noteId, files, {
|
||||
importService.uploadFiles(activeNote.noteId, files, {
|
||||
safeImport: true,
|
||||
shrinkImages: true,
|
||||
textImportedAsText: true,
|
||||
@@ -385,6 +385,8 @@ tabRow.addListener('tabRemove', async ({ detail }) => {
|
||||
});
|
||||
|
||||
$(tabRow.el).on('contextmenu', '.note-tab', e => {
|
||||
e.preventDefault();
|
||||
|
||||
const tab = $(e.target).closest(".note-tab");
|
||||
|
||||
contextMenuService.initContextMenu(e, {
|
||||
|
||||
292
src/public/javascripts/services/note_detail_book.js
Normal file
292
src/public/javascripts/services/note_detail_book.js
Normal file
@@ -0,0 +1,292 @@
|
||||
import server from "./server.js";
|
||||
import linkService from "./link.js";
|
||||
import utils from "./utils.js";
|
||||
import treeCache from "./tree_cache.js";
|
||||
import renderService from "./render.js";
|
||||
import protectedSessionHolder from "./protected_session_holder.js";
|
||||
import protectedSessionService from "./protected_session.js";
|
||||
|
||||
const MIN_ZOOM_LEVEL = 1;
|
||||
const MAX_ZOOM_LEVEL = 6;
|
||||
|
||||
const ZOOMS = {
|
||||
1: {
|
||||
width: "100%",
|
||||
height: "100%"
|
||||
},
|
||||
2: {
|
||||
width: "49%",
|
||||
height: "350px"
|
||||
},
|
||||
3: {
|
||||
width: "32%",
|
||||
height: "250px"
|
||||
},
|
||||
4: {
|
||||
width: "24%",
|
||||
height: "200px"
|
||||
},
|
||||
5: {
|
||||
width: "19%",
|
||||
height: "175px"
|
||||
},
|
||||
6: {
|
||||
width: "16%",
|
||||
height: "150px"
|
||||
}
|
||||
};
|
||||
|
||||
class NoteDetailBook {
|
||||
/**
|
||||
* @param {TabContext} ctx
|
||||
*/
|
||||
constructor(ctx) {
|
||||
this.ctx = ctx;
|
||||
this.$component = ctx.$tabContent.find('.note-detail-book');
|
||||
this.$content = this.$component.find('.note-detail-book-content');
|
||||
this.$zoomInButton = this.$component.find('.book-zoom-in-button');
|
||||
this.$zoomOutButton = this.$component.find('.book-zoom-out-button');
|
||||
this.$expandChildrenButton = this.$component.find('.expand-children-button');
|
||||
|
||||
this.$zoomInButton.click(() => this.setZoom(this.zoomLevel - 1));
|
||||
this.$zoomOutButton.click(() => this.setZoom(this.zoomLevel + 1));
|
||||
|
||||
this.$expandChildrenButton.click(async () => {
|
||||
for (let i = 1; i < 30; i++) { // protection against infinite cycle
|
||||
const $unexpandedLinks = this.$content.find('.note-book-open-children-button:visible');
|
||||
|
||||
if ($unexpandedLinks.length === 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
for (const link of $unexpandedLinks) {
|
||||
const $card = $(link).closest(".note-book-card");
|
||||
|
||||
await this.expandCard($card);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.$content.on('click', '.note-book-open-children-button', async ev => {
|
||||
const $card = $(ev.target).closest('.note-book-card');
|
||||
|
||||
await this.expandCard($card);
|
||||
});
|
||||
|
||||
this.$content.on('click', '.note-book-hide-children-button', async ev => {
|
||||
const $card = $(ev.target).closest('.note-book-card');
|
||||
|
||||
$card.find('.note-book-open-children-button').show();
|
||||
$card.find('.note-book-hide-children-button').hide();
|
||||
|
||||
$card.find('.note-book-children-content').empty();
|
||||
});
|
||||
}
|
||||
|
||||
async expandCard($card) {
|
||||
const noteId = $card.attr('data-note-id');
|
||||
const note = await treeCache.getNote(noteId);
|
||||
|
||||
$card.find('.note-book-open-children-button').hide();
|
||||
$card.find('.note-book-hide-children-button').show();
|
||||
|
||||
await this.renderIntoElement(note, $card.find('.note-book-children-content'));
|
||||
}
|
||||
|
||||
setZoom(zoomLevel) {
|
||||
if (!(zoomLevel in ZOOMS)) {
|
||||
zoomLevel = this.getDefaultZoomLevel();
|
||||
}
|
||||
|
||||
this.zoomLevel = zoomLevel;
|
||||
|
||||
this.$zoomInButton.prop("disabled", zoomLevel === MIN_ZOOM_LEVEL);
|
||||
this.$zoomOutButton.prop("disabled", zoomLevel === MAX_ZOOM_LEVEL);
|
||||
|
||||
this.$content.find('.note-book-card').css("flex-basis", ZOOMS[zoomLevel].width);
|
||||
this.$content.find('.note-book-content').css("max-height", ZOOMS[zoomLevel].height);
|
||||
}
|
||||
|
||||
async render() {
|
||||
this.$content.empty();
|
||||
|
||||
if (this.isAutoBook()) {
|
||||
const $addTextLink = $('<a href="javascript:">here</a>').click(() => {
|
||||
this.ctx.renderComponent(true);
|
||||
});
|
||||
|
||||
this.$content.append($('<div class="note-book-auto-message"></div>')
|
||||
.append(`This note doesn't have any content so we display its children. Click `)
|
||||
.append($addTextLink)
|
||||
.append(' if you want to add some text.'))
|
||||
}
|
||||
|
||||
const zoomLevel = parseInt(await this.ctx.note.getLabelValue('bookZoomLevel')) || this.getDefaultZoomLevel();
|
||||
this.setZoom(zoomLevel);
|
||||
|
||||
await this.renderIntoElement(this.ctx.note, this.$content);
|
||||
}
|
||||
|
||||
async renderIntoElement(note, $container) {
|
||||
for (const childNote of await note.getChildNotes()) {
|
||||
const type = this.getRenderingType(childNote);
|
||||
|
||||
const $card = $('<div class="note-book-card">')
|
||||
.attr('data-note-id', childNote.noteId)
|
||||
.css("flex-basis", ZOOMS[this.zoomLevel].width)
|
||||
.addClass("type-" + type)
|
||||
.append($('<h5 class="note-book-title">').append(await linkService.createNoteLink(childNote.noteId, null, false)))
|
||||
.append($('<div class="note-book-content">')
|
||||
.css("max-height", ZOOMS[this.zoomLevel].height)
|
||||
.append(await this.getNoteContent(type, childNote)));
|
||||
|
||||
const childCount = childNote.getChildNoteIds().length;
|
||||
|
||||
if (childCount > 0) {
|
||||
const label = `${childCount} child${childCount > 1 ? 'ren' : ''}`;
|
||||
|
||||
$card.append($('<div class="note-book-children">')
|
||||
.append($(`<a class="note-book-open-children-button" href="javascript:">+ Show ${label}</a>`))
|
||||
.append($(`<a class="note-book-hide-children-button" href="javascript:">- Hide ${label}</a>`).hide())
|
||||
.append($('<div class="note-book-children-content">'))
|
||||
);
|
||||
}
|
||||
|
||||
$container.append($card);
|
||||
}
|
||||
}
|
||||
|
||||
async getNoteContent(type, note) {
|
||||
if (type === 'text') {
|
||||
const fullNote = await server.get('notes/' + note.noteId);
|
||||
|
||||
const $content = $("<div>").html(fullNote.content);
|
||||
|
||||
if (utils.isHtmlEmpty(fullNote.content)) {
|
||||
return "";
|
||||
}
|
||||
else {
|
||||
return $content;
|
||||
}
|
||||
}
|
||||
else if (type === 'code') {
|
||||
const fullNote = await server.get('notes/' + note.noteId);
|
||||
|
||||
if (fullNote.content.trim() === "") {
|
||||
return "";
|
||||
}
|
||||
|
||||
return $("<pre>").text(fullNote.content);
|
||||
}
|
||||
else if (type === 'image') {
|
||||
return $("<img>").attr("src", `api/images/${note.noteId}/${note.title}`);
|
||||
}
|
||||
else if (type === 'file') {
|
||||
function getFileUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return utils.getHost() + "/api/notes/" + note.noteId + "/download";
|
||||
}
|
||||
|
||||
const $downloadButton = $('<button class="file-download btn btn-primary" type="button">Download</button>');
|
||||
const $openButton = $('<button class="file-open btn btn-primary" type="button">Open</button>');
|
||||
|
||||
$downloadButton.click(() => utils.download(getFileUrl()));
|
||||
$openButton.click(() => {
|
||||
if (utils.isElectron()) {
|
||||
const open = require("open");
|
||||
|
||||
open(getFileUrl());
|
||||
}
|
||||
else {
|
||||
window.location.href = getFileUrl();
|
||||
}
|
||||
});
|
||||
|
||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||
$openButton.toggle(!note.isProtected);
|
||||
|
||||
return $('<div>')
|
||||
.append($downloadButton)
|
||||
.append(' ')
|
||||
.append($openButton);
|
||||
}
|
||||
else if (type === 'render') {
|
||||
const $el = $('<div>');
|
||||
|
||||
await renderService.render(note, $el, this.ctx);
|
||||
|
||||
return $el;
|
||||
}
|
||||
else if (type === 'protected-session') {
|
||||
const $button = $(`<button class="btn btn-sm"><span class="jam jam-door"></span> Enter protected session</button>`)
|
||||
.click(protectedSessionService.enterProtectedSession);
|
||||
|
||||
return $("<div>")
|
||||
.append("<div>This note is protected and to access it you need to enter password.</div>")
|
||||
.append("<br/>")
|
||||
.append($button);
|
||||
}
|
||||
else {
|
||||
return "<em>Content of this note cannot be displayed in the book format</em>";
|
||||
}
|
||||
}
|
||||
|
||||
/** @return {boolean} true if this is "auto book" activated (empty text note) and not explicit book note */
|
||||
isAutoBook() {
|
||||
return this.ctx.note.type !== 'book';
|
||||
}
|
||||
|
||||
getDefaultZoomLevel() {
|
||||
if (this.isAutoBook()) {
|
||||
const w = this.$component.width();
|
||||
|
||||
if (w <= 600) {
|
||||
return 1;
|
||||
} else if (w <= 900) {
|
||||
return 2;
|
||||
} else if (w <= 1300) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
getRenderingType(childNote) {
|
||||
let type = childNote.type;
|
||||
|
||||
if (childNote.isProtected) {
|
||||
if (protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||
protectedSessionHolder.touchProtectedSession();
|
||||
}
|
||||
else {
|
||||
type = 'protected-session';
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
getContent() {}
|
||||
|
||||
show() {
|
||||
this.$component.show();
|
||||
}
|
||||
|
||||
focus() {}
|
||||
|
||||
onNoteChange() {}
|
||||
|
||||
cleanup() {
|
||||
this.$content.empty();
|
||||
}
|
||||
|
||||
scrollToTop() {
|
||||
this.$component.scrollTop(0);
|
||||
}
|
||||
}
|
||||
|
||||
export default NoteDetailBook;
|
||||
@@ -1,5 +1,4 @@
|
||||
import bundleService from "./bundle.js";
|
||||
import server from "./server.js";
|
||||
import renderService from "./render.js";
|
||||
|
||||
class NoteDetailRender {
|
||||
/**
|
||||
@@ -16,29 +15,10 @@ class NoteDetailRender {
|
||||
}
|
||||
|
||||
async render() {
|
||||
const attributes = await this.ctx.attributes.getAttributes();
|
||||
const renderNotes = attributes.filter(attr =>
|
||||
attr.type === 'relation'
|
||||
&& attr.name === 'renderNote'
|
||||
&& !!attr.value);
|
||||
|
||||
this.$component.show();
|
||||
this.$noteDetailRenderHelp.hide();
|
||||
|
||||
this.$noteDetailRenderContent.empty();
|
||||
this.$noteDetailRenderContent.toggle(renderNotes.length > 0);
|
||||
this.$noteDetailRenderHelp.toggle(renderNotes.length === 0);
|
||||
|
||||
for (const renderNote of renderNotes) {
|
||||
const bundle = await server.get('script/bundle/' + renderNote.value);
|
||||
|
||||
this.$noteDetailRenderContent.append(bundle.html);
|
||||
|
||||
const $result = await bundleService.executeBundle(bundle, this.ctx.note, this.ctx);
|
||||
|
||||
if ($result) {
|
||||
this.$noteDetailRenderContent.append($result);
|
||||
}
|
||||
}
|
||||
await renderService.render(this.ctx.note, this.$noteDetailRenderContent, this.ctx);
|
||||
}
|
||||
|
||||
getContent() {}
|
||||
|
||||
@@ -11,6 +11,7 @@ const NOTE_TYPES = [
|
||||
{ type: "text", mime: "text/html", title: "Text", selectable: true },
|
||||
{ type: "relation-map", mime: "application/json", title: "Relation Map", selectable: true },
|
||||
{ type: "render", mime: '', title: "Render Note", selectable: true },
|
||||
{ type: "book", mime: '', title: "Book", selectable: true },
|
||||
{ type: "code", mime: 'text/plain', title: "Code", selectable: true }
|
||||
];
|
||||
|
||||
|
||||
@@ -51,7 +51,11 @@ function reloadOptions() {
|
||||
return optionsReady;
|
||||
}
|
||||
|
||||
/** just waits for some options without triggering reload */
|
||||
/**
|
||||
* just waits for some options without triggering reload
|
||||
*
|
||||
* @return {Options}
|
||||
*/
|
||||
async function waitForOptions() {
|
||||
return await optionsReady;
|
||||
}
|
||||
|
||||
@@ -46,8 +46,7 @@ async function setupProtectedSession(password) {
|
||||
|
||||
await treeService.reload();
|
||||
|
||||
// it's important that tree has been already reloaded at this point since detail also uses tree cache (for children overview)
|
||||
// children overview is the reason why we need to reload all tabs
|
||||
// it's important that tree has been already reloaded at this point since detail also uses tree cache (for book)
|
||||
await noteDetailService.reloadAllTabs();
|
||||
|
||||
if (protectedSessionDeferred !== null) {
|
||||
|
||||
33
src/public/javascripts/services/render.js
Normal file
33
src/public/javascripts/services/render.js
Normal file
@@ -0,0 +1,33 @@
|
||||
import server from "./server.js";
|
||||
import bundleService from "./bundle.js";
|
||||
|
||||
async function render(note, $el, ctx) {
|
||||
const attributes = await note.getAttributes();
|
||||
const renderNoteIds = attributes.filter(attr =>
|
||||
attr.type === 'relation'
|
||||
&& attr.name === 'renderNote'
|
||||
&& !!attr.value).map(rel => rel.value);
|
||||
|
||||
$el.empty().toggle(renderNoteIds.length > 0);
|
||||
|
||||
for (const renderNoteId of renderNoteIds) {
|
||||
const bundle = await server.get('script/bundle/' + renderNoteId);
|
||||
|
||||
const $scriptContainer = $('<div>');
|
||||
$el.append($scriptContainer);
|
||||
|
||||
$scriptContainer.append(bundle.html);
|
||||
|
||||
const $result = await bundleService.executeBundle(bundle, note, ctx, $scriptContainer);
|
||||
|
||||
if ($result) {
|
||||
$scriptContainer.append($result);
|
||||
}
|
||||
}
|
||||
|
||||
return renderNoteIds.length > 0;
|
||||
}
|
||||
|
||||
export default {
|
||||
render
|
||||
}
|
||||
@@ -2,7 +2,7 @@ import FrontendScriptApi from './frontend_script_api.js';
|
||||
import utils from './utils.js';
|
||||
import treeCache from './tree_cache.js';
|
||||
|
||||
async function ScriptContext(startNoteId, allNoteIds, originEntity = null, tabContext = null) {
|
||||
async function ScriptContext(startNoteId, allNoteIds, originEntity = null, tabContext = null, $container = null) {
|
||||
const modules = {};
|
||||
|
||||
const startNote = await treeCache.getNote(startNoteId);
|
||||
@@ -11,7 +11,7 @@ async function ScriptContext(startNoteId, allNoteIds, originEntity = null, tabCo
|
||||
return {
|
||||
modules: modules,
|
||||
notes: utils.toObject(allNotes, note => [note.noteId, note]),
|
||||
apis: utils.toObject(allNotes, note => [note.noteId, new FrontendScriptApi(startNote, note, originEntity, tabContext)]),
|
||||
apis: utils.toObject(allNotes, note => [note.noteId, new FrontendScriptApi(startNote, note, originEntity, tabContext, $container)]),
|
||||
require: moduleNoteIds => {
|
||||
return moduleName => {
|
||||
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
||||
|
||||
48
src/public/javascripts/services/spell_check.js
Normal file
48
src/public/javascripts/services/spell_check.js
Normal file
@@ -0,0 +1,48 @@
|
||||
import optionsService from "./options.js";
|
||||
|
||||
export async function initSpellCheck() {
|
||||
const options = await optionsService.waitForOptions();
|
||||
|
||||
if (!options.is('spellCheckEnabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {SpellCheckHandler, ContextMenuListener, ContextMenuBuilder} = require('electron-spellchecker');
|
||||
const {remote, shell} = require('electron');
|
||||
|
||||
const spellCheckHandler = new SpellCheckHandler();
|
||||
spellCheckHandler.attachToInput();
|
||||
|
||||
spellCheckHandler.switchLanguage(options.get('spellCheckLanguageCode'));
|
||||
|
||||
spellCheckHandler.currentSpellcheckerChanged.subscribe(() => {
|
||||
console.debug(`Detected language is ${spellCheckHandler.currentSpellcheckerLanguage}`);
|
||||
|
||||
spellCheckHandler.currentSpellchecker.add("trilium");
|
||||
spellCheckHandler.currentSpellchecker.add("https");
|
||||
spellCheckHandler.currentSpellchecker.add("github");
|
||||
spellCheckHandler.currentSpellchecker.add("unordered");
|
||||
});
|
||||
|
||||
const contextMenuBuilder = new ContextMenuBuilder(spellCheckHandler, null, true, (menu, menuInfo) => {
|
||||
// There's no menu.remove(id) so this is a convoluted way of removing the 'Search with Google' menu item
|
||||
const oldItems = menu.items;
|
||||
menu.clear();
|
||||
oldItems.forEach(oldItem => {
|
||||
if (!oldItem.label.includes('Google')) {
|
||||
menu.append(oldItem);
|
||||
} else {
|
||||
menu.append(new remote.MenuItem({
|
||||
label: 'Search with DuckDuckGo',
|
||||
click: () => {
|
||||
shell.openExternal(`https://duckduckgo.com/?q=${encodeURIComponent(menuInfo.selectionText)}`);
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
new ContextMenuListener(async (info) => {
|
||||
await contextMenuBuilder.showPopupMenu(info);
|
||||
});
|
||||
}
|
||||
@@ -23,7 +23,8 @@ const componentClasses = {
|
||||
'search': "./note_detail_search.js",
|
||||
'render': "./note_detail_render.js",
|
||||
'relation-map': "./note_detail_relation_map.js",
|
||||
'protected-session': "./note_detail_protected_session.js"
|
||||
'protected-session': "./note_detail_protected_session.js",
|
||||
'book': "./note_detail_book.js"
|
||||
};
|
||||
|
||||
let showSidebarInNewTab = true;
|
||||
@@ -64,7 +65,6 @@ class TabContext {
|
||||
this.$notePathList = this.$tabContent.find(".note-path-list");
|
||||
this.$notePathCount = this.$tabContent.find(".note-path-count");
|
||||
this.$noteDetailComponents = this.$tabContent.find(".note-detail-component");
|
||||
this.$childrenOverview = this.$tabContent.find(".children-overview");
|
||||
this.$scriptArea = this.$tabContent.find(".note-detail-script-area");
|
||||
this.$savedIndicator = this.$tabContent.find(".saved-indicator");
|
||||
this.noteChangeDisabled = false;
|
||||
@@ -115,13 +115,13 @@ class TabContext {
|
||||
await this.initComponent();
|
||||
}
|
||||
|
||||
async initComponent() {
|
||||
const type = this.getComponentType();
|
||||
async initComponent(disableAutoBook = false) {
|
||||
this.type = this.getComponentType(disableAutoBook);
|
||||
|
||||
if (!(type in this.components)) {
|
||||
const clazz = await import(componentClasses[type]);
|
||||
if (!(this.type in this.components)) {
|
||||
const clazz = await import(componentClasses[this.type]);
|
||||
|
||||
this.components[type] = new clazz.default(this);
|
||||
this.components[this.type] = new clazz.default(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class TabContext {
|
||||
|
||||
this.setTitleBar();
|
||||
|
||||
this.closeAutocomplete(); // esp. on windows autocomplete is not getting closed automatically
|
||||
this.cleanup(); // esp. on windows autocomplete is not getting closed automatically
|
||||
|
||||
setTimeout(async () => {
|
||||
// we include the note into recent list only if the user stayed on the note at least 5 seconds
|
||||
@@ -179,8 +179,6 @@ class TabContext {
|
||||
|
||||
if (utils.isDesktop()) {
|
||||
this.noteType.update();
|
||||
|
||||
this.showChildrenOverview();
|
||||
}
|
||||
|
||||
if (this.sidebar) {
|
||||
@@ -210,11 +208,11 @@ class TabContext {
|
||||
this.setTitleBar();
|
||||
}
|
||||
|
||||
async renderComponent() {
|
||||
await this.initComponent();
|
||||
async renderComponent(disableAutoBook = false) {
|
||||
await this.initComponent(disableAutoBook);
|
||||
|
||||
for (const componentType in this.components) {
|
||||
if (componentType !== this.getComponentType()) {
|
||||
if (componentType !== this.type) {
|
||||
this.components[componentType].cleanup();
|
||||
}
|
||||
}
|
||||
@@ -283,30 +281,31 @@ class TabContext {
|
||||
}
|
||||
|
||||
getComponent() {
|
||||
const type = this.getComponentType();
|
||||
|
||||
return this.components[type];
|
||||
return this.components[this.type];
|
||||
}
|
||||
|
||||
getComponentType() {
|
||||
let type;
|
||||
|
||||
if (this.note) {
|
||||
type = this.note.type;
|
||||
|
||||
if (this.note.isProtected) {
|
||||
if (protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||
protectedSessionHolder.touchProtectedSession();
|
||||
} else {
|
||||
type = 'protected-session';
|
||||
|
||||
// user shouldn't be able to edit note title
|
||||
this.$noteTitle.prop("readonly", true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type = 'empty';
|
||||
getComponentType(disableAutoBook) {
|
||||
if (!this.note) {
|
||||
return "empty";
|
||||
}
|
||||
|
||||
let type = this.note.type;
|
||||
|
||||
if (type === 'text' && !disableAutoBook && utils.isHtmlEmpty(this.note.content) && this.note.hasChildren()) {
|
||||
type = 'book';
|
||||
}
|
||||
|
||||
if (this.note.isProtected) {
|
||||
if (protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||
protectedSessionHolder.touchProtectedSession();
|
||||
} else {
|
||||
type = 'protected-session';
|
||||
|
||||
// user shouldn't be able to edit note title
|
||||
this.$noteTitle.prop("readonly", true);
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -365,33 +364,6 @@ class TabContext {
|
||||
this.$savedIndicator.fadeOut();
|
||||
}
|
||||
|
||||
async showChildrenOverview() {
|
||||
const attributes = await this.attributes.getAttributes();
|
||||
const hideChildrenOverview = attributes.some(attr => attr.type === 'label' && attr.name === 'hideChildrenOverview')
|
||||
|| this.note.type === 'relation-map'
|
||||
|| this.note.type === 'image'
|
||||
|| this.note.type === 'file';
|
||||
|
||||
if (hideChildrenOverview) {
|
||||
this.$childrenOverview.hide();
|
||||
return;
|
||||
}
|
||||
|
||||
this.$childrenOverview.empty();
|
||||
|
||||
for (const childBranch of await this.note.getChildBranches()) {
|
||||
const link = $('<a>', {
|
||||
href: 'javascript:',
|
||||
text: await treeUtils.getNoteTitle(childBranch.noteId, childBranch.parentNoteId)
|
||||
}).attr('data-action', 'note').attr('data-note-path', this.notePath + '/' + childBranch.noteId);
|
||||
|
||||
const childEl = $('<div class="child-overview-item">').html(link);
|
||||
this.$childrenOverview.append(childEl);
|
||||
}
|
||||
|
||||
this.$childrenOverview.show();
|
||||
}
|
||||
|
||||
async addPath(notePath, isCurrent) {
|
||||
const title = await treeUtils.getNotePathTitle(notePath);
|
||||
|
||||
@@ -440,15 +412,17 @@ class TabContext {
|
||||
|
||||
async remove() {
|
||||
// sometimes there are orphan autocompletes after closing the tab
|
||||
this.closeAutocomplete();
|
||||
this.cleanup();
|
||||
|
||||
await this.saveNoteIfChanged();
|
||||
this.$tabContent.remove();
|
||||
}
|
||||
|
||||
closeAutocomplete() {
|
||||
if (utils.isDesktop()) {
|
||||
cleanup() {
|
||||
if (this.$tabContent && utils.isDesktop()) {
|
||||
this.$tabContent.find('.aa-input').autocomplete('close');
|
||||
|
||||
$('.note-tooltip').remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,16 @@ async function prepareBranch(note) {
|
||||
}
|
||||
}
|
||||
|
||||
const NOTE_TYPE_ICONS = {
|
||||
"file": "jam jam-attachment",
|
||||
"image": "jam jam-picture",
|
||||
"code": "jam jam-terminal",
|
||||
"render": "jam jam-play",
|
||||
"search": "jam jam-search-folder",
|
||||
"relation-map": "jam jam-map",
|
||||
"book": "jam jam-book"
|
||||
};
|
||||
|
||||
async function getIcon(note) {
|
||||
const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
|
||||
|
||||
@@ -48,23 +58,8 @@ async function getIcon(note) {
|
||||
return "jam jam-file";
|
||||
}
|
||||
}
|
||||
else if (note.type === 'file') {
|
||||
return "jam jam-attachment"
|
||||
}
|
||||
else if (note.type === 'image') {
|
||||
return "jam jam-picture"
|
||||
}
|
||||
else if (note.type === 'code') {
|
||||
return "jam jam-terminal"
|
||||
}
|
||||
else if (note.type === 'render') {
|
||||
return "jam jam-play"
|
||||
}
|
||||
else if (note.type === 'search') {
|
||||
return "jam jam-search-folder"
|
||||
}
|
||||
else if (note.type === 'relation-map') {
|
||||
return "jam jam-map"
|
||||
else {
|
||||
return NOTE_TYPE_ICONS[note.type];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,6 +156,10 @@ async function getExtraClasses(note) {
|
||||
extraClasses.push(utils.getMimeTypeClass(note.mime));
|
||||
}
|
||||
|
||||
if (note.archived) {
|
||||
extraClasses.push("archived");
|
||||
}
|
||||
|
||||
return extraClasses.join(" ");
|
||||
}
|
||||
|
||||
|
||||
@@ -201,6 +201,10 @@ function closeActiveDialog() {
|
||||
}
|
||||
}
|
||||
|
||||
function isHtmlEmpty(html) {
|
||||
return $("<div>").html(html).text().trim().length === 0 && !html.toLowerCase().includes('<img');
|
||||
}
|
||||
|
||||
export default {
|
||||
reloadApp,
|
||||
parseDate,
|
||||
@@ -231,5 +235,6 @@ export default {
|
||||
getCookie,
|
||||
getNoteTypeClass,
|
||||
getMimeTypeClass,
|
||||
closeActiveDialog
|
||||
closeActiveDialog,
|
||||
isHtmlEmpty
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
import utils from './utils.js';
|
||||
import infoService from "./info.js";
|
||||
import treeService from "./tree.js";
|
||||
|
||||
const $outstandingSyncsCount = $("#outstanding-syncs-count");
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class NoteRevisionsWidget extends StandardWidget {
|
||||
const $showFullButton = $("<a>").append("show dialog").addClass('widget-header-action');
|
||||
$showFullButton.click(async () => {
|
||||
const attributesDialog = await import("../dialogs/note_revisions.js");
|
||||
attributesDialog.showDialog();
|
||||
attributesDialog.showCurrentNoteRevisions(this.ctx.note.noteId);
|
||||
});
|
||||
|
||||
return [$showFullButton];
|
||||
|
||||
@@ -31,11 +31,6 @@
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.link-map-container .floating-button {
|
||||
position: absolute !important;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.link-map-active-note {
|
||||
background-color: var(--accented-background-color) !important;
|
||||
}
|
||||
|
||||
@@ -75,9 +75,4 @@
|
||||
|
||||
.note-detail-relation-map .ui-contextmenu {
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.note-detail-relation-map .floating-button {
|
||||
position: absolute !important;
|
||||
z-index: 100;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ ul.fancytree-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 200px;
|
||||
min-height: 500px;
|
||||
overflow-wrap: break-word; /* otherwise CKEditor fails miserably on super long lines */
|
||||
font-family: var(--detail-font-family);
|
||||
font-size: var(--detail-font-size);
|
||||
@@ -136,7 +136,7 @@ ul.fancytree-container {
|
||||
border: 0 !important;
|
||||
box-shadow: none !important;
|
||||
/* This is because with empty content height of editor is 0 and it's impossible to click into it */
|
||||
min-height: 200px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.note-detail-text p:first-child, .note-detail-text::before {
|
||||
@@ -213,6 +213,10 @@ span.fancytree-node:hover span.fancytree-title {
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
span.fancytree-node.archived {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.ui-autocomplete {
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
@@ -353,11 +357,11 @@ div.ui-tooltip {
|
||||
}
|
||||
|
||||
.note-detail-code-editor {
|
||||
min-height: 200px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.note-detail-render {
|
||||
min-height: 200px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.CodeMirror {
|
||||
@@ -367,7 +371,7 @@ div.ui-tooltip {
|
||||
}
|
||||
|
||||
.CodeMirror-scroll {
|
||||
min-height: 200px;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
@@ -390,37 +394,6 @@ div.ui-tooltip {
|
||||
font-size: larger;
|
||||
}
|
||||
|
||||
.children-overview {
|
||||
flex-grow: 1000;
|
||||
flex-shrink: 1000;
|
||||
flex-basis: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
height: 110px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.child-overview-item {
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
background: var(--accented-background-color);
|
||||
width: 150px;
|
||||
height: 85px;
|
||||
line-height: 2em;
|
||||
margin-right: 20px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
text-overflow: ellipsis;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.child-overview-item a {
|
||||
color: var(--muted-text-color);
|
||||
}
|
||||
|
||||
#sql-console-query {
|
||||
height: 150px;
|
||||
width: 100%;
|
||||
@@ -817,4 +790,71 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
||||
|
||||
.modal-header {
|
||||
padding: 0.7rem 1rem !important; /* make modal header padding slightly smaller */
|
||||
}
|
||||
|
||||
.floating-button {
|
||||
position: absolute !important;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.note-detail-book {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.note-detail-book-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.note-book-card {
|
||||
border-radius: 10px;
|
||||
background-color: var(--accented-background-color);
|
||||
padding: 15px;
|
||||
padding-bottom: 5px;
|
||||
margin: 5px;
|
||||
margin-left: 0;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.note-book-card .note-book-card {
|
||||
border: 1px solid var(--main-border-color);
|
||||
}
|
||||
|
||||
.note-book-content {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.note-book-card.type-image .note-book-content, .note-book-card.type-file .note-book-content, .note-book-card.type-protected-session .note-book-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.note-book-card.type-image .note-book-content img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.note-book-title {
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.note-book-content {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.note-book-auto-message {
|
||||
background-color: var(--accented-background-color);
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
padding: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
--main-background-color: white;
|
||||
--main-text-color: black;
|
||||
--main-border-color: #ccc;
|
||||
--accented-background-color: #eee;
|
||||
--accented-background-color: #f5f5f5;
|
||||
--more-accented-background-color: #ccc;
|
||||
--header-background-color: #f8f8f8;
|
||||
--button-background-color: #eee;
|
||||
@@ -183,6 +183,8 @@ body {
|
||||
/* todo lists */
|
||||
|
||||
--ck-color-todo-list-checkmark-border: var(--main-border-color);
|
||||
|
||||
--ck-color-engine-placeholder-text: var(--main-text-color);
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@@ -13,7 +13,7 @@ const ImportContext = require('../../services/import_context');
|
||||
|
||||
async function importToBranch(req) {
|
||||
const {parentNoteId} = req.params;
|
||||
const {importId} = req.body;
|
||||
const {importId, last} = req.body;
|
||||
|
||||
const options = {
|
||||
safeImport: req.body.safeImport !== 'false',
|
||||
@@ -65,6 +65,11 @@ async function importToBranch(req) {
|
||||
return [500, message];
|
||||
}
|
||||
|
||||
if (last === "true") {
|
||||
// small timeout to avoid race condition (message is received before the transaction is committed)
|
||||
setTimeout(() => importContext.importSucceeded(parentNoteId, note.noteId), 1000);
|
||||
}
|
||||
|
||||
// import has deactivated note events so note cache is not updated
|
||||
// instead we force it to reload (can be async)
|
||||
noteCacheService.load();
|
||||
|
||||
@@ -32,7 +32,9 @@ const ALLOWED_OPTIONS = [
|
||||
'similarNotesWidget',
|
||||
'editedNotesWidget',
|
||||
'calendarWidget',
|
||||
'codeNotesMimeTypes'
|
||||
'codeNotesMimeTypes',
|
||||
'spellCheckEnabled',
|
||||
'spellCheckLanguageCode'
|
||||
];
|
||||
|
||||
async function getOptions() {
|
||||
|
||||
@@ -75,6 +75,7 @@ async function forceNoteSync(req) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
await syncTableService.addNoteSync(noteId);
|
||||
await syncTableService.addNoteContentSync(noteId);
|
||||
|
||||
for (const branchId of await sql.getColumn("SELECT branchId FROM branches WHERE isDeleted = 0 AND noteId = ?", [noteId])) {
|
||||
await syncTableService.addBranchSync(branchId);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
const sql = require('../../services/sql');
|
||||
const optionService = require('../../services/options');
|
||||
const protectedSessionService = require('../../services/protected_session');
|
||||
const noteCacheService = require('../../services/note_cache');
|
||||
|
||||
async function getNotes(noteIds) {
|
||||
const notes = await sql.getManyRows(`
|
||||
@@ -31,7 +32,11 @@ async function getNotes(noteIds) {
|
||||
|
||||
protectedSessionService.decryptNotes(notes);
|
||||
|
||||
notes.forEach(note => note.isProtected = !!note.isProtected);
|
||||
notes.forEach(note => {
|
||||
note.isProtected = !!note.isProtected;
|
||||
note.archived = noteCacheService.isArchived(note.noteId)
|
||||
});
|
||||
|
||||
return notes;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||
|
||||
const APP_DB_VERSION = 145;
|
||||
const APP_DB_VERSION = 146;
|
||||
const SYNC_VERSION = 10;
|
||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ const BUILTIN_ATTRIBUTES = [
|
||||
{ type: 'label', name: 'disableInclusion' },
|
||||
{ type: 'label', name: 'appCss' },
|
||||
{ type: 'label', name: 'appTheme' },
|
||||
{ type: 'label', name: 'hideChildrenOverview' },
|
||||
{ type: 'label', name: 'hidePromotedAttributes' },
|
||||
{ type: 'label', name: 'readOnly' },
|
||||
{ type: 'label', name: 'run', isDangerous: true },
|
||||
{ type: 'label', name: 'customRequestHandler', isDangerous: true },
|
||||
{ type: 'label', name: 'customResourceProvider', isDangerous: true },
|
||||
{ type: 'label', name: 'bookZoomLevel', isDangerous: false },
|
||||
|
||||
// relation names
|
||||
{ type: 'relation', name: 'runOnNoteView', isDangerous: true },
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2019-10-09T23:09:38+02:00", buildRevision: "6c3809e1db71ebca7bf0ca69f664c3c3f1af793a" };
|
||||
module.exports = { buildDate:"2019-10-15T20:42:17+02:00", buildRevision: "2be1aca2f3a5912c0b1347bc4ebdce6bff999018" };
|
||||
|
||||
@@ -216,7 +216,7 @@ async function findLogicIssues() {
|
||||
FROM notes
|
||||
WHERE
|
||||
isDeleted = 0
|
||||
AND type NOT IN ('text', 'code', 'render', 'file', 'image', 'search', 'relation-map')`,
|
||||
AND type NOT IN ('text', 'code', 'render', 'file', 'image', 'search', 'relation-map', 'book')`,
|
||||
({noteId, type}) => `Note ${noteId} has invalid type=${type}`);
|
||||
|
||||
await findIssues(`
|
||||
|
||||
@@ -64,6 +64,7 @@ const EXTENSION_TO_MIME = {
|
||||
".swift": "text/x-swift"
|
||||
};
|
||||
|
||||
/** @returns false if MIME is not detected */
|
||||
function getMime(fileName) {
|
||||
if (fileName.toLowerCase() === 'dockerfile') {
|
||||
return "text/x-dockerfile";
|
||||
@@ -79,7 +80,7 @@ function getMime(fileName) {
|
||||
}
|
||||
|
||||
function getType(importContext, mime) {
|
||||
mime = mime.toLowerCase();
|
||||
mime = mime ? mime.toLowerCase() : '';
|
||||
|
||||
if (importContext.textImportedAsText && (mime === 'text/html' || ['text/markdown', 'text/x-markdown'].includes(mime))) {
|
||||
return 'text';
|
||||
@@ -96,7 +97,7 @@ function getType(importContext, mime) {
|
||||
}
|
||||
|
||||
function normalizeMimeType(mime) {
|
||||
mime = mime.toLowerCase();
|
||||
mime = mime ? mime.toLowerCase() : '';
|
||||
|
||||
if (!(mime in CODE_MIME_TYPES) || CODE_MIME_TYPES[mime] === true) {
|
||||
return mime;
|
||||
|
||||
@@ -8,7 +8,7 @@ const path = require('path');
|
||||
const mimeService = require('./mime');
|
||||
|
||||
async function importSingleFile(importContext, file, parentNote) {
|
||||
const mime = mimeService.getMime(file.originalname);
|
||||
const mime = mimeService.getMime(file.originalname) || file.mimetype;
|
||||
|
||||
if (importContext.textImportedAsText) {
|
||||
if (mime === 'text/html') {
|
||||
@@ -47,7 +47,7 @@ async function importFile(importContext, file, parentNote) {
|
||||
target: 'into',
|
||||
isProtected: parentNote.isProtected && protectedSessionService.isProtectedSessionAvailable(),
|
||||
type: 'file',
|
||||
mime: mimeService.getMime(originalName),
|
||||
mime: mimeService.getMime(originalName) || file.mimetype,
|
||||
attributes: [
|
||||
{ type: "label", name: "originalFileName", value: originalName },
|
||||
{ type: "label", name: "fileSize", value: size }
|
||||
@@ -62,7 +62,7 @@ async function importFile(importContext, file, parentNote) {
|
||||
async function importCodeNote(importContext, file, parentNote) {
|
||||
const title = getFileNameWithoutExtension(file.originalname);
|
||||
const content = file.buffer.toString("UTF-8");
|
||||
const detectedMime = mimeService.getMime(file.originalname);
|
||||
const detectedMime = mimeService.getMime(file.originalname) || file.mimetype;
|
||||
const mime = mimeService.normalizeMimeType(detectedMime);
|
||||
|
||||
const {note} = await noteService.createNote(parentNote.noteId, title, content, {
|
||||
|
||||
@@ -14,6 +14,7 @@ const commonmark = require('commonmark');
|
||||
const ImportContext = require('../import_context');
|
||||
const protectedSessionService = require('../protected_session');
|
||||
const mimeService = require("./mime");
|
||||
const treeService = require("../tree");
|
||||
|
||||
/**
|
||||
* @param {ImportContext} importContext
|
||||
@@ -115,11 +116,7 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
function getNoteId(noteMeta, filePath) {
|
||||
const filePathNoExt = getTextFileWithoutExtension(filePath);
|
||||
|
||||
console.log(`Searching for noteId of filePath ${filePath} with meta: ${!!noteMeta}`);
|
||||
|
||||
if (filePathNoExt in createdPaths) {
|
||||
console.log("Found existing path", filePathNoExt, createdPaths[filePathNoExt]);
|
||||
|
||||
return createdPaths[filePathNoExt];
|
||||
}
|
||||
|
||||
@@ -131,7 +128,7 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
}
|
||||
|
||||
function detectFileTypeAndMime(importContext, filePath) {
|
||||
const mime = mimeService.getMime(filePath);
|
||||
const mime = mimeService.getMime(filePath) || "application/octet-stream";
|
||||
const type = mimeService.getType(importContext, mime);
|
||||
|
||||
return { mime, type };
|
||||
@@ -426,6 +423,12 @@ async function importTar(importContext, fileBuffer, importRootNote) {
|
||||
for (const noteId in createdNoteIds) { // now the noteIds are unique
|
||||
await noteService.scanForLinks(noteId);
|
||||
|
||||
if (!metaFile) {
|
||||
// if there's no meta file then the notes are created based on the order in that tar file but that
|
||||
// is usually quite random so we sort the notes in the way they would appear in the file manager
|
||||
await treeService.sortNotesAlphabetically(noteId, true);
|
||||
}
|
||||
|
||||
importContext.increaseProgressCount();
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class ImportContext {
|
||||
async increaseProgressCount() {
|
||||
this.progressCount++;
|
||||
|
||||
if (Date.now() - this.lastSentCountTs >= 500) {
|
||||
if (Date.now() - this.lastSentCountTs >= 1000) {
|
||||
this.lastSentCountTs = Date.now();
|
||||
|
||||
await ws.sendMessageToAllClients({
|
||||
@@ -51,6 +51,15 @@ class ImportContext {
|
||||
message: message
|
||||
});
|
||||
}
|
||||
|
||||
// must remaing non-static
|
||||
async importSucceeded(parentNoteId, importedNoteId) {
|
||||
await ws.sendMessageToAllClients({
|
||||
type: 'import-succeeded',
|
||||
parentNoteId: parentNoteId,
|
||||
importedNoteId: importedNoteId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ImportContext;
|
||||
@@ -86,9 +86,12 @@ async function findNotes(query) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// trim is necessary because even with .split() trailing spaces are tokens which causes havoc
|
||||
// filtering '/' because it's used as separator
|
||||
const allTokens = query.trim().toLowerCase().split(" ").filter(token => token !== '/');
|
||||
const allTokens = query
|
||||
.trim() // necessary because even with .split() trailing spaces are tokens which causes havoc
|
||||
.toLowerCase()
|
||||
.split(/[ -]/)
|
||||
.filter(token => token !== '/'); // '/' is used as separator
|
||||
|
||||
const tokens = allTokens.slice();
|
||||
let results = [];
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ async function initNotSyncedOptions(initialized, startNotePath = 'root', opts =
|
||||
await optionService.createOption('similarNotesWidget', '{"enabled":true,"expanded":true,"position":600}', false);
|
||||
|
||||
await optionService.createOption('initialized', initialized ? 'true' : 'false', false);
|
||||
|
||||
await optionService.createOption('spellCheckEnabled', 'true', false);
|
||||
await optionService.createOption('spellCheckLanguageCode', 'en-US', false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -87,15 +87,28 @@ async function loadSubtreeNoteIds(parentNoteId, subtreeNoteIds) {
|
||||
}
|
||||
}
|
||||
|
||||
async function sortNotesAlphabetically(parentNoteId) {
|
||||
async function sortNotesAlphabetically(parentNoteId, directoriesFirst = false) {
|
||||
await sql.transactional(async () => {
|
||||
const notes = await sql.getRows(`SELECT branchId, noteId, title, isProtected
|
||||
FROM notes JOIN branches USING(noteId)
|
||||
WHERE branches.isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]);
|
||||
const notes = await sql.getRows(
|
||||
`SELECT branches.branchId, notes.noteId, title, isProtected,
|
||||
CASE WHEN COUNT(childBranches.noteId) > 0 THEN 1 ELSE 0 END AS hasChildren
|
||||
FROM notes
|
||||
JOIN branches ON branches.noteId = notes.noteId
|
||||
LEFT JOIN branches childBranches ON childBranches.parentNoteId = notes.noteId AND childBranches.isDeleted = 0
|
||||
WHERE branches.isDeleted = 0 AND branches.parentNoteId = ?
|
||||
GROUP BY notes.noteId`, [parentNoteId]);
|
||||
|
||||
protectedSessionService.decryptNotes(notes);
|
||||
|
||||
notes.sort((a, b) => a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1);
|
||||
notes.sort((a, b) => {
|
||||
if (directoriesFirst && ((a.hasChildren && !b.hasChildren) || (!a.hasChildren && b.hasChildren))) {
|
||||
// exactly one note of the two is a directory so the sorting will be done based on this status
|
||||
return a.hasChildren ? -1 : 1;
|
||||
}
|
||||
else {
|
||||
return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1;
|
||||
}
|
||||
});
|
||||
|
||||
let position = 1;
|
||||
|
||||
|
||||
17
src/views/details/book.ejs
Normal file
17
src/views/details/book.ejs
Normal file
@@ -0,0 +1,17 @@
|
||||
<div class="note-detail-book note-detail-component">
|
||||
<div class="btn-group floating-button" style="right: 20px; top: 20px;">
|
||||
<button type="button"
|
||||
class="expand-children-button btn icon-button jam jam-arrows-v"
|
||||
title="Expand all children"></button>
|
||||
|
||||
<button type="button"
|
||||
class="book-zoom-in-button btn icon-button jam jam-search-plus"
|
||||
title="Zoom In"></button>
|
||||
|
||||
<button type="button"
|
||||
class="book-zoom-out-button btn icon-button jam jam-search-minus"
|
||||
title="Zoom Out"></button>
|
||||
</div>
|
||||
|
||||
<div class="note-detail-book-content"></div>
|
||||
</div>
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="export-subtree-format" id="export-subtree-format-html"
|
||||
value="html">
|
||||
<label class="form-check-label" for="export-subtree-format-html">HTML in TAR archiv - this is recommended since this preserves all the formatting.</label>
|
||||
<label class="form-check-label" for="export-subtree-format-html">HTML in TAR archive - this is recommended since this preserves all the formatting.</label>
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
</div>
|
||||
<form id="import-form">
|
||||
<div class="modal-body">
|
||||
<div id="import-progress-count-wrapper" class="alert alert-primary" style="padding: 15px;">
|
||||
<strong>Note import progress count:</strong> <span id="import-progress-count"></span>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="import-file-upload-input"><strong>Choose import file</strong></label>
|
||||
|
||||
|
||||
@@ -22,15 +22,12 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-change-password">Change password</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-protected-session">Protected session</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-note-revisions">Note revisions</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-sync-setup">Sync</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-other">Other</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#options-advanced">Advanced</a>
|
||||
</li>
|
||||
@@ -41,8 +38,7 @@
|
||||
<% include options/sidebar.ejs %>
|
||||
<% include options/code_notes.ejs %>
|
||||
<% include options/change_password.ejs %>
|
||||
<% include options/protected_session.ejs %>
|
||||
<% include options/note_revisions.ejs %>
|
||||
<% include options/other.ejs %>
|
||||
<% include options/sync.ejs %>
|
||||
<% include options/advanced.ejs %>
|
||||
</div>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<div id="options-note-revisions" class="tab-pane">
|
||||
<h4>Note revisions snapshot interval</h4>
|
||||
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note.</p>
|
||||
|
||||
<form id="note-revision-snapshot-time-interval-form">
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
|
||||
<button class="btn btn-secondary" type="button" data-help-page="Note-revisions">Help</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
44
src/views/dialogs/options/other.ejs
Normal file
44
src/views/dialogs/options/other.ejs
Normal file
@@ -0,0 +1,44 @@
|
||||
<div id="options-other" class="tab-pane">
|
||||
<div>
|
||||
<h4>Spell check</h4>
|
||||
|
||||
<p>These options apply only for desktop builds, browsers will use their own native spell check.</p>
|
||||
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input type="checkbox" class="custom-control-input" id="spell-check-enabled">
|
||||
<label class="custom-control-label" for="spell-check-enabled">Enable spellcheck</label>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="spell-check-language-code">Language code</label>
|
||||
<input type="email" class="form-control" id="spell-check-language-code" placeholder="for example "en-US", "de-AT"">
|
||||
</div>
|
||||
|
||||
<p>Changes to the spell check options will take effect after application restart.</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Protected session timeout</h4>
|
||||
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes. See <a href="https://github.com/zadam/trilium/wiki/Protected-notes" class="external">wiki</a> for more info.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4>Note revisions snapshot interval</h4>
|
||||
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note. See <a href="https://github.com/zadam/trilium/wiki/Note-revisions" class="external">wiki</a> for more info.</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,19 +0,0 @@
|
||||
<div id="options-protected-session" class="tab-pane">
|
||||
<h4>Protected session timeout</h4>
|
||||
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes.</p>
|
||||
|
||||
<form id="protected-session-timeout-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-primary">Save</button>
|
||||
|
||||
<button class="btn btn-secondary" type="button" data-help-page="Protected-notes">Help</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<% include details/protected_session_password.ejs %>
|
||||
|
||||
<div class="children-overview hide-toggle"></div>
|
||||
<% include details/book.ejs %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user