Skip to content

Commit 2c74158

Browse files
Merge branch '10.2.x' into mtsvyatkova/fix-8697-10.2.x
2 parents 4fe228a + 6bc8794 commit 2c74158

File tree

17 files changed

+215
-97
lines changed

17 files changed

+215
-97
lines changed

.github/workflows/nodejs.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
branches: [ master, '[0-9]+.[0-9]+.x' ]
1111

1212
jobs:
13-
build:
13+
run-tests:
1414

1515
runs-on: ubuntu-latest
1616

@@ -19,11 +19,10 @@ jobs:
1919
node-version: [10.x, 12.x, 14.x]
2020

2121
steps:
22-
- uses: actions/checkout@v2
22+
- name: Checkout
23+
uses: actions/checkout@v2
2324
- name: Use Node.js ${{ matrix.node-version }}
2425
uses: actions/setup-node@v1
25-
with:
26-
node-version: ${{ matrix.node-version }}
2726
- run: npm ci
2827
- run: npm run lint:lib
2928
- run: npm run build:lib
@@ -40,3 +39,16 @@ jobs:
4039
env:
4140
NODE_OPTIONS: --max_old_space_size=4096
4241
- run: npm run test:schematics
42+
- name: Install coverage combiner
43+
if: github.repository == 'IgniteUI/igniteui-angular' && matrix.node-version == '14.x'
44+
run: sudo npm install -g istanbul-combine
45+
- name: Combine scripts
46+
if: github.repository == 'IgniteUI/igniteui-angular' && matrix.node-version == '14.x'
47+
run: istanbul-combine -d coverage -p none -r lcov -r cobertura coverage/hierarchical-grid/coverage-final.json coverage/tree-grid/coverage-final.json coverage/non-grid/coverage-final.json coverage/grid/coverage-final.json
48+
- name: Publish to coveralls.io
49+
if: github.repository == 'IgniteUI/igniteui-angular' && matrix.node-version == '14.x'
50+
uses: coverallsapp/[email protected]
51+
with:
52+
github-token: ${{ github.token }}
53+
54+

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ script:
2424
- if [ -z "${TRAVIS_TAG}" ]; then npm run test:lib:grid; fi
2525
- if [ -z "${TRAVIS_TAG}" ]; then npm run test:lib:tgrid; fi
2626
- if [ -z "${TRAVIS_TAG}" ]; then npm run test:lib:hgrid; fi
27-
- if [ -z "${TRAVIS_TAG}" ]; then istanbul-combine -d coverage -p none -r lcov -r html coverage/hierarchical-grid/coverage-final.json coverage/tree-grid/coverage-final.json coverage/non-grid/coverage-final.json coverage/grid/coverage-final.json; fi
2827
- if [ -z "${TRAVIS_TAG}" ]; then npm run test:schematics; fi
29-
- if [ -z "${TRAVIS_TAG}" ] && [ "${TRAVIS_REPO_SLUG}" == "IgniteUI/igniteui-angular" ]; then cat ./coverage/lcov.info | coveralls; fi
28+
## Use only Github actions for publishing coveralls.io status
29+
#- if [ -z "${TRAVIS_TAG}" ]; then istanbul-combine -d coverage -p none -r lcov -r html coverage/hierarchical-grid/coverage-final.json coverage/tree-grid/coverage-final.json coverage/non-grid/coverage-final.json coverage/grid/coverage-final.json; fi
30+
# - if [ -z "${TRAVIS_TAG}" ] && [ "${TRAVIS_REPO_SLUG}" == "IgniteUI/igniteui-angular" ]; then cat ./coverage/lcov.info | coveralls; fi
3031

3132
# before_deploy:
3233
# - npm run build:schematics

azure-pipelines.yml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,17 @@ steps:
3838
env:
3939
NODE_OPTIONS: "--max_old_space_size=4096"
4040

41-
- script: istanbul-combine -d coverage -p none -r lcov -r cobertura coverage/hierarchical-grid/coverage-final.json coverage/tree-grid/coverage-final.json coverage/non-grid/coverage-final.json coverage/grid/coverage-final.json
42-
displayName: 'Combine coverage results'
43-
env:
44-
AZURE_PIPELINES: "true"
41+
## Use only Github actions for publishing coveralls.io status
42+
# - script: istanbul-combine -d coverage -p none -r lcov -r cobertura coverage/hierarchical-grid/coverage-final.json coverage/tree-grid/coverage-final.json coverage/non-grid/coverage-final.json coverage/grid/coverage-final.json
43+
# displayName: 'Combine coverage results'
44+
# env:
45+
# AZURE_PIPELINES: "true"
4546

46-
- script: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
47-
condition: and(succeeded(), eq(variables['system.teamProject'], 'igniteui-angular'))
48-
displayName: 'Code coverage @ Coveralls'
49-
env:
50-
COVERALLS_REPO_TOKEN: $(coveralls.repoToken)
47+
# - script: cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
48+
# condition: and(succeeded(), eq(variables['system.teamProject'], 'igniteui-angular'))
49+
# displayName: 'Code coverage @ Coveralls'
50+
# env:
51+
# COVERALLS_REPO_TOKEN: $(coveralls.repoToken)
5152

5253
- script: npm run test:schematics
5354
displayName: 'Run migrations & schematics'

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export class IgxCalendarBaseDirective implements ControlValueAccessor {
181181
* Sets the date that will be presented in the default view when the component renders.
182182
*/
183183
public set viewDate(value: Date) {
184+
if (Array.isArray(value)) { return; }
184185
if (this._viewDate) {
185186
this.selectedDatesWithoutFocus = value;
186187
}

projects/igniteui-angular/src/lib/calendar/months-view/months-view.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ export class IgxMonthsViewComponent implements ControlValueAccessor {
4848
* @memberof IgxMonthsViewComponent
4949
*/
5050
@Input()
51-
public set date(value) {
51+
public set date(value: Date) {
52+
if (!(value instanceof Date)) { return; }
5253
this._date = value;
5354
this.activeMonth = this.date.getMonth();
5455
}

projects/igniteui-angular/src/lib/calendar/years-view/years-view.component.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,14 @@ export class IgxYearsViewComponent implements ControlValueAccessor {
5757
* @memberof IgxYearsViewComponent
5858
*/
5959
@Input()
60-
public date = new Date();
60+
public get date() {
61+
return this._date;
62+
}
63+
64+
public set date(value: Date) {
65+
if (!(value instanceof Date)) { return; }
66+
this._date = value;
67+
}
6168

6269
/**
6370
* Gets the year format option of the years view.
@@ -181,6 +188,10 @@ export class IgxYearsViewComponent implements ControlValueAccessor {
181188
* @hidden
182189
*/
183190
private _calendarModel: Calendar;
191+
/**
192+
* @hidden
193+
*/
194+
private _date = new Date();
184195

185196
/**
186197
* @hidden

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

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { async, TestBed, fakeAsync, tick } from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { BrowserAnimationsModule, NoopAnimationsModule } from '@angular/platform-browser/animations';
55
import { UIInteractions } from '../test-utils/ui-interactions.spec';
6-
import { IDialogEventArgs, IgxDialogComponent, IgxDialogModule } from './dialog.component';
6+
import { IDialogCancellableEventArgs, IDialogEventArgs, IgxDialogComponent, IgxDialogModule } from './dialog.component';
77
import { configureTestSuite } from '../test-utils/configure-suite';
88
import { useAnimation } from '@angular/animations';
99
import { PositionSettings, HorizontalAlignment, VerticalAlignment } from '../services/overlay/utilities';
@@ -87,7 +87,7 @@ describe('Dialog', () => {
8787
const expectedMessage = 'message';
8888

8989
dialog.isOpen = true;
90-
tick();
90+
tick(100);
9191
fixture.detectChanges();
9292
expect(dialog.isOpen).toEqual(true);
9393

@@ -105,7 +105,7 @@ describe('Dialog', () => {
105105
fixture.componentInstance.myDialog = true;
106106

107107
fixture.detectChanges();
108-
tick();
108+
tick(100);
109109
expect(dialog.isOpen).toEqual(true);
110110

111111

@@ -198,19 +198,36 @@ describe('Dialog', () => {
198198
const dialog = fixture.componentInstance.dialog;
199199
const args: IDialogEventArgs = {
200200
dialog,
201-
event: null
201+
event: undefined,
202+
};
203+
let cancellableArgs: IDialogCancellableEventArgs = {
204+
dialog,
205+
event: null,
206+
cancel: false
202207
};
208+
203209
spyOn(dialog.onOpen, 'emit');
210+
spyOn(dialog.onOpened, 'emit');
211+
spyOn(dialog.isOpenChange, 'emit');
212+
spyOn(dialog.onClose, 'emit');
213+
spyOn(dialog.onClosed, 'emit');
214+
204215
dialog.open();
205216
tick();
206217
fixture.detectChanges();
207-
expect(dialog.onOpen.emit).toHaveBeenCalledWith(args);
208218

209-
spyOn(dialog.onClose, 'emit');
219+
expect(dialog.onOpen.emit).toHaveBeenCalledWith(cancellableArgs);
220+
expect(dialog.isOpenChange.emit).toHaveBeenCalledWith(true);
221+
// expect(dialog.onOpened.emit).toHaveBeenCalled();
222+
210223
dialog.close();
211224
tick();
212225
fixture.detectChanges();
213-
expect(dialog.onClose.emit).toHaveBeenCalledWith(args);
226+
227+
cancellableArgs = { dialog, event: undefined, cancel: false };
228+
expect(dialog.onClose.emit).toHaveBeenCalledWith(cancellableArgs);
229+
expect(dialog.onClosed.emit).toHaveBeenCalledWith(args);
230+
expect(dialog.isOpenChange.emit).toHaveBeenCalledWith(false);
214231

215232
dialog.open();
216233
tick();
@@ -283,10 +300,10 @@ describe('Dialog', () => {
283300

284301
it('Should initialize igx-dialog custom title and actions', () => {
285302
const data = [{
286-
component: CustomTemplates1DialogComponent
287-
}, {
288-
component: CustomTemplates2DialogComponent
289-
}];
303+
component: CustomTemplates1DialogComponent
304+
}, {
305+
component: CustomTemplates2DialogComponent
306+
}];
290307

291308
data.forEach((item) => {
292309
const fixture = TestBed.createComponent(item.component);
@@ -338,7 +355,7 @@ describe('Dialog', () => {
338355
expect(overlayWrapper.classList.contains(OVERLAY_WRAPPER_CLASS)).toBe(false);
339356
}));
340357

341-
it('Default button of the dialog is focused after opening the dialog and can be closed with keyboard.', fakeAsync( () => {
358+
it('Default button of the dialog is focused after opening the dialog and can be closed with keyboard.', fakeAsync(() => {
342359
const fix = TestBed.createComponent(DialogComponent);
343360
fix.detectChanges();
344361

@@ -368,7 +385,7 @@ describe('Dialog', () => {
368385
let fix;
369386
let dialog;
370387

371-
beforeEach( fakeAsync(() => {
388+
beforeEach(fakeAsync(() => {
372389
fix = TestBed.createComponent(PositionSettingsDialogComponent);
373390
fix.detectChanges();
374391
dialog = fix.componentInstance.dialog;
@@ -414,7 +431,7 @@ describe('Dialog', () => {
414431
expect(dialog.isOpen).toEqual(false);
415432
}));
416433

417-
it('Set animation settings', () => {
434+
it('Set animation settings', () => {
418435
const currentElement = fix.componentInstance;
419436

420437
// Check initial animation settings
@@ -584,7 +601,7 @@ class PositionSettingsDialogComponent {
584601
horizontalStartPoint: HorizontalAlignment.Left,
585602
verticalStartPoint: VerticalAlignment.Middle,
586603
openAnimation: useAnimation(slideInTop, { params: { duration: '200ms' } }),
587-
closeAnimation: useAnimation(slideOutBottom, { params: { duration: '200ms'} })
604+
closeAnimation: useAnimation(slideOutBottom, { params: { duration: '200ms' } })
588605
};
589606

590607
public newPositionSettings: PositionSettings = {
@@ -594,7 +611,7 @@ class PositionSettingsDialogComponent {
594611

595612
public animationSettings: PositionSettings = {
596613
openAnimation: useAnimation(slideInTop, { params: { duration: '800ms' } }),
597-
closeAnimation: useAnimation(slideOutBottom, { params: { duration: '700ms'} })
614+
closeAnimation: useAnimation(slideOutBottom, { params: { duration: '700ms' } })
598615
};
599616

600617
}

projects/igniteui-angular/src/lib/dialog/dialog.component.ts

Lines changed: 62 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { IgxToggleModule, IgxToggleDirective } from '../directives/toggle/toggle
2424
import { OverlaySettings, GlobalPositionStrategy, NoOpScrollStrategy, PositionSettings } from '../services/public_api';
2525
import { slideInBottom, slideOutTop } from '../animations/slide/index';
2626
import { IgxFocusModule } from '../directives/focus/focus.directive';
27-
import { IBaseEventArgs } from '../core/utils';
27+
import { CancelableEventArgs, IBaseEventArgs } from '../core/utils';
2828

2929
let DIALOG_ID = 0;
3030
/**
@@ -277,24 +277,44 @@ export class IgxDialogComponent implements IToggleView, OnInit, OnDestroy, After
277277
}
278278

279279
/**
280-
* An event that is emitted when the dialog is opened.
280+
* An event that is emitted before the dialog is opened.
281281
* ```html
282282
* <igx-dialog (onOpen)="onDialogOpenHandler($event)" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK">
283283
* </igx-dialog>
284284
* ```
285285
*/
286286
@Output()
287-
public onOpen = new EventEmitter<IDialogEventArgs>();
287+
public onOpen = new EventEmitter<IDialogCancellableEventArgs>();
288288

289289
/**
290-
* An event that is emitted when the dialog is closed.
290+
* An event that is emitted after the dialog is opened.
291+
* ```html
292+
* <igx-dialog (onOpened)="onDialogOpenedHandler($event)" (onLeftButtonSelect)="dialog.close()" rightButtonLabel="OK">
293+
* </igx-dialog>
294+
* ```
295+
*/
296+
@Output()
297+
public onOpened = new EventEmitter<IDialogEventArgs>();
298+
299+
/**
300+
* An event that is emitted before the dialog is closed.
291301
* ```html
292302
* <igx-dialog (onClose)="onDialogCloseHandler($event)" title="Confirmation" leftButtonLabel="Cancel" rightButtonLabel="OK">
293303
* </igx-dialog>
294304
* ```
295305
*/
296306
@Output()
297-
public onClose = new EventEmitter<IDialogEventArgs>();
307+
public onClose = new EventEmitter<IDialogCancellableEventArgs>();
308+
309+
/**
310+
* An event that is emitted after the dialog is closed.
311+
* ```html
312+
* <igx-dialog (onClosed)="onDialogClosedHandler($event)" title="Confirmation" leftButtonLabel="Cancel" rightButtonLabel="OK">
313+
* </igx-dialog>
314+
* ```
315+
*/
316+
@Output()
317+
public onClosed = new EventEmitter<IDialogEventArgs>();
298318

299319
/**
300320
* An event that is emitted when the left button is clicked.
@@ -389,12 +409,15 @@ export class IgxDialogComponent implements IToggleView, OnInit, OnDestroy, After
389409
return !this.toggleRef.collapsed;
390410
}
391411
public set isOpen(value: boolean) {
392-
393-
this.isOpenChange.emit(value);
394-
if (value) {
395-
this.open();
396-
} else {
397-
this.close();
412+
if (value !== this.isOpen) {
413+
this.isOpenChange.emit(value);
414+
if (value) {
415+
requestAnimationFrame(() => {
416+
this.open();
417+
});
418+
} else {
419+
this.close();
420+
}
398421
}
399422
}
400423

@@ -458,11 +481,26 @@ export class IgxDialogComponent implements IToggleView, OnInit, OnDestroy, After
458481
}
459482

460483
ngAfterContentInit() {
461-
this.toggleRef.onClosing.pipe(takeUntil(this.destroy$)).subscribe(() => this.emitCloseFromDialog());
484+
this.toggleRef.onClosing.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => this.emitCloseFromDialog(eventArgs));
485+
this.toggleRef.onClosed.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => this.emitClosedFromDialog(eventArgs));
486+
this.toggleRef.onOpened.pipe(takeUntil(this.destroy$)).subscribe((eventArgs) => this.emitOpenedFromDialog(eventArgs));
462487
}
463488

464-
private emitCloseFromDialog() {
465-
this.onClose.emit({ dialog: this, event: null });
489+
private emitCloseFromDialog(eventArgs) {
490+
const dialogEventsArgs = { dialog: this, event: eventArgs.event, cancel: eventArgs.cancel };
491+
this.onClose.emit(dialogEventsArgs);
492+
eventArgs.cancel = dialogEventsArgs.cancel;
493+
if (!eventArgs.cancel) {
494+
this.isOpenChange.emit(false);
495+
}
496+
}
497+
498+
private emitClosedFromDialog(eventArgs) {
499+
this.onClosed.emit({ dialog: this, event: eventArgs.event });
500+
}
501+
502+
private emitOpenedFromDialog(eventArgs) {
503+
this.onOpened.emit({ dialog: this, event: eventArgs.event });
466504
}
467505

468506
/**
@@ -474,10 +512,14 @@ export class IgxDialogComponent implements IToggleView, OnInit, OnDestroy, After
474512
* ```
475513
*/
476514
public open(overlaySettings: OverlaySettings = this._overlayDefaultSettings) {
477-
this.toggleRef.open(overlaySettings);
478-
this.onOpen.emit({ dialog: this, event: null });
479-
if (!this.leftButtonLabel && !this.rightButtonLabel) {
480-
this.toggleRef.element.focus();
515+
const eventArgs: IDialogCancellableEventArgs = { dialog: this, event: null, cancel: false };
516+
this.onOpen.emit(eventArgs);
517+
if (!eventArgs.cancel) {
518+
this.toggleRef.open(overlaySettings);
519+
this.isOpenChange.emit(true);
520+
if (!this.leftButtonLabel && !this.rightButtonLabel) {
521+
this.toggleRef.element.focus();
522+
}
481523
}
482524
}
483525

@@ -559,6 +601,8 @@ export interface IDialogEventArgs extends IBaseEventArgs {
559601
event: Event;
560602
}
561603

604+
export interface IDialogCancellableEventArgs extends IDialogEventArgs, CancelableEventArgs { }
605+
562606
/**
563607
* @hidden
564608
*/

0 commit comments

Comments
 (0)