UX: rework date time input range (#9524)

This commit is contained in:
Joffrey JAFFEUX
2020-04-22 22:17:53 +02:00
committed by GitHub
parent 094ddb1c1f
commit 3bbd8b1258
29 changed files with 581 additions and 612 deletions

View File

@@ -1,7 +1,7 @@
import discourseComputed from "discourse-common/utils/decorators";
import { makeArray } from "discourse-common/lib/helpers";
import { alias, or, and, reads, equal, notEmpty } from "@ember/object/computed";
import EmberObject from "@ember/object";
import { alias, or, and, equal, notEmpty } from "@ember/object/computed";
import EmberObject, { computed, action } from "@ember/object";
import { next } from "@ember/runloop";
import Component from "@ember/component";
import ReportLoader from "discourse/lib/reports-loader";
@@ -9,6 +9,7 @@ import { exportEntity } from "discourse/lib/export-csv";
import { outputExportResult } from "discourse/lib/export-result";
import Report, { SCHEMA_VERSION } from "admin/models/report";
import ENV from "discourse-common/config/environment";
import { isPresent } from "@ember/utils";
const TABLE_OPTIONS = {
perPage: 8,
@@ -69,8 +70,21 @@ export default Component.extend({
this._reports = [];
},
startDate: reads("filters.startDate"),
endDate: reads("filters.endDate"),
startDate: computed("filters.startDate", function() {
if (this.filters && isPresent(this.filters.startDate)) {
return moment(this.filters.startDate, "YYYY-MM-DD");
} else {
return moment();
}
}),
endDate: computed("filters.endDate", function() {
if (this.filters && isPresent(this.filters.endDate)) {
return moment(this.filters.endDate, "YYYY-MM-DD");
} else {
return moment();
}
}),
didReceiveAttrs() {
this._super(...arguments);
@@ -126,39 +140,18 @@ export default Component.extend({
return `admin-report-${currentMode.replace(/_/g, "-")}`;
},
@discourseComputed("startDate")
normalizedStartDate(startDate) {
return startDate && typeof startDate.isValid === "function"
? moment
.utc(startDate.toISOString())
.locale("en")
.format("YYYYMMDD")
: moment(startDate)
.locale("en")
.format("YYYYMMDD");
},
@discourseComputed("endDate")
normalizedEndDate(endDate) {
return endDate && typeof endDate.isValid === "function"
? moment
.utc(endDate.toISOString())
.locale("en")
.format("YYYYMMDD")
: moment(endDate)
.locale("en")
.format("YYYYMMDD");
},
@discourseComputed(
"dataSourceName",
"normalizedStartDate",
"normalizedEndDate",
"startDate",
"endDate",
"filters.customFilters"
)
reportKey(dataSourceName, startDate, endDate, customFilters) {
if (!dataSourceName || !startDate || !endDate) return null;
startDate = startDate.toISOString(true).split("T")[0];
endDate = endDate.toISOString(true).split("T")[0];
let reportKey = "reports:";
reportKey += [
dataSourceName,
@@ -179,74 +172,61 @@ export default Component.extend({
return reportKey;
},
actions: {
onChangeEndDate(date) {
const startDate = moment(this.startDate);
const newEndDate = moment(date).endOf("day");
@action
onChangeDateRange(range) {
this.send("refreshReport", {
startDate: range.from,
endDate: range.to
});
},
if (newEndDate.isSameOrAfter(startDate)) {
this.set("endDate", newEndDate.format("YYYY-MM-DD"));
} else {
this.set("endDate", startDate.endOf("day").format("YYYY-MM-DD"));
}
@action
applyFilter(id, value) {
let customFilters = this.get("filters.customFilters") || {};
this.send("refreshReport");
},
onChangeStartDate(date) {
const endDate = moment(this.endDate);
const newStartDate = moment(date).startOf("day");
if (newStartDate.isSameOrBefore(endDate)) {
this.set("startDate", newStartDate.format("YYYY-MM-DD"));
} else {
this.set("startDate", endDate.startOf("day").format("YYYY-MM-DD"));
}
this.send("refreshReport");
},
applyFilter(id, value) {
let customFilters = this.get("filters.customFilters") || {};
if (typeof value === "undefined") {
delete customFilters[id];
} else {
customFilters[id] = value;
}
this.attrs.onRefresh({
type: this.get("model.type"),
startDate: this.startDate,
endDate: this.endDate,
filters: customFilters
});
},
refreshReport() {
this.attrs.onRefresh({
type: this.get("model.type"),
startDate: this.startDate,
endDate: this.endDate,
filters: this.get("filters.customFilters")
});
},
exportCsv() {
const customFilters = this.get("filters.customFilters") || {};
exportEntity("report", {
name: this.get("model.type"),
start_date: this.startDate,
end_date: this.endDate,
category_id: customFilters.category,
group_id: customFilters.group
}).then(outputExportResult);
},
changeMode(mode) {
this.set("currentMode", mode);
if (typeof value === "undefined") {
delete customFilters[id];
} else {
customFilters[id] = value;
}
this.send("refreshReport", {
filters: customFilters
});
},
@action
refreshReport(options = {}) {
this.attrs.onRefresh({
type: this.get("model.type"),
startDate:
typeof options.startDate === "undefined"
? this.startDate
: options.startDate,
endDate:
typeof options.endDate === "undefined" ? this.endDate : options.endDate,
filters:
typeof options.filters === "undefined"
? this.get("filters.customFilters")
: options.filters
});
},
@action
exportCsv() {
const customFilters = this.get("filters.customFilters") || {};
exportEntity("report", {
name: this.get("model.type"),
start_date: this.startDate.toISOString(true).split("T")[0],
end_date: this.endDate.toISOString(true).split("T")[0],
category_id: customFilters.category,
group_id: customFilters.group
}).then(outputExportResult);
},
@action
changeMode(mode) {
this.set("currentMode", mode);
},
_computeReport() {
@@ -276,10 +256,8 @@ export default Component.extend({
if (!this.startDate || !this.endDate) {
report = sort(filteredReports)[0];
} else {
const reportKey = this.reportKey;
report = sort(
filteredReports.filter(r => r.report_key.includes(reportKey))
filteredReports.filter(r => r.report_key.includes(this.reportKey))
)[0];
if (!report) return;
@@ -339,15 +317,15 @@ export default Component.extend({
let payload = { data: { cache: true, facets } };
if (this.startDate) {
payload.data.start_date = moment
.utc(this.startDate, "YYYY-MM-DD")
.toISOString();
payload.data.start_date = moment(this.startDate)
.toISOString(true)
.split("T")[0];
}
if (this.endDate) {
payload.data.end_date = moment
.utc(this.endDate, "YYYY-MM-DD")
.toISOString();
payload.data.end_date = moment(this.endDate)
.toISOString(true)
.split("T")[0];
}
if (this.get("reportOptions.table.limit")) {

View File

@@ -13,8 +13,7 @@ export default DiscourseRoute.extend({
params.startDate =
params.start_date ||
moment
.utc()
moment()
.subtract(1, "day")
.subtract(1, "month")
.startOf("day")
@@ -23,8 +22,7 @@ export default DiscourseRoute.extend({
params.endDate =
params.end_date ||
moment
.utc()
moment()
.endOf("day")
.format("YYYY-MM-DD");
delete params.end_date;
@@ -56,9 +54,13 @@ export default DiscourseRoute.extend({
onParamsChange(params) {
const queryParams = {
type: params.type,
start_date: params.startDate,
start_date: params.startDate
? params.startDate.toISOString(true).split("T")[0]
: null,
filters: params.filters,
end_date: params.endDate
? params.endDate.toISOString(true).split("T")[0]
: null
};
this.transitionTo("adminReports.show", { queryParams });

View File

@@ -132,26 +132,16 @@
{{#if showDatesOptions}}
<div class="control">
<span class="label">
{{i18n "admin.dashboard.reports.start_date"}}
{{i18n "admin.dashboard.reports.dates"}}
</span>
<div class="input">
{{date-input
date=startDate
onChange=(action "onChangeStartDate")
}}
</div>
</div>
<div class="control">
<span class="label">
{{i18n "admin.dashboard.reports.end_date"}}
</span>
<div class="input">
{{date-input
date=endDate
onChange=(action "onChangeEndDate")
{{date-time-input-range
from=startDate
to=endDate
onChange=(action "onChangeDateRange")
showFromTime=false
showToTime=false
}}
</div>
</div>

View File

@@ -1,4 +1,5 @@
import { schedule } from "@ember/runloop";
import { action } from "@ember/object";
import Component from "@ember/component";
/* global Pikaday:true */
import loadScript from "discourse/lib/load-script";
@@ -25,8 +26,8 @@ export default Component.extend({
this._loadPikadayPicker(container);
}
if (this.date && this._picker) {
this._picker.setDate(this.date, true);
if (this._picker && this.date) {
this._picker.setDate(moment(this.date).toDate(), true);
}
});
},
@@ -34,9 +35,12 @@ export default Component.extend({
didUpdateAttrs() {
this._super(...arguments);
if (this._picker && typeof this.date === "string") {
const [year, month, day] = this.date.split("-").map(x => parseInt(x, 10));
this._picker.setDate(new Date(year, month - 1, day), true);
if (this._picker && this.date) {
this._picker.setDate(moment(this.date).toDate(), true);
}
if (this._picker && this.relativeDate) {
this._picker.setMinDate(moment(this.relativeDate).toDate(), true);
}
if (this._picker && !this.date) {
@@ -46,13 +50,12 @@ export default Component.extend({
_loadPikadayPicker(container) {
loadScript("/javascripts/pikaday.js").then(() => {
const defaultOptions = {
let defaultOptions = {
field: this.element.querySelector(".date-picker"),
container: container || this.element.querySelector(".picker-container"),
bound: container === null,
format: "LL",
firstDay: 1,
trigger: this.element,
i18n: {
previousMonth: I18n.t("dates.previous_month"),
nextMonth: I18n.t("dates.next_month"),
@@ -63,8 +66,16 @@ export default Component.extend({
onSelect: date => this._handleSelection(date)
};
this._picker = new Pikaday(Object.assign(defaultOptions, this._opts()));
this._picker.setDate(this.date, true);
if (this.relativeDate) {
defaultOptions = Object.assign({}, defaultOptions, {
minDate: moment(this.relativeDate).toDate()
});
}
this._picker = new Pikaday(
Object.assign({}, defaultOptions, this._opts())
);
this._picker.setDate(moment(this.date).toDate(), true);
});
},
@@ -79,18 +90,23 @@ export default Component.extend({
/* do nothing for native */
};
picker.setDate = date => {
picker.value = date;
picker.value = moment(date).format("YYYY-MM-DD");
};
picker.setMinDate = date => {
picker.min = date;
};
this._picker = picker;
if (this.date) {
picker.setDate(this.date);
}
},
_handleSelection(value) {
if (!this.element || this.isDestroying || this.isDestroyed) return;
this._picker && this._picker.hide();
if (this.onChange) {
this.onChange(value);
this.onChange(value ? moment(value) : null);
}
},
@@ -98,8 +114,8 @@ export default Component.extend({
_destroy() {
if (this._picker) {
this._picker.destroy();
this._picker = null;
}
this._picker = null;
},
@discourseComputed()
@@ -111,9 +127,8 @@ export default Component.extend({
return null;
},
actions: {
onInput(event) {
this._picker && this._picker.setDate(event.target.value, true);
}
@action
onChangeDate(event) {
this._handleSelection(event.target.value);
}
});

View File

@@ -1,53 +1,46 @@
import { equal } from "@ember/object/computed";
import Component from "@ember/component";
import { action } from "@ember/object";
export default Component.extend({
classNames: ["d-date-time-input-range"],
from: null,
to: null,
onChangeTo: null,
onChangeFrom: null,
currentPanel: "from",
showFromTime: true,
toTimeFirst: false,
showToTime: true,
error: null,
showFromTime: true,
clearable: false,
fromPanelActive: equal("currentPanel", "from"),
toPanelActive: equal("currentPanel", "to"),
@action
onChangeRanges(options, value) {
if (this.onChange) {
const state = {
from: this.from,
to: this.to
};
_valid(state) {
if (state.to && state.from && state.to < state.from) {
return I18n.t("date_time_picker.errors.to_before_from");
}
const diff = {};
return true;
},
actions: {
_onChange(options, value) {
if (this.onChange) {
const state = {
from: this.from,
to: this.to
};
const diff = {};
diff[options.prop] = value;
const newState = Object.assign(state, diff);
const validation = this._valid(newState);
if (validation === true) {
this.set("error", null);
this.onChange(newState);
if (options.prop === "from") {
if (value && value.isAfter(this.to)) {
diff[options.prop] = value;
diff["to"] = value.clone().add(1, "hour");
} else {
this.set("error", validation);
diff[options.prop] = value;
}
}
},
onChangePanel(panel) {
this.set("currentPanel", panel);
if (options.prop === "to") {
if (value && value.isBefore(this.from)) {
diff[options.prop] = this.from.clone().add(1, "hour");
} else {
diff[options.prop] = value;
}
}
const newState = Object.assign({}, state, diff);
this.onChange(newState);
}
}
});

View File

@@ -1,44 +1,63 @@
import Component from "@ember/component";
import { computed } from "@ember/object";
import { computed, action } from "@ember/object";
export default Component.extend({
classNames: ["d-date-time-input"],
date: null,
relativeDate: null,
showTime: true,
clearable: false,
_hours: computed("date", function() {
return this.date && this.showTime ? new Date(this.date).getHours() : null;
hours: computed("date", "showTime", function() {
return this.date && this.get("showTime") ? this.date.hours() : null;
}),
_minutes: computed("date", function() {
return this.date && this.showTime ? new Date(this.date).getMinutes() : null;
minutes: computed("date", "showTime", function() {
return this.date && this.get("showTime") ? this.date.minutes() : null;
}),
actions: {
onClear() {
this.onChange(null);
},
@action
onClear() {
this.onChange(null);
},
onChangeTime(time) {
if (this.onChange) {
const date = new Date(this.date);
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
this.onChange(new Date(year, month, day, time.hours, time.minutes));
}
},
@action
onChangeTime(time) {
if (this.onChange) {
const date = this.date
? this.date
: this.relativeDate
? this.relativeDate
: moment();
onChangeDate(date) {
if (this.onChange) {
const year = date.getFullYear();
const month = date.getMonth();
const day = date.getDate();
this.onChange(
new Date(year, month, day, this._hours || 0, this._minutes || 0)
);
}
this.onChange(
moment({
year: date.year(),
month: date.month(),
day: date.date(),
hours: time.hours,
minutes: time.minutes
})
);
}
},
@action
onChangeDate(date) {
if (!date) {
this.onClear();
return;
}
this.onChange &&
this.onChange(
moment({
year: date.year(),
month: date.month(),
day: date.date(),
hours: this.hours || 0,
minutes: this.minutes || 0
})
);
}
});

View File

@@ -1,76 +1,171 @@
import { oneWay, or } from "@ember/object/computed";
import { schedule } from "@ember/runloop";
import { isPresent } from "@ember/utils";
import { computed, action } from "@ember/object";
import Component from "@ember/component";
import { isNumeric } from "discourse/lib/utilities";
function convertMinutes(num) {
return { hours: Math.floor(num / 60), minutes: num % 60 };
}
function convertMinutesToString(n) {
const hoursAndMinutes = convertMinutes(n);
return `${hoursAndMinutes.hours
.toString()
.padStart(2, "0")}:${hoursAndMinutes.minutes.toString().padStart(2, "0")}`;
}
function convertMinutesToDurationString(n) {
const hoursAndMinutes = convertMinutes(n);
let output = "";
if (hoursAndMinutes.hours) {
output = `${hoursAndMinutes.hours}h`;
if (hoursAndMinutes.minutes > 0) {
output = `${output} ${hoursAndMinutes.minutes} min`;
}
} else {
output = `${hoursAndMinutes.minutes} min`;
}
return output;
}
export default Component.extend({
classNames: ["d-time-input"],
hours: null,
minutes: null,
_hours: oneWay("hours"),
_minutes: oneWay("minutes"),
isSafari: oneWay("capabilities.isSafari"),
isMobile: oneWay("site.mobileView"),
nativePicker: or("isSafari", "isMobile"),
actions: {
onInput(options, event) {
event.preventDefault();
relativeDate: null,
if (this.onChange) {
let value = event.target.value;
didReceiveAttrs() {
this._super(...arguments);
if (!isNumeric(value)) {
value = 0;
} else {
value = parseInt(value, 10);
}
if (isPresent(this.date)) {
this.setProperties({
hours: this.date.hours(),
minutes: this.date.minutes()
});
}
if (options.prop === "hours") {
value = Math.max(0, Math.min(value, 23))
.toString()
.padStart(2, "0");
this._processHoursChange(value);
} else {
value = Math.max(0, Math.min(value, 59))
.toString()
.padStart(2, "0");
this._processMinutesChange(value);
}
schedule("afterRender", () => (event.target.value = value));
}
},
onFocusIn(value, event) {
if (value && event.target) {
event.target.select();
}
},
onChangeTime(event) {
const time = event.target.value;
if (time && this.onChange) {
this.onChange({
hours: time.split(":")[0],
minutes: time.split(":")[1]
});
}
if (
!isPresent(this.date) &&
!isPresent(this.attrs.hours) &&
!isPresent(this.attrs.minutes)
) {
this.setProperties({
hours: null,
minutes: null
});
}
},
_processHoursChange(hours) {
this.onChange({
hours,
minutes: this._minutes || "00"
minimumTime: computed("relativeDate", "date", function() {
if (this.relativeDate) {
if (this.date) {
if (this.date.diff(this.relativeDate, "minutes") > 1440) {
return 0;
} else {
return this.relativeDate.hours() * 60 + this.relativeDate.minutes();
}
} else {
return this.relativeDate.hours() * 60 + this.relativeDate.minutes();
}
}
}),
timeOptions: computed("minimumTime", "hours", "minutes", function() {
let options = [];
const start = this.minimumTime
? this.minimumTime > this.time
? this.time
: this.minimumTime
: 0;
// theres 1440 minutes in a day
// and 1440 / 15 = 96
let i = 0;
while (i < 96) {
// while diff with minimumTime is less than one hour
// use 15 minutes steps and then 30 minutes
const minutes = this.minimumTime ? (i <= 4 ? 15 : 30) : 15;
const option = start + i * minutes;
// when start is higher than 0 we will reach 1440 minutes
// before the 96 iterations
if (option > 1440) {
break;
}
options.push(option);
i++;
}
if (this.time && !options.includes(this.time)) {
options = [this.time].concat(options);
}
options = options.sort((a, b) => a - b);
return options.map(option => {
let name = convertMinutesToString(option);
let label;
if (this.minimumTime) {
const diff = option - this.minimumTime;
label = `${name} <small>(${convertMinutesToDurationString(
diff
)})</small>`.htmlSafe();
}
return {
id: option,
name,
label,
title: name
};
});
}),
time: computed("minimumTime", "hours", "minutes", function() {
if (isPresent(this.hours) && isPresent(this.minutes)) {
return parseInt(this.hours, 10) * 60 + parseInt(this.minutes, 10);
}
}),
@action
onFocusIn(value, event) {
if (value && event.target) {
event.target.select();
}
},
_processMinutesChange(minutes) {
this.onChange({
hours: this._hours || "00",
minutes
});
@action
onChangeTime(time) {
if (isPresent(time) && this.onChange) {
if (typeof time === "string" && time.length) {
let [hours, minutes] = time.split(":");
if (hours && minutes) {
if (hours < 0) hours = 0;
if (hours > 23) hours = 23;
if (minutes < 0) minutes = 0;
if (minutes > 59) minutes = 59;
this.onChange({
hours: parseInt(hours, 10),
minutes: parseInt(minutes, 10)
});
}
} else {
this.onChange({
hours: convertMinutes(time).hours,
minutes: convertMinutes(time).minutes
});
}
}
}
});

View File

@@ -1,5 +1,6 @@
import discourseComputed from "discourse-common/utils/decorators";
import Controller from "@ember/controller";
import { isPresent } from "@ember/utils";
export default Controller.extend({
queryParams: [
@@ -86,12 +87,7 @@ export default Controller.extend({
},
setRange(range) {
if (range.from) {
this.set("from", new Date(range.from).toISOString().split("T")[0]);
}
if (range.to) {
this.set("to", new Date(range.to).toISOString().split("T")[0]);
}
this.setProperties(range);
},
actions: {
@@ -118,8 +114,12 @@ export default Controller.extend({
status: this.filterStatus,
category_id: this.filterCategoryId,
username: this.filterUsername,
from_date: this.filterFromDate,
to_date: this.filterToDate,
from_date: isPresent(this.filterFromDate)
? this.filterFromDate.toISOString(true).split("T")[0]
: null,
to_date: isPresent(this.filterToDate)
? this.filterToDate.toISOString(true).split("T")[0]
: null,
sort_order: this.filterSortOrder,
additional_filters: JSON.stringify(this.additionalFilters)
});

View File

@@ -1,4 +1,5 @@
import DiscourseRoute from "discourse/routes/discourse";
import { isPresent } from "@ember/utils";
export default DiscourseRoute.extend({
model(params) {
@@ -23,8 +24,8 @@ export default DiscourseRoute.extend({
filterPriority: meta.priority,
reviewableTypes: meta.reviewable_types,
filterUsername: meta.username,
filterFromDate: meta.from_date,
filterToDate: meta.to_date,
filterFromDate: isPresent(meta.from_date) ? moment(meta.from_date) : null,
filterToDate: isPresent(meta.to_date) ? moment(meta.to_date) : null,
filterSortOrder: meta.sort_order,
additionalFilters: meta.additional_filters || {}
});

View File

@@ -2,9 +2,8 @@
type=inputType
class="date-picker"
placeholder=placeholder
value=value
input=(action "onInput")
readonly=true
value=(readonly value)
input=(action "onChangeDate")
}}
<div class="picker-container"></div>

View File

@@ -1,35 +1,16 @@
<ul class="panels {{currentPanel}}">
<li>
{{d-button
label="date_time_picker.from"
class="from-panel"
action=(action "onChangePanel" "from")}}
</li>
<li>
{{d-button
label="date_time_picker.to"
class="to-panel"
action=(action "onChangePanel" "to")}}
</li>
</ul>
{{date-time-input
date=from
onChange=(action "onChangeRanges" (hash prop="from"))
showTime=showFromTime
class="from"
}}
{{#if error}}
<div class="alert error">{{error}}</div>
{{/if}}
<div class="panel from {{if fromPanelActive "visible"}}">
{{date-time-input
date=from
onChange=(action "_onChange" (hash prop="from"))
showTime=showFromTime
}}
</div>
<div class="panel to {{if toPanelActive "visible"}}">
{{date-time-input
date=to
onChange=(action "_onChange" (hash prop="to"))
showTime=showToTime
clearable=true
}}
</div>
{{date-time-input
date=to
relativeDate=from
onChange=(action "onChangeRanges" (hash prop="to"))
timeFirst=toTimeFirst
showTime=showToTime
clearable=clearable
class="to"
}}

View File

@@ -1,13 +1,31 @@
{{date-input date=date onChange=(action "onChangeDate")}}
{{#unless timeFirst}}
{{date-input
date=date
relativeDate=relativeDate
onChange=(action "onChangeDate")
}}
{{/unless}}
{{#if showTime}}
{{time-input
hours=_hours
minutes=_minutes
date=date
relativeDate=relativeDate
onChange=(action "onChangeTime")
}}
{{#if clearable}}
{{d-button icon="times" action=(action "onClear")}}
{{/if}}
{{/if}}
{{#if timeFirst}}
{{date-input
date=date
relativeDate=relativeDate
onChange=(action "onChangeDate")
}}
{{/if}}
{{#if clearable}}
{{d-button
class="clear-date-time"
icon="times"
action=(action "onClear")
}}
{{/if}}

View File

@@ -1,40 +1,12 @@
<div class="fields">
{{#if nativePicker}}
{{input
class="field time"
type="time"
value=(concat _hours ":" _minutes)
change=(action "onChangeTime")
}}
{{else}}
{{input
class="field hours"
type="number"
title="Hours"
minlength=2
maxlength=2
max="23"
min="0"
placeholder="00"
value=_hours
input=(action "onInput" (hash prop="hours"))
focus-in=(action "onFocusIn")
}}
<div class="separator">:</div>
{{input
class="field minutes"
title="Minutes"
type="number"
minlength=2
maxlength=2
max="59"
min="0"
placeholder="00"
value=_minutes
input=(action "onInput" (hash prop="minutes"))
focus-in=(action "onFocusIn")
}}
{{/if}}
</div>
{{combo-box
value=time
content=timeOptions
onChange=(action "onChangeTime")
options=(hash
translatedNone="--:--"
allowAny=true
filterable=false
autoInsertNoneItem=false
translatedFilterPlaceholder="--:--"
)
}}

View File

@@ -77,7 +77,13 @@
{{/if}}
<div class="reviewable-filter date-range">
{{date-time-input-range showFromTime=false showToTime=false from=filterFromDate to=filterToDate onChange=setRange}}
{{date-time-input-range
from=filterFromDate
to=filterToDate
onChange=setRange
showFromTime=false
showToTime=false
}}
</div>
<div class="reviewable-filter sort-order">

View File

@@ -482,10 +482,7 @@ export default Component.extend(
this.selectKit.options.allowAny &&
!this.selectKit.isExpanded
) {
return this.defaultItem(
null,
I18n.t("select_kit.filter_placeholder_with_any")
);
return null;
}
let item;
@@ -754,8 +751,6 @@ export default Component.extend(
},
_onCloseWrapper(event) {
this._focusFilter(this.multiSelect);
this.set("selectKit.highlighted", null);
let boundaryAction = this._boundaryActionHandler("onClose");