This commit is contained in:
zadam
2020-07-09 23:59:27 +02:00
parent 055db32510
commit 0ecb2f3662
8 changed files with 149 additions and 109 deletions

View File

@@ -195,6 +195,7 @@ function lexAndParse(str, allowEmptyRelations = false) {
}
export default {
preprocess,
lexer,
parser,
lexAndParse

View File

@@ -115,13 +115,16 @@ export default class AttributeDetailWidget extends BasicWidget {
});
}
async showAttributeDetail({attribute, isOwned, x, y}) {
async showAttributeDetail({allAttributes, attribute, isOwned, x, y}) {
if (!attribute) {
this.hide();
return;
}
this.allAttributes = allAttributes;
this.attribute = attribute;
this.toggleInt(true);
let {results, count} = await server.post('search-related', attribute);
@@ -173,11 +176,13 @@ export default class AttributeDetailWidget extends BasicWidget {
this.$attrEditName
.val(attribute.name)
.attr('readonly', () => !isOwned);
.attr('readonly', () => !isOwned)
.on('keyup', () => this.updateParent());
this.$attrEditValue
.val(attribute.value)
.attr('readonly', () => !isOwned);
.attr('readonly', () => !isOwned)
.on('keyup', () => this.updateParent());
this.$attrEditButtonRow.toggle(!!isOwned);
@@ -186,6 +191,13 @@ export default class AttributeDetailWidget extends BasicWidget {
this.$widget.show();
}
updateParent() {
this.attribute.name = this.$attrEditName.val();
this.attribute.value = this.$attrEditValue.val();
this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
}
hide() {
this.toggleInt(false);
}

View File

@@ -71,6 +71,59 @@ const mentionSetup = {
]
};
const editorConfig = {
removePlugins: [
'Enter',
'ShiftEnter',
'Heading',
'Link',
'Autoformat',
'Bold',
'Italic',
'Underline',
'Strikethrough',
'Code',
'Superscript',
'Subscript',
'BlockQuote',
'Image',
'ImageCaption',
'ImageStyle',
'ImageToolbar',
'ImageUpload',
'ImageResize',
'List',
'TodoList',
'PasteFromOffice',
'Table',
'TableToolbar',
'TableProperties',
'TableCellProperties',
'Indent',
'IndentBlock',
'BlockToolbar',
'ParagraphButtonUI',
'HeadingButtonsUI',
'UploadimagePlugin',
'InternalLinkPlugin',
'MarkdownImportPlugin',
'CuttonotePlugin',
'TextTransformation',
'Font',
'FontColor',
'FontBackgroundColor',
'CodeBlock',
'SelectAll',
'IncludeNote',
'CutToNote'
],
toolbar: {
items: []
},
placeholder: "Type the labels and relations here ...",
mention: mentionSetup
};
const TPL = `
<div class="note-attributes">
<style>
@@ -321,102 +374,48 @@ export default class NoteAttributesWidget extends TabAwareWidget {
async initEditor() {
await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
// CKEditor since version 12 needs the element to be visible before initialization. At the same time
// we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
// display of $widget in both branches.
this.$widget.show();
this.$editor.on("click", async e => {
const pos = this.textEditor.model.document.selection.getFirstPosition();
if (pos && pos.textNode && pos.textNode.data) {
const attrText = pos.textNode.data;
const clickIndex = pos.offset - pos.textNode.startOffset;
const parsedAttrs = attributesParser.lexAndParse(attrText, true);
let matchedAttr = null;
for (const attr of parsedAttrs) {
if (clickIndex >= attr.startIndex && clickIndex <= attr.endIndex) {
matchedAttr = attr;
break;
}
}
this.attributeDetailWidget.showAttributeDetail({
attribute: matchedAttr,
isOwned: true,
x: e.pageX,
y: e.pageY
});
}
});
this.textEditor = await BalloonEditor.create(this.$editor[0], {
removePlugins: [
'Enter',
'ShiftEnter',
'Heading',
'Link',
'Autoformat',
'Bold',
'Italic',
'Underline',
'Strikethrough',
'Code',
'Superscript',
'Subscript',
'BlockQuote',
'Image',
'ImageCaption',
'ImageStyle',
'ImageToolbar',
'ImageUpload',
'ImageResize',
'List',
'TodoList',
'PasteFromOffice',
'Table',
'TableToolbar',
'TableProperties',
'TableCellProperties',
'Indent',
'IndentBlock',
'BlockToolbar',
'ParagraphButtonUI',
'HeadingButtonsUI',
'UploadimagePlugin',
'InternalLinkPlugin',
'MarkdownImportPlugin',
'CuttonotePlugin',
'TextTransformation',
'Font',
'FontColor',
'FontBackgroundColor',
'CodeBlock',
'SelectAll',
'IncludeNote',
'CutToNote'
],
toolbar: {
items: []
},
placeholder: "Type the labels and relations here ...",
mention: mentionSetup
});
this.$editor.on("click", e => this.handleEditorClick(e));
this.textEditor = await BalloonEditor.create(this.$editor[0], editorConfig);
this.textEditor.model.document.on('change:data', () => this.spacedUpdate.scheduleUpdate());
// disable spellcheck for attribute editor
this.textEditor.editing.view.change( writer => {
writer.setAttribute( 'spellcheck', 'false', this.textEditor.editing.view.document.getRoot() );
} );
this.textEditor.editing.view.change(writer => writer.setAttribute('spellcheck', 'false', this.textEditor.editing.view.document.getRoot()));
//await import(/* webpackIgnore: true */'../../libraries/ckeditor/inspector.js');
//CKEditorInspector.attach(this.textEditor);
}
async handleEditorClick(e) {
const pos = this.textEditor.model.document.selection.getFirstPosition();
if (pos && pos.textNode && pos.textNode.data) {
const attrText = pos.textNode.data;
const clickIndex = pos.offset - pos.textNode.startOffset;
const parsedAttrs = attributesParser.lexAndParse(attrText, true);
let matchedAttr = null;
for (const attr of parsedAttrs) {
if (clickIndex >= attr.startIndex && clickIndex <= attr.endIndex) {
matchedAttr = attr;
break;
}
}
this.attributeDetailWidget.showAttributeDetail({
allAttributes: parsedAttrs,
attribute: matchedAttr,
isOwned: true,
x: e.pageX,
y: e.pageY
});
}
}
async loadReferenceLinkTitle(noteId, $el) {
const note = await treeCache.getNote(noteId, true);
@@ -436,14 +435,7 @@ export default class NoteAttributesWidget extends TabAwareWidget {
}
async refreshWithNote(note) {
const ownedAttributes = note.getOwnedAttributes();
const $attributesContainer = $("<div>");
await this.renderAttributesIntoCKEditor(ownedAttributes, $attributesContainer);
await this.spacedUpdate.allowUpdateWithoutChange(() => {
this.textEditor.setData($attributesContainer.html());
});
await this.renderOwnedAttributes(note.getOwnedAttributes());
const inheritedAttributes = note.getAttributes().filter(attr => attr.noteId !== this.noteId);
@@ -465,6 +457,16 @@ export default class NoteAttributesWidget extends TabAwareWidget {
this.parseAttributes();
}
async renderOwnedAttributes(ownedAttributes) {
const $attributesContainer = $("<div>");
await this.renderAttributesIntoCKEditor(ownedAttributes, $attributesContainer);
await this.spacedUpdate.allowUpdateWithoutChange(() => {
this.textEditor.setData($attributesContainer.html());
});
}
attrPlural(number) {
return 'attribute' + (number === 1 ? '' : 's');
}
@@ -554,4 +556,8 @@ export default class NoteAttributesWidget extends TabAwareWidget {
this.$editor.trigger('focus');
}
}
updateAttributeListCommand({attributes}) {
this.renderOwnedAttributes(attributes);
}
}

View File

@@ -168,7 +168,23 @@ function executeWithoutTransaction(query, params = []) {
}
function executeMany(query, params) {
getManyRows(query, params);
while (params.length > 0) {
const curParams = params.slice(0, Math.min(params.length, PARAM_LIMIT));
params = params.slice(curParams.length);
const curParamsObj = {};
let j = 1;
for (const param of curParams) {
curParamsObj['param' + j++] = param;
}
let i = 1;
const questionMarks = curParams.map(() => ":param" + i++).join(",");
const curQuery = query.replace(/\?\?\?/g, questionMarks);
dbConnection.prepare(curQuery).run(curParamsObj);
}
}
function executeScript(query) {