mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
split out attribute_editor widget, WIP
This commit is contained in:
parent
9f527f0330
commit
a94ae81c30
@ -45,13 +45,18 @@ const TPL = `
|
|||||||
border: 1px solid var(--main-border-color);
|
border: 1px solid var(--main-border-color);
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attribute-errors {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="attribute-list-editor" tabindex="200"></div>
|
<div class="attribute-list-editor" tabindex="200"></div>
|
||||||
|
|
||||||
<div class="bx bx-save save-attributes-button" title="Save attributes <enter>, <tab>)"></div>
|
<div class="bx bx-save save-attributes-button" title="Save attributes <enter>, <tab>)"></div>
|
||||||
|
|
||||||
<div class="bx bx-plus add-new-attribute-button" title="Add a new attribute"></div>
|
<div class="bx bx-plus add-new-attribute-button" title="Add a new attribute"></div>
|
||||||
|
|
||||||
|
<div class="attribute-errors" style="display: none;"></div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -171,6 +176,12 @@ const editorConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default class AttributeEditorWidget extends TabAwareWidget {
|
export default class AttributeEditorWidget extends TabAwareWidget {
|
||||||
|
constructor(attributeDetailWidget) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.attributeDetailWidget = attributeDetailWidget;
|
||||||
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
this.$editor = this.$widget.find('.attribute-list-editor');
|
this.$editor = this.$widget.find('.attribute-list-editor');
|
||||||
@ -190,76 +201,83 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.$addNewAttributeButton = this.$widget.find('.add-new-attribute-button');
|
this.$addNewAttributeButton = this.$widget.find('.add-new-attribute-button');
|
||||||
this.$addNewAttributeButton.on('click', e => {
|
this.$addNewAttributeButton.on('click', e => this.addNewAttribute(e));
|
||||||
contextMenuService.show({
|
|
||||||
x: e.pageX,
|
|
||||||
y: e.pageY,
|
|
||||||
orientation: 'left',
|
|
||||||
items: [
|
|
||||||
{title: "Add new label", command: "addNewLabel", uiIcon: "hash"},
|
|
||||||
{title: "Add new relation", command: "addNewRelation", uiIcon: "transfer"},
|
|
||||||
{title: "----"},
|
|
||||||
{title: "Add new label definition", command: "addNewLabelDefinition", uiIcon: "empty"},
|
|
||||||
{title: "Add new relation definition", command: "addNewRelationDefinition", uiIcon: "empty"},
|
|
||||||
],
|
|
||||||
selectMenuItemHandler: async ({command}) => {
|
|
||||||
const attrs = this.parseAttributes();
|
|
||||||
|
|
||||||
if (!attrs) {
|
this.$saveAttributesButton = this.$widget.find('.save-attributes-button');
|
||||||
return;
|
this.$saveAttributesButton.on('click', () => this.save());
|
||||||
}
|
|
||||||
|
|
||||||
let type, name;
|
this.$errors = this.$widget.find('.attribute-errors');
|
||||||
|
}
|
||||||
|
|
||||||
if (command === 'addNewLabel') {
|
addNewAttribute(e) {
|
||||||
type = 'label';
|
contextMenuService.show({
|
||||||
name = 'fillName';
|
x: e.pageX,
|
||||||
}
|
y: e.pageY,
|
||||||
else if (command === 'addNewRelation') {
|
orientation: 'left',
|
||||||
type = 'relation';
|
items: [
|
||||||
name = 'fillName';
|
{title: "Add new label", command: "addNewLabel", uiIcon: "hash"},
|
||||||
}
|
{title: "Add new relation", command: "addNewRelation", uiIcon: "transfer"},
|
||||||
else if (command === 'addNewLabelDefinition') {
|
{title: "----"},
|
||||||
type = 'label';
|
{title: "Add new label definition", command: "addNewLabelDefinition", uiIcon: "empty"},
|
||||||
name = 'label:fillName';
|
{title: "Add new relation definition", command: "addNewRelationDefinition", uiIcon: "empty"},
|
||||||
}
|
],
|
||||||
else if (command === 'addNewRelationDefinition') {
|
selectMenuItemHandler: ({command}) => this.handleAddNewAttributeCommand(command)
|
||||||
type = 'label';
|
|
||||||
name = 'relation:fillName';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
attrs.push({
|
|
||||||
type,
|
|
||||||
name,
|
|
||||||
value: '',
|
|
||||||
isInheritable: false
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.renderOwnedAttributes(attrs);
|
|
||||||
|
|
||||||
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({
|
|
||||||
allAttributes: attrs,
|
|
||||||
attribute: attrs[attrs.length - 1],
|
|
||||||
isOwned: true,
|
|
||||||
x: (rect.left + rect.right) / 2,
|
|
||||||
y: rect.bottom
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleAddNewAttributeCommand(command) {
|
||||||
|
const attrs = this.parseAttributes();
|
||||||
|
|
||||||
|
if (!attrs) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let type, name;
|
||||||
|
|
||||||
|
if (command === 'addNewLabel') {
|
||||||
|
type = 'label';
|
||||||
|
name = 'fillName';
|
||||||
|
} else if (command === 'addNewRelation') {
|
||||||
|
type = 'relation';
|
||||||
|
name = 'fillName';
|
||||||
|
} else if (command === 'addNewLabelDefinition') {
|
||||||
|
type = 'label';
|
||||||
|
name = 'label:fillName';
|
||||||
|
} else if (command === 'addNewRelationDefinition') {
|
||||||
|
type = 'label';
|
||||||
|
name = 'relation:fillName';
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs.push({
|
||||||
|
type,
|
||||||
|
name,
|
||||||
|
value: '',
|
||||||
|
isInheritable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.renderOwnedAttributes(attrs);
|
||||||
|
|
||||||
|
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({
|
||||||
|
allAttributes: attrs,
|
||||||
|
attribute: attrs[attrs.length - 1],
|
||||||
|
isOwned: true,
|
||||||
|
x: (rect.left + rect.right) / 2,
|
||||||
|
y: rect.bottom
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
|
this.$saveAttributesButton.fadeOut();
|
||||||
|
|
||||||
const attributes = this.parseAttributes();
|
const attributes = this.parseAttributes();
|
||||||
|
|
||||||
if (attributes) {
|
if (attributes) {
|
||||||
@ -274,11 +292,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
return attrs;
|
return attrs;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
this.$widget.attr("title", e.message);
|
this.$errors.show().text(e.message);
|
||||||
this.$widget.addClass("error");
|
|
||||||
|
|
||||||
this.$ownedExpander.addClass("error");
|
|
||||||
this.$ownedExpanderText.text(e.message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -300,7 +314,16 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dataChanged() {
|
dataChanged() {
|
||||||
console.log("Data changed");
|
if (this.lastSavedContent === this.textEditor.getData()) {
|
||||||
|
this.$saveAttributesButton.fadeOut();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$saveAttributesButton.fadeIn();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$errors.is(":visible")) {
|
||||||
|
this.$errors.slideUp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleEditorClick(e) {
|
async handleEditorClick(e) {
|
||||||
@ -309,7 +332,15 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
if (pos && pos.textNode && pos.textNode.data) {
|
if (pos && pos.textNode && pos.textNode.data) {
|
||||||
const clickIndex = this.getClickIndex(pos);
|
const clickIndex = this.getClickIndex(pos);
|
||||||
|
|
||||||
const parsedAttrs = attributesParser.lexAndParse(this.textEditor.getData(), true);
|
let parsedAttrs;
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsedAttrs = attributesParser.lexAndParse(this.textEditor.getData(), true);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// the input is incorrect because user messed up with it and now needs to fix it manually
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
let matchedAttr = null;
|
let matchedAttr = null;
|
||||||
|
|
||||||
@ -370,7 +401,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
await this.renderOwnedAttributes(note.getOwnedAttributes());
|
await this.renderOwnedAttributes(note.getOwnedAttributes());
|
||||||
}
|
}
|
||||||
|
|
||||||
async renderOwnedAttributes(ownedAttributes) {
|
async renderOwnedAttributes(ownedAttributes, ) {
|
||||||
const $attributesContainer = $("<div>");
|
const $attributesContainer = $("<div>");
|
||||||
|
|
||||||
for (const attribute of ownedAttributes) {
|
for (const attribute of ownedAttributes) {
|
||||||
@ -378,6 +409,10 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.textEditor.setData($attributesContainer.html());
|
this.textEditor.setData($attributesContainer.html());
|
||||||
|
|
||||||
|
this.lastSavedContent = this.textEditor.getData();
|
||||||
|
|
||||||
|
this.$saveAttributesButton.fadeOut(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
async focusOnAttributesEvent({tabId}) {
|
async focusOnAttributesEvent({tabId}) {
|
||||||
@ -386,7 +421,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateAttributeListCommand({attributes}) {
|
updateAttributeList(attributes) {
|
||||||
this.renderOwnedAttributes(attributes);
|
this.renderOwnedAttributes(attributes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,8 @@ export default class AttributeListWidget extends TabAwareWidget {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.attributeEditorWidget = new AttributeEditorWidget().setParent(this);
|
|
||||||
this.attributeDetailWidget = new AttributeDetailWidget().setParent(this);
|
this.attributeDetailWidget = new AttributeDetailWidget().setParent(this);
|
||||||
|
this.attributeEditorWidget = new AttributeEditorWidget(this.attributeDetailWidget).setParent(this);
|
||||||
|
|
||||||
this.child(this.attributeEditorWidget, this.attributeDetailWidget);
|
this.child(this.attributeEditorWidget, this.attributeDetailWidget);
|
||||||
}
|
}
|
||||||
@ -183,4 +183,8 @@ export default class AttributeListWidget extends TabAwareWidget {
|
|||||||
attributeRenderer.renderAttribute(attribute, $span, false);
|
attributeRenderer.renderAttribute(attribute, $span, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateAttributeListCommand({attributes}) {
|
||||||
|
this.attributeEditorWidget.updateAttributeList(attributes);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
|||||||
const definitionType = definitionAttr.name.startsWith('label:') ? 'label' : 'relation';
|
const definitionType = definitionAttr.name.startsWith('label:') ? 'label' : 'relation';
|
||||||
const valueName = definitionAttr.name.substr(definitionType.length + 1);
|
const valueName = definitionAttr.name.substr(definitionType.length + 1);
|
||||||
|
|
||||||
let valueAttrs = attributes.filter(el => el.name === definitionAttr.name && el.type === definitionType);
|
let valueAttrs = attributes.filter(el => el.name === valueName && el.type === 'label');
|
||||||
|
|
||||||
if (valueAttrs.length === 0) {
|
if (valueAttrs.length === 0) {
|
||||||
valueAttrs.push({
|
valueAttrs.push({
|
||||||
|
Loading…
x
Reference in New Issue
Block a user