mirror of
https://github.com/zadam/trilium.git
synced 2025-11-15 17:55:52 +01:00
chore(react/type_widget): add deletion widget
This commit is contained in:
@@ -1,79 +0,0 @@
|
|||||||
import { t } from "../services/i18n.js";
|
|
||||||
import utils from "../services/utils.js";
|
|
||||||
import AttachmentActionsWidget from "./buttons/attachments_actions.js";
|
|
||||||
import BasicWidget from "./basic_widget.js";
|
|
||||||
import options from "../services/options.js";
|
|
||||||
import imageService from "../services/image.js";
|
|
||||||
import linkService from "../services/link.js";
|
|
||||||
import contentRenderer from "../services/content_renderer.js";
|
|
||||||
import toastService from "../services/toast.js";
|
|
||||||
import type FAttachment from "../entities/fattachment.js";
|
|
||||||
import type { EventData } from "../components/app_context.js";
|
|
||||||
|
|
||||||
const TPL = /*html*/`
|
|
||||||
<div class="attachment-deletion-warning alert alert-info" style="margin-top: 15px;"></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
|
|
||||||
export default class AttachmentDetailWidget extends BasicWidget {
|
|
||||||
attachment: FAttachment;
|
|
||||||
attachmentActionsWidget: AttachmentActionsWidget;
|
|
||||||
isFullDetail: boolean;
|
|
||||||
$wrapper!: JQuery<HTMLElement>;
|
|
||||||
|
|
||||||
constructor(attachment: FAttachment, isFullDetail: boolean) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.contentSized();
|
|
||||||
this.attachment = attachment;
|
|
||||||
this.attachmentActionsWidget = new AttachmentActionsWidget(attachment, isFullDetail);
|
|
||||||
this.isFullDetail = isFullDetail;
|
|
||||||
this.child(this.attachmentActionsWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
doRender() {
|
|
||||||
this.$widget = $(TPL);
|
|
||||||
this.refresh();
|
|
||||||
|
|
||||||
super.doRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
async refresh() {
|
|
||||||
this.$widget.find(".attachment-detail-wrapper").empty().append($(TPL).find(".attachment-detail-wrapper").html());
|
|
||||||
this.$wrapper = this.$widget.find(".attachment-detail-wrapper");
|
|
||||||
this.$wrapper.addClass(this.isFullDetail ? "full-detail" : "list-view");
|
|
||||||
|
|
||||||
const $deletionWarning = this.$wrapper.find(".attachment-deletion-warning");
|
|
||||||
const { utcDateScheduledForErasureSince } = this.attachment;
|
|
||||||
|
|
||||||
if (utcDateScheduledForErasureSince) {
|
|
||||||
this.$wrapper.addClass("scheduled-for-deletion");
|
|
||||||
|
|
||||||
const scheduledSinceTimestamp = utils.parseDate(utcDateScheduledForErasureSince)?.getTime();
|
|
||||||
// use default value (30 days in seconds) from options_init as fallback, in case getInt returns null
|
|
||||||
const intervalMs = options.getInt("eraseUnusedAttachmentsAfterSeconds") || 2592000 * 1000;
|
|
||||||
const deletionTimestamp = scheduledSinceTimestamp + intervalMs;
|
|
||||||
const willBeDeletedInMs = deletionTimestamp - Date.now();
|
|
||||||
|
|
||||||
$deletionWarning.show();
|
|
||||||
|
|
||||||
if (willBeDeletedInMs >= 60000) {
|
|
||||||
$deletionWarning.text(t("attachment_detail_2.will_be_deleted_in", { time: utils.formatTimeInterval(willBeDeletedInMs) }));
|
|
||||||
} else {
|
|
||||||
$deletionWarning.text(t("attachment_detail_2.will_be_deleted_soon"));
|
|
||||||
}
|
|
||||||
|
|
||||||
$deletionWarning.append(t("attachment_detail_2.deletion_reason"));
|
|
||||||
} else {
|
|
||||||
this.$wrapper.removeClass("scheduled-for-deletion");
|
|
||||||
$deletionWarning.hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$wrapper.find(".attachment-actions-container").append(this.attachmentActionsWidget.render());
|
|
||||||
|
|
||||||
const { $renderedContent } = await );
|
|
||||||
this.$wrapper.find(".attachment-content-wrapper").append($renderedContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -82,6 +82,10 @@
|
|||||||
.attachment-detail-wrapper.scheduled-for-deletion .attachment-content-wrapper img {
|
.attachment-detail-wrapper.scheduled-for-deletion .attachment-content-wrapper img {
|
||||||
filter: contrast(10%);
|
filter: contrast(10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.attachment-detail-wrapper .attachment-deletion-warning {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
/* #endregion */
|
/* #endregion */
|
||||||
|
|
||||||
/* #region Attachment detail */
|
/* #region Attachment detail */
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import dialog from "../../services/dialog";
|
|||||||
import ws from "../../services/ws";
|
import ws from "../../services/ws";
|
||||||
import appContext from "../../components/app_context";
|
import appContext from "../../components/app_context";
|
||||||
import { ConvertAttachmentToNoteResponse } from "@triliumnext/commons";
|
import { ConvertAttachmentToNoteResponse } from "@triliumnext/commons";
|
||||||
|
import options from "../../services/options";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the full list of attachments of a note and allows the user to interact with them.
|
* Displays the full list of attachments of a note and allows the user to interact with them.
|
||||||
@@ -158,7 +159,7 @@ function AttachmentInfo({ attachment, isFullDetail }: { attachment: FAttachment,
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="attachment-detail-widget">
|
<div className="attachment-detail-widget">
|
||||||
<div className="attachment-detail-wrapper">
|
<div className={`attachment-detail-wrapper ${isFullDetail ? "full-detail" : "list-view"} ${attachment.utcDateScheduledForErasureSince ? "scheduled-for-deletion" : ""}`}>
|
||||||
<div className="attachment-title-line">
|
<div className="attachment-title-line">
|
||||||
<AttachmentActions attachment={attachment} copyAttachmentLinkToClipboard={copyAttachmentLinkToClipboard} />
|
<AttachmentActions attachment={attachment} copyAttachmentLinkToClipboard={copyAttachmentLinkToClipboard} />
|
||||||
<h4 className="attachment-title">
|
<h4 className="attachment-title">
|
||||||
@@ -179,12 +180,30 @@ function AttachmentInfo({ attachment, isFullDetail }: { attachment: FAttachment,
|
|||||||
<div style="flex: 1 1;"></div>
|
<div style="flex: 1 1;"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{attachment.utcDateScheduledForErasureSince && <DeletionAlert utcDateScheduledForErasureSince={attachment.utcDateScheduledForErasureSince} />}
|
||||||
<div ref={contentWrapper} className="attachment-content-wrapper" />
|
<div ref={contentWrapper} className="attachment-content-wrapper" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function DeletionAlert({ utcDateScheduledForErasureSince }: { utcDateScheduledForErasureSince: string }) {
|
||||||
|
const scheduledSinceTimestamp = utils.parseDate(utcDateScheduledForErasureSince)?.getTime();
|
||||||
|
// use default value (30 days in seconds) from options_init as fallback, in case getInt returns null
|
||||||
|
const intervalMs = options.getInt("eraseUnusedAttachmentsAfterSeconds") || 2592000 * 1000;
|
||||||
|
const deletionTimestamp = scheduledSinceTimestamp + intervalMs;
|
||||||
|
const willBeDeletedInMs = deletionTimestamp - Date.now();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Alert className="attachment-deletion-warning" type="info">
|
||||||
|
{ willBeDeletedInMs >= 60000
|
||||||
|
? t("attachment_detail_2.will_be_deleted_in", { time: utils.formatTimeInterval(willBeDeletedInMs) })
|
||||||
|
: t("attachment_detail_2.will_be_deleted_soon")}
|
||||||
|
{t("attachment_detail_2.deletion_reason")}
|
||||||
|
</Alert>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function AttachmentActions({ attachment, copyAttachmentLinkToClipboard }: { attachment: FAttachment, copyAttachmentLinkToClipboard: () => void }) {
|
function AttachmentActions({ attachment, copyAttachmentLinkToClipboard }: { attachment: FAttachment, copyAttachmentLinkToClipboard: () => void }) {
|
||||||
const isElectron = utils.isElectron();
|
const isElectron = utils.isElectron();
|
||||||
const fileUploadRef = useRef<HTMLInputElement>(null);
|
const fileUploadRef = useRef<HTMLInputElement>(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user