mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95efcdd019 | |||
| a3787bdfa6 | |||
| 454d5e9c86 | |||
| d99bc8aeb6 | |||
| f81a4365fe | |||
| d4c84a97e8 | |||
| df828e9947 | |||
| d57c1f50b4 | |||
| 8f936a4111 | |||
| 35ee10e357 | |||
| 7ed3927082 | |||
| 9e22d60763 | |||
| 93845373a3 | |||
| ff5575ad0b | |||
| 3e35f7415e | |||
| 24290bcab7 | |||
| 5c1bbf2e50 | |||
| 6186e5237f | |||
| 3e1384048e | |||
| b774e22d8e | |||
| ec03e462f3 | |||
| bbbe477f47 | |||
| 711cb41626 | |||
| 4be253483d | |||
| 30f00d887d | |||
| 3aea2e6872 | |||
| c8ee52897e | |||
| 5ae85e4849 | |||
| cc34e5fb07 | |||
| 1d1c413169 | |||
| ee68df9be9 | |||
| a057b61d1f | |||
| c67647b8c2 | |||
| 3d9e8b2109 | |||
| 8737544d69 | |||
| a566c5ce44 | |||
| 65ff0f8246 | |||
| e227275087 | |||
| 7dd56736e8 | |||
| ff51e0933b | |||
| b4c7167d90 | |||
| 4fd78a99d2 | |||
| d0ce0110e8 | |||
| a7f8d9dc08 | |||
| f80fabbf27 | |||
| 455b64524f | |||
| b0e0f0014e | |||
| df6c2057f2 | |||
| f9781f9804 | |||
| 616df433c9 | |||
| e1ac52a0b4 | |||
| 6007af9651 | |||
| 66e940aebf | |||
| 0accc64cc0 | |||
| 08233b8374 | |||
| e1b9b662a0 | |||
| d04f98d713 | |||
| dc62446ef7 | |||
| 4ca81b09e8 | |||
| 426bcb999a | |||
| 6581ac94cd | |||
| e9c659a486 | |||
| 760b1f3d0b | |||
| 02b8e11e1e | |||
| a2087a1978 | |||
| 1af3ae3dee | |||
| af6f6e6448 | |||
| 1f8c53cd0c | |||
| 79fbc4eaba | |||
| 8ca0b0515d | |||
| df685ed7c5 | |||
| a2aa23d8b5 | |||
| b780d39612 | |||
| d28cf00df6 | |||
| 6eb5e37d6f | |||
| 7d1d604916 | |||
| 869ebc54e9 | |||
| 4af7e0c96a | |||
| 9bbc415408 | |||
| debe484188 |
@@ -4,7 +4,7 @@ description: 'Installs the dependencies using Yarn'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4
|
||||
- uses: actions/cache@704facf57e6136b1bc63b828d79edcd491f0ee84 # v3
|
||||
with:
|
||||
path: |
|
||||
./node_modules/
|
||||
|
||||
@@ -21,16 +21,16 @@ jobs:
|
||||
(github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'adev: preview'))
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
run: yarn bazel build --config=aio_local_deps //adev:build
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@73777547f819464aa5f48071b966eed34fd2c402
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
|
||||
- uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # tag=v3
|
||||
with:
|
||||
token: '${{secrets.GITHUB_TOKEN}}'
|
||||
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs
|
||||
npx -y firebase-tools@latest target:apply --config adev/firebase.json --project ${{env.PREVIEW_PROJECT}} hosting angular-docs ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@73777547f819464aa5f48071b966eed34fd2c402
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'adev-preview'
|
||||
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
# the number of concurrent actions is determined based on the host resources.
|
||||
- run: bazel build //aio:build --jobs=32 --announce_rc --verbose_failures
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/previews/pack-and-upload-artifact@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
workflow-artifact-name: 'aio'
|
||||
pull-number: '${{github.event.pull_request.number}}'
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
npx -y firebase-tools@latest target:clear --project ${{env.PREVIEW_PROJECT}} hosting aio
|
||||
npx -y firebase-tools@latest target:apply --project ${{env.PREVIEW_PROJECT}} hosting aio ${{env.PREVIEW_SITE}}
|
||||
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/previews/upload-artifacts-to-firebase@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
github-token: '${{secrets.GITHUB_TOKEN}}'
|
||||
workflow-artifact-name: 'aio'
|
||||
|
||||
@@ -16,6 +16,6 @@ jobs:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/branch-manager@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
- uses: ./.github/actions/yarn-install
|
||||
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
bazelrc: ./.bazelrc.user
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Starting Saucelabs tunnel service
|
||||
run: ./tools/saucelabs/sauce-service.sh run &
|
||||
# Build test fixtures for a test that rely on Bazel-generated fixtures. Note that disabling
|
||||
|
||||
+30
-32
@@ -23,7 +23,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -60,13 +60,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Run unit tests
|
||||
@@ -78,13 +78,13 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile --network-timeout 100000
|
||||
- name: Run CI tests for framework
|
||||
@@ -94,15 +94,15 @@ jobs:
|
||||
runs-on: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules for aio
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Run AIO tests with upstream packages
|
||||
@@ -115,11 +115,11 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@e52eb8237f2ed71195f87ce8046467a176568e58
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Build adev to ensure it continues to work
|
||||
@@ -130,15 +130,15 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Run AIO tests with local packages
|
||||
@@ -153,15 +153,15 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules for aio
|
||||
run: yarn install --cwd aio --frozen-lockfile
|
||||
- name: Set the stable branch environment variable
|
||||
@@ -184,7 +184,7 @@ jobs:
|
||||
run: yarn --cwd aio deploy-production
|
||||
- name: Notify about failed deployment
|
||||
if: ${{ failure() }}
|
||||
uses: slackapi/slack-github-action@2a8087d4af6f83146a87539a70defe909fe6dbe6 # v=v1.24.0
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v=v1.24.0
|
||||
with:
|
||||
channel-id: 'C07DT5M6V,CKV1F72BG'
|
||||
slack-message: 'Deploy to aio job failed for ${{ github.base_ref }} branch failed on build ${{ github.event.after }}: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}'
|
||||
@@ -197,13 +197,13 @@ jobs:
|
||||
labels: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: echo "https://${{secrets.SNAPSHOT_BUILDS_GITHUB_TOKEN}}:@github.com" > ${HOME}/.git_credentials
|
||||
@@ -215,7 +215,7 @@ jobs:
|
||||
labels: ubuntu-latest-4core
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
@@ -223,9 +223,9 @@ jobs:
|
||||
./packages/zone.js/node_modules
|
||||
./packages/zone.js/test/typings/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- run: |
|
||||
@@ -235,11 +235,9 @@ jobs:
|
||||
//packages/zone.js/test/closure:closure_js \
|
||||
|
||||
- run: |
|
||||
rm -Rf packages/zone.js/build
|
||||
rm -Rf packages/zone.js/test/extra/*.umd.js
|
||||
|
||||
mkdir -p packages/zone.js/build/
|
||||
mkdir -p packages/zone.js/build/test/
|
||||
mkdir -p packages/zone.js/test/
|
||||
|
||||
cp dist/bin/packages/zone.js/bundles/zone.umd.js packages/zone.js/build/zone.umd.js
|
||||
cp dist/bin/packages/zone.js/npm_package/bundles/zone-mix.umd.js ./packages/zone.js/test/extra/
|
||||
@@ -264,7 +262,7 @@ jobs:
|
||||
JOBS: 2
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
# Checking out the pull request commit is intended here as we need to run the changed code tests.
|
||||
@@ -272,9 +270,9 @@ jobs:
|
||||
- name: Install node modules
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel Remote Caching
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Set up Sauce Tunnel Daemon
|
||||
run: yarn bazel run //tools/saucelabs-daemon/background-service -- $JOBS &
|
||||
env:
|
||||
|
||||
@@ -13,13 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/commit-message-based-labels@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
post_approval_changes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/post-approval-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,6 +14,6 @@ jobs:
|
||||
if: github.repository == 'angular/angular'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/feature-request@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/feature-request@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/google-internal-tests@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
run-tests-guide-url: http://go/angular-g3sync-start
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -9,6 +9,6 @@ jobs:
|
||||
status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@7bd2697b40203c84826129b611e539fa663881f8
|
||||
- uses: angular/dev-infra/github-actions/unified-status-check@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
angular-robot-key: ${{ secrets.ANGULAR_ROBOT_PRIVATE_KEY }}
|
||||
|
||||
@@ -22,15 +22,15 @@ jobs:
|
||||
version: ['https://next.angular.io/', 'https://angular.io/']
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
./aio/node_modules
|
||||
- name: Setup Bazel
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/setup@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Setup Bazel RBE
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/bazel/configure-remote@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
- name: Install node modules in aio
|
||||
run: yarn install --frozen-lockfile --cwd aio
|
||||
- name: Run basic e2e and deployment config tests.
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Initialize environment
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/npm/checkout-and-setup-node@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
cache-node-modules: true
|
||||
node-module-directories: |
|
||||
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
env:
|
||||
ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN: ${{ secrets.ANGULAR_CLI_BUILDS_READONLY_GITHUB_TOKEN }}
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
branch-prefix: update-cli-help
|
||||
pr-title: 'docs: update Angular CLI help [${{github.ref_name}}]'
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Generate `events.json`
|
||||
run: node aio/scripts/generate-events/index.mjs --ignore-invalid-dates
|
||||
- name: Create a PR (if necessary)
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@7bd2697b40203c84826129b611e539fa663881f8
|
||||
uses: angular/dev-infra/github-actions/create-pr-for-changes@ae9155d1083fd8390e98bfe09a5ccf89f0375b52
|
||||
with:
|
||||
branch-prefix: docs-update-events
|
||||
pr-title: 'docs: update events'
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
|
||||
yarn -s ng-dev commit-message pre-commit-validate --file $1 2>/dev/null
|
||||
|
||||
+4
-1
@@ -1,8 +1,11 @@
|
||||
set +e
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
yarn -s ng-dev format staged 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "WARNING: failed to run file formatting (ng-dev format staged)"
|
||||
fi
|
||||
|
||||
|
||||
exit 0;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname $0)/_/husky.sh"
|
||||
|
||||
set +e
|
||||
|
||||
yarn -s ng-dev commit-message restore-commit-message-draft $1 $2 2>/dev/null
|
||||
|
||||
+1
-20
@@ -14,26 +14,13 @@ export const format: FormatConfig = {
|
||||
'packages/animations/**/*.{js,ts}',
|
||||
'packages/bazel/**/*.{js,ts}',
|
||||
'packages/benchpress/**/*.{js,ts}',
|
||||
'packages/common/**/*.{js,ts}',
|
||||
'packages/docs/**/*.{js,ts}',
|
||||
'packages/elements/**/*.{js,ts}',
|
||||
'packages/examples/**/*.{js,ts}',
|
||||
'packages/misc/**/*.{js,ts}',
|
||||
'packages/private/**/*.{js,ts}',
|
||||
'packages/service-worker/**/*.{js,ts}',
|
||||
'packages/upgrade/**/*.{js,ts}',
|
||||
|
||||
// Do not format d.ts files as they are generated
|
||||
'!**/*.d.ts',
|
||||
// Both third_party and .yarn are directories containing copied code which should
|
||||
// not be modified.
|
||||
'!third_party/**',
|
||||
'!.yarn/**',
|
||||
],
|
||||
},
|
||||
'clang-format': {
|
||||
'matchers': [
|
||||
//'**/*.{js,ts}',
|
||||
'**/*.{js,ts}',
|
||||
// TODO: burn down format failures and remove aio and integration exceptions.
|
||||
'!aio/**',
|
||||
'!integration/**',
|
||||
@@ -64,14 +51,8 @@ export const format: FormatConfig = {
|
||||
'!packages/animations/**/*.{js,ts}',
|
||||
'!packages/bazel/**/*.{js,ts}',
|
||||
'!packages/benchpress/**/*.{js,ts}',
|
||||
'!packages/common/**/*.{js,ts}',
|
||||
'!packages/docs/**/*.{js,ts}',
|
||||
'!packages/elements/**/*.{js,ts}',
|
||||
'!packages/examples/**/*.{js,ts}',
|
||||
'!packages/misc/**/*.{js,ts}',
|
||||
'!packages/private/**/*.{js,ts}',
|
||||
'!packages/service-worker/**/*.{js,ts}',
|
||||
'!packages/upgrade/**/*.{js,ts}',
|
||||
],
|
||||
},
|
||||
'buildifier': true,
|
||||
|
||||
+2
-11
@@ -166,9 +166,8 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- crisbeto
|
||||
- devversion
|
||||
- dylhunn
|
||||
- JoostK
|
||||
- dylhunn
|
||||
|
||||
# =========================================================
|
||||
# Framework: Migrations
|
||||
@@ -353,7 +352,6 @@ groups:
|
||||
- AndrewKushnir
|
||||
- atscott
|
||||
- crisbeto
|
||||
- devversion
|
||||
- dylhunn
|
||||
- jessicajaniuk
|
||||
- pkozlowski-opensource
|
||||
@@ -1071,16 +1069,9 @@ groups:
|
||||
])
|
||||
reviewers:
|
||||
users:
|
||||
- twerske
|
||||
- josephperrott
|
||||
- jelbourn
|
||||
- bencodezen
|
||||
- jessicajaniuk
|
||||
- dylhunn
|
||||
- AndrewKushnir
|
||||
- alxhub
|
||||
- crisbeto
|
||||
- atscott
|
||||
- pkozlowski-opensource
|
||||
|
||||
# =========================================================
|
||||
# Docs-infra
|
||||
|
||||
+7
-67
@@ -1,64 +1,3 @@
|
||||
<a name="17.1.3"></a>
|
||||
# 17.1.3 (2024-02-08)
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [bc4a6a9715](https://github.com/angular/angular/commit/bc4a6a9715547881ed8e65169a5aaebfd3188a7f) | fix | do not error due to multiple components named equally ([#54273](https://github.com/angular/angular/pull/54273)) |
|
||||
| [a997e08c6f](https://github.com/angular/angular/commit/a997e08c6f5c5321e5d18f3368ff0886fa133d59) | fix | handle default imports in defer blocks ([#53695](https://github.com/angular/angular/pull/53695)) |
|
||||
| [63a9027720](https://github.com/angular/angular/commit/63a9027720611002c6ee3b443a11e9feff213059) | fix | interpolatedSignalNotInvoked diagnostic for model signals ([#54338](https://github.com/angular/angular/pull/54338)) |
|
||||
| [40e1edc977](https://github.com/angular/angular/commit/40e1edc977fbe398adc535167f8ede2db8985656) | fix | properly catch fatal diagnostics in type checking ([#54309](https://github.com/angular/angular/pull/54309)) |
|
||||
| [9f6605d11b](https://github.com/angular/angular/commit/9f6605d11b7ee75f289b5a2ed69e201d65b038d8) | fix | support jumping to definitions of signal-based inputs ([#54233](https://github.com/angular/angular/pull/54233)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7df133dcc2](https://github.com/angular/angular/commit/7df133dcc243cd6b0f779fa35de7f916e6938301) | fix | `afterRender` hooks should allow updating state ([#54074](https://github.com/angular/angular/pull/54074)) |
|
||||
| [744e20641a](https://github.com/angular/angular/commit/744e20641a21d18c324bd9c157c8912d38741826) | fix | Fix possible infinite loop with `markForCheck` by partially reverting [#54074](https://github.com/angular/angular/pull/54074) ([#54329](https://github.com/angular/angular/pull/54329)) |
|
||||
| [0fb114274c](https://github.com/angular/angular/commit/0fb114274cead9f317a2fc902cc3a3f6b046e708) | fix | update imports to be compatible with rxjs 6 ([#54193](https://github.com/angular/angular/pull/54193)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [238f2a8bc9](https://github.com/angular/angular/commit/238f2a8bc9c46b0d08aff163349ecc1493441a69) | fix | Clear internal transition when navigation finalizes ([#54261](https://github.com/angular/angular/pull/54261)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.2"></a>
|
||||
# 17.1.2 (2024-01-31)
|
||||
###
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [ccddacf11d](https://github.com/angular/angular/commit/ccddacf11deaebeda12e1bdb6e93ec401397d352) | fix | cta clickability issue in adev homepage. ([#52905](https://github.com/angular/angular/pull/52905)) |
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [98d545fafa](https://github.com/angular/angular/commit/98d545fafa7fc3b1fb3ae049ce655e33ef9bd423) | fix | cleanup DOM elements when root view is removed with async animations ([#53033](https://github.com/angular/angular/pull/53033)) |
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cdc5e39532](https://github.com/angular/angular/commit/cdc5e3953237a192beafd6330f9d9e36ede34f2c) | fix | The date pipe should return ISO format for week and week-year as intended in the unit test. ([#53879](https://github.com/angular/angular/pull/53879)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f12b01ec88](https://github.com/angular/angular/commit/f12b01ec88eaf18041c2e46335428627aa0d7744) | fix | Update type check block to fix control flow source mappings ([#53980](https://github.com/angular/angular/pull/53980)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c477e876e3](https://github.com/angular/angular/commit/c477e876e39495b855b096440d53cf1dd1ad33c6) | fix | change defer block fixture default behavior to playthrough ([#54088](https://github.com/angular/angular/pull/54088)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8264382a6b](https://github.com/angular/angular/commit/8264382a6bf389fb3fca75fa2d6c0a2aa5a1e42f) | fix | error in standalone migration when non-array value is used as declarations in TestBed ([#54122](https://github.com/angular/angular/pull/54122)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.1"></a>
|
||||
# 17.1.1 (2024-01-24)
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [f222bee8fa](https://github.com/angular/angular/commit/f222bee8fa037f437761e5f7f127f22f280e9154) | fix | revert commit that replaced `last` helper with native `Array.at(-1)` ([#54021](https://github.com/angular/angular/pull/54021)) |
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="17.1.0"></a>
|
||||
# 17.1.0 (2024-01-17)
|
||||
### compiler
|
||||
@@ -390,16 +329,17 @@ Live long and prosper 🖖🏻
|
||||
|
||||
Node.js v16 is planned to be End-of-Life on 2023-09-11. Angular will stop supporting Node.js v16 in Angular v17. For Node.js release schedule details, please see: https://github.com/nodejs/release#release-schedule
|
||||
### common
|
||||
-
|
||||
- the NgSwitch directive now defaults to the === equality operator,
|
||||
migrating from the previously used == operator. NgSwitch expressions and / or
|
||||
migrating from the previously used ==. NgSwitch expressions and / or
|
||||
individual condition values need adjusting to this stricter equality
|
||||
check. The added warning message should help pin-pointing NgSwitch
|
||||
usages where adjustments are needed.
|
||||
check. The added warning message should help pinpointing NgSwitch
|
||||
usages where adjustements are needed.
|
||||
### core
|
||||
- Angular now requires `zone.js` version `~0.14.0`
|
||||
- Angular now required `zone.js` version `~0.14.0`
|
||||
- Versions of TypeScript older than 5.2 are no longer supported.
|
||||
- The `mutate` method was removed from the `WritableSignal` interface and completely
|
||||
dropped from the public API surface. As an alternative, please use the `update` method and
|
||||
dropped from the public API surface. As an alternative please use the update method and
|
||||
make immutable changes to the object.
|
||||
|
||||
Example before:
|
||||
@@ -497,7 +437,7 @@ Live long and prosper 🖖🏻
|
||||
- Swapping out the context object for `EmbeddedViewRef`
|
||||
is no longer supported. Support for this was introduced with v12.0.0, but
|
||||
this pattern is rarely used. There is no replacement, but you can use
|
||||
simple assignments in most cases, or `Object.assign` , or alternatively
|
||||
simple assignments in most cases, or `Object.assign , or alternatively
|
||||
still replace the full object by using a `Proxy` (see `NgTemplateOutlet`
|
||||
as an example).
|
||||
|
||||
|
||||
@@ -196,10 +196,10 @@ cldr_xml_data_repository(
|
||||
# sass rules
|
||||
http_archive(
|
||||
name = "io_bazel_rules_sass",
|
||||
sha256 = "386ef2b97bd4342e45db450ce7eb5acb343d22f7580c0bbae89186dc009fa14e",
|
||||
strip_prefix = "rules_sass-d970cb53ad159e7fd1d3a99a00a530cc2c83eff9",
|
||||
sha256 = "7a90567717c3417a23ff4b21963a698a6e9aa669ac9e682121ea33f218a2816a",
|
||||
strip_prefix = "rules_sass-425ecafa8268bc013d684216363fe75bc802323e",
|
||||
urls = [
|
||||
"https://github.com/bazelbuild/rules_sass/archive/d970cb53ad159e7fd1d3a99a00a530cc2c83eff9.zip",
|
||||
"https://github.com/bazelbuild/rules_sass/archive/425ecafa8268bc013d684216363fe75bc802323e.zip",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
@if (displaySecondaryNav()) {
|
||||
<adev-secondary-navigation />
|
||||
}
|
||||
<div class="docs-app-main-content">
|
||||
<div class="adev-app-main-content">
|
||||
<!--
|
||||
Avoid rendering cookies popup on the server,
|
||||
since there is no benefit of doing this and
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
// If navs are open, render a blurry background over content
|
||||
&:has(.docs-nav-secondary--open),
|
||||
&:has(.adev-nav-secondary--open),
|
||||
&:has(.adev-nav-primary--open) {
|
||||
.docs-app-main-content {
|
||||
.adev-app-main-content {
|
||||
&::after {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
@@ -54,7 +54,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-app-main-content {
|
||||
.adev-app-main-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</div>
|
||||
|
||||
<nav
|
||||
class="adev-nav-primary docs-scroll-hide"
|
||||
class="adev-nav-primary adev-scroll-hide"
|
||||
[class.adev-nav-primary--open]="isMobileNavigationOpened()"
|
||||
>
|
||||
<button
|
||||
@@ -126,7 +126,7 @@
|
||||
</a>
|
||||
|
||||
<!-- Version picker for v18+ -->
|
||||
<div class="adev-nav-item">
|
||||
<!-- <div class="adev-nav-item">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Select Angular version"
|
||||
@@ -166,7 +166,7 @@
|
||||
}
|
||||
</ul>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div> -->
|
||||
</li>
|
||||
|
||||
<!-- Search -->
|
||||
|
||||
@@ -6,10 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ComponentFixture, TestBed, fakeAsync, tick} from '@angular/core/testing';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import {PROGRESS_BAR_DELAY, ProgressBarComponent} from './progress-bar.component';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
import {ProgressBarComponent} from './progress-bar.component';
|
||||
|
||||
describe('ProgressBarComponent', () => {
|
||||
let component: ProgressBarComponent;
|
||||
@@ -17,7 +16,7 @@ describe('ProgressBarComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ProgressBarComponent, RouterTestingModule],
|
||||
imports: [ProgressBarComponent],
|
||||
}).compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ProgressBarComponent);
|
||||
@@ -25,13 +24,7 @@ describe('ProgressBarComponent', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should call progressBar.complete() on route change', fakeAsync(async () => {
|
||||
const progressBarCompleteSpy = spyOn(component.progressBar, 'complete');
|
||||
|
||||
const harness = await RouterTestingHarness.create();
|
||||
await harness.navigateByUrl('/');
|
||||
|
||||
tick(PROGRESS_BAR_DELAY);
|
||||
expect(progressBarCompleteSpy).toHaveBeenCalled();
|
||||
}));
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ import {
|
||||
import {filter, map, switchMap, take} from 'rxjs/operators';
|
||||
|
||||
/** Time to wait after navigation starts before showing the progress bar. This delay allows a small amount of time to skip showing the progress bar when a navigation is effectively immediate. 30ms is approximately the amount of time we can wait before a delay is perceptible.*/
|
||||
export const PROGRESS_BAR_DELAY = 30;
|
||||
const PROGRESS_BAR_DELAY = 30;
|
||||
|
||||
@Component({
|
||||
selector: 'adev-progress-bar',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div [attr.id]="SECONDARY_NAV_ID" class="adev-secondary-nav-mask" [class.docs-nav-secondary--open]="isSecondaryNavVisible()" (docsClickOutside)="close()" [docsClickOutsideIgnore]="[PRIMARY_NAV_ID]">
|
||||
<div class="docs-nav-secondary docs-scroll-track-transparent" [style.transform]="translateX()" [style.transition]="transition">
|
||||
<div [attr.id]="SECONDARY_NAV_ID" class="adev-secondary-nav-mask" [class.adev-nav-secondary--open]="isSecondaryNavVisible()" (docsClickOutside)="close()" [docsClickOutsideIgnore]="[PRIMARY_NAV_ID]">
|
||||
<div class="adev-nav-secondary adev-scroll-track-transparent" [style.transform]="translateX()" [style.transition]="transition">
|
||||
<!-- Secondary Nav -->
|
||||
@if (navigationItems && navigationItems.length > 0) {
|
||||
<docs-navigation-list
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
transform: translateX(0);
|
||||
z-index: 99;
|
||||
transition: transform 0.3s ease;
|
||||
&:has(.docs-nav-secondary--open) {
|
||||
&:has(.adev-nav-secondary--open) {
|
||||
transform: translateX(82px);
|
||||
transition: transform 0.3s ease-in 0.3s;
|
||||
}
|
||||
@@ -46,7 +46,7 @@
|
||||
@include mq.for-tablet-landscape-down {
|
||||
transform: translateX(-100%);
|
||||
|
||||
&.docs-nav-secondary--open {
|
||||
&.adev-nav-secondary--open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@
|
||||
// exit immediately
|
||||
transition: transform 0.45s ease-in;
|
||||
|
||||
&.docs-nav-secondary--open {
|
||||
&.adev-nav-secondary--open {
|
||||
transform: translateX(0);
|
||||
// enter delayed
|
||||
transition: transform 0.45s ease-out 0.2s;
|
||||
@@ -64,8 +64,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
// secondary nav - translated on x to display levels
|
||||
.docs-nav-secondary {
|
||||
// seconday nav - translated on x to display levels
|
||||
.adev-nav-secondary {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
max-width: var(--secondary-nav-width);
|
||||
|
||||
@@ -45,7 +45,7 @@ export class CustomErrorHandler implements ErrorHandler {
|
||||
openErrorSnackBar(): void {
|
||||
this.snackBar
|
||||
.openFromComponent(ErrorSnackBar, {
|
||||
panelClass: 'docs-invert-mode',
|
||||
panelClass: 'adev-invert-mode',
|
||||
data: {
|
||||
message: `Our docs have been updated, reload the page to see the latest.`,
|
||||
actionText: `Reload`,
|
||||
|
||||
@@ -19,7 +19,7 @@ export interface ErrorSnackBarData {
|
||||
template: `
|
||||
{{ message }}
|
||||
<button
|
||||
class="docs-primary-btn"
|
||||
class="adev-primary-btn"
|
||||
type="button"
|
||||
matSnackBarAction
|
||||
[attr.text]="actionText"
|
||||
|
||||
@@ -14,8 +14,8 @@ import {Subject} from 'rxjs';
|
||||
// Keep these constants in sync with the code in index.html
|
||||
|
||||
export const THEME_PREFERENCE_LOCAL_STORAGE_KEY = 'themePreference';
|
||||
export const DARK_MODE_CLASS_NAME = 'docs-dark-mode';
|
||||
export const LIGHT_MODE_CLASS_NAME = 'docs-light-mode';
|
||||
export const DARK_MODE_CLASS_NAME = 'adev-dark-mode';
|
||||
export const LIGHT_MODE_CLASS_NAME = 'adev-light-mode';
|
||||
export const PREFERS_COLOR_SCHEME_DARK = '(prefers-color-scheme: dark)';
|
||||
|
||||
export type Theme = 'dark' | 'light' | 'auto';
|
||||
@@ -38,13 +38,13 @@ export class ThemeManager {
|
||||
}
|
||||
|
||||
this.loadThemePreference();
|
||||
this.watchPreferredColorScheme();
|
||||
this.watchPreferedColorScheme();
|
||||
}
|
||||
|
||||
setTheme(theme: Theme): void {
|
||||
this.theme.set(theme);
|
||||
this.setThemeInLocalStorage();
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferredScheme() : theme);
|
||||
this.setThemeBodyClasses(theme === 'auto' ? preferedScheme() : theme);
|
||||
}
|
||||
|
||||
// 1. Read theme preferences stored in localStorage
|
||||
@@ -54,7 +54,7 @@ export class ThemeManager {
|
||||
const useTheme = savedUserPreference ?? 'auto';
|
||||
|
||||
this.theme.set(useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferredScheme() : useTheme);
|
||||
this.setThemeBodyClasses(useTheme === 'auto' ? preferedScheme() : useTheme);
|
||||
}
|
||||
|
||||
// Set theme classes on the body element
|
||||
@@ -81,14 +81,14 @@ export class ThemeManager {
|
||||
}
|
||||
}
|
||||
|
||||
private watchPreferredColorScheme() {
|
||||
private watchPreferedColorScheme() {
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (event) => {
|
||||
const preferredScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferredScheme);
|
||||
const preferedScheme = event.matches ? 'dark' : 'light';
|
||||
this.setThemeBodyClasses(preferedScheme);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function preferredScheme(): 'dark' | 'light' {
|
||||
function preferedScheme(): 'dark' | 'light' {
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
@@ -10,70 +10,22 @@ import {Injectable, VERSION, computed, signal} from '@angular/core';
|
||||
|
||||
// TODO(josephperrott): extract this out of the file into a managed location.
|
||||
const VERSIONS_CONFIG = {
|
||||
currentVersion: 'stable',
|
||||
historicalVersionsLinkPattern: 'https://v{{version}}.angular.dev',
|
||||
currentVersion: "stable",
|
||||
historicalVersionsLinkPattern: "https://v{{version}}.angular.dev",
|
||||
mainVersions: [
|
||||
{
|
||||
version: 'stable',
|
||||
url: 'https://angular.dev',
|
||||
version: "stable",
|
||||
url: "https://angular.dev"
|
||||
},
|
||||
{
|
||||
version: 'v16',
|
||||
url: 'https://v16.angular.io/docs',
|
||||
version: "rc",
|
||||
url: "https://rc.angular.dev"
|
||||
},
|
||||
{
|
||||
version: 'v15',
|
||||
url: 'https://v15.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v14',
|
||||
url: 'https://v14.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v13',
|
||||
url: 'https://v13.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v12',
|
||||
url: 'https://v12.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v11',
|
||||
url: 'https://v11.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v10',
|
||||
url: 'https://v10.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v9',
|
||||
url: 'https://v9.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v8',
|
||||
url: 'https://v8.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v7',
|
||||
url: 'https://v7.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v6',
|
||||
url: 'https://v6.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v5',
|
||||
url: 'https://v5.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v4',
|
||||
url: 'https://v4.angular.io/docs',
|
||||
},
|
||||
{
|
||||
version: 'v2',
|
||||
url: 'https://v2.angular.io/docs',
|
||||
},
|
||||
],
|
||||
version: "next",
|
||||
url: "https://next.angular.dev"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
export interface Version {
|
||||
|
||||
@@ -95,7 +95,7 @@ export class AlertManager {
|
||||
}
|
||||
|
||||
this.snackBar.openFromComponent(ErrorSnackBar, {
|
||||
panelClass: 'docs-invert-mode',
|
||||
panelClass: 'adev-invert-mode',
|
||||
data: {
|
||||
message,
|
||||
actionText: 'I understand',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!-- Code Editor Tabs -->
|
||||
<div class="docs-code-editor-tabs">
|
||||
<div class="adev-code-editor-tabs">
|
||||
<div class="adev-tabs-and-plus">
|
||||
<mat-tab-group animationDuration="0ms" mat-stretch-tabs="false">
|
||||
<!--
|
||||
@@ -13,7 +13,7 @@
|
||||
{{ file.filename.replace('src/', '') }}
|
||||
@if (tab.isActive && canDeleteFile(file.filename)) {
|
||||
<button
|
||||
class="docs-delete-file"
|
||||
class="adev-delete-file"
|
||||
aria-label="Delete file"
|
||||
(click)="deleteFile(file.filename)"
|
||||
>
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.docs-code-editor-tabs {
|
||||
.adev-code-editor-tabs {
|
||||
display: flex;
|
||||
background: var(--octonary-contrast);
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
@@ -79,7 +79,7 @@
|
||||
}
|
||||
|
||||
.adev-add-file,
|
||||
.docs-delete-file {
|
||||
.adev-delete-file {
|
||||
docs-icon {
|
||||
color: var(--gray-400);
|
||||
transition: color 0.3s ease;
|
||||
@@ -92,7 +92,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-delete-file {
|
||||
.adev-delete-file {
|
||||
padding-inline-start: 0.1rem;
|
||||
padding-inline-end: 0;
|
||||
margin-block-start: 0.2rem;
|
||||
|
||||
@@ -66,7 +66,7 @@ export const getTooltipExtension = (
|
||||
dom: tooltip,
|
||||
|
||||
// Note: force the tooltip to scroll to the top on mount and on position change
|
||||
// because depending on the position of the mouse and the size of the tooltip content,
|
||||
// because depending on the position of the mouse and the siez of the tooltip content,
|
||||
// the tooltip might render with its initial scroll position on the bottom
|
||||
mount: (_) => forceTooltipScrollTop(),
|
||||
positioned: (_) => forceTooltipScrollTop(),
|
||||
@@ -92,7 +92,7 @@ function forceTooltipScrollTop() {
|
||||
|
||||
function getMarkedHtmlFromString(content: string): HTMLDivElement {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.innerHTML = marked(content) as string;
|
||||
wrapper.innerHTML = marked(content);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
@@ -137,7 +137,7 @@ function getTagsHtml(tags: JSDocTagInfo[]): HTMLDivElement {
|
||||
}
|
||||
}
|
||||
|
||||
tagsWrapper.innerHTML = marked(contentString) as string;
|
||||
tagsWrapper.innerHTML = marked(contentString);
|
||||
|
||||
return tagsWrapper;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div class="adev-editor-container" #editorContainer>
|
||||
<as-split class="docs-editor" [direction]="splitDirection" restrictMove="true" gutterSize="5">
|
||||
<as-split class="adev-editor" [direction]="splitDirection" restrictMove="true" gutterSize="5">
|
||||
<as-split-area class="adev-left-side" [size]="50">
|
||||
<!-- Code Editor -->
|
||||
@if (!displayOnlyTerminal()) {
|
||||
@@ -16,9 +16,9 @@
|
||||
</as-split-area>
|
||||
|
||||
<as-split-area [size]="50">
|
||||
<!-- Preview, Terminal & Console -->
|
||||
<!-- Preview, Termnial & Console -->
|
||||
@if (!displayOnlyTerminal()) {
|
||||
<as-split class="docs-right-side" direction="vertical" restrictMove="true" gutterSize="5">
|
||||
<as-split class="adev-right-side" direction="vertical" restrictMove="true" gutterSize="5">
|
||||
<!-- Preview Section: for larger screens -->
|
||||
@if (!displayPreviewInMatTabGroup()) {
|
||||
<as-split-area [size]="50" [order]="1">
|
||||
@@ -34,9 +34,9 @@
|
||||
</as-split-area>
|
||||
}
|
||||
|
||||
<as-split-area class="docs-editor-tabs-and-refresh" [size]="50" [order]="2">
|
||||
<as-split-area class="adev-editor-tabs-and-refresh" [size]="50" [order]="2">
|
||||
<!-- Container to hide preview, console and footer when only the interactive terminal is used -->
|
||||
<mat-tab-group class="docs-editor-tabs" animationDuration="0ms" mat-stretch-tabs="false">
|
||||
<mat-tab-group class="adev-editor-tabs" animationDuration="0ms" mat-stretch-tabs="false">
|
||||
@if (displayPreviewInMatTabGroup()) {
|
||||
<mat-tab label="Preview">
|
||||
<docs-tutorial-preview />
|
||||
|
||||
@@ -32,7 +32,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
|
||||
// If files are displayed, shpare the space
|
||||
&:has(.docs-editor-tabs) {
|
||||
&:has(.adev-editor-tabs) {
|
||||
.adev-tutorial-code-editor {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
@@ -56,7 +56,7 @@ $width-breakpoint: 950px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.docs-right-side {
|
||||
.adev-right-side {
|
||||
height: 100%;
|
||||
|
||||
// prevent border flicker when resizing editor
|
||||
@@ -71,7 +71,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
}
|
||||
|
||||
.docs-editor-tabs-and-refresh {
|
||||
.adev-editor-tabs-and-refresh {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
||||
@@ -81,7 +81,7 @@ $width-breakpoint: 950px;
|
||||
}
|
||||
|
||||
// preview, terminal, console side/container of the embedded editor
|
||||
.docs-editor-tabs {
|
||||
.adev-editor-tabs {
|
||||
height: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export const DEV_SERVER_READY_MSG = 'Watch mode enabled. Watching for file chang
|
||||
export const OUT_OF_MEMORY_MSG = 'Out of memory';
|
||||
|
||||
const enum PROCESS_EXIT_CODE {
|
||||
SUCCESS = 0, // process exited successfully
|
||||
SUCCESS = 0, // process exited succesfully
|
||||
ERROR = 10, // process exited with error
|
||||
SIGTERM = 143, // 143 = gracefully terminated by SIGTERM, e.g. Ctrl + C
|
||||
}
|
||||
@@ -73,7 +73,7 @@ export class NodeRuntimeSandbox {
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSandbox
|
||||
// Note: the error state can already be set when loading the NodeRuntimeSanbox
|
||||
// in an unsupported environment.
|
||||
if (this.nodeRuntimeState.error()) {
|
||||
return;
|
||||
@@ -155,7 +155,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for an Angular project
|
||||
*/
|
||||
private async initProject(): Promise<void> {
|
||||
// prevent re-initialization
|
||||
// prevent re-initializion
|
||||
if (this._isProjectInitialized()) return;
|
||||
|
||||
// clean up the sandbox if it was initialized before so that the CLI can
|
||||
@@ -230,7 +230,7 @@ export class NodeRuntimeSandbox {
|
||||
* Initialize the WebContainer for the Angular CLI
|
||||
*/
|
||||
private async initAngularCli() {
|
||||
// prevent re-initialization
|
||||
// prevent re-initializion
|
||||
if (this._isAngularCliInitialized()) return;
|
||||
|
||||
// clean up the sandbox if a project was initialized before so the CLI can
|
||||
@@ -292,7 +292,7 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
const terminal = this.terminalHandler.interactiveTerminalInstance;
|
||||
|
||||
// use WebContainer spawn directly so that the process isn't killed on
|
||||
// use WebContainer spawn directly so that the proccess isn't killed on
|
||||
// cleanup
|
||||
const shellProcess = await webContainer.spawn('bash');
|
||||
|
||||
@@ -516,10 +516,10 @@ export class NodeRuntimeSandbox {
|
||||
|
||||
/**
|
||||
* Kill existing processes and remove files from the WebContainer
|
||||
* when switching tutorials that have different requirements
|
||||
* when switching tutorials that have diferent requirements
|
||||
*/
|
||||
private async cleanup() {
|
||||
// await the process to be killed before removing the files because
|
||||
// await the proccess to be killed before removing the files because
|
||||
// a process can create files during the promise
|
||||
await this.killExistingProcesses();
|
||||
await this.removeFiles();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="adev-preview-error docs-light-mode docs-mini-scroll-track">
|
||||
<div class="adev-preview-error adev-light-mode adev-mini-scroll-track">
|
||||
@switch (true) {
|
||||
@case (error()?.type === ErrorType.UNSUPPORTED_BROWSER_ENVIRONMENT) {
|
||||
@if(isIos) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
:host {
|
||||
display: block;
|
||||
|
||||
.docs-dark-mode & {
|
||||
.adev-dark-mode & {
|
||||
.adev-embedded-editor-preview-container {
|
||||
background: var(--gray-100);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ export class TypingsLoader {
|
||||
.readFile(`./node_modules/${library}/package.json`, 'utf-8')
|
||||
.catch((error) => {
|
||||
// Note: "ENOENT" errors occurs:
|
||||
// - While resetting the NodeRuntimeSandbox.
|
||||
// - While reseting the NodeRuntimeSandbox.
|
||||
// - When the library is not a dependency in the project, its package.json won't exist.
|
||||
//
|
||||
// In both cases we ignore the error to continue the process.
|
||||
|
||||
@@ -14,7 +14,7 @@ import {ActivatedRoute} from '@angular/router';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-docs',
|
||||
selector: 'adev-docs',
|
||||
standalone: true,
|
||||
imports: [CommonModule, DocViewer],
|
||||
styleUrls: ['./docs.component.scss'],
|
||||
|
||||
@@ -8,6 +8,13 @@
|
||||
</p>
|
||||
<p class="adev-banner-cta">Read about our beta launch</p>
|
||||
</a>
|
||||
<a href="https://goo.gle/angular-event" class="adev-banner" target="_blank">
|
||||
<p>
|
||||
<code>ng update</code>
|
||||
to Angular v17 on November 8th!
|
||||
</p>
|
||||
<p class="adev-banner-cta">Learn more</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="adev-canvas"></div>
|
||||
@@ -81,6 +88,6 @@
|
||||
</div>
|
||||
<div class="adev-arrow"></div>
|
||||
<a routerLink="{{ctaLink}}" class="adev-cta">
|
||||
<button class="docs-primary-btn" [attr.text]="'Learn Angular'" aria-label="Learn Angular">Learn Angular</button>
|
||||
<button class="adev-primary-btn" [attr.text]="'Learn Angular'" aria-label="Learn Angular">Learn Angular</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
width: 100%;
|
||||
|
||||
// While editor is loading, display an svg of the editor
|
||||
.docs-dark-mode & {
|
||||
.adev-dark-mode & {
|
||||
.adev-editor-scroll-container img {
|
||||
content: url('../../../assets/images/editor-dark-horizontal.svg');
|
||||
@include mq.for-tablet-down {
|
||||
@@ -12,7 +12,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.docs-light-mode & {
|
||||
.adev-light-mode & {
|
||||
.adev-editor-scroll-container img {
|
||||
content: url('../../../assets/images/editor-light-horizontal.svg');
|
||||
@include mq.for-tablet-down {
|
||||
@@ -142,8 +142,7 @@
|
||||
display: inline-block;
|
||||
padding: 7px;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transition: opacity 0.5s linear, visibility 0.5s linear;
|
||||
transition: opacity 0.5s linear;
|
||||
|
||||
button {
|
||||
font-size: 1rem;
|
||||
@@ -308,7 +307,6 @@
|
||||
.adev-cta,
|
||||
.adev-arrow {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiItemLabel from './api-item-label.component';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
|
||||
describe('ApiItemLabel', () => {
|
||||
let component: ApiItemLabel;
|
||||
@@ -24,32 +23,7 @@ describe('ApiItemLabel', () => {
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should by default display short label for Class', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
});
|
||||
|
||||
it('should display full label for Class when labelMode equals full', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'full';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('Class');
|
||||
});
|
||||
|
||||
it('should display short label for Class when labelMode equals short', () => {
|
||||
component.type = ApiItemType.CLASS;
|
||||
component.mode = 'short';
|
||||
fixture.detectChanges();
|
||||
|
||||
const label = fixture.nativeElement.innerText;
|
||||
|
||||
expect(label).toBe('C');
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from '../pipes/api-label.pipe';
|
||||
|
||||
@Component({
|
||||
selector: 'docs-api-item-label',
|
||||
selector: 'adev-api-item-label',
|
||||
standalone: true,
|
||||
templateUrl: './api-item-label.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@@ -9,16 +9,16 @@
|
||||
@for (apiItem of group.items; track apiItem.url) {
|
||||
<li [class.adev-api-items-section-item-deprecated]="apiItem.isDeprecated">
|
||||
<a [routerLink]="'/' + apiItem.url" class="adev-api-items-section-item" [attr.aria-describedby]="apiItem.isDeprecated ? 'deprecated-description' : null">
|
||||
<docs-api-item-label
|
||||
<adev-api-item-label
|
||||
[type]="apiItem.itemType"
|
||||
mode="short"
|
||||
class="docs-api-item-label"
|
||||
class="adev-api-item-label"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<span class="adev-item-title">{{ apiItem.title }}</span>
|
||||
</a>
|
||||
@if (apiItem.isDeprecated) {
|
||||
<span class="docs-deprecated">
|
||||
<span class="adev-deprecated">
|
||||
<!>
|
||||
</span>
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.docs-deprecated {
|
||||
.adev-deprecated {
|
||||
font-family: var(--code-font);
|
||||
background-color: var(--senary-contrast);
|
||||
color: var(--tertiary-contrast);
|
||||
|
||||
+4
-79
@@ -13,44 +13,17 @@ import {ApiItemsGroup} from '../interfaces/api-items-group';
|
||||
import {ApiReferenceManager} from '../api-reference-list/api-reference-manager.service';
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiItemsSection', () => {
|
||||
let component: ApiItemsSection;
|
||||
let fixture: ComponentFixture<ApiItemsSection>;
|
||||
let apiReferenceManagerSpy: jasmine.SpyObj<ApiReferenceManager>;
|
||||
|
||||
const fakeFeaturedGroup: ApiItemsGroup = {
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
title: 'Featured',
|
||||
isFeatured: true,
|
||||
items: [
|
||||
{
|
||||
title: 'Fake Featured Title',
|
||||
itemType: ApiItemType.CLASS,
|
||||
url: 'api/fakeFeaturedTitle',
|
||||
isFeatured: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Deprecated Title',
|
||||
itemType: ApiItemType.CONST,
|
||||
url: 'api/fakeDeprecatedTitle',
|
||||
isFeatured: false,
|
||||
isDeprecated: true,
|
||||
},
|
||||
{
|
||||
title: 'Fake Standard Title',
|
||||
itemType: ApiItemType.DIRECTIVE,
|
||||
url: 'api/fakeTitle',
|
||||
isFeatured: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const fakeGroup: ApiItemsGroup = {
|
||||
title: 'Example group',
|
||||
isFeatured: false,
|
||||
items: [
|
||||
{title: 'Fake Title', itemType: ApiItemType.CONST, url: 'api/fakeTitle', isFeatured: false},
|
||||
{title: 'Fake Title', itemType: ApiItemType.CLASS, url: 'api/fakeTitle', isFeatured: true},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -61,60 +34,12 @@ describe('ApiItemsSection', () => {
|
||||
});
|
||||
fixture = TestBed.createComponent(ApiItemsSection);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should render star icon for featured group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render star icon for standard group', () => {
|
||||
component.group = fakeGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const starIcon = fixture.debugElement.query(By.css('.adev-api-items-section-header docs-icon'));
|
||||
|
||||
expect(starIcon).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should render list of all APIs of provided group', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const apis = fixture.debugElement.queryAll(By.css('.adev-api-items-section-grid li'));
|
||||
|
||||
expect(apis.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should display deprecated icon for deprecated API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const deprecatedApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .docs-deprecated'),
|
||||
);
|
||||
const deprecatedApiTitle = deprecatedApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(deprecatedApiIcons.length).toBe(1);
|
||||
expect(deprecatedApiIcons[0]).toBeTruthy();
|
||||
expect(deprecatedApiTitle?.nativeElement.innerText).toBe('Fake Deprecated Title');
|
||||
});
|
||||
|
||||
it('should display star icon for featured API', () => {
|
||||
component.group = fakeFeaturedGroup;
|
||||
fixture.detectChanges();
|
||||
|
||||
const featuredApiIcons = fixture.debugElement.queryAll(
|
||||
By.css('.adev-api-items-section-grid li .adev-api-items-section-item-featured'),
|
||||
);
|
||||
const featuredApiTitle = featuredApiIcons[0].parent?.query(By.css('.adev-item-title'));
|
||||
|
||||
expect(featuredApiIcons.length).toBe(1);
|
||||
expect(featuredApiIcons[0]).toBeTruthy();
|
||||
expect(featuredApiTitle?.nativeElement.innerText).toBe('Fake Featured Title');
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
<div class="adev-header-and-tabs docs-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="headerInnerHtml()" class="docs-reference-header"></docs-viewer>
|
||||
<div class="adev-header-and-tabs adev-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="headerInnerHtml()" class="adev-reference-header"></docs-viewer>
|
||||
|
||||
<mat-tab-group class="docs-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()">
|
||||
<mat-tab-group class="adev-reference-tabs" animationDuration="0ms" mat-stretch-tabs="false" [selectedIndex]="selectedTabIndex()">
|
||||
@for (tab of tabs(); track tab) {
|
||||
<mat-tab [label]="tab.title">
|
||||
<div class="adev-reference-tab-body">
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
@if (canDisplayCards() && membersMarginTopInPx() > 0) {
|
||||
<docs-viewer
|
||||
class="docs-reference-members-container"
|
||||
class="adev-reference-members-container"
|
||||
[docContent]="membersInnerHtml()"
|
||||
[style.marginTop.px]="membersMarginTopInPx()"
|
||||
(contentLoaded)="membersCardsLoaded()">
|
||||
|
||||
+25
-25
@@ -38,7 +38,7 @@
|
||||
@include mq.for-desktop-up {
|
||||
// this section should only be independently scrollable if
|
||||
// the API tab is active & the screen is wide enough
|
||||
&:has(.docs-reference-api-tab),
|
||||
&:has(.adev-reference-api-tab),
|
||||
&.adev-cli-content {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -48,10 +48,10 @@
|
||||
overflow-y: scroll;
|
||||
width: 50%;
|
||||
}
|
||||
&:has(.docs-reference-api-tab) {
|
||||
&:has(.adev-reference-api-tab) {
|
||||
width: 60%;
|
||||
}
|
||||
&:not(.docs-reference-api-tab) {
|
||||
&:not(.adev-reference-api-tab) {
|
||||
max-width: var(--page-width);
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-header {
|
||||
.adev-reference-header {
|
||||
> p {
|
||||
color: var(--secondary-contrast);
|
||||
margin-block-start: 0;
|
||||
@@ -94,7 +94,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-api-tab {
|
||||
.adev-reference-api-tab {
|
||||
display: flex;
|
||||
gap: 1.81rem;
|
||||
align-items: flex-start;
|
||||
@@ -155,7 +155,7 @@
|
||||
margin-block-start: 2.5rem;
|
||||
}
|
||||
|
||||
.docs-reference-members-container {
|
||||
.adev-reference-members-container {
|
||||
width: 40%;
|
||||
padding: 0 var(--layout-padding) 1rem 0;
|
||||
box-sizing: border-box;
|
||||
@@ -172,7 +172,7 @@
|
||||
}
|
||||
|
||||
// Sidebar
|
||||
.docs-reference-members {
|
||||
.adev-reference-members {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
@@ -182,7 +182,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-title {
|
||||
.adev-reference-title {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
@@ -217,7 +217,7 @@
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.docs-reference-category {
|
||||
.adev-reference-category {
|
||||
color: var(--gray-400);
|
||||
font-size: 0.875rem;
|
||||
font-weight: 500;
|
||||
@@ -225,7 +225,7 @@
|
||||
letter-spacing: -0.00875rem;
|
||||
}
|
||||
|
||||
.docs-reference-member-card {
|
||||
.adev-reference-member-card {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
border-radius: 0.25rem;
|
||||
position: relative;
|
||||
@@ -248,7 +248,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:has(.docs-reference-card-body) {
|
||||
&:has(.adev-reference-card-body) {
|
||||
header {
|
||||
border-radius: 0.25rem 0.25rem 0 0;
|
||||
border-bottom: 1px solid var(--senary-contrast);
|
||||
@@ -266,7 +266,7 @@
|
||||
transition: background-color 0.3s ease, border 0.3s ease;
|
||||
|
||||
// h3 + code || # of overloads
|
||||
.docs-reference-header {
|
||||
.adev-reference-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
@@ -299,7 +299,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-card-body {
|
||||
.adev-reference-card-body {
|
||||
padding: 0.25rem 1.25rem;
|
||||
background: var(--septenary-contrast);
|
||||
transition: background-color 0.3s ease;
|
||||
@@ -316,14 +316,14 @@
|
||||
}
|
||||
|
||||
// when it's not the only card...
|
||||
.docs-reference-card-item:has(~ .docs-reference-card-item) {
|
||||
.adev-reference-card-item:has(~ .adev-reference-card-item) {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
margin-block: 1rem;
|
||||
border-radius: 0.25rem;
|
||||
padding-inline: 1rem;
|
||||
}
|
||||
// & the last card
|
||||
.docs-reference-card-item:last-child {
|
||||
.adev-reference-card-item:last-child {
|
||||
&:not(:first-of-type) {
|
||||
border: 1px solid var(--senary-contrast);
|
||||
margin-block: 1rem;
|
||||
@@ -332,7 +332,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-card-item {
|
||||
.adev-reference-card-item {
|
||||
span {
|
||||
display: inline-block;
|
||||
font-size: 0.875rem;
|
||||
@@ -342,31 +342,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-function-definition {
|
||||
.adev-function-definition {
|
||||
&:has(*) {
|
||||
border-block-end: 1px solid var(--senary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.docs-param-group {
|
||||
.adev-param-group {
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
// If it's the only param group...
|
||||
.docs-param-group:not(:has(~ .docs-param-group)) {
|
||||
.adev-param-group:not(:has(~ .adev-param-group)) {
|
||||
margin-block: 1rem;
|
||||
}
|
||||
|
||||
.docs-return-type {
|
||||
.adev-return-type {
|
||||
padding-block: 1rem;
|
||||
|
||||
// & does not follow a function definition
|
||||
&:not(.docs-function-definition + .docs-return-type) {
|
||||
&:not(.adev-function-definition + .adev-return-type) {
|
||||
border-block-start: 1px solid var(--senary-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.docs-param-keyword {
|
||||
.adev-param-keyword {
|
||||
color: var(--primary-contrast);
|
||||
font-family: var(--code-font);
|
||||
margin-inline-end: 0.5rem;
|
||||
@@ -381,7 +381,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-deprecated {
|
||||
.adev-deprecated {
|
||||
color: var(--page-background);
|
||||
background-color: var(--quaternary-contrast);
|
||||
width: max-content;
|
||||
@@ -391,11 +391,11 @@
|
||||
}
|
||||
|
||||
// deprecated markers beside header
|
||||
.docs-reference-header ~ .docs-deprecated {
|
||||
.adev-reference-header ~ .adev-deprecated {
|
||||
margin-block-start: 0.5rem;
|
||||
}
|
||||
|
||||
.docs-parameter-description {
|
||||
.adev-parameter-description {
|
||||
p:first-child {
|
||||
margin-block-start: 0;
|
||||
}
|
||||
|
||||
+7
-38
@@ -17,25 +17,22 @@ import {provideRouter} from '@angular/router';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
|
||||
import ApiReferenceDetailsPage from './api-reference-details-page.component';
|
||||
import {By} from '@angular/platform-browser';
|
||||
|
||||
describe('ApiReferenceDetailsPage', () => {
|
||||
let component: ApiReferenceDetailsPage;
|
||||
let loader: HarnessLoader;
|
||||
let harness: RouterTestingHarness;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
membersMarginTopInPx: signal(10),
|
||||
membersMarginTopInPx: signal(0),
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT_WITH_TABS = `<div class="docs-reference-tabs">
|
||||
<div data-tab="API" data-tab-url="api" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" data-tab-url="description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" data-tab-url="examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" data-tab-url="usage-notes" class="adev-reference-tab"></div>
|
||||
<div class="docs-reference-members-container"></div>
|
||||
const SAMPLE_CONTENT_WITH_TABS = `<div class="adev-reference-tabs">
|
||||
<div data-tab="API" class="adev-reference-tab"></div>
|
||||
<div data-tab="Description" class="adev-reference-tab"></div>
|
||||
<div data-tab="Examples" class="adev-reference-tab"></div>
|
||||
<div data-tab="Usage Notes" class="adev-reference-tab"></div>
|
||||
</div>`;
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -57,7 +54,7 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
harness = await RouterTestingHarness.create();
|
||||
const harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', ApiReferenceDetailsPage);
|
||||
loader = TestbedHarnessEnvironment.loader(fixture);
|
||||
@@ -75,32 +72,4 @@ describe('ApiReferenceDetailsPage', () => {
|
||||
|
||||
expect(tabs.length).toBe(4);
|
||||
}));
|
||||
|
||||
it('should display members cards when API tab is active', waitForAsync(async () => {
|
||||
const matTabGroup = await loader.getHarness(MatTabGroupHarness);
|
||||
const tabs = await matTabGroup.getTabs();
|
||||
|
||||
let membersCard = harness.fixture.debugElement.query(
|
||||
By.css('.docs-reference-members-container'),
|
||||
);
|
||||
expect(membersCard).toBeTruthy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[1].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.docs-reference-members-container'));
|
||||
expect(membersCard).toBeFalsy();
|
||||
|
||||
await matTabGroup.selectTab({label: await tabs[0].getLabel()});
|
||||
|
||||
membersCard = harness.fixture.debugElement.query(By.css('.docs-reference-members-container'));
|
||||
expect(membersCard).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should setup scroll listeners when API members are loaded', () => {
|
||||
const setupListenersSpy = spyOn(fakeApiReferenceScrollHandler, 'setupListeners');
|
||||
|
||||
component.membersCardsLoaded();
|
||||
|
||||
expect(setupListenersSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@
|
||||
[class.adev-reference-list-legend-item-active]="type() === itemType"
|
||||
(click)="filterByItemType(itemType)"
|
||||
>
|
||||
<docs-api-item-label [type]="itemType" mode="short" class="docs-api-item-label" />
|
||||
<adev-api-item-label [type]="itemType" mode="short" class="adev-api-item-label" />
|
||||
<span>{{ itemType | adevApiLabel : 'full' }}</span>
|
||||
</li>
|
||||
}
|
||||
@@ -40,5 +40,5 @@
|
||||
<adev-api-items-section [group]="group" />
|
||||
}
|
||||
|
||||
<span id="deprecated-description" class="docs-deprecated-description">Deprecated</span>
|
||||
<span id="deprecated-description" class="adev-deprecated-description">Deprecated</span>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -96,6 +96,6 @@
|
||||
}
|
||||
|
||||
|
||||
.docs-deprecated-description {
|
||||
.adev-deprecated-description {
|
||||
display: none;
|
||||
}
|
||||
|
||||
+1
-17
@@ -8,7 +8,7 @@
|
||||
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import ApiReferenceList, {ALL_STATUSES_KEY} from './api-reference-list.component';
|
||||
import ApiReferenceList from './api-reference-list.component';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {ApiReferenceManager} from './api-reference-manager.service';
|
||||
import {signal} from '@angular/core';
|
||||
@@ -95,20 +95,4 @@ describe('ApiReferenceList', () => {
|
||||
|
||||
expect(component.filteredGroups()![0].items).toEqual([fakeItem2]);
|
||||
});
|
||||
|
||||
it('should set selected type when provided type is different than selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
});
|
||||
|
||||
it('should reset selected type when provided type is equal to selected', () => {
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ApiItemType.BLOCK);
|
||||
|
||||
component.filterByItemType(ApiItemType.BLOCK);
|
||||
|
||||
expect(component.type()).toBe(ALL_STATUSES_KEY);
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<div class="adev-header-and-tabs adev-cli-content docs-scroll-track-transparent">
|
||||
<div class="adev-header-and-tabs adev-cli-content adev-scroll-track-transparent">
|
||||
<docs-viewer [docContent]="mainContentInnerHtml()" />
|
||||
</div>
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reference-type-and-default {
|
||||
.adev-reference-type-and-default {
|
||||
width: 4.375rem;
|
||||
flex-shrink: 0;
|
||||
span {
|
||||
|
||||
+7
-33
@@ -6,18 +6,16 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
|
||||
import CliReferenceDetailsPage from './cli-reference-details-page.component';
|
||||
import {RouterTestingHarness, RouterTestingModule} from '@angular/router/testing';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {signal} from '@angular/core';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {TestbedHarnessEnvironment} from '@angular/cdk/testing/testbed';
|
||||
|
||||
describe('CliReferenceDetailsPage', () => {
|
||||
let component: CliReferenceDetailsPage;
|
||||
let harness: RouterTestingHarness;
|
||||
let fixture: ComponentFixture<CliReferenceDetailsPage>;
|
||||
|
||||
let fakeApiReferenceScrollHandler = {
|
||||
setupListeners: () => {},
|
||||
@@ -25,42 +23,18 @@ describe('CliReferenceDetailsPage', () => {
|
||||
updateMembersMarginTop: () => {},
|
||||
};
|
||||
|
||||
const SAMPLE_CONTENT = `
|
||||
<div class="cli">
|
||||
<div class="docs-reference-cli-content">First column content</div>
|
||||
<div class="docs-reference-members-container">Members content</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
beforeEach(async () => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [CliReferenceDetailsPage, RouterTestingModule],
|
||||
providers: [
|
||||
provideRouter([
|
||||
{
|
||||
path: '**',
|
||||
component: CliReferenceDetailsPage,
|
||||
data: {
|
||||
'docContent': {
|
||||
id: 'id',
|
||||
contents: SAMPLE_CONTENT,
|
||||
},
|
||||
},
|
||||
},
|
||||
]),
|
||||
],
|
||||
});
|
||||
TestBed.overrideProvider(ReferenceScrollHandler, {useValue: fakeApiReferenceScrollHandler});
|
||||
|
||||
harness = await RouterTestingHarness.create();
|
||||
const {fixture} = harness;
|
||||
component = await harness.navigateByUrl('/', CliReferenceDetailsPage);
|
||||
TestbedHarnessEnvironment.loader(fixture);
|
||||
fixture = TestBed.createComponent(CliReferenceDetailsPage);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should set content on init', () => {
|
||||
expect(component.mainContentInnerHtml()).toBe('First column content');
|
||||
expect(component.cardsInnerHtml()).toBe('Members content');
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import {map} from 'rxjs/operators';
|
||||
import {ReferenceScrollHandler} from '../services/reference-scroll-handler.service';
|
||||
import {API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME} from '../constants/api-reference-prerender.constants';
|
||||
|
||||
export const CLI_MAIN_CONTENT_SELECTOR = '.docs-reference-cli-content';
|
||||
export const CLI_MAIN_CONTENT_SELECTOR = '.adev-reference-cli-content';
|
||||
export const CLI_TOC = '.adev-reference-cli-toc';
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
*/
|
||||
|
||||
export const API_REFERENCE_DETAILS_PAGE_CONTENT_CLASS_NAME = '.adev-reference-content';
|
||||
export const API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME = '.docs-reference-header';
|
||||
export const API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME = '.docs-reference-members-container';
|
||||
export const API_REFERENCE_DETAILS_PAGE_HEADER_CLASS_NAME = '.adev-reference-header';
|
||||
export const API_REFERENCE_DETAILS_PAGE_MEMBERS_CLASS_NAME = '.adev-reference-members-container';
|
||||
export const API_REFERENCE_TAB_BODY_CLASS_NAME = '.adev-reference-tab-body';
|
||||
export const API_REFERENCE_TAB_ATTRIBUTE = 'data-tab';
|
||||
export const API_REFERENCE_TAB_URL_ATTRIBUTE = 'data-tab-url';
|
||||
export const API_REFERENCE_TAB_API_LABEL = 'API';
|
||||
export const API_REFERENCE_TAB_QUERY_PARAM = 'tab';
|
||||
export const API_TAB_CLASS_NAME = '.docs-reference-api-tab';
|
||||
export const API_REFERENCE_MEMBER_CARD_CLASS_NAME = '.docs-reference-member-card';
|
||||
export const API_TAB_CLASS_NAME = '.adev-reference-api-tab';
|
||||
export const API_REFERENCE_MEMBER_CARD_CLASS_NAME = '.adev-reference-member-card';
|
||||
export const API_TAB_ACTIVE_CODE_LINE = 'hljs-ln-line-highlighted';
|
||||
export const HIGHLIGHT_JS_CODE_LINE_CLASS_NAME = 'hljs-ln-line';
|
||||
export const MEMBER_ID_ATTRIBUTE = 'member-id';
|
||||
|
||||
@@ -56,12 +56,10 @@ export function getApiNavigationItems(): NavigationItem[] {
|
||||
|
||||
const packageNavigationItem: NavigationItem = {
|
||||
label: packageNameWithoutPrefix,
|
||||
children: packageApis
|
||||
.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
}))
|
||||
.sort((a, b) => a.label.localeCompare(b.label)),
|
||||
children: packageApis.map((api) => ({
|
||||
path: getApiUrl(packageNameWithoutPrefix, api.name),
|
||||
label: api.name,
|
||||
})),
|
||||
};
|
||||
|
||||
apiNavigationItems.push(packageNavigationItem);
|
||||
|
||||
@@ -6,23 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {ApiItemType} from '../interfaces/api-item-type';
|
||||
import {ApiLabel} from './api-label.pipe';
|
||||
|
||||
describe('ApiLabel', () => {
|
||||
let pipe: ApiLabel;
|
||||
|
||||
beforeEach(() => {
|
||||
pipe = new ApiLabel();
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'short');
|
||||
expect(result).toBe('C');
|
||||
});
|
||||
|
||||
it(`should return short label when labelType equals short`, () => {
|
||||
const result = pipe.transform(ApiItemType.CLASS, 'full');
|
||||
expect(result).toBe('Class');
|
||||
it('create an instance', () => {
|
||||
const pipe = new ApiLabel();
|
||||
expect(pipe).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -160,9 +160,6 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(activeLines)) {
|
||||
line.classList.remove(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.getAllMemberCards().forEach((card) => {
|
||||
card.blur();
|
||||
});
|
||||
} else {
|
||||
const lines = this.document.querySelectorAll<HTMLButtonElement>(
|
||||
`button[${MEMBER_ID_ATTRIBUTE}="${currentActiveMemberId}"]`,
|
||||
@@ -170,7 +167,6 @@ export class ReferenceScrollHandler implements OnDestroy, ReferenceScrollHandler
|
||||
for (const line of Array.from(lines)) {
|
||||
line.classList.add(API_TAB_ACTIVE_CODE_LINE);
|
||||
}
|
||||
this.document.getElementById(`${currentActiveMemberId}`)?.focus();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@use '@angular/docs/styles/media-queries' as mq;
|
||||
|
||||
// horizontal tutorial nav bar
|
||||
// horizozntal tutorial nav bar
|
||||
.adev-tutorial-nav-container {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -21,7 +21,7 @@
|
||||
transition: background-color 0.3s ease;
|
||||
container: nav-container / inline-size;
|
||||
|
||||
&:has(.docs-reveal-answer-button) {
|
||||
&:has(.adev-reveal-answer-button) {
|
||||
@container tutorial-content (max-width: 430px) {
|
||||
padding-block-end: calc(1.5rem + 85px);
|
||||
}
|
||||
@@ -115,7 +115,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.docs-reveal-answer-button {
|
||||
.adev-reveal-answer-button {
|
||||
height: 2.875rem;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@if (shouldRenderContent()) {
|
||||
<div
|
||||
#content
|
||||
class="docs-tutorial-content"
|
||||
class="adev-tutorial-content"
|
||||
[class.adev-nav-open]="showNavigationDropdown()"
|
||||
>
|
||||
<!-- Tutorial Nav: Current Tutorial Title and Nav Buttons -->
|
||||
@@ -30,7 +30,7 @@
|
||||
@if (shouldRenderEmbeddedEditor()) {
|
||||
<div
|
||||
#editor
|
||||
class="docs-tutorial-editor"
|
||||
class="adev-tutorial-editor"
|
||||
[class.adev-split-tutorial]="shouldRenderContent()"
|
||||
>
|
||||
@if (embeddedEditorComponent) {
|
||||
@@ -59,7 +59,7 @@
|
||||
#revealAnswerButton
|
||||
(click)="answerRevealed() ? handleResetAnswer() : handleRevealAnswer()"
|
||||
[disabled]="!canRevealAnswer()"
|
||||
class="docs-reveal-answer-button adev-reveal-desktop-button docs-primary-btn"
|
||||
class="adev-reveal-answer-button adev-reveal-desktop-button adev-primary-btn"
|
||||
[attr.text]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[attr.aria-label]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[class.adev-reset-answer-button]="answerRevealed()"
|
||||
@@ -74,7 +74,7 @@
|
||||
[download]="stepName() + '.zip'"
|
||||
[href]="localTutorialZipUrl()"
|
||||
>
|
||||
<button class="adev-download-button docs-primary-btn">
|
||||
<button class="adev-download-button adev-primary-btn">
|
||||
<docs-icon>download</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
@@ -83,26 +83,26 @@
|
||||
<div class="adev-nav-arrows">
|
||||
@if (previousStepPath) {
|
||||
<a [routerLink]="previousStepPath">
|
||||
<button class="docs-primary-btn">
|
||||
<button class="adev-primary-btn">
|
||||
<docs-icon>chevron_left</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
}
|
||||
@if (!previousStepPath) {
|
||||
<button class="docs-primary-btn" disabled>
|
||||
<button class="adev-primary-btn" disabled>
|
||||
<docs-icon>chevron_left</docs-icon>
|
||||
</button>
|
||||
}
|
||||
|
||||
@if (nextStepPath) {
|
||||
<a [routerLink]="nextStepPath">
|
||||
<button class="docs-primary-btn">
|
||||
<button class="adev-primary-btn">
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
</button>
|
||||
</a>
|
||||
}
|
||||
@if (!nextStepPath) {
|
||||
<button class="docs-primary-btn" disabled>
|
||||
<button class="adev-primary-btn" disabled>
|
||||
<docs-icon>chevron_right</docs-icon>
|
||||
</button>
|
||||
}
|
||||
@@ -115,7 +115,7 @@
|
||||
#revealAnswerButton
|
||||
(click)="answerRevealed() ? handleResetAnswer() : handleRevealAnswer()"
|
||||
[disabled]="!canRevealAnswer()"
|
||||
class="docs-reveal-answer-button adev-reveal-mobile-button docs-primary-btn"
|
||||
class="adev-reveal-answer-button adev-reveal-mobile-button adev-primary-btn"
|
||||
[attr.text]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[attr.aria-label]="answerRevealed() ? 'Reset' : 'Reveal Answer'"
|
||||
[class.adev-reset-answer-button]="answerRevealed()"
|
||||
|
||||
@@ -36,8 +36,8 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
|
||||
// if there is an embedded editor in view, apply column width
|
||||
&:has(.docs-tutorial-editor) {
|
||||
.docs-tutorial-content {
|
||||
&:has(.adev-tutorial-editor) {
|
||||
.adev-tutorial-content {
|
||||
width: $column-width;
|
||||
|
||||
@include mq.for-tablet-landscape-down {
|
||||
@@ -50,7 +50,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
// if tutorial nav exists, size editor to fit vertically within viewport on mobile
|
||||
@include mq.for-tablet-landscape-down {
|
||||
&:has(.adev-tutorial-nav-container) {
|
||||
.docs-tutorial-editor {
|
||||
.adev-tutorial-editor {
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
|
||||
@include mq.for-phone-only {
|
||||
&:has(.adev-tutorial-nav-container) {
|
||||
.docs-tutorial-editor {
|
||||
.adev-tutorial-editor {
|
||||
// account for reveal answer button height when on smaller screens
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
@@ -66,7 +66,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
}
|
||||
|
||||
.docs-tutorial-content {
|
||||
.adev-tutorial-content {
|
||||
max-width: var(--page-width);
|
||||
min-width: 300px;
|
||||
width: 100%;
|
||||
@@ -127,7 +127,7 @@ $column-width: calc(50% - #{$resizer-width} - var(--layout-padding));
|
||||
}
|
||||
}
|
||||
|
||||
.docs-tutorial-editor {
|
||||
.adev-tutorial-editor {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -125,7 +125,6 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () => import('./features/home/home.component'),
|
||||
data: {label: 'Home'}
|
||||
},
|
||||
{
|
||||
path: PagePrefix.DOCS,
|
||||
@@ -142,7 +141,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: PagePrefix.PLAYGROUND,
|
||||
loadComponent: () => import('./features/playground/playground.component'),
|
||||
data: {...commonTutorialRouteData, label: 'Playground'},
|
||||
data: {...commonTutorialRouteData},
|
||||
},
|
||||
...SUB_NAVIGATION_ROUTES,
|
||||
...API_REFERENCE_ROUTES,
|
||||
|
||||
@@ -943,7 +943,6 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
{
|
||||
path: DefaultPage.TUTORIALS,
|
||||
contentPath: 'tutorials/home',
|
||||
label: 'Tutorials'
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1337,11 +1336,6 @@ const REFERENCE_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
path: 'reference/migrations/typed-forms',
|
||||
contentPath: 'reference/migrations/typed-forms',
|
||||
},
|
||||
{
|
||||
label: 'Control Flow Syntax',
|
||||
path: 'reference/migrations/control-flow',
|
||||
contentPath: 'reference/migrations/control-flow',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 157 288"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="docs-directives-svg"
|
||||
class="adev-directives-svg"
|
||||
>
|
||||
<g style="mix-blend-mode: multiply;">
|
||||
<path
|
||||
|
||||
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 433 182"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="docs-roadmap-svg"
|
||||
class="adev-roadmap-svg"
|
||||
>
|
||||
<path
|
||||
d="M26.0339 81.4492H316.739L406.475 153.601H114.71L26.0339 81.4492Z"
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
@@ -4,7 +4,7 @@
|
||||
viewBox="0 0 297 205"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="docs-what-is-angular-svg"
|
||||
class="adev-what-is-angular-svg"
|
||||
>
|
||||
<g style="mix-blend-mode: multiply;">
|
||||
<path
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -19,7 +19,7 @@ In the image above, there is a series of change detection calls triggered by eve
|
||||
|
||||
## Run tasks outside `NgZone`
|
||||
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/api/core/NgZone).
|
||||
In such cases, you can instruct Angular to avoid calling change detection for tasks scheduled by a given piece of code using [NgZone](/guide/zone).
|
||||
|
||||
<docs-code header="Run outside of the Zone" language='ts' linenums>
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -3,7 +3,6 @@ import { Architect } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { schema } from '@angular-devkit/core';
|
||||
import { promises as fs } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
describe('Copy File Builder', () => {
|
||||
let architect: Architect;
|
||||
@@ -20,7 +19,7 @@ describe('Copy File Builder', () => {
|
||||
|
||||
// This will either take a Node package name, or a path to the directory
|
||||
// for the package.json file.
|
||||
await architectHost.addBuilderFromPackage(join(__dirname, '..'));
|
||||
await architectHost.addBuilderFromPackage('..');
|
||||
});
|
||||
|
||||
it('can copy files', async () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// #docregion
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HeroModule } from './hero.module';
|
||||
import { HEROES } from './mock-heroes';
|
||||
|
||||
@Injectable({
|
||||
// we declare that this service should be created
|
||||
// by any injector that includes HeroModule.
|
||||
providedIn: HeroModule,
|
||||
})
|
||||
export class HeroService {
|
||||
getHeroes() { return HEROES; }
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('forms-overview App', () => {
|
||||
describe('forms-overvoew App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
load("//aio/content/examples:examples.bzl", "docs_example")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
docs_example(
|
||||
name = "providers",
|
||||
)
|
||||
@@ -0,0 +1,23 @@
|
||||
import { element, by } from 'protractor';
|
||||
import { AppPage } from './app.po';
|
||||
|
||||
describe('providers App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(async () => {
|
||||
page = new AppPage();
|
||||
await page.navigateTo();
|
||||
});
|
||||
|
||||
it('should display header that says Users list', async () => {
|
||||
expect(await page.getTitleText()).toEqual('Users list');
|
||||
});
|
||||
|
||||
it('shows a list of customers', async () => {
|
||||
const items = element.all(by.css('app-root li'));
|
||||
expect(await items.count()).toBe(10);
|
||||
expect(await items.get(0).getText()).toBe('1 Maria');
|
||||
expect(await items.get(9).getText()).toBe('10 Seth');
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
<h1>
|
||||
{{ title }}
|
||||
</h1>
|
||||
|
||||
<li *ngFor="let user of users">
|
||||
<span>{{ user.id }}</span> {{ user.name }}
|
||||
</li>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { User, UserService } from './user.service';
|
||||
|
||||
// #docregion component-providers
|
||||
@Component({
|
||||
// #enddocregion component-providers
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css'],
|
||||
// #docregion component-providers
|
||||
providers: [UserService]
|
||||
})
|
||||
// #enddocregion component-providers
|
||||
export class AppComponent implements OnInit {
|
||||
title = 'Users list';
|
||||
users: User[] = [];
|
||||
|
||||
constructor(private userService: UserService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.userService.getUsers().then(users => this.users = users);
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user