mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	attr detail handles label/relation definition updates
This commit is contained in:
		@@ -10,16 +10,16 @@ module.exports = () => {
 | 
				
			|||||||
            tokens.push('promoted');
 | 
					            tokens.push('promoted');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obj.labelType) {
 | 
					 | 
				
			||||||
            tokens.push(obj.labelType);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (obj.multiplicityType === 'singlevalue') {
 | 
					        if (obj.multiplicityType === 'singlevalue') {
 | 
				
			||||||
            tokens.push('single');
 | 
					            tokens.push('single');
 | 
				
			||||||
        } else if (obj.multiplicityType === 'multivalue') {
 | 
					        } else if (obj.multiplicityType === 'multivalue') {
 | 
				
			||||||
            tokens.push('multi');
 | 
					            tokens.push('multi');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (obj.labelType) {
 | 
				
			||||||
 | 
					            tokens.push(obj.labelType);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obj.numberPrecision) {
 | 
					        if (obj.numberPrecision) {
 | 
				
			||||||
            tokens.push('precision='+obj.numberPrecision);
 | 
					            tokens.push('precision='+obj.numberPrecision);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -38,16 +38,16 @@ module.exports = () => {
 | 
				
			|||||||
            tokens.push('promoted');
 | 
					            tokens.push('promoted');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (obj.inverseRelation) {
 | 
					 | 
				
			||||||
            tokens.push('inverse=' + obj.inverseRelation);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (obj.multiplicityType === 'singlevalue') {
 | 
					        if (obj.multiplicityType === 'singlevalue') {
 | 
				
			||||||
            tokens.push('single');
 | 
					            tokens.push('single');
 | 
				
			||||||
        } else if (obj.multiplicityType === 'multivalue') {
 | 
					        } else if (obj.multiplicityType === 'multivalue') {
 | 
				
			||||||
            tokens.push('multi');
 | 
					            tokens.push('multi');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (obj.inverseRelation) {
 | 
				
			||||||
 | 
					            tokens.push('inverse=' + obj.inverseRelation);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const newValue = tokens.join(',');
 | 
					        const newValue = tokens.join(',');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sql.execute('UPDATE attributes SET value = ? WHERE attributeId = ?', [newValue, attr.attributeId]);
 | 
					        sql.execute('UPDATE attributes SET value = ? WHERE attributeId = ?', [newValue, attr.attributeId]);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					import promotedAttributeDefinitionParser from '../services/promoted_attribute_definition_parser.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Attribute {
 | 
					class Attribute {
 | 
				
			||||||
    constructor(treeCache, row) {
 | 
					    constructor(treeCache, row) {
 | 
				
			||||||
        this.treeCache = treeCache;
 | 
					        this.treeCache = treeCache;
 | 
				
			||||||
@@ -76,35 +78,7 @@ class Attribute {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getDefinition() {
 | 
					    getDefinition() {
 | 
				
			||||||
        const tokens = this.value.split(',').map(t => t.trim());
 | 
					        return promotedAttributeDefinitionParser.parse(this.value);
 | 
				
			||||||
        const defObj = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const token of tokens) {
 | 
					 | 
				
			||||||
            if (token === 'promoted') {
 | 
					 | 
				
			||||||
                defObj.isPromoted = true;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (['text', 'number', 'boolean', 'date', 'url'].includes(token)) {
 | 
					 | 
				
			||||||
                defObj.labelType = token;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (['single', 'multi'].includes(token)) {
 | 
					 | 
				
			||||||
                defObj.multiplicity = token;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (token.startsWith('precision')) {
 | 
					 | 
				
			||||||
                const chunks = token.split('=');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                defObj.numberPrecision = parseInt(chunks[1]);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else if (token.startsWith('inverse')) {
 | 
					 | 
				
			||||||
                const chunks = token.split('=');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                defObj.inverseRelation = chunks[1];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                console.log("Unrecognized attribute definition token:", token);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return defObj;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					function parse(value) {
 | 
				
			||||||
 | 
					    const tokens = value.split(',').map(t => t.trim());
 | 
				
			||||||
 | 
					    const defObj = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const token of tokens) {
 | 
				
			||||||
 | 
					        if (token === 'promoted') {
 | 
				
			||||||
 | 
					            defObj.isPromoted = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (['text', 'number', 'boolean', 'date', 'url'].includes(token)) {
 | 
				
			||||||
 | 
					            defObj.labelType = token;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (['single', 'multi'].includes(token)) {
 | 
				
			||||||
 | 
					            defObj.multiplicity = token;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (token.startsWith('precision')) {
 | 
				
			||||||
 | 
					            const chunks = token.split('=');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            defObj.numberPrecision = parseInt(chunks[1]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (token.startsWith('inverse')) {
 | 
				
			||||||
 | 
					            const chunks = token.split('=');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            defObj.inverseRelation = chunks[1];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else {
 | 
				
			||||||
 | 
					            console.log("Unrecognized attribute definition token:", token);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return defObj;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    parse
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -4,6 +4,7 @@ import treeService from "../services/tree.js";
 | 
				
			|||||||
import linkService from "../services/link.js";
 | 
					import linkService from "../services/link.js";
 | 
				
			||||||
import BasicWidget from "./basic_widget.js";
 | 
					import BasicWidget from "./basic_widget.js";
 | 
				
			||||||
import noteAutocompleteService from "../services/note_autocomplete.js";
 | 
					import noteAutocompleteService from "../services/note_autocomplete.js";
 | 
				
			||||||
 | 
					import promotedAttributeDefinitionParser from '../services/promoted_attribute_definition_parser.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TPL = `
 | 
					const TPL = `
 | 
				
			||||||
<div class="attr-detail">
 | 
					<div class="attr-detail">
 | 
				
			||||||
@@ -27,15 +28,15 @@ const TPL = `
 | 
				
			|||||||
            margin-bottom: 10px;
 | 
					            margin-bottom: 10px;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        .attr-edit {
 | 
					        .attr-edit-table {
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        .attr-edit th {
 | 
					        .attr-edit-table th {
 | 
				
			||||||
            text-align: left;
 | 
					            text-align: left;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        .attr-edit td input {
 | 
					        .attr-edit-table td input {
 | 
				
			||||||
            width: 100%;
 | 
					            width: 100%;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
@@ -53,59 +54,70 @@ const TPL = `
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    <div class="attr-is-owned-by"></div>
 | 
					    <div class="attr-is-owned-by"></div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <table class="attr-edit">
 | 
					    <table class="attr-edit-table">
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <th>Name:</th>
 | 
					            <th>Name:</th>
 | 
				
			||||||
            <td><input type="text" class="attr-edit-name form-control form-control-sm" /></td>
 | 
					            <td><input type="text" class="attr-input-name form-control" /></td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-value-row">
 | 
					        <tr class="attr-row-value">
 | 
				
			||||||
            <th>Value:</th>
 | 
					            <th>Value:</th>
 | 
				
			||||||
            <td><input type="text" class="attr-edit-value form-control form-control-sm" /></td>
 | 
					            <td><input type="text" class="attr-input-value form-control" /></td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-target-note-row">
 | 
					        <tr class="attr-row-target-note">
 | 
				
			||||||
            <th>Target note:</th>
 | 
					            <th>Target note:</th>
 | 
				
			||||||
            <td>
 | 
					            <td>
 | 
				
			||||||
                <div class="input-group">
 | 
					                <div class="input-group">
 | 
				
			||||||
                    <input type="text" class="attr-edit-target-note form-control" />
 | 
					                    <input type="text" class="attr-input-target-note form-control" />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-definition-promoted">
 | 
					        <tr class="attr-row-promoted">
 | 
				
			||||||
            <th>Promoted:</th>
 | 
					            <th>Promoted:</th>
 | 
				
			||||||
            <td><input type="checkbox" class="attr-edit-inheritable form-control form-control-sm" /></td>
 | 
					            <td><input type="checkbox" class="attr-input-promoted form-control form-control-sm" /></td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-definition-multiplicity">
 | 
					        <tr class="attr-row-multiplicity">
 | 
				
			||||||
            <th>Multiplicity:</th>
 | 
					            <th>Multiplicity:</th>
 | 
				
			||||||
            <td>
 | 
					            <td>
 | 
				
			||||||
                <select class="form-control">
 | 
					                <select class="attr-input-multiplicity form-control">
 | 
				
			||||||
                  <option>Single value</option>
 | 
					                  <option value="single">Single value</option>
 | 
				
			||||||
                  <option>Multi value</option>
 | 
					                  <option value="multi">Multi value</option>
 | 
				
			||||||
                </select>
 | 
					                </select>
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-definition-label-type">
 | 
					        <tr class="attr-row-label-type">
 | 
				
			||||||
            <th>Type:</th>
 | 
					            <th>Type:</th>
 | 
				
			||||||
            <td>
 | 
					            <td>
 | 
				
			||||||
                <select class="form-control">
 | 
					                <select class="attr-input-label-type form-control">
 | 
				
			||||||
                  <option>Text</option>
 | 
					                  <option value="text">Text</option>
 | 
				
			||||||
                  <option>Number</option>
 | 
					                  <option value="number">Number</option>
 | 
				
			||||||
                  <option>Boolean</option>
 | 
					                  <option value="boolean">Boolean</option>
 | 
				
			||||||
                  <option>Date</option>
 | 
					                  <option value="date">Date</option>
 | 
				
			||||||
                  <option>URL</option>
 | 
					                  <option value="url">URL</option>
 | 
				
			||||||
                </select>
 | 
					                </select>
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr class="attr-definition-inverse-relation">
 | 
					        <tr class="attr-row-number-precision">
 | 
				
			||||||
 | 
					            <th>Precision:</th>
 | 
				
			||||||
 | 
					            <td>
 | 
				
			||||||
 | 
					                <div class="input-group">
 | 
				
			||||||
 | 
					                    <input type="number" class="form-control attr-input-number-precision" style="text-align: right">
 | 
				
			||||||
 | 
					                    <div class="input-group-append">
 | 
				
			||||||
 | 
					                        <span class="input-group-text">digits</span>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        <tr class="attr-row-inverse-relation">
 | 
				
			||||||
            <th>Inverse relation:</th>
 | 
					            <th>Inverse relation:</th>
 | 
				
			||||||
            <td>
 | 
					            <td>
 | 
				
			||||||
                <div class="input-group">
 | 
					                <div class="input-group">
 | 
				
			||||||
                    <input type="text" class="form-control" />
 | 
					                    <input type="text" class="attr-input-inverse-relation form-control" />
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </td>
 | 
					            </td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
            <th>Inheritable:</th>
 | 
					            <th>Inheritable:</th>
 | 
				
			||||||
            <td><input type="checkbox" class="attr-edit-inheritable form-control form-control-sm" /></td>
 | 
					            <td><input type="checkbox" class="attr-input-inheritable form-control form-control-sm" /></td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
    </table>
 | 
					    </table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -140,22 +152,37 @@ export default class AttributeDetailWidget extends BasicWidget {
 | 
				
			|||||||
        this.$relatedNotesList = this.$relatedNotesContainer.find('.related-notes-list');
 | 
					        this.$relatedNotesList = this.$relatedNotesContainer.find('.related-notes-list');
 | 
				
			||||||
        this.$relatedNotesMoreNotes = this.$relatedNotesContainer.find('.related-notes-more-notes');
 | 
					        this.$relatedNotesMoreNotes = this.$relatedNotesContainer.find('.related-notes-more-notes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrEditName = this.$widget.find('.attr-edit-name');
 | 
					        this.$attrInputName = this.$widget.find('.attr-input-name');
 | 
				
			||||||
        this.$attrEditName.on('keyup', () => this.updateParent());
 | 
					        this.$attrInputName.on('keyup', () => this.updateParent());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrValueRow = this.$widget.find('.attr-value-row');
 | 
					        this.$attrRowValue = this.$widget.find('.attr-row-value');
 | 
				
			||||||
        this.$attrEditValue = this.$widget.find('.attr-edit-value');
 | 
					        this.$attrInputValue = this.$widget.find('.attr-input-value');
 | 
				
			||||||
        this.$attrEditValue.on('keyup', () => this.updateParent());
 | 
					        this.$attrInputValue.on('keyup', () => this.updateParent());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrDefinitionPromoted = this.$widget.find('.attr-definition-promoted');
 | 
					        this.$attrRowPromoted = this.$widget.find('.attr-row-promoted');
 | 
				
			||||||
        this.$attrDefinitionMultiplicity = this.$widget.find('.attr-definition-multiplicity');
 | 
					        this.$attrInputPromoted = this.$widget.find('.attr-input-promoted');
 | 
				
			||||||
        this.$attrDefinitionLabelType = this.$widget.find('.attr-definition-label-type');
 | 
					        this.$attrInputPromoted.on('change', () => this.updateDefinition());
 | 
				
			||||||
        this.$attrDefinitionInverseRelation = this.$widget.find('.attr-definition-inverse-relation');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrTargetNoteRow = this.$widget.find('.attr-target-note-row');
 | 
					        this.$attrRowMultiplicity = this.$widget.find('.attr-row-multiplicity');
 | 
				
			||||||
        this.$attrEditTargetNote = this.$widget.find('.attr-edit-target-note');
 | 
					        this.$attrInputMultiplicity = this.$widget.find('.attr-input-multiplicity');
 | 
				
			||||||
 | 
					        this.$attrInputMultiplicity.on('change', () => this.updateDefinition());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        noteAutocompleteService.initNoteAutocomplete(this.$attrEditTargetNote)
 | 
					        this.$attrRowLabelType = this.$widget.find('.attr-row-label-type');
 | 
				
			||||||
 | 
					        this.$attrInputLabelType = this.$widget.find('.attr-input-label-type');
 | 
				
			||||||
 | 
					        this.$attrInputLabelType.on('change', () => this.updateDefinition());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowNumberPrecision = this.$widget.find('.attr-row-number-precision');
 | 
				
			||||||
 | 
					        this.$attrInputNumberPrecision = this.$widget.find('.attr-input-number-precision');
 | 
				
			||||||
 | 
					        this.$attrInputNumberPrecision.on('change', () => this.updateDefinition());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowInverseRelation = this.$widget.find('.attr-row-inverse-relation');
 | 
				
			||||||
 | 
					        this.$attrInputInverseRelation = this.$widget.find('.attr-input-inverse-relation');
 | 
				
			||||||
 | 
					        this.$attrInputInverseRelation.on('keyup', () => this.updateDefinition());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowTargetNote = this.$widget.find('.attr-row-target-note');
 | 
				
			||||||
 | 
					        this.$attrInputTargetNote = this.$widget.find('.attr-input-target-note');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        noteAutocompleteService.initNoteAutocomplete(this.$attrInputTargetNote)
 | 
				
			||||||
            .on('autocomplete:selected', (event, suggestion, dataset) => {
 | 
					            .on('autocomplete:selected', (event, suggestion, dataset) => {
 | 
				
			||||||
                if (!suggestion.notePath) {
 | 
					                if (!suggestion.notePath) {
 | 
				
			||||||
                    return false;
 | 
					                    return false;
 | 
				
			||||||
@@ -166,8 +193,8 @@ export default class AttributeDetailWidget extends BasicWidget {
 | 
				
			|||||||
                this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
 | 
					                this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrEditInheritable = this.$widget.find('.attr-edit-inheritable');
 | 
					        this.$attrInputInheritable = this.$widget.find('.attr-input-inheritable');
 | 
				
			||||||
        this.$attrEditInheritable.on('change', () => this.updateParent());
 | 
					        this.$attrInputInheritable.on('change', () => this.updateParent());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$closeAttrDetailButton = this.$widget.find('.close-attr-detail-button');
 | 
					        this.$closeAttrDetailButton = this.$widget.find('.close-attr-detail-button');
 | 
				
			||||||
        this.$attrIsOwnedBy = this.$widget.find('.attr-is-owned-by');
 | 
					        this.$attrIsOwnedBy = this.$widget.find('.attr-is-owned-by');
 | 
				
			||||||
@@ -191,9 +218,13 @@ export default class AttributeDetailWidget extends BasicWidget {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const attrType = this.getAttrType(attribute);
 | 
					        this.attrType = this.getAttrType(attribute);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$title.text(ATTR_TITLES[attrType]);
 | 
					        const definition = this.attrType.endsWith('-definition')
 | 
				
			||||||
 | 
					            ? promotedAttributeDefinitionParser.parse(attribute.value)
 | 
				
			||||||
 | 
					            : {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$title.text(ATTR_TITLES[this.attrType]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.allAttributes = allAttributes;
 | 
					        this.allAttributes = allAttributes;
 | 
				
			||||||
        this.attribute = attribute;
 | 
					        this.attribute = attribute;
 | 
				
			||||||
@@ -246,33 +277,53 @@ export default class AttributeDetailWidget extends BasicWidget {
 | 
				
			|||||||
                .append(await linkService.createNoteLink(attribute.noteId))
 | 
					                .append(await linkService.createNoteLink(attribute.noteId))
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrEditName
 | 
					        this.$attrInputName
 | 
				
			||||||
            .val(attribute.name)
 | 
					            .val(attribute.name)
 | 
				
			||||||
            .attr('readonly', () => !isOwned);
 | 
					            .attr('readonly', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrValueRow.toggle(attrType === 'label');
 | 
					        this.$attrRowValue.toggle(this.attrType === 'label');
 | 
				
			||||||
        this.$attrTargetNoteRow.toggle(attrType === 'relation');
 | 
					        this.$attrRowTargetNote.toggle(this.attrType === 'relation');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrDefinitionPromoted.toggle(['label-definition', 'relation-definition'].includes(attrType));
 | 
					        this.$attrRowPromoted.toggle(['label-definition', 'relation-definition'].includes(this.attrType));
 | 
				
			||||||
        this.$attrDefinitionMultiplicity.toggle(['label-definition', 'relation-definition'].includes(attrType));
 | 
					        this.$attrInputPromoted
 | 
				
			||||||
        this.$attrDefinitionLabelType.toggle(attrType === 'label-definition');
 | 
					            .prop("checked", !!definition.isPromoted)
 | 
				
			||||||
        this.$attrDefinitionInverseRelation.toggle(attrType === 'relation-definition');
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowMultiplicity.toggle(['label-definition', 'relation-definition'].includes(this.attrType));
 | 
				
			||||||
 | 
					        this.$attrInputMultiplicity
 | 
				
			||||||
 | 
					            .val(definition.multiplicity)
 | 
				
			||||||
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowLabelType.toggle(this.attrType === 'label-definition');
 | 
				
			||||||
 | 
					        this.$attrInputLabelType
 | 
				
			||||||
 | 
					            .val(definition.labelType)
 | 
				
			||||||
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowNumberPrecision.toggle(this.attrType === 'label-definition' && definition.labelType === 'number');
 | 
				
			||||||
 | 
					        this.$attrInputNumberPrecision
 | 
				
			||||||
 | 
					            .val(definition.numberPrecision)
 | 
				
			||||||
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowInverseRelation.toggle(this.attrType === 'relation-definition');
 | 
				
			||||||
 | 
					        this.$attrInputInverseRelation
 | 
				
			||||||
 | 
					            .val(definition.inverseRelation)
 | 
				
			||||||
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (attribute.type === 'label') {
 | 
					        if (attribute.type === 'label') {
 | 
				
			||||||
            this.$attrEditValue
 | 
					            this.$attrInputValue
 | 
				
			||||||
                .val(attribute.value)
 | 
					                .val(attribute.value)
 | 
				
			||||||
                .attr('readonly', () => !isOwned);
 | 
					                .attr('readonly', () => !isOwned);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        else if (attribute.type === 'relation') {
 | 
					        else if (attribute.type === 'relation') {
 | 
				
			||||||
            const targetNote = await treeCache.getNote(attribute.value);
 | 
					            const targetNote = await treeCache.getNote(attribute.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.$attrEditTargetNote
 | 
					            this.$attrInputTargetNote
 | 
				
			||||||
                .attr('readonly', () => !isOwned)
 | 
					                .attr('readonly', () => !isOwned)
 | 
				
			||||||
                .val(targetNote ? targetNote.title : "")
 | 
					                .val(targetNote ? targetNote.title : "")
 | 
				
			||||||
                .setSelectedNotePath(attribute.value);
 | 
					                .setSelectedNotePath(attribute.value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$attrEditInheritable
 | 
					        this.$attrInputInheritable
 | 
				
			||||||
            .prop("checked", !!attribute.isInheritable)
 | 
					            .prop("checked", !!attribute.isInheritable)
 | 
				
			||||||
            .attr('disabled', () => !isOwned);
 | 
					            .attr('disabled', () => !isOwned);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -301,9 +352,37 @@ export default class AttributeDetailWidget extends BasicWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updateParent() {
 | 
					    updateParent() {
 | 
				
			||||||
        this.attribute.name = this.$attrEditName.val();
 | 
					        this.attribute.name = this.$attrInputName.val();
 | 
				
			||||||
        this.attribute.value = this.$attrEditValue.val();
 | 
					        this.attribute.value = this.$attrInputValue.val();
 | 
				
			||||||
        this.attribute.isInheritable = this.$attrEditInheritable.is(":checked");
 | 
					        this.attribute.isInheritable = this.$attrInputInheritable.is(":checked");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    updateDefinition() {
 | 
				
			||||||
 | 
					        this.attribute.name = this.$attrInputName.val();
 | 
				
			||||||
 | 
					        this.attribute.isInheritable = this.$attrInputInheritable.is(":checked");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const props = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.$attrInputPromoted.is(":checked")) {
 | 
				
			||||||
 | 
					            props.push("promoted");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        props.push(this.$attrInputMultiplicity.val());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.attrType === 'label-definition') {
 | 
				
			||||||
 | 
					            props.push(this.$attrInputLabelType.val());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        else if (this.attrType === 'relation-definition' && this.$attrInputInverseRelation.val().trim().length > 0) {
 | 
				
			||||||
 | 
					            props.push("inverse=" + this.$attrInputInverseRelation.val());
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.$attrRowNumberPrecision.toggle(
 | 
				
			||||||
 | 
					            this.attrType === 'label-definition'
 | 
				
			||||||
 | 
					            && this.$attrInputLabelType.val() === 'number');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.attribute.value = props.join(",");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
 | 
					        this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -234,20 +234,24 @@ export default class AttributeEditorWidget extends TabAwareWidget {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let type, name;
 | 
					        let type, name, value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (command === 'addNewLabel') {
 | 
					        if (command === 'addNewLabel') {
 | 
				
			||||||
            type = 'label';
 | 
					            type = 'label';
 | 
				
			||||||
            name = 'fillName';
 | 
					            name = 'myLabel';
 | 
				
			||||||
 | 
					            value = '';
 | 
				
			||||||
        } else if (command === 'addNewRelation') {
 | 
					        } else if (command === 'addNewRelation') {
 | 
				
			||||||
            type = 'relation';
 | 
					            type = 'relation';
 | 
				
			||||||
            name = 'fillName';
 | 
					            name = 'myRelation';
 | 
				
			||||||
 | 
					            value = '';
 | 
				
			||||||
        } else if (command === 'addNewLabelDefinition') {
 | 
					        } else if (command === 'addNewLabelDefinition') {
 | 
				
			||||||
            type = 'label';
 | 
					            type = 'label';
 | 
				
			||||||
            name = 'label:fillName';
 | 
					            name = 'label:myLabel';
 | 
				
			||||||
 | 
					            value = 'promoted,single,text';
 | 
				
			||||||
        } else if (command === 'addNewRelationDefinition') {
 | 
					        } else if (command === 'addNewRelationDefinition') {
 | 
				
			||||||
            type = 'label';
 | 
					            type = 'label';
 | 
				
			||||||
            name = 'relation:fillName';
 | 
					            name = 'relation:myRelation';
 | 
				
			||||||
 | 
					            value = 'promoted,single';
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -255,7 +259,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
 | 
				
			|||||||
        attrs.push({
 | 
					        attrs.push({
 | 
				
			||||||
            type,
 | 
					            type,
 | 
				
			||||||
            name,
 | 
					            name,
 | 
				
			||||||
            value: '',
 | 
					            value,
 | 
				
			||||||
            isInheritable: false
 | 
					            isInheritable: false
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -347,7 +351,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
 | 
				
			|||||||
            let matchedAttr = null;
 | 
					            let matchedAttr = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (const attr of parsedAttrs) {
 | 
					            for (const attr of parsedAttrs) {
 | 
				
			||||||
                if (clickIndex >= attr.startIndex && clickIndex <= attr.endIndex) {
 | 
					                if (clickIndex > attr.startIndex && clickIndex <= attr.endIndex) {
 | 
				
			||||||
                    matchedAttr = attr;
 | 
					                    matchedAttr = attr;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user