diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js new file mode 100644 index 00000000000..d5459e82dcf --- /dev/null +++ b/plugins/discourse-local-dates/assets/javascripts/discourse-local-dates.js @@ -0,0 +1,75 @@ +(function($) { + $.fn.applyLocalDates = function(repeat) { + function _formatTimezone(timezone) { + return timezone.replace("_", " ").split("/"); + } + + function processElement($element, options) { + repeat = repeat || true; + + if (this.timeout) { + clearTimeout(this.timeout); + } + + var relativeTime = moment.utc(options.date + " " + options.time, "YYYY-MM-DD HH:mm"); + + if (options.recurring && relativeTime < moment().utc()) { + var parts = options.recurring.split("."); + var count = parseInt(parts[0], 10); + var type = parts[1]; + var diff = moment().diff(relativeTime, type); + var add = Math.ceil(diff + count); + + relativeTime = relativeTime.add(add, type); + } + + var previews = options.timezones.split("|").map(function(timezone) { + var dateTime = relativeTime.tz(timezone).format(options.format); + var timezoneParts = _formatTimezone(timezone); + + if (dateTime.match(/TZ/)) { + return dateTime.replace("TZ", timezoneParts.join(": ")); + } else { + var output = timezoneParts[0]; + if (timezoneParts[1]) { + output += " (" + timezoneParts[1] + ")"; + } + output += " " + dateTime; + return output; + } + }); + + relativeTime = relativeTime.tz(moment.tz.guess()).format(options.format); + + var html = ""; + html += ""; + html += relativeTime.replace("TZ", _formatTimezone(moment.tz.guess()).join(": ")); + html += ""; + + $element + .html(html) + .attr("title", previews.join("\n")) + .attr("onclick", "alert('" + previews.join("\\n") + "');return false;") + .addClass("cooked"); + + if (repeat) { + this.timeout = setTimeout(function() { + processElement($element, options); + }, 10000); + } + } + + return this.each(function() { + var $this = $(this); + + var options = {}; + options.format = $this.attr("data-format"); + options.date = $this.attr("data-date"); + options.time = $this.attr("data-time"); + options.recurring = $this.attr("data-recurring"); + options.timezones = $this.attr("data-timezones") || "Etc/UTC"; + + processElement($this, options); + }); + }; +})(jQuery); diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6 b/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6 new file mode 100644 index 00000000000..9cb7bf5ac1d --- /dev/null +++ b/plugins/discourse-local-dates/assets/javascripts/discourse/components/discourse-local-dates-create-form.js.es6 @@ -0,0 +1,116 @@ +import computed from "ember-addons/ember-computed-decorators"; +import { observes } from 'ember-addons/ember-computed-decorators'; + +export default Ember.Component.extend({ + timeFormat: "HH:mm", + dateFormat: "YYYY-MM-DD", + dateTimeFormat: "YYYY-MM-DD HH:mm", + config: null, + date: null, + time: null, + format: null, + formats: null, + recurring: null, + advancedMode: false, + + init() { + this._super(); + + this.set("date", moment().format(this.dateFormat)); + this.set("time", moment().format(this.timeFormat)); + this.set("format", `LLL`); + this.set("timezones", (this.siteSettings.discourse_local_dates_default_timezones || "").split("|").filter(f => f)); + this.set("formats", (this.siteSettings.discourse_local_dates_default_formats || "").split("|")); + }, + + didInsertElement() { + this._super(); + + this._setConfig(); + }, + + @computed + currentUserTimezone() { + return moment.tz.guess(); + }, + + @computed + recurringOptions() { + return [ + { name: "Every day", id: "1.days" }, + { name: "Every week", id: "1.weeks" }, + { name: "Every two weeks", id: "2.weeks" }, + { name: "Every month", id: "1.months" }, + { name: "Every two months", id: "2.months" }, + { name: "Every three months", id: "3.months" }, + { name: "Every six months", id: "6.months" }, + { name: "Every year", id: "1.years" }, + ]; + }, + + @computed() + allTimezones() { + return _.map(moment.tz.names(), (z) => z); + }, + + @observes("date", "time", "recurring", "format", "timezones") + _setConfig() { + const date = this.get("date"); + const time = this.get("time"); + const recurring = this.get("recurring"); + const format = this.get("format"); + const timezones = this.get("timezones"); + const dateTime = moment(`${date} ${time}`, this.dateTimeFormat).utc(); + + this.set("config", { + date: dateTime.format(this.dateFormat), + time: dateTime.format(this.timeFormat), + dateTime, + recurring, + format, + timezones, + }); + }, + + getTextConfig(config) { + let text = `[date=${config.date} `; + if (config.recurring) text += `recurring=${config.recurring} `; + text += `time=${config.time} `; + text += `format=${config.format} `; + text += `timezones="${config.timezones.join("|")}"`; + text += `]`; + return text; + }, + + @computed("config.dateTime") + validDate(dateTime) { + if (!dateTime) return false; + return dateTime.isValid(); + }, + + actions: { + advancedMode() { + this.toggleProperty("advancedMode"); + }, + + save() { + this._closeModal(); + + const textConfig = this.getTextConfig(this.get("config")); + this.get("toolbarEvent").addText(textConfig); + }, + + fillFormat(format) { + this.set("format", format); + }, + + cancel() { + this._closeModal(); + } + }, + + _closeModal() { + const composer = Discourse.__container__.lookup("controller:composer"); + composer.send("closeModal"); + } +}); diff --git a/plugins/discourse-local-dates/assets/javascripts/discourse/templates/components/discourse-local-dates-create-form.hbs b/plugins/discourse-local-dates/assets/javascripts/discourse/templates/components/discourse-local-dates-create-form.hbs new file mode 100644 index 00000000000..f9ffba54f25 --- /dev/null +++ b/plugins/discourse-local-dates/assets/javascripts/discourse/templates/components/discourse-local-dates-create-form.hbs @@ -0,0 +1,77 @@ +{{#d-modal-body + title="discourse_local_dates.create.modal_title" + class="discourse-local-dates-create-modal" + style="overflow: auto"}} + +