Skip to content

Commit af79a51

Browse files
author
Ruslan Farkhutdinov
committed
DateView: Improve types
1 parent 16f18b6 commit af79a51

File tree

1 file changed

+112
-74
lines changed

1 file changed

+112
-74
lines changed

packages/devextreme/js/__internal/ui/date_box/m_date_view.ts

Lines changed: 112 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import type { Device } from '@js/common/core/environment';
12
import dateLocalization from '@js/common/core/localization/date';
23
import registerComponent from '@js/core/component_registrator';
4+
import type { DefaultOptionsRule } from '@js/core/options/utils';
35
import type { dxElementWrapper } from '@js/core/renderer';
46
import $ from '@js/core/renderer';
57
import dateUtils from '@js/core/utils/date';
6-
import { each } from '@js/core/utils/iterator';
78
import type { OptionChanged } from '@ts/core/widget/types';
89
import Editor from '@ts/ui/editor/editor';
910

1011
import type { EditorProperties } from '../editor/editor';
1112
import uiDateUtils from './m_date_utils';
12-
import type { DateViewRollerProperties } from './m_date_view_roller';
1313
import DateViewRoller from './m_date_view_roller';
1414

1515
const DATEVIEW_CLASS = 'dx-dateview';
@@ -31,6 +31,15 @@ const ROLLER_TYPE = {
3131
hours: 'hours',
3232
};
3333

34+
export interface RollerConfig {
35+
type: string;
36+
setValue: string;
37+
valueItems: number[];
38+
displayItems: string[];
39+
selectedIndex?: number;
40+
getIndex: (value: Date) => number;
41+
}
42+
3443
export interface DateViewProperties extends EditorProperties {
3544
applyCompactClass?: boolean;
3645

@@ -46,15 +55,15 @@ class DateView extends Editor<DateViewProperties> {
4655

4756
_$wrapper?: dxElementWrapper;
4857

49-
_rollerConfigs!: DateViewRollerProperties;
58+
_rollerConfigs!: Record<string, RollerConfig>;
5059

5160
_rollers!: Record<string, DateViewRoller>;
5261

5362
_valueOption(): Date {
5463
const { value } = this.option();
5564
const date = new Date(value);
56-
// @ts-expect-error ts-error
57-
return !value || isNaN(date) ? this._getDefaultDate() : date;
65+
66+
return !value || isNaN(date.getTime()) ? this._getDefaultDate() : date;
5867
}
5968

6069
_getDefaultDate(): Date {
@@ -80,10 +89,10 @@ class DateView extends Editor<DateViewProperties> {
8089
};
8190
}
8291

83-
_defaultOptionsRules() {
92+
_defaultOptionsRules(): DefaultOptionsRule<DateViewProperties>[] {
8493
return super._defaultOptionsRules().concat([
8594
{
86-
device(device) {
95+
device(device: Device): boolean {
8796
return device.deviceType !== 'desktop';
8897
},
8998
options: {
@@ -99,14 +108,16 @@ class DateView extends Editor<DateViewProperties> {
99108

100109
const { type } = this.option();
101110

102-
this._toggleFormatClasses(type);
111+
this._toggleFormatClasses(type as string);
103112
this._toggleCompactClass();
104113
}
105114

106-
_toggleFormatClasses(currentFormat, previousFormat?): void {
115+
_toggleFormatClasses(currentFormat: string, previousFormat?: string): void {
107116
this.$element().addClass(`${DATEVIEW_CLASS}-${currentFormat}`);
108117

109-
previousFormat && this.$element().removeClass(`${DATEVIEW_CLASS}-${previousFormat}`);
118+
if (previousFormat) {
119+
this.$element().removeClass(`${DATEVIEW_CLASS}-${previousFormat}`);
120+
}
110121
}
111122

112123
_toggleCompactClass(): void {
@@ -135,56 +146,72 @@ class DateView extends Editor<DateViewProperties> {
135146

136147
this._rollers = {};
137148

138-
const that = this;
149+
Object.keys(this._rollerConfigs).forEach((name: string) => {
150+
const rollerType = this._rollerConfigs[name].type;
139151

140-
each(that._rollerConfigs, (name) => {
141-
// @ts-expect-error ts-error
142-
const $roller = $('<div>').appendTo(that._$rollersContainer)
143-
.addClass(`${DATEVIEW_ROLLER_CLASS}-${that._rollerConfigs[name].type}`);
152+
const $roller = $('<div>').appendTo(this._$rollersContainer as dxElementWrapper)
153+
.addClass(`${DATEVIEW_ROLLER_CLASS}-${rollerType}`);
144154

145-
that._rollers[that._rollerConfigs[name].type] = that._createComponent($roller, DateViewRoller, {
146-
items: that._rollerConfigs[name].displayItems,
147-
selectedIndex: that._rollerConfigs[name].selectedIndex,
155+
this._rollers[rollerType] = this._createComponent($roller, DateViewRoller, {
156+
items: this._rollerConfigs[name].displayItems,
157+
selectedIndex: this._rollerConfigs[name].selectedIndex,
148158
showScrollbar: 'never',
149159
scrollByContent: true,
150-
onStart(e) {
151-
const roller = e.component;
152-
roller._toggleActive(true);
153-
that._setActiveRoller(that._rollerConfigs[name]);
160+
// TODO Add event type once m_date_view_roller types is refactored
161+
onStart: (e) => {
162+
const { component } = e;
163+
const rollerConfig = this._rollerConfigs[name];
164+
165+
component._toggleActive(true);
166+
this._setActiveRoller(rollerConfig);
154167
},
155-
onEnd(e) {
156-
const roller = e.component;
157-
roller._toggleActive(false);
168+
// TODO Add event type once m_date_view_roller types is refactored
169+
onEnd: (e) => {
170+
e.component._toggleActive(false);
158171
},
159-
onClick(e) {
160-
const roller = e.component;
161-
roller._toggleActive(true);
162-
that._setActiveRoller(that._rollerConfigs[name]);
163-
that._setRollerState(that._rollerConfigs[name], roller.option('selectedIndex'));
164-
roller._toggleActive(false);
172+
// TODO Add event type once m_date_view_roller types is refactored
173+
onClick: (e) => {
174+
const { component } = e;
175+
const { selectedIndex } = component.option();
176+
const rollerConfig = this._rollerConfigs[name];
177+
178+
component._toggleActive(true);
179+
this._setActiveRoller(rollerConfig);
180+
this._setRollerState(rollerConfig, selectedIndex);
181+
component._toggleActive(false);
165182
},
166-
onSelectedIndexChanged(e) {
167-
const roller = e.component;
168-
that._setRollerState(that._rollerConfigs[name], roller.option('selectedIndex'));
183+
// TODO Add event type once m_date_view_roller types is refactored
184+
onSelectedIndexChanged: (e) => {
185+
const { component } = e;
186+
const { selectedIndex } = component.option();
187+
const rollerConfig = this._rollerConfigs[name];
188+
189+
this._setRollerState(rollerConfig, selectedIndex);
169190
},
170191
});
171192
});
172-
// @ts-expect-error ts-error
173-
that._$rollersContainer.appendTo(that._wrapper());
193+
194+
const $wrapper = this._wrapper();
195+
if ($wrapper) {
196+
this._$rollersContainer.appendTo($wrapper);
197+
}
174198
}
175199

176-
_createRollerConfigs(type?): void {
177-
const that = this;
178-
type = type || that.option('type');
179-
that._rollerConfigs = {};
180-
// @ts-expect-error ts-error
181-
dateLocalization.getFormatParts(uiDateUtils.FORMATS_MAP[type]).forEach((partName) => {
182-
that._createRollerConfig(partName);
183-
});
200+
_createRollerConfigs(type?: string): void {
201+
const { type: defaultType } = this.option();
202+
const selectedType = type ?? defaultType;
203+
this._rollerConfigs = {} as Record<string, RollerConfig>;
204+
205+
dateLocalization
206+
// @ts-expect-error core/DateLocalization type should be fixed
207+
.getFormatParts(uiDateUtils.FORMATS_MAP[selectedType as string])
208+
.forEach((partName: string) => {
209+
this._createRollerConfig(partName);
210+
});
184211
}
185212

186-
_createRollerConfig(componentName): void {
187-
// @ts-expect-error ts-error
213+
_createRollerConfig(componentName: string): void {
214+
// @ts-expect-error TODO remove once m_date_utils is refactored
188215
const componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName];
189216

190217
const valueRange = this._calculateRollerConfigValueRange(componentName);
@@ -195,57 +222,60 @@ class DateView extends Editor<DateViewProperties> {
195222

196223
const curDate = this._getCurrentDate();
197224

198-
const config = {
225+
const config: RollerConfig = {
199226
type: componentName,
200227
setValue: componentInfo.setter,
201228
valueItems: [],
202229
displayItems: [],
203-
getIndex(value): number {
230+
getIndex(value: Date): number {
204231
return value[componentInfo.getter]() - startValue;
205232
},
206233
};
207234

208-
for (let i = startValue; i <= endValue; i++) {
209-
// @ts-expect-error ts-error
235+
for (let i = startValue; i <= endValue; i += 1) {
210236
config.valueItems.push(i);
211-
// @ts-expect-error ts-error
212237
config.displayItems.push(formatter(i, curDate));
213238
}
214-
// @ts-expect-error ts-error
215239
config.selectedIndex = config.getIndex(curDate);
216240

217241
this._rollerConfigs[componentName] = config;
218242
}
219243

220-
_setActiveRoller(currentRoller): void {
244+
_setActiveRoller(currentRoller: RollerConfig): void {
221245
const activeRoller = currentRoller && this._rollers[currentRoller.type];
222246

223-
each(this._rollers, function () {
224-
this.toggleActiveState(this === activeRoller);
247+
Object.values(this._rollers).forEach((roller) => {
248+
roller.toggleActiveState(roller === activeRoller);
225249
});
226250
}
227251

228252
_updateRollersPosition(): void {
229-
const that = this;
230-
each(this._rollers, function (type) {
231-
const correctIndex = that._rollerConfigs[type].getIndex(that._getCurrentDate());
232-
this.option('selectedIndex', correctIndex);
253+
const currentDate = this._getCurrentDate();
254+
255+
Object.keys(this._rollers).forEach((type: string) => {
256+
const correctIndex = this._rollerConfigs[type].getIndex(currentDate);
257+
this._rollers[type].option('selectedIndex', correctIndex);
233258
});
234259
}
235260

236-
_setRollerState(roller, selectedIndex): void {
261+
_setRollerState(roller: RollerConfig, selectedIndex: number): void {
237262
if (selectedIndex !== roller.selectedIndex) {
238263
const rollerValue = roller.valueItems[selectedIndex];
239264
const { setValue } = roller;
240265
let currentValue = new Date(this._getCurrentDate());
241266
let currentDate = currentValue.getDate();
242-
const minDate = this.option('minDate');
243-
const maxDate = this.option('maxDate');
267+
const { minDate, maxDate } = this.option();
244268

245269
if (roller.type === ROLLER_TYPE.month) {
246-
currentDate = Math.min(currentDate, uiDateUtils.getMaxMonthDay(currentValue.getFullYear(), rollerValue));
270+
currentDate = Math.min(
271+
currentDate,
272+
uiDateUtils.getMaxMonthDay(currentValue.getFullYear(), rollerValue),
273+
);
247274
} else if (roller.type === ROLLER_TYPE.year) {
248-
currentDate = Math.min(currentDate, uiDateUtils.getMaxMonthDay(rollerValue, currentValue.getMonth()));
275+
currentDate = Math.min(
276+
currentDate,
277+
uiDateUtils.getMaxMonthDay(rollerValue, currentValue.getMonth()),
278+
);
249279
}
250280

251281
currentValue.setDate(currentDate);
@@ -270,14 +300,18 @@ class DateView extends Editor<DateViewProperties> {
270300
}
271301
}
272302

273-
_refreshRoller(rollerType): void {
303+
_refreshRoller(rollerType: string): void {
274304
const roller = this._rollers[rollerType];
275305

276306
if (roller) {
307+
// @ts-expect-error TODO Remove once m_date_view_roller is reworked
308+
const { items } = roller.option();
309+
277310
this._createRollerConfig(rollerType);
278311
const rollerConfig = this._rollerConfigs[rollerType];
279-
// eslint-disable-next-line @typescript-eslint/no-base-to-string
280-
if (rollerType === ROLLER_TYPE.day || rollerConfig.displayItems.toString() !== roller.option('items').toString()) {
312+
313+
if (rollerType === ROLLER_TYPE.day
314+
|| rollerConfig.displayItems.toString() !== items.toString()) {
281315
roller.option({
282316
items: rollerConfig.displayItems,
283317
selectedIndex: rollerConfig.selectedIndex,
@@ -286,15 +320,16 @@ class DateView extends Editor<DateViewProperties> {
286320
}
287321
}
288322

289-
_getCurrentDate() {
323+
_getCurrentDate(): Date {
290324
const curDate = this._valueOption();
291-
const minDate = this.option('minDate');
292-
const maxDate = this.option('maxDate');
325+
const { minDate, maxDate } = this.option();
293326

294-
return dateUtils.normalizeDate(curDate, minDate, maxDate);
327+
return dateUtils.normalizeDate(curDate, minDate, maxDate) as Date;
295328
}
296329

297-
_calculateRollerConfigValueRange(componentName) {
330+
_calculateRollerConfigValueRange(
331+
componentName: string,
332+
): { startValue: number; endValue: number } {
298333
const curDate = this._getCurrentDate();
299334
const { minDate, maxDate } = this.option();
300335

@@ -304,7 +339,7 @@ class DateView extends Editor<DateViewProperties> {
304339
const maxMonth = maxYear && curDate.getMonth() === maxDate.getMonth();
305340
const minHour = minMonth && curDate.getDate() === minDate.getDate();
306341
const maxHour = maxMonth && curDate.getDate() === maxDate.getDate();
307-
// @ts-expect-error ts-error
342+
// @ts-expect-error TODO remove once m_date_utils is refactored
308343
const componentInfo = uiDateUtils.DATE_COMPONENTS_INFO[componentName];
309344
let { startValue } = componentInfo;
310345
let { endValue } = componentInfo;
@@ -356,7 +391,10 @@ class DateView extends Editor<DateViewProperties> {
356391
case 'maxDate':
357392
case 'type':
358393
this._renderRollers();
359-
this._toggleFormatClasses(args.value, args.previousValue);
394+
395+
if (args.value) {
396+
this._toggleFormatClasses(args.value as string, args.previousValue as string);
397+
}
360398
break;
361399
case 'visible':
362400
super._optionChanged(args);

0 commit comments

Comments
 (0)