mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
wip attachment widget
This commit is contained in:
parent
9be524ef89
commit
fa406d3ded
@ -11,7 +11,9 @@ module.exports = () => {
|
||||
try {
|
||||
const attachment = note.convertToParentAttachment({force: false});
|
||||
|
||||
log.info(`Auto-converted note '${note.noteId}' into attachment '${attachment.attachmentId}'.`)
|
||||
if (attachment) {
|
||||
log.info(`Auto-converted note '${note.noteId}' into attachment '${attachment.attachmentId}'.`);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
log.error(`Cannot convert note '${note.noteId}' to attachment: ${e.message} ${e.stack}`);
|
||||
|
@ -1086,11 +1086,15 @@ class BNote extends AbstractBeccaEntity {
|
||||
.map(row => new BAttachment(row));
|
||||
}
|
||||
|
||||
/** @returns {BAttachment|undefined} */
|
||||
getAttachmentByName(name) {
|
||||
return sql.getRows("SELECT * FROM attachments WHERE parentId = ? AND name = ? AND isDeleted = 0", [this.noteId, name])
|
||||
.map(row => new BAttachment(row))
|
||||
[0];
|
||||
/** @returns {BAttachment|null} */
|
||||
getAttachmentById(attachmentId) {
|
||||
return sql.getRows(`
|
||||
SELECT attachments.*
|
||||
FROM attachments
|
||||
WHERE parentId = ?
|
||||
AND attachmentId = ?
|
||||
AND isDeleted = 0`, [this.noteId, attachmentId])
|
||||
.map(row => new BAttachment(row))[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
101
src/public/app/widgets/attachment_detail.js
Normal file
101
src/public/app/widgets/attachment_detail.js
Normal file
@ -0,0 +1,101 @@
|
||||
import TypeWidget from "./type_widget.js";
|
||||
import server from "../../services/server.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import AttachmentActionsWidget from "../buttons/attachments_actions.js";
|
||||
import BasicWidget from "./basic_widget.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="attachment-detail">
|
||||
<style>
|
||||
.attachment-detail-wrapper {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.attachment-title-line {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.attachment-details {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.attachment-content pre {
|
||||
max-height: 400px;
|
||||
background: var(--accented-background-color);
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.attachment-content img {
|
||||
margin: 10px;
|
||||
max-height: 300px;
|
||||
max-width: 90%;
|
||||
object-fit: contain;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="attachment-detail-wrapper"></div>
|
||||
</div>`;
|
||||
|
||||
export default class AttachmentDetailWidget extends BasicWidget {
|
||||
constructor(attachment) {
|
||||
super();
|
||||
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$wrapper = this.$widget.find('.attachment-detail-wrapper');
|
||||
|
||||
super.doRender();
|
||||
}
|
||||
|
||||
async doRefresh(note) {
|
||||
this.$list.empty();
|
||||
this.children = [];
|
||||
|
||||
const attachments = await server.get(`notes/${this.noteId}/attachments?includeContent=true`);
|
||||
|
||||
if (attachments.length === 0) {
|
||||
this.$list.html("<strong>This note has no attachments.</strong>");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (const attachment of attachments) {
|
||||
const attachmentActionsWidget = new AttachmentActionsWidget(attachment);
|
||||
this.child(attachmentActionsWidget);
|
||||
|
||||
this.$list.append(
|
||||
$('<div class="attachment-detail-wrapper">')
|
||||
.append(
|
||||
$('<div class="attachment-title-line">')
|
||||
.append($('<h4>').append($('<span class="attachment-title">').text(attachment.title)))
|
||||
.append(
|
||||
$('<div class="attachment-details">')
|
||||
.text(`Role: ${attachment.role}, Size: ${utils.formatSize(attachment.contentLength)}`)
|
||||
)
|
||||
.append($('<div style="flex: 1 1;">')) // spacer
|
||||
.append(attachmentActionsWidget.render())
|
||||
)
|
||||
.append(
|
||||
$('<div class="attachment-content">')
|
||||
.append(this.renderContent(attachment))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderContent(attachment) {
|
||||
if (attachment.content) {
|
||||
return $("<pre>").text(attachment.content);
|
||||
} else if (attachment.role === 'image') {
|
||||
return `<img src="api/notes/${attachment.parentId}/images/${attachment.attachmentId}/${encodeURIComponent(attachment.title)}?${attachment.utcDateModified}">`;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
import server from "../../services/server.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="dropdown attachment-actions">
|
||||
@ -38,58 +39,9 @@ export default class AttachmentActionsWidget extends BasicWidget {
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
|
||||
// this.$findInTextButton = this.$widget.find('.find-in-text-button');
|
||||
// this.$printActiveNoteButton = this.$widget.find('.print-active-note-button');
|
||||
// this.$showSourceButton = this.$widget.find('.show-source-button');
|
||||
// this.$renderNoteButton = this.$widget.find('.render-note-button');
|
||||
//
|
||||
// this.$exportNoteButton = this.$widget.find('.export-note-button');
|
||||
// this.$exportNoteButton.on("click", () => {
|
||||
// if (this.$exportNoteButton.hasClass("disabled")) {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// this.triggerCommand("showExportDialog", {
|
||||
// notePath: this.noteContext.notePath,
|
||||
// defaultType: "single"
|
||||
// });
|
||||
// });
|
||||
//
|
||||
// this.$importNoteButton = this.$widget.find('.import-files-button');
|
||||
// this.$importNoteButton.on("click", () => this.triggerCommand("showImportDialog", {noteId: this.noteId}));
|
||||
//
|
||||
// this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle'));
|
||||
//
|
||||
// this.$openNoteExternallyButton = this.$widget.find(".open-note-externally-button");
|
||||
//
|
||||
// this.$deleteNoteButton = this.$widget.find(".delete-note-button");
|
||||
// this.$deleteNoteButton.on("click", () => {
|
||||
// if (this.note.noteId === 'root') {
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// branchService.deleteNotes([this.note.getParentBranches()[0].branchId], true);
|
||||
// });
|
||||
}
|
||||
|
||||
refreshWithNote(note) {
|
||||
// this.toggleDisabled(this.$findInTextButton, ['text', 'code', 'book', 'search'].includes(note.type));
|
||||
//
|
||||
// this.toggleDisabled(this.$showSourceButton, ['text', 'relationMap', 'mermaid'].includes(note.type));
|
||||
//
|
||||
// this.toggleDisabled(this.$printActiveNoteButton, ['text', 'code'].includes(note.type));
|
||||
//
|
||||
// this.$renderNoteButton.toggle(note.type === 'render');
|
||||
//
|
||||
// this.$openNoteExternallyButton.toggle(utils.isElectron());
|
||||
}
|
||||
|
||||
toggleDisabled($el, enable) {
|
||||
if (enable) {
|
||||
$el.removeAttr('disabled');
|
||||
} else {
|
||||
$el.attr('disabled', 'disabled');
|
||||
}
|
||||
async deleteAttachmentCommand() {
|
||||
await server.remove(`notes/${this.attachment.parentId}/attachments/${this.attachment.attachmentId}`);
|
||||
}
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ export default class AttachmentsTypeWidget extends TypeWidget {
|
||||
}
|
||||
|
||||
for (const attachment of attachments) {
|
||||
const attachmentActionsWidget = new AttachmentActionsWidget();
|
||||
const attachmentActionsWidget = new AttachmentActionsWidget(attachment);
|
||||
this.child(attachmentActionsWidget);
|
||||
|
||||
this.$list.append(
|
||||
|
@ -175,6 +175,22 @@ function saveAttachment(req) {
|
||||
note.saveAttachment({attachmentId, role, mime, title, content});
|
||||
}
|
||||
|
||||
function deleteAttachment(req) {
|
||||
const {noteId, attachmentId} = req.params;
|
||||
|
||||
const note = becca.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
throw new NotFoundError(`Note '${noteId}' doesn't exist.`);
|
||||
}
|
||||
|
||||
const attachment = note.getAttachmentById(attachmentId);
|
||||
|
||||
if (attachment) {
|
||||
attachment.markAsDeleted();
|
||||
}
|
||||
}
|
||||
|
||||
function getRelationMap(req) {
|
||||
const {relationMapNoteId, noteIds} = req.body;
|
||||
|
||||
@ -390,5 +406,6 @@ module.exports = {
|
||||
uploadModifiedFile,
|
||||
forceSaveNoteRevision,
|
||||
getAttachments,
|
||||
saveAttachment
|
||||
saveAttachment,
|
||||
deleteAttachment
|
||||
};
|
||||
|
@ -128,6 +128,7 @@ function register(app) {
|
||||
apiRoute(PUT, '/api/notes/:noteId/type', notesApiRoute.setNoteTypeMime);
|
||||
apiRoute(GET, '/api/notes/:noteId/attachments', notesApiRoute.getAttachments);
|
||||
apiRoute(POST, '/api/notes/:noteId/attachments', notesApiRoute.saveAttachment);
|
||||
apiRoute(DELETE, '/api/notes/:noteId/attachments/:attachmentId', notesApiRoute.deleteAttachment);
|
||||
apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions);
|
||||
apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions);
|
||||
apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision);
|
||||
|
Loading…
x
Reference in New Issue
Block a user