diff --git a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js
index 0fea1a4a8..d35fe4f0f 100644
--- a/src/public/app/widgets/ribbon_widgets/promoted_attributes.js
+++ b/src/public/app/widgets/ribbon_widgets/promoted_attributes.js
@@ -115,9 +115,9 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
const $input = $("")
.prop("tabindex", 200 + definitionAttr.position)
- .prop("attribute-id", valueAttr.noteId === this.noteId ? valueAttr.attributeId : '') // if not owned, we'll force creation of a new attribute instead of updating the inherited one
- .prop("attribute-type", valueAttr.type)
- .prop("attribute-name", valueAttr.name)
+ .attr("data-attribute-id", valueAttr.noteId === this.noteId ? valueAttr.attributeId : '') // if not owned, we'll force creation of a new attribute instead of updating the inherited one
+ .attr("data-attribute-type", valueAttr.type)
+ .attr("data-attribute-name", valueAttr.name)
.prop("value", valueAttr.value)
.addClass("form-control")
.addClass("promoted-attribute-input")
@@ -230,7 +230,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
}
if (definition.multiplicity === "multi") {
- const addButton = $("")
+ const $addButton = $("")
.addClass("bx bx-plus pointer")
.prop("title", "Add new attribute")
.on('click', async () => {
@@ -246,12 +246,28 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
$new.find('input').trigger('focus');
});
- const removeButton = $("")
+ const $removeButton = $("")
.addClass("bx bx-trash pointer")
.prop("title", "Remove this attribute")
.on('click', async () => {
- if (valueAttr.attributeId) {
- await server.remove("notes/" + this.noteId + "/attributes/" + valueAttr.attributeId, this.componentId);
+ const attributeId = $input.attr("data-attribute-id");
+
+ if (attributeId) {
+ await server.remove("notes/" + this.noteId + "/attributes/" + attributeId, this.componentId);
+ }
+
+ // if it's the last one the create new empty form immediately
+ const sameAttrSelector = `input[data-attribute-type='${valueAttr.type}'][data-attribute-name='${valueName}']`;
+
+ if (this.$widget.find(sameAttrSelector).length <= 1) {
+ const $new = await this.createPromotedAttributeCell(definitionAttr, {
+ attributeId: "",
+ type: valueAttr.type,
+ name: valueName,
+ value: ""
+ }, valueName);
+
+ $wrapper.after($new);
}
$wrapper.remove();
@@ -259,9 +275,9 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
$multiplicityCell
.append(" ")
- .append(addButton)
+ .append($addButton)
.append(" ")
- .append(removeButton);
+ .append($removeButton);
}
return $wrapper;
@@ -275,7 +291,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
if ($attr.prop("type") === "checkbox") {
value = $attr.is(':checked') ? "true" : "false";
}
- else if ($attr.prop("attribute-type") === "relation") {
+ else if ($attr.attr("data-attribute-type") === "relation") {
const selectedPath = $attr.getSelectedNotePath();
value = selectedPath ? treeService.getNoteIdFromNotePath(selectedPath) : "";
@@ -285,13 +301,13 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
}
const result = await server.put(`notes/${this.noteId}/attribute`, {
- attributeId: $attr.prop("attribute-id"),
- type: $attr.prop("attribute-type"),
- name: $attr.prop("attribute-name"),
+ attributeId: $attr.attr("data-attribute-id"),
+ type: $attr.attr("data-attribute-type"),
+ name: $attr.attr("data-attribute-name"),
value: value
}, this.componentId);
- $attr.prop("attribute-id", result.attributeId);
+ $attr.attr("data-attribute-id", result.attributeId);
}
entitiesReloadedEvent({loadResults}) {
diff --git a/src/services/attributes.js b/src/services/attributes.js
index 175605deb..eb5484fdc 100644
--- a/src/services/attributes.js
+++ b/src/services/attributes.js
@@ -65,6 +65,7 @@ const BUILTIN_ATTRIBUTES = [
{ type: 'relation', name: 'renderNote', isDangerous: true }
];
+/** @returns {Note[]} */
function getNotesWithLabel(name, value) {
const query = formatAttrForSearch({type: 'label', name, value}, true);
return searchService.searchNotes(query, {
@@ -74,6 +75,7 @@ function getNotesWithLabel(name, value) {
}
// TODO: should be in search service
+/** @returns {Note|null} */
function getNoteWithLabel(name, value) {
// optimized version (~20 times faster) without using normal search, useful for e.g. finding date notes
const attrs = becca.findAttributes('label', name);
diff --git a/src/services/date_notes.js b/src/services/date_notes.js
index 66606f11a..7d9940690 100644
--- a/src/services/date_notes.js
+++ b/src/services/date_notes.js
@@ -25,15 +25,6 @@ function createNote(parentNote, noteTitle) {
}).note;
}
-function getNoteStartingWith(parentNoteId, startsWith) {
- const noteId = sql.getValue(`SELECT notes.noteId FROM notes JOIN branches USING(noteId)
- WHERE parentNoteId = ? AND title LIKE '${startsWith}%'
- AND notes.isDeleted = 0 AND isProtected = 0
- AND branches.isDeleted = 0`, [parentNoteId]);
-
- return becca.getNote(noteId);
-}
-
/** @returns {Note} */
function getRootCalendarNote() {
let rootNote = attributeService.getNoteWithLabel(CALENDAR_ROOT_LABEL);
@@ -164,12 +155,6 @@ function getDateNote(dateStr) {
const monthNote = getMonthNote(dateStr, rootNote);
const dayNumber = dateStr.substr(8, 2);
- dateNote = getNoteStartingWith(monthNote.noteId, dayNumber);
-
- if (dateNote) {
- return dateNote;
- }
-
const dateObj = dateUtils.parseLocalDate(dateStr);
const noteTitle = getDateNoteTitle(rootNote, dayNumber, dateObj);