This repository has been archived on 2023-03-18. You can view files and clone it, but cannot push or open issues or pull requests.
osr-discourse-src/app/assets/javascripts/discourse/app/components/topic-timer-info.js
Jarek Radosz 5538b8442e
DEV: Introduce discourseLater (#17532)
A wrapper for `later()` from `@ember/runloop`, similar to `discourseDebounce`. It automatically reduces the delay in testing environment.
2022-07-17 00:50:49 +02:00

151 lines
4.1 KiB
JavaScript

import { cancel } from "@ember/runloop";
import discourseLater from "discourse-common/lib/later";
import Category from "discourse/models/category";
import Component from "@ember/component";
import { DELETE_REPLIES_TYPE } from "discourse/controllers/edit-topic-timer";
import I18n from "I18n";
import discourseComputed, { on } from "discourse-common/utils/decorators";
import { iconHTML } from "discourse-common/lib/icon-library";
import { isTesting } from "discourse-common/config/environment";
import { htmlSafe } from "@ember/template";
export default Component.extend({
classNames: ["topic-timer-info"],
_delayedRerender: null,
clockIcon: htmlSafe(`${iconHTML("far-clock")}`),
trashLabel: I18n.t("post.controls.remove_timer"),
title: null,
notice: null,
showTopicTimer: null,
showTopicTimerModal: null,
removeTopicTimer: null,
@on("didReceiveAttrs")
setupRenderer() {
this.renderTopicTimer();
},
@on("willDestroyElement")
cancelDelayedRenderer() {
if (this._delayedRerender) {
cancel(this._delayedRerender);
}
},
@discourseComputed
canModifyTimer() {
return this.currentUser && this.currentUser.get("canManageTopic");
},
@discourseComputed("canModifyTimer", "removeTopicTimer")
showTrashCan(canModifyTimer, removeTopicTimer) {
return canModifyTimer && removeTopicTimer;
},
@discourseComputed("canModifyTimer", "showTopicTimerModal")
showEdit(canModifyTimer, showTopicTimerModal) {
return canModifyTimer && showTopicTimerModal;
},
additionalOpts() {
return {};
},
renderTopicTimer() {
const isDeleteRepliesType = this.statusType === DELETE_REPLIES_TYPE;
if (
!isDeleteRepliesType &&
!this.basedOnLastPost &&
(!this.executeAt || this.executeAt < moment())
) {
this.set("showTopicTimer", null);
return;
}
if (this.isDestroyed) {
return;
}
const topicStatus = this.topicClosed ? "close" : "open";
const topicStatusKnown = this.topicClosed !== undefined;
if (topicStatusKnown && topicStatus === this.statusType) {
return;
}
const statusUpdateAt = moment(this.executeAt);
const duration = moment.duration(statusUpdateAt - moment());
const minutesLeft = duration.asMinutes();
if (minutesLeft > 0 || isDeleteRepliesType || this.basedOnLastPost) {
// We don't want to display a notice before a topic timer time has been set
if (!this.executeAt) {
return;
}
let durationMinutes = parseInt(this.durationMinutes, 10) || 0;
let options = {
timeLeft: duration.humanize(true),
duration: moment
.duration(durationMinutes, "minutes")
.humanize({ s: 60, m: 60, h: 24 }),
};
const categoryId = this.categoryId;
if (categoryId) {
const category = Category.findById(categoryId);
options = Object.assign(
{
categoryName: category.get("slug"),
categoryUrl: category.get("url"),
},
options
);
}
options = Object.assign(options, this.additionalOpts());
this.setProperties({
title: htmlSafe(`${moment(this.executeAt).format("LLLL")}`),
notice: htmlSafe(`${I18n.t(this._noticeKey(), options)}`),
showTopicTimer: true,
});
// TODO Sam: concerned this can cause a heavy rerender loop
if (!isTesting()) {
this._delayedRerender = discourseLater(() => {
this.renderTopicTimer();
}, this.rerenderDelay(minutesLeft));
}
} else {
this.set("showTopicTimer", null);
}
},
rerenderDelay(minutesLeft) {
if (minutesLeft > 2160) {
return 12 * 60 * 60000;
} else if (minutesLeft > 1410) {
return 60 * 60000;
} else if (minutesLeft > 90) {
return 30 * 60000;
} else if (minutesLeft > 2) {
return 60000;
}
return 1000;
},
_noticeKey() {
let statusType = this.statusType;
if (statusType === "silent_close") {
statusType = "close";
}
if (this.basedOnLastPost && statusType === "close") {
statusType = "close_after_last_post";
}
return `topic.status_update_notice.auto_${statusType}`;
},
});