mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	hide attribute "status bar" for relation map to maximize screen space, some refactoring
This commit is contained in:
		| @@ -26,9 +26,9 @@ async function getAttributes() { | ||||
|  | ||||
| async function showAttributes() { | ||||
|     $promotedAttributesContainer.empty(); | ||||
|     $attributeList.hide(); | ||||
|     $attributeList.hide().empty(); | ||||
|  | ||||
|     const noteId = noteDetailService.getCurrentNoteId(); | ||||
|     const note = noteDetailService.getCurrentNote(); | ||||
|  | ||||
|     const attributes = await attributePromise; | ||||
|  | ||||
| @@ -37,168 +37,6 @@ async function showAttributes() { | ||||
|         && !attr.name.startsWith("child:") | ||||
|         && attr.value.isPromoted); | ||||
|  | ||||
|     let idx = 1; | ||||
|  | ||||
|     async function createRow(definitionAttr, valueAttr) { | ||||
|         const definition = definitionAttr.value; | ||||
|         const inputId = "promoted-input-" + idx; | ||||
|         const $tr = $("<tr>"); | ||||
|         const $labelCell = $("<th>").append(valueAttr.name); | ||||
|         const $input = $("<input>") | ||||
|             .prop("id", inputId) | ||||
|             .prop("tabindex", definitionAttr.position) | ||||
|             .prop("attribute-id", valueAttr.isOwned ? 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) | ||||
|             .prop("value", valueAttr.value) | ||||
|             .addClass("form-control") | ||||
|             .addClass("promoted-attribute-input") | ||||
|             .change(promotedAttributeChanged); | ||||
|  | ||||
|         idx++; | ||||
|  | ||||
|         const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input)); | ||||
|  | ||||
|         const $actionCell = $("<td>"); | ||||
|         const $multiplicityCell = $("<td>").addClass("multiplicity"); | ||||
|  | ||||
|         $tr | ||||
|             .append($labelCell) | ||||
|             .append($inputCell) | ||||
|             .append($actionCell) | ||||
|             .append($multiplicityCell); | ||||
|  | ||||
|         if (valueAttr.type === 'label') { | ||||
|             if (definition.labelType === 'text') { | ||||
|                 $input.prop("type", "text"); | ||||
|  | ||||
|                 // no need to await for this, can be done asynchronously | ||||
|                 server.get('attributes/values/' + encodeURIComponent(valueAttr.name)).then(attributeValues => { | ||||
|                     if (attributeValues.length === 0) { | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     attributeValues = attributeValues.map(attribute => { return { value: attribute }; }); | ||||
|  | ||||
|                     $input.autocomplete({ | ||||
|                         appendTo: document.querySelector('body'), | ||||
|                         hint: false, | ||||
|                         autoselect: true, | ||||
|                         openOnFocus: true, | ||||
|                         minLength: 0 | ||||
|                     }, [{ | ||||
|                         displayKey: 'value', | ||||
|                         source: function (term, cb) { | ||||
|                             term = term.toLowerCase(); | ||||
|  | ||||
|                             const filtered = attributeValues.filter(attr => attr.value.toLowerCase().includes(term)); | ||||
|  | ||||
|                             cb(filtered); | ||||
|                         } | ||||
|                     }]); | ||||
|                 }); | ||||
|             } | ||||
|             else if (definition.labelType === 'number') { | ||||
|                 $input.prop("type", "number"); | ||||
|             } | ||||
|             else if (definition.labelType === 'boolean') { | ||||
|                 $input.prop("type", "checkbox"); | ||||
|  | ||||
|                 if (valueAttr.value === "true") { | ||||
|                     $input.prop("checked", "checked"); | ||||
|                 } | ||||
|             } | ||||
|             else if (definition.labelType === 'date') { | ||||
|                 $input.prop("type", "date"); | ||||
|  | ||||
|                 const $todayButton = $("<button>").addClass("btn btn-sm").text("Today").click(() => { | ||||
|                     $input.val(utils.formatDateISO(new Date())); | ||||
|                     $input.trigger("change"); | ||||
|                 }); | ||||
|  | ||||
|                 $actionCell.append($todayButton); | ||||
|             } | ||||
|             else if (definition.labelType === 'url') { | ||||
|                 $input.prop("placeholder", "http://website..."); | ||||
|  | ||||
|                 const $openButton = $("<button>").addClass("btn btn-sm").text("Open").click(() => { | ||||
|                     window.open($input.val(), '_blank'); | ||||
|                 }); | ||||
|  | ||||
|                 $actionCell.append($openButton); | ||||
|             } | ||||
|             else { | ||||
|                 messagingService.logError("Unknown labelType=" + definitionAttr.labelType); | ||||
|             } | ||||
|         } | ||||
|         else if (valueAttr.type === 'relation') { | ||||
|             if (valueAttr.value) { | ||||
|                 $input.val(await treeUtils.getNoteTitle(valueAttr.value)); | ||||
|             } | ||||
|  | ||||
|             // no need to wait for this | ||||
|             noteAutocompleteService.initNoteAutocomplete($input); | ||||
|  | ||||
|             $input.on('autocomplete:selected', function(event, suggestion, dataset) { | ||||
|                 promotedAttributeChanged(event); | ||||
|             }); | ||||
|  | ||||
|             $input.prop("data-selected-path", valueAttr.value); | ||||
|  | ||||
|             // ideally we'd use link instead of button which would allow tooltip preview, but | ||||
|             // we can't guarantee updating the link in the a element | ||||
|             const $openButton = $("<button>").addClass("btn btn-sm").text("Open").click(() => { | ||||
|                 const notePath = $input.getSelectedPath(); | ||||
|  | ||||
|                 if (notePath) { | ||||
|                     treeService.activateNote(notePath); | ||||
|                 } | ||||
|                 else { | ||||
|                     console.log("Empty note path, nothing to open."); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             $actionCell.append($openButton); | ||||
|         } | ||||
|         else { | ||||
|             messagingService.logError("Unknown attribute type=" + valueAttr.type); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (definition.multiplicityType === "multivalue") { | ||||
|             const addButton = $("<span>") | ||||
|                 .addClass("jam jam-plus pointer") | ||||
|                 .prop("title", "Add new attribute") | ||||
|                 .click(async () => { | ||||
|                     const $new = await createRow(definitionAttr, { | ||||
|                         attributeId: "", | ||||
|                         type: valueAttr.type, | ||||
|                         name: definitionAttr.name, | ||||
|                         value: "" | ||||
|                     }); | ||||
|  | ||||
|                     $tr.after($new); | ||||
|  | ||||
|                     $new.find('input').focus(); | ||||
|                 }); | ||||
|  | ||||
|             const removeButton = $("<span>") | ||||
|                 .addClass("jam jam-trash pointer") | ||||
|                 .prop("title", "Remove this attribute") | ||||
|                 .click(async () => { | ||||
|                     if (valueAttr.attributeId) { | ||||
|                         await server.remove("notes/" + noteId + "/attributes/" + valueAttr.attributeId); | ||||
|                     } | ||||
|  | ||||
|                     $tr.remove(); | ||||
|                 }); | ||||
|  | ||||
|             $multiplicityCell.append(addButton).append("   ").append(removeButton); | ||||
|         } | ||||
|  | ||||
|         return $tr; | ||||
|     } | ||||
|  | ||||
|     if (promoted.length > 0) { | ||||
|         const $tbody = $("<tbody>"); | ||||
|  | ||||
| @@ -222,7 +60,7 @@ async function showAttributes() { | ||||
|             } | ||||
|  | ||||
|             for (const valueAttr of valueAttrs) { | ||||
|                 const $tr = await createRow(definitionAttr, valueAttr); | ||||
|                 const $tr = await createPromotedAttributeRow(definitionAttr, valueAttr); | ||||
|  | ||||
|                 $tbody.append($tr); | ||||
|             } | ||||
| @@ -232,9 +70,7 @@ async function showAttributes() { | ||||
|         // (previously we saw promoted attributes doubling) | ||||
|         $promotedAttributesContainer.empty().append($tbody); | ||||
|     } | ||||
|     else { | ||||
|         $attributeListInner.empty(); | ||||
|  | ||||
|     else if (note.type !== 'relation-map') { | ||||
|         if (attributes.length > 0) { | ||||
|             for (const attribute of attributes) { | ||||
|                 if (attribute.type === 'label') { | ||||
| @@ -265,6 +101,162 @@ async function showAttributes() { | ||||
|     return attributes; | ||||
| } | ||||
|  | ||||
| async function createPromotedAttributeRow(definitionAttr, valueAttr) { | ||||
|     const definition = definitionAttr.value; | ||||
|     const $tr = $("<tr>"); | ||||
|     const $labelCell = $("<th>").append(valueAttr.name); | ||||
|     const $input = $("<input>") | ||||
|         .prop("tabindex", definitionAttr.position) | ||||
|         .prop("attribute-id", valueAttr.isOwned ? 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) | ||||
|         .prop("value", valueAttr.value) | ||||
|         .addClass("form-control") | ||||
|         .addClass("promoted-attribute-input") | ||||
|         .change(promotedAttributeChanged); | ||||
|  | ||||
|     const $inputCell = $("<td>").append($("<div>").addClass("input-group").append($input)); | ||||
|  | ||||
|     const $actionCell = $("<td>"); | ||||
|     const $multiplicityCell = $("<td>").addClass("multiplicity"); | ||||
|  | ||||
|     $tr | ||||
|         .append($labelCell) | ||||
|         .append($inputCell) | ||||
|         .append($actionCell) | ||||
|         .append($multiplicityCell); | ||||
|  | ||||
|     if (valueAttr.type === 'label') { | ||||
|         if (definition.labelType === 'text') { | ||||
|             $input.prop("type", "text"); | ||||
|  | ||||
|             // no need to await for this, can be done asynchronously | ||||
|             server.get('attributes/values/' + encodeURIComponent(valueAttr.name)).then(attributeValues => { | ||||
|                 if (attributeValues.length === 0) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 attributeValues = attributeValues.map(attribute => { return { value: attribute }; }); | ||||
|  | ||||
|                 $input.autocomplete({ | ||||
|                     appendTo: document.querySelector('body'), | ||||
|                     hint: false, | ||||
|                     autoselect: true, | ||||
|                     openOnFocus: true, | ||||
|                     minLength: 0 | ||||
|                 }, [{ | ||||
|                     displayKey: 'value', | ||||
|                     source: function (term, cb) { | ||||
|                         term = term.toLowerCase(); | ||||
|  | ||||
|                         const filtered = attributeValues.filter(attr => attr.value.toLowerCase().includes(term)); | ||||
|  | ||||
|                         cb(filtered); | ||||
|                     } | ||||
|                 }]); | ||||
|             }); | ||||
|         } | ||||
|         else if (definition.labelType === 'number') { | ||||
|             $input.prop("type", "number"); | ||||
|         } | ||||
|         else if (definition.labelType === 'boolean') { | ||||
|             $input.prop("type", "checkbox"); | ||||
|  | ||||
|             if (valueAttr.value === "true") { | ||||
|                 $input.prop("checked", "checked"); | ||||
|             } | ||||
|         } | ||||
|         else if (definition.labelType === 'date') { | ||||
|             $input.prop("type", "date"); | ||||
|  | ||||
|             const $todayButton = $("<button>").addClass("btn btn-sm").text("Today").click(() => { | ||||
|                 $input.val(utils.formatDateISO(new Date())); | ||||
|                 $input.trigger("change"); | ||||
|             }); | ||||
|  | ||||
|             $actionCell.append($todayButton); | ||||
|         } | ||||
|         else if (definition.labelType === 'url') { | ||||
|             $input.prop("placeholder", "http://website..."); | ||||
|  | ||||
|             const $openButton = $("<button>").addClass("btn btn-sm").text("Open").click(() => { | ||||
|                 window.open($input.val(), '_blank'); | ||||
|             }); | ||||
|  | ||||
|             $actionCell.append($openButton); | ||||
|         } | ||||
|         else { | ||||
|             messagingService.logError("Unknown labelType=" + definitionAttr.labelType); | ||||
|         } | ||||
|     } | ||||
|     else if (valueAttr.type === 'relation') { | ||||
|         if (valueAttr.value) { | ||||
|             $input.val(await treeUtils.getNoteTitle(valueAttr.value)); | ||||
|         } | ||||
|  | ||||
|         // no need to wait for this | ||||
|         noteAutocompleteService.initNoteAutocomplete($input); | ||||
|  | ||||
|         $input.on('autocomplete:selected', function(event, suggestion, dataset) { | ||||
|             promotedAttributeChanged(event); | ||||
|         }); | ||||
|  | ||||
|         $input.prop("data-selected-path", valueAttr.value); | ||||
|  | ||||
|         // ideally we'd use link instead of button which would allow tooltip preview, but | ||||
|         // we can't guarantee updating the link in the a element | ||||
|         const $openButton = $("<button>").addClass("btn btn-sm").text("Open").click(() => { | ||||
|             const notePath = $input.getSelectedPath(); | ||||
|  | ||||
|             if (notePath) { | ||||
|                 treeService.activateNote(notePath); | ||||
|             } | ||||
|             else { | ||||
|                 console.log("Empty note path, nothing to open."); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         $actionCell.append($openButton); | ||||
|     } | ||||
|     else { | ||||
|         messagingService.logError("Unknown attribute type=" + valueAttr.type); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     if (definition.multiplicityType === "multivalue") { | ||||
|         const addButton = $("<span>") | ||||
|             .addClass("jam jam-plus pointer") | ||||
|             .prop("title", "Add new attribute") | ||||
|             .click(async () => { | ||||
|                 const $new = await createPromotedAttributeRow(definitionAttr, { | ||||
|                     attributeId: "", | ||||
|                     type: valueAttr.type, | ||||
|                     name: definitionAttr.name, | ||||
|                     value: "" | ||||
|                 }); | ||||
|  | ||||
|                 $tr.after($new); | ||||
|  | ||||
|                 $new.find('input').focus(); | ||||
|             }); | ||||
|  | ||||
|         const removeButton = $("<span>") | ||||
|             .addClass("jam jam-trash pointer") | ||||
|             .prop("title", "Remove this attribute") | ||||
|             .click(async () => { | ||||
|                 if (valueAttr.attributeId) { | ||||
|                     await server.remove("notes/" + noteId + "/attributes/" + valueAttr.attributeId); | ||||
|                 } | ||||
|  | ||||
|                 $tr.remove(); | ||||
|             }); | ||||
|  | ||||
|         $multiplicityCell.append(addButton).append("   ").append(removeButton); | ||||
|     } | ||||
|  | ||||
|     return $tr; | ||||
| } | ||||
|  | ||||
| async function promotedAttributeChanged(event) { | ||||
|     const $attr = $(event.target); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user