@coolon/angular-ui-powerups 0.0.89 → 0.0.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/bundles/coolon-angular-ui-powerups.umd.js +641 -488
  2. package/bundles/coolon-angular-ui-powerups.umd.js.map +1 -1
  3. package/bundles/coolon-angular-ui-powerups.umd.min.js +1 -1
  4. package/bundles/coolon-angular-ui-powerups.umd.min.js.map +1 -1
  5. package/coolon-angular-ui-powerups.d.ts +19 -18
  6. package/coolon-angular-ui-powerups.metadata.json +1 -1
  7. package/esm2015/coolon-angular-ui-powerups.js +18 -17
  8. package/esm2015/lib/directives/command.directive.js +28 -5
  9. package/esm2015/lib/interaction/components/activity-container/activity-container.component.js +3 -8
  10. package/esm2015/lib/interaction/components/inplace-interaction-context/inplace-interaction-context.component.js +4 -9
  11. package/esm2015/lib/interaction/interaction-context.js +78 -6
  12. package/esm2015/lib/interaction/services/dialog-interaction.service.js +12 -20
  13. package/esm2015/lib/place/navigation-session.js +182 -39
  14. package/esm2015/lib/place/place-component.js +4 -19
  15. package/esm2015/lib/place/place-definition.js +16 -19
  16. package/esm2015/lib/place/place-router.js +177 -39
  17. package/esm2015/lib/place/route/guards/enter-place-guard.service.js +3 -38
  18. package/esm2015/lib/place/route/guards/leave-place.guard.js +7 -177
  19. package/esm2015/lib/place/visit.js +4 -11
  20. package/esm5/coolon-angular-ui-powerups.js +18 -17
  21. package/esm5/lib/directives/command.directive.js +32 -5
  22. package/esm5/lib/interaction/components/activity-container/activity-container.component.js +3 -12
  23. package/esm5/lib/interaction/components/inplace-interaction-context/inplace-interaction-context.component.js +4 -13
  24. package/esm5/lib/interaction/interaction-context.js +100 -11
  25. package/esm5/lib/interaction/services/dialog-interaction.service.js +12 -23
  26. package/esm5/lib/place/navigation-session.js +225 -54
  27. package/esm5/lib/place/place-component.js +4 -35
  28. package/esm5/lib/place/place-definition.js +17 -39
  29. package/esm5/lib/place/place-router.js +202 -37
  30. package/esm5/lib/place/route/guards/enter-place-guard.service.js +3 -44
  31. package/esm5/lib/place/route/guards/leave-place.guard.js +7 -176
  32. package/esm5/lib/place/visit.js +4 -14
  33. package/fesm2015/coolon-angular-ui-powerups.js +494 -365
  34. package/fesm2015/coolon-angular-ui-powerups.js.map +1 -1
  35. package/fesm5/coolon-angular-ui-powerups.js +592 -439
  36. package/fesm5/coolon-angular-ui-powerups.js.map +1 -1
  37. package/lib/directives/command.directive.d.ts +2 -0
  38. package/lib/interaction/components/activity-container/activity-container.component.d.ts +2 -3
  39. package/lib/interaction/components/inplace-interaction-context/inplace-interaction-context.component.d.ts +4 -5
  40. package/lib/interaction/interaction-context.d.ts +7 -3
  41. package/lib/interaction/services/dialog-interaction.service.d.ts +4 -6
  42. package/lib/place/navigation-session.d.ts +26 -9
  43. package/lib/place/place-component.d.ts +4 -9
  44. package/lib/place/place-definition.d.ts +0 -4
  45. package/lib/place/place-router.d.ts +21 -2
  46. package/lib/place/route/guards/enter-place-guard.service.d.ts +0 -1
  47. package/lib/place/route/guards/leave-place.guard.d.ts +2 -10
  48. package/lib/place/visit.d.ts +0 -2
  49. package/package.json +1 -1
@@ -4,10 +4,10 @@ import { FormsModule } from '@angular/forms';
4
4
  import { MatInputModule, MatFormFieldModule, MatSelectModule, MatDialog, MatButtonModule, MatDialogModule, MatTabsModule as MatTabsModule$1, MatProgressSpinnerModule } from '@angular/material';
5
5
  import { MatTabsModule } from '@angular/material/tabs';
6
6
  import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
7
- import { GarbageCollector, assert, UnaryCommand, lang, Dsl, Logger, DelegatingFormValueModel, UseDelegate, ValueModel, ListModel, StoreInListModel, DelegatingValueModel, MutableStream, MutableListModel, DelegatingListModel, Binding, MutableValueModel, Trace, Guard as Guard$1, Command, StoreInValueModel, OptionsHelper, ValueHolder } from '@coolon/pectin';
7
+ import { GarbageCollector, DelegatingValueModel, assert, UnaryCommand, lang, Dsl, Logger, DelegatingFormValueModel, UseDelegate, ValueModel, ListModel, StoreInListModel, DelegatingListModel, Deferred, MutableStream, MutableListModel, MutableValueModel, Binding, Trace, Guard as Guard$1, Command, StoreInValueModel, OptionsHelper, ValueHolder } from '@coolon/pectin';
8
8
  import { __decorate, __metadata, __awaiter } from 'tslib';
9
9
  import { PortalModule } from '@angular/cdk/portal';
10
- import { Router, RouterModule, UrlSegment, NavigationStart, NavigationEnd, NavigationError, ActivatedRouteSnapshot, RouterStateSnapshot, UrlSerializer } from '@angular/router';
10
+ import { Router, RouterModule, NavigationStart, NavigationEnd, NavigationError, UrlSerializer, UrlSegment, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
11
11
  import ___default, { last, isNil, isEqual } from 'lodash';
12
12
  import { assert as assert$1, Opts, Klass } from '@coolon/typescript-utilities';
13
13
  import { MatDialogConfig, MAT_DIALOG_DEFAULT_OPTIONS, MatDialog as MatDialog$1 } from '@angular/material/dialog';
@@ -34,8 +34,23 @@ class CommandDirective extends GarbageCollector {
34
34
  constructor(elementRef) {
35
35
  super();
36
36
  this.elementRef = elementRef;
37
+ this._commandEnabled = new DelegatingValueModel().withDefault(false);
37
38
  this._commandParameterProvided = false;
38
39
  }
40
+ /**
41
+ * @param {?} command
42
+ * @return {?}
43
+ */
44
+ set pectinCommand(command) {
45
+ this._command = command;
46
+ this._commandEnabled.setDelegate(command ? command.enabled : null);
47
+ }
48
+ /**
49
+ * @return {?}
50
+ */
51
+ get pectinCommand() {
52
+ return this._command;
53
+ }
39
54
  /**
40
55
  * @param {?} value
41
56
  * @return {?}
@@ -73,7 +88,7 @@ class CommandDirective extends GarbageCollector {
73
88
  // for some reason mat-buttons kills the disabled host binding. It works on a regular button but for now
74
89
  // we need to do this.
75
90
  const { chain } = Dsl.disposeWith(this);
76
- chain(this.pectinCommand.enabled).subscribe((/**
91
+ chain(this._commandEnabled).subscribe((/**
77
92
  * @param {?} enabled
78
93
  * @return {?}
79
94
  */
@@ -134,8 +149,16 @@ CommandDirective.propDecorators = {
134
149
  notifyClick: [{ type: HostListener, args: ['click', ['$event'],] }]
135
150
  };
136
151
  if (false) {
137
- /** @type {?} */
138
- CommandDirective.prototype.pectinCommand;
152
+ /**
153
+ * @type {?}
154
+ * @private
155
+ */
156
+ CommandDirective.prototype._command;
157
+ /**
158
+ * @type {?}
159
+ * @private
160
+ */
161
+ CommandDirective.prototype._commandEnabled;
139
162
  /**
140
163
  * @type {?}
141
164
  * @private
@@ -741,14 +764,79 @@ class InteractionContext extends GarbageCollector {
741
764
  */
742
765
  constructor() {
743
766
  super();
767
+ /**
768
+ * Returns the current list of activities that are in progress.
769
+ * This model is only updated in the next tick after the view has been updated.
770
+ */
771
+ this._activityListDelegate = new DelegatingListModel();
772
+ const { chain, valueOf, before, when, after, observe, switchOn } = Dsl.disposeWith(this);
773
+ when.listOf(this.activityList).becomesPopulated((/**
774
+ * @param {?} activities
775
+ * @return {?}
776
+ */
777
+ (activities) => {
778
+ if (this.deferredGetCurrentActivity) {
779
+ this.deferredGetCurrentActivity.resolve(last(activities));
780
+ this.deferredGetCurrentActivity = null;
781
+ }
782
+ }));
783
+ }
784
+ /**
785
+ * @protected
786
+ * @param {?} activityList
787
+ * @return {?}
788
+ */
789
+ setActivityList(activityList) {
790
+ this._activityListDelegate.setDelegate(activityList);
791
+ }
792
+ /**
793
+ * @return {?}
794
+ */
795
+ get activityList() {
796
+ return this._activityListDelegate.readonly;
744
797
  }
745
798
  /**
746
799
  * Returns the activity that is currently active.
747
800
  * This model is only updated in the next tick after the view has been updated.
748
801
  * @return {?}
749
802
  */
750
- get currentActivity() {
751
- return last(this.activityList.value);
803
+ getCurrentActivity() {
804
+ return __awaiter(this, void 0, void 0, function* () {
805
+ if (!this.isActive()) {
806
+ return Promise.reject('no activity in progress');
807
+ }
808
+ else {
809
+ if (this.deferredGetCurrentActivity) {
810
+ // we're already waiting then just return the same promise
811
+ return this.deferredGetCurrentActivity.promise;
812
+ }
813
+ else {
814
+ if (this.activityList.length < 1) {
815
+ this.deferredGetCurrentActivity = Deferred.defer();
816
+ return this.deferredGetCurrentActivity.promise;
817
+ }
818
+ else {
819
+ return last(this.activityList.value);
820
+ }
821
+ }
822
+ }
823
+ });
824
+ }
825
+ /**
826
+ * @param {?} confirm
827
+ * @return {?}
828
+ */
829
+ confirm(confirm) {
830
+ // Important: we have to implement confirmOrReject as the main entry point
831
+ // as the canDeactivation guards need to be able to cancel an interaction
832
+ // without caring about returning a value.
833
+ return this.confirmOrReject(confirm).then((/**
834
+ * @return {?}
835
+ */
836
+ () => true)).catch((/**
837
+ * @return {?}
838
+ */
839
+ () => false));
752
840
  }
753
841
  }
754
842
  if (false) {
@@ -756,8 +844,14 @@ if (false) {
756
844
  * Returns the current list of activities that are in progress.
757
845
  * This model is only updated in the next tick after the view has been updated.
758
846
  * @type {?}
847
+ * @private
848
+ */
849
+ InteractionContext.prototype._activityListDelegate;
850
+ /**
851
+ * @type {?}
852
+ * @private
759
853
  */
760
- InteractionContext.prototype.activityList;
854
+ InteractionContext.prototype.deferredGetCurrentActivity;
761
855
  /**
762
856
  * Returns true if an activity is currently running.
763
857
  * @abstract
@@ -777,7 +871,7 @@ if (false) {
777
871
  * @param {?} confirm
778
872
  * @return {?}
779
873
  */
780
- InteractionContext.prototype.confirm = function (confirm) { };
874
+ InteractionContext.prototype.confirmOrReject = function (confirm) { };
781
875
  /**
782
876
  * Presents the confirmation to the user and runs the activity only if the user confirms.
783
877
  * @abstract
@@ -1290,6 +1384,7 @@ class ActivityContainerComponent extends InteractionContext {
1290
1384
  * @return {?}
1291
1385
  */
1292
1386
  () => this.onNestedActivityFinished()));
1387
+ this.setActivityList(this._activityList.readonly);
1293
1388
  }
1294
1389
  /**
1295
1390
  * @param {?} initialContext
@@ -1337,12 +1432,6 @@ class ActivityContainerComponent extends InteractionContext {
1337
1432
  isActive() {
1338
1433
  return !!this._initialActivityOutletContext;
1339
1434
  }
1340
- /**
1341
- * @return {?}
1342
- */
1343
- get activityList() {
1344
- return this._activityList.readonly;
1345
- }
1346
1435
  /**
1347
1436
  * @return {?}
1348
1437
  */
@@ -1422,7 +1511,7 @@ class ActivityContainerComponent extends InteractionContext {
1422
1511
  * @param {?} confirm
1423
1512
  * @return {?}
1424
1513
  */
1425
- confirm(confirm) {
1514
+ confirmOrReject(confirm) {
1426
1515
  return this.startActivity(ConfirmationDialogComponent, confirm);
1427
1516
  }
1428
1517
  /**
@@ -1581,13 +1670,8 @@ class InplaceInteractionContextComponent extends InteractionContext {
1581
1670
  /**
1582
1671
  * @return {?}
1583
1672
  */
1584
- ngOnInit() {
1585
- }
1586
- /**
1587
- * @return {?}
1588
- */
1589
- get activityList() {
1590
- return this.interactionContext.activityList;
1673
+ ngAfterViewInit() {
1674
+ this.setActivityList(this.interactionContext.activityList);
1591
1675
  }
1592
1676
  /**
1593
1677
  * @return {?}
@@ -1607,7 +1691,7 @@ class InplaceInteractionContextComponent extends InteractionContext {
1607
1691
  * @param {?} confirm
1608
1692
  * @return {?}
1609
1693
  */
1610
- confirm(confirm) {
1694
+ confirmOrReject(confirm) {
1611
1695
  return this._startActivity(ConfirmationDialogComponent, confirm);
1612
1696
  }
1613
1697
  /**
@@ -1762,29 +1846,21 @@ class DialogInteractionService extends InteractionContext {
1762
1846
  this.router = router;
1763
1847
  this.dialogServiceDefaults = dialogServiceDefaults;
1764
1848
  this.matDialogDefaultConfig = matDialogDefaultConfig;
1765
- this._activityList = new DelegatingListModel();
1766
1849
  this.startingGuard = new Guard();
1850
+ this._inActivityPromise = new MutableValueModel(false);
1767
1851
  assert$1.notNil(dialogService);
1768
- const { chain, valueOf, before, when, after, observe, switchOn } = Dsl.disposeWith(this);
1769
- this.active = chain(this._activityList).isNotEmpty();
1770
1852
  }
1771
1853
  /**
1772
1854
  * @return {?}
1773
1855
  */
1774
1856
  isActive() {
1775
- return this.active.value;
1776
- }
1777
- /**
1778
- * @return {?}
1779
- */
1780
- cancelActivity() {
1781
- this.currentActivity.cancel(null);
1857
+ return this._inActivityPromise.value;
1782
1858
  }
1783
1859
  /**
1784
1860
  * @return {?}
1785
1861
  */
1786
- get activityList() {
1787
- return this._activityList.readonly;
1862
+ get active() {
1863
+ return this._inActivityPromise.readonly;
1788
1864
  }
1789
1865
  /**
1790
1866
  * @template D, R, E
@@ -1816,6 +1892,7 @@ class DialogInteractionService extends InteractionContext {
1816
1892
  */
1817
1893
  () => {
1818
1894
  console.log('###### STARTING');
1895
+ this._inActivityPromise.value = true;
1819
1896
  // this.currentActivityId = uuid.v1();
1820
1897
  // this.location.go(this.router.routerState.snapshot.url, "aup");
1821
1898
  /** @type {?} */
@@ -1874,6 +1951,7 @@ class DialogInteractionService extends InteractionContext {
1874
1951
  * @return {?}
1875
1952
  */
1876
1953
  () => {
1954
+ this._inActivityPromise.value = false;
1877
1955
  console.log('###### FINISHED');
1878
1956
  // this.currentActivityId = null;
1879
1957
  self.safelyUpdateActivityListDelegate(null);
@@ -1889,7 +1967,7 @@ class DialogInteractionService extends InteractionContext {
1889
1967
  setTimeout((/**
1890
1968
  * @return {?}
1891
1969
  */
1892
- () => this._activityList.setDelegate(delegate)));
1970
+ () => this.setActivityList(delegate)));
1893
1971
  }
1894
1972
  /**
1895
1973
  * @param {?} alert
@@ -1903,7 +1981,7 @@ class DialogInteractionService extends InteractionContext {
1903
1981
  * @param {?} confirm
1904
1982
  * @return {?}
1905
1983
  */
1906
- confirm(confirm) {
1984
+ confirmOrReject(confirm) {
1907
1985
  return this._startActivity(ConfirmationDialogComponent, confirm, true);
1908
1986
  }
1909
1987
  /**
@@ -1940,14 +2018,12 @@ if (false) {
1940
2018
  * @type {?}
1941
2019
  * @private
1942
2020
  */
1943
- DialogInteractionService.prototype._activityList;
2021
+ DialogInteractionService.prototype.startingGuard;
1944
2022
  /**
1945
2023
  * @type {?}
1946
2024
  * @private
1947
2025
  */
1948
- DialogInteractionService.prototype.startingGuard;
1949
- /** @type {?} */
1950
- DialogInteractionService.prototype.active;
2026
+ DialogInteractionService.prototype._inActivityPromise;
1951
2027
  /**
1952
2028
  * @type {?}
1953
2029
  * @private
@@ -2343,20 +2419,15 @@ class PlaceDefinition {
2343
2419
  return routeIdParameterDef ? visit.getParameter(routeIdParameterDef.name) : null;
2344
2420
  }
2345
2421
  /**
2346
- * Returns angular router commands that specify the route id and any route parameters. The result does
2347
- * not include any path information.
2348
2422
  * @param {?} visit
2349
2423
  * @return {?}
2350
2424
  */
2351
- // getFormattedRouterCommands(visit: Visit): any[] {
2352
- // return this.hasRouteId() ?
2353
- // [this.getFormattedRouteId(visit), this.getFormattedRouteParameters(visit)] :
2354
- // [this.getFormattedRouteParameters(visit)];
2355
- // }
2356
2425
  getFormattedRouteId(visit) {
2357
- return visit.hasRouteId() ? this.getRouteIdParameterDef().urlFormat.format(visit.getRouteId()) : null;
2426
+ // Note: RouteIds are always present in the url and are just empty strings when not defined. This is
2427
+ // mandated by the fact that redirects from <path> to <path>/:id always include the id parameter as
2428
+ // an empty string.
2429
+ return visit.hasRouteId() ? this.getRouteIdParameterDef().urlFormat.format(visit.getRouteId()) : "";
2358
2430
  }
2359
- // @Trace()
2360
2431
  /**
2361
2432
  * @param {?} visit
2362
2433
  * @param {?=} includeRouteId
@@ -2441,15 +2512,17 @@ class PlaceDefinition {
2441
2512
  }
2442
2513
  else {
2443
2514
  /** @type {?} */
2444
- const value = def.urlFormat.parse(params.get(def.name));
2445
- // because our id routes redirect if the id isn't pressent we always have a id
2446
- // parameter in our params. This will bugger our remember and defaultvalue sanitisation
2447
- // as it'll see that the id is present (event thought its null). The sanitisation can't
2448
- // check for null as that's a valid value for the id.
2449
- /** @type {?} */
2450
- const isEmptyRouteId = def.isRouteId && def.isEmptyValue(value);
2451
- if (!isEmptyRouteId) {
2452
- result[def.name] = value;
2515
+ const value = params.get(def.name);
2516
+ if (def.isRouteId) { // TODO: Move this to parameter def so it's a strategy pattern
2517
+ // because our id routes redirect if the id isn't present we always have a id
2518
+ // parameter in our params. This will bugger our remember and defaultvalue sanitisation
2519
+ // as it'll see that the id is present (event thought its a blank string).
2520
+ if (!___default.isEmpty(value)) {
2521
+ result[def.name] = def.urlFormat.parse(value);
2522
+ }
2523
+ }
2524
+ else {
2525
+ result[def.name] = def.urlFormat.parse(value);
2453
2526
  }
2454
2527
  }
2455
2528
  }
@@ -2515,7 +2588,7 @@ const DEFINITION_META_DATA_KEY = 'PLACE_DEFINITION_OPTIONS';
2515
2588
  // this one seems ok.
2516
2589
  /** @type {?} */
2517
2590
  const ROUTE_PARAMETER_LIST_KEY = Symbol('place:route:parameters');
2518
- class PlaceComponent extends GarbageCollector {
2591
+ class PlaceComponent extends DisposableComponent {
2519
2592
  constructor() {
2520
2593
  super();
2521
2594
  }
@@ -2582,27 +2655,11 @@ class PlaceComponent extends GarbageCollector {
2582
2655
  */
2583
2656
  d => d.component));
2584
2657
  }
2585
- /**
2586
- * @return {?}
2587
- */
2588
- canDeactivate() {
2589
- return true;
2590
- }
2591
2658
  /**
2592
2659
  * @return {?}
2593
2660
  */
2594
2661
  onPlaceReady() {
2595
2662
  }
2596
- /**
2597
- * Called by the place outlet after all animations have finished. We need this instead of ngOnDestroy
2598
- * to avoid the fact that the angular router calls it before the animations have run causing the component
2599
- * to loose any pectin bindings.
2600
- * @return {?}
2601
- */
2602
- // @Trace()
2603
- onPlaceDestroyed() {
2604
- this.dispose();
2605
- }
2606
2663
  }
2607
2664
  __decorate([
2608
2665
  Memoize$1(),
@@ -2736,8 +2793,10 @@ class Visit {
2736
2793
  else {
2737
2794
  // copy non route params as is, but only if they already exist otherwise we'll inject nil values and break the
2738
2795
  // defaults and remember sanitisation process.
2796
+ /** @type {?} */
2797
+ const value = this.getParameter(def.name);
2739
2798
  if (this.hasParameter(def.name)) {
2740
- params[def.name] = this.getParameter(def.name);
2799
+ params[def.name] = value;
2741
2800
  }
2742
2801
  }
2743
2802
  }));
@@ -2763,14 +2822,6 @@ class Visit {
2763
2822
  const sameNonRouteParameters = isEqual(this.placeDefinition.getNonRouteParameters(this), this.placeDefinition.getNonRouteParameters(other));
2764
2823
  return !sameNonRouteParameters || this.hasRoutingChangedFrom(other);
2765
2824
  }
2766
- /**
2767
- * @return {?}
2768
- */
2769
- getUrlSegments() {
2770
- return this.placeDefinition.hasRouteId() ?
2771
- [new UrlSegment(this.placeDefinition.path, {}), new UrlSegment(this.placeDefinition.getFormattedRouteId(this), this.placeDefinition.getFormattedRouteParameters(this))] :
2772
- [new UrlSegment(this.placeDefinition.path, this.placeDefinition.getFormattedRouteParameters(this))];
2773
- }
2774
2825
  }
2775
2826
  if (false) {
2776
2827
  /** @type {?} */
@@ -2808,11 +2859,15 @@ class NavigationSession {
2808
2859
  /**
2809
2860
  * @protected
2810
2861
  * @param {?} firstNavigation
2862
+ * @param {?} appModalInteractionContext
2811
2863
  */
2812
- constructor(firstNavigation) {
2864
+ constructor(firstNavigation, appModalInteractionContext) {
2813
2865
  this.firstNavigation = firstNavigation;
2866
+ this.appModalInteractionContext = appModalInteractionContext;
2814
2867
  this._alreadyAccepted = [];
2815
2868
  this._visits = new Map();
2869
+ this.componentDeactivationHandlers = new Map();
2870
+ this.dialogOpenOnStart = this.appModalInteractionContext.isActive();
2816
2871
  }
2817
2872
  /**
2818
2873
  * @param {?} visit
@@ -2828,34 +2883,30 @@ class NavigationSession {
2828
2883
  getVisitFor(placeDef) {
2829
2884
  return this._visits.get(placeDef);
2830
2885
  }
2831
- /**
2832
- * @param {?} params
2833
- * @return {?}
2834
- */
2835
- mergePrivatePlaceParameters(params) {
2836
- return null;
2837
- }
2838
- // @Trace()
2839
- /**
2840
- * @param {?} placeComponent
2841
- * @return {?}
2842
- */
2843
- alreadyAccepted(placeComponent) {
2844
- return this._alreadyAccepted.includes(placeComponent);
2845
- }
2846
- // @Trace()
2847
2886
  /**
2848
2887
  * @param {?} component
2888
+ * @param {?} nextState
2849
2889
  * @return {?}
2850
2890
  */
2851
- rememberAcceptanceOf(component) {
2852
- this._alreadyAccepted.push(component);
2891
+ canDeactivate(component, nextState) {
2892
+ return __awaiter(this, void 0, void 0, function* () {
2893
+ // lookup the handler and create it if we've not seen it yet
2894
+ /** @type {?} */
2895
+ let handler = this.componentDeactivationHandlers.get(component);
2896
+ if (!handler) {
2897
+ /** @type {?} */
2898
+ const isPrimaryHandler = this.componentDeactivationHandlers.size === 0;
2899
+ handler = new NavigationSession.ComponentDeactivationHandler(component, this.appModalInteractionContext, isPrimaryHandler);
2900
+ this.componentDeactivationHandlers.set(component, handler);
2901
+ }
2902
+ return handler.canDeactivate(nextState);
2903
+ });
2853
2904
  }
2854
2905
  /**
2855
2906
  * @param {?} url
2856
2907
  * @return {?}
2857
2908
  */
2858
- setPopstateReturn(url) {
2909
+ setPopstateReturnUrl(url) {
2859
2910
  this._popStateReturnUrl = url;
2860
2911
  }
2861
2912
  /**
@@ -2896,15 +2947,28 @@ if (false) {
2896
2947
  /** @type {?} */
2897
2948
  NavigationSession.prototype.isExternal;
2898
2949
  /** @type {?} */
2950
+ NavigationSession.prototype.dialogOpenOnStart;
2951
+ /**
2952
+ * @type {?}
2953
+ * @private
2954
+ */
2955
+ NavigationSession.prototype.componentDeactivationHandlers;
2956
+ /** @type {?} */
2899
2957
  NavigationSession.prototype.firstNavigation;
2958
+ /**
2959
+ * @type {?}
2960
+ * @private
2961
+ */
2962
+ NavigationSession.prototype.appModalInteractionContext;
2900
2963
  }
2901
2964
  (function (NavigationSession) {
2902
2965
  class External extends NavigationSession {
2903
2966
  /**
2904
2967
  * @param {?} isFirstTime
2968
+ * @param {?} appModelInteractionContext
2905
2969
  */
2906
- constructor(isFirstTime) {
2907
- super(isFirstTime);
2970
+ constructor(isFirstTime, appModelInteractionContext) {
2971
+ super(isFirstTime, appModelInteractionContext);
2908
2972
  this.isExternal = true;
2909
2973
  }
2910
2974
  }
@@ -2915,9 +2979,10 @@ if (false) {
2915
2979
  class Internal extends NavigationSession {
2916
2980
  /**
2917
2981
  * @param {?} visit
2982
+ * @param {?} appModelInteractionContext
2918
2983
  */
2919
- constructor(visit) {
2920
- super(false);
2984
+ constructor(visit, appModelInteractionContext) {
2985
+ super(false, appModelInteractionContext);
2921
2986
  this.isExternal = false;
2922
2987
  this.storeVisit(visit);
2923
2988
  }
@@ -2926,22 +2991,148 @@ if (false) {
2926
2991
  /** @type {?} */
2927
2992
  Internal.prototype.isExternal;
2928
2993
  }
2929
- /**
2930
- * @param {?} visit
2931
- * @return {?}
2932
- */
2933
- function createInternal(visit) {
2934
- return new Internal(visit);
2994
+ class Factory {
2995
+ /**
2996
+ * @param {?} appModelInteractionContext
2997
+ */
2998
+ constructor(appModelInteractionContext) {
2999
+ this.appModelInteractionContext = appModelInteractionContext;
3000
+ }
3001
+ /**
3002
+ * @param {?} visit
3003
+ * @return {?}
3004
+ */
3005
+ createInternal(visit) {
3006
+ return new Internal(visit, this.appModelInteractionContext);
3007
+ }
3008
+ /**
3009
+ * @param {?} firstTimeRoute
3010
+ * @return {?}
3011
+ */
3012
+ createExternal(firstTimeRoute) {
3013
+ return new External(firstTimeRoute, this.appModelInteractionContext);
3014
+ }
2935
3015
  }
2936
- NavigationSession.createInternal = createInternal;
2937
- /**
2938
- * @param {?} firstTimeRoute
2939
- * @return {?}
2940
- */
2941
- function createExternal(firstTimeRoute) {
2942
- return new External(firstTimeRoute);
3016
+ Factory.decorators = [
3017
+ { type: Injectable, args: [{
3018
+ providedIn: 'root'
3019
+ },] },
3020
+ ];
3021
+ /** @nocollapse */
3022
+ Factory.ctorParameters = () => [
3023
+ { type: InteractionContext }
3024
+ ];
3025
+ NavigationSession.Factory = Factory;
3026
+ if (false) {
3027
+ /** @type {?} */
3028
+ Factory.prototype.appModelInteractionContext;
3029
+ }
3030
+ class ComponentDeactivationHandler {
3031
+ /**
3032
+ * @param {?} component
3033
+ * @param {?} appModelInteractionContext
3034
+ * @param {?} primary
3035
+ */
3036
+ constructor(component, appModelInteractionContext, primary) {
3037
+ this.component = component;
3038
+ this.appModelInteractionContext = appModelInteractionContext;
3039
+ this.primary = primary;
3040
+ this.alreadyAccepted = false;
3041
+ // super();
3042
+ }
3043
+ /**
3044
+ * @param {?} nextState
3045
+ * @return {?}
3046
+ */
3047
+ canDeactivate(nextState) {
3048
+ return __awaiter(this, void 0, void 0, function* () {
3049
+ console.log(`${this.constructor.name}.canDeactivate`, { component: this.component });
3050
+ if (this.alreadyAccepted) {
3051
+ // We'll get called multiple times if there's any parameter sanitisation so
3052
+ // we always return true if we accepted on a previous cycle of the current
3053
+ // navigation session.
3054
+ return true;
3055
+ }
3056
+ else {
3057
+ if (this.primary && this.appModelInteractionContext.isActive()) {
3058
+ // We check the global interaction first
3059
+ yield this.cancelCurrentActivityOf(this.appModelInteractionContext);
3060
+ return false;
3061
+ }
3062
+ this.alreadyAccepted = yield this.canDeactivateComponent(nextState);
3063
+ return this.alreadyAccepted;
3064
+ }
3065
+ });
3066
+ }
3067
+ /**
3068
+ * @protected
3069
+ * @param {?} nextState
3070
+ * @return {?}
3071
+ */
3072
+ canDeactivateComponent(nextState) {
3073
+ return __awaiter(this, void 0, void 0, function* () {
3074
+ // check if the component has an active interaction. This will handle
3075
+ // an inplace interaction contexts
3076
+ /** @type {?} */
3077
+ const hasCustomInteractionContext = this.component.interactionContext &&
3078
+ !this.isAppModalInteractionContext(this.component.interactionContext) &&
3079
+ this.component.interactionContext.isActive();
3080
+ if (hasCustomInteractionContext) {
3081
+ this.cancelCurrentActivityOf(this.component.interactionContext);
3082
+ return false;
3083
+ }
3084
+ if (this.isLeavingCurrentPlace(nextState) && this.component.canDeactivate) {
3085
+ // No interaction in progress, so ask the component .
3086
+ // This may start an interaction, hence checking the interaction context before now. I.e. if the place pops up the dialog, and
3087
+ // the user clicks back again, we'll re-enter here and go bang when the component tries to open another dialog.
3088
+ return this.component.canDeactivate();
3089
+ }
3090
+ return true;
3091
+ });
3092
+ }
3093
+ /**
3094
+ * @param {?} interactionContext
3095
+ * @return {?}
3096
+ */
3097
+ isAppModalInteractionContext(interactionContext) {
3098
+ return this.appModelInteractionContext === interactionContext;
3099
+ }
3100
+ /**
3101
+ * @protected
3102
+ * @param {?} interactionContext
3103
+ * @return {?}
3104
+ */
3105
+ cancelCurrentActivityOf(interactionContext) {
3106
+ return __awaiter(this, void 0, void 0, function* () {
3107
+ /** @type {?} */
3108
+ const activity = yield interactionContext.getCurrentActivity();
3109
+ console.log('cancelling', { activity });
3110
+ activity.cancel(null);
3111
+ });
3112
+ }
3113
+ /**
3114
+ * @protected
3115
+ * @param {?} nextState
3116
+ * @return {?}
3117
+ */
3118
+ isLeavingCurrentPlace(nextState) {
3119
+ return !nextState.includesPathOf(this.component.placeDefinition);
3120
+ }
3121
+ }
3122
+ NavigationSession.ComponentDeactivationHandler = ComponentDeactivationHandler;
3123
+ if (false) {
3124
+ /**
3125
+ * @type {?}
3126
+ * @private
3127
+ */
3128
+ ComponentDeactivationHandler.prototype.alreadyAccepted;
3129
+ /** @type {?} */
3130
+ ComponentDeactivationHandler.prototype.component;
3131
+ /** @type {?} */
3132
+ ComponentDeactivationHandler.prototype.appModelInteractionContext;
3133
+ /** @type {?} */
3134
+ ComponentDeactivationHandler.prototype.primary;
2943
3135
  }
2944
- NavigationSession.createExternal = createExternal;
2945
3136
  })(NavigationSession || (NavigationSession = {}));
2946
3137
 
2947
3138
  /**
@@ -3013,12 +3204,16 @@ if (false) {
3013
3204
  class PlaceRouter extends GarbageCollector {
3014
3205
  /**
3015
3206
  * @param {?} router
3207
+ * @param {?} urlSerializer
3208
+ * @param {?} navigationSessionFactory
3016
3209
  * @param {?} angularLocation
3017
3210
  * @param {?} placeHistory
3018
3211
  */
3019
- constructor(router, angularLocation, placeHistory) {
3212
+ constructor(router, urlSerializer, navigationSessionFactory, angularLocation, placeHistory) {
3020
3213
  super();
3021
3214
  this.router = router;
3215
+ this.urlSerializer = urlSerializer;
3216
+ this.navigationSessionFactory = navigationSessionFactory;
3022
3217
  this.angularLocation = angularLocation;
3023
3218
  this.placeHistory = placeHistory;
3024
3219
  this.firstRoute = true;
@@ -3048,8 +3243,11 @@ class PlaceRouter extends GarbageCollector {
3048
3243
  if (event instanceof NavigationStart) {
3049
3244
  this.onAngularRouterStarted(event);
3050
3245
  }
3051
- if (event instanceof NavigationEnd || event instanceof NavigationError) {
3052
- this.onAngularRouterFinished();
3246
+ if (event instanceof NavigationEnd) {
3247
+ this.onAngularRouterFinished(false);
3248
+ }
3249
+ if (event instanceof NavigationError) {
3250
+ this.onAngularRouterFinished(true);
3053
3251
  }
3054
3252
  }));
3055
3253
  this.navigationSessionActive = chain(this.navigationSessionModel).isNotNil();
@@ -3124,21 +3322,19 @@ class PlaceRouter extends GarbageCollector {
3124
3322
  * @return {?}
3125
3323
  */
3126
3324
  router => {
3127
- // we have to to use the definition for route id as our redirection always includes
3128
- // the id in the url segements (but leaves it blank when there's no id). I.e. in the
3129
- // no id case we're doing the following redirect [<placePath>, ""] -> ["..", <id>]
3130
- /** @type {?} */
3131
- const relativePath = !!previous.placeDefinition.hasRouteId() ? '..' : '.';
3132
3325
  /** @type {?} */
3133
- const commands = [
3134
- relativePath,
3135
- ...this.createRouteParameters(next),
3136
- ...this.extractChildPath(activatedRoute.snapshot)
3137
- ];
3138
- console.log('### Push Changes to route Redirect', { commands, relativeTo: activatedRoute.snapshot.url });
3139
- return router.navigate(commands, {
3140
- relativeTo: activatedRoute
3141
- });
3326
+ const commands = this.parseUrl(this.router.routerState.snapshot).createRedirectCommandsFor(next);
3327
+ // // we have to to use the definition for route id as our redirection always includes
3328
+ // // the id in the url segements (but leaves it blank when there's no id). I.e. in the
3329
+ // // no id case we're doing the following redirect [<placePath>, ""] -> ["..", <id>]
3330
+ // const relativePath = !!previous.placeDefinition.hasRouteId() ? '..' : '.';
3331
+ // const commands = [
3332
+ // relativePath,
3333
+ // ...this.createRouteParameters(next),
3334
+ // ...this.extractChildPath(activatedRoute.snapshot)
3335
+ // ];
3336
+ console.log('### Push Changes to route Redirect', { commands });
3337
+ return router.navigate(commands);
3142
3338
  }));
3143
3339
  }
3144
3340
  });
@@ -3150,13 +3346,15 @@ class PlaceRouter extends GarbageCollector {
3150
3346
  */
3151
3347
  doNavigation(visit, customNavigation) {
3152
3348
  return __awaiter(this, void 0, void 0, function* () {
3153
- this._navigationSessionModel.value = NavigationSession.createInternal(visit);
3349
+ this._navigationSessionModel.value = this.navigationSessionFactory.createInternal(visit);
3154
3350
  try {
3155
3351
  yield customNavigation(this.router);
3156
3352
  }
3157
3353
  finally {
3354
+ // Router has finished (since there was no router change required) so we
3355
+ // need to end the navigation session.
3158
3356
  if (this.navigationSession && !this.router.getCurrentNavigation()) {
3159
- this.onAngularRouterFinished();
3357
+ this.onAngularRouterFinished(false);
3160
3358
  }
3161
3359
  }
3162
3360
  });
@@ -3183,9 +3381,9 @@ class PlaceRouter extends GarbageCollector {
3183
3381
  if (!this.navigationSession) { // We been activated by an external route rather than placeRouter.go(visit)
3184
3382
  console.log('navigation started', { firstTime: this.firstRoute });
3185
3383
  /** @type {?} */
3186
- const session = NavigationSession.createExternal(this.firstRoute);
3384
+ const session = this.navigationSessionFactory.createExternal(this.firstRoute);
3187
3385
  if (event.navigationTrigger === 'popstate') {
3188
- session.setPopstateReturn(this.router.routerState.snapshot.url);
3386
+ session.setPopstateReturnUrl(this.router.routerState.snapshot.url);
3189
3387
  }
3190
3388
  this._navigationSessionModel.value = session;
3191
3389
  }
@@ -3194,23 +3392,32 @@ class PlaceRouter extends GarbageCollector {
3194
3392
  // @Trace()
3195
3393
  /**
3196
3394
  * @private
3395
+ * @param {?} cancelled
3197
3396
  * @return {?}
3198
3397
  */
3199
- onAngularRouterFinished() {
3398
+ onAngularRouterFinished(cancelled) {
3200
3399
  /** @type {?} */
3201
3400
  const session = this._navigationSessionModel.value;
3202
- // Update visits before we end the navigation session. This allows the place out let to
3203
- // gate ignore changes that occur while the visit is active
3204
- /** @type {?} */
3205
- const visits = session.getVisits();
3206
- visits.forEach((/**
3207
- * @param {?} v
3208
- * @return {?}
3209
- */
3210
- v => {
3211
- this.placeHistory.add(v);
3212
- }));
3213
- this._activeVisits.value = visits;
3401
+ if (!cancelled) {
3402
+ // Update visits before we end the navigation session. This allows the placeOutets to
3403
+ // ignore visit changes that occur while the navigation is in progress
3404
+ /** @type {?} */
3405
+ const visits = session.getVisits();
3406
+ visits.forEach((/**
3407
+ * @param {?} v
3408
+ * @return {?}
3409
+ */
3410
+ v => this.placeHistory.add(v)));
3411
+ this._activeVisits.value = visits;
3412
+ }
3413
+ else {
3414
+ // Angular doesn't preserve the url when a guard cancels the back button.
3415
+ // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
3416
+ if (session.isPopState) {
3417
+ console.log('cancelled during popstate');
3418
+ this.angularLocation.go(session.popStateReturnUrl);
3419
+ }
3420
+ }
3214
3421
  this._navigationSessionModel.value = null;
3215
3422
  }
3216
3423
  /**
@@ -3224,6 +3431,13 @@ class PlaceRouter extends GarbageCollector {
3224
3431
  */
3225
3432
  child => child.url)));
3226
3433
  }
3434
+ /**
3435
+ * @param {?} snapshot
3436
+ * @return {?}
3437
+ */
3438
+ parseUrl(snapshot) {
3439
+ return new PlaceRouter.UrlHelper(this.urlSerializer.parse(snapshot.url));
3440
+ }
3227
3441
  }
3228
3442
  PlaceRouter.decorators = [
3229
3443
  { type: Injectable, args: [{
@@ -3233,10 +3447,12 @@ PlaceRouter.decorators = [
3233
3447
  /** @nocollapse */
3234
3448
  PlaceRouter.ctorParameters = () => [
3235
3449
  { type: Router },
3450
+ { type: UrlSerializer },
3451
+ { type: NavigationSession.Factory },
3236
3452
  { type: Location },
3237
3453
  { type: PlaceHistory }
3238
3454
  ];
3239
- /** @nocollapse */ PlaceRouter.ngInjectableDef = ɵɵdefineInjectable({ factory: function PlaceRouter_Factory() { return new PlaceRouter(ɵɵinject(Router), ɵɵinject(Location), ɵɵinject(PlaceHistory)); }, token: PlaceRouter, providedIn: "root" });
3455
+ /** @nocollapse */ PlaceRouter.ngInjectableDef = ɵɵdefineInjectable({ factory: function PlaceRouter_Factory() { return new PlaceRouter(ɵɵinject(Router), ɵɵinject(UrlSerializer), ɵɵinject(NavigationSession.Factory), ɵɵinject(Location), ɵɵinject(PlaceHistory)); }, token: PlaceRouter, providedIn: "root" });
3240
3456
  __decorate([
3241
3457
  Trace(),
3242
3458
  __metadata("design:type", Function),
@@ -3268,11 +3484,123 @@ if (false) {
3268
3484
  * @private
3269
3485
  */
3270
3486
  PlaceRouter.prototype.router;
3487
+ /**
3488
+ * @type {?}
3489
+ * @private
3490
+ */
3491
+ PlaceRouter.prototype.urlSerializer;
3492
+ /**
3493
+ * @type {?}
3494
+ * @private
3495
+ */
3496
+ PlaceRouter.prototype.navigationSessionFactory;
3271
3497
  /** @type {?} */
3272
3498
  PlaceRouter.prototype.angularLocation;
3273
3499
  /** @type {?} */
3274
3500
  PlaceRouter.prototype.placeHistory;
3275
3501
  }
3502
+ (function (PlaceRouter) {
3503
+ class UrlHelper {
3504
+ /**
3505
+ * @param {?} urlTree
3506
+ */
3507
+ constructor(urlTree) {
3508
+ this.urlTree = urlTree;
3509
+ console.log({ segments: this.urlTree.root.children.primary.segments });
3510
+ }
3511
+ /**
3512
+ * @return {?}
3513
+ */
3514
+ cloneUrlSegmentList() {
3515
+ return [...this.urlTree.root.children.primary.segments];
3516
+ }
3517
+ /**
3518
+ * @param {?} visit
3519
+ * @return {?}
3520
+ */
3521
+ updateVisitSegments(visit) {
3522
+ // Ugly, but it works for now.
3523
+ /** @type {?} */
3524
+ const segments = this.cloneUrlSegmentList();
3525
+ /** @type {?} */
3526
+ const visitSegments = this.convertToUrlSegments(visit);
3527
+ /** @type {?} */
3528
+ const replaceAt = segments.findIndex((/**
3529
+ * @param {?} segment
3530
+ * @return {?}
3531
+ */
3532
+ segment => segment.path === visitSegments[0].path));
3533
+ // do not use the return value, it's the items that were removed!
3534
+ segments.splice(replaceAt, visitSegments.length, ...visitSegments);
3535
+ return segments;
3536
+ }
3537
+ /**
3538
+ * Converts the visit into segments. Please not that these segments are not e
3539
+ * @param {?} visit
3540
+ * @return {?}
3541
+ */
3542
+ convertToUrlSegments(visit) {
3543
+ return visit.placeDefinition.hasRouteId() ?
3544
+ [
3545
+ // NOTE:
3546
+ // It's important to attach the params to the root path and not the id. If we attach them
3547
+ // to an empty id then the angular router won't match the pattern.
3548
+ new UrlSegment(visit.placeDefinition.path, visit.placeDefinition.getFormattedRouteParameters(visit)),
3549
+ new UrlSegment(visit.placeDefinition.getFormattedRouteId(visit), {})
3550
+ ]
3551
+ :
3552
+ [
3553
+ new UrlSegment(visit.placeDefinition.path, visit.placeDefinition.getFormattedRouteParameters(visit))
3554
+ ];
3555
+ }
3556
+ /**
3557
+ * @param {?} visit
3558
+ * @return {?}
3559
+ */
3560
+ createRedirectCommandsFor(visit) {
3561
+ /** @type {?} */
3562
+ const segments = this.updateVisitSegments(visit);
3563
+ /** @type {?} */
3564
+ const commands = [];
3565
+ segments.forEach((/**
3566
+ * @param {?} s
3567
+ * @return {?}
3568
+ */
3569
+ s => {
3570
+ commands.push(s.path);
3571
+ if (s.parameterMap.keys.length > 0) {
3572
+ commands.push(s.parameters);
3573
+ }
3574
+ }));
3575
+ return commands;
3576
+ }
3577
+ /**
3578
+ * @param {?} placeDef
3579
+ * @return {?}
3580
+ */
3581
+ includesPathOf(placeDef) {
3582
+ return this.cloneUrlSegmentList().find((/**
3583
+ * @param {?} s
3584
+ * @return {?}
3585
+ */
3586
+ s => s.path === placeDef.path));
3587
+ }
3588
+ }
3589
+ __decorate([
3590
+ Trace(),
3591
+ __metadata("design:type", Function),
3592
+ __metadata("design:paramtypes", [Visit]),
3593
+ __metadata("design:returntype", Array)
3594
+ ], UrlHelper.prototype, "createRedirectCommandsFor", null);
3595
+ PlaceRouter.UrlHelper = UrlHelper;
3596
+ if (false) {
3597
+ /**
3598
+ * @type {?}
3599
+ * @private
3600
+ */
3601
+ UrlHelper.prototype.urlTree;
3602
+ }
3603
+ })(PlaceRouter || (PlaceRouter = {}));
3276
3604
 
3277
3605
  /**
3278
3606
  * @fileoverview added by tsickle
@@ -4851,10 +5179,9 @@ class EnterPlaceGuard {
4851
5179
  // Save the visit with any updated parameters. We need to save it so we remember any non route parameters
4852
5180
  this.placeRouter.navigationSession.storeVisit(sanitisedVisit);
4853
5181
  if (initialVisit.hasRoutingChangedFrom(sanitisedVisit)) {
4854
- /** @type {?} */
4855
- const routerStateUrlTree = this.urlSerializer.parse(state.url);
4856
5182
  // Regenerate the url
4857
- const { commands } = this.createRedirectCommands(sanitisedVisit, [...routerStateUrlTree.root.children.primary.segments]);
5183
+ /** @type {?} */
5184
+ const commands = this.placeRouter.parseUrl(state).createRedirectCommandsFor(sanitisedVisit);
4858
5185
  console.log('##### Place Guard Redirect', commands);
4859
5186
  return this.router.createUrlTree(commands, {
4860
5187
  replaceUrl: true,
@@ -4870,40 +5197,6 @@ class EnterPlaceGuard {
4870
5197
  }
4871
5198
  });
4872
5199
  }
4873
- /**
4874
- * @private
4875
- * @param {?} sanitisedVisit
4876
- * @param {?} path
4877
- * @return {?}
4878
- */
4879
- createRedirectCommands(sanitisedVisit, path) {
4880
- // Ugly, but it works for now.
4881
- /** @type {?} */
4882
- const newSegments = sanitisedVisit.getUrlSegments();
4883
- /** @type {?} */
4884
- const replaceAt = path.findIndex((/**
4885
- * @param {?} segment
4886
- * @return {?}
4887
- */
4888
- segment => segment.path === newSegments[0].path));
4889
- /** @type {?} */
4890
- const newPath = [...path];
4891
- newPath.splice(replaceAt, newSegments.length, ...newSegments); // do not use the return value, it's the items that were removed!
4892
- // do not use the return value, it's the items that were removed!
4893
- /** @type {?} */
4894
- const commands = [];
4895
- newPath.forEach((/**
4896
- * @param {?} s
4897
- * @return {?}
4898
- */
4899
- s => {
4900
- commands.push(s.path);
4901
- if (s.parameterMap.keys.length > 0) {
4902
- commands.push(s.parameters);
4903
- }
4904
- }));
4905
- return { newPath, commands };
4906
- }
4907
5200
  }
4908
5201
  EnterPlaceGuard.decorators = [
4909
5202
  { type: Injectable, args: [{
@@ -5082,86 +5375,10 @@ if (false) {
5082
5375
  */
5083
5376
  class LeavePlaceGuard {
5084
5377
  /**
5085
- * @param {?} router
5086
- * @param {?} injector
5087
5378
  * @param {?} placeRouter
5088
- * @param {?} dialogInteractionContext
5089
- * @param {?} angularLocation
5090
5379
  */
5091
- constructor(router, injector, placeRouter, dialogInteractionContext, angularLocation) {
5092
- this.router = router;
5093
- this.injector = injector;
5380
+ constructor(placeRouter) {
5094
5381
  this.placeRouter = placeRouter;
5095
- this.dialogInteractionContext = dialogInteractionContext;
5096
- this.angularLocation = angularLocation;
5097
- }
5098
- // @Trace()
5099
- /**
5100
- * @private
5101
- * @param {?} nextState
5102
- * @param {?} placeDefinition
5103
- * @return {?}
5104
- */
5105
- isLeavingTheCurrentPlace(nextState, placeDefinition) {
5106
- // TODO: this will break with child routes... need to examine the router states properly.
5107
- // console.log('canDeactivate', {
5108
- // staticPath: placeDefinitionPath,
5109
- // currentStateUrl: currentState.url,
5110
- // nextStateUrl: nextState.url
5111
- // // alreadyDeclined: this._alreadyAccepted
5112
- // });
5113
- // Example of the above when navigating to a different child route.
5114
- // canDeactivate {staticPath: "/hero-details",
5115
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-details",
5116
- // nextStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats"
5117
- // }
5118
- // TODO: this will break with child routes... need to examine the router states properly.
5119
- // console.log('canDeactivate', {
5120
- // staticPath: placeDefinitionPath,
5121
- // currentStateUrl: currentState.url,
5122
- // nextStateUrl: nextState.url
5123
- // // alreadyDeclined: this._alreadyAccepted
5124
- // });
5125
- // Example of the above when navigating to a different child route.
5126
- // canDeactivate {staticPath: "/hero-details",
5127
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-details",
5128
- // nextStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats"
5129
- // }
5130
- // Example clicking on router tab of the parent component (de-activates the parent due to route param changes)
5131
- // canDeactivate {
5132
- // staticPath: "/hero-stats",
5133
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats",
5134
- // nextStateUrl: "/route-parameters/"
5135
- // }
5136
- // canDeactivate {
5137
- // staticPath: "/route-parameters",
5138
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats",
5139
- // nextStateUrl: "/route-parameters/"
5140
- // }
5141
- // logger.class.js:54 ParameterSnapshot.sanitise -> {idModel: -1, pv: undefined, pl: Array(0), dv: undefined, dl: Array(0), …}
5142
- // parameter-snapshot.ts:20 {name: "idModel", mine: -1, theirs: null}
5143
- // place-router.ts:28 redirect path (3) ["route-parameters", "-1", {…}]
5144
- // canDeactivate {
5145
- // staticPath: "/hero-stats",
5146
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats",
5147
- // nextStateUrl: "/route-parameters/-1"
5148
- // }
5149
- // canDeactivate {
5150
- // staticPath: "/route-parameters",
5151
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats",
5152
- // nextStateUrl: "/route-parameters/-1"
5153
- // }
5154
- // logger.class.js:54 ParameterSnapshot.sanitise -> {idModel: -1, pv: undefined, pl: Array(0), dv: "A", dl: Array(3), …}
5155
- // parameter-snapshot.ts:20 {name: "dv", mine: "A", theirs: undefined}
5156
- // place-router.ts:28 redirect path (3) ["route-parameters", "-1", {…}]
5157
- // canDeactivate {
5158
- // staticPath: "/hero-stats",
5159
- // currentStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c/hero-stats",
5160
- // nextStateUrl: "/route-parameters/-1;dv=A;dl=a,b,c;rdv=A;rdl=a,b,c"
5161
- // }
5162
- /** @type {?} */
5163
- const placeDefinitionPath = `/${placeDefinition.path}`;
5164
- return !nextState.url.startsWith(placeDefinitionPath);
5165
5382
  }
5166
5383
  /**
5167
5384
  * @param {?} component
@@ -5172,77 +5389,7 @@ class LeavePlaceGuard {
5172
5389
  */
5173
5390
  canDeactivate(component, currentRoute, currentState, nextState) {
5174
5391
  return __awaiter(this, void 0, void 0, function* () {
5175
- if (this.placeRouter.navigationSession.alreadyAccepted(component)) {
5176
- // We'll get called multiple times if there's any parameter sanitisation so
5177
- // we always return true if we accepted on a previous cycle of the current
5178
- // navigation session.
5179
- return true;
5180
- }
5181
- else {
5182
- /** @type {?} */
5183
- const self = this;
5184
- /** @type {?} */
5185
- let canLeave = true;
5186
- if (this.isLeavingTheCurrentPlace(nextState, component.placeDefinition)) {
5187
- // we check the dialog interaction first, so that components that don't need to check if they're in an
5188
- // interaction during the canDeactivate cycle.
5189
- // TODO: Add tests: show dialog -> hit back -> same route
5190
- if (this.dialogInteractionContext.isActive()) {
5191
- console.log('cancelling', { activity: this.dialogInteractionContext.currentActivity });
5192
- this.dialogInteractionContext.currentActivity.cancel(null);
5193
- canLeave = false;
5194
- }
5195
- else {
5196
- canLeave = true;
5197
- }
5198
- if (canLeave) {
5199
- // now check if the component has an active interaction. This will handle
5200
- // an inplace interaction contexts
5201
- if (component.interactionContext && component.interactionContext.isActive()) {
5202
- canLeave = false;
5203
- console.log('cancelling', { activity: component.interactionContext.currentActivity });
5204
- component.interactionContext.currentActivity.cancel(null);
5205
- }
5206
- }
5207
- // No interaction in progress, so ask the component .
5208
- // This may start an interaction, hence checking the interaction context above. I.e. if the place pops up the dialog, and
5209
- // the user clicks back again, we'll re-enter here and go bang when the component tries to open another
5210
- // dialog.
5211
- if (canLeave) {
5212
- // TODO: Add tests: hit back -> confirm leave dialog -> hit back -> close dialog -> hit back -> confirm leave dialog.
5213
- canLeave = yield component.canDeactivate();
5214
- }
5215
- // We also block back button parameter changes while the dialog is open.
5216
- // NOTE: Now that I'm catching parameter changes I could possibly retry using a fragment or
5217
- // query parameter to track the dialog being open. Previously I was just checking this on
5218
- // path changes... if that worked it'd fix the case where the back button breaks with an activity
5219
- // open on the first page: https://coolon.atlassian.net/browse/AUP-33
5220
- }
5221
- else {
5222
- if (this.dialogInteractionContext.isActive()) {
5223
- console.log('cancelling', { activity: this.dialogInteractionContext.currentActivity });
5224
- this.dialogInteractionContext.currentActivity.cancel(null);
5225
- canLeave = false;
5226
- }
5227
- else {
5228
- canLeave = true;
5229
- }
5230
- }
5231
- if (canLeave) {
5232
- // We'll get called multiple times if there's any parameter sanitisation so
5233
- // we remember the acceptance for the duration of the current navigation session.
5234
- self.placeRouter.navigationSession.rememberAcceptanceOf(component);
5235
- }
5236
- else {
5237
- // Angular doesn't preserve the url when a guard cancels the back button.
5238
- // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
5239
- if (this.placeRouter.navigationSession.isPopState) {
5240
- console.log('cancelled during popstate');
5241
- this.angularLocation.go(this.placeRouter.navigationSession.popStateReturnUrl);
5242
- }
5243
- }
5244
- return canLeave;
5245
- }
5392
+ return this.placeRouter.navigationSession.canDeactivate(component, this.placeRouter.parseUrl(nextState));
5246
5393
  });
5247
5394
  }
5248
5395
  }
@@ -5253,33 +5400,15 @@ LeavePlaceGuard.decorators = [
5253
5400
  ];
5254
5401
  /** @nocollapse */
5255
5402
  LeavePlaceGuard.ctorParameters = () => [
5256
- { type: Router },
5257
- { type: Injector },
5258
- { type: PlaceRouter },
5259
- { type: InteractionContext },
5260
- { type: Location }
5403
+ { type: PlaceRouter }
5261
5404
  ];
5262
- /** @nocollapse */ LeavePlaceGuard.ngInjectableDef = ɵɵdefineInjectable({ factory: function LeavePlaceGuard_Factory() { return new LeavePlaceGuard(ɵɵinject(Router), ɵɵinject(INJECTOR), ɵɵinject(PlaceRouter), ɵɵinject(InteractionContext), ɵɵinject(Location)); }, token: LeavePlaceGuard, providedIn: "root" });
5405
+ /** @nocollapse */ LeavePlaceGuard.ngInjectableDef = ɵɵdefineInjectable({ factory: function LeavePlaceGuard_Factory() { return new LeavePlaceGuard(ɵɵinject(PlaceRouter)); }, token: LeavePlaceGuard, providedIn: "root" });
5263
5406
  if (false) {
5264
- /**
5265
- * @type {?}
5266
- * @private
5267
- */
5268
- LeavePlaceGuard.prototype.router;
5269
- /**
5270
- * @type {?}
5271
- * @private
5272
- */
5273
- LeavePlaceGuard.prototype.injector;
5274
5407
  /**
5275
5408
  * @type {?}
5276
5409
  * @private
5277
5410
  */
5278
5411
  LeavePlaceGuard.prototype.placeRouter;
5279
- /** @type {?} */
5280
- LeavePlaceGuard.prototype.dialogInteractionContext;
5281
- /** @type {?} */
5282
- LeavePlaceGuard.prototype.angularLocation;
5283
5412
  }
5284
5413
 
5285
5414
  /**
@@ -5302,5 +5431,5 @@ if (false) {
5302
5431
  * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
5303
5432
  */
5304
5433
 
5305
- export { ACTIVITY_DATA, AUP_PLACE_CONFIG, AbstractActivity, AbstractInputComponent, AbstractPlaceNavigationComponent, Activity, ActivityContainerComponent, ActivityOutletComponent, AlertDialogComponent, AngularUiPowerupsModule, Bounds, BusyOverlayComponent, CommandDirective, ComponentsModule, ConfirmThenDialogComponent, ConfirmationDialogComponent, DEFINITION_META_DATA_KEY, DIALOG_INTERACTION_SERVICE_DEFAULTS, DialogInteractionService, Dimension, DirectivesModule, DisposableComponent, EmptyStateComponent, EnterPlaceGuard, FocusBindingDirective, Formatter, InplaceInteractionContextComponent, InteractionContext, InteractionGuard, InteractionModule, InteractionOutletComponent, LEFT_RIGHT_PLACE_ANIMATION, LeavePlaceGuard, ListPlaceNavComponent, NavigationSession, NoopComponent, NumberInputComponent, ParameterDefinition, PasswordInputComponent, Place, PlaceComponent, PlaceDefinition, PlaceHistory, PlaceModule, PlaceOutletComponent, PlaceRouter, Point, ROUTE_PARAMETER_LIST_KEY, ResizeAwareComponent, RouteId, SelectInputComponent, StringInputComponent, TabbedPlaceNavigationComponent, Visit, VisitParameter, VisitParameterList, VisitSanitiser, leftRightPlaceAnimation, slideDownAndUpAnimation, DirectivesModule as ɵa, CommandDirective as ɵb, InteractionContext as ɵba, ActivityOutletComponent as ɵbb, ConfirmationDialogComponent as ɵbc, AbstractActivity as ɵbd, ACTIVITY_DATA as ɵbe, Activity as ɵbf, ConfirmThenDialogComponent as ɵbh, AlertDialogComponent as ɵbi, InteractionOutletComponent as ɵbk, InplaceInteractionContextComponent as ɵbl, DIALOG_INTERACTION_SERVICE_DEFAULTS as ɵbm, DialogInteractionService as ɵbn, FocusBindingDirective as ɵc, DisposableComponent as ɵd, ComponentsModule as ɵe, NumberInputComponent as ɵf, AbstractInputComponent as ɵg, StringInputComponent as ɵh, PasswordInputComponent as ɵi, SelectInputComponent as ɵj, NoopComponent as ɵk, PlaceModule as ɵl, EmptyStateComponent as ɵm, BusyOverlayComponent as ɵn, PlaceOutletComponent as ɵo, leftRightPlaceAnimation as ɵp, LEFT_RIGHT_PLACE_ANIMATION as ɵq, AUP_PLACE_CONFIG as ɵr, PlaceRouter as ɵt, PlaceHistory as ɵu, TabbedPlaceNavigationComponent as ɵv, AbstractPlaceNavigationComponent as ɵw, ListPlaceNavComponent as ɵx, InteractionModule as ɵy, ActivityContainerComponent as ɵz };
5434
+ export { ACTIVITY_DATA, AUP_PLACE_CONFIG, AbstractActivity, AbstractInputComponent, AbstractPlaceNavigationComponent, Activity, ActivityContainerComponent, ActivityOutletComponent, AlertDialogComponent, AngularUiPowerupsModule, Bounds, BusyOverlayComponent, CommandDirective, ComponentsModule, ConfirmThenDialogComponent, ConfirmationDialogComponent, DEFINITION_META_DATA_KEY, DIALOG_INTERACTION_SERVICE_DEFAULTS, DialogInteractionService, Dimension, DirectivesModule, DisposableComponent, EmptyStateComponent, EnterPlaceGuard, FocusBindingDirective, Formatter, InplaceInteractionContextComponent, InteractionContext, InteractionGuard, InteractionModule, InteractionOutletComponent, LEFT_RIGHT_PLACE_ANIMATION, LeavePlaceGuard, ListPlaceNavComponent, NavigationSession, NoopComponent, NumberInputComponent, ParameterDefinition, PasswordInputComponent, Place, PlaceComponent, PlaceDefinition, PlaceHistory, PlaceModule, PlaceOutletComponent, PlaceRouter, Point, ROUTE_PARAMETER_LIST_KEY, ResizeAwareComponent, RouteId, SelectInputComponent, StringInputComponent, TabbedPlaceNavigationComponent, Visit, VisitParameter, VisitParameterList, VisitSanitiser, leftRightPlaceAnimation, slideDownAndUpAnimation, DirectivesModule as ɵa, CommandDirective as ɵb, InteractionModule as ɵba, ActivityContainerComponent as ɵbb, ActivityOutletComponent as ɵbc, ConfirmationDialogComponent as ɵbd, AbstractActivity as ɵbe, ACTIVITY_DATA as ɵbf, Activity as ɵbg, ConfirmThenDialogComponent as ɵbi, AlertDialogComponent as ɵbj, InteractionOutletComponent as ɵbl, InplaceInteractionContextComponent as ɵbm, DIALOG_INTERACTION_SERVICE_DEFAULTS as ɵbn, DialogInteractionService as ɵbo, FocusBindingDirective as ɵc, DisposableComponent as ɵd, ComponentsModule as ɵe, NumberInputComponent as ɵf, AbstractInputComponent as ɵg, StringInputComponent as ɵh, PasswordInputComponent as ɵi, SelectInputComponent as ɵj, NoopComponent as ɵk, PlaceModule as ɵl, EmptyStateComponent as ɵm, BusyOverlayComponent as ɵn, PlaceOutletComponent as ɵo, leftRightPlaceAnimation as ɵp, LEFT_RIGHT_PLACE_ANIMATION as ɵq, AUP_PLACE_CONFIG as ɵr, PlaceRouter as ɵt, NavigationSession as ɵu, InteractionContext as ɵv, PlaceHistory as ɵw, TabbedPlaceNavigationComponent as ɵx, AbstractPlaceNavigationComponent as ɵy, ListPlaceNavComponent as ɵz };
5306
5435
  //# sourceMappingURL=coolon-angular-ui-powerups.js.map