2018-08-02 22:48:21 +02:00
"use strict" ;
const sql = require ( '../../services/sql' ) ;
2020-06-05 17:25:14 +02:00
const log = require ( '../../services/log' ) ;
2018-08-02 22:48:21 +02:00
const attributeService = require ( '../../services/attributes' ) ;
2021-05-17 22:09:49 +02:00
const Attribute = require ( '../../becca/entities/attribute.js' ) ;
const becca = require ( "../../becca/becca.js" ) ;
2018-08-02 22:48:21 +02:00
2020-06-20 12:31:38 +02:00
function getEffectiveNoteAttributes ( req ) {
2021-05-02 11:23:58 +02:00
const note = becca . getNote ( req . params . noteId ) ;
2018-08-07 13:33:10 +02:00
2020-06-20 12:31:38 +02:00
return note . getAttributes ( ) ;
2018-08-02 22:48:21 +02:00
}
2020-06-20 12:31:38 +02:00
function updateNoteAttribute ( req ) {
2018-08-06 14:43:42 +02:00
const noteId = req . params . noteId ;
const body = req . body ;
let attribute ;
if ( body . attributeId ) {
2021-05-02 11:23:58 +02:00
attribute = becca . getAttribute ( body . attributeId ) ;
2020-01-28 22:37:06 +01:00
if ( attribute . noteId !== noteId ) {
return [ 400 , ` Attribute ${ body . attributeId } is not owned by ${ noteId } ` ] ;
}
if ( body . type !== attribute . type
|| body . name !== attribute . name
|| ( body . type === 'relation' && body . value !== attribute . value ) ) {
2020-11-11 23:02:14 +01:00
let newAttribute ;
2020-01-28 22:37:06 +01:00
if ( body . type !== 'relation' || ! ! body . value . trim ( ) ) {
2020-11-11 23:02:14 +01:00
newAttribute = attribute . createClone ( body . type , body . name , body . value ) ;
2020-06-20 12:31:38 +02:00
newAttribute . save ( ) ;
2020-01-28 22:37:06 +01:00
}
2021-05-02 20:32:50 +02:00
attribute . markAsDeleted ( ) ;
2020-01-28 22:37:06 +01:00
return {
2020-11-11 23:02:14 +01:00
attributeId : newAttribute ? newAttribute . attributeId : null
2020-01-28 22:37:06 +01:00
} ;
}
2018-08-06 14:43:42 +02:00
}
else {
2018-11-12 23:34:22 +01:00
if ( body . type === 'relation' && ! body . value . trim ( ) ) {
return { } ;
}
2018-08-06 14:43:42 +02:00
attribute = new Attribute ( ) ;
attribute . noteId = noteId ;
attribute . name = body . name ;
attribute . type = body . type ;
}
2020-10-23 00:11:44 +02:00
if ( attribute . type === 'label' || body . value . trim ( ) ) {
2018-11-12 23:34:22 +01:00
attribute . value = body . value ;
}
else {
// relations should never have empty target
2021-05-02 20:32:50 +02:00
attribute . markAsDeleted ( ) ;
2018-11-12 23:34:22 +01:00
}
2018-08-06 14:43:42 +02:00
2020-06-20 12:31:38 +02:00
attribute . save ( ) ;
2018-08-06 17:24:35 +02:00
return {
attributeId : attribute . attributeId
} ;
}
2020-10-24 23:50:32 +02:00
function setNoteAttribute ( req ) {
const noteId = req . params . noteId ;
const body = req . body ;
2021-05-17 22:05:35 +02:00
const attributeId = sql . getValue ( ` SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = ? AND name = ? ` , [ noteId , body . type , body . name ] ) ;
2020-10-24 23:50:32 +02:00
2021-05-17 22:05:35 +02:00
if ( attributeId ) {
const attr = becca . getAttribute ( attributeId ) ;
2020-10-24 23:50:32 +02:00
attr . value = body . value ;
2021-05-17 22:05:35 +02:00
attr . save ( ) ;
2020-10-24 23:50:32 +02:00
} else {
2021-05-17 22:05:35 +02:00
const attr = new Attribute ( body ) ;
2020-10-24 23:50:32 +02:00
attr . noteId = noteId ;
2021-05-17 22:05:35 +02:00
attr . save ( ) ;
2020-10-24 23:50:32 +02:00
}
}
2021-01-17 23:01:01 +01:00
function addNoteAttribute ( req ) {
const noteId = req . params . noteId ;
const body = req . body ;
const attr = new Attribute ( body ) ;
attr . noteId = noteId ;
attr . save ( ) ;
}
2020-06-20 12:31:38 +02:00
function deleteNoteAttribute ( req ) {
2018-08-07 11:38:00 +02:00
const noteId = req . params . noteId ;
2018-08-06 17:24:35 +02:00
const attributeId = req . params . attributeId ;
2021-04-26 22:24:55 +02:00
const attribute = becca . getAttribute ( attributeId ) ;
2018-08-06 17:24:35 +02:00
if ( attribute ) {
2018-08-07 11:38:00 +02:00
if ( attribute . noteId !== noteId ) {
return [ 400 , ` Attribute ${ attributeId } is not owned by ${ noteId } ` ] ;
}
2021-05-02 20:32:50 +02:00
attribute . markAsDeleted ( ) ;
2018-08-06 17:24:35 +02:00
}
2018-08-06 14:43:42 +02:00
}
2020-07-04 10:29:17 +02:00
function updateNoteAttributes ( req ) {
2020-06-05 17:25:14 +02:00
const noteId = req . params . noteId ;
const incomingAttributes = req . body ;
2021-05-02 11:23:58 +02:00
const note = becca . getNote ( noteId ) ;
2020-06-05 17:25:14 +02:00
2020-08-12 00:02:19 +02:00
let existingAttrs = note . getOwnedAttributes ( ) ;
2020-06-05 17:25:14 +02:00
let position = 0 ;
for ( const incAttr of incomingAttributes ) {
position += 10 ;
const perfectMatchAttr = existingAttrs . find ( attr =>
attr . type === incAttr . type &&
attr . name === incAttr . name &&
attr . isInheritable === incAttr . isInheritable &&
attr . value === incAttr . value ) ;
if ( perfectMatchAttr ) {
existingAttrs = existingAttrs . filter ( attr => attr . attributeId !== perfectMatchAttr . attributeId ) ;
if ( perfectMatchAttr . position !== position ) {
perfectMatchAttr . position = position ;
2020-06-20 12:31:38 +02:00
perfectMatchAttr . save ( ) ;
2020-06-05 17:25:14 +02:00
}
continue ; // nothing to update
}
if ( incAttr . type === 'relation' ) {
2021-05-02 11:23:58 +02:00
const targetNote = becca . getNote ( incAttr . value ) ;
2020-06-05 17:25:14 +02:00
if ( ! targetNote || targetNote . isDeleted ) {
log . error ( ` Target note of relation ${ JSON . stringify ( incAttr ) } does not exist or is deleted ` ) ;
continue ;
}
}
const matchedAttr = existingAttrs . find ( attr =>
attr . type === incAttr . type &&
attr . name === incAttr . name &&
attr . isInheritable === incAttr . isInheritable ) ;
if ( matchedAttr ) {
matchedAttr . value = incAttr . value ;
matchedAttr . position = position ;
2020-06-20 12:31:38 +02:00
matchedAttr . save ( ) ;
2020-06-05 17:25:14 +02:00
existingAttrs = existingAttrs . filter ( attr => attr . attributeId !== matchedAttr . attributeId ) ;
continue ;
}
// no existing attribute has been matched so we need to create a new one
// type, name and isInheritable are immutable so even if there is an attribute with matching type & name, we need to create a new one and delete the former one
2020-06-20 12:31:38 +02:00
note . addAttribute ( incAttr . type , incAttr . name , incAttr . value , incAttr . isInheritable , position ) ;
2020-06-05 17:25:14 +02:00
}
// all the remaining existing attributes are not defined anymore and should be deleted
for ( const toDeleteAttr of existingAttrs ) {
2020-11-11 23:15:48 +01:00
if ( ! toDeleteAttr . isAutoLink ( ) ) {
2021-05-02 20:32:50 +02:00
toDeleteAttr . markAsDeleted ( ) ;
2020-11-11 23:15:48 +01:00
}
2020-06-05 17:25:14 +02:00
}
}
2020-06-20 12:31:38 +02:00
function getAttributeNames ( req ) {
2018-08-03 11:11:57 +02:00
const type = req . query . type ;
const query = req . query . query ;
2018-08-02 22:48:21 +02:00
2018-08-03 11:11:57 +02:00
return attributeService . getAttributeNames ( type , query ) ;
2018-08-02 22:48:21 +02:00
}
2020-06-20 12:31:38 +02:00
function getValuesForAttribute ( req ) {
2018-08-02 22:48:21 +02:00
const attributeName = req . params . attributeName ;
2020-06-20 12:31:38 +02:00
return sql . getColumn ( "SELECT DISTINCT value FROM attributes WHERE isDeleted = 0 AND name = ? AND type = 'label' AND value != '' ORDER BY value" , [ attributeName ] ) ;
2018-08-02 22:48:21 +02:00
}
2020-06-20 12:31:38 +02:00
function createRelation ( req ) {
2018-10-29 22:38:51 +01:00
const sourceNoteId = req . params . noteId ;
const targetNoteId = req . params . targetNoteId ;
const name = req . params . name ;
2021-05-17 22:05:35 +02:00
const attributeId = sql . getValue ( ` SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ? ` , [ sourceNoteId , name , targetNoteId ] ) ;
let attribute = becca . getAttribute ( attributeId ) ;
2018-10-29 22:38:51 +01:00
if ( ! attribute ) {
2021-05-17 22:05:35 +02:00
attribute = new Attribute ( {
noteId : sourceNoteId ,
name : name ,
type : 'relation' ,
value : targetNoteId
} ) . save ( ) ;
2018-10-29 22:38:51 +01:00
}
2018-10-30 10:36:19 +01:00
return attribute ;
}
2020-06-20 12:31:38 +02:00
function deleteRelation ( req ) {
2018-10-30 10:36:19 +01:00
const sourceNoteId = req . params . noteId ;
const targetNoteId = req . params . targetNoteId ;
const name = req . params . name ;
2021-05-17 22:05:35 +02:00
const attributeId = sql . getValue ( ` SELECT attributeId FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = 'relation' AND name = ? AND value = ? ` , [ sourceNoteId , name , targetNoteId ] ) ;
2018-10-30 10:36:19 +01:00
2021-05-17 22:05:35 +02:00
if ( attributeId ) {
const attribute = becca . getAttribute ( attributeId ) ;
2021-05-02 20:32:50 +02:00
attribute . markAsDeleted ( ) ;
2018-10-30 10:36:19 +01:00
}
2018-10-29 22:38:51 +01:00
}
2018-08-02 22:48:21 +02:00
module . exports = {
updateNoteAttributes ,
2018-08-06 14:43:42 +02:00
updateNoteAttribute ,
2020-10-24 23:50:32 +02:00
setNoteAttribute ,
2021-01-17 23:01:01 +01:00
addNoteAttribute ,
2018-08-06 17:24:35 +02:00
deleteNoteAttribute ,
2018-08-03 11:11:57 +02:00
getAttributeNames ,
2018-08-06 08:59:26 +02:00
getValuesForAttribute ,
2018-10-29 22:38:51 +01:00
getEffectiveNoteAttributes ,
2018-10-30 10:36:19 +01:00
createRelation ,
2020-06-18 22:28:18 +02:00
deleteRelation
2020-05-11 23:57:39 +02:00
} ;