From 1da4e1be0a6d7f9cb5d3f35604f6c085951ec7c0 Mon Sep 17 00:00:00 2001 From: Jarek Radosz Date: Fri, 24 Nov 2023 14:16:17 +0100 Subject: [PATCH] DEV: Convert relative-time-picker to gjs (#24324) --- .../app/components/relative-time-picker.gjs | 174 ++++++++++++++++ .../app/components/relative-time-picker.hbs | 17 -- .../app/components/relative-time-picker.js | 195 ------------------ 3 files changed, 174 insertions(+), 212 deletions(-) create mode 100644 app/assets/javascripts/discourse/app/components/relative-time-picker.gjs delete mode 100644 app/assets/javascripts/discourse/app/components/relative-time-picker.hbs delete mode 100644 app/assets/javascripts/discourse/app/components/relative-time-picker.js diff --git a/app/assets/javascripts/discourse/app/components/relative-time-picker.gjs b/app/assets/javascripts/discourse/app/components/relative-time-picker.gjs new file mode 100644 index 00000000000..17155a80d31 --- /dev/null +++ b/app/assets/javascripts/discourse/app/components/relative-time-picker.gjs @@ -0,0 +1,174 @@ +import Component from "@glimmer/component"; +import { tracked } from "@glimmer/tracking"; +import { on } from "@ember/modifier"; +import { action } from "@ember/object"; +import { isBlank } from "@ember/utils"; +import I18n from "discourse-i18n"; +import ComboBox from "select-kit/components/combo-box"; + +export default class RelativeTimePicker extends Component { + @tracked duration; + @tracked selectedInterval; + + constructor() { + super(...arguments); + + const usesHours = this.args.durationHours !== undefined; + const usesMinutes = this.args.durationMinutes !== undefined; + + if (usesHours && usesMinutes) { + throw new Error( + "relative-time needs initial duration in hours OR minutes, both are not supported" + ); + } + + if (usesHours) { + this._setInitialDurationFromHours(); + } else { + this._setInitialDurationFromMinutes(); + } + } + + _roundedDuration(duration) { + const rounded = parseFloat(duration.toFixed(2)); + + // showing 2.00 instead of just 2 in the input is weird + return rounded % 1 === 0 ? parseInt(rounded, 10) : rounded; + } + + _setInitialDurationFromHours() { + if (this.args.durationHours === null) { + this.duration = this.args.durationHours; + this.selectedInterval = "hours"; + } else if (this.args.durationHours >= 8760) { + this.duration = this._roundedDuration(this.args.durationHours / 365 / 24); + this.selectedInterval = "years"; + } else if (this.args.durationHours >= 730) { + this.duration = this._roundedDuration(this.args.durationHours / 30 / 24); + this.selectedInterval = "months"; + } else if (this.args.durationHours >= 24) { + this.duration = this._roundedDuration(this.args.durationHours / 24); + this.selectedInterval = "days"; + } else if (this.args.durationHours < 1) { + this.duration = this._roundedDuration(this.args.durationHours * 60); + this.selectedInterval = "mins"; + } else { + this.duration = this.args.durationHours; + this.selectedInterval = "hours"; + } + } + + _setInitialDurationFromMinutes() { + if (this.args.durationMinutes >= 525600) { + this.duration = this._roundedDuration( + this.args.durationMinutes / 365 / 60 / 24 + ); + this.selectedInterval = "years"; + } else if (this.args.durationMinutes >= 43800) { + this.duration = this._roundedDuration( + this.args.durationMinutes / 30 / 60 / 24 + ); + this.selectedInterval = "months"; + } else if (this.args.durationMinutes >= 1440) { + this.duration = this._roundedDuration( + this.args.durationMinutes / 60 / 24 + ); + this.selectedInterval = "days"; + } else if (this.args.durationMinutes >= 60) { + this.duration = this._roundedDuration(this.args.durationMinutes / 60); + this.selectedInterval = "hours"; + } else { + this.duration = this.args.durationMinutes; + this.selectedInterval = "mins"; + } + } + + get durationMin() { + return this.selectedInterval === "mins" ? 1 : 0.1; + } + + get durationStep() { + return this.selectedInterval === "mins" ? 1 : 0.05; + } + + get intervals() { + const count = this.duration ? parseFloat(this.duration) : 0; + + return [ + { + id: "mins", + name: I18n.t("relative_time_picker.minutes", { count }), + }, + { + id: "hours", + name: I18n.t("relative_time_picker.hours", { count }), + }, + { + id: "days", + name: I18n.t("relative_time_picker.days", { count }), + }, + { + id: "months", + name: I18n.t("relative_time_picker.months", { count }), + }, + { + id: "years", + name: I18n.t("relative_time_picker.years", { count }), + }, + ].filter((interval) => !this.args.hiddenIntervals?.includes(interval.id)); + } + + get calculatedMinutes() { + if (isBlank(this.duration)) { + return null; + } + + const duration = parseFloat(this.duration); + + switch (this.selectedInterval) { + case "mins": + // we round up here in case the user manually inputted a step < 1 + return Math.ceil(duration); + case "hours": + return duration * 60; + case "days": + return duration * 60 * 24; + case "months": + return duration * 60 * 24 * 30; // less accurate because of varying days in months + case "years": + return duration * 60 * 24 * 365; // least accurate because of varying days in months/years + } + } + + @action + onChangeInterval(interval) { + this.selectedInterval = interval; + this.args.onChange?.(this.calculatedMinutes); + } + + @action + onChangeDuration(event) { + this.duration = event.target.value; + this.args.onChange?.(this.calculatedMinutes); + } + + +} diff --git a/app/assets/javascripts/discourse/app/components/relative-time-picker.hbs b/app/assets/javascripts/discourse/app/components/relative-time-picker.hbs deleted file mode 100644 index ae3fc3c2d7c..00000000000 --- a/app/assets/javascripts/discourse/app/components/relative-time-picker.hbs +++ /dev/null @@ -1,17 +0,0 @@ -
- - -
\ No newline at end of file diff --git a/app/assets/javascripts/discourse/app/components/relative-time-picker.js b/app/assets/javascripts/discourse/app/components/relative-time-picker.js deleted file mode 100644 index ac973881a3b..00000000000 --- a/app/assets/javascripts/discourse/app/components/relative-time-picker.js +++ /dev/null @@ -1,195 +0,0 @@ -import Component from "@ember/component"; -import { action } from "@ember/object"; -import { isBlank } from "@ember/utils"; -import discourseComputed, { on } from "discourse-common/utils/decorators"; -import I18n from "discourse-i18n"; - -export default Component.extend({ - tagName: "", - selectedInterval: "mins", - durationMinutes: null, - durationHours: null, - duration: null, - hiddenIntervals: null, - - @on("init") - cloneDuration() { - const usesHours = Object.hasOwn(this.attrs, "durationHours"); - const usesMinutes = Object.hasOwn(this.attrs, "durationMinutes"); - - if (usesHours && usesMinutes) { - throw new Error( - "relative-time needs initial duration in hours OR minutes, both are not supported" - ); - } - - if (usesHours) { - this._setInitialDurationFromHours(this.durationHours); - } else { - this._setInitialDurationFromMinutes(this.durationMinutes); - } - }, - - @on("init") - setHiddenIntervals() { - 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 === null) { - this.setProperties({ - duration: hours, - selectedInterval: "hours", - }); - } else if (hours >= 8760) { - this.setProperties({ - 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: this._roundedDuration(hours / 24), - selectedInterval: "days", - }); - } else if (hours < 1) { - this.setProperties({ - duration: this._roundedDuration(hours * 60), - selectedInterval: "mins", - }); - } else { - this.setProperties({ - duration: hours, - selectedInterval: "hours", - }); - } - }, - - _setInitialDurationFromMinutes(mins) { - if (mins >= 525600) { - this.setProperties({ - 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: this._roundedDuration(mins / 60 / 24), - selectedInterval: "days", - }); - } else if (mins >= 60) { - this.setProperties({ - duration: this._roundedDuration(mins / 60), - selectedInterval: "hours", - }); - } else { - this.setProperties({ - duration: mins, - selectedInterval: "mins", - }); - } - }, - - @discourseComputed("selectedInterval") - durationMin(selectedInterval) { - return selectedInterval === "mins" ? 1 : 0.1; - }, - - @discourseComputed("selectedInterval") - durationStep(selectedInterval) { - return selectedInterval === "mins" ? 1 : 0.05; - }, - - @discourseComputed("duration") - intervals(duration) { - const count = duration ? parseFloat(duration) : 0; - - return [ - { - id: "mins", - name: I18n.t("relative_time_picker.minutes", { count }), - }, - { - id: "hours", - name: I18n.t("relative_time_picker.hours", { count }), - }, - { - id: "days", - name: I18n.t("relative_time_picker.days", { count }), - }, - { - 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)); - }, - - @discourseComputed("selectedInterval", "duration") - calculatedMinutes(interval, duration) { - if (isBlank(duration)) { - return null; - } - duration = parseFloat(duration); - - let mins = 0; - - switch (interval) { - case "mins": - // we round up here in case the user manually inputted a step < 1 - mins = Math.ceil(duration); - break; - case "hours": - mins = duration * 60; - break; - case "days": - mins = duration * 60 * 24; - break; - case "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; - } - - return mins; - }, - - @action - onChangeInterval(newInterval) { - this.set("selectedInterval", newInterval); - if (this.onChange) { - this.onChange(this.calculatedMinutes); - } - }, - - @action - onChangeDuration() { - if (this.onChange) { - this.onChange(this.calculatedMinutes); - } - }, -});