2018-08-01 09:26:02 +02:00
|
|
|
const eventService = require('./events');
|
|
|
|
const scriptService = require('./script');
|
|
|
|
const treeService = require('./tree');
|
2020-11-19 14:29:26 +01:00
|
|
|
const noteService = require('./notes');
|
2019-09-08 16:57:41 +02:00
|
|
|
const repository = require('./repository');
|
2021-04-16 23:01:56 +02:00
|
|
|
const becca = require('./becca/becca.js');
|
2018-11-12 23:34:22 +01:00
|
|
|
const Attribute = require('../entities/attribute');
|
2018-08-01 09:26:02 +02:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function runAttachedRelations(note, relationName, originEntity) {
|
2020-10-12 22:30:30 +02:00
|
|
|
// same script note can get here with multiple ways, but execute only once
|
|
|
|
const notesToRun = new Set(
|
|
|
|
note.getRelations(relationName)
|
|
|
|
.map(relation => relation.getTargetNote())
|
|
|
|
.filter(note => !!note)
|
|
|
|
);
|
2018-08-01 09:26:02 +02:00
|
|
|
|
2020-10-12 22:30:30 +02:00
|
|
|
for (const noteToRun of notesToRun) {
|
|
|
|
scriptService.executeNoteNoException(noteToRun, { originEntity });
|
2018-08-01 09:26:02 +02:00
|
|
|
}
|
2018-08-09 20:08:00 +02:00
|
|
|
}
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe(eventService.NOTE_TITLE_CHANGED, note => {
|
|
|
|
runAttachedRelations(note, 'runOnNoteTitleChange', note);
|
2018-08-01 09:26:02 +02:00
|
|
|
|
|
|
|
if (!note.isRoot()) {
|
2021-04-16 23:00:08 +02:00
|
|
|
const noteFromCache = becca.notes[note.noteId];
|
2018-08-01 09:26:02 +02:00
|
|
|
|
2021-01-30 22:25:40 +01:00
|
|
|
if (!noteFromCache) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-01-23 21:00:59 +01:00
|
|
|
for (const parentNote of noteFromCache.parents) {
|
|
|
|
if (parentNote.hasLabel("sorted")) {
|
2021-02-28 23:40:15 +01:00
|
|
|
treeService.sortNotesByTitle(parentNote.noteId);
|
2018-08-01 09:26:02 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-09 20:08:00 +02:00
|
|
|
});
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETED ], ({ entityName, entity }) => {
|
2018-08-09 20:08:00 +02:00
|
|
|
if (entityName === 'attributes') {
|
2020-06-20 12:31:38 +02:00
|
|
|
runAttachedRelations(entity.getNote(), 'runOnAttributeChange', entity);
|
2018-08-15 22:06:49 +02:00
|
|
|
}
|
|
|
|
else if (entityName === 'notes') {
|
2020-06-20 12:31:38 +02:00
|
|
|
runAttachedRelations(entity, 'runOnNoteChange', entity);
|
2018-08-15 22:06:49 +02:00
|
|
|
}
|
|
|
|
});
|
2018-08-09 20:08:00 +02:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => {
|
2018-08-15 22:06:49 +02:00
|
|
|
if (entityName === 'attributes') {
|
2020-06-20 12:31:38 +02:00
|
|
|
runAttachedRelations(entity.getNote(), 'runOnAttributeCreation', entity);
|
2019-09-08 16:57:41 +02:00
|
|
|
|
|
|
|
if (entity.type === 'relation' && entity.name === 'template') {
|
2020-06-20 12:31:38 +02:00
|
|
|
const note = repository.getNote(entity.noteId);
|
2019-09-08 16:57:41 +02:00
|
|
|
|
2020-11-19 14:29:26 +01:00
|
|
|
const templateNote = repository.getNote(entity.value);
|
2019-09-08 16:57:41 +02:00
|
|
|
|
2020-11-19 14:29:26 +01:00
|
|
|
if (!templateNote) {
|
2019-09-08 16:57:41 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-06 21:34:03 +01:00
|
|
|
const content = note.getContent();
|
|
|
|
|
2021-03-09 20:51:57 +01:00
|
|
|
if (["text", "code"].includes(note.type)
|
2021-03-06 21:34:03 +01:00
|
|
|
// if the note has already content we're not going to overwrite it with template's one
|
|
|
|
&& (!content || content.trim().length === 0)
|
|
|
|
&& templateNote.isStringNote()) {
|
|
|
|
|
2020-11-19 14:29:26 +01:00
|
|
|
const templateNoteContent = templateNote.getContent();
|
2020-08-29 23:08:53 +02:00
|
|
|
|
2020-11-19 14:29:26 +01:00
|
|
|
if (templateNoteContent) {
|
|
|
|
note.setContent(templateNoteContent);
|
|
|
|
}
|
2020-12-07 09:35:39 +01:00
|
|
|
|
|
|
|
note.type = templateNote.type;
|
|
|
|
note.mime = templateNote.mime;
|
|
|
|
note.save();
|
2020-08-29 23:08:53 +02:00
|
|
|
}
|
2020-11-19 14:29:26 +01:00
|
|
|
|
2021-03-06 21:34:03 +01:00
|
|
|
// we'll copy the children notes only if there's none so far
|
|
|
|
// this protects against e.g. multiple assignment of template relation resulting in having multiple copies of the subtree
|
|
|
|
if (note.getChildNotes().length === 0 && !note.isDescendantOfNote(templateNote.noteId)) {
|
|
|
|
noteService.duplicateSubtreeWithoutRoot(templateNote.noteId, note.noteId);
|
|
|
|
}
|
2019-09-08 16:57:41 +02:00
|
|
|
}
|
2020-06-23 22:03:01 +02:00
|
|
|
else if (entity.type === 'label' && entity.name === 'sorted') {
|
2021-02-28 23:40:15 +01:00
|
|
|
treeService.sortNotesByTitle(entity.noteId);
|
2021-01-23 21:00:59 +01:00
|
|
|
|
|
|
|
if (entity.isInheritable) {
|
2021-04-16 23:00:08 +02:00
|
|
|
const note = becca.notes[entity.noteId];
|
2021-01-23 21:00:59 +01:00
|
|
|
|
|
|
|
if (note) {
|
|
|
|
for (const noteId of note.subtreeNoteIds) {
|
2021-02-28 23:40:15 +01:00
|
|
|
treeService.sortNotesByTitle(noteId);
|
2021-01-23 21:00:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-23 22:03:01 +02:00
|
|
|
}
|
2018-08-09 20:08:00 +02:00
|
|
|
}
|
2018-08-15 22:06:49 +02:00
|
|
|
else if (entityName === 'notes') {
|
2020-06-20 12:31:38 +02:00
|
|
|
runAttachedRelations(entity, 'runOnNoteCreation', entity);
|
2018-08-15 22:06:49 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe(eventService.CHILD_NOTE_CREATED, ({ parentNote, childNote }) => {
|
|
|
|
runAttachedRelations(parentNote, 'runOnChildNoteCreation', childNote);
|
2018-11-12 23:34:22 +01:00
|
|
|
});
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function processInverseRelations(entityName, entity, handler) {
|
2018-11-12 23:34:22 +01:00
|
|
|
if (entityName === 'attributes' && entity.type === 'relation') {
|
2020-06-20 12:31:38 +02:00
|
|
|
const note = entity.getNote();
|
2020-12-21 20:55:01 +01:00
|
|
|
const relDefinitions = note.getLabels('relation:' + entity.name);
|
2018-11-12 23:34:22 +01:00
|
|
|
|
2020-12-21 20:55:01 +01:00
|
|
|
for (const relDefinition of relDefinitions) {
|
|
|
|
const definition = relDefinition.getDefinition();
|
2018-11-12 23:34:22 +01:00
|
|
|
|
2018-11-19 12:07:33 +01:00
|
|
|
if (definition.inverseRelation && definition.inverseRelation.trim()) {
|
2020-06-20 12:31:38 +02:00
|
|
|
const targetNote = entity.getTargetNote();
|
2018-11-12 23:34:22 +01:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
handler(definition, note, targetNote);
|
2018-11-12 23:34:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe(eventService.ENTITY_CHANGED, ({ entityName, entity }) => {
|
|
|
|
processInverseRelations(entityName, entity, (definition, note, targetNote) => {
|
2018-11-19 12:07:33 +01:00
|
|
|
// we need to make sure that also target's inverse attribute exists and if note, then create it
|
|
|
|
// inverse attribute has to target our note as well
|
2020-06-20 12:31:38 +02:00
|
|
|
const hasInverseAttribute = (targetNote.getRelations(definition.inverseRelation))
|
2018-11-19 00:06:04 +01:00
|
|
|
.some(attr => attr.value === note.noteId);
|
|
|
|
|
2018-11-19 12:07:33 +01:00
|
|
|
if (!hasInverseAttribute) {
|
2020-06-20 12:31:38 +02:00
|
|
|
new Attribute({
|
2018-11-12 23:34:22 +01:00
|
|
|
noteId: targetNote.noteId,
|
|
|
|
type: 'relation',
|
2018-11-19 12:07:33 +01:00
|
|
|
name: definition.inverseRelation,
|
2018-11-12 23:34:22 +01:00
|
|
|
value: note.noteId,
|
|
|
|
isInheritable: entity.isInheritable
|
|
|
|
}).save();
|
|
|
|
|
|
|
|
targetNote.invalidateAttributeCache();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
eventService.subscribe(eventService.ENTITY_DELETED, ({ entityName, entity }) => {
|
|
|
|
processInverseRelations(entityName, entity, (definition, note, targetNote) => {
|
2018-11-19 12:07:33 +01:00
|
|
|
// if one inverse attribute is deleted then the other should be deleted as well
|
2020-06-20 12:31:38 +02:00
|
|
|
const relations = targetNote.getOwnedRelations(definition.inverseRelation);
|
2018-11-12 23:34:22 +01:00
|
|
|
|
|
|
|
for (const relation of relations) {
|
2018-11-19 00:06:04 +01:00
|
|
|
if (relation.value === note.noteId) {
|
2021-02-17 20:59:44 +01:00
|
|
|
note.invalidateAttributeCache();
|
|
|
|
targetNote.invalidateAttributeCache();
|
|
|
|
|
2018-11-19 00:06:04 +01:00
|
|
|
relation.isDeleted = true;
|
2020-06-20 12:31:38 +02:00
|
|
|
relation.save();
|
2018-11-19 00:06:04 +01:00
|
|
|
}
|
2018-11-12 23:34:22 +01:00
|
|
|
}
|
|
|
|
});
|
2020-06-20 12:31:38 +02:00
|
|
|
});
|