mirror of
https://github.com/discourse/discourse.git
synced 2025-02-20 10:25:32 +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("time", moment().format(this.timeFormat));
|
||||
this.set("currentMoment", moment());
|
||||
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("|"));
|
||||
|
@ -34,6 +35,16 @@ export default Ember.Component.extend({
|
|||
return moment.tz.guess();
|
||||
},
|
||||
|
||||
@computed("formats")
|
||||
previewedFormats(formats) {
|
||||
return formats.map(format => {
|
||||
return {
|
||||
format: format,
|
||||
preview: moment().format(format)
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
@computed
|
||||
recurringOptions() {
|
||||
return [
|
||||
|
@ -88,6 +99,11 @@ export default Ember.Component.extend({
|
|||
return dateTime.isValid();
|
||||
},
|
||||
|
||||
@computed("advancedMode")
|
||||
toggleModeBtnLabel(advancedMode) {
|
||||
return advancedMode ? "discourse_local_dates.create.form.simple_mode" : "discourse_local_dates.create.form.advanced_mode";
|
||||
},
|
||||
|
||||
actions: {
|
||||
advancedMode() {
|
||||
this.toggleProperty("advancedMode");
|
||||
|
|
|
@ -5,56 +5,78 @@
|
|||
style="overflow: auto"}}
|
||||
|
||||
<div class="form">
|
||||
<div class="control-group">
|
||||
<div class="controls date-time">
|
||||
{{date-picker-future class="date" value=date defaultDate="DD-MM-YYYY"}}
|
||||
{{input type="time" value=time class="time"}}
|
||||
<span>{{currentUserTimezone}}</span>
|
||||
<div class="date-time-configuration">
|
||||
<div class="control-group date">
|
||||
<label class="control-label">
|
||||
{{i18n "discourse_local_dates.create.form.date_title"}}
|
||||
</label>
|
||||
<div class="controls">
|
||||
{{date-picker-future class="date-input" value=date defaultDate="DD-MM-YYYY"}}
|
||||
</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>
|
||||
|
||||
<h3>{{i18n "discourse_local_dates.create.form.recurring_title"}}</h3>
|
||||
<div class="control-group">
|
||||
{{#unless validDate}}
|
||||
<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}}
|
||||
<label>{{{i18n "discourse_local_dates.create.form.recurring_description"}}}</label>
|
||||
<p>{{{i18n "discourse_local_dates.create.form.recurring_description"}}}</p>
|
||||
{{/if}}
|
||||
<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>
|
||||
|
||||
{{d-button
|
||||
class="advanced-mode-btn"
|
||||
action=(action "advancedMode")
|
||||
icon="cog"
|
||||
label="discourse_local_dates.create.form.advanced_mode"}}
|
||||
|
||||
{{#if advancedMode}}
|
||||
<div class="advanced-options">
|
||||
<div class="control-group">
|
||||
<label>
|
||||
<div class="control-group format">
|
||||
<label>{{i18n "discourse_local_dates.create.form.format_title"}}</label>
|
||||
<p>
|
||||
{{i18n "discourse_local_dates.create.form.format_description"}}
|
||||
(<a target="_blank" rel="noopener" href="https://momentjs.com/docs/#/parsing/string-format/">?</a>)
|
||||
</label>
|
||||
<a target="_blank" rel="noopener" href="https://momentjs.com/docs/#/parsing/string-format/">
|
||||
{{d-icon "question-circle"}}
|
||||
</a>
|
||||
</p>
|
||||
<div class="controls">
|
||||
{{text-field value=format}}
|
||||
{{text-field value=format class="format-input"}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<ul class="formats">
|
||||
{{#each formats as |format|}}
|
||||
{{#each previewedFormats as |previewedFormat|}}
|
||||
<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>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<h3>{{i18n "discourse_local_dates.create.form.timezones_title"}}</h3>
|
||||
<div class="control-group">
|
||||
<label>{{i18n "discourse_local_dates.create.form.timezones_description"}}</label>
|
||||
<div class="control-group timezones">
|
||||
<label>{{i18n "discourse_local_dates.create.form.timezones_title"}}</label>
|
||||
<p>{{i18n "discourse_local_dates.create.form.timezones_description"}}</p>
|
||||
<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>
|
||||
|
@ -63,16 +85,19 @@
|
|||
{{/d-modal-body}}
|
||||
|
||||
<div class="modal-footer discourse-local-dates-create-modal-footer">
|
||||
|
||||
{{#if validDate}}
|
||||
{{d-button class="btn"
|
||||
action="save"
|
||||
label="discourse_local_dates.create.form.insert"}}
|
||||
{{else}}
|
||||
<span class="validation-error">{{i18n "discourse_local_dates.create.form.invalid_date"}}</span>
|
||||
{{/if}}
|
||||
|
||||
<a href {{action "cancel"}}>
|
||||
{{i18n 'cancel'}}
|
||||
<a class="cancel-action" href {{action "cancel"}}>
|
||||
{{i18n "cancel"}}
|
||||
</a>
|
||||
|
||||
{{d-button
|
||||
class="advanced-mode-btn"
|
||||
action=(action "advancedMode")
|
||||
icon="cog"
|
||||
label=toggleModeBtnLabel}}
|
||||
</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:
|
||||
insert: Insert
|
||||
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)"
|
||||
timezones_title: Timezones to display
|
||||
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_none: No recurrence
|
||||
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)
|
||||
|
||||
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-timezone.js", :vendored_core_pretty_text
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user