diff --git a/db/demo.zip b/db/demo.zip index ce0297825..f80ce3cc6 100644 Binary files a/db/demo.zip and b/db/demo.zip differ diff --git a/src/etapi/attributes.js b/src/etapi/attributes.js index 4b5edcc89..74d3dbfa9 100644 --- a/src/etapi/attributes.js +++ b/src/etapi/attributes.js @@ -19,20 +19,20 @@ function register(router) { 'value': [v.notNull, v.isString], 'isInheritable': [v.notNull, v.isBoolean] }; - + eu.route(router, 'post' ,'/etapi/attributes', (req, res, next) => { if (req.body.type === 'relation') { eu.getAndCheckNote(req.body.value); } - + const params = {}; - + eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_ATTRIBUTE); try { const attr = attributeService.createAttribute(params); - res.json(mappers.mapAttributeToPojo(attr)); + res.status(201).json(mappers.mapAttributeToPojo(attr)); } catch (e) { throw new eu.EtapiError(500, eu.GENERIC_CODE, e.message); @@ -49,9 +49,9 @@ function register(router) { if (attribute.type === 'relation') { eu.getAndCheckNote(req.body.value); } - + eu.validateAndPatch(attribute, req.body, ALLOWED_PROPERTIES_FOR_PATCH); - + attribute.save(); res.json(mappers.mapAttributeToPojo(attribute)); diff --git a/src/etapi/auth.js b/src/etapi/auth.js index 372bdfe60..c83369ea6 100644 --- a/src/etapi/auth.js +++ b/src/etapi/auth.js @@ -12,8 +12,8 @@ function register(router) { } const {authToken} = etapiTokenService.createToken(tokenName || "ETAPI login"); - - res.json({ + + res.status(201).json({ authToken }); }); @@ -26,18 +26,18 @@ function register(router) { } const etapiToken = becca.getEtapiToken(parsed.etapiTokenId); - + if (!etapiToken) { // shouldn't happen since this already passed auth validation throw new Error(`Cannot find the token ${parsed.etapiTokenId}.`); } - + etapiToken.markAsDeletedSimple(); - + res.sendStatus(204); }); } module.exports = { register -} \ No newline at end of file +} diff --git a/src/etapi/branches.js b/src/etapi/branches.js index 589165478..71117e339 100644 --- a/src/etapi/branches.js +++ b/src/etapi/branches.js @@ -22,10 +22,10 @@ function register(router) { 'prefix': [v.isString], 'isExpanded': [v.notNull, v.isBoolean] }; - + eu.route(router, 'post' ,'/etapi/branches', (req, res, next) => { const params = {}; - + eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_BRANCH); const existing = becca.getBranchFromChildAndParent(params.noteId, params.parentNoteId); @@ -33,15 +33,16 @@ function register(router) { if (existing) { existing.notePosition = params.notePosition; existing.prefix = params.prefix; + existing.isExpanded = params.isExpanded; existing.save(); - return res.json(mappers.mapBranchToPojo(existing)); + return res.status(200).json(mappers.mapBranchToPojo(existing)); } try { const branch = new Branch(params).save(); - res.json(mappers.mapBranchToPojo(branch)); + res.status(201).json(mappers.mapBranchToPojo(branch)); } catch (e) { throw new eu.EtapiError(400, eu.GENERIC_CODE, e.message); diff --git a/src/etapi/etapi.openapi.yaml b/src/etapi/etapi.openapi.yaml index 7cdba426f..3877bc03a 100644 --- a/src/etapi/etapi.openapi.yaml +++ b/src/etapi/etapi.openapi.yaml @@ -27,7 +27,7 @@ paths: schema: $ref: '#/components/schemas/CreateNoteDef' responses: - '200': + '201': description: note created content: application/json: @@ -56,7 +56,7 @@ paths: description: search query string as described in https://github.com/zadam/trilium/wiki/Search schema: type: string - examples: + examples: fulltext: summary: Fulltext search for keywords (not exact match) value: 'towers tolkien' @@ -205,7 +205,7 @@ paths: $ref: '#/components/schemas/Note' responses: '200': - description: update note + description: note updated content: application/json: schema: @@ -252,7 +252,10 @@ paths: schema: $ref: '#/components/schemas/Error' post: - description: create a branch (clone a note to a different location in the tree) + description: > + Create a branch (clone a note to a different location in the tree). + In case there is a branch between parent note and child note already, + then this will update the existing branch with prefix, notePosition and isExpanded. operationId: postBranch requestBody: required: true @@ -262,11 +265,17 @@ paths: $ref: '#/components/schemas/Branch' responses: '200': - description: update branch + description: branch updated (branch between parent note and child note already existed) content: application/json: schema: - $ref: '#/components/schemas/Note' + $ref: '#/components/schemas/Branch' + '201': + description: branch created + content: + application/json: + schema: + $ref: '#/components/schemas/Branch' default: description: unexpected error content: @@ -284,11 +293,11 @@ paths: $ref: '#/components/schemas/Branch' responses: '200': - description: update branch + description: branch updated content: application/json: schema: - $ref: '#/components/schemas/Note' + $ref: '#/components/schemas/Branch' default: description: unexpected error content: @@ -342,8 +351,8 @@ paths: schema: $ref: '#/components/schemas/Attribute' responses: - '200': - description: update attribute + '201': + description: attribute created content: application/json: schema: @@ -365,7 +374,7 @@ paths: $ref: '#/components/schemas/Attribute' responses: '200': - description: update attribute + description: attribute updated content: application/json: schema: @@ -421,7 +430,7 @@ paths: in: path required: true schema: - type: string + type: string format: date example: 2022-02-22 responses: @@ -547,17 +556,17 @@ paths: content: application/json: schema: - properties: + properties: password: type: string description: user's password used to e.g. login to Trilium server and/or protect notes responses: - '200': + '201': description: auth token content: application/json: schema: - properties: + properties: authToken: type: string example: Bc4bFn0Ffiok_4NpbVCDnFz7B2WU+pdhW8B5Ne3DiR5wXrEyqdjgRIsk= @@ -602,7 +611,7 @@ components: type: string type: type: string - enum: + enum: - text - code - file diff --git a/src/etapi/notes.js b/src/etapi/notes.js index 1aa66d135..f5110d646 100644 --- a/src/etapi/notes.js +++ b/src/etapi/notes.js @@ -15,21 +15,21 @@ function register(router) { if (!search?.trim()) { throw new eu.EtapiError(400, 'SEARCH_QUERY_PARAM_MANDATORY', "'search' query parameter is mandatory"); } - + const searchParams = parseSearchParams(req); const searchContext = new SearchContext(searchParams); - + const searchResults = searchService.findResultsWithQuery(search, searchContext); const foundNotes = searchResults.map(sr => becca.notes[sr.noteId]); - + const resp = { results: foundNotes.map(note => mappers.mapNoteToPojo(note)) }; - + if (searchContext.debugInfo) { resp.debugInfo = searchContext.debugInfo; } - + res.json(resp); }); @@ -51,16 +51,16 @@ function register(router) { 'noteId': [v.notNull, v.isValidEntityId], 'branchId': [v.notNull, v.isValidEntityId], }; - + eu.route(router, 'post' ,'/etapi/create-note', (req, res, next) => { const params = {}; - + eu.validateAndPatch(params, req.body, ALLOWED_PROPERTIES_FOR_CREATE_NOTE); try { const resp = noteService.createNewNote(params); - res.json({ + res.status(201).json({ note: mappers.mapNoteToPojo(resp.note), branch: mappers.mapBranchToPojo(resp.branch) }); diff --git a/src/public/app/services/note_context.js b/src/public/app/services/note_context.js index 7d1c9bf3f..2b7e71fa3 100644 --- a/src/public/app/services/note_context.js +++ b/src/public/app/services/note_context.js @@ -218,9 +218,10 @@ class NoteContext extends Component { } } } - + hasNoteList() { - return this.note.hasChildren() + return this.note + && this.note.hasChildren() && ['book', 'text', 'code'].includes(this.note.type) && this.note.mime !== 'text/x-sqlite;schema=trilium' && !this.note.hasLabel('hideChildrenOverview'); diff --git a/test-etapi/_login.http b/test-etapi/_login.http index 1af4bc2de..9976e7cd4 100644 --- a/test-etapi/_login.http +++ b/test-etapi/_login.http @@ -6,7 +6,7 @@ Content-Type: application/json } > {% - client.assert(response.status === 200); - + client.assert(response.status === 201); + client.global.set("authToken", response.body.authToken); -%} \ No newline at end of file +%} diff --git a/test-etapi/create-entities.http b/test-etapi/create-entities.http index a01555a9e..41f321e02 100644 --- a/test-etapi/create-entities.http +++ b/test-etapi/create-entities.http @@ -11,15 +11,15 @@ Content-Type: application/json "content": "Hi there!" } -> {% - client.assert(response.status === 200); +> {% + client.assert(response.status === 201); client.assert(response.body.note.noteId.startsWith("forcedId")); client.assert(response.body.note.title == "Hello"); client.assert(response.body.branch.branchId.startsWith("forcedId")); client.assert(response.body.branch.parentNoteId == "root"); client.log(`Created note ` + response.body.note.noteId + ` and branch ` + response.body.branch.branchId); - + client.global.set("createdNoteId", response.body.note.noteId); client.global.set("createdBranchId", response.body.branch.branchId); %} @@ -37,11 +37,11 @@ Content-Type: application/json } > {% - client.assert(response.status === 200); + client.assert(response.status === 201); client.assert(response.body.parentNoteId == "hidden"); client.global.set("clonedBranchId", response.body.branchId); - + client.log(`Created cloned branch ` + response.body.branchId); %} @@ -107,9 +107,9 @@ Authorization: {{authToken}} } > {% - client.assert(response.status === 200); + client.assert(response.status === 201); client.assert(response.body.attributeId.startsWith("forcedAttributeId")); - + client.global.set("createdAttributeId", response.body.attributeId); %} @@ -121,4 +121,4 @@ Authorization: {{authToken}} > {% client.assert(response.status === 200); client.assert(response.body.attributeId == client.global.get("createdAttributeId")); -%} \ No newline at end of file +%} diff --git a/test-etapi/logout.http b/test-etapi/logout.http index 8aa54ac21..9bd7355e0 100644 --- a/test-etapi/logout.http +++ b/test-etapi/logout.http @@ -6,8 +6,8 @@ Content-Type: application/json } > {% - client.assert(response.status === 200); - + client.assert(response.status === 201); + client.global.set("testAuthToken", response.body.authToken); %} @@ -31,4 +31,4 @@ Content-Type: application/json GET {{triliumHost}}/etapi/notes/root Authorization: {{testAuthToken}} -> {% client.assert(response.status === 401); %} \ No newline at end of file +> {% client.assert(response.status === 401); %}