mirror of
https://github.com/TriliumNext/Notes.git
synced 2025-07-27 18:12:29 +08:00
chore(client/ts): port widgets/attribute_widgets/attribute_detail
This commit is contained in:
parent
7a2b5e731e
commit
c5fa865d9d
@ -12,6 +12,7 @@ import utils from '../services/utils.js';
|
|||||||
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
* event / command is executed in all components - by simply awaiting the `triggerEvent()`.
|
||||||
*/
|
*/
|
||||||
export default class Component {
|
export default class Component {
|
||||||
|
$widget!: JQuery<HTMLElement>;
|
||||||
componentId: string;
|
componentId: string;
|
||||||
children: Component[];
|
children: Component[];
|
||||||
initialized: Promise<void> | null;
|
initialized: Promise<void> | null;
|
||||||
|
@ -3,9 +3,9 @@ import server from "./server.js";
|
|||||||
|
|
||||||
interface InitOptions {
|
interface InitOptions {
|
||||||
$el: JQuery<HTMLElement>;
|
$el: JQuery<HTMLElement>;
|
||||||
attributeType: AttributeType | (() => AttributeType);
|
attributeType?: AttributeType | (() => AttributeType);
|
||||||
open: boolean;
|
open: boolean;
|
||||||
nameCallback: () => string;
|
nameCallback?: () => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +54,10 @@ async function initLabelValueAutocomplete({ $el, open, nameCallback }: InitOptio
|
|||||||
$el.autocomplete('destroy');
|
$el.autocomplete('destroy');
|
||||||
}
|
}
|
||||||
|
|
||||||
const attributeName = nameCallback();
|
let attributeName = "";
|
||||||
|
if (nameCallback) {
|
||||||
|
attributeName = nameCallback();
|
||||||
|
}
|
||||||
|
|
||||||
if (attributeName.trim() === "") {
|
if (attributeName.trim() === "") {
|
||||||
return;
|
return;
|
||||||
|
@ -10,6 +10,8 @@ import SpacedUpdate from "../../services/spaced_update.js";
|
|||||||
import utils from "../../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
import shortcutService from "../../services/shortcuts.js";
|
import shortcutService from "../../services/shortcuts.js";
|
||||||
import appContext from "../../components/app_context.js";
|
import appContext from "../../components/app_context.js";
|
||||||
|
import FAttribute from "../../entities/fattribute.js";
|
||||||
|
import FNote, { FNoteRow } from "../../entities/fnote.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="attr-detail">
|
<div class="attr-detail">
|
||||||
@ -27,42 +29,42 @@ const TPL = `
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
box-shadow: 10px 10px 93px -25px black;
|
box-shadow: 10px 10px 93px -25px black;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-help td {
|
.attr-help td {
|
||||||
color: var(--muted-text-color);
|
color: var(--muted-text-color);
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.related-notes-list {
|
.related-notes-list {
|
||||||
padding-left: 20px;
|
padding-left: 20px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-edit-table {
|
.attr-edit-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-edit-table th {
|
.attr-edit-table th {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-edit-table td input {
|
.attr-edit-table td input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-attr-detail-button {
|
.close-attr-detail-button {
|
||||||
font-size: x-large;
|
font-size: x-large;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -2px;
|
top: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-save-delete-button-container {
|
.attr-save-delete-button-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.attr-detail input[readonly] {
|
.attr-detail input[readonly] {
|
||||||
background-color: var(--accented-background-color) !important;
|
background-color: var(--accented-background-color) !important;
|
||||||
}
|
}
|
||||||
@ -70,7 +72,7 @@ const TPL = `
|
|||||||
|
|
||||||
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
<div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
|
||||||
<h5 class="attr-detail-title">${t('attribute_detail.attr_detail_title')}</h5>
|
<h5 class="attr-detail-title">${t('attribute_detail.attr_detail_title')}</h5>
|
||||||
|
|
||||||
<span class="bx bx-x close-attr-detail-button" title="${t('attribute_detail.close_button_title')}"></span>
|
<span class="bx bx-x close-attr-detail-button" title="${t('attribute_detail.close_button_title')}"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -154,10 +156,10 @@ const TPL = `
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="attr-save-delete-button-container">
|
<div class="attr-save-delete-button-container">
|
||||||
<button class="btn btn-primary btn-sm attr-save-changes-and-close-button"
|
<button class="btn btn-primary btn-sm attr-save-changes-and-close-button"
|
||||||
style="flex-grow: 1; margin-right: 20px">
|
style="flex-grow: 1; margin-right: 20px">
|
||||||
${t('attribute_detail.save_and_close')}</button>
|
${t('attribute_detail.save_and_close')}</button>
|
||||||
|
|
||||||
<button class="btn btn-secondary btn-sm attr-delete-button">
|
<button class="btn btn-secondary btn-sm attr-delete-button">
|
||||||
${t('attribute_detail.delete')}</button>
|
${t('attribute_detail.delete')}</button>
|
||||||
</div>
|
</div>
|
||||||
@ -166,23 +168,23 @@ const TPL = `
|
|||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<h5 class="related-notes-tile">${t('attribute_detail.related_notes_title')}</h5>
|
<h5 class="related-notes-tile">${t('attribute_detail.related_notes_title')}</h5>
|
||||||
|
|
||||||
<ul class="related-notes-list"></ul>
|
<ul class="related-notes-list"></ul>
|
||||||
|
|
||||||
<div class="related-notes-more-notes">${t('attribute_detail.more_notes')}</div>
|
<div class="related-notes-more-notes">${t('attribute_detail.more_notes')}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const DISPLAYED_NOTES = 10;
|
const DISPLAYED_NOTES = 10;
|
||||||
|
|
||||||
const ATTR_TITLES = {
|
const ATTR_TITLES: Record<string, string> = {
|
||||||
"label": t('attribute_detail.label'),
|
"label": t('attribute_detail.label'),
|
||||||
"label-definition": t('attribute_detail.label_definition'),
|
"label-definition": t('attribute_detail.label_definition'),
|
||||||
"relation": t('attribute_detail.relation'),
|
"relation": t('attribute_detail.relation'),
|
||||||
"relation-definition": t('attribute_detail.relation_definition')
|
"relation-definition": t('attribute_detail.relation_definition')
|
||||||
};
|
};
|
||||||
|
|
||||||
const ATTR_HELP = {
|
const ATTR_HELP: Record<string, Record<string, string>> = {
|
||||||
"label": {
|
"label": {
|
||||||
"disableVersioning": t('attribute_detail.disable_versioning'),
|
"disableVersioning": t('attribute_detail.disable_versioning'),
|
||||||
"calendarRoot": t('attribute_detail.calendar_root'),
|
"calendarRoot": t('attribute_detail.calendar_root'),
|
||||||
@ -266,7 +268,61 @@ const ATTR_HELP = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface AttributeDetailOpts {
|
||||||
|
allAttributes: FAttribute[];
|
||||||
|
attribute: FAttribute;
|
||||||
|
isOwned: boolean;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
focus: "name";
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchRelatedResponse {
|
||||||
|
// TODO: Deduplicate once we split client from server.
|
||||||
|
results: {
|
||||||
|
noteId: string;
|
||||||
|
notePathArray: string[];
|
||||||
|
}[];
|
||||||
|
count: number;
|
||||||
|
}
|
||||||
|
|
||||||
export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
||||||
|
|
||||||
|
private $title!: JQuery<HTMLElement>;
|
||||||
|
private $inputName!: JQuery<HTMLElement>;
|
||||||
|
private $inputValue!: JQuery<HTMLElement>;
|
||||||
|
private $rowPromoted!: JQuery<HTMLElement>;
|
||||||
|
private $inputPromoted!: JQuery<HTMLElement>;
|
||||||
|
private $inputPromotedAlias!: JQuery<HTMLElement>;
|
||||||
|
private $inputMultiplicity!: JQuery<HTMLElement>;
|
||||||
|
private $inputInverseRelation!: JQuery<HTMLElement>;
|
||||||
|
private $inputLabelType!: JQuery<HTMLElement>;
|
||||||
|
private $inputTargetNote!: JQuery<HTMLElement>;
|
||||||
|
private $inputNumberPrecision!: JQuery<HTMLElement>;
|
||||||
|
private $inputInheritable!: JQuery<HTMLElement>;
|
||||||
|
private $rowValue!: JQuery<HTMLElement>;
|
||||||
|
private $rowMultiplicity!: JQuery<HTMLElement>;
|
||||||
|
private $rowLabelType!: JQuery<HTMLElement>;
|
||||||
|
private $rowNumberPrecision!: JQuery<HTMLElement>;
|
||||||
|
private $rowInverseRelation!: JQuery<HTMLElement>;
|
||||||
|
private $rowTargetNote!: JQuery<HTMLElement>;
|
||||||
|
private $rowPromotedAlias!: JQuery<HTMLElement>;
|
||||||
|
private $attrIsOwnedBy!: JQuery<HTMLElement>;
|
||||||
|
private $attrSaveDeleteButtonContainer!: JQuery<HTMLElement>;
|
||||||
|
private $closeAttrDetailButton!: JQuery<HTMLElement>;
|
||||||
|
private $saveAndCloseButton!: JQuery<HTMLElement>;
|
||||||
|
private $deleteButton!: JQuery<HTMLElement>;
|
||||||
|
private $relatedNotesContainer!: JQuery<HTMLElement>;
|
||||||
|
private $relatedNotesTitle!: JQuery<HTMLElement>;
|
||||||
|
private $relatedNotesList!: JQuery<HTMLElement>;
|
||||||
|
private $relatedNotesMoreNotes!: JQuery<HTMLElement>;
|
||||||
|
private $attrHelp!: JQuery<HTMLElement>;
|
||||||
|
|
||||||
|
private relatedNotesSpacedUpdate!: SpacedUpdate;
|
||||||
|
private attribute!: FAttribute;
|
||||||
|
private allAttributes!: FAttribute[];
|
||||||
|
private attrType!: ReturnType<AttributeDetailWidget["getAttrType"]>;
|
||||||
|
|
||||||
async refresh() {
|
async refresh() {
|
||||||
// switching note/tab should close the widget
|
// switching note/tab should close the widget
|
||||||
|
|
||||||
@ -286,7 +342,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
this.$inputName = this.$widget.find('.attr-input-name');
|
this.$inputName = this.$widget.find('.attr-input-name');
|
||||||
this.$inputName.on('input', ev => {
|
this.$inputName.on('input', ev => {
|
||||||
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
if (!(ev.originalEvent as KeyboardEvent)?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
this.userEditedAttribute();
|
this.userEditedAttribute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -296,7 +352,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.$inputName.on('focus', () => {
|
this.$inputName.on('focus', () => {
|
||||||
attributeAutocompleteService.initAttributeNameAutocomplete({
|
attributeAutocompleteService.initAttributeNameAutocomplete({
|
||||||
$el: this.$inputName,
|
$el: this.$inputName,
|
||||||
attributeType: () => ['relation', 'relation-definition'].includes(this.attrType) ? 'relation' : 'label',
|
attributeType: () => ['relation', 'relation-definition'].includes(this.attrType || "") ? 'relation' : 'label',
|
||||||
open: true
|
open: true
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -304,7 +360,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.$rowValue = this.$widget.find('.attr-row-value');
|
this.$rowValue = this.$widget.find('.attr-row-value');
|
||||||
this.$inputValue = this.$widget.find('.attr-input-value');
|
this.$inputValue = this.$widget.find('.attr-input-value');
|
||||||
this.$inputValue.on('input', ev => {
|
this.$inputValue.on('input', ev => {
|
||||||
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
if (!(ev.originalEvent as KeyboardEvent)?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
this.userEditedAttribute();
|
this.userEditedAttribute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -314,7 +370,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
attributeAutocompleteService.initLabelValueAutocomplete({
|
attributeAutocompleteService.initLabelValueAutocomplete({
|
||||||
$el: this.$inputValue,
|
$el: this.$inputValue,
|
||||||
open: true,
|
open: true,
|
||||||
nameCallback: () => this.$inputName.val()
|
nameCallback: () => String(this.$inputName.val())
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -341,7 +397,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.$rowInverseRelation = this.$widget.find('.attr-row-inverse-relation');
|
this.$rowInverseRelation = this.$widget.find('.attr-row-inverse-relation');
|
||||||
this.$inputInverseRelation = this.$widget.find('.attr-input-inverse-relation');
|
this.$inputInverseRelation = this.$widget.find('.attr-input-inverse-relation');
|
||||||
this.$inputInverseRelation.on('input', ev => {
|
this.$inputInverseRelation.on('input', ev => {
|
||||||
if (!ev.originalEvent?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
if (!(ev.originalEvent as KeyboardEvent)?.isComposing) { // https://github.com/zadam/trilium/pull/3812
|
||||||
this.userEditedAttribute();
|
this.userEditedAttribute();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -403,7 +459,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async showAttributeDetail({ allAttributes, attribute, isOwned, x, y, focus }) {
|
async showAttributeDetail({ allAttributes, attribute, isOwned, x, y, focus }: AttributeDetailOpts) {
|
||||||
if (!attribute) {
|
if (!attribute) {
|
||||||
this.hide();
|
this.hide();
|
||||||
|
|
||||||
@ -418,11 +474,13 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.attrType === 'label-definition' ? attribute.name.substr(6)
|
this.attrType === 'label-definition' ? attribute.name.substr(6)
|
||||||
: (this.attrType === 'relation-definition' ? attribute.name.substr(9) : attribute.name);
|
: (this.attrType === 'relation-definition' ? attribute.name.substr(9) : attribute.name);
|
||||||
|
|
||||||
const definition = this.attrType.endsWith('-definition')
|
const definition = this.attrType?.endsWith('-definition')
|
||||||
? promotedAttributeDefinitionParser.parse(attribute.value)
|
? promotedAttributeDefinitionParser.parse(attribute.value)
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
this.$title.text(ATTR_TITLES[this.attrType]);
|
if (this.attrType) {
|
||||||
|
this.$title.text(ATTR_TITLES[this.attrType]);
|
||||||
|
}
|
||||||
|
|
||||||
this.allAttributes = allAttributes;
|
this.allAttributes = allAttributes;
|
||||||
this.attribute = attribute;
|
this.attribute = attribute;
|
||||||
@ -444,51 +502,53 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
.append(await linkService.createLink(attribute.noteId))
|
.append(await linkService.createLink(attribute.noteId))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const disabledFn = (() => !isOwned ? "true" : undefined);
|
||||||
|
|
||||||
this.$inputName
|
this.$inputName
|
||||||
.val(attrName)
|
.val(attrName)
|
||||||
.attr('readonly', () => !isOwned);
|
.attr('readonly', disabledFn);
|
||||||
|
|
||||||
this.$rowValue.toggle(this.attrType === 'label');
|
this.$rowValue.toggle(this.attrType === 'label');
|
||||||
this.$rowTargetNote.toggle(this.attrType === 'relation');
|
this.$rowTargetNote.toggle(this.attrType === 'relation');
|
||||||
|
|
||||||
this.$rowPromoted.toggle(['label-definition', 'relation-definition'].includes(this.attrType));
|
this.$rowPromoted.toggle(['label-definition', 'relation-definition'].includes(this.attrType || ""));
|
||||||
this.$inputPromoted
|
this.$inputPromoted
|
||||||
.prop("checked", !!definition.isPromoted)
|
.prop("checked", !!definition.isPromoted)
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.$rowPromotedAlias.toggle(!!definition.isPromoted);
|
this.$rowPromotedAlias.toggle(!!definition.isPromoted);
|
||||||
this.$inputPromotedAlias
|
this.$inputPromotedAlias
|
||||||
.val(definition.promotedAlias)
|
.val(definition.promotedAlias || "")
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.$rowMultiplicity.toggle(['label-definition', 'relation-definition'].includes(this.attrType));
|
this.$rowMultiplicity.toggle(['label-definition', 'relation-definition'].includes(this.attrType || ""));
|
||||||
this.$inputMultiplicity
|
this.$inputMultiplicity
|
||||||
.val(definition.multiplicity)
|
.val(definition.multiplicity || "")
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.$rowLabelType.toggle(this.attrType === 'label-definition');
|
this.$rowLabelType.toggle(this.attrType === 'label-definition');
|
||||||
this.$inputLabelType
|
this.$inputLabelType
|
||||||
.val(definition.labelType)
|
.val(definition.labelType || "")
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.$rowNumberPrecision.toggle(this.attrType === 'label-definition' && definition.labelType === 'number');
|
this.$rowNumberPrecision.toggle(this.attrType === 'label-definition' && definition.labelType === 'number');
|
||||||
this.$inputNumberPrecision
|
this.$inputNumberPrecision
|
||||||
.val(definition.numberPrecision)
|
.val(definition.numberPrecision || "")
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.$rowInverseRelation.toggle(this.attrType === 'relation-definition');
|
this.$rowInverseRelation.toggle(this.attrType === 'relation-definition');
|
||||||
this.$inputInverseRelation
|
this.$inputInverseRelation
|
||||||
.val(definition.inverseRelation)
|
.val(definition.inverseRelation || "")
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
if (attribute.type === 'label') {
|
if (attribute.type === 'label') {
|
||||||
this.$inputValue
|
this.$inputValue
|
||||||
.val(attribute.value)
|
.val(attribute.value)
|
||||||
.attr('readonly', () => !isOwned);
|
.attr('readonly', disabledFn);
|
||||||
}
|
}
|
||||||
else if (attribute.type === 'relation') {
|
else if (attribute.type === 'relation') {
|
||||||
this.$inputTargetNote
|
this.$inputTargetNote
|
||||||
.attr('readonly', () => !isOwned)
|
.attr('readonly', disabledFn)
|
||||||
.val("")
|
.val("")
|
||||||
.setSelectedNotePath("");
|
.setSelectedNotePath("");
|
||||||
|
|
||||||
@ -505,23 +565,27 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
|
|
||||||
this.$inputInheritable
|
this.$inputInheritable
|
||||||
.prop("checked", !!attribute.isInheritable)
|
.prop("checked", !!attribute.isInheritable)
|
||||||
.attr('disabled', () => !isOwned);
|
.attr('disabled', disabledFn);
|
||||||
|
|
||||||
this.updateHelp();
|
this.updateHelp();
|
||||||
|
|
||||||
this.toggleInt(true);
|
this.toggleInt(true);
|
||||||
|
|
||||||
const offset = this.parent.$widget.offset();
|
const offset = this.parent?.$widget.offset() || { top: 0, left: 0 };
|
||||||
const detPosition = this.getDetailPosition(x, offset);
|
const detPosition = this.getDetailPosition(x, offset);
|
||||||
|
const outerHeight = this.$widget.outerHeight();
|
||||||
|
const height = $(window).height();
|
||||||
|
|
||||||
this.$widget
|
if (detPosition && outerHeight && height) {
|
||||||
.css("left", detPosition.left)
|
this.$widget
|
||||||
.css("right", detPosition.right)
|
.css("left", detPosition.left)
|
||||||
.css("top", y - offset.top + 70)
|
.css("right", detPosition.right)
|
||||||
.css("max-height",
|
.css("top", y - offset.top + 70)
|
||||||
this.$widget.outerHeight() + y > $(window).height() - 50
|
.css("max-height",
|
||||||
? $(window).height() - y - 50
|
outerHeight + y > height - 50
|
||||||
: 10000);
|
? height - y - 50
|
||||||
|
: 10000);
|
||||||
|
}
|
||||||
|
|
||||||
if (focus === 'name') {
|
if (focus === 'name') {
|
||||||
this.$inputName
|
this.$inputName
|
||||||
@ -530,16 +594,21 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDetailPosition(x, offset) {
|
getDetailPosition(x: number, offset: { left: number }) {
|
||||||
let left = x - offset.left - this.$widget.outerWidth() / 2;
|
const outerWidth = this.$widget.outerWidth();
|
||||||
let right = "";
|
if (!outerWidth) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let left: number | string = x - offset.left - outerWidth / 2;
|
||||||
|
let right: number | string = "";
|
||||||
|
|
||||||
if (left < 0) {
|
if (left < 0) {
|
||||||
left = 10;
|
left = 10;
|
||||||
} else {
|
} else {
|
||||||
const rightEdge = left + this.$widget.outerWidth();
|
const rightEdge = left + outerWidth;
|
||||||
|
|
||||||
if (rightEdge > this.parent.$widget.outerWidth() - 10) {
|
if (rightEdge > outerWidth - 10) {
|
||||||
left = "";
|
left = "";
|
||||||
right = 10;
|
right = 10;
|
||||||
}
|
}
|
||||||
@ -571,9 +640,10 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateHelp() {
|
updateHelp() {
|
||||||
const attrName = this.$inputName.val();
|
const attrName = String(this.$inputName.val());
|
||||||
|
|
||||||
if (this.attrType in ATTR_HELP && attrName in ATTR_HELP[this.attrType]) {
|
if (this.attrType && this.attrType in ATTR_HELP &&
|
||||||
|
attrName && attrName in ATTR_HELP[this.attrType]) {
|
||||||
this.$attrHelp
|
this.$attrHelp
|
||||||
.empty()
|
.empty()
|
||||||
.append($("<td colspan=2>")
|
.append($("<td colspan=2>")
|
||||||
@ -589,7 +659,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async updateRelatedNotes() {
|
async updateRelatedNotes() {
|
||||||
let { results, count } = await server.post('search-related', this.attribute);
|
let { results, count } = await server.post<SearchRelatedResponse>('search-related', this.attribute);
|
||||||
|
|
||||||
for (const res of results) {
|
for (const res of results) {
|
||||||
res.noteId = res.notePathArray[res.notePathArray.length - 1];
|
res.noteId = res.notePathArray[res.notePathArray.length - 1];
|
||||||
@ -626,7 +696,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getAttrType(attribute) {
|
getAttrType(attribute: FAttribute) {
|
||||||
if (attribute.type === 'label') {
|
if (attribute.type === 'label') {
|
||||||
if (attribute.name.startsWith('label:')) {
|
if (attribute.name.startsWith('label:')) {
|
||||||
return "label-definition";
|
return "label-definition";
|
||||||
@ -645,7 +715,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateAttributeInEditor() {
|
updateAttributeInEditor() {
|
||||||
let attrName = this.$inputName.val();
|
let attrName = String(this.$inputName.val());
|
||||||
|
|
||||||
if (!utils.isValidAttributeName(attrName)) {
|
if (!utils.isValidAttributeName(attrName)) {
|
||||||
// invalid characters are simply ignored (from user perspective they are not even entered)
|
// invalid characters are simply ignored (from user perspective they are not even entered)
|
||||||
@ -663,14 +733,14 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.attribute.name = attrName;
|
this.attribute.name = attrName;
|
||||||
this.attribute.isInheritable = this.$inputInheritable.is(":checked");
|
this.attribute.isInheritable = this.$inputInheritable.is(":checked");
|
||||||
|
|
||||||
if (this.attrType.endsWith('-definition')) {
|
if (this.attrType?.endsWith('-definition')) {
|
||||||
this.attribute.value = this.buildDefinitionValue();
|
this.attribute.value = this.buildDefinitionValue();
|
||||||
}
|
}
|
||||||
else if (this.attrType === 'relation') {
|
else if (this.attrType === 'relation') {
|
||||||
this.attribute.value = this.$inputTargetNote.getSelectedNoteId();
|
this.attribute.value = this.$inputTargetNote.getSelectedNoteId() || "";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.attribute.value = this.$inputValue.val();
|
this.attribute.value = String(this.$inputValue.val());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
|
this.triggerCommand('updateAttributeList', { attributes: this.allAttributes });
|
||||||
@ -695,10 +765,10 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
if (this.$inputLabelType.val() === 'number' && this.$inputNumberPrecision.val() !== '') {
|
if (this.$inputLabelType.val() === 'number' && this.$inputNumberPrecision.val() !== '') {
|
||||||
props.push(`precision=${this.$inputNumberPrecision.val()}`);
|
props.push(`precision=${this.$inputNumberPrecision.val()}`);
|
||||||
}
|
}
|
||||||
} else if (this.attrType === 'relation-definition' && this.$inputInverseRelation.val().trim().length > 0) {
|
} else if (this.attrType === 'relation-definition' && String(this.$inputInverseRelation.val())?.trim().length > 0) {
|
||||||
const inverseRelationName = this.$inputInverseRelation.val();
|
const inverseRelationName = this.$inputInverseRelation.val();
|
||||||
|
|
||||||
props.push(`inverse=${utils.filterAttributeName(inverseRelationName)}`);
|
props.push(`inverse=${utils.filterAttributeName(String(inverseRelationName))}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$rowNumberPrecision.toggle(
|
this.$rowNumberPrecision.toggle(
|
||||||
@ -714,7 +784,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
|
|||||||
this.toggleInt(false);
|
this.toggleInt(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
createLink(noteId) {
|
createLink(noteId: string) {
|
||||||
return $("<a>", {
|
return $("<a>", {
|
||||||
href: `#root/${noteId}`,
|
href: `#root/${noteId}`,
|
||||||
class: 'reference-link'
|
class: 'reference-link'
|
@ -13,7 +13,6 @@ class BasicWidget extends Component {
|
|||||||
private classes: string[];
|
private classes: string[];
|
||||||
private childPositionCounter: number;
|
private childPositionCounter: number;
|
||||||
private cssEl?: string;
|
private cssEl?: string;
|
||||||
protected $widget!: JQuery<HTMLElement>;
|
|
||||||
_noteId!: string;
|
_noteId!: string;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -49,9 +48,9 @@ class BasicWidget extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Conditionally adds the given components as children to this component.
|
* Conditionally adds the given components as children to this component.
|
||||||
*
|
*
|
||||||
* @param condition whether to add the components.
|
* @param condition whether to add the components.
|
||||||
* @param components the components to be added as children to this component provided the condition is truthy.
|
* @param components the components to be added as children to this component provided the condition is truthy.
|
||||||
* @returns self for chaining.
|
* @returns self for chaining.
|
||||||
*/
|
*/
|
||||||
optChild(condition: boolean, ...components: Component[]) {
|
optChild(condition: boolean, ...components: Component[]) {
|
||||||
@ -74,7 +73,7 @@ class BasicWidget extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the CSS attribute of the given name to the given value.
|
* Sets the CSS attribute of the given name to the given value.
|
||||||
*
|
*
|
||||||
* @param name the name of the CSS attribute to set (e.g. `padding-left`).
|
* @param name the name of the CSS attribute to set (e.g. `padding-left`).
|
||||||
* @param value the value of the CSS attribute to set (e.g. `12px`).
|
* @param value the value of the CSS attribute to set (e.g. `12px`).
|
||||||
* @returns self for chaining.
|
* @returns self for chaining.
|
||||||
@ -86,7 +85,7 @@ class BasicWidget extends Component {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the CSS attribute of the given name to the given value, but only if the condition provided is truthy.
|
* Sets the CSS attribute of the given name to the given value, but only if the condition provided is truthy.
|
||||||
*
|
*
|
||||||
* @param condition `true` in order to apply the CSS, `false` to ignore it.
|
* @param condition `true` in order to apply the CSS, `false` to ignore it.
|
||||||
* @param name the name of the CSS attribute to set (e.g. `padding-left`).
|
* @param name the name of the CSS attribute to set (e.g. `padding-left`).
|
||||||
* @param value the value of the CSS attribute to set (e.g. `12px`).
|
* @param value the value of the CSS attribute to set (e.g. `12px`).
|
||||||
@ -129,7 +128,7 @@ class BasicWidget extends Component {
|
|||||||
render() {
|
render() {
|
||||||
try {
|
try {
|
||||||
this.doRender();
|
this.doRender();
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
this.logRenderingError(e);
|
this.logRenderingError(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user