mirror of
https://github.com/discourse/discourse.git
synced 2025-02-21 22:34:27 +08:00
UX: improves local-dates modal form UI
This commit is contained in:
parent
8128cbd7db
commit
c3ec758107
@ -18,6 +18,7 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
this.set("date", moment().format(this.dateFormat));
|
this.set("date", moment().format(this.dateFormat));
|
||||||
this.set("time", moment().format(this.timeFormat));
|
this.set("time", moment().format(this.timeFormat));
|
||||||
|
this.set("currentMoment", moment());
|
||||||
this.set("format", `LLL`);
|
this.set("format", `LLL`);
|
||||||
this.set("timezones", (this.siteSettings.discourse_local_dates_default_timezones || "").split("|").filter(f => f));
|
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("|"));
|
this.set("formats", (this.siteSettings.discourse_local_dates_default_formats || "").split("|"));
|
||||||
@ -34,6 +35,16 @@ export default Ember.Component.extend({
|
|||||||
return moment.tz.guess();
|
return moment.tz.guess();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed("formats")
|
||||||
|
previewedFormats(formats) {
|
||||||
|
return formats.map(format => {
|
||||||
|
return {
|
||||||
|
format: format,
|
||||||
|
preview: moment().format(format)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
@computed
|
@computed
|
||||||
recurringOptions() {
|
recurringOptions() {
|
||||||
return [
|
return [
|
||||||
@ -88,6 +99,11 @@ export default Ember.Component.extend({
|
|||||||
return dateTime.isValid();
|
return dateTime.isValid();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed("advancedMode")
|
||||||
|
toggleModeBtnLabel(advancedMode) {
|
||||||
|
return advancedMode ? "discourse_local_dates.create.form.simple_mode" : "discourse_local_dates.create.form.advanced_mode";
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
advancedMode() {
|
advancedMode() {
|
||||||
this.toggleProperty("advancedMode");
|
this.toggleProperty("advancedMode");
|
||||||
|
@ -5,56 +5,78 @@
|
|||||||
style="overflow: auto"}}
|
style="overflow: auto"}}
|
||||||
|
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<div class="control-group">
|
<div class="date-time-configuration">
|
||||||
<div class="controls date-time">
|
<div class="control-group date">
|
||||||
{{date-picker-future class="date" value=date defaultDate="DD-MM-YYYY"}}
|
<label class="control-label">
|
||||||
{{input type="time" value=time class="time"}}
|
{{i18n "discourse_local_dates.create.form.date_title"}}
|
||||||
<span>{{currentUserTimezone}}</span>
|
</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{date-picker-future class="date-input" value=date defaultDate="DD-MM-YYYY"}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group time">
|
||||||
|
<label class="control-label">
|
||||||
|
{{i18n "discourse_local_dates.create.form.time_title"}}
|
||||||
|
</label>
|
||||||
|
<div class="controls">
|
||||||
|
{{input type="time" value=time class="time-input"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<span class="preview">{{currentUserTimezone}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>{{i18n "discourse_local_dates.create.form.recurring_title"}}</h3>
|
{{#unless validDate}}
|
||||||
<div class="control-group">
|
<span class="validation-error">{{i18n "discourse_local_dates.create.form.invalid_date"}}</span>
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
|
<div class="control-group recurrence">
|
||||||
|
<label class="control-label">
|
||||||
|
{{i18n "discourse_local_dates.create.form.recurring_title"}}
|
||||||
|
</label>
|
||||||
{{#if advancedMode}}
|
{{#if advancedMode}}
|
||||||
<label>{{{i18n "discourse_local_dates.create.form.recurring_description"}}}</label>
|
<p>{{{i18n "discourse_local_dates.create.form.recurring_description"}}}</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{combo-box content=recurringOptions value=recurring none="discourse_local_dates.create.form.recurring_none"}}
|
{{combo-box content=recurringOptions class="recurrence-input" value=recurring none="discourse_local_dates.create.form.recurring_none"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{d-button
|
|
||||||
class="advanced-mode-btn"
|
|
||||||
action=(action "advancedMode")
|
|
||||||
icon="cog"
|
|
||||||
label="discourse_local_dates.create.form.advanced_mode"}}
|
|
||||||
|
|
||||||
{{#if advancedMode}}
|
{{#if advancedMode}}
|
||||||
<div class="advanced-options">
|
<div class="advanced-options">
|
||||||
<div class="control-group">
|
<div class="control-group format">
|
||||||
<label>
|
<label>{{i18n "discourse_local_dates.create.form.format_title"}}</label>
|
||||||
|
<p>
|
||||||
{{i18n "discourse_local_dates.create.form.format_description"}}
|
{{i18n "discourse_local_dates.create.form.format_description"}}
|
||||||
(<a target="_blank" rel="noopener" href="https://momentjs.com/docs/#/parsing/string-format/">?</a>)
|
<a target="_blank" rel="noopener" href="https://momentjs.com/docs/#/parsing/string-format/">
|
||||||
</label>
|
{{d-icon "question-circle"}}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{text-field value=format}}
|
{{text-field value=format class="format-input"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<ul class="formats">
|
<ul class="formats">
|
||||||
{{#each formats as |format|}}
|
{{#each previewedFormats as |previewedFormat|}}
|
||||||
<li class="format">
|
<li class="format">
|
||||||
<a href {{action "fillFormat" format}}>{{format}}</a>
|
<a class="moment-format" href {{action "fillFormat" previewedFormat.format}}>
|
||||||
|
{{previewedFormat.format}}
|
||||||
|
</a>
|
||||||
|
<span class="previewed-format">
|
||||||
|
{{previewedFormat.preview}}
|
||||||
|
</span>
|
||||||
</li>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>{{i18n "discourse_local_dates.create.form.timezones_title"}}</h3>
|
<div class="control-group timezones">
|
||||||
<div class="control-group">
|
<label>{{i18n "discourse_local_dates.create.form.timezones_title"}}</label>
|
||||||
<label>{{i18n "discourse_local_dates.create.form.timezones_description"}}</label>
|
<p>{{i18n "discourse_local_dates.create.form.timezones_description"}}</p>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{multi-select allowAny=false maximum=5 content=allTimezones values=timezones}}
|
{{multi-select class="timezones-input" allowAny=false maximum=5 content=allTimezones values=timezones}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -63,16 +85,19 @@
|
|||||||
{{/d-modal-body}}
|
{{/d-modal-body}}
|
||||||
|
|
||||||
<div class="modal-footer discourse-local-dates-create-modal-footer">
|
<div class="modal-footer discourse-local-dates-create-modal-footer">
|
||||||
|
|
||||||
{{#if validDate}}
|
{{#if validDate}}
|
||||||
{{d-button class="btn"
|
{{d-button class="btn"
|
||||||
action="save"
|
action="save"
|
||||||
label="discourse_local_dates.create.form.insert"}}
|
label="discourse_local_dates.create.form.insert"}}
|
||||||
{{else}}
|
|
||||||
<span class="validation-error">{{i18n "discourse_local_dates.create.form.invalid_date"}}</span>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<a href {{action "cancel"}}>
|
<a class="cancel-action" href {{action "cancel"}}>
|
||||||
{{i18n 'cancel'}}
|
{{i18n "cancel"}}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
{{d-button
|
||||||
|
class="advanced-mode-btn"
|
||||||
|
action=(action "advancedMode")
|
||||||
|
icon="cog"
|
||||||
|
label=toggleModeBtnLabel}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -0,0 +1,131 @@
|
|||||||
|
.discourse-local-date {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
&.cooked {
|
||||||
|
color: $primary;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
.d-icon-globe {
|
||||||
|
margin-right: .25em;
|
||||||
|
color: $primary-medium;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary-high;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .d-icon-globe {
|
||||||
|
color: $primary-high;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ .discourse-local-date {
|
||||||
|
margin-left: .5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.discourse-local-dates-create-modal-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
&:before, &:after {
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-action {
|
||||||
|
margin: 0 5px 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn + .cancel-action {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advanced-mode-btn {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.discourse-local-dates-create-modal {
|
||||||
|
min-height: 300px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
.form {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-time-configuration {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.date {
|
||||||
|
.date-input {
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
.date-picker {
|
||||||
|
padding-top: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
margin: 0;
|
||||||
|
width: 120px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
margin-right: 1em;
|
||||||
|
|
||||||
|
.time-input {
|
||||||
|
margin: 0 0.5em 0 0;
|
||||||
|
width: 120px;
|
||||||
|
padding: 3.5px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.validation-error {
|
||||||
|
color: $danger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recurrence {
|
||||||
|
.recurrence-input {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.format {
|
||||||
|
.format-input {
|
||||||
|
width: 280px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.formats {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
.format {
|
||||||
|
.previewed-format {
|
||||||
|
color: $primary-medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.control-group.recurrence, .control-group.format, .control-group.timezones {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.timezones-input {
|
||||||
|
width: 99%;
|
||||||
|
}
|
||||||
|
}
|
@ -1,83 +0,0 @@
|
|||||||
.discourse-local-date {
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
|
|
||||||
&.cooked {
|
|
||||||
color: $primary;
|
|
||||||
font-weight: bold;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
.d-icon-globe {
|
|
||||||
margin-right: .25em;
|
|
||||||
color: $primary-medium;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $primary-high;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .d-icon-globe {
|
|
||||||
color: $primary-high;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ .discourse-local-date {
|
|
||||||
margin-left: .5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.discourse-local-dates-create-modal-footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
.validation-error {
|
|
||||||
color: $danger;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:before, &:after {
|
|
||||||
content: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.discourse-local-dates-create-modal {
|
|
||||||
min-height: 300px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
.form {
|
|
||||||
flex: 1;
|
|
||||||
.controls {
|
|
||||||
&.date-time {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
|
|
||||||
.date {
|
|
||||||
margin: 0 0.5em 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.date-picker {
|
|
||||||
padding-top: 5px;
|
|
||||||
bottom: 5px;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.time {
|
|
||||||
margin: 0 0.5em 0 0;
|
|
||||||
max-width: 100px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.advanced-mode-btn {
|
|
||||||
margin-top: 2em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.select-kit.multi-select {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,16 @@
|
|||||||
|
.discourse-local-dates-create-modal {
|
||||||
|
.form {
|
||||||
|
.date-time-configuration {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
.date .date-input .date-picker {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time .time-input {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ en:
|
|||||||
form:
|
form:
|
||||||
insert: Insert
|
insert: Insert
|
||||||
advanced_mode: Advanced mode
|
advanced_mode: Advanced mode
|
||||||
|
simple_mode: Simple mode
|
||||||
format_description: "Format used to display the date to the user. Use \"\\T\\Z\" to display the user timezone in words (Europe/Paris)"
|
format_description: "Format used to display the date to the user. Use \"\\T\\Z\" to display the user timezone in words (Europe/Paris)"
|
||||||
timezones_title: Timezones to display
|
timezones_title: Timezones to display
|
||||||
timezones_description: Timezones will be used to display dates in preview and fallback.
|
timezones_description: Timezones will be used to display dates in preview and fallback.
|
||||||
@ -15,3 +16,6 @@ en:
|
|||||||
recurring_description: "Define the recurrence of an event. You can also manually edit the recurring option generated by the form and use one of the following keys: years, quarters, months, weeks, days, hours, minutes, seconds, milliseconds."
|
recurring_description: "Define the recurrence of an event. You can also manually edit the recurring option generated by the form and use one of the following keys: years, quarters, months, weeks, days, hours, minutes, seconds, milliseconds."
|
||||||
recurring_none: No recurrence
|
recurring_none: No recurrence
|
||||||
invalid_date: Invalid date, make sure date and time are correct
|
invalid_date: Invalid date, make sure date and time are correct
|
||||||
|
date_title: Date
|
||||||
|
time_title: Time
|
||||||
|
format_title: Date format
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
hide_plugin if self.respond_to?(:hide_plugin)
|
hide_plugin if self.respond_to?(:hide_plugin)
|
||||||
|
|
||||||
register_asset "javascripts/discourse-local-dates.js"
|
register_asset "javascripts/discourse-local-dates.js"
|
||||||
register_asset "stylesheets/discourse-local-dates.scss"
|
register_asset "stylesheets/common/discourse-local-dates.scss"
|
||||||
|
register_asset "stylesheets/mobile/discourse-local-dates.scss"
|
||||||
register_asset "moment.js", :vendored_core_pretty_text
|
register_asset "moment.js", :vendored_core_pretty_text
|
||||||
register_asset "moment-timezone.js", :vendored_core_pretty_text
|
register_asset "moment-timezone.js", :vendored_core_pretty_text
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user