mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
Merge branch 'stable' into next61
# Conflicts: # src/etapi/etapi.openapi.yaml # src/etapi/notes.js # src/public/app/widgets/type_widgets/editable_text.js # src/services/app_info.js
This commit is contained in:
commit
995f1c9fc4
1
db/migrations/0214__fix_root_children_ordering.sql
Normal file
1
db/migrations/0214__fix_root_children_ordering.sql
Normal file
@ -0,0 +1 @@
|
||||
UPDATE branches SET notePosition = notePosition - 999899999 WHERE parentNoteId = 'root' AND notePosition > 999999999;
|
@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.60.2-beta",
|
||||
"version": "0.60.4",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
|
@ -33,13 +33,7 @@ paths:
|
||||
content:
|
||||
application/json; charset=utf-8:
|
||||
schema:
|
||||
properties:
|
||||
note:
|
||||
$ref: '#/components/schemas/Note'
|
||||
description: Created note
|
||||
branch:
|
||||
$ref: '#/components/schemas/Branch'
|
||||
description: Created branch
|
||||
$ref: '#/components/schemas/NoteWithBranch'
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
@ -291,6 +285,29 @@ paths:
|
||||
application/json; charset=utf-8:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/notes/{noteId}/import:
|
||||
parameters:
|
||||
- name: noteId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/components/schemas/EntityId'
|
||||
post:
|
||||
description: Imports ZIP file into a given note.
|
||||
operationId: importZip
|
||||
responses:
|
||||
'201':
|
||||
description: note created
|
||||
content:
|
||||
application/json; charset=utf-8:
|
||||
schema:
|
||||
$ref: '#/components/schemas/NoteWithBranch'
|
||||
default:
|
||||
description: unexpected error
|
||||
content:
|
||||
application/json; charset=utf-8:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
/notes/{noteId}/revision:
|
||||
parameters:
|
||||
- name: noteId
|
||||
@ -855,6 +872,13 @@ components:
|
||||
utcDateModified:
|
||||
$ref: '#/components/schemas/UtcDateTime'
|
||||
readOnly: true
|
||||
NoteWithBranch:
|
||||
type: object
|
||||
properties:
|
||||
note:
|
||||
$ref: '#/components/schemas/Note'
|
||||
branch:
|
||||
$ref: '#/components/schemas/Branch'
|
||||
Attribute:
|
||||
type: object
|
||||
description: Attribute (Label, Relation) is a key-value record attached to a note.
|
||||
|
@ -8,6 +8,7 @@ const v = require("./validators");
|
||||
const searchService = require("../services/search/services/search");
|
||||
const SearchContext = require("../services/search/search_context");
|
||||
const zipExportService = require("../services/export/zip");
|
||||
const zipImportService = require("../services/import/zip");
|
||||
|
||||
function register(router) {
|
||||
eu.route(router, 'get', '/etapi/notes', (req, res, next) => {
|
||||
@ -151,6 +152,18 @@ function register(router) {
|
||||
zipExportService.exportToZip(taskContext, branch, format, res);
|
||||
});
|
||||
|
||||
eu.route(router, 'post' ,'/etapi/notes/:noteId/import', (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
const taskContext = new TaskContext('no-progress-reporting');
|
||||
|
||||
zipImportService.importZip(taskContext, req.body, note).then(importedNote => {
|
||||
res.status(201).json({
|
||||
note: mappers.mapNoteToPojo(importedNote),
|
||||
branch: mappers.mapBranchToPojo(importedNote.getBranches()[0]),
|
||||
});
|
||||
}); // we need better error handling here, async errors won't be properly processed.
|
||||
});
|
||||
|
||||
eu.route(router, 'post' ,'/etapi/notes/:noteId/revision', (req, res, next) => {
|
||||
const note = eu.getAndCheckNote(req.params.noteId);
|
||||
|
||||
|
@ -212,6 +212,15 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
async runActiveNoteCommand(params) {
|
||||
if (this.isNoteContext(params.ntxId)) {
|
||||
// make sure that script is saved before running it #4028
|
||||
await this.spacedUpdate.updateNowIfNecessary();
|
||||
}
|
||||
|
||||
return await this.parent.triggerCommand('runActiveNote', params);
|
||||
}
|
||||
|
||||
async printActiveNoteEvent() {
|
||||
if (!this.noteContext.isActive()) {
|
||||
return;
|
||||
|
@ -93,11 +93,11 @@ export default class NoteIconWidget extends NoteContextAwareWidget {
|
||||
});
|
||||
|
||||
this.$iconCategory = this.$widget.find("select[name='icon-category']");
|
||||
this.$iconCategory.on('change', () => this.renderFilteredDropdown());
|
||||
this.$iconCategory.on('change', () => this.renderDropdown());
|
||||
this.$iconCategory.on('click', e => e.stopPropagation());
|
||||
|
||||
this.$iconSearch = this.$widget.find("input[name='icon-search']");
|
||||
this.$iconSearch.on('input', () => this.renderFilteredDropdown());
|
||||
this.$iconSearch.on('input', () => this.renderDropdown());
|
||||
|
||||
this.$notePathList = this.$widget.find(".note-path-list");
|
||||
this.$widget.on('show.bs.dropdown', async () => {
|
||||
@ -140,15 +140,9 @@ export default class NoteIconWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
renderFilteredDropdown() {
|
||||
const categoryId = parseInt(this.$iconCategory.find('option:selected').val());
|
||||
const search = this.$iconSearch.val();
|
||||
|
||||
this.renderDropdown(categoryId, search);
|
||||
}
|
||||
|
||||
async renderDropdown(categoryId, search) {
|
||||
const iconToCountPromise = this.getIconToCountMap();
|
||||
async renderDropdown() {
|
||||
const iconToCount = await this.getIconToCountMap();
|
||||
const {icons} = (await import('./icon_list.js')).default;
|
||||
|
||||
this.$iconList.empty();
|
||||
|
||||
@ -164,9 +158,8 @@ export default class NoteIconWidget extends NoteContextAwareWidget {
|
||||
);
|
||||
}
|
||||
|
||||
const {icons} = (await import('./icon_list.js')).default;
|
||||
|
||||
search = search?.trim()?.toLowerCase();
|
||||
const categoryId = parseInt(this.$iconCategory.find('option:selected').val());
|
||||
const search = this.$iconSearch.val().trim().toLowerCase();
|
||||
|
||||
const filteredIcons = icons.filter(icon => {
|
||||
if (categoryId && icon.category_id !== categoryId) {
|
||||
@ -182,8 +175,6 @@ export default class NoteIconWidget extends NoteContextAwareWidget {
|
||||
return true;
|
||||
});
|
||||
|
||||
const iconToCount = await iconToCountPromise;
|
||||
|
||||
filteredIcons.sort((a, b) => {
|
||||
const countA = iconToCount[a.className] || 0;
|
||||
const countB = iconToCount[b.className] || 0;
|
||||
@ -199,9 +190,12 @@ export default class NoteIconWidget extends NoteContextAwareWidget {
|
||||
}
|
||||
|
||||
async getIconToCountMap() {
|
||||
const {iconClassToCountMap} = await server.get('other/icon-usage');
|
||||
if (!this.iconToCountCache) {
|
||||
this.iconToCountCache = server.get('other/icon-usage');
|
||||
setTimeout(() => this.iconToCountCache = null, 20000); // invalidate cache after 20 seconds
|
||||
}
|
||||
|
||||
return iconClassToCountMap;
|
||||
return (await this.iconToCountCache).iconClassToCountMap;
|
||||
}
|
||||
|
||||
renderIcon(icon) {
|
||||
|
@ -185,14 +185,8 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
async doRefresh(note) {
|
||||
const blob = await note.getBlob();
|
||||
|
||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||
// https://github.com/zadam/trilium/issues/3914
|
||||
// todo: quite hacky, but it works. remove it if ckeditor has fixed it.
|
||||
this.$editor.trigger('focus');
|
||||
this.$editor.trigger('blur');
|
||||
|
||||
this.watchdog.editor.setData(blob.content || "");
|
||||
});
|
||||
await this.spacedUpdate.allowUpdateWithoutChange(() =>
|
||||
this.watchdog.editor.setData(blob.content || ""));
|
||||
}
|
||||
|
||||
getData() {
|
||||
|
@ -4,7 +4,7 @@ const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||
|
||||
const APP_DB_VERSION = 221;
|
||||
const APP_DB_VERSION = 222;
|
||||
const SYNC_VERSION = 30;
|
||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||
|
||||
|
@ -1 +1 @@
|
||||
module.exports = { buildDate:"2023-06-08T22:46:52+02:00", buildRevision: "6e69cafe5419e8efcc6f652647f9227dbcfa1e18" };
|
||||
module.exports = { buildDate:"2023-06-19T23:26:50+02:00", buildRevision: "5905950c17791ce0eb278e010c2c8b3450fdb447" };
|
||||
|
@ -27,11 +27,13 @@ const ws = require("./ws");
|
||||
function getNewNotePosition(parentNote) {
|
||||
if (parentNote.isLabelTruthy('newNotesOnTop')) {
|
||||
const minNotePos = parentNote.getChildBranches()
|
||||
.filter(branch => branch.noteId !== '_hidden') // has "always last" note position
|
||||
.reduce((min, note) => Math.min(min, note.notePosition), 0);
|
||||
|
||||
return minNotePos - 10;
|
||||
} else {
|
||||
const maxNotePos = parentNote.getChildBranches()
|
||||
.filter(branch => branch.noteId !== '_hidden') // has "always last" note position
|
||||
.reduce((max, note) => Math.max(max, note.notePosition), 0);
|
||||
|
||||
return maxNotePos + 10;
|
||||
|
@ -6,7 +6,7 @@ const ws = require('./ws');
|
||||
const taskContexts = {};
|
||||
|
||||
class TaskContext {
|
||||
constructor(taskId, taskType = null, data = null) {
|
||||
constructor(taskId, taskType = null, data = {}) {
|
||||
this.taskId = taskId;
|
||||
this.taskType = taskType;
|
||||
this.data = data;
|
||||
|
12
test-etapi/import-zip.http
Normal file
12
test-etapi/import-zip.http
Normal file
@ -0,0 +1,12 @@
|
||||
POST {{triliumHost}}/etapi/notes/root/import
|
||||
Authorization: {{authToken}}
|
||||
Content-Type: application/octet-stream
|
||||
Content-Transfer-Encoding: binary
|
||||
|
||||
< ../db/demo.zip
|
||||
|
||||
> {%
|
||||
client.assert(response.status === 201);
|
||||
client.assert(response.body.note.title == "Trilium Demo");
|
||||
client.assert(response.body.branch.parentNoteId == "root");
|
||||
%}
|
Loading…
x
Reference in New Issue
Block a user