Skip to content

Commit 9a6d9c1

Browse files
authored
Merge branch '10.2.x' into bpenkov/getTypeDefinitionAtPosition-fallback-10.2
2 parents 332a2b9 + 43a1c8b commit 9a6d9c1

39 files changed

+1288
-185
lines changed

projects/igniteui-angular/src/lib/calendar/calendar-base.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,16 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
156156
*/
157157
public set value(value: Date | Date[]) {
158158
if (!value || !!value && (value as Date[]).length === 0) {
159+
this.selectedDatesWithoutFocus = new Date();
159160
return;
160161
}
161-
162+
if (!this.selectedDatesWithoutFocus) {
163+
const valueDate = value[0] ? Math.min.apply(null, value) : value;
164+
const date = this.getDateOnly(new Date(valueDate)).setDate(1);
165+
this.viewDate = new Date(date);
166+
}
162167
this.selectDate(value);
168+
this.selectedDatesWithoutFocus = value;
163169
}
164170

165171
/**
@@ -175,6 +181,9 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
175181
* Sets the date that will be presented in the default view when the component renders.
176182
*/
177183
public set viewDate(value: Date) {
184+
if (this._viewDate) {
185+
this.selectedDatesWithoutFocus = value;
186+
}
178187
const date = this.getDateOnly(value).setDate(1);
179188
this._viewDate = new Date(date);
180189
}
@@ -380,6 +389,11 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
380389
*/
381390
public selectedDates;
382391

392+
/**
393+
* @hidden
394+
*/
395+
private selectedDatesWithoutFocus;
396+
383397
/**
384398
* @hidden
385399
*/

projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,8 @@ describe('IgxCalendar - ', () => {
174174
configureTestSuite();
175175
beforeAll(async(() => {
176176
TestBed.configureTestingModule({
177-
declarations: [IgxCalendarSampleComponent, IgxCalendarRangeComponent, IgxCalendarDisabledSpecialDatesComponent],
177+
declarations: [IgxCalendarSampleComponent, IgxCalendarRangeComponent, IgxCalendarDisabledSpecialDatesComponent,
178+
IgxCalendarValueComponent],
178179
imports: [IgxCalendarModule, FormsModule, NoopAnimationsModule]
179180
}).compileComponents();
180181
}));
@@ -291,6 +292,27 @@ describe('IgxCalendar - ', () => {
291292
expect(bodyMonth.nativeElement.textContent.trim()).toMatch('8');
292293
});
293294

295+
it('Should show right month when value is set', () => {
296+
fixture = TestBed.createComponent(IgxCalendarValueComponent);
297+
fixture.detectChanges();
298+
calendar = fixture.componentInstance.calendar;
299+
300+
expect(calendar.weekStart).toEqual(WEEKDAYS.SUNDAY);
301+
expect(calendar.selection).toEqual('single');
302+
expect(calendar.viewDate.getMonth()).toEqual(calendar.value.getMonth());
303+
304+
const date = new Date(2020, 8, 28);
305+
calendar.viewDate = date;
306+
fixture.detectChanges();
307+
308+
expect(calendar.viewDate.getMonth()).toEqual(date.getMonth());
309+
310+
calendar.value = new Date(2020, 9, 15);
311+
fixture.detectChanges();
312+
313+
expect(calendar.viewDate.getMonth()).toEqual(date.getMonth());
314+
});
315+
294316
it('Should properly set locale', () => {
295317
fixture.componentInstance.viewDate = new Date(2018, 8, 17);
296318
fixture.componentInstance.model = new Date();
@@ -1998,6 +2020,16 @@ export class IgxCalendarDisabledSpecialDatesComponent {
19982020
@ViewChild(IgxCalendarComponent, { static: true }) public calendar: IgxCalendarComponent;
19992021
}
20002022

2023+
@Component({
2024+
template: `
2025+
<igx-calendar [value]="value"></igx-calendar>
2026+
`
2027+
})
2028+
export class IgxCalendarValueComponent {
2029+
public value = new Date(2020, 7, 13);
2030+
@ViewChild(IgxCalendarComponent, { static: true }) public calendar: IgxCalendarComponent;
2031+
}
2032+
20012033
class DateTester {
20022034
// tests whether a date is disabled or not
20032035
static testDatesAvailability(dates: IgxDayItemComponent[], disabled: boolean) {

projects/igniteui-angular/src/lib/core/styles/themes/schemas/dark/_action-strip.scss

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,24 @@ $_dark-action-strip: extend(
2828
/// Generates a dark fluent action strip schema.
2929
/// @type {Map}
3030
/// @requires {function} extend
31-
/// @requires $_fluent-action-strip
32-
$_dark-fluent-action-strip: extend($_fluent-action-strip);
31+
/// @requires $_dark-action-strip
32+
$_dark-fluent-action-strip: extend(
33+
$_dark-action-strip,
34+
(
35+
variant: 'fluent'
36+
)
37+
);
3338

3439
/// Generates a dark bootstrap action strip schema.
3540
/// @type {Map}
3641
/// @requires {function} extend
37-
/// @requires $_bootstrap-action-strip
38-
$_dark-bootstrap-action-strip: extend($_bootstrap-action-strip);
42+
/// @requires $_dark-action-strip
43+
$_dark-bootstrap-action-strip: extend(
44+
$_dark-action-strip,
45+
(
46+
variant: 'bootstrap'
47+
)
48+
);
3949

4050
/// Generates a dark indigo action strip schema.
4151
/// @type {Map}

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

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,36 @@ export function isObject(value: any): boolean {
9898
* @returns true if provided variable is Date
9999
* @hidden
100100
*/
101-
export function isDate(value: any) {
102-
return Object.prototype.toString.call(value) === '[object Date]';
101+
export function isDate(value: any): boolean {
102+
return value instanceof Date;
103+
}
104+
105+
/**
106+
* Parse provided input to Date.
107+
* @param value input to parse
108+
* @returns Date if parse succeed or null
109+
* @hidden
110+
*/
111+
export function parseDate(value: any): Date | null {
112+
// if value is Invalid Date return null
113+
if (isDate(value)) {
114+
return !isNaN(value.getTime()) ? value : null;
115+
}
116+
return value ? new Date(value) : null;
117+
}
118+
119+
/**
120+
* Returns an array with unique dates only.
121+
* @param columnValues collection of date values (might be numbers or ISO 8601 strings)
122+
* @returns collection of unique dates.
123+
* @hidden
124+
*/
125+
export function uniqueDates(columnValues: any[]) {
126+
return columnValues.reduce((a, c) => {
127+
if (!a.cache[c.label]) { a.result.push(c); }
128+
a.cache[c.label] = true;
129+
return a;
130+
}, {result: [], cache: {}}).result;
103131
}
104132

105133
/**
@@ -305,9 +333,9 @@ export interface CancelableBrowserEventArgs extends CancelableEventArgs {
305333
event?: Event;
306334
}
307335

308-
export interface IBaseCancelableBrowserEventArgs extends CancelableBrowserEventArgs, IBaseEventArgs {}
336+
export interface IBaseCancelableBrowserEventArgs extends CancelableBrowserEventArgs, IBaseEventArgs { }
309337

310-
export interface IBaseCancelableEventArgs extends CancelableEventArgs, IBaseEventArgs {}
338+
export interface IBaseCancelableEventArgs extends CancelableEventArgs, IBaseEventArgs { }
311339

312340
export const HORIZONTAL_NAV_KEYS = new Set(['arrowleft', 'left', 'arrowright', 'right', 'home', 'end']);
313341

@@ -328,8 +356,11 @@ export const NAVIGATION_KEYS = new Set([
328356
]);
329357
export const ROW_EXPAND_KEYS = new Set('right down arrowright arrowdown'.split(' '));
330358
export const ROW_COLLAPSE_KEYS = new Set('left up arrowleft arrowup'.split(' '));
331-
export const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup', '+', 'add']);
332-
export const HEADER_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'escape', 'esc' , 'l']);
359+
export const ROW_ADD_KEYS = new Set(['+', 'add', '≠', '±', '=']);
360+
export const SUPPORTED_KEYS = new Set([...Array.from(NAVIGATION_KEYS), ...Array.from(ROW_ADD_KEYS), 'enter', 'f2', 'escape', 'esc', 'pagedown', 'pageup']);
361+
export const HEADER_KEYS = new Set([...Array.from(NAVIGATION_KEYS), 'escape', 'esc' , 'l',
362+
/** This symbol corresponds to the Alt + L combination under MAC. */
363+
'¬']);
333364

334365
/**
335366
* @hidden
@@ -442,7 +473,7 @@ export function yieldingLoop(count: number, chunkSize: number, callback: (index:
442473
let i = 0;
443474
const chunk = () => {
444475
const end = Math.min(i + chunkSize, count);
445-
for ( ; i < end; ++i) {
476+
for (; i < end; ++i) {
446477
callback(i);
447478
}
448479
if (i < count) {

projects/igniteui-angular/src/lib/data-operations/data-util.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ITreeGridRecord } from '../grids/tree-grid/public_api';
1515
import { cloneValue, mergeObjects, mkenum } from '../core/utils';
1616
import { Transaction, TransactionType, HierarchicalTransaction } from '../services/transaction/transaction';
1717
import { getHierarchy, isHierarchyMatch } from './operations';
18+
import { GridType } from '../grids/common/grid.interface';
1819

1920
/**
2021
* @hidden
@@ -31,25 +32,27 @@ export type DataType = (typeof DataType)[keyof typeof DataType];
3132
* @hidden
3233
*/
3334
export class DataUtil {
34-
public static sort<T>(data: T[], expressions: ISortingExpression[], sorting: IGridSortingStrategy = new IgxSorting()): T[] {
35-
return sorting.sort(data, expressions);
35+
public static sort<T>(data: T[], expressions: ISortingExpression[], sorting: IGridSortingStrategy = new IgxSorting(),
36+
grid?: GridType): T[] {
37+
return sorting.sort(data, expressions, grid);
3638
}
3739

3840
public static treeGridSort(hierarchicalData: ITreeGridRecord[],
3941
expressions: ISortingExpression[],
4042
sorting: IGridSortingStrategy = new IgxDataRecordSorting(),
41-
parent?: ITreeGridRecord): ITreeGridRecord[] {
43+
parent?: ITreeGridRecord,
44+
grid?: GridType): ITreeGridRecord[] {
4245
let res: ITreeGridRecord[] = [];
4346
hierarchicalData.forEach((hr: ITreeGridRecord) => {
4447
const rec: ITreeGridRecord = DataUtil.cloneTreeGridRecord(hr);
4548
rec.parent = parent;
4649
if (rec.children) {
47-
rec.children = DataUtil.treeGridSort(rec.children, expressions, sorting, rec);
50+
rec.children = DataUtil.treeGridSort(rec.children, expressions, sorting, rec, grid);
4851
}
4952
res.push(rec);
5053
});
5154

52-
res = DataUtil.sort(res, expressions, sorting);
55+
res = DataUtil.sort(res, expressions, sorting, grid);
5356

5457
return res;
5558
}
@@ -66,7 +69,7 @@ export class DataUtil {
6669
return rec;
6770
}
6871

69-
public static group<T>(data: T[], state: IGroupingState, grid: any = null,
72+
public static group<T>(data: T[], state: IGroupingState, grid: GridType = null,
7073
groupsRecords: any[] = [], fullResult: IGroupByResult = { data: [], metadata: [] }): IGroupByResult {
7174
const grouping = new IgxGrouping();
7275
groupsRecords.splice(0, groupsRecords.length);
@@ -105,11 +108,11 @@ export class DataUtil {
105108
return data.slice(index * recordsPerPage, (index + 1) * recordsPerPage);
106109
}
107110

108-
public static filter<T>(data: T[], state: IFilteringState): T[] {
111+
public static filter<T>(data: T[], state: IFilteringState, grid?: GridType): T[] {
109112
if (!state.strategy) {
110113
state.strategy = new FilteringStrategy();
111114
}
112-
return state.strategy.filter(data, state.expressionsTree, state.advancedExpressionsTree);
115+
return state.strategy.filter(data, state.expressionsTree, state.advancedExpressionsTree, grid);
113116
}
114117

115118
public static correctPagingState(state: IPagingState, length: number) {

projects/igniteui-angular/src/lib/data-operations/filtering-condition.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ export class IgxDateFilteringOperand extends IgxFilteringOperand {
391391

392392
protected findValueInSet(target: any, searchVal: Set<any>) {
393393
if (!target) { return false; }
394-
return searchVal.has(new Date(target.getFullYear(), target.getMonth(), target.getDate()).toISOString());
394+
return searchVal.has(target.toISOString());
395395
}
396396
}
397397

projects/igniteui-angular/src/lib/data-operations/filtering-strategy.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('Unit testing FilteringStrategy', () => {
2323
searchVal: 1
2424
}
2525
];
26-
const res = fs.filter(data, expressionTree);
26+
const res = fs.filter(data, expressionTree, null, null);
2727
expect(dataGenerator.getValuesForColumn(res, 'number'))
2828
.toEqual([2, 3, 4]);
2929
});
@@ -65,7 +65,7 @@ describe('Unit testing FilteringStrategy', () => {
6565
searchVal: 'ROW'
6666
}
6767
];
68-
const res = filterstr.filter(data, expressionTree);
68+
const res = filterstr.filter(data, expressionTree, null, null);
6969
expect(dataGenerator.getValuesForColumn(res, 'number'))
7070
.toEqual([0]);
7171
});

projects/igniteui-angular/src/lib/data-operations/filtering-strategy.ts

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { FilteringLogic, IFilteringExpression } from './filtering-expression.interface';
22
import { FilteringExpressionsTree, IFilteringExpressionsTree } from './filtering-expressions-tree';
3-
import { resolveNestedPath } from '../core/utils';
3+
import { resolveNestedPath, parseDate } from '../core/utils';
4+
import { GridType } from '../grids/common/grid.interface';
5+
6+
const DateType = 'date';
47

58
export interface IFilteringStrategy {
6-
filter(data: any[], expressionsTree: IFilteringExpressionsTree, advancedExpressionsTree?: IFilteringExpressionsTree): any[];
9+
filter(data: any[], expressionsTree: IFilteringExpressionsTree, advancedExpressionsTree?: IFilteringExpressionsTree,
10+
grid?: GridType): any[];
711
}
812

913
export class NoopFilteringStrategy implements IFilteringStrategy {
@@ -22,17 +26,17 @@ export class NoopFilteringStrategy implements IFilteringStrategy {
2226

2327
export abstract class BaseFilteringStrategy implements IFilteringStrategy {
2428
public abstract filter(data: any[], expressionsTree: IFilteringExpressionsTree,
25-
advancedExpressionsTree?: IFilteringExpressionsTree): any[];
29+
advancedExpressionsTree?: IFilteringExpressionsTree, grid?: GridType): any[];
2630

27-
protected abstract getFieldValue(rec: object, fieldName: string): any;
31+
protected abstract getFieldValue(rec: object, fieldName: string, isDate?: boolean): any;
2832

29-
public findMatchByExpression(rec: object, expr: IFilteringExpression): boolean {
33+
public findMatchByExpression(rec: object, expr: IFilteringExpression, isDate?: boolean): boolean {
3034
const cond = expr.condition;
31-
const val = this.getFieldValue(rec, expr.fieldName);
35+
const val = this.getFieldValue(rec, expr.fieldName, isDate);
3236
return cond.logic(val, expr.searchVal, expr.ignoreCase);
3337
}
3438

35-
public matchRecord(rec: object, expressions: IFilteringExpressionsTree | IFilteringExpression): boolean {
39+
public matchRecord(rec: object, expressions: IFilteringExpressionsTree | IFilteringExpression, grid?: GridType): boolean {
3640
if (expressions) {
3741
if (expressions instanceof FilteringExpressionsTree) {
3842
const expressionsTree = expressions as IFilteringExpressionsTree;
@@ -42,7 +46,7 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
4246
if (expressionsTree.filteringOperands && expressionsTree.filteringOperands.length) {
4347
for (let i = 0; i < expressionsTree.filteringOperands.length; i++) {
4448
operand = expressionsTree.filteringOperands[i];
45-
matchOperand = this.matchRecord(rec, operand);
49+
matchOperand = this.matchRecord(rec, operand, grid);
4650

4751
// Return false if at least one operand does not match and the filtering logic is And
4852
if (!matchOperand && operator === FilteringLogic.And) {
@@ -61,7 +65,9 @@ export abstract class BaseFilteringStrategy implements IFilteringStrategy {
6165
return true;
6266
} else {
6367
const expression = expressions as IFilteringExpression;
64-
return this.findMatchByExpression(rec, expression);
68+
const isDate = grid && grid.getColumnByName(expression.fieldName) ?
69+
grid.getColumnByName(expression.fieldName).dataType === DateType : false;
70+
return this.findMatchByExpression(rec, expression, isDate);
6571
}
6672
}
6773

@@ -78,7 +84,8 @@ export class FilteringStrategy extends BaseFilteringStrategy {
7884
return this._instace || (this._instace = new this());
7985
}
8086

81-
public filter<T>(data: T[], expressionsTree: IFilteringExpressionsTree, advancedExpressionsTree?: IFilteringExpressionsTree): T[] {
87+
public filter<T>(data: T[], expressionsTree: IFilteringExpressionsTree, advancedExpressionsTree: IFilteringExpressionsTree,
88+
grid: GridType): T[] {
8289
let i;
8390
let rec;
8491
const len = data.length;
@@ -88,14 +95,16 @@ export class FilteringStrategy extends BaseFilteringStrategy {
8895
}
8996
for (i = 0; i < len; i++) {
9097
rec = data[i];
91-
if (this.matchRecord(rec, expressionsTree) && this.matchRecord(rec, advancedExpressionsTree)) {
98+
if (this.matchRecord(rec, expressionsTree, grid) && this.matchRecord(rec, advancedExpressionsTree, grid)) {
9299
res.push(rec);
93100
}
94101
}
95102
return res;
96103
}
97104

98-
protected getFieldValue(rec: object, fieldName: string): any {
99-
return resolveNestedPath(rec, fieldName);
105+
protected getFieldValue(rec: object, fieldName: string, isDate: boolean = false): any {
106+
let value = resolveNestedPath(rec, fieldName);
107+
value = value && isDate ? parseDate(value) : value;
108+
return value;
100109
}
101110
}

0 commit comments

Comments
 (0)