Compare commits
183 Commits
4.4.5
...
5.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
cea02414b0 | |||
f0ec31e47f | |||
ff5c58be6b | |||
dca50deae4 | |||
7f2037f0b6 | |||
fd6ae571b8 | |||
b14250bef9 | |||
6fb5250185 | |||
2f9d8ff46d | |||
e54bd59f22 | |||
1e1833198d | |||
6f2038cc85 | |||
f0a55016af | |||
fcadbf4bf6 | |||
d9d00bd9b5 | |||
f69561b2de | |||
685cc26ab2 | |||
5b7432b6ea | |||
04b18a9f46 | |||
05472cb21b | |||
c0c03dc4ba | |||
f9f8924c49 | |||
10897d6473 | |||
340837aa46 | |||
42ef1be75c | |||
a5801b6020 | |||
70b62949de | |||
36161d99f6 | |||
0714139e37 | |||
bcb36d9b6d | |||
ca695e0632 | |||
9b015a95eb | |||
939dc44391 | |||
5651e4ac72 | |||
1dca575701 | |||
333a708bb6 | |||
3a227a1f6f | |||
81cb5bc3a7 | |||
1640d2aa0b | |||
5f501c722b | |||
ea07856cc5 | |||
7c47b62a96 | |||
e25b3dd163 | |||
6a88659c9a | |||
44ae6e94e3 | |||
1635a06bda | |||
3923c30df0 | |||
99017bf3ff | |||
4d117faf1a | |||
5cc9913ded | |||
1d09838622 | |||
9adf40aa77 | |||
89c616199f | |||
1e1af7ffcb | |||
a84b2bc945 | |||
7abcb99d57 | |||
49cd8513e4 | |||
82b067fc40 | |||
9479a106bb | |||
e64b54b67b | |||
cc2a4c41f9 | |||
a11542a375 | |||
b6c4af6495 | |||
67dff7bd5d | |||
381471d338 | |||
ebef5e697a | |||
d71ae278ef | |||
46207538ef | |||
71eb7437b6 | |||
b5ffbe342b | |||
0f79223008 | |||
a085223331 | |||
c383048259 | |||
b18eb04b46 | |||
c8c2ab012a | |||
ecff8e6c93 | |||
51f1da1b85 | |||
a5e18c4cdf | |||
cf6284656f | |||
3182ddaf3e | |||
416ed691e5 | |||
0fb7484d51 | |||
6a3454e81e | |||
c3fbe87012 | |||
24117d7a49 | |||
5808153359 | |||
9030c8a03e | |||
b14fc06fa2 | |||
a7f2468184 | |||
fae47d86b3 | |||
d20ac14fe2 | |||
cae3e6dca0 | |||
086f4aa72c | |||
82923a381d | |||
5152abb037 | |||
67f7032321 | |||
205abe8140 | |||
b582e2b311 | |||
91ab39cc55 | |||
38ec05f533 | |||
b3085e96c2 | |||
4cea2bd612 | |||
ce47546188 | |||
6279e50d78 | |||
8bcb268140 | |||
6fc5940959 | |||
0317c4c478 | |||
b7a6f52d59 | |||
7ae7573bc8 | |||
abee785821 | |||
619e625ee2 | |||
a6c635e69e | |||
e0a9625e46 | |||
fd0cc01eed | |||
1bfc77bf8c | |||
a094769bca | |||
b4c98305da | |||
a3a54299af | |||
15a3e2d307 | |||
54e0244954 | |||
43c33d5663 | |||
6d7799fce9 | |||
d31dc7b2b3 | |||
4cd4f7a208 | |||
72fe45db2b | |||
8d2819121b | |||
073e8ba2f2 | |||
5d1864fe68 | |||
eaa843b55f | |||
c6cf678a07 | |||
31cb418370 | |||
8de44cf5e3 | |||
c67bad4f43 | |||
410f21c75c | |||
54ea5b6ffd | |||
0af03beaed | |||
d71fa734f5 | |||
6f45519d6f | |||
65c9e13105 | |||
9208f0beea | |||
5344be5182 | |||
5db6f38b73 | |||
d22f8f54db | |||
23146c9201 | |||
a5205c686e | |||
807648251f | |||
5c62e300e1 | |||
256bc8acdd | |||
59c23c7bd7 | |||
e03adb9edd | |||
b399cb26d9 | |||
3b588fe2b0 | |||
95635c18c7 | |||
e20cfe1bbc | |||
eb6fb5f87e | |||
ad3029e786 | |||
2a2fe11e8d | |||
7d0f2cd51e | |||
36faba1aab | |||
92179bcc64 | |||
cdb069ab0e | |||
c453b7bcfa | |||
9d97163c64 | |||
f054c8360b | |||
758848961e | |||
99b666614d | |||
3f331b53b2 | |||
375d598a9f | |||
cd67fced1c | |||
a77cf7ee37 | |||
2150b45954 | |||
9f99f4fae2 | |||
c6ad212a98 | |||
47b3ecd9a3 | |||
8c81c62d46 | |||
7e72317059 | |||
0bb8423df9 | |||
95698d93ad | |||
c649da9f0a | |||
0bf0c35bca | |||
97e6901ded | |||
30e76fcd80 | |||
44b50427d9 |
@ -11,7 +11,7 @@
|
|||||||
anchor_1: &job_defaults
|
anchor_1: &job_defaults
|
||||||
working_directory: ~/ng
|
working_directory: ~/ng
|
||||||
docker:
|
docker:
|
||||||
- image: angular/ngcontainer:0.0.2
|
- image: angular/ngcontainer
|
||||||
|
|
||||||
# After checkout, rebase on top of master.
|
# After checkout, rebase on top of master.
|
||||||
# Similar to travis behavior, but not quite the same.
|
# Similar to travis behavior, but not quite the same.
|
||||||
@ -27,9 +27,10 @@ jobs:
|
|||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
|
||||||
|
|
||||||
- run: yarn install --freeze-lockfile --non-interactive
|
- run: npm install
|
||||||
|
- run: npm run postinstall
|
||||||
- run: ./node_modules/.bin/gulp lint
|
- run: ./node_modules/.bin/gulp lint
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@ -38,12 +39,12 @@ jobs:
|
|||||||
- checkout:
|
- checkout:
|
||||||
<<: *post_checkout
|
<<: *post_checkout
|
||||||
- restore_cache:
|
- restore_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
|
||||||
|
|
||||||
- run: bazel run @yarn//:yarn
|
- run: bazel run @build_bazel_rules_typescript_node//:bin/npm install
|
||||||
- run: bazel build ...
|
- run: bazel build packages/...
|
||||||
- save_cache:
|
- save_cache:
|
||||||
key: angular-{{ .Branch }}-{{ checksum "yarn.lock" }}
|
key: angular-{{ .Branch }}-{{ checksum "npm-shrinkwrap.json" }}
|
||||||
paths:
|
paths:
|
||||||
- "node_modules"
|
- "node_modules"
|
||||||
|
|
||||||
|
@ -69,8 +69,8 @@ groups:
|
|||||||
- "*.lock"
|
- "*.lock"
|
||||||
- "tools/*"
|
- "tools/*"
|
||||||
exclude:
|
exclude:
|
||||||
- "tools/@angular/tsc-wrapped/*"
|
|
||||||
- "tools/public_api_guard/*"
|
- "tools/public_api_guard/*"
|
||||||
|
- "tools/ngc-wrapped/*"
|
||||||
- "aio/*"
|
- "aio/*"
|
||||||
users:
|
users:
|
||||||
- IgorMinar #primary
|
- IgorMinar #primary
|
||||||
@ -136,8 +136,9 @@ groups:
|
|||||||
compiler-cli:
|
compiler-cli:
|
||||||
conditions:
|
conditions:
|
||||||
files:
|
files:
|
||||||
- "tools/@angular/tsc-wrapped/*"
|
- "packages/tsc-wrapped/*"
|
||||||
- "packages/compiler-cli/*"
|
- "packages/compiler-cli/*"
|
||||||
|
- "tools/ngc-wrapped/*"
|
||||||
users:
|
users:
|
||||||
- alexeagle
|
- alexeagle
|
||||||
- chuckjaz
|
- chuckjaz
|
||||||
|
229
CHANGELOG.md
229
CHANGELOG.md
@ -1,129 +1,126 @@
|
|||||||
<a name="4.4.5"></a>
|
<a name="5.0.0-beta.3"></a>
|
||||||
## [4.4.5](https://github.com/angular/angular/compare/4.4.4...4.4.5) (2017-10-12)
|
# [5.0.0-beta.3](https://github.com/angular/angular/compare/5.0.0-beta.2...5.0.0-beta.3) (2017-08-09)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* reformat files from previous cherry-picks ([ccc25ee](https://github.com/angular/angular/commit/ccc25ee))
|
* **animations:** revert container/queried animations accordingly during cancel ([#18516](https://github.com/angular/angular/issues/18516)) ([c0c03dc](https://github.com/angular/angular/commit/c0c03dc))
|
||||||
* **aio:** downgrade yarn to 1.0.2 temporarily ([#19600](https://github.com/angular/angular/issues/19600)) ([d45e3aa](https://github.com/angular/angular/commit/d45e3aa))
|
* **animations:** support persisting dynamic styles within animation states ([#18468](https://github.com/angular/angular/issues/18468)) ([05472cb](https://github.com/angular/angular/commit/05472cb)), closes [#18423](https://github.com/angular/angular/issues/18423) [#17505](https://github.com/angular/angular/issues/17505)
|
||||||
* **aio:** fix SearchService to work with TypeScript 2.4 ([#19600](https://github.com/angular/angular/issues/19600)) ([cf4b4d5](https://github.com/angular/angular/commit/cf4b4d5))
|
* **benchpress:** compile cleanly with TS 2.4 ([#18455](https://github.com/angular/angular/issues/18455)) ([e25b3dd](https://github.com/angular/angular/commit/e25b3dd))
|
||||||
* **compiler:** `TestBed.overrideProvider` should keep imported `NgModule`s eager ([#19624](https://github.com/angular/angular/issues/19624)) ([734378c](https://github.com/angular/angular/commit/734378c))
|
* **common:** don't recreate view when context shape doesn't change ([#18277](https://github.com/angular/angular/issues/18277)) ([685cc26](https://github.com/angular/angular/commit/685cc26)), closes [#13407](https://github.com/angular/angular/issues/13407)
|
||||||
* **compiler:** correctly instantiate eager providers that are used via `Injector.get` ([#19558](https://github.com/angular/angular/issues/19558)) ([e292548](https://github.com/angular/angular/commit/e292548)), closes [#15501](https://github.com/angular/angular/issues/15501)
|
* **compiler:** cleanly compile with TypeScript 2.4 ([#18456](https://github.com/angular/angular/issues/18456)) ([7c47b62](https://github.com/angular/angular/commit/7c47b62))
|
||||||
* **compiler:** disallow references for select and index evaluation ([95f3b1d](https://github.com/angular/angular/commit/95f3b1d))
|
* **compiler:** ignore [@import](https://github.com/import) in multi-line css ([#18452](https://github.com/angular/angular/issues/18452)) ([1dca575](https://github.com/angular/angular/commit/1dca575)), closes [#18038](https://github.com/angular/angular/issues/18038)
|
||||||
* **core:** make dynamic & inline code checking behave the same ([#19189](https://github.com/angular/angular/issues/19189)) ([6c66031](https://github.com/angular/angular/commit/6c66031))
|
* **compiler-cli:** disable buggy expression lowering ([#18513](https://github.com/angular/angular/issues/18513)) ([ca695e0](https://github.com/angular/angular/commit/ca695e0))
|
||||||
* **platform-browser:** support customEqualityTesters when overriding Jasmine toEqual ([cc8ae32](https://github.com/angular/angular/commit/cc8ae32))
|
* **compiler-cli:** fix and re-enable expression lowering ([#18570](https://github.com/angular/angular/issues/18570)) ([6f2038c](https://github.com/angular/angular/commit/6f2038c)), closes [#18388](https://github.com/angular/angular/issues/18388)
|
||||||
* **tsc-wrapped:** don't rewrite imports when annotating for closure ([#19579](https://github.com/angular/angular/issues/19579)) ([c9f8718](https://github.com/angular/angular/commit/c9f8718))
|
* **compiler-cli:** modified ngc to throw all errors, not just syntax ([#18388](https://github.com/angular/angular/issues/18388)) ([5651e4a](https://github.com/angular/angular/commit/5651e4a))
|
||||||
|
* **compiler-cli:** remove minimist dependency of compiler-cli/index ([#18532](https://github.com/angular/angular/issues/18532)) ([5b7432b](https://github.com/angular/angular/commit/5b7432b))
|
||||||
|
* **core:** fix platform-browser-dynamic ([#18576](https://github.com/angular/angular/issues/18576)) ([f0a5501](https://github.com/angular/angular/commit/f0a5501))
|
||||||
|
* **core:** forbid destroyed views to be inserted or moved in VC ([#18568](https://github.com/angular/angular/issues/18568)) ([e54bd59](https://github.com/angular/angular/commit/e54bd59)), closes [#17780](https://github.com/angular/angular/issues/17780)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **core:** Create StaticInjector which does not depend on Reflect polyfill. ([d9d00bd](https://github.com/angular/angular/commit/d9d00bd))
|
||||||
|
* **forms:** add default updateOn values for groups and arrays ([#18536](https://github.com/angular/angular/issues/18536)) ([ff5c58b](https://github.com/angular/angular/commit/ff5c58b))
|
||||||
|
* **forms:** add updateOn blur option to FormControls ([#18408](https://github.com/angular/angular/issues/18408)) ([333a708](https://github.com/angular/angular/commit/333a708)), closes [#7113](https://github.com/angular/angular/issues/7113)
|
||||||
|
* **forms:** add updateOn submit option to FormControls ([#18514](https://github.com/angular/angular/issues/18514)) ([f69561b](https://github.com/angular/angular/commit/f69561b))
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* switch angular to use StaticInjector instead of ReflectiveInjector ([fcadbf4](https://github.com/angular/angular/commit/fcadbf4)), closes [#18496](https://github.com/angular/angular/issues/18496)
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
<a name="4.4.4"></a>
|
* `platformXXXX()` no longer accepts providers which depend on reflection.
|
||||||
## [4.4.4](https://github.com/angular/angular/compare/4.4.3...4.4.4) (2017-09-28)
|
Specifically the method signature when from `Provider[]` to
|
||||||
|
`StaticProvider[]`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
Before:
|
||||||
|
```
|
||||||
|
[
|
||||||
|
MyClass,
|
||||||
|
{provide: ClassA, useClass: SubClassA}
|
||||||
|
]
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
After:
|
||||||
|
```
|
||||||
|
[
|
||||||
|
{provide: MyClass, deps: [Dep1,...]},
|
||||||
|
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
NOTE: This only applies to platform creation and providers for the JIT
|
||||||
|
compiler. It does not apply to `@Component` or `@NgModule` provides
|
||||||
|
declarations.
|
||||||
|
|
||||||
|
Benchpress note: Previously Benchpress also supported reflective
|
||||||
|
provides, which now require static providers.
|
||||||
|
|
||||||
|
DEPRECATION:
|
||||||
|
|
||||||
|
- `ReflectiveInjector` is now deprecated as it will be remove. Use
|
||||||
|
`Injector.create` as a replacement.
|
||||||
|
|
||||||
|
<a name="5.0.0-beta.2"></a>
|
||||||
|
# [5.0.0-beta.2](https://github.com/angular/angular/compare/5.0.0-beta.1...5.0.0-beta.2) (2017-08-02)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **animations:** support negative query limit value ([#19419](https://github.com/angular/angular/issues/19419)) ([bc81fbd](https://github.com/angular/angular/commit/bc81fbd)), closes [#19232](https://github.com/angular/angular/issues/19232)
|
* **compiler:** do not consider arguments when determining recursion ([e64b54b](https://github.com/angular/angular/commit/e64b54b))
|
||||||
* **compiler:** correctly map error message locations ([#19424](https://github.com/angular/angular/issues/19424)) ([c3b39ba](https://github.com/angular/angular/commit/c3b39ba))
|
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([381471d](https://github.com/angular/angular/commit/381471d)), closes [#18314](https://github.com/angular/angular/issues/18314)
|
||||||
* **compiler:** do not consider a reference with members as a reference ([#19466](https://github.com/angular/angular/issues/19466)) ([7fc2dce](https://github.com/angular/angular/commit/7fc2dce))
|
|
||||||
* **compiler:** skip when trimming / removing whitespaces ([#19310](https://github.com/angular/angular/issues/19310)) ([c7aa8a1](https://github.com/angular/angular/commit/c7aa8a1)), closes [#19304](https://github.com/angular/angular/issues/19304)
|
|
||||||
* **tsc-wrapped:** add metadata for `type` declarations ([#19040](https://github.com/angular/angular/issues/19040)) ([ae52851](https://github.com/angular/angular/commit/ae52851))
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.4.3"></a>
|
|
||||||
## [4.4.3](https://github.com/angular/angular/compare/4.4.2...4.4.3) (2017-09-19)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **tsc-wrapped:** deduplicate metadata only when the module is the same ([#19261](https://github.com/angular/angular/issues/19261)) ([0371538](https://github.com/angular/angular/commit/0371538)), closes [#19219](https://github.com/angular/angular/issues/19219)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.4.2"></a>
|
|
||||||
## [4.4.2](https://github.com/angular/angular/compare/4.4.1...4.4.2) (2017-09-18)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **platform-server**: fix for packaging issues [#19250](https://github.com/angular/angular/issues/19250)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.4.1"></a>
|
|
||||||
# [4.4.1](https://github.com/angular/angular/compare/4.3.6...4.4.1) (2017-09-15)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **animations:** do not leak DOM nodes/styling for host triggered animations ([#18853](https://github.com/angular/angular/issues/18853)) ([1cc3fe2](https://github.com/angular/angular/commit/1cc3fe2)), closes [#18606](https://github.com/angular/angular/issues/18606)
|
|
||||||
* **common:** fix improper packaging for [@angular](https://github.com/angular)/common/http ([#18613](https://github.com/angular/angular/issues/18613)) ([a203a95](https://github.com/angular/angular/commit/a203a95))
|
|
||||||
* **common:** fix XSSI prefix stripping by using JSON.parse always ([#18466](https://github.com/angular/angular/issues/18466)) ([8821723](https://github.com/angular/angular/commit/8821723)), closes [#18396](https://github.com/angular/angular/issues/18396) [#18453](https://github.com/angular/angular/issues/18453)
|
|
||||||
* **compiler:** normalize the locale name ([#18963](https://github.com/angular/angular/issues/18963)) ([497e017](https://github.com/angular/angular/commit/497e017))
|
|
||||||
* **core:** complete EventEmitter in QueryList on component destroy ([#18902](https://github.com/angular/angular/issues/18902)) ([7d137d7](https://github.com/angular/angular/commit/7d137d7)), closes [#18741](https://github.com/angular/angular/issues/18741)
|
|
||||||
* **tsc-wrapped:** deduplicate metadata for re-exported modules ([48ae1a6](https://github.com/angular/angular/commit/48ae1a6))
|
|
||||||
* **tsc-wrapped:** fix metadata symbol reference ([f6a7183](https://github.com/angular/angular/commit/f6a7183))
|
|
||||||
* **upgrade:** remove code setting id attribute. ([#19182](https://github.com/angular/angular/issues/19182)) ([b20c5d2](https://github.com/angular/angular/commit/b20c5d2)), closes [#18446](https://github.com/angular/angular/issues/18446)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* **compiler:** allow multiple exportAs names ([#18723](https://github.com/angular/angular/issues/18723)) ([7ec28fe](https://github.com/angular/angular/commit/7ec28fe))
|
* **forms:** add options arg to abstract controls ([ebef5e6](https://github.com/angular/angular/commit/ebef5e6))
|
||||||
* **core:** add option to remove blank text nodes from compiled templates ([#18823](https://github.com/angular/angular/issues/18823)) ([b8b551c](https://github.com/angular/angular/commit/b8b551c))
|
* **router:** add events tracking activation of individual routes ([49cd851](https://github.com/angular/angular/commit/49cd851))
|
||||||
|
|
||||||
|
|
||||||
Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1 instead. oops :-)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.3.6"></a>
|
|
||||||
## [4.3.6](https://github.com/angular/angular/compare/4.3.5...4.3.6) (2017-08-23)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **animations:** ensure animations are disabled on the element containing the @.disabled flag ([#18714](https://github.com/angular/angular/issues/18714)) ([5d68c83](https://github.com/angular/angular/commit/5d68c83))
|
|
||||||
* **animations:** make sure @.disabled respects disabled parent/sub animation sequences ([#18715](https://github.com/angular/angular/issues/18715)) ([c3dcbf9](https://github.com/angular/angular/commit/c3dcbf9))
|
|
||||||
* **animations:** make sure animation cancellations respect AUTO style values ([#18787](https://github.com/angular/angular/issues/18787)) ([9a754f9](https://github.com/angular/angular/commit/9a754f9)), closes [#17450](https://github.com/angular/angular/issues/17450)
|
|
||||||
* **animations:** resolve error when using AnimationBuilder with platform-server ([#18642](https://github.com/angular/angular/issues/18642)) ([f9b2905](https://github.com/angular/angular/commit/f9b2905)), closes [#18635](https://github.com/angular/angular/issues/18635)
|
|
||||||
* **animations:** restore auto-style support for removed DOM nodes ([#18787](https://github.com/angular/angular/issues/18787)) ([e1f45a3](https://github.com/angular/angular/commit/e1f45a3))
|
|
||||||
* **core:** correct order in ContentChildren query result ([#18326](https://github.com/angular/angular/issues/18326)) ([fec3b1a](https://github.com/angular/angular/commit/fec3b1a)), closes [#16568](https://github.com/angular/angular/issues/16568)
|
|
||||||
* **core:** make sure onStable runs in the right zone ([#18706](https://github.com/angular/angular/issues/18706)) ([ee5591d](https://github.com/angular/angular/commit/ee5591d))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* **animations:** allow @.disabled property to work without an expression ([#18713](https://github.com/angular/angular/issues/18713)) ([ac58914](https://github.com/angular/angular/commit/ac58914))
|
|
||||||
* **common:** add an empty DeprecatedI18NPipesModule module ([793f31b](https://github.com/angular/angular/commit/793f31b))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.3.5"></a>
|
|
||||||
## [4.3.5](https://github.com/angular/angular/compare/4.3.4...4.3.5) (2017-08-16)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **core:** forbid destroyed views to be inserted or moved in VC ([972538b](https://github.com/angular/angular/commit/972538b)), closes [#18615](https://github.com/angular/angular/issues/18615)
|
|
||||||
* **forms:** re-assigning options should not clear select ([a1624f2](https://github.com/angular/angular/commit/a1624f2)), closes [#18330](https://github.com/angular/angular/issues/18330)
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.3.4"></a>
|
|
||||||
## [4.3.4](https://github.com/angular/angular/compare/4.3.3...4.3.4) (2017-08-10)
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* **animations:** revert container/queried animations accordingly during cancel ([#18516](https://github.com/angular/angular/issues/18516)) ([5a165eb](https://github.com/angular/angular/commit/5a165eb))
|
|
||||||
* **animations:** support persisting dynamic styles within animation states ([#18468](https://github.com/angular/angular/issues/18468)) ([e0660b1](https://github.com/angular/angular/commit/e0660b1)), closes [#18423](https://github.com/angular/angular/issues/18423) [#17505](https://github.com/angular/angular/issues/17505)
|
|
||||||
* **benchpress:** compile cleanly with TS 2.4 ([#18455](https://github.com/angular/angular/issues/18455)) ([5afc7ab](https://github.com/angular/angular/commit/5afc7ab))
|
|
||||||
* **compiler:** cleanly compile with TypeScript 2.4 ([#18456](https://github.com/angular/angular/issues/18456)) ([5e4054b](https://github.com/angular/angular/commit/5e4054b))
|
|
||||||
* **compiler:** ignore [@import](https://github.com/import) in multi-line css ([#18452](https://github.com/angular/angular/issues/18452)) ([e7e7622](https://github.com/angular/angular/commit/e7e7622)), closes [#18038](https://github.com/angular/angular/issues/18038)
|
|
||||||
|
|
||||||
<a name="4.3.3"></a>
|
<a name="4.3.3"></a>
|
||||||
## [4.3.3](https://github.com/angular/angular/compare/4.3.2...4.3.3) (2017-08-02)
|
## [4.3.3](https://github.com/angular/angular/compare/4.3.2...4.3.3) (2017-08-02)
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([f5cbc2e](https://github.com/angular/angular/commit/f5cbc2e)), closes [#18314](https://github.com/angular/angular/issues/18314)
|
* **compiler:** fix for element needing implicit parent placed in top-level ng-container ([f5cbc2e](https://github.com/angular/angular/commit/f5cbc2e)), closes [#18314](https://github.com/angular/angular/issues/18314)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.0.0-beta.1"></a>
|
||||||
|
# [5.0.0-beta.1](https://github.com/angular/angular/compare/5.0.0-beta.0...5.0.0-beta.1) (2017-07-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** export BrowserModule as apart of BrowserAnimationsModule ([#18263](https://github.com/angular/angular/issues/18263)) ([fd0cc01](https://github.com/angular/angular/commit/fd0cc01))
|
||||||
|
* **compiler:** add equiv & disp attributes to Xliff2 ICU placeholders ([#18283](https://github.com/angular/angular/issues/18283)) ([38ec05f](https://github.com/angular/angular/commit/38ec05f)), closes [#17344](https://github.com/angular/angular/issues/17344)
|
||||||
|
* **compiler:** allow numbers for ICU message cases in lexer ([#18095](https://github.com/angular/angular/issues/18095)) ([a3a5429](https://github.com/angular/angular/commit/a3a5429)), closes [#17799](https://github.com/angular/angular/issues/17799)
|
||||||
|
* **core:** invoke error handler outside of the Angular Zone ([#18269](https://github.com/angular/angular/issues/18269)) ([7ae7573](https://github.com/angular/angular/commit/7ae7573)), closes [#17073](https://github.com/angular/angular/issues/17073) [#7774](https://github.com/angular/angular/issues/7774)
|
||||||
|
* **platform-server:** don't clobber parse5 properties when setting ([#18237](https://github.com/angular/angular/issues/18237)) ([a094769](https://github.com/angular/angular/commit/a094769)), closes [#17050](https://github.com/angular/angular/issues/17050)
|
||||||
|
* **router:** child CanActivate guard should wait for parent to complete ([#18110](https://github.com/angular/angular/issues/18110)) ([086f4aa](https://github.com/angular/angular/commit/086f4aa)), closes [#15670](https://github.com/angular/angular/issues/15670)
|
||||||
|
* **router:** should throw when lazy loaded module doesn't define any routes ([#15001](https://github.com/angular/angular/issues/15001)) ([82923a3](https://github.com/angular/angular/commit/82923a3)), closes [#14596](https://github.com/angular/angular/issues/14596)
|
||||||
|
* **upgrade:** ensure downgraded components are created in the Angular zone ([#18209](https://github.com/angular/angular/issues/18209)) ([43c33d5](https://github.com/angular/angular/commit/43c33d5))
|
||||||
|
* **upgrade:** throw error if trying to get injector before setting ([#18209](https://github.com/angular/angular/issues/18209)) ([d31dc7b](https://github.com/angular/angular/commit/d31dc7b))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **compiler:** add representation of placeholders to xliff & xmb ([b3085e9](https://github.com/angular/angular/commit/b3085e9)), closes [#17345](https://github.com/angular/angular/issues/17345)
|
||||||
|
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* latest tsickle to tree shake: abstract class methods & interfaces ([#18236](https://github.com/angular/angular/issues/18236)) ([b7a6f52](https://github.com/angular/angular/commit/b7a6f52))
|
||||||
|
* **core:** use native addEventListener for faster rendering. ([#18107](https://github.com/angular/angular/issues/18107)) ([6279e50](https://github.com/angular/angular/commit/6279e50))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.3.2"></a>
|
<a name="4.3.2"></a>
|
||||||
## [4.3.2](https://github.com/angular/angular/compare/4.3.1...4.3.2) (2017-07-26)
|
## [4.3.2](https://github.com/angular/angular/compare/4.3.1...4.3.2) (2017-07-26)
|
||||||
|
|
||||||
@ -141,6 +138,35 @@ Note: the 4.4.0 release on npm accidentally glitched-out midway, so we cut 4.4.1
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="5.0.0-beta.0"></a>
|
||||||
|
# [5.0.0-beta.0](https://github.com/angular/angular/compare/4.3.0...5.0.0-beta.0) (2017-07-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **animations:** always camelcase style property names that contain auto styles ([d22f8f5](https://github.com/angular/angular/commit/d22f8f5)), closes [#17938](https://github.com/angular/angular/issues/17938)
|
||||||
|
* **animations:** capture cancelled animation styles within grouped animations ([23146c9](https://github.com/angular/angular/commit/23146c9)), closes [#17170](https://github.com/angular/angular/issues/17170)
|
||||||
|
* **animations:** do not crash animations if a nested component fires CD during CD ([5db6f38](https://github.com/angular/angular/commit/5db6f38)), closes [#18193](https://github.com/angular/angular/issues/18193)
|
||||||
|
* **animations:** make sure @.disabled works in non-animation components ([5344be5](https://github.com/angular/angular/commit/5344be5))
|
||||||
|
* **common:** send flushed body as error instead of null ([5c62e30](https://github.com/angular/angular/commit/5c62e30)), closes [#18181](https://github.com/angular/angular/issues/18181)
|
||||||
|
* **compiler:** ensure jit external id arguments names are unique ([95635c1](https://github.com/angular/angular/commit/95635c1))
|
||||||
|
* **compiler-cli:** don't generate empty <target/> when extracting xliff ([65c9e13](https://github.com/angular/angular/commit/65c9e13)), closes [#15754](https://github.com/angular/angular/issues/15754)
|
||||||
|
* **platform-server:** provide XhrFactory for HttpClient ([8076482](https://github.com/angular/angular/commit/8076482))
|
||||||
|
* **router:** canDeactivate guards should run from bottom to top ([e20cfe1](https://github.com/angular/angular/commit/e20cfe1)), closes [#15657](https://github.com/angular/angular/issues/15657)
|
||||||
|
* **router:** should navigate to the same url when config changes ([eb6fb5f](https://github.com/angular/angular/commit/eb6fb5f)), closes [#15535](https://github.com/angular/angular/issues/15535)
|
||||||
|
* **router:** should run resolvers for the same route concurrently ([ad3029e](https://github.com/angular/angular/commit/ad3029e)), closes [#14279](https://github.com/angular/angular/issues/14279)
|
||||||
|
* **router:** terminal route in custom matcher ([b399cb2](https://github.com/angular/angular/commit/b399cb2))
|
||||||
|
* **upgrade:** allow accessing AngularJS injector from downgraded module ([a5205c6](https://github.com/angular/angular/commit/a5205c6))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **animations:** support :increment and :decrement transition aliases ([6f45519](https://github.com/angular/angular/commit/6f45519))
|
||||||
|
* **upgrade:** propagate touched state of NgModelController ([59c23c7](https://github.com/angular/angular/commit/59c23c7))
|
||||||
|
* **upgrade:** support lazy-loading Angular module into AngularJS app ([30e76fc](https://github.com/angular/angular/commit/30e76fc))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="4.3.1"></a>
|
<a name="4.3.1"></a>
|
||||||
## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19)
|
## [4.3.1](https://github.com/angular/angular/compare/4.3.0...4.3.1) (2017-07-19)
|
||||||
|
|
||||||
@ -1212,6 +1238,7 @@ templates is unaffected. We expect no or little impact on apps from this change,
|
|||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
|
* **aio:** add initial angular-cli scaffold ([#14118](https://github.com/angular/angular/issues/14118)) ([e130bc1](https://github.com/angular/angular/commit/e130bc1))
|
||||||
* **common:** rename underlying `NgFor` class and add a type parameter ([#14104](https://github.com/angular/angular/issues/14104)) ([86b2b25](https://github.com/angular/angular/commit/86b2b25))
|
* **common:** rename underlying `NgFor` class and add a type parameter ([#14104](https://github.com/angular/angular/issues/14104)) ([86b2b25](https://github.com/angular/angular/commit/86b2b25))
|
||||||
* **compiler:** allow missing translations ([#14113](https://github.com/angular/angular/issues/14113)) ([8775ab9](https://github.com/angular/angular/commit/8775ab9)), closes [#13861](https://github.com/angular/angular/issues/13861)
|
* **compiler:** allow missing translations ([#14113](https://github.com/angular/angular/issues/14113)) ([8775ab9](https://github.com/angular/angular/commit/8775ab9)), closes [#13861](https://github.com/angular/angular/issues/13861)
|
||||||
* **compiler:** do not parse xtb messages not needed by angular ([#14111](https://github.com/angular/angular/issues/14111)) ([f7fba74](https://github.com/angular/angular/commit/f7fba74)), closes [#14046](https://github.com/angular/angular/issues/14046)
|
* **compiler:** do not parse xtb messages not needed by angular ([#14111](https://github.com/angular/angular/issues/14111)) ([f7fba74](https://github.com/angular/angular/commit/f7fba74)), closes [#14046](https://github.com/angular/angular/issues/14046)
|
||||||
|
@ -13,11 +13,7 @@ You should run all these tasks from the `angular/aio` folder.
|
|||||||
Here are the most important tasks you might need to use:
|
Here are the most important tasks you might need to use:
|
||||||
|
|
||||||
* `yarn` - install all the dependencies.
|
* `yarn` - install all the dependencies.
|
||||||
* `yarn setup` - install all the dependencies, boilerplate, plunkers, zips and run dgeni on the docs.
|
* `yarn setup` - Install all the dependencies, boilerplate, plunkers, zips and runs dgeni on the docs.
|
||||||
* `yarn setup-local` - same as `setup`, but use the locally built Angular packages for aio and docs examples boilerplate.
|
|
||||||
|
|
||||||
* `yarn build` - create a production build of the application (after installing dependencies, boilerplate, etc).
|
|
||||||
* `yarn build-local` - same as `build`, but use `setup-local` instead of `setup`.
|
|
||||||
|
|
||||||
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
* `yarn start` - run a development web server that watches the files; then builds the doc-viewer and reloads the page, as necessary.
|
||||||
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
* `yarn serve-and-sync` - run both the `docs-watch` and `start` in the same console.
|
||||||
@ -30,33 +26,32 @@ Here are the most important tasks you might need to use:
|
|||||||
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
* `yarn docs-lint` - check that the doc gen code follows our style rules.
|
||||||
* `yarn docs-test` - run the unit tests for the doc generation code.
|
* `yarn docs-test` - run the unit tests for the doc generation code.
|
||||||
|
|
||||||
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally. Add the option `--local` to use your local version of Angular contained in the "dist" folder.
|
* `yarn boilerplate:add` - generate all the boilerplate code for the examples, so that they can be run locally.
|
||||||
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
* `yarn boilerplate:remove` - remove all the boilerplate code that was added via `yarn boilerplate:add`.
|
||||||
* `yarn generate-plunkers` - generate the plunker files that are used by the `live-example` tags in the docs.
|
* `yarn generate-plunkers` - generate the plunker files that are used by the `live-example` tags in the docs.
|
||||||
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
* `yarn generate-zips` - generate the zip files from the examples. Zip available via the `live-example` tags in the docs.
|
||||||
|
|
||||||
* `yarn example-e2e` - run all e2e tests for examples
|
* `yarn example-e2e` - run all e2e tests for examples
|
||||||
- `yarn example-e2e --setup` - force webdriver update & other setup, then run tests
|
- `yarn example-e2e -- --setup` - force webdriver update & other setup, then run tests
|
||||||
- `yarn example-e2e --filter=foo` - limit e2e tests to those containing the word "foo"
|
- `yarn example-e2e -- --filter=foo` - limit e2e tests to those containing the word "foo"
|
||||||
- `yarn example-e2e --setup --local` - run e2e tests with the local version of Angular contained in the "dist" folder
|
|
||||||
|
|
||||||
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
|
* `yarn build-ie-polyfills` - generates a js file of polyfills that can be loaded in Internet Explorer.
|
||||||
|
|
||||||
## Using ServiceWorker locally
|
## Using ServiceWorker locally
|
||||||
|
|
||||||
Since abb36e3cb, running `yarn start --prod` will no longer set up the ServiceWorker, which
|
Since abb36e3cb, running `yarn start -- --prod` will no longer set up the ServiceWorker, which
|
||||||
would require manually running `yarn sw-manifest` and `yarn sw-copy` (something that is not possible
|
would require manually running `yarn sw-manifest` and `yarn sw-copy` (something that is not possible
|
||||||
with webpack serving the files from memory).
|
with webpack serving the files from memory).
|
||||||
|
|
||||||
If you want to test ServiceWorker locally, you can use `yarn build` and serve the files in `dist/`
|
If you want to test ServiceWorker locally, you can use `yarn build` and serve the files in `dist/`
|
||||||
with `yarn http-server dist -p 4200`.
|
with `yarn http-server -- dist -p 4200`.
|
||||||
|
|
||||||
For more details see #16745.
|
For more details see #16745.
|
||||||
|
|
||||||
|
|
||||||
## Guide to authoring
|
## Guide to authoring
|
||||||
|
|
||||||
There are two types of content in the documentation:
|
There are two types of content in the documentatation:
|
||||||
|
|
||||||
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
* **API docs**: descriptions of the modules, classes, interfaces, decorators, etc that make up the Angular platform.
|
||||||
API docs are generated directly from the source code.
|
API docs are generated directly from the source code.
|
||||||
@ -111,16 +106,8 @@ yarn start
|
|||||||
yarn docs-watch
|
yarn docs-watch
|
||||||
```
|
```
|
||||||
|
|
||||||
>Alternatively, try the consolidated `serve-and-sync` command that builds, watches and serves in the same terminal window
|
|
||||||
```bash
|
|
||||||
yarn serve-and-sync
|
|
||||||
```
|
|
||||||
|
|
||||||
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
* Open a browser at https://localhost:4200/ and navigate to the document on which you want to work.
|
||||||
You can automatically open the browser by using `yarn start -o` in the first terminal.
|
You can automatically open the browser by using `yarn start -- -o` in the first terminal.
|
||||||
|
|
||||||
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
* Make changes to the page's associated doc or example files. Every time a file is saved, the doc will
|
||||||
be regenerated, the app will rebuild and the page will reload.
|
be regenerated, the app will rebuild and the page will reload.
|
||||||
|
|
||||||
* If you get a build error complaining about examples or any other odd behavior, be sure to consult
|
|
||||||
the [Authors Style Guide](https://angular.io/guide/docs-style-guide).
|
|
||||||
|
@ -156,7 +156,7 @@ RUN find $AIO_SCRIPTS_SH_DIR -maxdepth 1 -type f -printf "%P\n" \
|
|||||||
# Set up the Node.js scripts
|
# Set up the Node.js scripts
|
||||||
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
|
COPY scripts-js/ $AIO_SCRIPTS_JS_DIR/
|
||||||
WORKDIR $AIO_SCRIPTS_JS_DIR/
|
WORKDIR $AIO_SCRIPTS_JS_DIR/
|
||||||
RUN yarn install --production --freeze-lockfile
|
RUN yarn install --production
|
||||||
|
|
||||||
|
|
||||||
# Set up health check
|
# Set up health check
|
||||||
|
@ -6,7 +6,7 @@ server=8.8.4.4
|
|||||||
# Listen for DHCP and DNS requests only on this address.
|
# Listen for DHCP and DNS requests only on this address.
|
||||||
listen-address=127.0.0.1
|
listen-address=127.0.0.1
|
||||||
|
|
||||||
# Force an IP address for these domains.
|
# Force an IP addres for these domains.
|
||||||
address=/{{$AIO_NGINX_HOSTNAME}}/127.0.0.1
|
address=/{{$AIO_NGINX_HOSTNAME}}/127.0.0.1
|
||||||
address=/{{$AIO_UPLOAD_HOSTNAME}}/127.0.0.1
|
address=/{{$AIO_UPLOAD_HOSTNAME}}/127.0.0.1
|
||||||
address=/{{$TEST_AIO_NGINX_HOSTNAME}}/127.0.0.1
|
address=/{{$TEST_AIO_NGINX_HOSTNAME}}/127.0.0.1
|
||||||
|
@ -32,8 +32,7 @@ export class BuildCreator extends EventEmitter {
|
|||||||
then(() => Promise.all([this.exists(prDir), this.exists(shaDir)])).
|
then(() => Promise.all([this.exists(prDir), this.exists(shaDir)])).
|
||||||
then(([prDirExisted, shaDirExisted]) => {
|
then(([prDirExisted, shaDirExisted]) => {
|
||||||
if (shaDirExisted) {
|
if (shaDirExisted) {
|
||||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
throw new UploadError(409, `Request to overwrite existing directory: ${shaDir}`);
|
||||||
throw new UploadError(409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dirToRemoveOnError = prDirExisted ? shaDir : prDir;
|
dirToRemoveOnError = prDirExisted ? shaDir : prDir;
|
||||||
|
@ -13,8 +13,10 @@ const AIO_REPO_SLUG = getEnvVar('AIO_REPO_SLUG');
|
|||||||
const AIO_TRUSTED_PR_LABEL = getEnvVar('AIO_TRUSTED_PR_LABEL');
|
const AIO_TRUSTED_PR_LABEL = getEnvVar('AIO_TRUSTED_PR_LABEL');
|
||||||
const AIO_UPLOAD_HOSTNAME = getEnvVar('AIO_UPLOAD_HOSTNAME');
|
const AIO_UPLOAD_HOSTNAME = getEnvVar('AIO_UPLOAD_HOSTNAME');
|
||||||
const AIO_UPLOAD_PORT = +getEnvVar('AIO_UPLOAD_PORT');
|
const AIO_UPLOAD_PORT = +getEnvVar('AIO_UPLOAD_PORT');
|
||||||
|
const AIO_WWW_USER = getEnvVar('AIO_WWW_USER');
|
||||||
|
|
||||||
// Run
|
// Run
|
||||||
|
process.setuid(AIO_WWW_USER); // TODO(gkalpak): Find more suitable way to run as `www-data`.
|
||||||
_main();
|
_main();
|
||||||
|
|
||||||
// Functions
|
// Functions
|
||||||
|
@ -18,7 +18,7 @@ const TEST_AIO_UPLOAD_PORT = +getEnvVar('TEST_AIO_UPLOAD_PORT');
|
|||||||
const WWW_USER = getEnvVar('AIO_WWW_USER');
|
const WWW_USER = getEnvVar('AIO_WWW_USER');
|
||||||
|
|
||||||
// Interfaces - Types
|
// Interfaces - Types
|
||||||
export interface CmdResult { success: boolean; err: Error | null; stdout: string; stderr: string; }
|
export interface CmdResult { success: boolean; err: Error; stdout: string; stderr: string; }
|
||||||
export interface FileSpecs { content?: string; size?: number; }
|
export interface FileSpecs { content?: string; size?: number; }
|
||||||
|
|
||||||
export type CleanUpFn = () => void;
|
export type CleanUpFn = () => void;
|
||||||
@ -143,7 +143,7 @@ class Helper {
|
|||||||
statusText = status[1];
|
statusText = status[1];
|
||||||
} else {
|
} else {
|
||||||
statusCode = status;
|
statusCode = status;
|
||||||
statusText = http.STATUS_CODES[statusCode] || 'UNKNOWN_STATUS_CODE';
|
statusText = http.STATUS_CODES[statusCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (result: CmdResult) => {
|
return (result: CmdResult) => {
|
||||||
@ -196,7 +196,7 @@ class Helper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Methods - Protected
|
// Methods - Protected
|
||||||
protected createCleanUpFn(fn: () => void): CleanUpFn {
|
protected createCleanUpFn(fn: Function): CleanUpFn {
|
||||||
const cleanUpFn = () => {
|
const cleanUpFn = () => {
|
||||||
const idx = this.cleanUpFns.indexOf(cleanUpFn);
|
const idx = this.cleanUpFns.indexOf(cleanUpFn);
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
|
@ -110,7 +110,6 @@ describe('upload-server (on HTTP)', () => {
|
|||||||
const authorizationHeader2 = isPublic ?
|
const authorizationHeader2 = isPublic ?
|
||||||
authorizationHeader : `--header "Authorization: ${c.BV_verify_verifiedNotTrusted}"`;
|
authorizationHeader : `--header "Authorization: ${c.BV_verify_verifiedNotTrusted}"`;
|
||||||
const cmdPrefix = curl('', `${authorizationHeader2} ${xFileHeader}`);
|
const cmdPrefix = curl('', `${authorizationHeader2} ${xFileHeader}`);
|
||||||
const overwriteRe = RegExp(`^Request to overwrite existing ${isPublic ? 'public' : 'non-public'} directory`);
|
|
||||||
|
|
||||||
|
|
||||||
it('should not overwrite existing builds', done => {
|
it('should not overwrite existing builds', done => {
|
||||||
@ -121,7 +120,7 @@ describe('upload-server (on HTTP)', () => {
|
|||||||
expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content');
|
expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content');
|
||||||
|
|
||||||
h.runCmd(`${cmdPrefix} http://${host}/create-build/${pr}/${sha9}`).
|
h.runCmd(`${cmdPrefix} http://${host}/create-build/${pr}/${sha9}`).
|
||||||
then(h.verifyResponse(409, overwriteRe)).
|
then(h.verifyResponse(409, /^Request to overwrite existing directory/)).
|
||||||
then(() => expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content')).
|
then(() => expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content')).
|
||||||
then(done);
|
then(done);
|
||||||
});
|
});
|
||||||
@ -142,7 +141,7 @@ describe('upload-server (on HTTP)', () => {
|
|||||||
expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content');
|
expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content');
|
||||||
|
|
||||||
h.runCmd(`${cmdPrefix} http://${host}/create-build/${pr}/${sha9Almost}`).
|
h.runCmd(`${cmdPrefix} http://${host}/create-build/${pr}/${sha9Almost}`).
|
||||||
then(h.verifyResponse(409, overwriteRe)).
|
then(h.verifyResponse(409, /^Request to overwrite existing directory/)).
|
||||||
then(() => expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content')).
|
then(() => expect(h.readBuildFile(pr, sha9, 'index.html', isPublic)).toBe('My content')).
|
||||||
then(done);
|
then(done);
|
||||||
});
|
});
|
||||||
@ -311,7 +310,7 @@ describe('upload-server (on HTTP)', () => {
|
|||||||
expect(h.buildExists(pr, sha0, isPublic)).toBe(false);
|
expect(h.buildExists(pr, sha0, isPublic)).toBe(false);
|
||||||
|
|
||||||
uploadBuild(sha0).
|
uploadBuild(sha0).
|
||||||
then(h.verifyResponse(409, overwriteRe)).
|
then(h.verifyResponse(409, /^Request to overwrite existing directory/)).
|
||||||
then(() => {
|
then(() => {
|
||||||
checkPrVisibility(isPublic);
|
checkPrVisibility(isPublic);
|
||||||
expect(h.readBuildFile(pr, sha0, 'index.html', isPublic)).toContain(pr);
|
expect(h.readBuildFile(pr, sha0, 'index.html', isPublic)).toContain(pr);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"prebuild": "yarn clean-dist",
|
"prebuild": "yarn clean-dist",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build-watch": "yarn tsc --watch",
|
"build-watch": "yarn tsc -- --watch",
|
||||||
"clean-dist": "node --eval \"require('shelljs').rm('-rf', 'dist')\"",
|
"clean-dist": "node --eval \"require('shelljs').rm('-rf', 'dist')\"",
|
||||||
"dev": "concurrently --kill-others --raw --success first \"yarn build-watch\" \"yarn test-watch\"",
|
"dev": "concurrently --kill-others --raw --success first \"yarn build-watch\" \"yarn test-watch\"",
|
||||||
"lint": "tslint --project tsconfig.json",
|
"lint": "tslint --project tsconfig.json",
|
||||||
@ -20,26 +20,26 @@
|
|||||||
"test-watch": "nodemon --exec \"yarn ~~test-only\" --watch dist"
|
"test-watch": "nodemon --exec \"yarn ~~test-only\" --watch dist"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.18.2",
|
"body-parser": "^1.17.2",
|
||||||
"express": "^4.15.4",
|
"express": "^4.14.1",
|
||||||
"jasmine": "^2.8.0",
|
"jasmine": "^2.5.3",
|
||||||
"jsonwebtoken": "^8.0.1",
|
"jsonwebtoken": "^7.3.0",
|
||||||
"shelljs": "^0.7.8",
|
"shelljs": "^0.7.6"
|
||||||
"tslib": "^1.7.1"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/body-parser": "^1.16.5",
|
"@types/body-parser": "^1.16.4",
|
||||||
"@types/express": "^4.0.37",
|
"@types/express": "^4.0.35",
|
||||||
"@types/jasmine": "^2.6.0",
|
"@types/jasmine": "^2.5.43",
|
||||||
"@types/jsonwebtoken": "^7.2.3",
|
"@types/jsonwebtoken": "^7.2.0",
|
||||||
"@types/node": "^8.0.30",
|
"@types/node": "^7.0.5",
|
||||||
"@types/shelljs": "^0.7.4",
|
"@types/shelljs": "^0.7.0",
|
||||||
"@types/supertest": "^2.0.3",
|
"@types/supertest": "^2.0.0",
|
||||||
"concurrently": "^3.5.0",
|
"concurrently": "^3.3.0",
|
||||||
"nodemon": "^1.12.1",
|
"eslint": "^3.15.0",
|
||||||
|
"eslint-plugin-jasmine": "^2.2.0",
|
||||||
|
"nodemon": "^1.11.0",
|
||||||
"supertest": "^3.0.0",
|
"supertest": "^3.0.0",
|
||||||
"tslint": "^5.7.0",
|
"tslint": "^4.4.2",
|
||||||
"tslint-jasmine-noSkipOrFocus": "^1.0.8",
|
"typescript": "^2.1.6"
|
||||||
"typescript": "^2.5.2"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,8 @@ describe('BuildCleaner', () => {
|
|||||||
let cleanerGetExistingBuildNumbersSpy: jasmine.Spy;
|
let cleanerGetExistingBuildNumbersSpy: jasmine.Spy;
|
||||||
let cleanerGetOpenPrNumbersSpy: jasmine.Spy;
|
let cleanerGetOpenPrNumbersSpy: jasmine.Spy;
|
||||||
let cleanerRemoveUnnecessaryBuildsSpy: jasmine.Spy;
|
let cleanerRemoveUnnecessaryBuildsSpy: jasmine.Spy;
|
||||||
let existingBuildsDeferred: {resolve: (v?: any) => void, reject: (e?: any) => void};
|
let existingBuildsDeferred: {resolve: Function, reject: Function};
|
||||||
let openPrsDeferred: {resolve: (v?: any) => void, reject: (e?: any) => void};
|
let openPrsDeferred: {resolve: Function, reject: Function};
|
||||||
let promise: Promise<void>;
|
let promise: Promise<void>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -195,7 +195,7 @@ describe('BuildCleaner', () => {
|
|||||||
|
|
||||||
|
|
||||||
describe('getOpenPrNumbers()', () => {
|
describe('getOpenPrNumbers()', () => {
|
||||||
let prDeferred: {resolve: (v: any) => void, reject: (v: any) => void};
|
let prDeferred: {resolve: Function, reject: Function};
|
||||||
let promise: Promise<number[]>;
|
let promise: Promise<number[]>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -277,10 +277,7 @@ describe('BuildCleaner', () => {
|
|||||||
|
|
||||||
it('should catch errors and log them', () => {
|
it('should catch errors and log them', () => {
|
||||||
const consoleErrorSpy = spyOn(console, 'error');
|
const consoleErrorSpy = spyOn(console, 'error');
|
||||||
shellRmSpy.and.callFake(() => {
|
shellRmSpy.and.callFake(() => { throw 'Test'; });
|
||||||
// tslint:disable-next-line: no-string-throw
|
|
||||||
throw 'Test';
|
|
||||||
});
|
|
||||||
|
|
||||||
(cleaner as any).removeDir('/foo/bar');
|
(cleaner as any).removeDir('/foo/bar');
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ describe('GithubApi', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('should not pass data to \'request()\'', () => {
|
it('should not pass data to \'request()\'', () => {
|
||||||
(api.get as any)('foo', {}, {});
|
(api.get as Function)('foo', {}, {});
|
||||||
|
|
||||||
expect(apiRequestSpy).toHaveBeenCalled();
|
expect(apiRequestSpy).toHaveBeenCalled();
|
||||||
expect(apiRequestSpy.calls.argsFor(0)[2]).toBeUndefined();
|
expect(apiRequestSpy.calls.argsFor(0)[2]).toBeUndefined();
|
||||||
@ -144,7 +144,7 @@ describe('GithubApi', () => {
|
|||||||
|
|
||||||
|
|
||||||
describe('getPaginated()', () => {
|
describe('getPaginated()', () => {
|
||||||
let deferreds: {resolve: (v: any) => void, reject: (v: any) => void}[];
|
let deferreds: {resolve: Function, reject: Function}[];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
deferreds = [];
|
deferreds = [];
|
||||||
@ -292,7 +292,7 @@ describe('GithubApi', () => {
|
|||||||
|
|
||||||
|
|
||||||
describe('onResponse', () => {
|
describe('onResponse', () => {
|
||||||
let promise: Promise<object>;
|
let promise: Promise<Object>;
|
||||||
let respond: (statusCode: number) => IncomingMessage;
|
let respond: (statusCode: number) => IncomingMessage;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -22,7 +22,7 @@ describe('GithubPullRequests', () => {
|
|||||||
|
|
||||||
describe('addComment()', () => {
|
describe('addComment()', () => {
|
||||||
let prs: GithubPullRequests;
|
let prs: GithubPullRequests;
|
||||||
let deferred: {resolve: (v: any) => void, reject: (v: any) => void};
|
let deferred: {resolve: Function, reject: Function};
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
prs = new GithubPullRequests('12345', 'foo/bar');
|
prs = new GithubPullRequests('12345', 'foo/bar');
|
||||||
|
@ -153,8 +153,7 @@ describe('BuildCreator', () => {
|
|||||||
it('should abort and skip further operations if the build does already exist', done => {
|
it('should abort and skip further operations if the build does already exist', done => {
|
||||||
existsValues[shaDir] = true;
|
existsValues[shaDir] = true;
|
||||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
expectToBeUploadError(err, 409, `Request to overwrite existing directory: ${shaDir}`);
|
||||||
expectToBeUploadError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
|
||||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||||
@ -170,8 +169,7 @@ describe('BuildCreator', () => {
|
|||||||
expect(bcExistsSpy(shaDir)).toBe(false);
|
expect(bcExistsSpy(shaDir)).toBe(false);
|
||||||
|
|
||||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||||
const publicOrNot = isPublic ? 'public' : 'non-public';
|
expectToBeUploadError(err, 409, `Request to overwrite existing directory: ${shaDir}`);
|
||||||
expectToBeUploadError(err, 409, `Request to overwrite existing ${publicOrNot} directory: ${shaDir}`);
|
|
||||||
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
expect(shellMkdirSpy).not.toHaveBeenCalled();
|
||||||
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
expect(bcExtractArchiveSpy).not.toHaveBeenCalled();
|
||||||
expect(bcEmitSpy).not.toHaveBeenCalled();
|
expect(bcEmitSpy).not.toHaveBeenCalled();
|
||||||
@ -223,7 +221,6 @@ describe('BuildCreator', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('should reject with an UploadError', done => {
|
it('should reject with an UploadError', done => {
|
||||||
// tslint:disable-next-line: no-string-throw
|
|
||||||
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
|
shellMkdirSpy.and.callFake(() => { throw 'Test'; });
|
||||||
bc.create(pr, sha, archive, isPublic).catch(err => {
|
bc.create(pr, sha, archive, isPublic).catch(err => {
|
||||||
expectToBeUploadError(err, 500, `Error while uploading to directory: ${shaDir}\nTest`);
|
expectToBeUploadError(err, 500, `Error while uploading to directory: ${shaDir}\nTest`);
|
||||||
@ -408,7 +405,6 @@ describe('BuildCreator', () => {
|
|||||||
|
|
||||||
|
|
||||||
it('should reject with an UploadError', done => {
|
it('should reject with an UploadError', done => {
|
||||||
// tslint:disable-next-line: no-string-throw
|
|
||||||
shellMvSpy.and.callFake(() => { throw 'Test'; });
|
shellMvSpy.and.callFake(() => { throw 'Test'; });
|
||||||
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
bc.updatePrVisibility(pr, makePublic).catch(err => {
|
||||||
expectToBeUploadError(err, 500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
expectToBeUploadError(err, 500, `Error while making PR ${pr} ${makePublic ? 'public' : 'hidden'}.\nTest`);
|
||||||
@ -436,11 +432,11 @@ describe('BuildCreator', () => {
|
|||||||
|
|
||||||
describe('exists()', () => {
|
describe('exists()', () => {
|
||||||
let fsAccessSpy: jasmine.Spy;
|
let fsAccessSpy: jasmine.Spy;
|
||||||
let fsAccessCbs: ((v?: any) => void)[];
|
let fsAccessCbs: Function[];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fsAccessCbs = [];
|
fsAccessCbs = [];
|
||||||
fsAccessSpy = spyOn(fs, 'access').and.callFake((_: string, cb: (v?: any) => void) => fsAccessCbs.push(cb));
|
fsAccessSpy = spyOn(fs, 'access').and.callFake((_: string, cb: Function) => fsAccessCbs.push(cb));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -484,7 +480,7 @@ describe('BuildCreator', () => {
|
|||||||
let shellChmodSpy: jasmine.Spy;
|
let shellChmodSpy: jasmine.Spy;
|
||||||
let shellRmSpy: jasmine.Spy;
|
let shellRmSpy: jasmine.Spy;
|
||||||
let cpExecSpy: jasmine.Spy;
|
let cpExecSpy: jasmine.Spy;
|
||||||
let cpExecCbs: ((...args: any[]) => void)[];
|
let cpExecCbs: Function[];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cpExecCbs = [];
|
cpExecCbs = [];
|
||||||
@ -492,7 +488,7 @@ describe('BuildCreator', () => {
|
|||||||
consoleWarnSpy = spyOn(console, 'warn');
|
consoleWarnSpy = spyOn(console, 'warn');
|
||||||
shellChmodSpy = spyOn(shell, 'chmod');
|
shellChmodSpy = spyOn(shell, 'chmod');
|
||||||
shellRmSpy = spyOn(shell, 'rm');
|
shellRmSpy = spyOn(shell, 'rm');
|
||||||
cpExecSpy = spyOn(cp, 'exec').and.callFake((_: string, cb: (...args: any[]) => void) => cpExecCbs.push(cb));
|
cpExecSpy = spyOn(cp, 'exec').and.callFake((_: string, cb: Function) => cpExecCbs.push(cb));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -558,11 +554,7 @@ describe('BuildCreator', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
shellChmodSpy.and.callFake(() => {
|
shellChmodSpy.and.callFake(() => { throw 'Test'; });
|
||||||
// tslint:disable-next-line: no-string-throw
|
|
||||||
throw 'Test';
|
|
||||||
});
|
|
||||||
|
|
||||||
cpExecCbs[0]();
|
cpExecCbs[0]();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -575,11 +567,7 @@ describe('BuildCreator', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
|
|
||||||
shellRmSpy.and.callFake(() => {
|
shellRmSpy.and.callFake(() => { throw 'Test'; });
|
||||||
// tslint:disable-next-line: no-string-throw
|
|
||||||
throw 'Test';
|
|
||||||
});
|
|
||||||
|
|
||||||
cpExecCbs[0]();
|
cpExecCbs[0]();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ describe('uploadServerFactory', () => {
|
|||||||
|
|
||||||
it('should log the server address info on \'listening\'', () => {
|
it('should log the server address info on \'listening\'', () => {
|
||||||
const consoleInfoSpy = spyOn(console, 'info');
|
const consoleInfoSpy = spyOn(console, 'info');
|
||||||
const server = createUploadServer();
|
const server = createUploadServer('builds/dir');
|
||||||
server.address = () => ({address: 'foo', family: '', port: 1337});
|
server.address = () => ({address: 'foo', family: '', port: 1337});
|
||||||
|
|
||||||
expect(consoleInfoSpy).not.toHaveBeenCalled();
|
expect(consoleInfoSpy).not.toHaveBeenCalled();
|
||||||
|
@ -1,66 +1,25 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Basic Options */
|
"alwaysStrict": true,
|
||||||
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
|
"forceConsistentCasingInFileNames": true,
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"inlineSourceMap": true,
|
||||||
"lib": [
|
"lib": [
|
||||||
"es2015",
|
"es2016"
|
||||||
"es2016.array.include"
|
],
|
||||||
], /* Specify library files to be included in the compilation: */
|
"noImplicitAny": true,
|
||||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
"noImplicitReturns": true,
|
||||||
// "checkJs": true, /* Report errors in .js files. */
|
"noImplicitThis": true,
|
||||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
"noUnusedLocals": true,
|
||||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
"noUnusedParameters": true,
|
||||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
"outDir": "dist",
|
||||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
"pretty": true,
|
||||||
"outDir": "dist", /* Redirect output structure to the directory. */
|
"rootDir": ".",
|
||||||
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"skipLibCheck": true,
|
||||||
// "removeComments": true, /* Do not emit comments to output. */
|
"strictNullChecks": true,
|
||||||
// "noEmit": true, /* Do not emit outputs. */
|
"target": "es5",
|
||||||
"importHelpers": true, /* Import emit helpers from 'tslib'. */
|
|
||||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
|
||||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
|
||||||
|
|
||||||
/* Strict Type-Checking Options */
|
|
||||||
"strict": true, /* Enable all strict type-checking options. */
|
|
||||||
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
|
|
||||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
|
||||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
|
||||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
|
||||||
|
|
||||||
/* Additional Checks */
|
|
||||||
"noUnusedLocals": true, /* Report errors on unused locals. */
|
|
||||||
"noUnusedParameters": true, /* Report errors on unused parameters. */
|
|
||||||
"noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
|
||||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
|
||||||
|
|
||||||
/* Module Resolution Options */
|
|
||||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
|
||||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
|
||||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
|
||||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"node_modules/@types"
|
"node_modules/@types"
|
||||||
], /* List of folders to include type definitions from. */
|
]
|
||||||
// "types": [], /* Type declaration files to be included in compilation. */
|
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
|
||||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
|
||||||
|
|
||||||
/* Source Map Options */
|
|
||||||
// "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
|
||||||
// "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */
|
|
||||||
"inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
|
||||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
|
||||||
|
|
||||||
/* Experimental Options */
|
|
||||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
|
||||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
|
||||||
|
|
||||||
/* Other */
|
|
||||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
|
||||||
"newLine": "LF", /* Use the specified end of line sequence to be used when emitting files: "crlf" (windows) or "lf" (unix). */
|
|
||||||
"pretty": true, /* Stylize errors and messages using color and context. */
|
|
||||||
"skipLibCheck": true /* Skip type checking of all declaration files (*.d.ts). */
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"lib/**/*",
|
"lib/**/*",
|
||||||
|
@ -1,24 +1,15 @@
|
|||||||
{
|
{
|
||||||
"defaultSeverity": "error",
|
"extends": "tslint:recommended",
|
||||||
"extends": [
|
|
||||||
"tslint:recommended"
|
|
||||||
],
|
|
||||||
"jsRules": {},
|
|
||||||
"rules": {
|
"rules": {
|
||||||
"array-type": [true, "array"],
|
"array-type": [true, "array"],
|
||||||
"arrow-parens": [true, "ban-single-arg-parens"],
|
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||||
"interface-name": [true, "never-prefix"],
|
"interface-name": [true, "never-prefix"],
|
||||||
"max-classes-per-file": [true, 4],
|
"max-classes-per-file": [true, 4],
|
||||||
"no-consecutive-blank-lines": [true, 2],
|
"no-consecutive-blank-lines": [true, 2],
|
||||||
"no-console": [false],
|
"no-console": false,
|
||||||
"no-focused-test": true,
|
|
||||||
"no-namespace": [true, "allow-declarations"],
|
"no-namespace": [true, "allow-declarations"],
|
||||||
"no-skipped-test": true,
|
|
||||||
"no-string-literal": false,
|
"no-string-literal": false,
|
||||||
"quotemark": [true, "single"],
|
"quotemark": [true, "single"],
|
||||||
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"]
|
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore"]
|
||||||
},
|
}
|
||||||
"rulesDirectory": [
|
|
||||||
"node_modules/tslint-jasmine-noSkipOrFocus"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -6,9 +6,10 @@ export AIO_GITHUB_TOKEN=$(head -c -1 /aio-secrets/GITHUB_TOKEN 2>/dev/null || ec
|
|||||||
export AIO_PREVIEW_DEPLOYMENT_TOKEN=$(head -c -1 /aio-secrets/PREVIEW_DEPLOYMENT_TOKEN 2>/dev/null || echo "MISSING_PREVIEW_DEPLOYMENT_TOKEN")
|
export AIO_PREVIEW_DEPLOYMENT_TOKEN=$(head -c -1 /aio-secrets/PREVIEW_DEPLOYMENT_TOKEN 2>/dev/null || echo "MISSING_PREVIEW_DEPLOYMENT_TOKEN")
|
||||||
|
|
||||||
# Start the upload-server instance
|
# Start the upload-server instance
|
||||||
|
# TODO(gkalpak): Ideally, the upload server should be run as a non-privileged user.
|
||||||
|
# (Currently, there doesn't seem to be a straight forward way.)
|
||||||
action=$([ "$1" == "stop" ] && echo "stop" || echo "start")
|
action=$([ "$1" == "stop" ] && echo "stop" || echo "start")
|
||||||
pm2 $action $AIO_SCRIPTS_JS_DIR/dist/lib/upload-server \
|
pm2 $action $AIO_SCRIPTS_JS_DIR/dist/lib/upload-server \
|
||||||
--uid $AIO_WWW_USER \
|
|
||||||
--log /var/log/aio/upload-server-prod.log \
|
--log /var/log/aio/upload-server-prod.log \
|
||||||
--name aio-upload-server-prod \
|
--name aio-upload-server-prod \
|
||||||
${@:2}
|
${@:2}
|
||||||
|
@ -15,12 +15,13 @@ export AIO_GITHUB_TOKEN=$(head -c -1 /aio-secrets/TEST_GITHUB_TOKEN 2>/dev/null
|
|||||||
export AIO_PREVIEW_DEPLOYMENT_TOKEN=$(head -c -1 /aio-secrets/TEST_PREVIEW_DEPLOYMENT_TOKEN 2>/dev/null || echo "TEST_PREVIEW_DEPLOYMENT_TOKEN")
|
export AIO_PREVIEW_DEPLOYMENT_TOKEN=$(head -c -1 /aio-secrets/TEST_PREVIEW_DEPLOYMENT_TOKEN 2>/dev/null || echo "TEST_PREVIEW_DEPLOYMENT_TOKEN")
|
||||||
|
|
||||||
# Start the upload-server instance
|
# Start the upload-server instance
|
||||||
|
# TODO(gkalpak): Ideally, the upload server should be run as a non-privileged user.
|
||||||
|
# (Currently, there doesn't seem to be a straight forward way.)
|
||||||
appName=aio-upload-server-test
|
appName=aio-upload-server-test
|
||||||
if [[ "$1" == "stop" ]]; then
|
if [[ "$1" == "stop" ]]; then
|
||||||
pm2 delete $appName
|
pm2 delete $appName
|
||||||
else
|
else
|
||||||
pm2 start $AIO_SCRIPTS_JS_DIR/dist/lib/verify-setup/start-test-upload-server.js \
|
pm2 start $AIO_SCRIPTS_JS_DIR/dist/lib/verify-setup/start-test-upload-server.js \
|
||||||
--uid $AIO_WWW_USER \
|
|
||||||
--log /var/log/aio/upload-server-test.log \
|
--log /var/log/aio/upload-server-test.log \
|
||||||
--name $appName \
|
--name $appName \
|
||||||
--no-autorestart \
|
--no-autorestart \
|
||||||
|
@ -46,8 +46,8 @@ with a bried explanation of what they mean:
|
|||||||
Request method other than POST.
|
Request method other than POST.
|
||||||
|
|
||||||
- **409 (Conflict)**:
|
- **409 (Conflict)**:
|
||||||
Request to overwrite existing (public or non-public) directory (e.g. deploy existing build or
|
Request to overwrite existing directory (e.g. deploy existing build or change PR visibility when
|
||||||
change PR visibility when the destination directory does already exist).
|
the destination directory does already exist).
|
||||||
|
|
||||||
- **413 (Payload Too Large)**:
|
- **413 (Payload Too Large)**:
|
||||||
Payload larger than size specified in `AIO_UPLOAD_MAX_SIZE`.
|
Payload larger than size specified in `AIO_UPLOAD_MAX_SIZE`.
|
||||||
@ -71,8 +71,7 @@ with a bried explanation of what they mean:
|
|||||||
Request method other than POST.
|
Request method other than POST.
|
||||||
|
|
||||||
- **409 (Conflict)**:
|
- **409 (Conflict)**:
|
||||||
Request to overwrite existing (public or non-public) directory (i.e. directories for both
|
Request to overwrite existing directory (i.e. directories for both visibilities exist).
|
||||||
visibilities exist).
|
|
||||||
(Normally, this should not happen.)
|
(Normally, this should not happen.)
|
||||||
|
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ VM host to update the preview server based on changes in the source code.
|
|||||||
The script will pull the latest changes from the origin's master branch and examine if there have
|
The script will pull the latest changes from the origin's master branch and examine if there have
|
||||||
been any changes in files inside the preview server source code directory (see below). If there are,
|
been any changes in files inside the preview server source code directory (see below). If there are,
|
||||||
it will create a new image and verify that is works as expected. Finally, it will stop and remove
|
it will create a new image and verify that is works as expected. Finally, it will stop and remove
|
||||||
the old docker container and image, create a new container based on the new image and start it.
|
the old docker container and image, create and new container based on the new image and start it.
|
||||||
|
|
||||||
The script assumes that the preview server source code is in the repository's
|
The script assumes that the preview server source code is in the repository's
|
||||||
`aio/aio-builds-setup/` directory and expects the following inputs:
|
`aio/aio-builds-setup/` directory and expects the following inputs:
|
||||||
|
@ -9,7 +9,7 @@ readonly defaultImageNameAndTag="aio-builds:latest"
|
|||||||
# (Necessary, because only `scripts-js/dist/` is copied to the docker image.)
|
# (Necessary, because only `scripts-js/dist/` is copied to the docker image.)
|
||||||
(
|
(
|
||||||
cd "$SCRIPTS_JS_DIR"
|
cd "$SCRIPTS_JS_DIR"
|
||||||
yarn install --freeze-lockfile --non-interactive
|
yarn install
|
||||||
yarn build
|
yarn build
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -7,6 +7,6 @@ source "`dirname $0`/_env.sh"
|
|||||||
# Test `scripts-js/`
|
# Test `scripts-js/`
|
||||||
(
|
(
|
||||||
cd "$SCRIPTS_JS_DIR"
|
cd "$SCRIPTS_JS_DIR"
|
||||||
yarn install --freeze-lockfile --non-interactive
|
yarn install
|
||||||
yarn test
|
yarn test
|
||||||
)
|
)
|
||||||
|
4
aio/content/examples/.gitignore
vendored
4
aio/content/examples/.gitignore
vendored
@ -55,6 +55,10 @@ dist/
|
|||||||
!testing/src/browser-test-shim.js
|
!testing/src/browser-test-shim.js
|
||||||
!testing/karma*.js
|
!testing/karma*.js
|
||||||
|
|
||||||
|
# TS to JS
|
||||||
|
!ts-to-js/js*/**/*.js
|
||||||
|
ts-to-js/js*/**/system*.js
|
||||||
|
|
||||||
# webpack
|
# webpack
|
||||||
!webpack/**/config/*.js
|
!webpack/**/config/*.js
|
||||||
!webpack/**/*webpack*.js
|
!webpack/**/*webpack*.js
|
||||||
|
@ -335,17 +335,17 @@ describe('Animation Tests', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBoundingClientWidth(el: ElementFinder) {
|
function getBoundingClientWidth(el: ElementFinder): promise.Promise<number> {
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return arguments[0].getBoundingClientRect().width',
|
'return arguments[0].getBoundingClientRect().width',
|
||||||
el.getWebElement()
|
el.getWebElement()
|
||||||
) as PromiseLike<number>;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getOffsetWidth(el: ElementFinder) {
|
function getOffsetWidth(el: ElementFinder): promise.Promise<number> {
|
||||||
return browser.executeScript(
|
return browser.executeScript(
|
||||||
'return arguments[0].offsetWidth',
|
'return arguments[0].offsetWidth',
|
||||||
el.getWebElement()
|
el.getWebElement()
|
||||||
) as PromiseLike<number>;
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// #docplaster
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
// #docregion animations-module
|
// #docregion animations-module
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
// #enddocregion animations-module
|
// #enddocregion animations-module
|
||||||
@ -16,12 +15,11 @@ import { HeroListAutoComponent } from './hero-list-auto.component';
|
|||||||
import { HeroListGroupsComponent } from './hero-list-groups.component';
|
import { HeroListGroupsComponent } from './hero-list-groups.component';
|
||||||
import { HeroListMultistepComponent } from './hero-list-multistep.component';
|
import { HeroListMultistepComponent } from './hero-list-multistep.component';
|
||||||
import { HeroListTimingsComponent } from './hero-list-timings.component';
|
import { HeroListTimingsComponent } from './hero-list-timings.component';
|
||||||
// #docregion animations-module
|
|
||||||
|
|
||||||
|
// #docregion animation-module
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [ BrowserModule, BrowserAnimationsModule ],
|
imports: [ BrowserModule, BrowserAnimationsModule ],
|
||||||
// ... more stuff ...
|
// #enddocregion animation-module
|
||||||
// #enddocregion animations-module
|
|
||||||
declarations: [
|
declarations: [
|
||||||
HeroTeamBuilderComponent,
|
HeroTeamBuilderComponent,
|
||||||
HeroListBasicComponent,
|
HeroListBasicComponent,
|
||||||
@ -36,8 +34,5 @@ import { HeroListTimingsComponent } from './hero-list-timings.component';
|
|||||||
HeroListGroupsComponent
|
HeroListGroupsComponent
|
||||||
],
|
],
|
||||||
bootstrap: [ HeroTeamBuilderComponent ]
|
bootstrap: [ HeroTeamBuilderComponent ]
|
||||||
// #docregion animations-module
|
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule { }
|
||||||
// #enddocregion animations-module
|
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
transition
|
transition
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-auto',
|
selector: 'hero-list-auto',
|
||||||
@ -43,5 +43,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListAutoComponent {
|
export class HeroListAutoComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ import {
|
|||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-basic',
|
selector: 'hero-list-basic',
|
||||||
@ -66,5 +66,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListBasicComponent {
|
export class HeroListBasicComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-combined-transitions',
|
selector: 'hero-list-combined-transitions',
|
||||||
@ -55,5 +55,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListCombinedTransitionsComponent {
|
export class HeroListCombinedTransitionsComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
transition
|
transition
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-enter-leave-states',
|
selector: 'hero-list-enter-leave-states',
|
||||||
@ -59,5 +59,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListEnterLeaveStatesComponent {
|
export class HeroListEnterLeaveStatesComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
transition
|
transition
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-enter-leave',
|
selector: 'hero-list-enter-leave',
|
||||||
@ -47,5 +47,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListEnterLeaveComponent {
|
export class HeroListEnterLeaveComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
group
|
group
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-groups',
|
selector: 'hero-list-groups',
|
||||||
@ -76,5 +76,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListGroupsComponent {
|
export class HeroListGroupsComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-inline-styles',
|
selector: 'hero-list-inline-styles',
|
||||||
@ -56,5 +56,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListInlineStylesComponent {
|
export class HeroListInlineStylesComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
AnimationEvent
|
AnimationEvent
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-multistep',
|
selector: 'hero-list-multistep',
|
||||||
@ -59,7 +59,7 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListMultistepComponent {
|
export class HeroListMultistepComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
|
|
||||||
animationStarted(event: AnimationEvent) {
|
animationStarted(event: AnimationEvent) {
|
||||||
console.warn('Animation started: ', event);
|
console.warn('Animation started: ', event);
|
||||||
|
@ -10,7 +10,7 @@ import {
|
|||||||
transition
|
transition
|
||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-timings',
|
selector: 'hero-list-timings',
|
||||||
@ -54,5 +54,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListTimingsComponent {
|
export class HeroListTimingsComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
} from '@angular/animations';
|
} from '@angular/animations';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
|
|
||||||
import { Hero } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-list-twoway',
|
selector: 'hero-list-twoway',
|
||||||
@ -54,5 +54,5 @@ import { Hero } from './hero.service';
|
|||||||
// #enddocregion animationdef
|
// #enddocregion animationdef
|
||||||
})
|
})
|
||||||
export class HeroListTwowayComponent {
|
export class HeroListTwowayComponent {
|
||||||
@Input() heroes: Hero[];
|
@Input() heroes: Heroes;
|
||||||
}
|
}
|
||||||
|
@ -1,41 +1,40 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Heroes } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'hero-team-builder',
|
selector: 'hero-team-builder',
|
||||||
template: `
|
template: `
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<button [disabled]="!heroService.canAdd()" (click)="heroService.addInactive()">Add inactive hero</button>
|
<button [disabled]="!heroes.canAdd()" (click)="heroes.addInactive()">Add inactive hero</button>
|
||||||
<button [disabled]="!heroService.canAdd()" (click)="heroService.addActive()">Add active hero</button>
|
<button [disabled]="!heroes.canAdd()" (click)="heroes.addActive()">Add active hero</button>
|
||||||
<button [disabled]="!heroService.canRemove()" (click)="heroService.remove()">Remove hero</button>
|
<button [disabled]="!heroes.canRemove()" (click)="heroes.remove()">Remove hero</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Basic State</h4>
|
<h4>Basic State</h4>
|
||||||
<p>Switch between active/inactive on click.</p>
|
<p>Switch between active/inactive on click.</p>
|
||||||
<hero-list-basic [heroes]="heroes"></hero-list-basic>
|
<hero-list-basic [heroes]=heroes></hero-list-basic>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Styles inline in transitions</h4>
|
<h4>Styles inline in transitions</h4>
|
||||||
<p>Animated effect on click, no persistent end styles.</p>
|
<p>Animated effect on click, no persistend end styles.</p>
|
||||||
<hero-list-inline-styles [heroes]="heroes"></hero-list-inline-styles>
|
<hero-list-inline-styles [heroes]=heroes></hero-list-inline-styles>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Combined transition syntax</h4>
|
<h4>Combined transition syntax</h4>
|
||||||
<p>Switch between active/inactive on click. Define just one transition used in both directions.</p>
|
<p>Switch between active/inactive on click. Define just one transition used in both directions.</p>
|
||||||
<hero-list-combined-transitions [heroes]="heroes"></hero-list-combined-transitions>
|
<hero-list-combined-transitions [heroes]=heroes></hero-list-combined-transitions>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Two-way transition syntax</h4>
|
<h4>Two-way transition syntax</h4>
|
||||||
<p>Switch between active/inactive on click. Define just one transition used in both directions using the <=> syntax.</p>
|
<p>Switch between active/inactive on click. Define just one transition used in both directions using the <=> syntax.</p>
|
||||||
<hero-list-twoway [heroes]="heroes"></hero-list-twoway>
|
<hero-list-twoway [heroes]=heroes></hero-list-twoway>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Enter & Leave</h4>
|
<h4>Enter & Leave</h4>
|
||||||
<p>Enter and leave animations using the void state.</p>
|
<p>Enter and leave animations using the void state.</p>
|
||||||
<hero-list-enter-leave [heroes]="heroes"></hero-list-enter-leave>
|
<hero-list-enter-leave [heroes]=heroes></hero-list-enter-leave>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
@ -45,27 +44,27 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
Enter and leave animations combined with active/inactive state animations.
|
Enter and leave animations combined with active/inactive state animations.
|
||||||
Different enter and leave transitions depending on state.
|
Different enter and leave transitions depending on state.
|
||||||
</p>
|
</p>
|
||||||
<hero-list-enter-leave-states [heroes]="heroes"></hero-list-enter-leave-states>
|
<hero-list-enter-leave-states [heroes]=heroes></hero-list-enter-leave-states>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Auto Style Calc</h4>
|
<h4>Auto Style Calc</h4>
|
||||||
<p>Leave animation from the current computed height using the auto-style value *.</p>
|
<p>Leave animation from the current computed height using the auto-style value *.</p>
|
||||||
<hero-list-auto [heroes]="heroes"></hero-list-auto>
|
<hero-list-auto [heroes]=heroes></hero-list-auto>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Different Timings</h4>
|
<h4>Different Timings</h4>
|
||||||
<p>Enter and leave animations with different easings, ease-in for enter, ease-out for leave.</p>
|
<p>Enter and leave animations with different easings, ease-in for enter, ease-out for leave.</p>
|
||||||
<hero-list-timings [heroes]="heroes"></hero-list-timings>
|
<hero-list-timings [heroes]=heroes></hero-list-timings>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Multiple Keyframes</h4>
|
<h4>Multiple Keyframes</h4>
|
||||||
<p>Enter and leave animations with three keyframes in each, to give the transition some bounce.</p>
|
<p>Enter and leave animations with three keyframes in each, to give the transition some bounce.</p>
|
||||||
<hero-list-multistep [heroes]="heroes"></hero-list-multistep>
|
<hero-list-multistep [heroes]=heroes></hero-list-multistep>
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<h4>Parallel Groups</h4>
|
<h4>Parallel Groups</h4>
|
||||||
<p>Enter and leave animations with multiple properties animated in parallel with different timings.</p>
|
<p>Enter and leave animations with multiple properties animated in parallel with different timings.</p>
|
||||||
<hero-list-groups [heroes]="heroes"></hero-list-groups>
|
<hero-list-groups [heroes]=heroes></hero-list-groups>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@ -88,12 +87,8 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
min-height: 6em;
|
min-height: 6em;
|
||||||
}
|
}
|
||||||
`],
|
`],
|
||||||
providers: [HeroService]
|
providers: [Heroes]
|
||||||
})
|
})
|
||||||
export class HeroTeamBuilderComponent {
|
export class HeroTeamBuilderComponent {
|
||||||
heroes: Hero[];
|
constructor(private heroes: Heroes) { }
|
||||||
|
|
||||||
constructor(private heroService: HeroService) {
|
|
||||||
this.heroes = heroService.heroes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
// #docregion hero
|
class Hero {
|
||||||
export class Hero {
|
constructor(public name: string,
|
||||||
constructor(public name: string, public state = 'inactive') { }
|
public state = 'inactive') {
|
||||||
|
}
|
||||||
|
|
||||||
toggleState() {
|
toggleState() {
|
||||||
this.state = this.state === 'active' ? 'inactive' : 'active';
|
this.state = (this.state === 'active' ? 'inactive' : 'active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #enddocregion hero
|
|
||||||
|
|
||||||
const ALL_HEROES = [
|
let ALL_HEROES = [
|
||||||
'Windstorm',
|
'Windstorm',
|
||||||
'RubberMan',
|
'RubberMan',
|
||||||
'Bombasto',
|
'Bombasto',
|
||||||
@ -25,30 +25,36 @@ const ALL_HEROES = [
|
|||||||
].map(name => new Hero(name));
|
].map(name => new Hero(name));
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HeroService {
|
export class Heroes implements Iterable<Hero> {
|
||||||
|
|
||||||
heroes: Hero[] = [];
|
currentHeroes: Hero[] = [];
|
||||||
|
|
||||||
|
[Symbol.iterator]() {
|
||||||
|
return this.currentHeroes.values();
|
||||||
|
}
|
||||||
|
|
||||||
canAdd() {
|
canAdd() {
|
||||||
return this.heroes.length < ALL_HEROES.length;
|
return this.currentHeroes.length < ALL_HEROES.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
canRemove() {
|
canRemove() {
|
||||||
return this.heroes.length > 0;
|
return this.currentHeroes.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
addActive(active = true) {
|
addActive() {
|
||||||
let hero = ALL_HEROES[this.heroes.length];
|
let hero = ALL_HEROES[this.currentHeroes.length];
|
||||||
hero.state = active ? 'active' : 'inactive';
|
hero.state = 'active';
|
||||||
this.heroes.push(hero);
|
this.currentHeroes.push(hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
addInactive() {
|
addInactive() {
|
||||||
this.addActive(false);
|
let hero = ALL_HEROES[this.currentHeroes.length];
|
||||||
|
hero.state = 'inactive';
|
||||||
|
this.currentHeroes.push(hero);
|
||||||
}
|
}
|
||||||
|
|
||||||
remove() {
|
remove() {
|
||||||
this.heroes.length -= 1;
|
this.currentHeroes.splice(this.currentHeroes.length - 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,13 +12,13 @@ describe('Router', () => {
|
|||||||
beforeAll(() => browser.get(''));
|
beforeAll(() => browser.get(''));
|
||||||
|
|
||||||
function getPageStruct() {
|
function getPageStruct() {
|
||||||
const hrefEles = element.all(by.css('my-app > nav a'));
|
const hrefEles = element.all(by.css('my-app a'));
|
||||||
const crisisDetail = element.all(by.css('my-app > ng-component > ng-component > ng-component > div')).first();
|
const crisisDetail = element.all(by.css('my-app > ng-component > ng-component > ng-component > div')).first();
|
||||||
const heroDetail = element(by.css('my-app > ng-component > div'));
|
const heroDetail = element(by.css('my-app > ng-component > div'));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hrefs: hrefEles,
|
hrefs: hrefEles,
|
||||||
activeHref: element(by.css('my-app > nav a.active')),
|
activeHref: element(by.css('my-app a.active')),
|
||||||
|
|
||||||
crisisHref: hrefEles.get(0),
|
crisisHref: hrefEles.get(0),
|
||||||
crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
|
crisisList: element.all(by.css('my-app > ng-component > ng-component li')),
|
||||||
|
@ -15,10 +15,6 @@
|
|||||||
height: 1.6em;
|
height: 1.6em;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
.items li a {
|
|
||||||
display: block;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.items li:hover {
|
.items li:hover {
|
||||||
color: #607D8B;
|
color: #607D8B;
|
||||||
background-color: #DDD;
|
background-color: #DDD;
|
||||||
|
@ -28,7 +28,7 @@ const appRoutes: Routes = [
|
|||||||
data: { preload: true }
|
data: { preload: true }
|
||||||
},
|
},
|
||||||
// #enddocregion preload-v2
|
// #enddocregion preload-v2
|
||||||
{ path: '', redirectTo: '/superheroes', pathMatch: 'full' },
|
{ path: '', redirectTo: '/heroes', pathMatch: 'full' },
|
||||||
{ path: '**', component: PageNotFoundComponent }
|
{ path: '**', component: PageNotFoundComponent }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
// #docplaster
|
|
||||||
// #docregion
|
|
||||||
import { Component } from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'my-app',
|
|
||||||
// #docregion template
|
|
||||||
template: `
|
|
||||||
<h1 class="title">Angular Router</h1>
|
|
||||||
<nav>
|
|
||||||
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
|
||||||
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
|
|
||||||
<a routerLink="/admin" routerLinkActive="active">Admin</a>
|
|
||||||
<a routerLink="/login" routerLinkActive="active">Login</a>
|
|
||||||
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
|
|
||||||
</nav>
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
<router-outlet name="popup"></router-outlet>
|
|
||||||
`
|
|
||||||
// #enddocregion template
|
|
||||||
})
|
|
||||||
export class AppComponent {
|
|
||||||
}
|
|
@ -9,7 +9,7 @@ import { Component } from '@angular/core';
|
|||||||
<h1 class="title">Angular Router</h1>
|
<h1 class="title">Angular Router</h1>
|
||||||
<nav>
|
<nav>
|
||||||
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
<a routerLink="/crisis-center" routerLinkActive="active">Crisis Center</a>
|
||||||
<a routerLink="/superheroes" routerLinkActive="active">Heroes</a>
|
<a routerLink="/heroes" routerLinkActive="active">Heroes</a>
|
||||||
<a routerLink="/admin" routerLinkActive="active">Admin</a>
|
<a routerLink="/admin" routerLinkActive="active">Admin</a>
|
||||||
<a routerLink="/login" routerLinkActive="active">Login</a>
|
<a routerLink="/login" routerLinkActive="active">Login</a>
|
||||||
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
|
<a [routerLink]="[{ outlets: { popup: ['compose'] } }]">Contact</a>
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { CanDeactivate,
|
import { CanDeactivate,
|
||||||
ActivatedRouteSnapshot,
|
ActivatedRouteSnapshot,
|
||||||
RouterStateSnapshot } from '@angular/router';
|
RouterStateSnapshot } from '@angular/router';
|
||||||
@ -14,7 +13,7 @@ export class CanDeactivateGuard implements CanDeactivate<CrisisDetailComponent>
|
|||||||
component: CrisisDetailComponent,
|
component: CrisisDetailComponent,
|
||||||
route: ActivatedRouteSnapshot,
|
route: ActivatedRouteSnapshot,
|
||||||
state: RouterStateSnapshot
|
state: RouterStateSnapshot
|
||||||
): Observable<boolean> | boolean {
|
): Promise<boolean> | boolean {
|
||||||
// Get the Crisis Center ID
|
// Get the Crisis Center ID
|
||||||
console.log(route.paramMap.get('id'));
|
console.log(route.paramMap.get('id'));
|
||||||
|
|
||||||
@ -26,7 +25,7 @@ export class CanDeactivateGuard implements CanDeactivate<CrisisDetailComponent>
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise ask the user with the dialog service and return its
|
// Otherwise ask the user with the dialog service and return its
|
||||||
// observable which resolves to true or false when the user decides
|
// promise which resolves to true or false when the user decides
|
||||||
return component.dialogService.confirm('Discard changes?');
|
return component.dialogService.confirm('Discard changes?');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,18 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import 'rxjs/add/operator/take';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Router, Resolve, RouterStateSnapshot,
|
import { Router, Resolve, RouterStateSnapshot,
|
||||||
ActivatedRouteSnapshot } from '@angular/router';
|
ActivatedRouteSnapshot } from '@angular/router';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CrisisDetailResolver implements Resolve<Crisis> {
|
export class CrisisDetailResolver implements Resolve<Crisis> {
|
||||||
constructor(private cs: CrisisService, private router: Router) {}
|
constructor(private cs: CrisisService, private router: Router) {}
|
||||||
|
|
||||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<Crisis> {
|
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<Crisis> {
|
||||||
let id = route.paramMap.get('id');
|
let id = route.paramMap.get('id');
|
||||||
|
|
||||||
return this.cs.getCrisis(id).take(1).map(crisis => {
|
return this.cs.getCrisis(id).then(crisis => {
|
||||||
if (crisis) {
|
if (crisis) {
|
||||||
return crisis;
|
return crisis;
|
||||||
} else { // id not found
|
} else { // id not found
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
@ -46,8 +45,7 @@ export class CrisisDetailComponent implements OnInit {
|
|||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.route.paramMap
|
this.route.paramMap
|
||||||
.switchMap((params: ParamMap) =>
|
.switchMap((params: ParamMap) => this.service.getCrisis(params.get('id')))
|
||||||
this.service.getCrisis(params.get('id')))
|
|
||||||
.subscribe((crisis: Crisis) => {
|
.subscribe((crisis: Crisis) => {
|
||||||
if (crisis) {
|
if (crisis) {
|
||||||
this.editName = crisis.name;
|
this.editName = crisis.name;
|
||||||
@ -68,13 +66,13 @@ export class CrisisDetailComponent implements OnInit {
|
|||||||
this.gotoCrises();
|
this.gotoCrises();
|
||||||
}
|
}
|
||||||
|
|
||||||
canDeactivate(): Observable<boolean> | boolean {
|
canDeactivate(): Promise<boolean> | boolean {
|
||||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
||||||
if (!this.crisis || this.crisis.name === this.editName) {
|
if (!this.crisis || this.crisis.name === this.editName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise ask the user with the dialog service and return its
|
// Otherwise ask the user with the dialog service and return its
|
||||||
// observable which resolves to true or false when the user decides
|
// promise which resolves to true or false when the user decides
|
||||||
return this.dialogService.confirm('Discard changes?');
|
return this.dialogService.confirm('Discard changes?');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
import { Crisis } from './crisis.service';
|
import { Crisis } from './crisis.service';
|
||||||
@ -63,13 +62,13 @@ export class CrisisDetailComponent implements OnInit {
|
|||||||
// #enddocregion cancel-save
|
// #enddocregion cancel-save
|
||||||
|
|
||||||
// #docregion canDeactivate
|
// #docregion canDeactivate
|
||||||
canDeactivate(): Observable<boolean> | boolean {
|
canDeactivate(): Promise<boolean> | boolean {
|
||||||
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
// Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged
|
||||||
if (!this.crisis || this.crisis.name === this.editName) {
|
if (!this.crisis || this.crisis.name === this.editName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Otherwise ask the user with the dialog service and return its
|
// Otherwise ask the user with the dialog service and return its
|
||||||
// observable which resolves to true or false when the user decides
|
// promise which resolves to true or false when the user decides
|
||||||
return this.dialogService.confirm('Discard changes?');
|
return this.dialogService.confirm('Discard changes?');
|
||||||
}
|
}
|
||||||
// #enddocregion canDeactivate
|
// #enddocregion canDeactivate
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import 'rxjs/add/operator/do';
|
||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
@ -10,34 +10,35 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
// #docregion relative-navigation-router-link
|
// #docregion relative-navigation-router-link
|
||||||
template: `
|
template: `
|
||||||
<ul class="items">
|
<ul class="items">
|
||||||
<li *ngFor="let crisis of crises$ | async"
|
<li *ngFor="let crisis of crises | async">
|
||||||
[class.selected]="crisis.id === selectedId">
|
<a [routerLink]="[crisis.id]"
|
||||||
<a [routerLink]="[crisis.id]">
|
[class.selected]="isSelected(crisis)">
|
||||||
<span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
|
<span class="badge">{{ crisis.id }}</span>
|
||||||
|
{{ crisis.name }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>`
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
`
|
|
||||||
// #enddocregion relative-navigation-router-link
|
// #enddocregion relative-navigation-router-link
|
||||||
})
|
})
|
||||||
export class CrisisListComponent implements OnInit {
|
export class CrisisListComponent implements OnInit {
|
||||||
crises$: Observable<Crisis[]>;
|
crises: Observable<Crisis[]>;
|
||||||
selectedId: number;
|
selectedId: number;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private service: CrisisService,
|
private service: CrisisService,
|
||||||
private route: ActivatedRoute
|
private route: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.crises$ = this.route.paramMap
|
this.crises = this.route.paramMap
|
||||||
.switchMap((params: ParamMap) => {
|
.switchMap((params: ParamMap) => {
|
||||||
this.selectedId = +params.get('id');
|
this.selectedId = +params.get('id');
|
||||||
return this.service.getCrises();
|
return this.service.getCrises();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isSelected(crisis: Crisis) {
|
||||||
|
return crisis.id === this.selectedId;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, Router, ParamMap } from '@angular/router';
|
||||||
|
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { Crisis, CrisisService } from './crisis.service';
|
import { Crisis, CrisisService } from './crisis.service';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<ul class="items">
|
<ul class="items">
|
||||||
<li *ngFor="let crisis of crises$ | async"
|
<li *ngFor="let crisis of crises | async"
|
||||||
[class.selected]="crisis.id === selectedId">
|
(click)="onSelect(crisis)"
|
||||||
<a [routerLink]="[crisis.id]">
|
[class.selected]="isSelected(crisis)">
|
||||||
<span class="badge">{{ crisis.id }}</span>{{ crisis.name }}
|
<span class="badge">{{ crisis.id }}</span>
|
||||||
</a>
|
{{ crisis.name }}
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -21,21 +22,35 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class CrisisListComponent implements OnInit {
|
export class CrisisListComponent implements OnInit {
|
||||||
crises$: Observable<Crisis[]>;
|
crises: Observable<Crisis[]>;
|
||||||
selectedId: number;
|
selectedId: number;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
private service: CrisisService,
|
private service: CrisisService,
|
||||||
private route: ActivatedRoute
|
private route: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
) {}
|
) {}
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
isSelected(crisis: Crisis) {
|
||||||
|
return crisis.id === this.selectedId;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.crises$ = this.route.paramMap
|
this.crises = this.route.paramMap
|
||||||
.switchMap((params: ParamMap) => {
|
.switchMap((params: ParamMap) => {
|
||||||
this.selectedId = +params.get('id');
|
this.selectedId = +params.get('id');
|
||||||
return this.service.getCrises();
|
return this.service.getCrises();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #docregion onSelect
|
||||||
|
onSelect(crisis: Crisis) {
|
||||||
|
this.selectedId = crisis.id;
|
||||||
|
|
||||||
|
// Navigate with relative link
|
||||||
|
this.router.navigate([crisis.id], { relativeTo: this.route });
|
||||||
|
}
|
||||||
|
// #enddocregion onSelect
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
// #docplaster
|
// #docplaster
|
||||||
// #docregion , mock-crises
|
// #docregion , mock-crises
|
||||||
import 'rxjs/add/observable/of';
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|
||||||
|
|
||||||
export class Crisis {
|
export class Crisis {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
}
|
}
|
||||||
@ -16,18 +12,20 @@ const CRISES = [
|
|||||||
];
|
];
|
||||||
// #enddocregion mock-crises
|
// #enddocregion mock-crises
|
||||||
|
|
||||||
|
let crisesPromise = Promise.resolve(CRISES);
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CrisisService {
|
export class CrisisService {
|
||||||
static nextCrisisId = 100;
|
|
||||||
private crises$: BehaviorSubject<Crisis[]> = new BehaviorSubject<Crisis[]>(CRISES);
|
|
||||||
|
|
||||||
getCrises() { return this.crises$; }
|
static nextCrisisId = 100;
|
||||||
|
|
||||||
|
getCrises() { return crisesPromise; }
|
||||||
|
|
||||||
getCrisis(id: number | string) {
|
getCrisis(id: number | string) {
|
||||||
return this.getCrises()
|
return crisesPromise
|
||||||
.map(crises => crises.find(crisis => crisis.id === +id));
|
.then(crises => crises.find(crisis => crisis.id === +id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
@ -35,8 +33,7 @@ export class CrisisService {
|
|||||||
name = name.trim();
|
name = name.trim();
|
||||||
if (name) {
|
if (name) {
|
||||||
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
let crisis = new Crisis(CrisisService.nextCrisisId++, name);
|
||||||
CRISES.push(crisis);
|
crisesPromise.then(crises => crises.push(crisis));
|
||||||
this.crises$.next(CRISES);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// #docregion
|
// #docregion
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/observable/of';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async modal dialog service
|
* Async modal dialog service
|
||||||
* DialogService makes this app easier to test by faking this service.
|
* DialogService makes this app easier to test by faking this service.
|
||||||
@ -12,11 +9,11 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
export class DialogService {
|
export class DialogService {
|
||||||
/**
|
/**
|
||||||
* Ask user to confirm an action. `message` explains the action and choices.
|
* Ask user to confirm an action. `message` explains the action and choices.
|
||||||
* Returns observable resolving to `true`=confirm or `false`=cancel
|
* Returns promise resolving to `true`=confirm or `false`=cancel
|
||||||
*/
|
*/
|
||||||
confirm(message?: string): Observable<boolean> {
|
confirm(message?: string) {
|
||||||
const confirmation = window.confirm(message || 'Is it OK?');
|
return new Promise<boolean>(resolve => {
|
||||||
|
return resolve(window.confirm(message || 'Is it OK?'));
|
||||||
return Observable.of(confirmation);
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
// #enddocregion rxjs-operator-import
|
// #enddocregion rxjs-operator-import
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
// #docregion imports
|
// #docregion imports
|
||||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
// #enddocregion imports
|
// #enddocregion imports
|
||||||
@ -14,7 +13,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<h2>HEROES</h2>
|
<h2>HEROES</h2>
|
||||||
<div *ngIf="hero$ | async as hero">
|
<div *ngIf="hero">
|
||||||
<h3>"{{ hero.name }}"</h3>
|
<h3>"{{ hero.name }}"</h3>
|
||||||
<div>
|
<div>
|
||||||
<label>Id: </label>{{ hero.id }}</div>
|
<label>Id: </label>{{ hero.id }}</div>
|
||||||
@ -29,7 +28,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnInit {
|
||||||
hero$: Observable<Hero>;
|
hero: Hero;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
@ -41,9 +40,10 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.hero$ = this.route.paramMap
|
this.route.paramMap
|
||||||
.switchMap((params: ParamMap) =>
|
.switchMap((params: ParamMap) =>
|
||||||
this.service.getHero(params.get('id')));
|
this.service.getHero(params.get('id')))
|
||||||
|
.subscribe((hero: Hero) => this.hero = hero);
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
|
@ -2,14 +2,13 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<h2>HEROES</h2>
|
<h2>HEROES</h2>
|
||||||
<div *ngIf="hero$ | async as hero">
|
<div *ngIf="hero">
|
||||||
<h3>"{{ hero.name }}"</h3>
|
<h3>"{{ hero.name }}"</h3>
|
||||||
<div>
|
<div>
|
||||||
<label>Id: </label>{{ hero.id }}</div>
|
<label>Id: </label>{{ hero.id }}</div>
|
||||||
@ -24,7 +23,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class HeroDetailComponent implements OnInit {
|
export class HeroDetailComponent implements OnInit {
|
||||||
hero$: Observable<Hero>;
|
hero: Hero;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -36,7 +35,8 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
let id = this.route.snapshot.paramMap.get('id');
|
let id = this.route.snapshot.paramMap.get('id');
|
||||||
|
|
||||||
this.hero$ = this.service.getHero(id);
|
this.service.getHero(id)
|
||||||
|
.then((hero: Hero) => this.hero = hero);
|
||||||
}
|
}
|
||||||
// #enddocregion snapshot
|
// #enddocregion snapshot
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
import 'rxjs/add/operator/switchMap';
|
import 'rxjs/add/operator/switchMap';
|
||||||
// #enddocregion rxjs-operator-import
|
// #enddocregion rxjs-operator-import
|
||||||
import { Component, OnInit, HostBinding } from '@angular/core';
|
import { Component, OnInit, HostBinding } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
|
|
||||||
import { slideInDownAnimation } from '../animations';
|
import { slideInDownAnimation } from '../animations';
|
||||||
@ -14,7 +13,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
@Component({
|
@Component({
|
||||||
template: `
|
template: `
|
||||||
<h2>HEROES</h2>
|
<h2>HEROES</h2>
|
||||||
<div *ngIf="hero$ | async as hero">
|
<div *ngIf="hero">
|
||||||
<h3>"{{ hero.name }}"</h3>
|
<h3>"{{ hero.name }}"</h3>
|
||||||
<div>
|
<div>
|
||||||
<label>Id: </label>{{ hero.id }}</div>
|
<label>Id: </label>{{ hero.id }}</div>
|
||||||
@ -23,7 +22,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
<input [(ngModel)]="hero.name" placeholder="name"/>
|
<input [(ngModel)]="hero.name" placeholder="name"/>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
<button (click)="gotoHeroes(hero)">Back</button>
|
<button (click)="gotoHeroes()">Back</button>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
@ -36,7 +35,7 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
@HostBinding('style.position') position = 'absolute';
|
@HostBinding('style.position') position = 'absolute';
|
||||||
// #enddocregion host-bindings
|
// #enddocregion host-bindings
|
||||||
|
|
||||||
hero$: Observable<Hero>;
|
hero: Hero;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
@ -48,15 +47,16 @@ export class HeroDetailComponent implements OnInit {
|
|||||||
|
|
||||||
// #docregion ngOnInit
|
// #docregion ngOnInit
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.hero$ = this.route.paramMap
|
this.route.paramMap
|
||||||
.switchMap((params: ParamMap) =>
|
.switchMap((params: ParamMap) =>
|
||||||
this.service.getHero(params.get('id')));
|
this.service.getHero(params.get('id')))
|
||||||
|
.subscribe((hero: Hero) => this.hero = hero);
|
||||||
}
|
}
|
||||||
// #enddocregion ngOnInit
|
// #enddocregion ngOnInit
|
||||||
|
|
||||||
// #docregion gotoHeroes
|
// #docregion gotoHeroes
|
||||||
gotoHeroes(hero: Hero) {
|
gotoHeroes() {
|
||||||
let heroId = hero ? hero.id : null;
|
let heroId = this.hero ? this.hero.id : null;
|
||||||
// Pass along the hero id if available
|
// Pass along the hero id if available
|
||||||
// so that the HeroList component can select that hero.
|
// so that the HeroList component can select that hero.
|
||||||
// Include a junk 'foo' property for fun.
|
// Include a junk 'foo' property for fun.
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
// TODO SOMEDAY: Feature Componetized like HeroCenter
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
|
|
||||||
@ -12,12 +11,9 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
template: `
|
template: `
|
||||||
<h2>HEROES</h2>
|
<h2>HEROES</h2>
|
||||||
<ul class="items">
|
<ul class="items">
|
||||||
<li *ngFor="let hero of heroes$ | async">
|
<li *ngFor="let hero of heroes | async"
|
||||||
// #docregion nav-to-detail
|
(click)="onSelect(hero)">
|
||||||
<a [routerLink]="['/hero', hero.id]">
|
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
|
||||||
<span class="badge">{{ hero.id }}</span>{{ hero.name }}
|
|
||||||
</a>
|
|
||||||
// #enddocregion nav-to-detail
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -26,7 +22,7 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
// #enddocregion template
|
// #enddocregion template
|
||||||
})
|
})
|
||||||
export class HeroListComponent implements OnInit {
|
export class HeroListComponent implements OnInit {
|
||||||
heroes$: Observable<Hero[]>;
|
heroes: Promise<Hero[]>;
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
constructor(
|
constructor(
|
||||||
@ -36,8 +32,16 @@ export class HeroListComponent implements OnInit {
|
|||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.heroes$ = this.service.getHeroes();
|
this.heroes = this.service.getHeroes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #docregion select
|
||||||
|
onSelect(hero: Hero) {
|
||||||
|
// #docregion nav-to-detail
|
||||||
|
this.router.navigate(['/hero', hero.id]);
|
||||||
|
// #enddocregion nav-to-detail
|
||||||
|
}
|
||||||
|
// #enddocregion select
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import { Observable } from 'rxjs/Observable';
|
|||||||
// #enddocregion rxjs-imports
|
// #enddocregion rxjs-imports
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
// #docregion import-router
|
// #docregion import-router
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { Router, ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
// #enddocregion import-router
|
// #enddocregion import-router
|
||||||
|
|
||||||
import { Hero, HeroService } from './hero.service';
|
import { Hero, HeroService } from './hero.service';
|
||||||
@ -17,11 +17,10 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
template: `
|
template: `
|
||||||
<h2>HEROES</h2>
|
<h2>HEROES</h2>
|
||||||
<ul class="items">
|
<ul class="items">
|
||||||
<li *ngFor="let hero of heroes$ | async"
|
<li *ngFor="let hero of heroes | async"
|
||||||
[class.selected]="hero.id === selectedId">
|
[class.selected]="isSelected(hero)"
|
||||||
<a [routerLink]="['/hero', hero.id]">
|
(click)="onSelect(hero)">
|
||||||
<span class="badge">{{ hero.id }}</span>{{ hero.name }}
|
<span class="badge">{{ hero.id }}</span> {{ hero.name }}
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@ -31,17 +30,18 @@ import { Hero, HeroService } from './hero.service';
|
|||||||
})
|
})
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
export class HeroListComponent implements OnInit {
|
export class HeroListComponent implements OnInit {
|
||||||
heroes$: Observable<Hero[]>;
|
heroes: Observable<Hero[]>;
|
||||||
|
|
||||||
private selectedId: number;
|
private selectedId: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private service: HeroService,
|
private service: HeroService,
|
||||||
private route: ActivatedRoute
|
private route: ActivatedRoute,
|
||||||
|
private router: Router
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.heroes$ = this.route.paramMap
|
this.heroes = this.route.paramMap
|
||||||
.switchMap((params: ParamMap) => {
|
.switchMap((params: ParamMap) => {
|
||||||
// (+) before `params.get()` turns the string into a number
|
// (+) before `params.get()` turns the string into a number
|
||||||
this.selectedId = +params.get('id');
|
this.selectedId = +params.get('id');
|
||||||
@ -49,6 +49,16 @@ export class HeroListComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
// #enddocregion ctor
|
// #enddocregion ctor
|
||||||
|
|
||||||
|
// #docregion isSelected
|
||||||
|
isSelected(hero: Hero) { return hero.id === this.selectedId; }
|
||||||
|
// #enddocregion isSelected
|
||||||
|
|
||||||
|
// #docregion select
|
||||||
|
onSelect(hero: Hero) {
|
||||||
|
this.router.navigate(['/hero', hero.id]);
|
||||||
|
}
|
||||||
|
// #enddocregion select
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
}
|
}
|
||||||
// #enddocregion
|
// #enddocregion
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
// #docregion
|
// #docregion
|
||||||
import 'rxjs/add/observable/of';
|
|
||||||
import 'rxjs/add/operator/map';
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
|
|
||||||
export class Hero {
|
export class Hero {
|
||||||
constructor(public id: number, public name: string) { }
|
constructor(public id: number, public name: string) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
const HEROES = [
|
let HEROES = [
|
||||||
new Hero(11, 'Mr. Nice'),
|
new Hero(11, 'Mr. Nice'),
|
||||||
new Hero(12, 'Narco'),
|
new Hero(12, 'Narco'),
|
||||||
new Hero(13, 'Bombasto'),
|
new Hero(13, 'Bombasto'),
|
||||||
@ -17,13 +14,15 @@ const HEROES = [
|
|||||||
new Hero(16, 'RubberMan')
|
new Hero(16, 'RubberMan')
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let heroesPromise = Promise.resolve(HEROES);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
getHeroes() { return Observable.of(HEROES); }
|
getHeroes() { return heroesPromise; }
|
||||||
|
|
||||||
getHero(id: number | string) {
|
getHero(id: number | string) {
|
||||||
return this.getHeroes()
|
return heroesPromise
|
||||||
// (+) before `id` turns the string into a number
|
// (+) before `id` turns the string into a number
|
||||||
.map(heroes => heroes.find(hero => hero.id === +id));
|
.then(heroes => heroes.find(hero => hero.id === +id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// #docregion
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
|
||||||
|
|
||||||
import { HeroListComponent } from './hero-list.component';
|
|
||||||
import { HeroDetailComponent } from './hero-detail.component';
|
|
||||||
|
|
||||||
const heroesRoutes: Routes = [
|
|
||||||
{ path: 'heroes', component: HeroListComponent },
|
|
||||||
// #docregion hero-detail-route
|
|
||||||
{ path: 'hero/:id', component: HeroDetailComponent }
|
|
||||||
// #enddocregion hero-detail-route
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [
|
|
||||||
RouterModule.forChild(heroesRoutes)
|
|
||||||
],
|
|
||||||
exports: [
|
|
||||||
RouterModule
|
|
||||||
]
|
|
||||||
})
|
|
||||||
export class HeroRoutingModule { }
|
|
||||||
// #enddocregion
|
|
@ -6,10 +6,10 @@ import { HeroListComponent } from './hero-list.component';
|
|||||||
import { HeroDetailComponent } from './hero-detail.component';
|
import { HeroDetailComponent } from './hero-detail.component';
|
||||||
|
|
||||||
const heroesRoutes: Routes = [
|
const heroesRoutes: Routes = [
|
||||||
{ path: 'heroes', redirectTo: '/superheroes' },
|
{ path: 'heroes', component: HeroListComponent },
|
||||||
{ path: 'hero/:id', redirectTo: '/superhero/:id' },
|
// #docregion hero-detail-route
|
||||||
{ path: 'superheroes', component: HeroListComponent },
|
{ path: 'hero/:id', component: HeroDetailComponent }
|
||||||
{ path: 'superhero/:id', component: HeroDetailComponent }
|
// #enddocregion hero-detail-route
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -35,7 +35,7 @@ export class HeroDetailComponent {
|
|||||||
@Input() prefix = '';
|
@Input() prefix = '';
|
||||||
|
|
||||||
// #docregion deleteRequest
|
// #docregion deleteRequest
|
||||||
// This component makes a request but it can't actually delete a hero.
|
// This component make a request but it can't actually delete a hero.
|
||||||
deleteRequest = new EventEmitter<Hero>();
|
deleteRequest = new EventEmitter<Hero>();
|
||||||
|
|
||||||
delete() {
|
delete() {
|
||||||
|
@ -44,7 +44,6 @@ System.config({
|
|||||||
map: {
|
map: {
|
||||||
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
|
||||||
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
|
||||||
'@angular/common/http/testing': 'npm:@angular/common/bundles/common-http-testing.umd.js',
|
|
||||||
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
|
||||||
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
|
||||||
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
|
||||||
|
@ -52,10 +52,6 @@ module.exports = function(config) {
|
|||||||
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
{ pattern: 'node_modules/rxjs/**/*.js', included: false, watched: false },
|
||||||
{ pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
|
{ pattern: 'node_modules/rxjs/**/*.js.map', included: false, watched: false },
|
||||||
|
|
||||||
// tslib (TS helper fns such as `__extends`)
|
|
||||||
{ pattern: 'node_modules/tslib/**/*.js', included: false, watched: false },
|
|
||||||
{ pattern: 'node_modules/tslib/**/*.js.map', included: false, watched: false },
|
|
||||||
|
|
||||||
// Paths loaded via module imports:
|
// Paths loaded via module imports:
|
||||||
// Angular itself
|
// Angular itself
|
||||||
{ pattern: 'node_modules/@angular/**/*.js', included: false, watched: false },
|
{ pattern: 'node_modules/@angular/**/*.js', included: false, watched: false },
|
||||||
|
77
aio/content/examples/ts-to-js/e2e-spec.ts
Normal file
77
aio/content/examples/ts-to-js/e2e-spec.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
'use strict'; // necessary for es6 output in node
|
||||||
|
|
||||||
|
import { browser, element, by } from 'protractor';
|
||||||
|
|
||||||
|
describe('TypeScript to Javascript tests', function () {
|
||||||
|
|
||||||
|
beforeAll(function () {
|
||||||
|
browser.get('');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the basic component example', function () {
|
||||||
|
testTag('hero-view', 'Hero Detail: Windstorm');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display the component example with lifecycle methods', function () {
|
||||||
|
testTag('hero-lifecycle', 'Hero: Windstorm');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display component with DI example', function () {
|
||||||
|
testTag('hero-di', 'Hero: Windstorm');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should display component with DI using @Inject example', function () {
|
||||||
|
testTag('hero-di-inject', 'Hero: Windstorm');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support optional, attribute, and query injections', function () {
|
||||||
|
let app = element(by.css('hero-di-inject-additional'));
|
||||||
|
let h1 = app.element(by.css('h1'));
|
||||||
|
let okMsg = app.element(by.css('p'));
|
||||||
|
|
||||||
|
expect(h1.getText()).toBe('Tour of Heroes');
|
||||||
|
app.element(by.buttonText('OK')).click();
|
||||||
|
expect(okMsg.getText()).toBe('OK!');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support component with inputs and outputs', function () {
|
||||||
|
let app = element(by.css('hero-io'));
|
||||||
|
let confirmComponent = app.element(by.css('app-confirm'));
|
||||||
|
|
||||||
|
confirmComponent.element(by.buttonText('OK')).click();
|
||||||
|
expect(app.element(by.cssContainingText('span', 'OK clicked')).isPresent()).toBe(true);
|
||||||
|
|
||||||
|
confirmComponent.element(by.buttonText('Cancel')).click();
|
||||||
|
expect(app.element(by.cssContainingText('span', 'Cancel clicked')).isPresent()).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support host bindings and host listeners', function() {
|
||||||
|
let app = element(by.css('hero-host'));
|
||||||
|
let h1 = app.element(by.css('h1'));
|
||||||
|
|
||||||
|
expect(app.getAttribute('class')).toBe('heading');
|
||||||
|
expect(app.getAttribute('title')).toContain('Tooltip');
|
||||||
|
|
||||||
|
h1.click();
|
||||||
|
expect(h1.getAttribute('class')).toBe('active');
|
||||||
|
|
||||||
|
h1.click();
|
||||||
|
browser.actions().doubleClick(h1.getWebElement()).perform();
|
||||||
|
expect(h1.getAttribute('class')).toBe('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should support content and view queries', function() {
|
||||||
|
let app = element(by.css('hero-queries'));
|
||||||
|
let windstorm = app.element(by.css('view-child:first-child'));
|
||||||
|
|
||||||
|
app.element(by.css('button')).click();
|
||||||
|
expect(windstorm.element(by.css('h2')).getAttribute('class')).toBe('active');
|
||||||
|
expect(windstorm.element(by.css('content-child')).getText()).toBe('Active');
|
||||||
|
});
|
||||||
|
|
||||||
|
function testTag(selector: string, expectedText: string) {
|
||||||
|
let component = element(by.css(selector));
|
||||||
|
expect(component.getText()).toBe(expectedText);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"build": "build:babel"
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"description": "TypeScript to JavaScript",
|
||||||
|
"basePath": "src/",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js"
|
||||||
|
],
|
||||||
|
"tags":["cookbook"]
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015",
|
||||||
|
"angular2"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host, hero-host-meta { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AppComponent {
|
||||||
|
title = 'ES6 JavaScript with Decorators';
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Decorators</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
<hero-host-meta></hero-host-meta>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata</h4>
|
||||||
|
<hero-queries></hero-queries>
|
@ -0,0 +1,55 @@
|
|||||||
|
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ConfirmComponent } from './confirm.component';
|
||||||
|
// #docregion appimport
|
||||||
|
import { HeroComponent } from './hero.component';
|
||||||
|
// #enddocregion appimport
|
||||||
|
import { HeroComponent as HeroDIComponent } from './hero-di.component';
|
||||||
|
import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
|
||||||
|
import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
|
||||||
|
import { HeroHostComponent } from './hero-host.component';
|
||||||
|
import { HeroHostMetaComponent } from './hero-host-meta.component';
|
||||||
|
import { HeroIOComponent } from './hero-io.component';
|
||||||
|
import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
|
||||||
|
import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
|
||||||
|
import { HeroTitleComponent } from './hero-title.component';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
BrowserModule
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ConfirmComponent,
|
||||||
|
HeroComponent,
|
||||||
|
HeroDIComponent,
|
||||||
|
HeroDIInjectComponent,
|
||||||
|
HeroDIInjectAdditionalComponent,
|
||||||
|
HeroHostComponent, HeroHostMetaComponent,
|
||||||
|
HeroIOComponent,
|
||||||
|
HeroLifecycleComponent,
|
||||||
|
HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
|
||||||
|
HeroTitleComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
|
|
||||||
|
/* tslint:disable no-unused-variable */
|
||||||
|
// #docregion ng2import
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import {
|
||||||
|
LocationStrategy,
|
||||||
|
HashLocationStrategy
|
||||||
|
} from '@angular/common';
|
||||||
|
// #enddocregion ng2import
|
@ -0,0 +1,21 @@
|
|||||||
|
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: './confirm.component.html'
|
||||||
|
})
|
||||||
|
export class ConfirmComponent {
|
||||||
|
@Input() okMsg = '';
|
||||||
|
@Input('cancelMsg') notOkMsg = '';
|
||||||
|
@Output() ok = new EventEmitter();
|
||||||
|
@Output('cancel') notOk = new EventEmitter();
|
||||||
|
|
||||||
|
onOkClick() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
onNotOkClick() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
@ -0,0 +1,6 @@
|
|||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class DataService {
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
getHeroName() {
|
||||||
|
return 'Windstorm';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di-inject-additional',
|
||||||
|
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
||||||
|
})
|
||||||
|
export class HeroComponent { }
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di-inject',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(@Inject('heroName') name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
@ -0,0 +1,15 @@
|
|||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-di',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
name = '';
|
||||||
|
constructor(dataService: DataService) {
|
||||||
|
this.name = dataService.getHeroName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
@ -0,0 +1,44 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host-meta',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Metadata</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
host: {
|
||||||
|
// HostBindings to the <hero-host-meta> element
|
||||||
|
'[title]': 'title',
|
||||||
|
'[class.heading]': 'headingClass',
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host-meta> element
|
||||||
|
'(click)': 'clicked()',
|
||||||
|
'(mouseenter)': 'enter($event)',
|
||||||
|
'(mouseleave)': 'leave($event)'
|
||||||
|
},
|
||||||
|
// Styles within (but excluding) the <hero-host-meta> element
|
||||||
|
styles: ['.active {background-color: coral;}']
|
||||||
|
})
|
||||||
|
export class HeroHostMetaComponent {
|
||||||
|
title = 'Hero Host in Metadata Tooltip';
|
||||||
|
headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
@ -0,0 +1,39 @@
|
|||||||
|
import { Component, HostBinding, HostListener } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-host',
|
||||||
|
template: `
|
||||||
|
<h1 [class.active]="active">Hero Host in Decorators</h1>
|
||||||
|
<div>Heading clicks: {{clicks}}</div>
|
||||||
|
`,
|
||||||
|
// Styles within (but excluding) the <hero-host> element
|
||||||
|
styles: ['.active {background-color: yellow;}']
|
||||||
|
})
|
||||||
|
export class HeroHostComponent {
|
||||||
|
// HostBindings to the <hero-host> element
|
||||||
|
@HostBinding() title = 'Hero Host in Decorators Tooltip';
|
||||||
|
@HostBinding('class.heading') headingClass = true;
|
||||||
|
|
||||||
|
active = false;
|
||||||
|
clicks = 0;
|
||||||
|
|
||||||
|
// HostListeners on the entire <hero-host> element
|
||||||
|
@HostListener('click')
|
||||||
|
clicked() {
|
||||||
|
this.clicks += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseenter', ['$event'])
|
||||||
|
enter(event: Event) {
|
||||||
|
this.active = true;
|
||||||
|
this.headingClass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('mouseleave', ['$event'])
|
||||||
|
leave(event: Event) {
|
||||||
|
this.active = false;
|
||||||
|
this.headingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
@ -0,0 +1,26 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-io',
|
||||||
|
template: `
|
||||||
|
<app-confirm [okMsg]="'OK'"
|
||||||
|
[cancelMsg]="'Cancel'"
|
||||||
|
(ok)="onOk()"
|
||||||
|
(cancel)="onCancel()">
|
||||||
|
</app-confirm>
|
||||||
|
<span *ngIf="okClicked">OK clicked</span>
|
||||||
|
<span *ngIf="cancelClicked">Cancel clicked</span>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroIOComponent {
|
||||||
|
okClicked = false;
|
||||||
|
cancelClicked = false;
|
||||||
|
|
||||||
|
onOk() {
|
||||||
|
this.okClicked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCancel() {
|
||||||
|
this.cancelClicked = true;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-lifecycle',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
export class HeroComponent {
|
||||||
|
name = '';
|
||||||
|
ngOnInit() {
|
||||||
|
// todo: fetch from server async
|
||||||
|
setTimeout(() => this.name = 'Windstorm', 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
import {
|
||||||
|
Component,
|
||||||
|
ContentChild,
|
||||||
|
Input,
|
||||||
|
QueryList,
|
||||||
|
ViewChildren
|
||||||
|
} from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'content-child',
|
||||||
|
template: `
|
||||||
|
<span class="content-child" *ngIf="active">
|
||||||
|
Active
|
||||||
|
</span>`
|
||||||
|
})
|
||||||
|
export class ContentChildComponent {
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion content
|
||||||
|
@Component({
|
||||||
|
selector: 'view-child',
|
||||||
|
template: `
|
||||||
|
<h2 [class.active]=active>
|
||||||
|
{{hero.name}}
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>`,
|
||||||
|
styles: ['.active {font-weight: bold; background-color: skyblue;}']
|
||||||
|
})
|
||||||
|
export class ViewChildComponent {
|
||||||
|
@Input() hero;
|
||||||
|
active = false;
|
||||||
|
|
||||||
|
@ContentChild(ContentChildComponent) content;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.content.activate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion content
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
|
||||||
|
// #docregion view
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-queries',
|
||||||
|
template: `
|
||||||
|
<view-child *ngFor="let hero of heroData" [hero]="hero">
|
||||||
|
<content-child></content-child>
|
||||||
|
</view-child>
|
||||||
|
<button (click)="activate()">{{buttonLabel}} All</button>
|
||||||
|
`
|
||||||
|
})
|
||||||
|
export class HeroQueriesComponent {
|
||||||
|
active = false;
|
||||||
|
heroData = [
|
||||||
|
{id: 1, name: 'Windstorm'},
|
||||||
|
{id: 2, name: 'LaughingGas'}
|
||||||
|
];
|
||||||
|
|
||||||
|
@ViewChildren(ViewChildComponent) views;
|
||||||
|
|
||||||
|
activate() {
|
||||||
|
this.active = !this.active;
|
||||||
|
this.views.forEach(
|
||||||
|
view => view.activate()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
get buttonLabel() {
|
||||||
|
return this.active ? 'Deactivate' : 'Activate';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion view
|
@ -0,0 +1,25 @@
|
|||||||
|
import { Attribute, Component, Inject, Optional } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
// #docregion templateUrl
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-title',
|
||||||
|
templateUrl: './hero-title.component.html'
|
||||||
|
})
|
||||||
|
// #enddocregion templateUrl
|
||||||
|
export class HeroTitleComponent {
|
||||||
|
msg = '';
|
||||||
|
constructor(
|
||||||
|
@Inject('titlePrefix') @Optional() titlePrefix,
|
||||||
|
@Attribute('title') title
|
||||||
|
) {
|
||||||
|
this.titlePrefix = titlePrefix;
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok() {
|
||||||
|
this.msg = 'OK!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #enddocregion
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
<!-- #docregion -->
|
||||||
|
<h1>{{titlePrefix}} {{title}}</h1>
|
||||||
|
<button (click)="ok()">OK</button>
|
||||||
|
<p>{{ msg }}</p>
|
@ -0,0 +1,15 @@
|
|||||||
|
// #docregion
|
||||||
|
// #docregion metadata
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hero-view',
|
||||||
|
template: '<h1>{{title}}: {{getName()}}</h1>'
|
||||||
|
})
|
||||||
|
// #docregion appexport, class
|
||||||
|
export class HeroComponent {
|
||||||
|
title = 'Hero Detail';
|
||||||
|
getName() {return 'Windstorm'; }
|
||||||
|
}
|
||||||
|
// #enddocregion appexport, class
|
||||||
|
// #enddocregion metadata
|
@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<base href="/">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link rel="stylesheet" href="styles.css">
|
||||||
|
<title>TypeScript to JavaScript</title>
|
||||||
|
|
||||||
|
<!-- Polyfill(s) for older browsers -->
|
||||||
|
<script src="node_modules/core-js/client/shim.min.js"></script>
|
||||||
|
|
||||||
|
<script src="node_modules/zone.js/dist/zone.js"></script>
|
||||||
|
<script src="node_modules/systemjs/dist/system.src.js"></script>
|
||||||
|
|
||||||
|
<script src="systemjs.config.js"></script>
|
||||||
|
<script>
|
||||||
|
System.import('main.js').catch(function(err){ console.error(err); });
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<my-app>Loading...</my-app>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -0,0 +1,4 @@
|
|||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import { AppModule } from './app/app.module';
|
||||||
|
|
||||||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
3
aio/content/examples/ts-to-js/js-es6/example-config.json
Normal file
3
aio/content/examples/ts-to-js/js-es6/example-config.json
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"build": "build:babel"
|
||||||
|
}
|
9
aio/content/examples/ts-to-js/js-es6/plnkr.json
Normal file
9
aio/content/examples/ts-to-js/js-es6/plnkr.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"description": "TypeScript to JavaScript",
|
||||||
|
"basePath": "src/",
|
||||||
|
"files":[
|
||||||
|
"!**/*.d.ts",
|
||||||
|
"!**/*.js"
|
||||||
|
],
|
||||||
|
"tags":["cookbook"]
|
||||||
|
}
|
5
aio/content/examples/ts-to-js/js-es6/src/.babelrc
Normal file
5
aio/content/examples/ts-to-js/js-es6/src/.babelrc
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015"
|
||||||
|
]
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
export class AppComponent {
|
||||||
|
constructor() {
|
||||||
|
this.title = 'Plain ES6 JavaScript';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AppComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'my-app',
|
||||||
|
templateUrl: './app.component.html',
|
||||||
|
styles: [
|
||||||
|
// See hero-di-inject-additional.component
|
||||||
|
'hero-host { border: 1px dashed black; display: block; padding: 4px;}',
|
||||||
|
'.heading {font-style: italic}'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
@ -0,0 +1,30 @@
|
|||||||
|
<a id="toc"></a>
|
||||||
|
<h1>{{title}}</h1>
|
||||||
|
<a href="#class-metadata">Classes and Class Metadata</a><br>
|
||||||
|
<a href="#io-metadata">Input and Output Metadata</a><br>
|
||||||
|
<a href="#dependency-injection">Dependency Injection</a><br>
|
||||||
|
<a href="#host-metadata">Host Metadata</a><br>
|
||||||
|
<a href="#view-child-metadata">View and Child Metadata</a><br>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="class-metadata">Classes and Class Metadata</h4>
|
||||||
|
<hero-view></hero-view>
|
||||||
|
<hero-lifecycle></hero-lifecycle>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="io-metadata">Input and Output Metadata</h4>
|
||||||
|
<hero-io></hero-io>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="dependency-injection">Dependency Injection</h4>
|
||||||
|
<hero-di></hero-di>
|
||||||
|
<hero-di-inject></hero-di-inject>
|
||||||
|
<hero-di-inject-additional></hero-di-inject-additional>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="host-metadata">Host Metadata</h4>
|
||||||
|
<hero-host></hero-host>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<h4 id="view-child-metadata">View and Child Metadata</h4>
|
||||||
|
<hero-queries></hero-queries>
|
56
aio/content/examples/ts-to-js/js-es6/src/app/app.module.es6
Normal file
56
aio/content/examples/ts-to-js/js-es6/src/app/app.module.es6
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { NgModule, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
|
import { ConfirmComponent } from './confirm.component';
|
||||||
|
// #docregion appimport
|
||||||
|
import { HeroComponent } from './hero.component';
|
||||||
|
|
||||||
|
// #enddocregion appimport
|
||||||
|
import { HeroComponent as HeroDIComponent } from './hero-di.component';
|
||||||
|
import { HeroComponent as HeroDIInjectComponent } from './hero-di-inject.component';
|
||||||
|
import { HeroComponent as HeroDIInjectAdditionalComponent } from './hero-di-inject-additional.component';
|
||||||
|
import { HeroHostComponent } from './hero-host.component';
|
||||||
|
import { HeroIOComponent } from './hero-io.component';
|
||||||
|
import { HeroComponent as HeroLifecycleComponent } from './hero-lifecycle.component';
|
||||||
|
import { HeroQueriesComponent, ViewChildComponent, ContentChildComponent } from './hero-queries.component';
|
||||||
|
import { HeroTitleComponent } from './hero-title.component';
|
||||||
|
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
export class AppModule { }
|
||||||
|
|
||||||
|
AppModule.annotations = [
|
||||||
|
new NgModule({
|
||||||
|
imports: [ BrowserModule],
|
||||||
|
declarations: [
|
||||||
|
AppComponent,
|
||||||
|
ConfirmComponent,
|
||||||
|
HeroComponent,
|
||||||
|
HeroDIComponent,
|
||||||
|
HeroDIInjectComponent,
|
||||||
|
HeroDIInjectAdditionalComponent,
|
||||||
|
HeroHostComponent,
|
||||||
|
HeroIOComponent,
|
||||||
|
HeroLifecycleComponent,
|
||||||
|
HeroQueriesComponent, ViewChildComponent, ContentChildComponent,
|
||||||
|
HeroTitleComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
DataService,
|
||||||
|
{ provide: 'heroName', useValue: 'Windstorm' }
|
||||||
|
],
|
||||||
|
bootstrap: [ AppComponent ],
|
||||||
|
|
||||||
|
// schemas: [ NO_ERRORS_SCHEMA ] // helpful for debugging
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
/* tslint:disable no-unused-variable */
|
||||||
|
// #docregion ng2import
|
||||||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||||
|
import {
|
||||||
|
LocationStrategy,
|
||||||
|
HashLocationStrategy
|
||||||
|
} from '@angular/common';
|
||||||
|
// #enddocregion ng2import
|
@ -0,0 +1,31 @@
|
|||||||
|
import { Component, EventEmitter } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class ConfirmComponent {
|
||||||
|
constructor(){
|
||||||
|
this.ok = new EventEmitter();
|
||||||
|
this.notOk = new EventEmitter();
|
||||||
|
}
|
||||||
|
onOkClick() {
|
||||||
|
this.ok.emit(true);
|
||||||
|
}
|
||||||
|
onNotOkClick() {
|
||||||
|
this.notOk.emit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfirmComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'app-confirm',
|
||||||
|
templateUrl: './confirm.component.html',
|
||||||
|
inputs: [
|
||||||
|
'okMsg',
|
||||||
|
'notOkMsg: cancelMsg'
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
'ok',
|
||||||
|
'notOk: cancel'
|
||||||
|
]
|
||||||
|
})
|
||||||
|
];
|
||||||
|
// #enddocregion
|
@ -0,0 +1,6 @@
|
|||||||
|
<button (click)="onOkClick()">
|
||||||
|
{{okMsg}}
|
||||||
|
</button>
|
||||||
|
<button (click)="onNotOkClick()">
|
||||||
|
{{notOkMsg}}
|
||||||
|
</button>
|
@ -0,0 +1,13 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
export class DataService {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
getHeroName() {
|
||||||
|
return 'Windstorm';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataService.annotations = [
|
||||||
|
new Injectable()
|
||||||
|
];
|
@ -0,0 +1,10 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
export class HeroComponent { }
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di-inject-additional',
|
||||||
|
template: `<hero-title title="Tour of Heroes"></hero-title>`
|
||||||
|
})
|
||||||
|
];
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
|
||||||
|
// #docregion
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di-inject',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
HeroComponent.parameters = [
|
||||||
|
[new Inject('heroName')]
|
||||||
|
];
|
||||||
|
// #enddocregion
|
@ -0,0 +1,21 @@
|
|||||||
|
// #docregion
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { DataService } from './data.service';
|
||||||
|
|
||||||
|
export class HeroComponent {
|
||||||
|
constructor(dataService) {
|
||||||
|
this.name = dataService.getHeroName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeroComponent.annotations = [
|
||||||
|
new Component({
|
||||||
|
selector: 'hero-di',
|
||||||
|
template: `<h1>Hero: {{name}}</h1>`
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
HeroComponent.parameters = [
|
||||||
|
[DataService]
|
||||||
|
];
|
||||||
|
// #enddocregion
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user