mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
add promoted attributes widget to the mobile version, closes #4314
This commit is contained in:
parent
00f5924251
commit
137703ada4
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.61.8-beta",
|
"version": "0.61.9-beta",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.61.8-beta",
|
"version": "0.61.9-beta",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -22,6 +22,7 @@ import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
|||||||
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
import LauncherContainer from "../widgets/containers/launcher_container.js";
|
||||||
import RootContainer from "../widgets/containers/root_container.js";
|
import RootContainer from "../widgets/containers/root_container.js";
|
||||||
import SharedInfoWidget from "../widgets/shared_info.js";
|
import SharedInfoWidget from "../widgets/shared_info.js";
|
||||||
|
import PromotedAttributesWidget from "../widgets/ribbon_widgets/promoted_attributes.js";
|
||||||
|
|
||||||
const MOBILE_CSS = `
|
const MOBILE_CSS = `
|
||||||
<style>
|
<style>
|
||||||
@ -154,6 +155,7 @@ export default class MobileLayout {
|
|||||||
.child(new HideFloatingButtonsButton())
|
.child(new HideFloatingButtonsButton())
|
||||||
)
|
)
|
||||||
.child(new MermaidWidget())
|
.child(new MermaidWidget())
|
||||||
|
.child(new PromotedAttributesWidget())
|
||||||
.child(
|
.child(
|
||||||
new ScrollingContainer()
|
new ScrollingContainer()
|
||||||
.filling()
|
.filling()
|
||||||
|
@ -5,6 +5,7 @@ import noteAutocompleteService from "../../services/note_autocomplete.js";
|
|||||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
import attributeService from "../../services/attributes.js";
|
import attributeService from "../../services/attributes.js";
|
||||||
import options from "../../services/options.js";
|
import options from "../../services/options.js";
|
||||||
|
import utils from "../../services/utils.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div>
|
<div>
|
||||||
@ -37,9 +38,13 @@ const TPL = `
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="promoted-attributes-container"></div>
|
<div class="promoted-attributes-container"></div>
|
||||||
</div>
|
</div>`;
|
||||||
`;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This widget is quite special because it's used in the desktop ribbon, but in mobile outside of ribbon.
|
||||||
|
* This works without many issues (apart from autocomplete), but it should be kept in mind when changing things
|
||||||
|
* and testing.
|
||||||
|
*/
|
||||||
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
||||||
get name() {
|
get name() {
|
||||||
return "promotedAttributes";
|
return "promotedAttributes";
|
||||||
@ -147,34 +152,37 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
if (definition.labelType === 'text') {
|
if (definition.labelType === 'text') {
|
||||||
$input.prop("type", "text");
|
$input.prop("type", "text");
|
||||||
|
|
||||||
// no need to await for this, can be done asynchronously
|
// autocomplete for label values is just nice to have, mobile can keep labels editable without autocomplete
|
||||||
server.get(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then(attributeValues => {
|
if (utils.isDesktop()) {
|
||||||
if (attributeValues.length === 0) {
|
// no need to await for this, can be done asynchronously
|
||||||
return;
|
server.get(`attribute-values/${encodeURIComponent(valueAttr.name)}`).then(attributeValues => {
|
||||||
}
|
if (attributeValues.length === 0) {
|
||||||
|
return;
|
||||||
attributeValues = attributeValues.map(attribute => ({value: attribute}));
|
|
||||||
|
|
||||||
$input.autocomplete({
|
|
||||||
appendTo: document.querySelector('body'),
|
|
||||||
hint: false,
|
|
||||||
autoselect: false,
|
|
||||||
openOnFocus: true,
|
|
||||||
minLength: 0,
|
|
||||||
tabAutocomplete: false
|
|
||||||
}, [{
|
|
||||||
displayKey: 'value',
|
|
||||||
source: function (term, cb) {
|
|
||||||
term = term.toLowerCase();
|
|
||||||
|
|
||||||
const filtered = attributeValues.filter(attr => attr.value.toLowerCase().includes(term));
|
|
||||||
|
|
||||||
cb(filtered);
|
|
||||||
}
|
}
|
||||||
}]);
|
|
||||||
|
|
||||||
$input.on('autocomplete:selected', e => this.promotedAttributeChanged(e));
|
attributeValues = attributeValues.map(attribute => ({value: attribute}));
|
||||||
});
|
|
||||||
|
$input.autocomplete({
|
||||||
|
appendTo: document.querySelector('body'),
|
||||||
|
hint: false,
|
||||||
|
autoselect: false,
|
||||||
|
openOnFocus: true,
|
||||||
|
minLength: 0,
|
||||||
|
tabAutocomplete: false
|
||||||
|
}, [{
|
||||||
|
displayKey: 'value',
|
||||||
|
source: function (term, cb) {
|
||||||
|
term = term.toLowerCase();
|
||||||
|
|
||||||
|
const filtered = attributeValues.filter(attr => attr.value.toLowerCase().includes(term));
|
||||||
|
|
||||||
|
cb(filtered);
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
|
$input.on('autocomplete:selected', e => this.promotedAttributeChanged(e));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (definition.labelType === 'number') {
|
else if (definition.labelType === 'number') {
|
||||||
$input.prop("type", "number");
|
$input.prop("type", "number");
|
||||||
@ -219,7 +227,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
.append($openButton));
|
.append($openButton));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ws.logError(`Unknown labelType=${definitionAttr.labelType}`);
|
ws.logError(`Unknown labelType '${definitionAttr.labelType}'`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (valueAttr.type === 'relation') {
|
else if (valueAttr.type === 'relation') {
|
||||||
@ -227,17 +235,22 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
|
|||||||
$input.val(await treeService.getNoteTitle(valueAttr.value));
|
$input.val(await treeService.getNoteTitle(valueAttr.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// no need to wait for this
|
if (utils.isDesktop()) {
|
||||||
noteAutocompleteService.initNoteAutocomplete($input, {allowCreatingNotes: true});
|
// no need to wait for this
|
||||||
|
noteAutocompleteService.initNoteAutocomplete($input, {allowCreatingNotes: true});
|
||||||
|
|
||||||
$input.on('autocomplete:noteselected', (event, suggestion, dataset) => {
|
$input.on('autocomplete:noteselected', (event, suggestion, dataset) => {
|
||||||
this.promotedAttributeChanged(event);
|
this.promotedAttributeChanged(event);
|
||||||
});
|
});
|
||||||
|
|
||||||
$input.setSelectedNotePath(valueAttr.value);
|
$input.setSelectedNotePath(valueAttr.value);
|
||||||
|
} else {
|
||||||
|
// we can't provide user a way to edit the relation so make it read only
|
||||||
|
$input.attr("readonly", "readonly");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ws.logError(`Unknown attribute type=${valueAttr.type}`);
|
ws.logError(`Unknown attribute type '${valueAttr.type}'`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user