mirror of
https://github.com/zadam/trilium.git
synced 2025-10-30 01:36:24 +01:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21e77c83fc | ||
|
|
b0310e34e2 | ||
|
|
761c51069a | ||
|
|
4dc285d84f | ||
|
|
a1402c7c66 | ||
|
|
6ba3e5ab7f | ||
|
|
f740e52ebf | ||
|
|
e9454e4db7 | ||
|
|
bfc7570e14 | ||
|
|
5de92171a7 | ||
|
|
29c5e394ab | ||
|
|
07b3d11fe5 | ||
|
|
67663fba50 | ||
|
|
995ebbf577 | ||
|
|
d0e6be3e0c | ||
|
|
01370a5968 |
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.37.5",
|
"version": "0.37.7",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"productName": "Trilium Notes",
|
"productName": "Trilium Notes",
|
||||||
"description": "Trilium Notes",
|
"description": "Trilium Notes",
|
||||||
"version": "0.37.6",
|
"version": "0.37.8",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"main": "electron.js",
|
"main": "electron.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -334,6 +334,11 @@ class Note extends Entity {
|
|||||||
// we order by noteId so that attributes from same note stay together. Actual noteId ordering doesn't matter.
|
// we order by noteId so that attributes from same note stay together. Actual noteId ordering doesn't matter.
|
||||||
|
|
||||||
const filteredAttributes = attributes.filter((attr, index) => {
|
const filteredAttributes = attributes.filter((attr, index) => {
|
||||||
|
// if this exact attribute already appears then don't include it (can happen via cloning)
|
||||||
|
if (attributes.findIndex(it => it.attributeId === attr.attributeId) !== index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (attr.isDefinition()) {
|
if (attr.isDefinition()) {
|
||||||
const firstDefinitionIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name);
|
const firstDefinitionIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name);
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (const appCssNoteId of window.appCssNoteIds) {
|
for (const appCssNoteId of window.appCssNoteIds) {
|
||||||
cssLoader.requireCss(`/api/notes/download/${appCssNoteId}`);
|
cssLoader.requireCss(`api/notes/download/${appCssNoteId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const wikiBaseUrl = "https://github.com/zadam/trilium/wiki/";
|
const wikiBaseUrl = "https://github.com/zadam/trilium/wiki/";
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ export default class ApperanceOptions {
|
|||||||
if (noteId) {
|
if (noteId) {
|
||||||
// make sure the CSS is loaded
|
// make sure the CSS is loaded
|
||||||
// if the CSS has been loaded and then updated then the changes won't take effect though
|
// if the CSS has been loaded and then updated then the changes won't take effect though
|
||||||
cssLoader.requireCss(`/api/notes/download/${noteId}`);
|
cssLoader.requireCss(`api/notes/download/${noteId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$body.addClass("theme-" + newTheme);
|
this.$body.addClass("theme-" + newTheme);
|
||||||
|
|||||||
@@ -411,6 +411,10 @@ div.ui-tooltip {
|
|||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sql-console-query .CodeMirror-scroll {
|
||||||
|
min-height: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
border-radius: var(--button-border-radius);
|
border-radius: var(--button-border-radius);
|
||||||
}
|
}
|
||||||
@@ -460,9 +464,10 @@ button.icon-button {
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
/* setting the display to block since "table" doesn't support scrolling */
|
/* setting the display to block since "table" doesn't support scrolling */
|
||||||
display: block;
|
display: block;
|
||||||
flex-basis: content;
|
/** flex-basis: content; - use once "content" is implemented by chrome */
|
||||||
flex-shrink: 1;
|
flex-shrink: 0;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
max-height: 30%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ async function anonymize() {
|
|||||||
|
|
||||||
await db.run("UPDATE notes SET title = 'title'");
|
await db.run("UPDATE notes SET title = 'title'");
|
||||||
await db.run("UPDATE note_contents SET content = 'text'");
|
await db.run("UPDATE note_contents SET content = 'text'");
|
||||||
await db.run("UPDATE note_revisions SET title = 'title', content = 'text'");
|
await db.run("UPDATE note_revisions SET title = 'title'");
|
||||||
|
await db.run("UPDATE note_revision_contents SET content = 'title'");
|
||||||
|
await db.run("UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label'");
|
||||||
|
await db.run("UPDATE attributes SET name = 'name' WHERE type = 'relation'");
|
||||||
await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");
|
await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");
|
||||||
await db.run(`UPDATE options SET value = 'anonymized' WHERE name IN
|
await db.run(`UPDATE options SET value = 'anonymized' WHERE name IN
|
||||||
('documentSecret', 'encryptedDataKey', 'passwordVerificationHash',
|
('documentSecret', 'encryptedDataKey', 'passwordVerificationHash',
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2019-11-26T22:50:08+01:00", buildRevision: "5193f073e9e55f5440fe2e71fbd2cdfcdb2d2c6b" };
|
module.exports = { buildDate:"2019-12-03T22:31:20+01:00", buildRevision: "b0310e34e2c6f023cc8190310ff63d840157f6cc" };
|
||||||
|
|||||||
@@ -626,12 +626,31 @@ async function runAllChecks() {
|
|||||||
return !unrecoveredConsistencyErrors;
|
return !unrecoveredConsistencyErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function showEntityStat(name, query) {
|
||||||
|
const map = await sql.getMap(query);
|
||||||
|
|
||||||
|
map[0] = map[0] || 0;
|
||||||
|
map[1] = map[1] || 0;
|
||||||
|
|
||||||
|
log.info(`${name} deleted: ${map[1]}, not deleted ${map[0]}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runDbDiagnostics() {
|
||||||
|
await showEntityStat("Notes", `SELECT isDeleted, count(noteId) FROM notes GROUP BY isDeleted`);
|
||||||
|
await showEntityStat("Note revisions", `SELECT isErased, count(noteRevisionId) FROM note_revisions GROUP BY isErased`);
|
||||||
|
await showEntityStat("Branches", `SELECT isDeleted, count(branchId) FROM branches GROUP BY isDeleted`);
|
||||||
|
await showEntityStat("Attributes", `SELECT isDeleted, count(attributeId) FROM attributes GROUP BY isDeleted`);
|
||||||
|
await showEntityStat("API tokens", `SELECT isDeleted, count(apiTokenId) FROM api_tokens GROUP BY isDeleted`);
|
||||||
|
}
|
||||||
|
|
||||||
async function runChecks() {
|
async function runChecks() {
|
||||||
let elapsedTimeMs;
|
let elapsedTimeMs;
|
||||||
|
|
||||||
await syncMutexService.doExclusively(async () => {
|
await syncMutexService.doExclusively(async () => {
|
||||||
const startTime = new Date();
|
const startTime = new Date();
|
||||||
|
|
||||||
|
await runDbDiagnostics();
|
||||||
|
|
||||||
await runAllChecks();
|
await runAllChecks();
|
||||||
|
|
||||||
elapsedTimeMs = Date.now() - startTime.getTime();
|
elapsedTimeMs = Date.now() - startTime.getTime();
|
||||||
@@ -663,7 +682,7 @@ sqlInit.dbReady.then(() => {
|
|||||||
setInterval(cls.wrap(runChecks), 60 * 60 * 1000);
|
setInterval(cls.wrap(runChecks), 60 * 60 * 1000);
|
||||||
|
|
||||||
// kickoff checks soon after startup (to not block the initial load)
|
// kickoff checks soon after startup (to not block the initial load)
|
||||||
setTimeout(cls.wrap(runChecks), 10 * 1000);
|
setTimeout(cls.wrap(runChecks), 20 * 1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = {};
|
module.exports = {};
|
||||||
@@ -81,7 +81,7 @@ eventService.subscribe(eventService.CHILD_NOTE_CREATED, async ({ parentNote, chi
|
|||||||
async function processInverseRelations(entityName, entity, handler) {
|
async function processInverseRelations(entityName, entity, handler) {
|
||||||
if (entityName === 'attributes' && entity.type === 'relation') {
|
if (entityName === 'attributes' && entity.type === 'relation') {
|
||||||
const note = await entity.getNote();
|
const note = await entity.getNote();
|
||||||
const attributes = (await note.getAttributes(entity.name)).filter(relation => relation.type === 'relation-definition');
|
const attributes = (await note.getOwnedAttributes(entity.name)).filter(relation => relation.type === 'relation-definition');
|
||||||
|
|
||||||
for (const attribute of attributes) {
|
for (const attribute of attributes) {
|
||||||
const definition = attribute.value;
|
const definition = attribute.value;
|
||||||
|
|||||||
@@ -12,9 +12,7 @@ const imageminGifLossy = require('imagemin-giflossy');
|
|||||||
const jimp = require('jimp');
|
const jimp = require('jimp');
|
||||||
const imageType = require('image-type');
|
const imageType = require('image-type');
|
||||||
const sanitizeFilename = require('sanitize-filename');
|
const sanitizeFilename = require('sanitize-filename');
|
||||||
const dateUtils = require('./date_utils');
|
|
||||||
const noteRevisionService = require('./note_revisions.js');
|
const noteRevisionService = require('./note_revisions.js');
|
||||||
const NoteRevision = require("../entities/note_revision");
|
|
||||||
|
|
||||||
async function processImage(uploadBuffer, originalName, shrinkImageSwitch) {
|
async function processImage(uploadBuffer, originalName, shrinkImageSwitch) {
|
||||||
const origImageFormat = imageType(uploadBuffer);
|
const origImageFormat = imageType(uploadBuffer);
|
||||||
|
|||||||
@@ -258,7 +258,8 @@ async function importTar(taskContext, fileBuffer, importRootNote) {
|
|||||||
content = content.toString("UTF-8");
|
content = content.toString("UTF-8");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((noteMeta && noteMeta.format === 'markdown') || (!noteMeta && ['text/markdown', 'text/x-markdown'].includes(mime))) {
|
if ((noteMeta && noteMeta.format === 'markdown')
|
||||||
|
|| (!noteMeta && taskContext.data.textImportedAsText && ['text/markdown', 'text/x-markdown'].includes(mime))) {
|
||||||
const parsed = mdReader.parse(content);
|
const parsed = mdReader.parse(content);
|
||||||
content = mdWriter.render(parsed);
|
content = mdWriter.render(parsed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,9 +43,6 @@ async function migrate() {
|
|||||||
try {
|
try {
|
||||||
log.info("Attempting migration to version " + mig.dbVersion);
|
log.info("Attempting migration to version " + mig.dbVersion);
|
||||||
|
|
||||||
// needs to happen outside of the transaction (otherwise it's a NO-OP)
|
|
||||||
await sql.execute("PRAGMA foreign_keys = OFF");
|
|
||||||
|
|
||||||
await sql.transactional(async () => {
|
await sql.transactional(async () => {
|
||||||
if (mig.type === 'sql') {
|
if (mig.type === 'sql') {
|
||||||
const migrationSql = fs.readFileSync(resourceDir.MIGRATIONS_DIR + "/" + mig.file).toString('utf8');
|
const migrationSql = fs.readFileSync(resourceDir.MIGRATIONS_DIR + "/" + mig.file).toString('utf8');
|
||||||
@@ -76,10 +73,6 @@ async function migrate() {
|
|||||||
|
|
||||||
utils.crash();
|
utils.crash();
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
// make sure foreign keys are enabled even if migration script disables them
|
|
||||||
await sql.execute("PRAGMA foreign_keys = ON");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (await sqlInit.isDbUpToDate()) {
|
if (await sqlInit.isDbUpToDate()) {
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ const dateUtils = require('../services/date_utils');
|
|||||||
* @param {Note} note
|
* @param {Note} note
|
||||||
*/
|
*/
|
||||||
async function protectNoteRevisions(note) {
|
async function protectNoteRevisions(note) {
|
||||||
if (await note.hasLabel('disableVersioning')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const revision of await note.getRevisions()) {
|
for (const revision of await note.getRevisions()) {
|
||||||
if (note.isProtected !== revision.isProtected) {
|
if (note.isProtected !== revision.isProtected) {
|
||||||
const content = await revision.getContent();
|
const content = await revision.getContent();
|
||||||
@@ -30,6 +26,10 @@ async function protectNoteRevisions(note) {
|
|||||||
* @return {NoteRevision}
|
* @return {NoteRevision}
|
||||||
*/
|
*/
|
||||||
async function createNoteRevision(note) {
|
async function createNoteRevision(note) {
|
||||||
|
if (await note.hasLabel("disableVersioning")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const noteRevision = await new NoteRevision({
|
const noteRevision = await new NoteRevision({
|
||||||
noteId: note.noteId,
|
noteId: note.noteId,
|
||||||
// title and text should be decrypted now
|
// title and text should be decrypted now
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ async function createNewNote(parentNoteId, noteData) {
|
|||||||
isExpanded: !!noteData.isExpanded
|
isExpanded: !!noteData.isExpanded
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
for (const attr of await parentNote.getAttributes()) {
|
for (const attr of await parentNote.getOwnedAttributes()) {
|
||||||
if (attr.name.startsWith("child:")) {
|
if (attr.name.startsWith("child:")) {
|
||||||
await new Attribute({
|
await new Attribute({
|
||||||
noteId: note.noteId,
|
noteId: note.noteId,
|
||||||
@@ -308,8 +308,7 @@ async function saveLinks(note, content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function saveNoteRevision(note) {
|
async function saveNoteRevision(note) {
|
||||||
// files and images are immutable, they can't be updated
|
// files and images are versioned separately
|
||||||
// but we don't even version titles which is probably not correct
|
|
||||||
if (note.type === 'file' || note.type === 'image' || await note.hasLabel('disableVersioning')) {
|
if (note.type === 'file' || note.type === 'image' || await note.hasLabel('disableVersioning')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -480,7 +479,7 @@ async function eraseDeletedNotes() {
|
|||||||
SET content = NULL,
|
SET content = NULL,
|
||||||
utcDateModified = '${utcNowDateTime}'
|
utcDateModified = '${utcNowDateTime}'
|
||||||
WHERE noteRevisionId IN
|
WHERE noteRevisionId IN
|
||||||
(SELECT noteRevisionId FROM note_revisions WHERE isErased = 0 AND noteId IN ((???)))`, noteIdsToErase);
|
(SELECT noteRevisionId FROM note_revisions WHERE isErased = 0 AND noteId IN (???))`, noteIdsToErase);
|
||||||
|
|
||||||
await sql.executeMany(`
|
await sql.executeMany(`
|
||||||
UPDATE note_revisions
|
UPDATE note_revisions
|
||||||
@@ -514,7 +513,7 @@ async function duplicateNote(noteId, parentNoteId) {
|
|||||||
notePosition: origBranch ? origBranch.notePosition + 1 : null
|
notePosition: origBranch ? origBranch.notePosition + 1 : null
|
||||||
}).save();
|
}).save();
|
||||||
|
|
||||||
for (const attribute of await origNote.getAttributes()) {
|
for (const attribute of await origNote.getOwnedAttributes()) {
|
||||||
const attr = new Attribute(attribute);
|
const attr = new Attribute(attribute);
|
||||||
attr.attributeId = undefined; // force creation of new attribute
|
attr.attributeId = undefined; // force creation of new attribute
|
||||||
attr.noteId = newNote.noteId;
|
attr.noteId = newNote.noteId;
|
||||||
|
|||||||
@@ -57,8 +57,6 @@ async function initDbConnection() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await sql.execute("PRAGMA foreign_keys = ON");
|
|
||||||
|
|
||||||
const currentDbVersion = await getDbVersion();
|
const currentDbVersion = await getDbVersion();
|
||||||
|
|
||||||
if (currentDbVersion > appInfo.dbVersion) {
|
if (currentDbVersion > appInfo.dbVersion) {
|
||||||
@@ -175,9 +173,11 @@ async function isDbUpToDate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function dbInitialized() {
|
async function dbInitialized() {
|
||||||
await optionService.setOption('initialized', 'true');
|
if (!await isDbInitialized()) {
|
||||||
|
await optionService.setOption('initialized', 'true');
|
||||||
|
|
||||||
await initDbConnection();
|
await initDbConnection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dbReady.then(async () => {
|
dbReady.then(async () => {
|
||||||
|
|||||||
@@ -1,48 +1,32 @@
|
|||||||
const fs = require('fs');
|
/**
|
||||||
const dataDir = require('../services/data_dir');
|
* Usage: node src/tools/generate_document.js 1000
|
||||||
|
* will create 1000 new notes and some clones into a current document.db
|
||||||
fs.unlinkSync(dataDir.DOCUMENT_PATH);
|
*/
|
||||||
|
|
||||||
require('../entities/entity_constructor');
|
require('../entities/entity_constructor');
|
||||||
const optionService = require('../services/options');
|
|
||||||
const sqlInit = require('../services/sql_init');
|
const sqlInit = require('../services/sql_init');
|
||||||
const myScryptService = require('../services/my_scrypt');
|
|
||||||
const passwordEncryptionService = require('../services/password_encryption');
|
|
||||||
const utils = require('../services/utils');
|
|
||||||
const noteService = require('../services/notes');
|
const noteService = require('../services/notes');
|
||||||
|
const attributeService = require('../services/attributes');
|
||||||
const cls = require('../services/cls');
|
const cls = require('../services/cls');
|
||||||
const cloningService = require('../services/cloning');
|
const cloningService = require('../services/cloning');
|
||||||
const loremIpsum = require('lorem-ipsum');
|
const loremIpsum = require('lorem-ipsum').loremIpsum;
|
||||||
|
|
||||||
async function setUserNamePassword() {
|
|
||||||
const username = "test";
|
|
||||||
const password = "test";
|
|
||||||
|
|
||||||
await optionService.setOption('username', username);
|
|
||||||
|
|
||||||
await optionService.setOption('passwordVerificationSalt', utils.randomSecureToken(32));
|
|
||||||
await optionService.setOption('passwordDerivedKeySalt', utils.randomSecureToken(32));
|
|
||||||
|
|
||||||
const passwordVerificationKey = utils.toBase64(await myScryptService.getVerificationHash(password));
|
|
||||||
await optionService.setOption('passwordVerificationHash', passwordVerificationKey);
|
|
||||||
|
|
||||||
await passwordEncryptionService.setDataKey(password, utils.randomSecureToken(16));
|
|
||||||
|
|
||||||
await sqlInit.initDbConnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
const noteCount = parseInt(process.argv[2]);
|
const noteCount = parseInt(process.argv[2]);
|
||||||
|
|
||||||
|
if (!noteCount) {
|
||||||
|
console.error(`Please enter number of notes as program parameter.`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
const notes = ['root'];
|
const notes = ['root'];
|
||||||
|
|
||||||
function getRandomParentNoteId() {
|
function getRandomNoteId() {
|
||||||
const index = Math.floor(Math.random() * notes.length);
|
const index = Math.floor(Math.random() * notes.length);
|
||||||
|
|
||||||
return notes[index];
|
return notes[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function start() {
|
async function start() {
|
||||||
await setUserNamePassword();
|
|
||||||
|
|
||||||
for (let i = 0; i < noteCount; i++) {
|
for (let i = 0; i < noteCount; i++) {
|
||||||
const title = loremIpsum({ count: 1, units: 'sentences', sentenceLowerBound: 1, sentenceUpperBound: 10 });
|
const title = loremIpsum({ count: 1, units: 'sentences', sentenceLowerBound: 1, sentenceUpperBound: 10 });
|
||||||
|
|
||||||
@@ -50,17 +34,17 @@ async function start() {
|
|||||||
const content = loremIpsum({ count: paragraphCount, units: 'paragraphs', sentenceLowerBound: 1, sentenceUpperBound: 15,
|
const content = loremIpsum({ count: paragraphCount, units: 'paragraphs', sentenceLowerBound: 1, sentenceUpperBound: 15,
|
||||||
paragraphLowerBound: 3, paragraphUpperBound: 10, format: 'html' });
|
paragraphLowerBound: 3, paragraphUpperBound: 10, format: 'html' });
|
||||||
|
|
||||||
const {note} = await noteService.createNote(getRandomParentNoteId(), title, content);
|
const {note} = await noteService.createNote(getRandomNoteId(), title, content);
|
||||||
|
|
||||||
console.log(`Created note ${i}: ${title}`);
|
console.log(`Created note ${i}: ${title}`);
|
||||||
|
|
||||||
notes.push(note.noteId);
|
notes.push(note.noteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we'll create clones for 20% of notes
|
// we'll create clones for 4% of notes
|
||||||
for (let i = 0; i < (noteCount / 50); i++) {
|
for (let i = 0; i < (noteCount / 25); i++) {
|
||||||
const noteIdToClone = getRandomParentNoteId();
|
const noteIdToClone = getRandomNoteId();
|
||||||
const parentNoteId = getRandomParentNoteId();
|
const parentNoteId = getRandomNoteId();
|
||||||
const prefix = Math.random() > 0.8 ? "prefix" : null;
|
const prefix = Math.random() > 0.8 ? "prefix" : null;
|
||||||
|
|
||||||
const result = await cloningService.cloneNoteToParent(noteIdToClone, parentNoteId, prefix);
|
const result = await cloningService.cloneNoteToParent(noteIdToClone, parentNoteId, prefix);
|
||||||
@@ -68,6 +52,30 @@ async function start() {
|
|||||||
console.log(`Cloning ${i}:`, result.success ? "succeeded" : "FAILED");
|
console.log(`Cloning ${i}:`, result.success ? "succeeded" : "FAILED");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < noteCount; i++) {
|
||||||
|
await attributeService.createAttribute({
|
||||||
|
noteId: getRandomNoteId(),
|
||||||
|
type: 'label',
|
||||||
|
name: 'label',
|
||||||
|
value: 'value',
|
||||||
|
isInheritable: Math.random() > 0.1 // 10% are inheritable
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Creating label ${i}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < noteCount; i++) {
|
||||||
|
await attributeService.createAttribute({
|
||||||
|
noteId: getRandomNoteId(),
|
||||||
|
type: 'relation',
|
||||||
|
name: 'relation',
|
||||||
|
value: getRandomNoteId(),
|
||||||
|
isInheritable: Math.random() > 0.1 // 10% are inheritable
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`Creating relation ${i}`);
|
||||||
|
}
|
||||||
|
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
<link rel="shortcut icon" href="favicon.ico">
|
||||||
<title>Trilium Notes</title>
|
<title>Trilium Notes</title>
|
||||||
</head>
|
</head>
|
||||||
<body class="desktop theme-<%= theme %>" style="--main-font-size: <%= mainFontSize %>%; --tree-font-size: <%= treeFontSize %>%; --detail-font-size: <%= detailFontSize %>%;">
|
<body class="desktop theme-<%= theme %>" style="--main-font-size: <%= mainFontSize %>%; --tree-font-size: <%= treeFontSize %>%; --detail-font-size: <%= detailFontSize %>%;">
|
||||||
|
|||||||
Reference in New Issue
Block a user