Notes/docs/backend_api/becca_entities_battribute.js.html

284 lines
8.2 KiB
HTML
Raw Normal View History

2021-09-30 12:26:13 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
2023-01-03 13:54:27 +01:00
<title>JSDoc: Source: becca/entities/battribute.js</title>
2021-09-30 12:26:13 +02:00
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
2023-01-03 13:54:27 +01:00
<h1 class="page-title">Source: becca/entities/battribute.js</h1>
2021-09-30 12:26:13 +02:00
<section>
<article>
<pre class="prettyprint source linenums"><code>"use strict";
2023-01-03 13:54:27 +01:00
const BNote = require('./bnote');
const AbstractBeccaEntity = require("./abstract_becca_entity");
2022-01-10 19:54:38 +01:00
const sql = require("../../services/sql");
const dateUtils = require("../../services/date_utils");
2021-09-30 12:26:13 +02:00
const promotedAttributeDefinitionParser = require("../../services/promoted_attribute_definition_parser");
const {sanitizeAttributeName} = require("../../services/sanitize_attribute_name");
2021-09-30 12:26:13 +02:00
/**
* Attribute is an abstract concept which has two real uses - label (key - value pair)
* and relation (representing named relationship between source and target note)
2022-04-16 00:17:32 +02:00
*
2023-01-03 13:54:27 +01:00
* @extends AbstractBeccaEntity
*/
2023-01-03 13:54:27 +01:00
class BAttribute extends AbstractBeccaEntity {
2021-09-30 12:26:13 +02:00
static get entityName() { return "attributes"; }
static get primaryKeyName() { return "attributeId"; }
static get hashedProperties() { return ["attributeId", "noteId", "type", "name", "value", "isInheritable"]; }
constructor(row) {
super();
if (!row) {
return;
}
this.updateFromRow(row);
this.init();
}
updateFromRow(row) {
this.update([
row.attributeId,
row.noteId,
row.type,
row.name,
row.value,
row.isInheritable,
row.position,
row.utcDateModified
]);
}
update([attributeId, noteId, type, name, value, isInheritable, position, utcDateModified]) {
/** @type {string} */
2021-09-30 12:26:13 +02:00
this.attributeId = attributeId;
/** @type {string} */
2021-09-30 12:26:13 +02:00
this.noteId = noteId;
/** @type {string} */
2021-09-30 12:26:13 +02:00
this.type = type;
/** @type {string} */
2021-09-30 12:26:13 +02:00
this.name = name;
/** @type {int} */
2021-09-30 12:26:13 +02:00
this.position = position;
/** @type {string} */
2022-01-14 19:53:59 +01:00
this.value = value || "";
/** @type {boolean} */
2021-09-30 12:26:13 +02:00
this.isInheritable = !!isInheritable;
/** @type {string} */
2021-09-30 12:26:13 +02:00
this.utcDateModified = utcDateModified;
return this;
}
init() {
if (this.attributeId) {
this.becca.attributes[this.attributeId] = this;
}
if (!(this.noteId in this.becca.notes)) {
// entities can come out of order in sync, create skeleton which will be filled later
2023-01-03 13:54:27 +01:00
this.becca.addNote(this.noteId, new BNote({noteId: this.noteId}));
2021-09-30 12:26:13 +02:00
}
this.becca.notes[this.noteId].ownedAttributes.push(this);
const key = `${this.type}-${this.name.toLowerCase()}`;
this.becca.attributeIndex[key] = this.becca.attributeIndex[key] || [];
this.becca.attributeIndex[key].push(this);
const targetNote = this.targetNote;
if (targetNote) {
targetNote.targetRelations.push(this);
}
}
2022-12-14 23:51:56 +01:00
validate() {
if (!["label", "relation"].includes(this.type)) {
2022-12-22 14:57:00 +01:00
throw new Error(`Invalid attribute type '${this.type}' in attribute '${this.attributeId}' of note '${this.noteId}'`);
2022-12-14 23:51:56 +01:00
}
if (!this.name?.trim()) {
2022-12-22 14:57:00 +01:00
throw new Error(`Invalid empty name in attribute '${this.attributeId}' of note '${this.noteId}'`);
}
if (this.type === 'relation' &amp;&amp; !(this.value in this.becca.notes)) {
throw new Error(`Cannot save relation '${this.name}' of note '${this.noteId}' since it target not existing note '${this.value}'.`);
2022-12-14 23:51:56 +01:00
}
}
2021-09-30 12:26:13 +02:00
get isAffectingSubtree() {
return this.isInheritable
|| (this.type === 'relation' &amp;&amp; this.name === 'template');
}
get targetNoteId() { // alias
return this.type === 'relation' ? this.value : undefined;
}
isAutoLink() {
return this.type === 'relation' &amp;&amp; ['internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink'].includes(this.name);
}
get note() {
return this.becca.notes[this.noteId];
}
get targetNote() {
if (this.type === 'relation') {
return this.becca.notes[this.value];
}
}
/**
2023-01-03 13:54:27 +01:00
* @returns {BNote|null}
2021-09-30 12:26:13 +02:00
*/
getNote() {
2022-12-14 23:51:56 +01:00
const note = this.becca.getNote(this.noteId);
if (!note) {
throw new Error(`Note '${this.noteId}' of attribute '${this.attributeId}', type '${this.type}', name '${this.name}' does not exist.`);
}
return note;
2021-09-30 12:26:13 +02:00
}
/**
2023-01-03 13:54:27 +01:00
* @returns {BNote|null}
2021-09-30 12:26:13 +02:00
*/
getTargetNote() {
if (this.type !== 'relation') {
throw new Error(`Attribute ${this.attributeId} is not relation`);
}
if (!this.value) {
return null;
}
return this.becca.getNote(this.value);
}
/**
* @return {boolean}
*/
isDefinition() {
return this.type === 'label' &amp;&amp; (this.name.startsWith('label:') || this.name.startsWith('relation:'));
}
getDefinition() {
return promotedAttributeDefinitionParser.parse(this.value);
}
getDefinedName() {
if (this.type === 'label' &amp;&amp; this.name.startsWith('label:')) {
return this.name.substr(6);
} else if (this.type === 'label' &amp;&amp; this.name.startsWith('relation:')) {
return this.name.substr(9);
} else {
return this.name;
}
}
get isDeleted() {
return !(this.attributeId in this.becca.attributes);
}
2021-09-30 12:26:13 +02:00
beforeSaving() {
2022-12-14 23:51:56 +01:00
this.validate();
2021-09-30 12:26:13 +02:00
this.name = sanitizeAttributeName(this.name);
2022-12-22 14:57:00 +01:00
if (!this.value) {
2021-09-30 12:26:13 +02:00
// null value isn't allowed
this.value = "";
}
if (this.position === undefined) {
// TODO: can be calculated from becca
this.position = 1 + sql.getValue(`SELECT COALESCE(MAX(position), 0) FROM attributes WHERE noteId = ?`, [this.noteId]);
}
if (!this.isInheritable) {
this.isInheritable = false;
}
this.utcDateModified = dateUtils.utcNowDateTime();
super.beforeSaving();
this.becca.attributes[this.attributeId] = this;
}
getPojo() {
return {
attributeId: this.attributeId,
noteId: this.noteId,
type: this.type,
name: this.name,
position: this.position,
value: this.value,
isInheritable: this.isInheritable,
utcDateModified: this.utcDateModified,
isDeleted: false
};
}
createClone(type, name, value, isInheritable) {
2023-01-03 13:54:27 +01:00
return new BAttribute({
2021-09-30 12:26:13 +02:00
noteId: this.noteId,
type: type,
name: name,
value: value,
position: this.position,
isInheritable: isInheritable,
utcDateModified: this.utcDateModified
});
}
}
2023-01-03 13:54:27 +01:00
module.exports = BAttribute;
2021-09-30 12:26:13 +02:00
</code></pre>
</article>
</section>
</div>
<nav>
2023-01-03 13:54:27 +01:00
<h2><a href="index.html">Home</a></h2><h3>Modules</h3><ul><li><a href="module-sql.html">sql</a></li></ul><h3>Classes</h3><ul><li><a href="AbstractBeccaEntity.html">AbstractBeccaEntity</a></li><li><a href="BAttribute.html">BAttribute</a></li><li><a href="BBranch.html">BBranch</a></li><li><a href="BEtapiToken.html">BEtapiToken</a></li><li><a href="BNote.html">BNote</a></li><li><a href="BNoteRevision.html">BNoteRevision</a></li><li><a href="BOption.html">BOption</a></li><li><a href="BRecentNote.html">BRecentNote</a></li><li><a href="BackendScriptApi.html">BackendScriptApi</a></li></ul><h3><a href="global.html">Global</a></h3>
2021-09-30 12:26:13 +02:00
</nav>
<br class="clear">
<footer>
2022-11-07 21:26:13 +01:00
Documentation generated by <a href="https://github.com/jsdoc/jsdoc">JSDoc 4.0.0</a>
2021-09-30 12:26:13 +02:00
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>