diff --git a/app/assets/javascripts/discourse/app/components/relative-time-picker.js b/app/assets/javascripts/discourse/app/components/relative-time-picker.js index be95d8e0d83..cb23e50cadf 100644 --- a/app/assets/javascripts/discourse/app/components/relative-time-picker.js +++ b/app/assets/javascripts/discourse/app/components/relative-time-picker.js @@ -35,17 +35,38 @@ export default Component.extend({ this.hiddenIntervals = this.hiddenIntervals || []; }, + _roundedDuration(duration) { + let rounded = parseFloat(duration.toFixed(2)); + + // showing 2.00 instead of just 2 in the input is weird + if (rounded % 1 === 0) { + return parseInt(rounded, 10); + } + + return rounded; + }, + _setInitialDurationFromHours(hours) { - if (hours >= 730) { + if (hours >= 8760) { this.setProperties({ - duration: Math.floor(hours / 30 / 24), + duration: this._roundedDuration(hours / 365 / 24), + selectedInterval: "years", + }); + } else if (hours >= 730) { + this.setProperties({ + duration: this._roundedDuration(hours / 30 / 24), selectedInterval: "months", }); } else if (hours >= 24) { this.setProperties({ - duration: Math.floor(hours / 24), + duration: this._roundedDuration(hours / 24), selectedInterval: "days", }); + } else if (hours < 1) { + this.setProperties({ + duration: this._roundedDuration(hours * 60), + selectedInterval: "mins", + }); } else { this.setProperties({ duration: hours, @@ -55,19 +76,24 @@ export default Component.extend({ }, _setInitialDurationFromMinutes(mins) { - if (mins >= 43800) { + if (mins >= 525600) { this.setProperties({ - duration: Math.floor(mins / 30 / 60 / 24), + duration: this._roundedDuration(mins / 365 / 60 / 24), + selectedInterval: "years", + }); + } else if (mins >= 43800) { + this.setProperties({ + duration: this._roundedDuration(mins / 30 / 60 / 24), selectedInterval: "months", }); } else if (mins >= 1440) { this.setProperties({ - duration: Math.floor(mins / 60 / 24), + duration: this._roundedDuration(mins / 60 / 24), selectedInterval: "days", }); } else if (mins >= 60) { this.setProperties({ - duration: Math.floor(mins / 60), + duration: this._roundedDuration(mins / 60), selectedInterval: "hours", }); } else { @@ -109,6 +135,10 @@ export default Component.extend({ id: "months", name: I18n.t("relative_time_picker.months", { count }), }, + { + id: "years", + name: I18n.t("relative_time_picker.years", { count }), + }, ].filter((interval) => !this.hiddenIntervals.includes(interval.id)); }, @@ -133,7 +163,10 @@ export default Component.extend({ mins = duration * 60 * 24; break; case "months": - mins = duration * 60 * 24 * 30; // least accurate because of varying days in months + mins = duration * 60 * 24 * 30; // less accurate because of varying days in months + break; + case "years": + mins = duration * 60 * 24 * 365; // least accurate because of varying days in months/years break; } diff --git a/app/assets/javascripts/discourse/app/controllers/edit-topic-timer.js b/app/assets/javascripts/discourse/app/controllers/edit-topic-timer.js index 2cfbdc74c32..96ce3817ef2 100644 --- a/app/assets/javascripts/discourse/app/controllers/edit-topic-timer.js +++ b/app/assets/javascripts/discourse/app/controllers/edit-topic-timer.js @@ -203,7 +203,11 @@ export default Controller.extend(ModalFunctionality, { }, removeTimer() { - this._setTimer(null, null, this.get("topicTimer.status_type")); + let statusType = this.get("topicTimer.status_type"); + if (statusType === CLOSE_AFTER_LAST_POST_STATUS_TYPE) { + statusType = CLOSE_STATUS_TYPE; + } + this._setTimer(null, null, statusType); }, }, }); diff --git a/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js b/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js new file mode 100644 index 00000000000..e0ed34fb08c --- /dev/null +++ b/app/assets/javascripts/discourse/tests/integration/components/relative-time-picker-test.js @@ -0,0 +1,120 @@ +import componentTest, { + setupRenderingTest, +} from "discourse/tests/helpers/component-test"; +import { discourseModule, query } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import selectKit from "discourse/tests/helpers/select-kit-helper"; + +discourseModule( + "Integration | Component | relative-time-picker", + function (hooks) { + setupRenderingTest(hooks); + + hooks.beforeEach(function () { + this.set("subject", selectKit()); + }); + + componentTest("prefills and preselects minutes", { + template: hbs`{{relative-time-picker durationMinutes="5"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "mins"); + assert.equal(prefilledDuration, 5); + }, + }); + + componentTest("prefills and preselects hours based on translated minutes", { + template: hbs`{{relative-time-picker durationMinutes="90"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "hours"); + assert.equal(prefilledDuration, 1.5); + }, + }); + + componentTest("prefills and preselects days based on translated minutes", { + template: hbs`{{relative-time-picker durationMinutes="2880"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "days"); + assert.equal(prefilledDuration, 2); + }, + }); + + componentTest( + "prefills and preselects months based on translated minutes", + { + template: hbs`{{relative-time-picker durationMinutes="129600"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "months"); + assert.equal(prefilledDuration, 3); + }, + } + ); + + componentTest("prefills and preselects years based on translated minutes", { + template: hbs`{{relative-time-picker durationMinutes="525600"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "years"); + assert.equal(prefilledDuration, 1); + }, + }); + + componentTest("prefills and preselects hours", { + template: hbs`{{relative-time-picker durationHours="5"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "hours"); + assert.equal(prefilledDuration, 5); + }, + }); + + componentTest("prefills and preselects minutes based on translated hours", { + template: hbs`{{relative-time-picker durationHours="0.5"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "mins"); + assert.equal(prefilledDuration, 30); + }, + }); + + componentTest("prefills and preselects days based on translated hours", { + template: hbs`{{relative-time-picker durationHours="48"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "days"); + assert.equal(prefilledDuration, 2); + }, + }); + + componentTest("prefills and preselects months based on translated hours", { + template: hbs`{{relative-time-picker durationHours="2160"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "months"); + assert.equal(prefilledDuration, 3); + }, + }); + + componentTest("prefills and preselects years based on translated hours", { + template: hbs`{{relative-time-picker durationHours="17520"}}`, + + test(assert) { + const prefilledDuration = query(".relative-time-duration").value; + assert.equal(this.subject.header().value(), "years"); + assert.equal(prefilledDuration, 2); + }, + }); + } +); diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 13bd961ea4f..f693968c785 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -588,6 +588,9 @@ en: months: one: "month" other: "months" + years: + one: "year" + other: "years" time_shortcut: later_today: "Later today"