mirror of
https://github.com/zadam/trilium.git
synced 2025-02-25 15:35:43 +08:00
add label/relation from menu
This commit is contained in:
parent
528418aecb
commit
3d02f82c77
4 changed files with 93 additions and 52 deletions
|
@ -7,10 +7,10 @@ class ContextMenu {
|
||||||
|
|
||||||
$(document).on('click', () => this.hide());
|
$(document).on('click', () => this.hide());
|
||||||
}
|
}
|
||||||
|
|
||||||
async show(options) {
|
async show(options) {
|
||||||
this.options = options;
|
this.options = options;
|
||||||
|
|
||||||
this.$widget.empty();
|
this.$widget.empty();
|
||||||
|
|
||||||
this.addItems(this.$widget, options.items);
|
this.addItems(this.$widget, options.items);
|
||||||
|
@ -27,7 +27,7 @@ class ContextMenu {
|
||||||
// in such case we'll position it above click coordinates so it will fit into client
|
// in such case we'll position it above click coordinates so it will fit into client
|
||||||
const clientHeight = document.documentElement.clientHeight;
|
const clientHeight = document.documentElement.clientHeight;
|
||||||
const contextMenuHeight = this.$widget.outerHeight() + 30;
|
const contextMenuHeight = this.$widget.outerHeight() + 30;
|
||||||
let top;
|
let top, left;
|
||||||
|
|
||||||
if (this.options.y + contextMenuHeight > clientHeight) {
|
if (this.options.y + contextMenuHeight > clientHeight) {
|
||||||
top = clientHeight - contextMenuHeight - 10;
|
top = clientHeight - contextMenuHeight - 10;
|
||||||
|
@ -35,10 +35,17 @@ class ContextMenu {
|
||||||
top = this.options.y - 10;
|
top = this.options.y - 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.options.orientation === 'left') {
|
||||||
|
left = this.options.x - this.$widget.outerWidth() + 20;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
left = this.options.x - 20;
|
||||||
|
}
|
||||||
|
|
||||||
this.$widget.css({
|
this.$widget.css({
|
||||||
display: "block",
|
display: "block",
|
||||||
top: top,
|
top: top,
|
||||||
left: this.options.x - 20
|
left: left
|
||||||
}).addClass("show");
|
}).addClass("show");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,4 +120,4 @@ class ContextMenu {
|
||||||
|
|
||||||
const contextMenu = new ContextMenu();
|
const contextMenu = new ContextMenu();
|
||||||
|
|
||||||
export default contextMenu;
|
export default contextMenu;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import BasicWidget from "./basic_widget.js";
|
||||||
import noteAutocompleteService from "../services/note_autocomplete.js";
|
import noteAutocompleteService from "../services/note_autocomplete.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="attr-detail" style="display: none;">
|
<div class="attr-detail">
|
||||||
<style>
|
<style>
|
||||||
.attr-detail {
|
.attr-detail {
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -14,7 +14,7 @@ const TPL = `
|
||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-border-color);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
padding: 10px;
|
padding: 15px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
max-width: 600px;
|
max-width: 600px;
|
||||||
max-height: 600px;
|
max-height: 600px;
|
||||||
|
@ -76,13 +76,15 @@ const TPL = `
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br/>
|
<div class="related-notes-container">
|
||||||
|
<br/>
|
||||||
|
|
||||||
<h5 class="related-notes-tile">Other notes with this label</h5>
|
<h5 class="related-notes-tile">Other notes with this label</h5>
|
||||||
|
|
||||||
<ul class="related-notes-list"></ul>
|
<ul class="related-notes-list"></ul>
|
||||||
|
|
||||||
<div class="related-notes-more-notes"></div>
|
<div class="related-notes-more-notes"></div>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
|
|
||||||
|
@ -91,9 +93,11 @@ const DISPLAYED_NOTES = 10;
|
||||||
export default class AttributeDetailWidget extends BasicWidget {
|
export default class AttributeDetailWidget extends BasicWidget {
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$relatedNotesTitle = this.$widget.find('.related-notes-tile');
|
|
||||||
this.$relatedNotesList = this.$widget.find('.related-notes-list');
|
this.$relatedNotesContainer = this.$widget.find('.related-notes-container');
|
||||||
this.$relatedNotesMoreNotes = this.$widget.find('.related-notes-more-notes');
|
this.$relatedNotesTitle = this.$relatedNotesContainer.find('.related-notes-tile');
|
||||||
|
this.$relatedNotesList = this.$relatedNotesContainer.find('.related-notes-list');
|
||||||
|
this.$relatedNotesMoreNotes = this.$relatedNotesContainer.find('.related-notes-more-notes');
|
||||||
|
|
||||||
this.$attrEditName = this.$widget.find('.attr-edit-name');
|
this.$attrEditName = this.$widget.find('.attr-edit-name');
|
||||||
this.$attrEditName.on('keyup', () => this.updateParent());
|
this.$attrEditName.on('keyup', () => this.updateParent());
|
||||||
|
@ -130,6 +134,8 @@ export default class AttributeDetailWidget extends BasicWidget {
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.toggleInt(false); // initial state is hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
async showAttributeDetail({allAttributes, attribute, isOwned, x, y}) {
|
async showAttributeDetail({allAttributes, attribute, isOwned, x, y}) {
|
||||||
|
@ -142,8 +148,6 @@ export default class AttributeDetailWidget extends BasicWidget {
|
||||||
this.allAttributes = allAttributes;
|
this.allAttributes = allAttributes;
|
||||||
this.attribute = attribute;
|
this.attribute = attribute;
|
||||||
|
|
||||||
this.toggleInt(true);
|
|
||||||
|
|
||||||
let {results, count} = await server.post('search-related', attribute);
|
let {results, count} = await server.post('search-related', attribute);
|
||||||
|
|
||||||
for (const res of results) {
|
for (const res of results) {
|
||||||
|
@ -153,31 +157,32 @@ export default class AttributeDetailWidget extends BasicWidget {
|
||||||
results = results.filter(({noteId}) => noteId !== this.noteId);
|
results = results.filter(({noteId}) => noteId !== this.noteId);
|
||||||
|
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
this.$relatedNotesTitle.hide();
|
this.$relatedNotesContainer.hide();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
this.$relatedNotesContainer.show();
|
||||||
this.$relatedNotesTitle.text(`Other notes with ${attribute.type} name "${attribute.name}"`);
|
this.$relatedNotesTitle.text(`Other notes with ${attribute.type} name "${attribute.name}"`);
|
||||||
}
|
|
||||||
|
|
||||||
this.$relatedNotesList.empty();
|
this.$relatedNotesList.empty();
|
||||||
|
|
||||||
const displayedResults = results.length <= DISPLAYED_NOTES ? results : results.slice(0, DISPLAYED_NOTES);
|
const displayedResults = results.length <= DISPLAYED_NOTES ? results : results.slice(0, DISPLAYED_NOTES);
|
||||||
const displayedNotes = await treeCache.getNotes(displayedResults.map(res => res.noteId));
|
const displayedNotes = await treeCache.getNotes(displayedResults.map(res => res.noteId));
|
||||||
|
|
||||||
for (const note of displayedNotes) {
|
for (const note of displayedNotes) {
|
||||||
const notePath = treeService.getSomeNotePath(note);
|
const notePath = treeService.getSomeNotePath(note);
|
||||||
const $noteLink = await linkService.createNoteLink(notePath, {showNotePath: true});
|
const $noteLink = await linkService.createNoteLink(notePath, {showNotePath: true});
|
||||||
|
|
||||||
this.$relatedNotesList.append(
|
this.$relatedNotesList.append(
|
||||||
$("<li>").append($noteLink)
|
$("<li>").append($noteLink)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.length > DISPLAYED_NOTES) {
|
if (results.length > DISPLAYED_NOTES) {
|
||||||
this.$relatedNotesMoreNotes.show().text(`... and ${count - DISPLAYED_NOTES} more.`);
|
this.$relatedNotesMoreNotes.show().text(`... and ${count - DISPLAYED_NOTES} more.`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.$relatedNotesMoreNotes.hide();
|
this.$relatedNotesMoreNotes.hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOwned) {
|
if (isOwned) {
|
||||||
|
@ -212,11 +217,14 @@ export default class AttributeDetailWidget extends BasicWidget {
|
||||||
.setSelectedNotePath(attribute.value);
|
.setSelectedNotePath(attribute.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$attrEditInheritable.prop("checked", !!attribute.isInheritable);
|
this.$attrEditInheritable
|
||||||
|
.prop("checked", !!attribute.isInheritable)
|
||||||
|
.attr('disabled', () => !isOwned);
|
||||||
|
|
||||||
this.$widget.css("left", x - this.$widget.width() / 2);
|
this.toggleInt(true);
|
||||||
this.$widget.css("top", y + 30);
|
|
||||||
this.$widget.show();
|
this.$widget.css("left", x - this.$widget.outerWidth() / 2);
|
||||||
|
this.$widget.css("top", y + 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateParent() {
|
updateParent() {
|
||||||
|
|
|
@ -51,7 +51,9 @@ class BasicWidget extends Component {
|
||||||
this.$widget.addClass('component')
|
this.$widget.addClass('component')
|
||||||
.prop('component', this);
|
.prop('component', this);
|
||||||
|
|
||||||
this.toggleInt(this.isEnabled());
|
if (!this.isEnabled()) {
|
||||||
|
this.toggleInt(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.cssEl) {
|
if (this.cssEl) {
|
||||||
const css = this.cssEl.trim().startsWith('<style>') ? this.cssEl : `<style>${this.cssEl}</style>`;
|
const css = this.cssEl.trim().startsWith('<style>') ? this.cssEl : `<style>${this.cssEl}</style>`;
|
||||||
|
|
|
@ -326,12 +326,13 @@ export default class NoteAttributesWidget extends TabAwareWidget {
|
||||||
contextMenuService.show({
|
contextMenuService.show({
|
||||||
x: e.pageX,
|
x: e.pageX,
|
||||||
y: e.pageY,
|
y: e.pageY,
|
||||||
|
orientation: 'left',
|
||||||
items: [
|
items: [
|
||||||
{title: "Add new label", command: "addNewLabel", uiIcon: "hash"},
|
{title: "Add new label", command: "addNewLabel", uiIcon: "hash"},
|
||||||
{title: "Add new relation", command: "addNewRelation", uiIcon: "transfer"},
|
{title: "Add new relation", command: "addNewRelation", uiIcon: "transfer"},
|
||||||
{title: "----"},
|
{title: "----"},
|
||||||
{title: "Add new label definition", command: "addNewRelation", uiIcon: "empty"},
|
{title: "Add new label definition", command: "addNewLabelDefinition", uiIcon: "empty"},
|
||||||
{title: "Add new relation definition", command: "addNewRelation", uiIcon: "empty"},
|
{title: "Add new relation definition", command: "addNewRelationDefinition", uiIcon: "empty"},
|
||||||
],
|
],
|
||||||
selectMenuItemHandler: async ({command}) => {
|
selectMenuItemHandler: async ({command}) => {
|
||||||
const attrs = this.parseAttributes();
|
const attrs = this.parseAttributes();
|
||||||
|
@ -340,20 +341,43 @@ export default class NoteAttributesWidget extends TabAwareWidget {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let type, name;
|
||||||
|
|
||||||
if (command === 'addNewLabel') {
|
if (command === 'addNewLabel') {
|
||||||
attrs.push({
|
type = 'label';
|
||||||
type: 'label',
|
name = 'fillName';
|
||||||
name: 'fillName',
|
}
|
||||||
value: '',
|
else if (command === 'addNewRelation') {
|
||||||
isInheritable: false
|
type = 'relation';
|
||||||
});
|
name = 'fillName';
|
||||||
|
}
|
||||||
|
else if (command === 'addNewLabelDefinition') {
|
||||||
|
type = 'label';
|
||||||
|
name = 'label:fillName';
|
||||||
|
}
|
||||||
|
else if (command === 'addNewRelationDefinition') {
|
||||||
|
type = 'label';
|
||||||
|
name = 'relation:fillName';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await this.renderOwnedAttributes(attrs);
|
attrs.push({
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
value: '',
|
||||||
|
isInheritable: false
|
||||||
|
});
|
||||||
|
|
||||||
this.$editor.scrollTop(this.$editor[0].scrollHeight);
|
await this.renderOwnedAttributes(attrs);
|
||||||
|
|
||||||
const rect = this.$editor[0].getBoundingClientRect();
|
this.$editor.scrollTop(this.$editor[0].scrollHeight);
|
||||||
|
|
||||||
|
const rect = this.$editor[0].getBoundingClientRect();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// showing a little bit later because there's a conflict with outside click closing the attr detail
|
||||||
this.attributeDetailWidget.showAttributeDetail({
|
this.attributeDetailWidget.showAttributeDetail({
|
||||||
allAttributes: attrs,
|
allAttributes: attrs,
|
||||||
attribute: attrs[attrs.length - 1],
|
attribute: attrs[attrs.length - 1],
|
||||||
|
@ -361,7 +385,7 @@ export default class NoteAttributesWidget extends TabAwareWidget {
|
||||||
x: (rect.left + rect.right) / 2,
|
x: (rect.left + rect.right) / 2,
|
||||||
y: rect.bottom
|
y: rect.bottom
|
||||||
});
|
});
|
||||||
}
|
}, 100);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue