import server from "./server.js"; import ws from "./ws.js"; import treeUtils from "./tree_utils.js"; import noteAutocompleteService from "./note_autocomplete.js"; class Attributes { /** * @param {TabContext} ctx */ constructor(ctx) { this.ctx = ctx; this.$promotedAttributesContainer = ctx.$tabContent.find(".note-detail-promoted-attributes"); this.$savedIndicator = ctx.$tabContent.find(".saved-indicator"); this.attributePromise = null; } invalidateAttributes() { this.attributePromise = null; } reloadAttributes() { this.attributePromise = server.get(`notes/${this.ctx.note.noteId}/attributes`); } async refreshAttributes() { this.reloadAttributes(); await this.showAttributes(); } async getAttributes() { if (!this.attributePromise) { this.reloadAttributes(); } return await this.attributePromise; } async showAttributes() { this.$promotedAttributesContainer.empty(); const attributes = await this.getAttributes(); const promoted = attributes.filter(attr => (attr.type === 'label-definition' || attr.type === 'relation-definition') && !attr.name.startsWith("child:") && attr.value.isPromoted); const hidePromotedAttributes = attributes.some(attr => attr.type === 'label' && attr.name === 'hidePromotedAttributes'); if (promoted.length > 0 && !hidePromotedAttributes) { const $tbody = $("
"); for (const definitionAttr of promoted) { const definitionType = definitionAttr.type; const valueType = definitionType.substr(0, definitionType.length - 11); let valueAttrs = attributes.filter(el => el.name === definitionAttr.name && el.type === valueType); if (valueAttrs.length === 0) { valueAttrs.push({ attributeId: "", type: valueType, name: definitionAttr.name, value: "" }); } if (definitionAttr.value.multiplicityType === 'singlevalue') { valueAttrs = valueAttrs.slice(0, 1); } for (const valueAttr of valueAttrs) { const $tr = await this.createPromotedAttributeRow(definitionAttr, valueAttr); $tbody.append($tr); } } // we replace the whole content in one step so there can't be any race conditions // (previously we saw promoted attributes doubling) this.$promotedAttributesContainer.empty().append($tbody); } return attributes; } async createPromotedAttributeRow(definitionAttr, valueAttr) { const definition = definitionAttr.value; const $tr = $("