mirror of
https://github.com/zadam/trilium.git
synced 2025-02-25 07:25:32 +08:00
split out attribute_editor widget, WIP
This commit is contained in:
parent
9f527f0330
commit
a94ae81c30
3 changed files with 114 additions and 75 deletions
|
@ -45,13 +45,18 @@ const TPL = `
|
|||
border: 1px solid var(--main-border-color);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.attribute-errors {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<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-plus add-new-attribute-button" title="Add a new attribute"></div>
|
||||
|
||||
<div class="attribute-errors" style="display: none;"></div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
|
@ -171,6 +176,12 @@ const editorConfig = {
|
|||
};
|
||||
|
||||
export default class AttributeEditorWidget extends TabAwareWidget {
|
||||
constructor(attributeDetailWidget) {
|
||||
super();
|
||||
|
||||
this.attributeDetailWidget = attributeDetailWidget;
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
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.on('click', 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();
|
||||
this.$addNewAttributeButton.on('click', e => this.addNewAttribute(e));
|
||||
|
||||
if (!attrs) {
|
||||
return;
|
||||
}
|
||||
this.$saveAttributesButton = this.$widget.find('.save-attributes-button');
|
||||
this.$saveAttributesButton.on('click', () => this.save());
|
||||
|
||||
let type, name;
|
||||
this.$errors = this.$widget.find('.attribute-errors');
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
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: ({command}) => this.handleAddNewAttributeCommand(command)
|
||||
});
|
||||
}
|
||||
|
||||
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() {
|
||||
this.$saveAttributesButton.fadeOut();
|
||||
|
||||
const attributes = this.parseAttributes();
|
||||
|
||||
if (attributes) {
|
||||
|
@ -274,11 +292,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
return attrs;
|
||||
}
|
||||
catch (e) {
|
||||
this.$widget.attr("title", e.message);
|
||||
this.$widget.addClass("error");
|
||||
|
||||
this.$ownedExpander.addClass("error");
|
||||
this.$ownedExpanderText.text(e.message);
|
||||
this.$errors.show().text(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,7 +314,16 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -309,7 +332,15 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
if (pos && pos.textNode && pos.textNode.data) {
|
||||
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;
|
||||
|
||||
|
@ -370,7 +401,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
await this.renderOwnedAttributes(note.getOwnedAttributes());
|
||||
}
|
||||
|
||||
async renderOwnedAttributes(ownedAttributes) {
|
||||
async renderOwnedAttributes(ownedAttributes, ) {
|
||||
const $attributesContainer = $("<div>");
|
||||
|
||||
for (const attribute of ownedAttributes) {
|
||||
|
@ -378,6 +409,10 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
}
|
||||
|
||||
this.textEditor.setData($attributesContainer.html());
|
||||
|
||||
this.lastSavedContent = this.textEditor.getData();
|
||||
|
||||
this.$saveAttributesButton.fadeOut(0);
|
||||
}
|
||||
|
||||
async focusOnAttributesEvent({tabId}) {
|
||||
|
@ -386,7 +421,7 @@ export default class AttributeEditorWidget extends TabAwareWidget {
|
|||
}
|
||||
}
|
||||
|
||||
updateAttributeListCommand({attributes}) {
|
||||
updateAttributeList(attributes) {
|
||||
this.renderOwnedAttributes(attributes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,8 +93,8 @@ export default class AttributeListWidget extends TabAwareWidget {
|
|||
constructor() {
|
||||
super();
|
||||
|
||||
this.attributeEditorWidget = new AttributeEditorWidget().setParent(this);
|
||||
this.attributeDetailWidget = new AttributeDetailWidget().setParent(this);
|
||||
this.attributeEditorWidget = new AttributeEditorWidget(this.attributeDetailWidget).setParent(this);
|
||||
|
||||
this.child(this.attributeEditorWidget, this.attributeDetailWidget);
|
||||
}
|
||||
|
@ -183,4 +183,8 @@ export default class AttributeListWidget extends TabAwareWidget {
|
|||
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 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) {
|
||||
valueAttrs.push({
|
||||
|
|
Loading…
Reference in a new issue