mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
support for promoted multi value attributes
This commit is contained in:
parent
21551d7b77
commit
fcf6141cde
@ -236,13 +236,99 @@ async function loadAttributes() {
|
|||||||
|
|
||||||
let idx = 1;
|
let idx = 1;
|
||||||
|
|
||||||
|
async function createRow(definitionAttr, valueAttr) {
|
||||||
|
const definition = definitionAttr.value;
|
||||||
|
const inputId = "promoted-input-" + (idx++);
|
||||||
|
const $tr = $("<tr>");
|
||||||
|
const $labelCell = $("<th>").append(valueAttr.name);
|
||||||
|
const $input = $("<input>")
|
||||||
|
.prop("id", inputId)
|
||||||
|
.prop("attribute-id", valueAttr.attributeId)
|
||||||
|
.prop("attribute-type", valueAttr.type)
|
||||||
|
.prop("attribute-name", valueAttr.name)
|
||||||
|
.prop("value", valueAttr.value)
|
||||||
|
.addClass("form-control")
|
||||||
|
.addClass("promoted-attribute-input");
|
||||||
|
|
||||||
|
const $inputCell = $("<td>").append($input);
|
||||||
|
|
||||||
|
const $actionCell = $("<td>");
|
||||||
|
const $multiplicityCell = $("<td>");
|
||||||
|
|
||||||
|
$tr
|
||||||
|
.append($labelCell)
|
||||||
|
.append($inputCell)
|
||||||
|
.append($actionCell)
|
||||||
|
.append($multiplicityCell);
|
||||||
|
|
||||||
|
if (valueAttr.type === 'label') {
|
||||||
|
if (definition.labelType === 'text') {
|
||||||
|
$input.prop("type", "text");
|
||||||
|
}
|
||||||
|
else if (definition.labelType === 'number') {
|
||||||
|
$input.prop("type", "number");
|
||||||
|
}
|
||||||
|
else if (definition.labelType === 'boolean') {
|
||||||
|
$input.prop("type", "checkbox");
|
||||||
|
|
||||||
|
if (valueAttr.value === "true") {
|
||||||
|
$input.prop("checked", "checked");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (definition.labelType === 'date') {
|
||||||
|
$input.prop("type", "text");
|
||||||
|
|
||||||
|
$input.datepicker({
|
||||||
|
changeMonth: true,
|
||||||
|
changeYear: true,
|
||||||
|
dateFormat: "yy-mm-dd"
|
||||||
|
});
|
||||||
|
|
||||||
|
const $todayButton = $("<button>").addClass("btn btn-small").text("Today").click(() => {
|
||||||
|
$input.val(utils.formatDateISO(new Date()));
|
||||||
|
$input.trigger("change");
|
||||||
|
});
|
||||||
|
|
||||||
|
$actionCell.append($todayButton);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
messagingService.logError("Unknown labelType=" + definitionAttr.labelType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (definition.multiplicityType === "multivalue") {
|
||||||
|
const addButton = $("<button>").addClass("btn btn-small").text("Add new").click(async () => {
|
||||||
|
const $new = await createRow(definitionAttr, {
|
||||||
|
attributeId: "",
|
||||||
|
type: valueAttr.type,
|
||||||
|
name: definitionAttr.name,
|
||||||
|
value: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
$tr.after($new);
|
||||||
|
});
|
||||||
|
|
||||||
|
$multiplicityCell.append(addButton);
|
||||||
|
|
||||||
|
const removeButton = $("<button>").addClass("btn btn-small").text("Delete").click(async () => {
|
||||||
|
if (valueAttr.attributeId) {
|
||||||
|
await server.remove("notes/" + noteId + "/attributes/" + valueAttr.attributeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
$tr.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
$multiplicityCell.append(removeButton);
|
||||||
|
}
|
||||||
|
return $tr;
|
||||||
|
}
|
||||||
|
|
||||||
if (promoted.length > 0) {
|
if (promoted.length > 0) {
|
||||||
for (const definitionAttr of promoted) {
|
for (const definitionAttr of promoted) {
|
||||||
const definitionType = definitionAttr.type;
|
const definitionType = definitionAttr.type;
|
||||||
const definition = definitionAttr.value;
|
|
||||||
const valueType = definitionType.substr(0, definitionType.length - 11);
|
const valueType = definitionType.substr(0, definitionType.length - 11);
|
||||||
|
|
||||||
const valueAttrs = attributes.filter(el => el.name === definitionAttr.name && el.type === valueType);
|
let valueAttrs = attributes.filter(el => el.name === definitionAttr.name && el.type === valueType);
|
||||||
|
|
||||||
if (valueAttrs.length === 0) {
|
if (valueAttrs.length === 0) {
|
||||||
valueAttrs.push({
|
valueAttrs.push({
|
||||||
@ -253,59 +339,14 @@ async function loadAttributes() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (definitionAttr.value.multiplicityType === 'singlevalue') {
|
||||||
|
valueAttrs = valueAttrs.slice(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
for (const valueAttr of valueAttrs) {
|
for (const valueAttr of valueAttrs) {
|
||||||
const inputId = "promoted-input-" + (idx++);
|
const $tr = await createRow(definitionAttr, valueAttr);
|
||||||
const $tr = $("<tr>");
|
|
||||||
const $labelCell = $("<th>").append(valueAttr.name);
|
|
||||||
const $input = $("<input>")
|
|
||||||
.prop("id", inputId)
|
|
||||||
.prop("attribute-id", valueAttr.attributeId)
|
|
||||||
.prop("attribute-type", valueAttr.type)
|
|
||||||
.prop("attribute-name", valueAttr.name)
|
|
||||||
.prop("value", valueAttr.value)
|
|
||||||
.addClass("form-control")
|
|
||||||
.addClass("promoted-attribute-input");
|
|
||||||
|
|
||||||
const $inputCell = $("<td>").append($input);
|
|
||||||
|
|
||||||
$tr.append($labelCell).append($inputCell);
|
|
||||||
|
|
||||||
$promotedAttributesContainer.append($tr);
|
$promotedAttributesContainer.append($tr);
|
||||||
|
|
||||||
if (valueAttr.type === 'label') {
|
|
||||||
if (definition.labelType === 'text') {
|
|
||||||
$input.prop("type", "text");
|
|
||||||
}
|
|
||||||
else if (definition.labelType === 'number') {
|
|
||||||
$input.prop("type", "number");
|
|
||||||
}
|
|
||||||
else if (definition.labelType === 'boolean') {
|
|
||||||
$input.prop("type", "checkbox");
|
|
||||||
|
|
||||||
if (valueAttr.value === "true") {
|
|
||||||
$input.prop("checked", "checked");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (definition.labelType === 'date') {
|
|
||||||
$input.prop("type", "text");
|
|
||||||
|
|
||||||
$input.datepicker({
|
|
||||||
changeMonth: true,
|
|
||||||
changeYear: true,
|
|
||||||
dateFormat: "yy-mm-dd"
|
|
||||||
});
|
|
||||||
|
|
||||||
const $todayButton = $("<button>").text("Today").click(() => {
|
|
||||||
$input.val(utils.formatDateISO(new Date()));
|
|
||||||
$input.trigger("change");
|
|
||||||
});
|
|
||||||
|
|
||||||
$tr.append($("<tr>").append($todayButton));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
messagingService.logError("Unknown labelType=" + definitionAttr.labelType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -414,13 +455,15 @@ $promotedAttributesContainer.on('change', '.promoted-attribute-input', async eve
|
|||||||
value = $attr.val();
|
value = $attr.val();
|
||||||
}
|
}
|
||||||
|
|
||||||
await server.put("notes/" + getCurrentNoteId() + "/attribute", {
|
const result = await server.put("notes/" + getCurrentNoteId() + "/attribute", {
|
||||||
attributeId: $attr.prop("attribute-id"),
|
attributeId: $attr.prop("attribute-id"),
|
||||||
type: $attr.prop("attribute-type"),
|
type: $attr.prop("attribute-type"),
|
||||||
name: $attr.prop("attribute-name"),
|
name: $attr.prop("attribute-name"),
|
||||||
value: value
|
value: value
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$attr.prop("attribute-id", result.attributeId);
|
||||||
|
|
||||||
infoService.showMessage("Attribute has been saved.");
|
infoService.showMessage("Attribute has been saved.");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -427,6 +427,10 @@ html.theme-dark body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#note-detail-promoted-attributes {
|
#note-detail-promoted-attributes {
|
||||||
width: 50%;
|
max-width: 70%;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#note-detail-promoted-attributes td, note-detail-promoted-attributes th {
|
||||||
|
padding: 5px;
|
||||||
|
}
|
@ -76,6 +76,21 @@ async function updateNoteAttribute(req) {
|
|||||||
attribute.value = body.value;
|
attribute.value = body.value;
|
||||||
|
|
||||||
await attribute.save();
|
await attribute.save();
|
||||||
|
|
||||||
|
return {
|
||||||
|
attributeId: attribute.attributeId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteNoteAttribute(req) {
|
||||||
|
const attributeId = req.params.attributeId;
|
||||||
|
|
||||||
|
const attribute = await repository.getAttribute(attributeId);
|
||||||
|
|
||||||
|
if (attribute) {
|
||||||
|
attribute.isDeleted = 1;
|
||||||
|
await attribute.save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateNoteAttributes(req) {
|
async function updateNoteAttributes(req) {
|
||||||
@ -129,6 +144,7 @@ async function getValuesForAttribute(req) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
updateNoteAttributes,
|
updateNoteAttributes,
|
||||||
updateNoteAttribute,
|
updateNoteAttribute,
|
||||||
|
deleteNoteAttribute,
|
||||||
getAttributeNames,
|
getAttributeNames,
|
||||||
getValuesForAttribute,
|
getValuesForAttribute,
|
||||||
getEffectiveNoteAttributes
|
getEffectiveNoteAttributes
|
||||||
|
@ -137,6 +137,7 @@ function register(app) {
|
|||||||
apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes);
|
apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes);
|
apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/attribute', attributesRoute.updateNoteAttribute);
|
apiRoute(PUT, '/api/notes/:noteId/attribute', attributesRoute.updateNoteAttribute);
|
||||||
|
apiRoute(DELETE, '/api/notes/:noteId/attributes/:attributeId', attributesRoute.deleteNoteAttribute);
|
||||||
apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames);
|
apiRoute(GET, '/api/attributes/names', attributesRoute.getAttributeNames);
|
||||||
apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute);
|
apiRoute(GET, '/api/attributes/values/:attributeName', attributesRoute.getValuesForAttribute);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user