Skip to content

Commit ea5ee73

Browse files
authored
Merge branch 'master' into mpopov/card-spacing
2 parents aa4c981 + 48f1fed commit ea5ee73

37 files changed

+1209
-844
lines changed

.github/workflows/stale.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Mark stale issues and pull requests
2+
3+
on:
4+
schedule:
5+
- cron: "0 0 * * *"
6+
7+
jobs:
8+
stale:
9+
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- uses: actions/stale@v1
14+
with:
15+
repo-token: ${{ secrets.GITHUB_TOKEN }}
16+
stale-issue-message: 'There has been no recent activity and this issue has been marked inactive.'
17+
stale-pr-message: 'There has been no recent activity and this PR has been marked inactive.'
18+
stale-issue-label: 'status: inactive'
19+
stale-pr-label: 'status: inactive'

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ All notable changes for each version of this project will be documented in this
162162
- Added `tabIndex` input so it can support change detection as well.
163163

164164

165+
- `IgxHighlightDirective`
166+
- New `metadata` property was introduced, which allows adding additional, custom logic to the activation condition of a highlighted element.
167+
165168
### RTL Support
166169
- `igxSlider` have full right-to-left (RTL) support.
167170

projects/igniteui-angular/src/lib/core/utils.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,3 +355,31 @@ export function resizeObservable(target: HTMLElement): Observable<ResizeObserver
355355
return unsubscribe;
356356
});
357357
}
358+
359+
/**
360+
* @hidden
361+
* @internal
362+
*
363+
* Compares two maps.
364+
*/
365+
export function compareMaps(map1: Map<any, any>, map2: Map<any, any>): boolean {
366+
if (!map2) {
367+
return !map1 ? true : false;
368+
}
369+
if (map1.size !== map2.size) {
370+
return false;
371+
}
372+
let match = true;
373+
const keys = Array.from(map2.keys());
374+
for (const key of keys) {
375+
if (map1.has(key)) {
376+
match = map1.get(key) === map2.get(key);
377+
} else {
378+
match = false;
379+
}
380+
if (!match) {
381+
break;
382+
}
383+
}
384+
return match;
385+
}

projects/igniteui-angular/src/lib/date-picker/date-picker.utils.ts

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,13 @@ export const enum DateState {
1111
Invalid = 'invalid',
1212
}
1313

14-
/**
15-
* @hidden
16-
*/
14+
/** @hidden */
1715
const enum FormatDesc {
1816
Numeric = 'numeric',
1917
TwoDigits = '2-digit'
2018
}
2119

22-
/**
23-
* @hidden
24-
*/
20+
/** @hidden */
2521
const enum DateChars {
2622
YearChar = 'y',
2723
MonthChar = 'M',
@@ -31,25 +27,32 @@ const enum DateChars {
3127
const DATE_CHARS = ['h', 'H', 'm', 's', 'S', 't', 'T'];
3228
const TIME_CHARS = ['d', 'D', 'M', 'y', 'Y'];
3329

34-
/**
35-
* @hidden
36-
*/
30+
/** @hidden */
3731
const enum DateParts {
3832
Day = 'day',
3933
Month = 'month',
4034
Year = 'year'
4135
}
4236

43-
/**
44-
* @hidden
45-
*/
37+
38+
/** @hidden */
4639
export abstract class DatePickerUtil {
40+
public static readonly DEFAULT_INPUT_FORMAT = 'MM/dd/yyyy';
41+
// TODO: this is the def mask for the date-picker, should remove it during refactoring
4742
private static readonly SHORT_DATE_MASK = 'MM/dd/yy';
4843
private static readonly SEPARATOR = 'literal';
4944
private static readonly NUMBER_OF_MONTHS = 12;
5045
private static readonly PROMPT_CHAR = '_';
5146
private static readonly DEFAULT_LOCALE = 'en';
5247

48+
49+
50+
/**
51+
* TODO: Unit tests for all public methods.
52+
*/
53+
54+
55+
5356
/**
5457
* Parse a Date value from masked string input based on determined date parts
5558
* @param inputData masked value to parse
@@ -92,20 +95,6 @@ export abstract class DatePickerUtil {
9295
);
9396
}
9497

95-
private static ensureLeadingZero(part: DatePartInfo) {
96-
switch (part.type) {
97-
case DatePart.Date:
98-
case DatePart.Month:
99-
case DatePart.Hours:
100-
case DatePart.Minutes:
101-
case DatePart.Seconds:
102-
if (part.format.length === 1) {
103-
part.format = part.format.repeat(2);
104-
}
105-
break;
106-
}
107-
}
108-
10998
/**
11099
* Parse the mask into date/time and literal parts
111100
*/
@@ -256,6 +245,72 @@ export abstract class DatePickerUtil {
256245
return newDate;
257246
}
258247

248+
/**
249+
* Determines whether the provided value is less than the provided min value.
250+
* @param includeTime set to false if you want to exclude time portion of the two dates
251+
* @param includeDate set to false if you want to exclude the date portion of the two dates
252+
*/
253+
public static greaterThanMaxValue(value: Date, maxValue: Date, includeTime = true, includeDate = true): boolean {
254+
if (includeTime && includeDate) {
255+
return value.getTime() > maxValue.getTime();
256+
}
257+
258+
let _value = new Date(value.getTime());
259+
let _maxValue = new Date(maxValue.getTime());
260+
if (includeDate) {
261+
_value.setHours(0, 0, 0, 0);
262+
_maxValue.setHours(0, 0, 0, 0);
263+
return _value.getTime() > maxValue.getTime();
264+
}
265+
if (includeTime) {
266+
_value = new Date(0, 0, 0, _value.getHours(), _value.getMinutes(), _value.getSeconds());
267+
_maxValue = new Date(0, 0, 0, _maxValue.getHours(), _maxValue.getMinutes(), _maxValue.getSeconds());
268+
return _value.getTime() > _maxValue.getTime();
269+
}
270+
271+
// throw?
272+
}
273+
274+
/**
275+
* Determines whether the provided value is greater than the provided min value.
276+
* @param includeTime set to false if you want to exclude time portion of the two dates
277+
* @param includeDate set to false if you want to exclude the date portion of the two dates
278+
*/
279+
public static lessThanMinValue(value: Date, minValue: Date, includeTime = true, includeDate = true): boolean {
280+
if (includeTime && includeDate) {
281+
return value.getTime() < minValue.getTime();
282+
}
283+
284+
let _value = new Date(value.getTime());
285+
let _minValue = new Date(minValue.getTime());
286+
if (includeDate) {
287+
_value.setHours(0, 0, 0, 0);
288+
_minValue.setHours(0, 0, 0, 0);
289+
return _value.getTime() < _minValue.getTime();
290+
}
291+
if (includeTime) {
292+
_value = new Date(0, 0, 0, _value.getHours(), _value.getMinutes(), _value.getSeconds());
293+
_minValue = new Date(0, 0, 0, _minValue.getHours(), _minValue.getMinutes(), _minValue.getSeconds());
294+
return _value.getTime() > _minValue.getTime();
295+
}
296+
297+
// throw?
298+
}
299+
300+
private static ensureLeadingZero(part: DatePartInfo) {
301+
switch (part.type) {
302+
case DatePart.Date:
303+
case DatePart.Month:
304+
case DatePart.Hours:
305+
case DatePart.Minutes:
306+
case DatePart.Seconds:
307+
if (part.format.length === 1) {
308+
part.format = part.format.repeat(2);
309+
}
310+
break;
311+
}
312+
}
313+
259314
private static getCleanVal(inputData: string, datePart: DatePartInfo, promptChar?: string): string {
260315
return DatePickerUtil.trimEmptyPlaceholders(inputData.substring(datePart.start, datePart.end), promptChar);
261316
}

projects/igniteui-angular/src/lib/date-range-picker/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,15 @@ With projected inputs:
108108
### Inputs
109109
| Name | Type | Description |
110110
|:-----------------|:-------------------|:------------|
111-
| mode | InteractionMode | Sets whether `IgxDateRangePickerComponent` is in dialog or dropdown mode. Default is `dialog` |
112-
| monthsViewNumber | number | Sets the number displayed month views. Default is `2`. |
111+
| doneButtonText | string | Changes the default text of the `done` button. It will show up only in `dialog` mode. Default value is `Done`. |
112+
| formatter | function => string | Applies a custom formatter function on the selected or passed date. |
113113
| hideOutsideDays | boolean | Sets whether dates that are not part of the current month will be displayed. Default value is `false`. |
114-
| weekStart | number | Sets the start day of the week. Can be assigned to a numeric value or to `WEEKDAYS` enum value. |
115114
| locale | string | Gets the `locale` of the calendar. Default value is `"en"`. |
116-
| formatter | function => string | Applies a custom formatter function on the selected or passed date. |
117-
| doneButtonText | string | Changes the default text of the `done` button. It will show up only in `dialog` mode. Default value is `Done`. |
118115
| overlaySettings | OverlaySettings | Changes the default overlay settings used by the `IgxDateRangePickerComponent`. |
116+
| mode | InteractionMode | Sets whether `IgxDateRangePickerComponent` is in dialog or dropdown mode. Default is `dialog` |
117+
| monthsViewNumber | number | Sets the number displayed month views. Default is `2`. |
118+
| placeholder | string | Sets the `placeholder` for single-input `IgxDateRangePickerComponent`. |
119+
| weekStart | number | Sets the start day of the week. Can be assigned to a numeric value or to `WEEKDAYS` enum value. |
119120

120121
### Outputs
121122
| Name | Type | Description |

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.spec.ts

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,6 @@ describe('IgxDateRangePicker', () => {
4545
expect(dateRange.value.end).toEqual(startDate);
4646
});
4747

48-
it('should set range dates correctly through selectToday method', () => {
49-
const dateRange = new IgxDateRangePickerComponent(elementRef, null, null, null);
50-
dateRange.calendar = calendar;
51-
const today = new Date();
52-
53-
dateRange.selectRange(new Date());
54-
expect(dateRange.value.start).toEqual(today);
55-
expect(dateRange.value.end).toEqual(today);
56-
});
57-
5848
it('should emit rangeSelected on selection', () => {
5949
const dateRange = new IgxDateRangePickerComponent(elementRef, null, null, null);
6050
dateRange.calendar = calendar;
@@ -78,19 +68,6 @@ describe('IgxDateRangePicker', () => {
7868
expect(dateRange.rangeSelected.emit).toHaveBeenCalledWith({ start: startDate, end: startDate });
7969
});
8070

81-
it('should emit rangeSelected on selectToday()', () => {
82-
const dateRange = new IgxDateRangePickerComponent(elementRef, null, null, null);
83-
dateRange.calendar = calendar;
84-
spyOn(dateRange.rangeSelected, 'emit');
85-
const today = new Date();
86-
87-
dateRange.selectRange(new Date());
88-
expect(dateRange.value.start).toEqual(today);
89-
expect(dateRange.value.end).toEqual(today);
90-
expect(dateRange.rangeSelected.emit).toHaveBeenCalledTimes(1);
91-
expect(dateRange.rangeSelected.emit).toHaveBeenCalledWith({ start: today, end: today });
92-
});
93-
9471
it('should correctly implement interface methods - ControlValueAccessor ', () => {
9572
const mockNgControl = jasmine.createSpyObj('NgControl', ['registerOnChangeCb', 'registerOnTouchedCb']);
9673
const range = { start: new Date(2020, 1, 18), end: new Date(2020, 1, 28) };
@@ -262,6 +239,15 @@ describe('IgxDateRangePicker', () => {
262239
});
263240

264241
describe('Properties & events tests', () => {
242+
it('should show date picker with placeholder', () => {
243+
fixture.detectChanges();
244+
expect(singleInputElement.nativeElement.placeholder).toEqual('MM/dd/yyyy - MM/dd/yyyy');
245+
246+
const placeholder = 'Some placeholder';
247+
fixture.componentInstance.dateRange.placeholder = placeholder;
248+
fixture.detectChanges();
249+
expect(singleInputElement.nativeElement.placeholder).toEqual(placeholder);
250+
});
265251
it('should close the calendar with the "Done" button', fakeAsync(() => {
266252
fixture.componentInstance.mode = InteractionMode.Dialog;
267253
fixture.detectChanges();
@@ -809,4 +795,7 @@ export class DateRangeDefaultCustomLabelComponent extends DateRangeTestComponent
809795
</igx-date-range-picker>
810796
`
811797
})
812-
export class DateRangeDefaultComponent extends DateRangeTestComponent { }
798+
export class DateRangeDefaultComponent extends DateRangeTestComponent {
799+
@ViewChild(IgxDateRangePickerComponent)
800+
public dateRange: IgxDateRangePickerComponent;
801+
}

projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,6 @@ import { CurrentResourceStrings } from '../core/i18n/resources';
4949
import { DisplayDensityBase, DisplayDensityToken, IDisplayDensityOptions } from '../core/density';
5050
import { DatePickerUtil } from '../date-picker/date-picker.utils';
5151
import { DateRangeType } from '../core/dates';
52-
import { TreeGridFilteringStrategy } from '../grids/tree-grid/tree-grid.filtering.pipe';
53-
54-
const DEFAULT_INPUT_FORMAT = 'MM/dd/yyyy';
5552

5653
/**
5754
* Provides the ability to select a range of dates from a calendar UI or editable inputs.
@@ -270,6 +267,16 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
270267
@Input()
271268
public disabled: boolean;
272269

270+
/**
271+
* Sets the `placeholder` for single-input `IgxDateRangePickerComponent`.
272+
* @example
273+
* ```html
274+
* <igx-date-range-picker [placeholder]="'Choose your dates'"></igx-date-range-picker>
275+
* ```
276+
*/
277+
@Input()
278+
public placeholder = '';
279+
273280
/**
274281
* Emitted when a range is selected.
275282
*
@@ -369,12 +376,15 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
369376
return this.formatter(this.value);
370377
}
371378
if (!this.hasProjectedInputs) {
379+
if (this.placeholder !== '') {
380+
return this.placeholder;
381+
}
372382
// TODO: use displayFormat - see how shortDate, longDate can be defined
373383
return this.inputFormat
374384
? `${this.inputFormat} - ${this.inputFormat}`
375-
: `${DEFAULT_INPUT_FORMAT} - ${DEFAULT_INPUT_FORMAT}`;
385+
: `${DatePickerUtil.DEFAULT_INPUT_FORMAT} - ${DatePickerUtil.DEFAULT_INPUT_FORMAT}`;
376386
} else {
377-
return this.inputFormat || DEFAULT_INPUT_FORMAT;
387+
return this.inputFormat || DatePickerUtil.DEFAULT_INPUT_FORMAT;
378388
}
379389
}
380390

@@ -619,7 +629,7 @@ export class IgxDateRangePickerComponent extends DisplayDensityBase
619629
/** @hidden @internal */
620630
public ngOnChanges(changes: SimpleChanges): void {
621631
if (changes['locale']) {
622-
this.inputFormat = DatePickerUtil.getDefaultInputFormat(this.locale || 'en') || DEFAULT_INPUT_FORMAT;
632+
this.inputFormat = DatePickerUtil.getDefaultInputFormat(this.locale || 'en') || DatePickerUtil.DEFAULT_INPUT_FORMAT;
623633
}
624634
}
625635

0 commit comments

Comments
 (0)