diff --git a/.github/workflows/build_all.yml b/.github/workflows/build_all.yml index 2067a377c7de..8116d73ffd1d 100644 --- a/.github/workflows/build_all.yml +++ b/.github/workflows/build_all.yml @@ -39,12 +39,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 3117e8c6ac29..c0b660b49fd5 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -33,12 +33,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/default_workflow.yml b/.github/workflows/default_workflow.yml index dab10b791215..27b7c4b20729 100644 --- a/.github/workflows/default_workflow.yml +++ b/.github/workflows/default_workflow.yml @@ -42,12 +42,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/demos_unit_tests.yml b/.github/workflows/demos_unit_tests.yml index 880b7763886e..e5c2928cea4c 100644 --- a/.github/workflows/demos_unit_tests.yml +++ b/.github/workflows/demos_unit_tests.yml @@ -55,12 +55,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 026da4b93f50..1816719ee6d4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,7 +12,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -40,12 +39,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -96,12 +93,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -140,12 +135,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -178,12 +171,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -227,12 +218,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/packages_publishing.yml b/.github/workflows/packages_publishing.yml index a65f8f264024..a84653d6491a 100644 --- a/.github/workflows/packages_publishing.yml +++ b/.github/workflows/packages_publishing.yml @@ -50,12 +50,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.PNPM_STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.PNPM_STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -150,12 +148,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.PNPM_STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.PNPM_STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/paths.yml b/.github/workflows/paths.yml index a19ec60fcaab..fe4389623dc6 100644 --- a/.github/workflows/paths.yml +++ b/.github/workflows/paths.yml @@ -13,7 +13,6 @@ on: env: MAX_LENGTH: 170 - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: diff --git a/.github/workflows/playgrounds_tests.yml b/.github/workflows/playgrounds_tests.yml index c63795bec9cc..f703c5f97389 100644 --- a/.github/workflows/playgrounds_tests.yml +++ b/.github/workflows/playgrounds_tests.yml @@ -12,7 +12,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -45,12 +44,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -120,12 +117,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/pr-storybook-deploy-manual.yml b/.github/workflows/pr-storybook-deploy-manual.yml index a6955d4a957b..96cfc87fe3a6 100644 --- a/.github/workflows/pr-storybook-deploy-manual.yml +++ b/.github/workflows/pr-storybook-deploy-manual.yml @@ -66,16 +66,14 @@ jobs: run: | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - - name: Setup pnpm + nx cache + - name: Setup pnpm cache if: inputs.action == 'deploy' uses: actions/cache@v4 with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies if: inputs.action == 'deploy' diff --git a/.github/workflows/publish-demos.yml b/.github/workflows/publish-demos.yml index ee81704afa95..66255d95fa61 100644 --- a/.github/workflows/publish-demos.yml +++ b/.github/workflows/publish-demos.yml @@ -25,12 +25,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: | @@ -59,7 +57,7 @@ jobs: devextreme-react-installer.tgz devextreme-vue-installer.tgz retention-days: 1 - + publish-ES: runs-on: ubuntu-latest needs: [build-devextreme-all] @@ -89,12 +87,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: | @@ -108,7 +104,7 @@ jobs: - name: Prepare configs working-directory: apps/demos run: pnpm run prepare-js - + - name: Copy metadata working-directory: apps/demos run: pnpm run make-demos-bundle --copy-metadata @@ -190,12 +186,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: | @@ -226,7 +220,7 @@ jobs: - name: Angular post process index.html working-directory: apps/demos run: pnpm run post-process-angular - + - name: Save publish-demos directory for Angular as an artifact uses: actions/upload-artifact@v4 with: @@ -236,7 +230,7 @@ jobs: deploy: runs-on: ubuntu-latest needs: [build-devextreme-all, publish-ES, publish-angular] - steps: + steps: - name: Download publish-demos artifact uses: actions/download-artifact@v4 with: diff --git a/.github/workflows/qunit_tests.yml b/.github/workflows/qunit_tests.yml index dbd0b3569282..1826a9c2cafd 100644 --- a/.github/workflows/qunit_tests.yml +++ b/.github/workflows/qunit_tests.yml @@ -13,7 +13,6 @@ on: workflow_dispatch: env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} RUN_ALL_TESTS: true @@ -54,12 +53,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/renovation.yml b/.github/workflows/renovation.yml index 45656a59b6be..9ecc5cc8ab07 100644 --- a/.github/workflows/renovation.yml +++ b/.github/workflows/renovation.yml @@ -12,7 +12,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -40,12 +39,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/run-testcafe-on-gh-pages.yml b/.github/workflows/run-testcafe-on-gh-pages.yml index 00d5e4203829..83890c9c5cbb 100644 --- a/.github/workflows/run-testcafe-on-gh-pages.yml +++ b/.github/workflows/run-testcafe-on-gh-pages.yml @@ -63,19 +63,17 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies working-directory: devextreme run: | corepack enable pnpm install --frozen-lockfile - + - name: Run TestCafe tests working-directory: devextreme/apps/demos env: diff --git a/.github/workflows/styles.yml b/.github/workflows/styles.yml index fc3160bc3d27..543df1d5caa0 100644 --- a/.github/workflows/styles.yml +++ b/.github/workflows/styles.yml @@ -12,7 +12,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -40,12 +39,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/testcafe_tests.yml b/.github/workflows/testcafe_tests.yml index a8a4290b09bf..d5be815f544e 100644 --- a/.github/workflows/testcafe_tests.yml +++ b/.github/workflows/testcafe_tests.yml @@ -13,7 +13,6 @@ on: workflow_dispatch: env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} RUN_TESTS: true @@ -69,9 +68,9 @@ jobs: name: Setup pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -176,9 +175,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/themebuilder_tests.yml b/.github/workflows/themebuilder_tests.yml index fae8008b019e..20e8186f6fac 100644 --- a/.github/workflows/themebuilder_tests.yml +++ b/.github/workflows/themebuilder_tests.yml @@ -12,7 +12,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -43,12 +42,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/ts_declarations.yml b/.github/workflows/ts_declarations.yml index 82ba85bcf70d..6fdfcfecb697 100644 --- a/.github/workflows/ts_declarations.yml +++ b/.github/workflows/ts_declarations.yml @@ -36,12 +36,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -87,12 +85,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/update_version.yml b/.github/workflows/update_version.yml index 848f66cc11a2..8c15b77d2f8d 100644 --- a/.github/workflows/update_version.yml +++ b/.github/workflows/update_version.yml @@ -40,12 +40,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -68,4 +66,4 @@ jobs: git commit -a -m "Bump devextreme version" git push --set-upstream origin $branch_name --force gh pr create --base ${{ inputs.branch_name }} --title "Bump devextreme version (${{ inputs.version }})" --body "Bump devextreme version" --reviewer DevExpress/devextreme-devops - + diff --git a/.github/workflows/visual-tests-demos.yml b/.github/workflows/visual-tests-demos.yml index 52ab6a5ed7c7..85c423cd6b10 100644 --- a/.github/workflows/visual-tests-demos.yml +++ b/.github/workflows/visual-tests-demos.yml @@ -13,7 +13,6 @@ on: workflow_dispatch: env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} RUN_TESTS: true @@ -132,9 +131,9 @@ jobs: name: Setup pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -225,9 +224,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -297,9 +296,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -367,9 +366,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -459,9 +458,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -550,9 +549,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -653,9 +652,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -813,9 +812,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -949,9 +948,9 @@ jobs: name: Restore pnpm cache with: path: ${{ env.STORE_PATH }} - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/wrapper_tests.yml b/.github/workflows/wrapper_tests.yml index 50e6025fe0b4..f096023bb2b2 100644 --- a/.github/workflows/wrapper_tests.yml +++ b/.github/workflows/wrapper_tests.yml @@ -8,7 +8,6 @@ on: branches: [26_1] env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -37,12 +36,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -75,12 +72,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -129,12 +124,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/wrapper_tests_e2e.yml b/.github/workflows/wrapper_tests_e2e.yml index 022816c61ff6..b134537394df 100644 --- a/.github/workflows/wrapper_tests_e2e.yml +++ b/.github/workflows/wrapper_tests_e2e.yml @@ -13,7 +13,6 @@ on: workflow_dispatch: env: - NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_TOKEN }} NX_SKIP_NX_CACHE: ${{ (github.event_name != 'pull_request' || contains( github.event.pull_request.labels.*.name, 'skip-cache')) && 'true' || 'false' }} jobs: @@ -43,12 +42,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -118,12 +115,10 @@ jobs: - uses: actions/cache@v4 name: Setup pnpm cache with: - path: | - ${{ env.STORE_PATH }} - .nx/cache - key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + path: ${{ env.STORE_PATH }} + key: 32477-${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: | - ${{ runner.os }}-pnpm-store + 32477-${{ runner.os }}-pnpm-store - name: Install dependencies run: pnpm install --frozen-lockfile @@ -142,6 +137,6 @@ jobs: if: ${{ failure() }} uses: actions/upload-artifact@v4 with: - name: test-fails-${{matrix.framework}} + name: test-fails-${{matrix.framework}} path: e2e/wrappers/screenshots - if-no-files-found: ignore \ No newline at end of file + if-no-files-found: ignore diff --git a/e2e/testcafe-devextreme/tests/dataGrid/common/editing/functional.ts b/e2e/testcafe-devextreme/tests/dataGrid/common/editing/functional.ts index b8df5f523f83..1a83cc1e8a3b 100644 --- a/e2e/testcafe-devextreme/tests/dataGrid/common/editing/functional.ts +++ b/e2e/testcafe-devextreme/tests/dataGrid/common/editing/functional.ts @@ -2149,6 +2149,99 @@ test('The onEditorPreparing event should be called once after clicking on a cell })(); }); +test('Adding rows to a second page should work correctly when initial row values ​​are specified in the onInitNewRow method (T1274123)', async (t) => { + // arrange + const dataGrid = new DataGrid('#container'); + const addAndSaveData = async () => { + // act + await dataGrid.apiAddRow(); + + const editPopup = dataGrid.getEditPopup(); + + // assert + await t + .expect(editPopup.isVisible()) + .ok(); + + // act + await dataGrid.apiSaveEditData(); + + // assert + await t + .expect(dataGrid.isReady()) + .ok() + .expect(editPopup.isVisible()) + .notOk(); + }; + + await t.expect(dataGrid.isReady()).ok(); + + // act + await dataGrid.apiPageIndex(1); + await t.expect(dataGrid.isReady()).ok(); + + // assert + let visibleRows = await dataGrid.apiGetVisibleRows(); + + await t.expect(visibleRows.length) + .eql(10) + .expect(dataGrid.getDataCell(20, 0).element.textContent) + .eql('21'); + + // act + await addAndSaveData(); + await addAndSaveData(); + + // assert + visibleRows = await dataGrid.apiGetVisibleRows(); + + await t + .expect(visibleRows.length) + .eql(12) + .expect(visibleRows[10].key) + .eql(31) + .expect(visibleRows[11].key) + .eql(32); +}).before(async () => { + await ClientFunction(() => { + (window as any).myData = new Array(30).fill(null).map((_, index) => ({ id: index + 1, text: `item ${index + 1}` })); + (window as any).myStore = new (window as any).DevExpress.data.ArrayStore({ + key: 'id', + data: (window as any).myData, + }); + })(); + + return createWidget('dxDataGrid', { + dataSource: { + key: 'id', + load(loadOptions) { + return (window as any).myStore.load(loadOptions); + }, + totalCount() { + return (window as any).myStore.totalCount(); + }, + insert(values) { + if (values.id === 0) { + values.id = (window as any).myData.length + 1; + } + + return (window as any).myStore.insert(values); + }, + } as any, + columns: ['id', 'text'], + showBorders: true, + editing: { + mode: 'popup', + allowAdding: true, + }, + onInitNewRow(e) { + e.data.id = 0; + e.data.text = 'test'; + }, + height: 300, + }); +}); + fixture`Editing - ShowEditorAlways` .page(url(__dirname, '../../../container.html')); diff --git a/nx.json b/nx.json index 7113236a0bd7..dfb7d794dcd2 100644 --- a/nx.json +++ b/nx.json @@ -1,7 +1,6 @@ { "extends": "nx/presets/npm.json", "$schema": "./node_modules/nx/schemas/nx-schema.json", - "nxCloudAccessToken": "ZDFmMzkyZTYtZmU5MC00MDMyLWI3NDktYjhhYWUxZWM4YTg3fHJlYWQ=", "plugins": ["./packages/nx-infra-plugin/dist"], "namedInputs": { "metadataToolsCommonInputs": [ diff --git a/packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/helpers/utils.ts b/packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/helpers/utils.ts index 6337eb7339a1..c093dfb2b7d9 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/helpers/utils.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/helpers/utils.ts @@ -5,6 +5,11 @@ import $ from '@js/core/renderer'; import type { Properties as DataGridProperties } from '@js/ui/data_grid'; import DataGrid from '@js/ui/data_grid'; import { DataGridModel } from '@ts/grids/data_grid/__tests__/__mock__/model/data_grid'; +import type { Controllers } from '@ts/grids/grid_core/m_types'; + +export interface DataGridInstance extends DataGrid { + getController: (name: T) => Controllers[T]; +} export const SELECTORS = { gridContainer: '#gridContainer', @@ -17,7 +22,7 @@ export const createDataGrid = async ( ): Promise<{ $container: dxElementWrapper; component: DataGridModel; - instance: DataGrid; + instance: DataGridInstance; }> => new Promise((resolve) => { const $container = $('
') .attr('id', GRID_CONTAINER_ID) @@ -28,7 +33,10 @@ export const createDataGrid = async ( ...options, }; - const instance = new DataGrid($container.get(0) as HTMLDivElement, dataGridOptions); + const instance = new DataGrid( + $container.get(0) as HTMLDivElement, + dataGridOptions, + ) as DataGridInstance; const component = new DataGridModel($container.get(0) as HTMLElement); jest.runAllTimers(); diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/__tests__/m_editing.integration.test.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/__tests__/m_editing.integration.test.ts index dbc797a2f41f..c34a6ea6c6e5 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/__tests__/m_editing.integration.test.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/__tests__/m_editing.integration.test.ts @@ -1,6 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, } from '@jest/globals'; +import CustomStore from '@ts/data/m_custom_store'; import { afterTest, @@ -9,40 +10,43 @@ import { flushAsync, } from '../../__tests__/__mock__/helpers/utils'; -const dataSource = [{ - ID: 1, - FirstName: 'John', - LastName: 'Heart', - Prefix: 'Mr.', - Position: 'CEO', - BirthDate: '1964/03/16', - HireDate: '1995/01/15', - Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.', - Address: '351 S Hill St.', -}, { - ID: 2, - FirstName: 'Olivia', - LastName: 'Peyton', - Prefix: 'Mrs.', - Position: 'Sales Assistant', - BirthDate: '1981/06/03', - HireDate: '2012/05/14', - Notes: 'Olivia loves to sell. She has been selling DevAV products since 2012. \r\n\r\nOlivia was homecoming queen in high school. She is expecting her first child in 6 months. Good Luck Olivia.', - Address: '807 W Paseo Del Mar', -}, { - ID: 3, - FirstName: 'Robert', - LastName: 'Reagan', - Prefix: 'Mr.', - Position: 'CMO', - BirthDate: '1974/09/07', - HireDate: '2002/11/08', - Notes: 'Robert was recently voted the CMO of the year by CMO Magazine. He is a proud member of the DevAV Management Team.\r\n\r\nRobert is a championship BBQ chef, so when you get the chance ask him for his secret recipe.', - Address: '4 Westmoreland Pl.', -}]; - describe('DataGrid editing', () => { - beforeEach(beforeTest); + let dataSource: Record[] = []; + + beforeEach(() => { + beforeTest(); + dataSource = [{ + ID: 1, + FirstName: 'John', + LastName: 'Heart', + Prefix: 'Mr.', + Position: 'CEO', + BirthDate: '1964/03/16', + HireDate: '1995/01/15', + Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.', + Address: '351 S Hill St.', + }, { + ID: 2, + FirstName: 'Olivia', + LastName: 'Peyton', + Prefix: 'Mrs.', + Position: 'Sales Assistant', + BirthDate: '1981/06/03', + HireDate: '2012/05/14', + Notes: 'Olivia loves to sell. She has been selling DevAV products since 2012. \r\n\r\nOlivia was homecoming queen in high school. She is expecting her first child in 6 months. Good Luck Olivia.', + Address: '807 W Paseo Del Mar', + }, { + ID: 3, + FirstName: 'Robert', + LastName: 'Reagan', + Prefix: 'Mr.', + Position: 'CMO', + BirthDate: '1974/09/07', + HireDate: '2002/11/08', + Notes: 'Robert was recently voted the CMO of the year by CMO Magazine. He is a proud member of the DevAV Management Team.\r\n\r\nRobert is a championship BBQ chef, so when you get the chance ask him for his secret recipe.', + Address: '4 Westmoreland Pl.', + }]; + }); afterEach(afterTest); // T1293181 @@ -97,4 +101,164 @@ describe('DataGrid editing', () => { expect(rows[recoveringRowIndex].data).toEqual(dataSource[recoveringRowIndex]); }); }); + + describe('Internal state cleanup after save', () => { + it('should clear internal state after updating and saving row', async () => { + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource, + editing: { + mode: 'batch', + allowUpdating: true, + }, + }); + + // Edit row using cellValue + instance.cellValue(0, 'FirstName', 'Updated'); + const editingController = instance.getController('editing'); + + // Verify internal state has entries before save + expect(editingController.getInternalStateSize()).toBe(1); + + // Save changes + instance.saveEditData(); + await flushAsync(); + + // Check internal state is cleared after save + expect(editingController.getInternalStateSize()).toBe(0); + }); + + it('should clear internal state after adding and saving row', async () => { + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource, + editing: { + mode: 'batch', + allowAdding: true, + }, + }); + + // Add new row + instance.addRow(); + await flushAsync(); + + const editingController = instance.getController('editing'); + expect(editingController.getInternalStateSize()).toBe(1); + + // Save changes + instance.saveEditData(); + await flushAsync(); + + // Check internal state is cleared + expect(editingController.getInternalStateSize()).toBe(0); + }); + + it('should clear internal state after deleting and saving row', async () => { + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource, + editing: { + mode: 'batch', + allowDeleting: true, + }, + }); + + // Delete row + instance.deleteRow(1); + + const editingController = instance.getController('editing'); + expect(editingController.getInternalStateSize()).toBe(1); + + // Save changes + instance.saveEditData(); + await flushAsync(); + + // Check internal state is cleared + expect(editingController.getInternalStateSize()).toBe(0); + }); + + it('should clear internal state for multiple operations after save', async () => { + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource, + editing: { + mode: 'batch', + allowUpdating: true, + allowAdding: true, + allowDeleting: true, + }, + }); + + // Multiple operations + instance.cellValue(0, 'FirstName', 'Updated'); + instance.deleteRow(1); + instance.addRow(); + await flushAsync(); + + const editingController = instance.getController('editing'); + expect(editingController.getInternalStateSize()).toBe(3); + + // Save all changes + instance.saveEditData(); + await flushAsync(); + + // Check internal state is completely cleared + expect(editingController.getInternalStateSize()).toBe(0); + }); + + it('should clear internal state when canceling changes', async () => { + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource, + editing: { + mode: 'batch', + allowUpdating: true, + allowAdding: true, + }, + }); + + // Make some changes + instance.cellValue(0, 'FirstName', 'Updated'); + instance.addRow(); + await flushAsync(); + + const editingController = instance.getController('editing'); + const stateBeforeCancel = editingController.getInternalStateSize(); + expect(stateBeforeCancel).toBe(2); + + // Cancel changes + instance.cancelEditData(); + + // Check internal state is cleared + expect(editingController.getInternalStateSize()).toBe(0); + }); + + it('should preserve internal state when save fails', async () => { + const failingDataSource = new CustomStore({ + key: 'ID', + load: () => Promise.resolve([...dataSource]), + update: () => Promise.reject(new Error('Save failed')), + }); + + const { instance } = await createDataGrid({ + keyExpr: 'ID', + dataSource: failingDataSource, + editing: { + mode: 'batch', + allowUpdating: true, + }, + }); + + instance.cellValue(0, 'FirstName', 'Updated'); + + const editingController = instance.getController('editing'); + + expect(editingController.getInternalStateSize()).toBe(1); + + instance.saveEditData(); + await flushAsync(); + + expect(editingController.getInternalStateSize()).toBe(1); + }); + }); }); diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts index b19c278be7fa..d7e0a5a091b8 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/m_editing.ts @@ -7,7 +7,7 @@ import { removeEvent } from '@js/common/core/events/remove'; import { addNamespace } from '@js/common/core/events/utils/index'; import messageLocalization from '@js/common/core/localization/message'; import { createObjectWithChanges } from '@js/common/data/array_utils'; -import type { GridsEditMode } from '@js/common/grids'; +import type { DataChange, GridsEditMode } from '@js/common/grids'; import devices from '@js/core/devices'; import domAdapter from '@js/core/dom_adapter'; import Guid from '@js/core/guid'; @@ -33,7 +33,9 @@ import type { HeaderPanel } from '@ts/grids/grid_core/header_panel/m_header_pane import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view'; import modules from '../m_modules'; -import type { Controllers, ModuleType, Views } from '../m_types'; +import type { + Controllers, ModuleType, RowKey, Views, +} from '../m_types'; import gridCoreUtils from '../m_utils'; import { ACTION_OPTION_NAMES, @@ -92,7 +94,9 @@ import { isEditingCell, isEditingOrShowEditorAlwaysDataCell, } from './m_editing_utils'; -import type { NormalizedEditCellOptions } from './types'; +import type { + InsertInfo, InternalEditData, NormalizedEditCellOptions, +} from './types'; class EditingControllerImpl extends modules.ViewController { protected _columnsController!: Controllers['columns']; @@ -133,7 +137,7 @@ class EditingControllerImpl extends modules.ViewController { protected _saveEditorHandler: any; - private _internalState!: Map; + private _internalState!: Map; protected _refocusEditCell: any; @@ -274,18 +278,19 @@ class EditingControllerImpl extends modules.ViewController { } } - private _getInternalData(key) { + private _getInternalData(key: RowKey): InternalEditData | undefined { return this._internalState.get(getKeyHash(key)); } - public _addInternalData(params) { + public _addInternalData(params: InternalEditData): InternalEditData { const internalData = this._getInternalData(params.key); if (internalData) { - return extend(internalData, params); + return extend(internalData, params) as InternalEditData; } this._internalState.set(getKeyHash(params.key), params); + return params; } @@ -774,6 +779,7 @@ class EditingControllerImpl extends modules.ViewController { this.update(changeType); const changes = this.getChanges(); + changes.forEach((change) => { const isInsert = change.type === DATA_EDIT_DATA_INSERT_TYPE; @@ -783,10 +789,10 @@ class EditingControllerImpl extends modules.ViewController { let { key } = change; - let insertInfo = this._getInternalData(key)?.insertInfo; + const insertInfo = this._getInternalData(key)?.insertInfo; + if (!isDefined(key) || !isDefined(insertInfo)) { - insertInfo = this._addInsertInfo(change); - key = insertInfo.key; + key = this._addInsertInfo(change).key; } const loadedRowIndex = this._getLoadedRowIndex(items, change); @@ -857,20 +863,22 @@ class EditingControllerImpl extends modules.ViewController { } } - private _createInsertInfo() { - const insertInfo = {}; - - insertInfo[INSERT_INDEX] = this._getInsertIndex(); - - return insertInfo; + private _createInsertInfo(): InsertInfo { + return { [INSERT_INDEX]: this._getInsertIndex() }; } - private _addInsertInfo(change, parentKey?) { - let insertInfo; + private _addInsertInfo( + change: Partial, + parentKey?: RowKey, + ): { insertInfo: InsertInfo; key: RowKey } { + let insertInfo: InsertInfo | undefined; + change.key = this.getChangeKeyValue(change); + const { key } = change; insertInfo = this._getInternalData(key)?.insertInfo; + if (!isDefined(insertInfo)) { const insertAfterOrBeforeKey = this._getInsertAfterOrBeforeKey(change); @@ -1042,7 +1050,7 @@ class EditingControllerImpl extends modules.ViewController { * @exteded: TreeList's editing */ protected _addRowCore(data, parentKey, initialOldEditRowIndex) { - const change = { data, type: DATA_EDIT_DATA_INSERT_TYPE }; + const change: Partial = { data, type: DATA_EDIT_DATA_INSERT_TYPE }; const editRowIndex = this._getVisibleEditRowIndex(); const insertInfo = this._addInsertInfo(change, parentKey); const { key } = insertInfo; @@ -1322,10 +1330,17 @@ class EditingControllerImpl extends modules.ViewController { return buttonConfig; } - private _removeInternalData(key) { + private _removeInternalData(key: RowKey): void { this._internalState.delete(getKeyHash(key)); } + private updateInternalDataKey(oldKey: RowKey, newKey: RowKey): void { + const internalData = this._getInternalData(oldKey) ?? {}; + + this._removeInternalData(oldKey); + this._addInternalData({ ...internalData, key: newKey }); + } + private _updateInsertAfterOrBeforeKeys(changes, index) { const removeChange = changes[index]; @@ -1612,7 +1627,10 @@ class EditingControllerImpl extends modules.ViewController { params = { data, cancel: false }; deferred = this._executeEditingAction('onRowInserting', params, () => store.insert(params.data).done((data, key) => { if (isDefined(key)) { + const initialKey = changeCopy.key; + changeCopy.key = key; + this.updateInternalDataKey(initialKey, key); } if (data && isObject(data) && data !== params.data) { changeCopy.data = data; @@ -1715,17 +1733,17 @@ class EditingControllerImpl extends modules.ViewController { private _fireSaveEditDataEvents(changes) { each(changes, (_, { data, key, type }) => { - const internalData = this._addInternalData({ key }); + const internalData = this._getInternalData(key); const params: any = { key, data }; - if (internalData.error) { + if (internalData?.error) { params.error = internalData.error; } // eslint-disable-next-line default-case switch (type) { case DATA_EDIT_DATA_REMOVE_TYPE: - this.executeAction('onRowRemoved', extend({}, params, { data: internalData.oldData })); + this.executeAction('onRowRemoved', extend({}, params, { data: internalData?.oldData })); break; case DATA_EDIT_DATA_INSERT_TYPE: this.executeAction('onRowInserted', params); @@ -1734,6 +1752,8 @@ class EditingControllerImpl extends modules.ViewController { this.executeAction('onRowUpdated', params); break; } + + this._removeInternalData(key); }); this.executeAction('onSaved', { changes }); @@ -2476,6 +2496,12 @@ class EditingControllerImpl extends modules.ViewController { protected _prepareEditCell(parameters: NormalizedEditCellOptions): boolean { return false; } + /// #DEBUG + public getInternalStateSize(): number { + return this._internalState.size; + } + /// #ENDDEBUG + public shouldHighlightCell(parameters) { const cellModified = this.isCellModified(parameters); return cellModified diff --git a/packages/devextreme/js/__internal/grids/grid_core/editing/types.ts b/packages/devextreme/js/__internal/grids/grid_core/editing/types.ts index a3602f14732b..e3360e331618 100644 --- a/packages/devextreme/js/__internal/grids/grid_core/editing/types.ts +++ b/packages/devextreme/js/__internal/grids/grid_core/editing/types.ts @@ -1,5 +1,7 @@ import type { Column } from '../columns_controller/m_columns_controller'; -import type { Item } from '../data_controller/m_data_controller'; +import type { Item, UserData } from '../data_controller/m_data_controller'; +import type { RowKey } from '../m_types'; +import type { INSERT_INDEX } from './const'; export interface NormalizedEditCellOptions { item: Item; @@ -9,3 +11,14 @@ export interface NormalizedEditCellOptions { oldRowIndex: number; rowIndex: number; } + +export interface InsertInfo { + [INSERT_INDEX]: number; +} + +export interface InternalEditData { + key: RowKey; + oldData?: UserData; + insertInfo?: InsertInfo; + error?: Error; +} diff --git a/packages/testcafe-models/dataGrid/editPopup.ts b/packages/testcafe-models/dataGrid/editPopup.ts new file mode 100644 index 000000000000..a86126cd03b7 --- /dev/null +++ b/packages/testcafe-models/dataGrid/editPopup.ts @@ -0,0 +1,4 @@ +import Popup from '../popup'; + +export default class EditPopup extends Popup { +} diff --git a/packages/testcafe-models/dataGrid/index.ts b/packages/testcafe-models/dataGrid/index.ts index 5bc809d69425..d97dee718e82 100644 --- a/packages/testcafe-models/dataGrid/index.ts +++ b/packages/testcafe-models/dataGrid/index.ts @@ -24,6 +24,7 @@ import { GroupPanel } from './groupPanel'; import GridCore from '../gridCore'; import { CLASS as CLASS_BASE } from '../gridCore'; import { AIPromptEditor } from './aiPromptEditor'; +import EditPopup from './editPopup'; export const CLASS = { ...CLASS_BASE, @@ -444,6 +445,10 @@ export default class DataGrid extends GridCore { return new EditForm(element, buttons); } + getEditPopup(): EditPopup { + return new EditPopup(Selector(`.${this.addWidgetPrefix(CLASS.popupEdit)}`)); + } + getToolbar(): Toolbar { return new Toolbar(this.element.find(`.${CLASS.toolbar}`)); } @@ -748,12 +753,18 @@ export default class DataGrid extends GridCore { )(); } - apiPageIndex(): Promise { + apiPageIndex(pageIndex?: number): Promise { const { getInstance } = this; return ClientFunction( - () => (getInstance() as any).pageIndex(), - { dependencies: { getInstance } }, + () => { + if (pageIndex === undefined) { + return (getInstance() as any).pageIndex(); + } + + (getInstance() as any).pageIndex(pageIndex); + }, + { dependencies: { getInstance, pageIndex } }, )(); }