From 716b64cfdc603e1910e28bb0a31e3e62961bd415 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 10:00:55 +0000 Subject: [PATCH 01/16] ci: add missing CI setup in line with sibling addons The repo had an abaplint.jsonc but no way to run it automatically: no workflows, no package.json, no .github/abaplint configs. Adds the same baseline the other addons have (ABAP_STANDARD, ABAP_CLOUD, rename_test workflows, cloud and rename abaplint configs, package.json with pinned @abaplint toolchain, .gitignore). All three checks verified locally with 0 issues on 20 files. Also points the README demo image at the abap2UI5-addons org the repo lives in today. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/abaplint/abap_cloud.jsonc | 46 ++++++++++ .github/abaplint/rename.json | 63 +++++++++++++ .github/workflows/ABAP_CLOUD.yaml | 20 +++++ .github/workflows/ABAP_STANDARD.yaml | 20 +++++ .github/workflows/rename_test.yaml | 20 +++++ .gitignore | 2 + README.md | 2 +- package-lock.json | 129 +++++++++++++++++++++++++++ package.json | 26 ++++++ 9 files changed, 327 insertions(+), 1 deletion(-) create mode 100644 .github/abaplint/abap_cloud.jsonc create mode 100644 .github/abaplint/rename.json create mode 100644 .github/workflows/ABAP_CLOUD.yaml create mode 100644 .github/workflows/ABAP_STANDARD.yaml create mode 100644 .github/workflows/rename_test.yaml create mode 100644 .gitignore create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/abaplint/abap_cloud.jsonc b/.github/abaplint/abap_cloud.jsonc new file mode 100644 index 0000000..b1c006e --- /dev/null +++ b/.github/abaplint/abap_cloud.jsonc @@ -0,0 +1,46 @@ +{ + "global": { + "files": "/../../src/**/*.*" + }, + "dependencies": [ + { + "url": "https://github.com/abapedia/steampunk-2305-api-intersect-702", + "folder": "/deps", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2UI5/abap2UI5", + "folder": "/abap2UI5", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2UI5-addons/popups", + "folder": "/popups", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2xlsx/abap2xlsx", + "folder": "/abap2xlsx", + "files": "/src/**/*.*" + } + ], + "syntax": { + "version": "Cloud", + "errorNamespace": "." + }, + "rules": { + "downport": true, + "begin_end_names": true, + "check_ddic": true, + "check_include": true, + "check_syntax": true, + "global_class": true, + "definitions_top": false, + "implement_methods": true, + "method_implemented_twice": true, + "parser_error": true, + "superclass_final": true, + "unknown_types": true, + "xml_consistency": true + } +} diff --git a/.github/abaplint/rename.json b/.github/abaplint/rename.json new file mode 100644 index 0000000..f430ae9 --- /dev/null +++ b/.github/abaplint/rename.json @@ -0,0 +1,63 @@ +{ + "global": { + "files": "/../../src/**/*.*" + }, + "dependencies": [ + { + "url": "https://github.com/abapedia/steampunk-2305-api-intersect-702", + "folder": "/deps", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2UI5/abap2UI5", + "folder": "/abap2UI5", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2UI5-addons/popups", + "folder": "/popups", + "files": "/src/**/*.*" + }, + { + "url": "https://github.com/abap2xlsx/abap2xlsx", + "folder": "/abap2xlsx", + "files": "/src/**/*.*" + } + ], + "rename": { + "output": "output", + "patterns": [ + { + "type": "CLAS|INTF|TABL", + "oldName": "z2ui5_(.*)", + "newName": "zabap2ui5_$1" + } + ] + }, + "syntax": { + "version": "v750", + "errorNamespace": "." + }, + "rules": { + "allowed_object_types": { + "allowed": [ + "CLAS", + "DEVC", + "INTF", + "TABL" + ] + }, + "allowed_object_naming": true, + "begin_end_names": true, + "check_ddic": true, + "check_include": true, + "check_syntax": true, + "global_class": true, + "implement_methods": true, + "method_implemented_twice": true, + "parser_error": true, + "superclass_final": true, + "unknown_types": true, + "xml_consistency": true + } +} diff --git a/.github/workflows/ABAP_CLOUD.yaml b/.github/workflows/ABAP_CLOUD.yaml new file mode 100644 index 0000000..2cf95d6 --- /dev/null +++ b/.github/workflows/ABAP_CLOUD.yaml @@ -0,0 +1,20 @@ +name: ABAP_CLOUD + +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + ABAP_CLOUD: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: npm ci + - run: npx abaplint .github/abaplint/abap_cloud.jsonc diff --git a/.github/workflows/ABAP_STANDARD.yaml b/.github/workflows/ABAP_STANDARD.yaml new file mode 100644 index 0000000..c6386ff --- /dev/null +++ b/.github/workflows/ABAP_STANDARD.yaml @@ -0,0 +1,20 @@ +name: ABAP_STANDARD + +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + ABAP_STANDARD: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: npm ci + - run: npx abaplint ./abaplint.jsonc diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml new file mode 100644 index 0000000..e65a583 --- /dev/null +++ b/.github/workflows/rename_test.yaml @@ -0,0 +1,20 @@ +name: rename_test + +on: + push: + branches: [main] + +permissions: + contents: read + +jobs: + rename_test: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + - run: npm ci + - run: npm run rename diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1406277 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +output diff --git a/README.md b/README.md index 11c54a1..c435727 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ _Supported Formats: JSON, CSV, XLSX..._ * XLSX Upload/Download for ABAP Cloud #### Demo -Table Content Loader start page with tiles for JSON, CSV and XLSX upload and download +Table Content Loader start page with tiles for JSON, CSV and XLSX upload and download #### Contribution & Support Pull Requests are welcome! Whether you're fixing a bug, adding new functionality, or improving the documentation, your contributions are always appreciated. If you run into problems, feel free to open an issue. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..bc1cdeb --- /dev/null +++ b/package-lock.json @@ -0,0 +1,129 @@ +{ + "name": "abap2ui5-table-content-loader", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "abap2ui5-table-content-loader", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@abaplint/cli": "^2.119.14", + "@abaplint/database-sqlite": "^2.11.78", + "@abaplint/runtime": "^2.13.22", + "@abaplint/transpiler-cli": "^2.13.22", + "@types/node": "^22.10.5", + "npm-check-updates": "^17.1.18" + } + }, + "node_modules/@abaplint/cli": { + "version": "2.119.65", + "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.119.65.tgz", + "integrity": "sha512-ezPrkiIOd31CR13G7KPGz0Hdhh5/ijx68N6aosOdYFsYEe+actT7N7WmM0xz+NjZkUNRC1xCA90HZv/lUE5hSQ==", + "dev": true, + "license": "MIT", + "bin": { + "abaplint": "abaplint" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/@abaplint/database-sqlite": { + "version": "2.13.40", + "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.13.40.tgz", + "integrity": "sha512-mgY84XJtoNThMXxNrsw9eq3Emc98lHMFlGJ9swz6nFJ5x+sivp5/lhr0SBJmFPnbg0KBj+dRb4Xgg3mKBABazQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sql.js": "^1.11.0" + } + }, + "node_modules/@abaplint/runtime": { + "version": "2.13.40", + "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.13.40.tgz", + "integrity": "sha512-Wm8eWtnzNaMiTaQ6CboRJqjHFlJ2S6JEC8QuMd6heAdtLZY5YBJidja6ityVzchAcoL5r+wrmyAyTJ4/m2LfgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "temporal-polyfill": "^0.3.2" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/@abaplint/transpiler-cli": { + "version": "2.13.40", + "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.13.40.tgz", + "integrity": "sha512-d7dVOIAJR3lVj+aV3Fsvk9drK9/sRYq0YkCyGxbB8xq7Qm1eC9WTXH0w0Rf9KSYiilcoHdE+QMxUr5rS4163MQ==", + "dev": true, + "license": "MIT", + "bin": { + "abap_transpile": "abap_transpile" + }, + "funding": { + "url": "https://github.com/sponsors/larshp" + } + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/npm-check-updates": { + "version": "17.1.18", + "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.18.tgz", + "integrity": "sha512-bkUy2g4v1i+3FeUf5fXMLbxmV95eG4/sS7lYE32GrUeVgQRfQEk39gpskksFunyaxQgTIdrvYbnuNbO/pSUSqw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "ncu": "build/cli.js", + "npm-check-updates": "build/cli.js" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0", + "npm": ">=8.12.1" + } + }, + "node_modules/sql.js": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz", + "integrity": "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/temporal-polyfill": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.3.2.tgz", + "integrity": "sha512-TzHthD/heRK947GNiSu3Y5gSPpeUDH34+LESnfsq8bqpFhsB79HFBX8+Z834IVX68P3EUyRPZK5bL/1fh437Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "temporal-spec": "0.3.1" + } + }, + "node_modules/temporal-spec": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.3.1.tgz", + "integrity": "sha512-B4TUhezh9knfSIMwt7RVggApDRJZo73uZdj8AacL2mZ8RP5KtLianh2MXxL06GN9ESYiIsiuoLQhgVfwe55Yhw==", + "dev": true, + "license": "ISC" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cbd4705 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "abap2ui5-table-content-loader", + "private": true, + "version": "1.0.0", + "description": "Upload, edit and download table content (JSON, CSV, XLSX), built with abap2UI5.", + "scripts": { + "rename": "abaplint .github/abaplint/rename.json --rename" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/abap2UI5-addons/table-content-loader.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/abap2UI5-addons/table-content-loader/issues" + }, + "homepage": "https://github.com/abap2UI5-addons/table-content-loader#readme", + "devDependencies": { + "@abaplint/cli": "^2.119.14", + "@abaplint/database-sqlite": "^2.11.78", + "@abaplint/runtime": "^2.13.22", + "@abaplint/transpiler-cli": "^2.13.22", + "@types/node": "^22.10.5", + "npm-check-updates": "^17.1.18" + } +} From 2d07f0e25713d93ac1192cf00a2cd65e412ba8ad Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 10:41:33 +0000 Subject: [PATCH 02/16] fix: correct row-limiting in table preview The preview kept the first five rows by deleting inside LOOP AT , but DELETE of the current row makes the loop skip the next one, so rows 7, 9, 11 ... survived alongside 1-5. Replaced with a single DELETE FROM 6, which keeps exactly the first five rows. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- src/z2ui5_cl_tcl_app_01.clas.abap | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/z2ui5_cl_tcl_app_01.clas.abap b/src/z2ui5_cl_tcl_app_01.clas.abap index a887a8a..c2510fa 100644 --- a/src/z2ui5_cl_tcl_app_01.clas.abap +++ b/src/z2ui5_cl_tcl_app_01.clas.abap @@ -127,16 +127,11 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. WHEN `PREVIEW`. DATA lr_tab TYPE REF TO data. - DATA lr_dummy TYPE REF TO data. lr_tab = z2ui5_cl_util=>conv_copy_ref_data( mt_tab ). ASSIGN lr_tab->* TO . - LOOP AT REFERENCE INTO lr_dummy. - IF sy-tabix > 5. - DELETE . - ENDIF. - ENDLOOP. + DELETE FROM 6. client->nav_app_call( z2ui5_cl_popup_table=>factory( ) ). From e5eb0c9a8ee035dfada9ed3d50ece68c9da02bde Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 10:44:13 +0000 Subject: [PATCH 03/16] ci: validate pull requests and add Dependabot The three workflows only triggered on push to main, so a PR with broken ABAP passed with no checks and the failure only surfaced after merge on a then-red main. Added pull_request as an additional trigger and a Dependabot config matching the other repos (weekly npm + github-actions, @abaplint grouped). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/dependabot.yml | 18 ++++++++++++++++++ .github/workflows/ABAP_CLOUD.yaml | 1 + .github/workflows/ABAP_STANDARD.yaml | 1 + .github/workflows/rename_test.yaml | 1 + 4 files changed, 21 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..9997317 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,18 @@ +# Keep the npm dependency tree and the GitHub Actions pinned versions +# up to date and covered by security alerts. +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + groups: + abaplint: + patterns: + - "@abaplint/*" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/workflows/ABAP_CLOUD.yaml b/.github/workflows/ABAP_CLOUD.yaml index 2cf95d6..4d250b1 100644 --- a/.github/workflows/ABAP_CLOUD.yaml +++ b/.github/workflows/ABAP_CLOUD.yaml @@ -3,6 +3,7 @@ name: ABAP_CLOUD on: push: branches: [main] + pull_request: permissions: contents: read diff --git a/.github/workflows/ABAP_STANDARD.yaml b/.github/workflows/ABAP_STANDARD.yaml index c6386ff..0ec924c 100644 --- a/.github/workflows/ABAP_STANDARD.yaml +++ b/.github/workflows/ABAP_STANDARD.yaml @@ -3,6 +3,7 @@ name: ABAP_STANDARD on: push: branches: [main] + pull_request: permissions: contents: read diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml index e65a583..1c5af4b 100644 --- a/.github/workflows/rename_test.yaml +++ b/.github/workflows/rename_test.yaml @@ -3,6 +3,7 @@ name: rename_test on: push: branches: [main] + pull_request: permissions: contents: read From 9405a0845afbcc70d214647312918bd9ad9a60b0 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 10:47:20 +0000 Subject: [PATCH 04/16] docs: note that authorization checks are the operator's responsibility This addon accesses data by table/SQL the user names and has no authorization check of its own by design (it is a developer tool). Document that explicitly and point operators at adding their own checks before using it beyond a development system. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index c435727..89c0d6e 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ _Supported Formats: JSON, CSV, XLSX..._ * S/4 Private Cloud or On-Premise (ABAP for Cloud, Standard ABAP) * SAP NetWeaver AS ABAP 7.50 or higher (Standard ABAP) +#### Security +This is a developer tool. It reads from and writes to any table the user names, without an authorization check of its own (the Z/Y namespace hint on write is only a warning, not an enforced restriction). Before using it beyond a development system, add your own authorization checks (e.g. `AUTHORITY-CHECK` on `S_TABU_DIS`/`S_TABU_NAM`) and restrict who may run the app. + #### Dependencies * [abap2UI5](https://github.com/abap2UI5/abap2UI5) * [popups](https://github.com/abap2UI5-addons/popups) From 1c0d026a924f51eeb71a697b53cf793d453a480f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 11:07:20 +0000 Subject: [PATCH 05/16] chore: remove Dependabot config Dependency updates will be handled manually. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/dependabot.yml | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 9997317..0000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Keep the npm dependency tree and the GitHub Actions pinned versions -# up to date and covered by security alerts. -version: 2 -updates: - - package-ecosystem: "npm" - directory: "/" - schedule: - interval: "weekly" - open-pull-requests-limit: 5 - groups: - abaplint: - patterns: - - "@abaplint/*" - - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" From 7b2b218939364a53a68ae10398db6a3bce234026 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 11:10:22 +0000 Subject: [PATCH 06/16] ci: add build_rename workflow for namespace branches Adds the same rename-branch feature abap2UI5 and frontend have: a workflow_dispatch that renames all artifacts to a chosen namespace and pushes the result to rename_ (e.g. rename_zmyui5), ready to pull with abapGit for a parallel installation in the same system. Reuses the existing .github/abaplint/rename.json (placeholder zabap2ui5) with the chosen name substituted; main is carried as second parent. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/workflows/build_rename.yaml | 101 ++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 .github/workflows/build_rename.yaml diff --git a/.github/workflows/build_rename.yaml b/.github/workflows/build_rename.yaml new file mode 100644 index 0000000..2452817 --- /dev/null +++ b/.github/workflows/build_rename.yaml @@ -0,0 +1,101 @@ +name: build_rename + +# Renames all artifacts to a chosen namespace and pushes the result to +# the branch rename_, e.g. rename_zmyui5 - ready to pull with +# abapGit for a parallel installation in the same SAP system. The +# renaming itself is the plain abaplint rename with the checked-in +# config .github/abaplint/rename.json (placeholder "zabap2ui5"); this +# workflow only sets the chosen name in the config and stores the +# result. Re-running with the same name updates the branch to the +# current main state; without content changes nothing is pushed. The +# main commit is carried as second parent so GitHub shows the branch as +# "ahead" instead of "behind" main. + +on: + workflow_dispatch: + inputs: + namespace: + description: "New namespace (max. 9 characters), e.g. ZMYUI5" + required: true + type: string + default: zabap2ui5 + +permissions: + contents: write + +concurrency: + group: build_rename-${{ inputs.namespace }} + cancel-in-progress: false + +jobs: + build_rename: + runs-on: ubuntu-latest + timeout-minutes: 15 + env: + NAMESPACE: ${{ inputs.namespace }} + steps: + # validate the input and derive the branch name before building + - name: Derive branch name + run: | + if ! printf '%s' "$NAMESPACE" | grep -Eq '^[A-Za-z][A-Za-z0-9_]{0,8}$'; then + echo "::error::Invalid namespace '$NAMESPACE' (letter + letters/digits/underscore, max. 9 characters)" + exit 1 + fi + ns=$(printf '%s' "$NAMESPACE" | tr '[:upper:]' '[:lower:]') + if [ "$ns" = "z2ui5" ]; then + echo "::error::Namespace '$NAMESPACE' is the original namespace - nothing to rename" + exit 1 + fi + echo "NS=$ns" >> "$GITHUB_ENV" + echo "BRANCH=rename_$ns" >> "$GITHUB_ENV" + echo "Building branch: rename_$ns" + + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: 'npm' + - run: npm ci + + # set the chosen name in the rename config and run the abaplint + # rename; it writes the renamed sources to + # .github/abaplint/output//src + - name: Rename to ${{ inputs.namespace }} + run: | + sed "s/zabap2ui5/$NS/g" .github/abaplint/rename.json > .github/abaplint/rename_run.json + npx abaplint .github/abaplint/rename_run.json --rename + + # branch content: the renamed src tree plus the abapGit descriptor + # and the license + - name: Assemble branch content + run: | + src=$(find .github/abaplint/output -type d -name src | head -n 1) + if [ -z "$src" ]; then + echo "::error::no renamed src folder found under .github/abaplint/output" + exit 1 + fi + out=".github/out/$BRANCH" + rm -rf "$out" + mkdir -p "$out" + cp -r "$src" "$out/src" + cp LICENSE "$out/" + cp .abapgit.xml "$out/" + + - name: Push renamed branch + run: | + b="$BRANCH" + git config user.name 'github-actions[bot]' + git config user.email 'github-actions[bot]@users.noreply.github.com' + git fetch origin "$b" --depth 1 2>/dev/null || true + parent=$(git rev-parse -q --verify "refs/remotes/origin/$b" || true) + index="$RUNNER_TEMP/index-$b" + rm -f "$index" + (cd ".github/out/$b" && GIT_DIR="$GITHUB_WORKSPACE/.git" GIT_WORK_TREE=. GIT_INDEX_FILE="$index" git add -A) + tree=$(GIT_INDEX_FILE="$index" git write-tree) + if [ -n "$parent" ] && [ "$(git rev-parse "$parent^{tree}")" = "$tree" ]; then + echo "$b: no changes" + exit 0 + fi + commit=$(git commit-tree "$tree" ${parent:+-p "$parent"} -p "$GITHUB_SHA" -m "build: $b from $GITHUB_SHA") + git push origin "$commit:refs/heads/$b" + echo "$b: pushed $commit" From 3f2d3a93fd27a30c4f39933ffc869f0b92bae2bd Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 11:12:39 +0000 Subject: [PATCH 07/16] chore: drop unused devDependencies Only @abaplint/cli is actually used (abaplint checks + rename). The transpiler/runtime/sqlite stack, @types/node and npm-check-updates had zero references - carried over from a template. abaplint still reports 0 issues after removal. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- package-lock.json | 99 +---------------------------------------------- package.json | 7 +--- 2 files changed, 2 insertions(+), 104 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc1cdeb..348dffb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,12 +9,7 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@abaplint/cli": "^2.119.14", - "@abaplint/database-sqlite": "^2.11.78", - "@abaplint/runtime": "^2.13.22", - "@abaplint/transpiler-cli": "^2.13.22", - "@types/node": "^22.10.5", - "npm-check-updates": "^17.1.18" + "@abaplint/cli": "^2.119.14" } }, "node_modules/@abaplint/cli": { @@ -32,98 +27,6 @@ "funding": { "url": "https://github.com/sponsors/larshp" } - }, - "node_modules/@abaplint/database-sqlite": { - "version": "2.13.40", - "resolved": "https://registry.npmjs.org/@abaplint/database-sqlite/-/database-sqlite-2.13.40.tgz", - "integrity": "sha512-mgY84XJtoNThMXxNrsw9eq3Emc98lHMFlGJ9swz6nFJ5x+sivp5/lhr0SBJmFPnbg0KBj+dRb4Xgg3mKBABazQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "sql.js": "^1.11.0" - } - }, - "node_modules/@abaplint/runtime": { - "version": "2.13.40", - "resolved": "https://registry.npmjs.org/@abaplint/runtime/-/runtime-2.13.40.tgz", - "integrity": "sha512-Wm8eWtnzNaMiTaQ6CboRJqjHFlJ2S6JEC8QuMd6heAdtLZY5YBJidja6ityVzchAcoL5r+wrmyAyTJ4/m2LfgA==", - "dev": true, - "license": "MIT", - "dependencies": { - "temporal-polyfill": "^0.3.2" - }, - "funding": { - "url": "https://github.com/sponsors/larshp" - } - }, - "node_modules/@abaplint/transpiler-cli": { - "version": "2.13.40", - "resolved": "https://registry.npmjs.org/@abaplint/transpiler-cli/-/transpiler-cli-2.13.40.tgz", - "integrity": "sha512-d7dVOIAJR3lVj+aV3Fsvk9drK9/sRYq0YkCyGxbB8xq7Qm1eC9WTXH0w0Rf9KSYiilcoHdE+QMxUr5rS4163MQ==", - "dev": true, - "license": "MIT", - "bin": { - "abap_transpile": "abap_transpile" - }, - "funding": { - "url": "https://github.com/sponsors/larshp" - } - }, - "node_modules/@types/node": { - "version": "22.20.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", - "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/npm-check-updates": { - "version": "17.1.18", - "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-17.1.18.tgz", - "integrity": "sha512-bkUy2g4v1i+3FeUf5fXMLbxmV95eG4/sS7lYE32GrUeVgQRfQEk39gpskksFunyaxQgTIdrvYbnuNbO/pSUSqw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "ncu": "build/cli.js", - "npm-check-updates": "build/cli.js" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0", - "npm": ">=8.12.1" - } - }, - "node_modules/sql.js": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sql.js/-/sql.js-1.14.1.tgz", - "integrity": "sha512-gcj8zBWU5cFsi9WUP+4bFNXAyF1iRpA3LLyS/DP5xlrNzGmPIizUeBggKa8DbDwdqaKwUcTEnChtd2grWo/x/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/temporal-polyfill": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/temporal-polyfill/-/temporal-polyfill-0.3.2.tgz", - "integrity": "sha512-TzHthD/heRK947GNiSu3Y5gSPpeUDH34+LESnfsq8bqpFhsB79HFBX8+Z834IVX68P3EUyRPZK5bL/1fh437Eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "temporal-spec": "0.3.1" - } - }, - "node_modules/temporal-spec": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/temporal-spec/-/temporal-spec-0.3.1.tgz", - "integrity": "sha512-B4TUhezh9knfSIMwt7RVggApDRJZo73uZdj8AacL2mZ8RP5KtLianh2MXxL06GN9ESYiIsiuoLQhgVfwe55Yhw==", - "dev": true, - "license": "ISC" - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" } } } diff --git a/package.json b/package.json index cbd4705..7c95b71 100644 --- a/package.json +++ b/package.json @@ -16,11 +16,6 @@ }, "homepage": "https://github.com/abap2UI5-addons/table-content-loader#readme", "devDependencies": { - "@abaplint/cli": "^2.119.14", - "@abaplint/database-sqlite": "^2.11.78", - "@abaplint/runtime": "^2.13.22", - "@abaplint/transpiler-cli": "^2.13.22", - "@types/node": "^22.10.5", - "npm-check-updates": "^17.1.18" + "@abaplint/cli": "^2.119.14" } } From ca5c1af49106360b83656c3671a973bc997fcded Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 11:39:30 +0000 Subject: [PATCH 08/16] refactor: vendor a tcl context class instead of calling z2ui5_cl_util Adopts the popups/samples pattern: table-content-loader now carries its own z2ui5_cl_tcl_context with the utility methods it uses (conv/itab/ json/xml/rtti helpers plus their private dependencies and the char constants), copied from the abap2UI5 utility class, instead of calling z2ui5_cl_util directly. The rtti attribute cache was dropped from the copy. abaplint: 0 issues, standard and cloud. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- src/z2ui5_cl_tcl_app_01.clas.abap | 4 +- src/z2ui5_cl_tcl_app_01.clas.testclasses.abap | 8 +- src/z2ui5_cl_tcl_app_02.clas.locals_imp.abap | 16 +- src/z2ui5_cl_tcl_app_03.clas.abap | 10 +- src/z2ui5_cl_tcl_app_04.clas.abap | 14 +- src/z2ui5_cl_tcl_app_05.clas.abap | 6 +- src/z2ui5_cl_tcl_app_06.clas.abap | 14 +- src/z2ui5_cl_tcl_context.clas.abap | 562 ++++++++++++++++++ src/z2ui5_cl_tcl_context.clas.xml | 16 + 9 files changed, 614 insertions(+), 36 deletions(-) create mode 100644 src/z2ui5_cl_tcl_context.clas.abap create mode 100644 src/z2ui5_cl_tcl_context.clas.xml diff --git a/src/z2ui5_cl_tcl_app_01.clas.abap b/src/z2ui5_cl_tcl_app_01.clas.abap index c2510fa..a064c7a 100644 --- a/src/z2ui5_cl_tcl_app_01.clas.abap +++ b/src/z2ui5_cl_tcl_app_01.clas.abap @@ -110,7 +110,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. CREATE DATA mt_tab TYPE STANDARD TABLE OF (ms_app-db_table). ASSIGN mt_tab->* TO . - z2ui5_cl_util=>json_parse( + z2ui5_cl_tcl_context=>json_parse( EXPORTING val = ms_app-file CHANGING @@ -128,7 +128,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. DATA lr_tab TYPE REF TO data. - lr_tab = z2ui5_cl_util=>conv_copy_ref_data( mt_tab ). + lr_tab = z2ui5_cl_tcl_context=>conv_copy_ref_data( mt_tab ). ASSIGN lr_tab->* TO . DELETE FROM 6. diff --git a/src/z2ui5_cl_tcl_app_01.clas.testclasses.abap b/src/z2ui5_cl_tcl_app_01.clas.testclasses.abap index a2ac6a6..0cf7fa7 100644 --- a/src/z2ui5_cl_tcl_app_01.clas.testclasses.abap +++ b/src/z2ui5_cl_tcl_app_01.clas.testclasses.abap @@ -17,11 +17,11 @@ CLASS ltcl_unit_test IMPLEMENTATION. DATA(lv_csv_base64) = `VXNlcm5hbWUsIElkZW50aWZpZXIsRmlyc3QgbmFtZSxMYXN0IG5hbWUNCmJvb2tlcjEyLDkwMTIsUmFjaGVsLEJvb2tlcg0KZ3JleTA3LDIwNzAsTGF1cmEsR3JleQ0Kam9obnNvbjgxLDQwODEsQ3JhaWcsSm9obnNvbg0KamVua2luczQ2LDkzNDYsTWFyeSxKZW5raW5zDQpzbWl0aDc5LDUwNzksSmFtaWUsU21pdGg=`. - DATA(lv_data) = z2ui5_cl_util=>conv_decode_x_base64( lv_csv_base64 ). - DATA(lv_ready) = z2ui5_cl_util=>conv_get_string_by_xstring( lv_data ). + DATA(lv_data) = z2ui5_cl_tcl_context=>conv_decode_x_base64( lv_csv_base64 ). + DATA(lv_ready) = z2ui5_cl_tcl_context=>conv_get_string_by_xstring( lv_data ). - DATA(lv_readyx) = z2ui5_cl_util=>conv_get_xstring_by_string( lv_ready ). - DATA(lv_data2) = z2ui5_cl_util=>conv_encode_x_base64( lv_readyx ). + DATA(lv_readyx) = z2ui5_cl_tcl_context=>conv_get_xstring_by_string( lv_ready ). + DATA(lv_data2) = z2ui5_cl_tcl_context=>conv_encode_x_base64( lv_readyx ). IF lv_data2 <> lv_csv_base64. ASSERT 1 = 0. diff --git a/src/z2ui5_cl_tcl_app_02.clas.locals_imp.abap b/src/z2ui5_cl_tcl_app_02.clas.locals_imp.abap index 4e33db1..067cda6 100644 --- a/src/z2ui5_cl_tcl_app_02.clas.locals_imp.abap +++ b/src/z2ui5_cl_tcl_app_02.clas.locals_imp.abap @@ -70,7 +70,7 @@ CLASS lcl_db IMPLEMENTATION. METHOD get_table_by_json. - z2ui5_cl_util=>json_parse( EXPORTING val = val + z2ui5_cl_tcl_context=>json_parse( EXPORTING val = val CHANGING data = result ). ENDMETHOD. @@ -78,7 +78,7 @@ CLASS lcl_db IMPLEMENTATION. METHOD get_table_by_xml. - z2ui5_cl_util=>xml_parse( EXPORTING xml = val + z2ui5_cl_tcl_context=>xml_parse( EXPORTING xml = val IMPORTING any = result ). ENDMETHOD. @@ -87,10 +87,10 @@ CLASS lcl_db IMPLEMENTATION. FIELD-SYMBOLS TYPE STANDARD TABLE. - DATA(lr_tab) = z2ui5_cl_util=>itab_get_itab_by_csv( val ). + DATA(lr_tab) = z2ui5_cl_tcl_context=>itab_get_itab_by_csv( val ). ASSIGN lr_tab->* TO . - z2ui5_cl_util=>itab_corresponding( EXPORTING val = + z2ui5_cl_tcl_context=>itab_corresponding( EXPORTING val = CHANGING tab = result ). ENDMETHOD. @@ -116,25 +116,25 @@ CLASS lcl_db IMPLEMENTATION. METHOD get_csv_by_table. - result = z2ui5_cl_util=>itab_get_csv_by_itab( val ). + result = z2ui5_cl_tcl_context=>itab_get_csv_by_itab( val ). ENDMETHOD. METHOD get_json_by_table. - result = z2ui5_cl_util=>json_stringify( val ). + result = z2ui5_cl_tcl_context=>json_stringify( val ). ENDMETHOD. METHOD get_xml_by_table. - result = z2ui5_cl_util=>xml_stringify( val ). + result = z2ui5_cl_tcl_context=>xml_stringify( val ). ENDMETHOD. METHOD get_fieldlist_by_table. - LOOP AT z2ui5_cl_util=>rtti_get_t_attri_by_any( it_table ) REFERENCE INTO DATA(lr_attri). + LOOP AT z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( it_table ) REFERENCE INTO DATA(lr_attri). INSERT CONV #( lr_attri->name ) INTO TABLE result. ENDLOOP. diff --git a/src/z2ui5_cl_tcl_app_03.clas.abap b/src/z2ui5_cl_tcl_app_03.clas.abap index bb44ab5..ff8416a 100644 --- a/src/z2ui5_cl_tcl_app_03.clas.abap +++ b/src/z2ui5_cl_tcl_app_03.clas.abap @@ -46,7 +46,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. METHOD factory_popup_by_itab. result = NEW #( ). - result->ms_app-itab = z2ui5_cl_util=>conv_copy_ref_data( itab ). + result->ms_app-itab = z2ui5_cl_tcl_context=>conv_copy_ref_data( itab ). result->ms_app-check_popup = abap_true. ENDMETHOD. @@ -95,7 +95,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. FIELD-SYMBOLS TYPE STANDARD TABLE. - mt_tab = z2ui5_cl_util=>rtti_create_tab_by_name( ms_app-db_table ). + mt_tab = z2ui5_cl_tcl_context=>rtti_create_tab_by_name( ms_app-db_table ). ASSIGN mt_tab->* TO . SELECT * @@ -104,7 +104,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. TRY. - ms_app-file = z2ui5_cl_util=>json_stringify( ). + ms_app-file = z2ui5_cl_tcl_context=>json_stringify( ). client->message_toast_display( |JSON created| ). CATCH cx_root INTO DATA(x). @@ -113,7 +113,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. WHEN `PREVIEW`. - mt_tab = z2ui5_cl_util=>rtti_create_tab_by_name( ms_app-db_table ). + mt_tab = z2ui5_cl_tcl_context=>rtti_create_tab_by_name( ms_app-db_table ). ASSIGN mt_tab->* TO . SELECT * @@ -121,7 +121,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. INTO CORRESPONDING FIELDS OF TABLE UP TO 10 ROWS. - DATA(lv_prev_json) = z2ui5_cl_util=>json_stringify( ). + DATA(lv_prev_json) = z2ui5_cl_tcl_context=>json_stringify( ). client->nav_app_call( z2ui5_cl_popup_textedit=>factory( lv_prev_json ) ). WHEN 'DOWNLOAD'. diff --git a/src/z2ui5_cl_tcl_app_04.clas.abap b/src/z2ui5_cl_tcl_app_04.clas.abap index a9d7d78..71952d0 100644 --- a/src/z2ui5_cl_tcl_app_04.clas.abap +++ b/src/z2ui5_cl_tcl_app_04.clas.abap @@ -43,10 +43,10 @@ CLASS Z2UI5_CL_TCL_APP_04 IMPLEMENTATION. WHEN 'UPLOAD'. - DATA(lv_data) = z2ui5_cl_util=>conv_get_xstring_by_data_uri( mv_value ). - DATA(lv_ready) = z2ui5_cl_util=>conv_get_string_by_xstring( lv_data ). + DATA(lv_data) = z2ui5_cl_tcl_context=>conv_get_xstring_by_data_uri( mv_value ). + DATA(lv_ready) = z2ui5_cl_tcl_context=>conv_get_string_by_xstring( lv_data ). - mr_table = z2ui5_cl_util=>itab_get_itab_by_csv( lv_ready ). + mr_table = z2ui5_cl_tcl_context=>itab_get_itab_by_csv( lv_ready ). client->message_box_display( `CSV loaded to table` ). ui5_view_main_display( ). @@ -96,9 +96,9 @@ CLASS Z2UI5_CL_TCL_APP_04 IMPLEMENTATION. FIELD-SYMBOLS TYPE table. ASSIGN mr_table->* TO . mv_check_download = abap_false. - DATA(lv_csv) = z2ui5_cl_util=>itab_get_csv_by_itab( ). - DATA(lv_xcsv) = z2ui5_cl_util=>conv_get_xstring_by_string( lv_csv ). - DATA(lv_base) = z2ui5_cl_util=>conv_encode_x_base64( lv_xcsv ). + DATA(lv_csv) = z2ui5_cl_tcl_context=>itab_get_csv_by_itab( ). + DATA(lv_xcsv) = z2ui5_cl_tcl_context=>conv_get_xstring_by_string( lv_csv ). + DATA(lv_base) = z2ui5_cl_tcl_context=>conv_encode_x_base64( lv_xcsv ). view->_cc_plain_xml( '' ). ENDIF. @@ -119,7 +119,7 @@ CLASS Z2UI5_CL_TCL_APP_04 IMPLEMENTATION. )->get_parent( )->get_parent( ). - DATA(lr_fields) = VALUE string_table( FOR row IN z2ui5_cl_util=>rtti_get_t_attri_by_any( ) ( row-name ) ). + DATA(lr_fields) = VALUE string_table( FOR row IN z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ) ( row-name ) ). DATA(lo_cols) = tab->columns( ). LOOP AT lr_fields REFERENCE INTO DATA(lr_col). lo_cols->column( )->text( lr_col->* ). diff --git a/src/z2ui5_cl_tcl_app_05.clas.abap b/src/z2ui5_cl_tcl_app_05.clas.abap index 93847c3..a267d3c 100644 --- a/src/z2ui5_cl_tcl_app_05.clas.abap +++ b/src/z2ui5_cl_tcl_app_05.clas.abap @@ -40,7 +40,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. WHEN 'UPLOAD'. - DATA(lv_xdata) = z2ui5_cl_util=>conv_get_xstring_by_data_uri( mv_value ). + DATA(lv_xdata) = z2ui5_cl_tcl_context=>conv_get_xstring_by_data_uri( mv_value ). mr_table = z2ui5_cl_tcl_xlsx_api=>get_table_by_xlsx( lv_xdata ). client->message_box_display( `XLSX loaded to table` ). @@ -83,7 +83,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. ASSIGN mr_table->* TO . mv_check_download = abap_false. DATA(lv_xlsx) = z2ui5_cl_tcl_xlsx_api=>get_xlsx_by_table( ). - DATA(lv_base) = z2ui5_cl_util=>conv_encode_x_base64( lv_xlsx ). + DATA(lv_base) = z2ui5_cl_tcl_context=>conv_encode_x_base64( lv_xlsx ). view->_generic( ns = `html` name = `iframe` t_prop = VALUE #( ( n = `src` v = `data:text/csv;base64,` && lv_base ) ( n = `hidden` v = `hidden` ) ) ). ENDIF. @@ -103,7 +103,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. customtextoff = 'View' )->get_parent( )->get_parent( ). - DATA(lr_fields) = z2ui5_cl_util=>rtti_get_t_attri_by_any( ). + DATA(lr_fields) = z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ). DATA(lo_cols) = tab->columns( ). LOOP AT lr_fields REFERENCE INTO DATA(lr_col). lo_cols->column( )->text( lr_col->name ). diff --git a/src/z2ui5_cl_tcl_app_06.clas.abap b/src/z2ui5_cl_tcl_app_06.clas.abap index 263912b..46659bb 100644 --- a/src/z2ui5_cl_tcl_app_06.clas.abap +++ b/src/z2ui5_cl_tcl_app_06.clas.abap @@ -70,7 +70,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. TRY. - DATA(lr_tab) = z2ui5_cl_util=>rtti_create_tab_by_name( ms_draft-table_name ). + DATA(lr_tab) = z2ui5_cl_tcl_context=>rtti_create_tab_by_name( ms_draft-table_name ). FIELD-SYMBOLS TYPE table. ASSIGN lr_tab->* TO . @@ -93,7 +93,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. title = ms_draft-t_config_head[ 1 ]-title settings = ms_draft-t_config[ 1 ] fieldcatalog = ms_draft-t_fcat ). - mv_file = z2ui5_cl_util=>conv_encode_x_base64( lv_result ). + mv_file = z2ui5_cl_tcl_context=>conv_encode_x_base64( lv_result ). ms_draft-file_rows = lines( ). ms_draft-file_size = xstrlen( lv_result ) / 1000. @@ -126,7 +126,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. ms_draft-table_name = CAST z2ui5_cl_popup_input_val( lo_prev )->result( )-value. ms_draft-check_load_pressed = abap_true. - ms_draft-t_tab = z2ui5_cl_util=>rtti_create_tab_by_name( ms_draft-table_name ). + ms_draft-t_tab = z2ui5_cl_tcl_context=>rtti_create_tab_by_name( ms_draft-table_name ). FIELD-SYMBOLS TYPE table. ASSIGN ms_draft-t_tab->* TO . @@ -340,7 +340,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. )->button( text = `Reset` press = client->_event( `RESET_CONFIG` ) icon = `sap-icon://refresh` type = `Emphasized` )->get_parent( )->get_parent( ). - DATA(lt_fields) = z2ui5_cl_util=>rtti_get_t_attri_by_any( ms_draft-t_config ). + DATA(lt_fields) = z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ms_draft-t_config ). DATA(lo_columns) = tab->columns( ). LOOP AT lt_fields INTO DATA(lv_field) FROM 1. @@ -368,7 +368,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. )->button( text = `Reset` press = client->_event( `RESET_CONFIG` ) icon = `sap-icon://refresh` type = `Emphasized` )->get_parent( )->get_parent( ). - lt_fields = z2ui5_cl_util=>rtti_get_t_attri_by_any( ms_draft-t_config_head ). + lt_fields = z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ms_draft-t_config_head ). lo_columns = tab->columns( ). LOOP AT lt_fields INTO lv_field FROM 1. @@ -401,7 +401,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. )->button( text = `Reset` press = client->_event( `RESET_FCAT` ) icon = `sap-icon://refresh` type = `Emphasized` )->get_parent( )->get_parent( ). - DATA(lt_fields) = z2ui5_cl_util=>rtti_get_t_attri_by_any( ms_draft-t_fcat ). + DATA(lt_fields) = z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ms_draft-t_fcat ). DATA(lo_columns) = tab->columns( ). LOOP AT lt_fields INTO DATA(lv_field) FROM 1. @@ -469,7 +469,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. )->button( text = `Reset` press = client->_event( `LOAD` ) icon = `sap-icon://refresh` type = `Emphasized` )->get_parent( )->get_parent( ). - DATA(lt_fields) = z2ui5_cl_util=>rtti_get_t_attri_by_any( ). + DATA(lt_fields) = z2ui5_cl_tcl_context=>rtti_get_t_attri_by_any( ). DATA(lo_columns) = tab->columns( ). LOOP AT lt_fields INTO DATA(lv_field) FROM 1. diff --git a/src/z2ui5_cl_tcl_context.clas.abap b/src/z2ui5_cl_tcl_context.clas.abap new file mode 100644 index 0000000..c7f712c --- /dev/null +++ b/src/z2ui5_cl_tcl_context.clas.abap @@ -0,0 +1,562 @@ +CLASS z2ui5_cl_tcl_context DEFINITION + PUBLIC + CREATE PUBLIC. + + PUBLIC SECTION. + + "! Vendored copy of the abap2UI5 utility methods this app uses, so the + "! app carries its own context instead of depending on z2ui5_cl_util. + CLASS-DATA cv_char_util_newline TYPE c LENGTH 1 READ-ONLY. + CLASS-DATA cv_char_util_cr_lf TYPE c LENGTH 2 READ-ONLY. + CLASS-DATA cv_char_util_horizontal_tab TYPE c LENGTH 1 READ-ONLY. + + CLASS-METHODS class_constructor. + + CLASS-METHODS conv_copy_ref_data + IMPORTING + !from TYPE any + RETURNING + VALUE(result) TYPE REF TO data. + + CLASS-METHODS conv_decode_x_base64 + IMPORTING + val TYPE string + RETURNING + VALUE(result) TYPE xstring. + + CLASS-METHODS conv_encode_x_base64 + IMPORTING + val TYPE xstring + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS conv_get_string_by_xstring + IMPORTING + val TYPE xstring + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS conv_get_xstring_by_data_uri + IMPORTING + val TYPE clike + RETURNING + VALUE(result) TYPE xstring. + + CLASS-METHODS conv_get_xstring_by_string + IMPORTING + val TYPE string + RETURNING + VALUE(result) TYPE xstring. + + CLASS-METHODS itab_corresponding + IMPORTING + val TYPE STANDARD TABLE + CHANGING + !tab TYPE STANDARD TABLE. + + CLASS-METHODS itab_get_csv_by_itab + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS itab_get_itab_by_csv + IMPORTING + val TYPE string + RETURNING + VALUE(result) TYPE REF TO data. + + CLASS-METHODS json_parse + IMPORTING + val TYPE any + CHANGING + !data TYPE any. + + CLASS-METHODS json_stringify + IMPORTING + !any TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS rtti_create_tab_by_name + IMPORTING + val TYPE clike + RETURNING + VALUE(result) TYPE REF TO data. + + CLASS-METHODS rtti_get_t_attri_by_any + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE cl_abap_structdescr=>component_table. + + CLASS-METHODS xml_parse + IMPORTING + !xml TYPE clike + EXPORTING + !any TYPE any. + + CLASS-METHODS xml_stringify + IMPORTING + !any TYPE any + RETURNING + VALUE(result) TYPE string + RAISING + cx_xslt_serialization_error. + + PROTECTED SECTION. + + CLASS-METHODS c_trim + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS c_trim_upper + IMPORTING + val TYPE clike + RETURNING + VALUE(result) TYPE string. + + CLASS-METHODS rtti_check_ref_data + IMPORTING + val TYPE any + RETURNING + VALUE(result) TYPE abap_bool. + + CLASS-METHODS rtti_get_t_attri_by_include + IMPORTING + !type TYPE REF TO cl_abap_datadescr + RETURNING + VALUE(result) TYPE abap_component_tab. + + PRIVATE SECTION. +ENDCLASS. + + +CLASS z2ui5_cl_tcl_context IMPLEMENTATION. + + METHOD class_constructor. + + cv_char_util_newline = cl_abap_char_utilities=>newline. + cv_char_util_cr_lf = cl_abap_char_utilities=>cr_lf. + cv_char_util_horizontal_tab = cl_abap_char_utilities=>horizontal_tab. + + ENDMETHOD. + + METHOD conv_copy_ref_data. + + FIELD-SYMBOLS TYPE data. + FIELD-SYMBOLS TYPE data. + + IF rtti_check_ref_data( from ). + ASSIGN from->* TO . + ELSE. + ASSIGN from TO . + ENDIF. + CREATE DATA result LIKE . + ASSIGN result->* TO . + + = . + + ENDMETHOD. + + METHOD conv_decode_x_base64. + DATA lv_web_http_name TYPE c LENGTH 19. + DATA classname TYPE c LENGTH 15. + + TRY. + + lv_web_http_name = `CL_WEB_HTTP_UTILITY`. + CALL METHOD (lv_web_http_name)=>(`DECODE_X_BASE64`) + EXPORTING + encoded = val + RECEIVING + decoded = result. + + CATCH cx_root. + + classname = `CL_HTTP_UTILITY`. + CALL METHOD (classname)=>(`DECODE_X_BASE64`) + EXPORTING + encoded = val + RECEIVING + decoded = result. + + ENDTRY. + + ENDMETHOD. + + METHOD conv_encode_x_base64. + DATA lv_web_http_name TYPE c LENGTH 19. + DATA classname TYPE c LENGTH 15. + + TRY. + + lv_web_http_name = `CL_WEB_HTTP_UTILITY`. + CALL METHOD (lv_web_http_name)=>(`ENCODE_X_BASE64`) + EXPORTING + unencoded = val + RECEIVING + encoded = result. + + CATCH cx_root. + + classname = `CL_HTTP_UTILITY`. + CALL METHOD (classname)=>(`ENCODE_X_BASE64`) + EXPORTING + unencoded = val + RECEIVING + encoded = result. + + ENDTRY. + + ENDMETHOD. + + METHOD conv_get_string_by_xstring. + + DATA conv TYPE REF TO object. + DATA conv_codepage TYPE c LENGTH 21. + DATA conv_in_class TYPE c LENGTH 18. + + TRY. + + conv_codepage = `CL_ABAP_CONV_CODEPAGE`. + CALL METHOD (conv_codepage)=>create_in + RECEIVING + instance = conv. + + CALL METHOD conv->(`IF_ABAP_CONV_IN~CONVERT`) + EXPORTING + source = val + RECEIVING + result = result. + + CATCH cx_root. + + conv_in_class = `CL_ABAP_CONV_IN_CE`. + CALL METHOD (conv_in_class)=>create + EXPORTING + encoding = `UTF-8` + RECEIVING + conv = conv. + + CALL METHOD conv->(`CONVERT`) + EXPORTING + input = val + IMPORTING + data = result. + ENDTRY. + + ENDMETHOD. + + METHOD conv_get_xstring_by_data_uri. + + DATA lv_metadata TYPE string ##NEEDED. + DATA lv_base64 TYPE string. + + SPLIT val AT `,` INTO lv_metadata lv_base64. + result = conv_decode_x_base64( lv_base64 ). + + ENDMETHOD. + + METHOD conv_get_xstring_by_string. + + DATA conv TYPE REF TO object. + DATA conv_codepage TYPE c LENGTH 21. + DATA conv_out_class TYPE c LENGTH 19. + + TRY. + + conv_codepage = `CL_ABAP_CONV_CODEPAGE`. + CALL METHOD (conv_codepage)=>create_out + RECEIVING + instance = conv. + + CALL METHOD conv->(`IF_ABAP_CONV_OUT~CONVERT`) + EXPORTING + source = val + RECEIVING + result = result. + + CATCH cx_root. + + conv_out_class = `CL_ABAP_CONV_OUT_CE`. + CALL METHOD (conv_out_class)=>create + EXPORTING + encoding = `UTF-8` + RECEIVING + conv = conv. + + CALL METHOD conv->(`CONVERT`) + EXPORTING + data = val + IMPORTING + buffer = result. + ENDTRY. + + ENDMETHOD. + + METHOD itab_corresponding. + + FIELD-SYMBOLS TYPE any. + FIELD-SYMBOLS TYPE any. + + LOOP AT val ASSIGNING . + APPEND INITIAL LINE TO tab ASSIGNING . + MOVE-CORRESPONDING TO . + ENDLOOP. + + ENDMETHOD. + + METHOD itab_get_csv_by_itab. + + FIELD-SYMBOLS TYPE table. + DATA lt_lines TYPE string_table. + DATA lv_line TYPE string. + + ASSIGN val TO . + DATA(tab) = CAST cl_abap_tabledescr( cl_abap_typedescr=>describe_by_data( ) ). + + DATA(struc) = CAST cl_abap_structdescr( tab->get_table_line_type( ) ). + + CLEAR lv_line. + LOOP AT struc->get_components( ) REFERENCE INTO DATA(lr_comp). + lv_line = |{ lv_line }{ lr_comp->name };|. + ENDLOOP. + INSERT lv_line INTO TABLE lt_lines. + + DATA lr_row TYPE REF TO data. + LOOP AT REFERENCE INTO lr_row. + + CLEAR lv_line. + DATA(lv_index) = 1. + DO. + ASSIGN lr_row->* TO FIELD-SYMBOL(). + ASSIGN COMPONENT lv_index OF STRUCTURE TO FIELD-SYMBOL(). + IF sy-subrc <> 0. + EXIT. + ENDIF. + lv_index = lv_index + 1. + DATA(lv_field_val) = |{ }|. + REPLACE ALL OCCURRENCES OF `;` IN lv_field_val WITH `,`. + lv_line = |{ lv_line }{ lv_field_val };|. + ENDDO. + INSERT lv_line INTO TABLE lt_lines. + ENDLOOP. + + result = concat_lines_of( table = lt_lines sep = cv_char_util_cr_lf ). + + ENDMETHOD. + + METHOD itab_get_itab_by_csv. + + DATA lt_comp TYPE cl_abap_structdescr=>component_table. + FIELD-SYMBOLS TYPE STANDARD TABLE. + DATA lr_row TYPE REF TO data. + + SPLIT val AT cv_char_util_newline INTO TABLE DATA(lt_rows). + SPLIT lt_rows[ 1 ] AT `;` INTO TABLE DATA(lt_cols). + + LOOP AT lt_cols REFERENCE INTO DATA(lr_col). + + DATA(lv_name) = c_trim_upper( lr_col->* ). + REPLACE ALL OCCURRENCES OF ` ` IN lv_name WITH `_`. + + INSERT VALUE #( name = lv_name + type = cl_abap_elemdescr=>get_c( 40 ) ) INTO TABLE lt_comp. + ENDLOOP. + + DATA(struc) = cl_abap_structdescr=>get( lt_comp ). + DATA(data) = CAST cl_abap_datadescr( struc ). + DATA(o_table_desc) = cl_abap_tabledescr=>create( p_line_type = data + p_table_kind = cl_abap_tabledescr=>tablekind_std + p_unique = abap_false ). + + CREATE DATA result TYPE HANDLE o_table_desc. + ASSIGN result->* TO . + DELETE lt_rows WHERE table_line IS INITIAL. + + LOOP AT lt_rows REFERENCE INTO DATA(lr_rows) FROM 2. + + SPLIT lr_rows->* AT `;` INTO TABLE lt_cols. + CREATE DATA lr_row TYPE HANDLE struc. + + LOOP AT lt_cols REFERENCE INTO lr_col. + ASSIGN lr_row->* TO FIELD-SYMBOL(). + ASSIGN COMPONENT sy-tabix OF STRUCTURE TO FIELD-SYMBOL(). + IF sy-subrc <> 0. + EXIT. + ENDIF. + = lr_col->*. + ENDLOOP. + + INSERT INTO TABLE . + ENDLOOP. + + ENDMETHOD. + + METHOD json_parse. + TRY. + + z2ui5_cl_ajson=>parse( val )->to_abap( EXPORTING iv_corresponding = abap_true + IMPORTING ev_container = data ). + + CATCH cx_root INTO DATA(x). + RAISE EXCEPTION TYPE z2ui5_cx_util_error + EXPORTING + val = x. + ENDTRY. + ENDMETHOD. + + METHOD json_stringify. + TRY. + + DATA(li_ajson) = CAST z2ui5_if_ajson( z2ui5_cl_ajson=>create_empty( ) ). + result = li_ajson->set( iv_path = `/` + iv_val = any )->stringify( ). + + CATCH cx_root INTO DATA(x). + RAISE EXCEPTION TYPE z2ui5_cx_util_error + EXPORTING + val = x. + ENDTRY. + ENDMETHOD. + + METHOD rtti_create_tab_by_name. + + DATA(struct_desc) = cl_abap_structdescr=>describe_by_name( val ). + DATA(data_desc) = CAST cl_abap_datadescr( struct_desc ). + DATA(gr_dyntable_typ) = cl_abap_tabledescr=>create( data_desc ). + CREATE DATA result TYPE HANDLE gr_dyntable_typ. + + ENDMETHOD. + + METHOD rtti_get_t_attri_by_any. + + DATA lo_struct TYPE REF TO cl_abap_structdescr. + DATA lo_type TYPE REF TO cl_abap_typedescr. + + TRY. + lo_type = cl_abap_typedescr=>describe_by_data( val ). + IF lo_type->kind = cl_abap_typedescr=>kind_ref. + lo_type = cl_abap_typedescr=>describe_by_data_ref( val ). + ENDIF. + CATCH cx_root. + TRY. + lo_type = cl_abap_typedescr=>describe_by_data_ref( val ). + CATCH cx_root. + lo_type = cl_abap_structdescr=>describe_by_name( val ). + ENDTRY. + ENDTRY. + + CASE lo_type->kind. + WHEN cl_abap_typedescr=>kind_struct. + lo_struct = CAST #( lo_type ). + WHEN cl_abap_typedescr=>kind_table. + lo_struct = CAST #( CAST cl_abap_tabledescr( lo_type )->get_table_line_type( ) ). + WHEN OTHERS. + lo_struct ?= lo_type. + ENDCASE. + + DATA(comps) = lo_struct->get_components( ). + + LOOP AT comps REFERENCE INTO DATA(lr_comp). + + IF lr_comp->as_include = abap_false. + APPEND lr_comp->* TO result. + ELSE. + DATA(lt_attri) = rtti_get_t_attri_by_include( lr_comp->type ). + APPEND LINES OF lt_attri TO result. + ENDIF. + ENDLOOP. + + ENDMETHOD. + + METHOD rtti_get_t_attri_by_include. + + TRY. + + cl_abap_typedescr=>describe_by_name( EXPORTING p_name = type->absolute_name + RECEIVING p_descr_ref = DATA(type_desc) + EXCEPTIONS type_not_found = 1 ). + + CATCH cx_root INTO DATA(x). + RAISE EXCEPTION TYPE z2ui5_cx_util_error + EXPORTING + previous = x. + ENDTRY. + DATA(sdescr) = CAST cl_abap_structdescr( type_desc ). + DATA(comps) = sdescr->get_components( ). + + LOOP AT comps REFERENCE INTO DATA(lr_comp). + + IF lr_comp->as_include = abap_true. + + DATA(incl_comps) = rtti_get_t_attri_by_include( lr_comp->type ). + + LOOP AT incl_comps REFERENCE INTO DATA(lr_incl_comp). + APPEND lr_incl_comp->* TO result. + ENDLOOP. + + ELSE. + + APPEND lr_comp->* TO result. + + ENDIF. + + ENDLOOP. + + ENDMETHOD. + + METHOD rtti_check_ref_data. + + TRY. + DATA(lo_typdescr) = cl_abap_typedescr=>describe_by_data( val ). + DATA(lo_ref) = CAST cl_abap_refdescr( lo_typdescr ) ##NEEDED. + result = abap_true. + CATCH cx_root ##NO_HANDLER. + ENDTRY. + + ENDMETHOD. + + METHOD c_trim. + + result = shift_left( shift_right( CONV string( val ) ) ). + result = shift_right( val = result + sub = cv_char_util_horizontal_tab ). + result = shift_left( val = result + sub = cv_char_util_horizontal_tab ). + result = shift_left( shift_right( result ) ). + + ENDMETHOD. + + METHOD c_trim_upper. + + result = to_upper( c_trim( CONV string( val ) ) ). + + ENDMETHOD. + + METHOD xml_parse. + + IF xml IS INITIAL. + CLEAR any. + RETURN. + ENDIF. + + CALL TRANSFORMATION id + SOURCE XML xml + RESULT data = any. + + ENDMETHOD. + + METHOD xml_stringify. + + CALL TRANSFORMATION id + SOURCE data = any + RESULT XML result + OPTIONS data_refs = `heap-or-create`. + + ENDMETHOD. + +ENDCLASS. diff --git a/src/z2ui5_cl_tcl_context.clas.xml b/src/z2ui5_cl_tcl_context.clas.xml new file mode 100644 index 0000000..321d714 --- /dev/null +++ b/src/z2ui5_cl_tcl_context.clas.xml @@ -0,0 +1,16 @@ + + + + + + Z2UI5_CL_TCL_CONTEXT + E + Table Content Loader - vendored utility context + 1 + X + X + X + + + + From 22bd10893ac7f2d66c7f2d1e8dfb60c0ff680b0d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 11:56:49 +0000 Subject: [PATCH 09/16] ci: bump actions/checkout and actions/setup-node to v5 The round-1 action-version pass skipped these four addons; they still ran @v4 while layout-management already uses @v5. Unify on @v5. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/workflows/ABAP_CLOUD.yaml | 4 ++-- .github/workflows/ABAP_STANDARD.yaml | 4 ++-- .github/workflows/build_rename.yaml | 4 ++-- .github/workflows/rename_test.yaml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ABAP_CLOUD.yaml b/.github/workflows/ABAP_CLOUD.yaml index 4d250b1..842a3be 100644 --- a/.github/workflows/ABAP_CLOUD.yaml +++ b/.github/workflows/ABAP_CLOUD.yaml @@ -13,8 +13,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: node-version: 22 - run: npm ci diff --git a/.github/workflows/ABAP_STANDARD.yaml b/.github/workflows/ABAP_STANDARD.yaml index 0ec924c..4024a39 100644 --- a/.github/workflows/ABAP_STANDARD.yaml +++ b/.github/workflows/ABAP_STANDARD.yaml @@ -13,8 +13,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: node-version: 22 - run: npm ci diff --git a/.github/workflows/build_rename.yaml b/.github/workflows/build_rename.yaml index 2452817..ad80cf3 100644 --- a/.github/workflows/build_rename.yaml +++ b/.github/workflows/build_rename.yaml @@ -50,8 +50,8 @@ jobs: echo "BRANCH=rename_$ns" >> "$GITHUB_ENV" echo "Building branch: rename_$ns" - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: node-version: '22' cache: 'npm' diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml index 1c5af4b..9a72b6b 100644 --- a/.github/workflows/rename_test.yaml +++ b/.github/workflows/rename_test.yaml @@ -13,8 +13,8 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@v5 + - uses: actions/setup-node@v5 with: node-version: 22 - run: npm ci From 7b4c07f9307f3c2cc7092e53f092891eaf211ccb Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 14:02:01 +0000 Subject: [PATCH 10/16] =?UTF-8?q?chore:=20hygiene=20batch=20=E2=80=94=20gi?= =?UTF-8?q?tattributes,=20CoC,=20workflows,=20badges,=20text=20polish,=20l?= =?UTF-8?q?int=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - .gitattributes (LF), CODE_OF_CONDUCT.md, LICENSE holder -> abap2UI5 - workflows: concurrency groups + npm cache - README: add CI status badge block - abaplint: enable exporting + omit_parameter_name (auto-fixed findings) - UI text: && -> string templates, 'filepath here...' -> backticks, lowercase 'cancel' toast -> 'Cancelled' abaplint: 0 issues, standard and cloud. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .gitattributes | 11 +++ .github/workflows/ABAP_CLOUD.yaml | 5 + .github/workflows/ABAP_STANDARD.yaml | 5 + .github/workflows/rename_test.yaml | 5 + CODE_OF_CONDUCT.md | 128 +++++++++++++++++++++++++ LICENSE | 2 +- README.md | 5 + abaplint.jsonc | 4 +- src/01/z2ui5_cl_tcl_xlsx_api.clas.abap | 2 +- src/z2ui5_cl_tcl_app_01.clas.abap | 4 +- src/z2ui5_cl_tcl_app_03.clas.abap | 4 +- src/z2ui5_cl_tcl_app_04.clas.abap | 4 +- src/z2ui5_cl_tcl_app_05.clas.abap | 4 +- src/z2ui5_cl_tcl_app_06.clas.abap | 14 +-- 14 files changed, 179 insertions(+), 18 deletions(-) create mode 100644 .gitattributes create mode 100644 CODE_OF_CONDUCT.md diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4120e63 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,11 @@ +# Normalize line endings to LF for all text files (abapGit + tooling expect LF) +* text=auto eol=lf +*.abap text eol=lf +*.xml text eol=lf +*.json text eol=lf +*.jsonc text eol=lf +*.md text eol=lf +*.mjs text eol=lf +*.js text eol=lf +*.yaml text eol=lf +*.yml text eol=lf diff --git a/.github/workflows/ABAP_CLOUD.yaml b/.github/workflows/ABAP_CLOUD.yaml index 842a3be..3f72411 100644 --- a/.github/workflows/ABAP_CLOUD.yaml +++ b/.github/workflows/ABAP_CLOUD.yaml @@ -8,6 +8,10 @@ on: permissions: contents: read +concurrency: + group: ABAP_CLOUD-${{ github.ref }} + cancel-in-progress: true + jobs: ABAP_CLOUD: runs-on: ubuntu-latest @@ -17,5 +21,6 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + cache: 'npm' - run: npm ci - run: npx abaplint .github/abaplint/abap_cloud.jsonc diff --git a/.github/workflows/ABAP_STANDARD.yaml b/.github/workflows/ABAP_STANDARD.yaml index 4024a39..640df49 100644 --- a/.github/workflows/ABAP_STANDARD.yaml +++ b/.github/workflows/ABAP_STANDARD.yaml @@ -8,6 +8,10 @@ on: permissions: contents: read +concurrency: + group: ABAP_STANDARD-${{ github.ref }} + cancel-in-progress: true + jobs: ABAP_STANDARD: runs-on: ubuntu-latest @@ -17,5 +21,6 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + cache: 'npm' - run: npm ci - run: npx abaplint ./abaplint.jsonc diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml index 9a72b6b..b332209 100644 --- a/.github/workflows/rename_test.yaml +++ b/.github/workflows/rename_test.yaml @@ -8,6 +8,10 @@ on: permissions: contents: read +concurrency: + group: rename_test-${{ github.ref }} + cancel-in-progress: true + jobs: rename_test: runs-on: ubuntu-latest @@ -17,5 +21,6 @@ jobs: - uses: actions/setup-node@v5 with: node-version: 22 + cache: 'npm' - run: npm ci - run: npm run rename diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..18c9147 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,128 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, religion, or sexual identity +and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the + overall community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or + advances of any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email + address, without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official e-mail address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement at +. +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series +of actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or +permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within +the community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], +version 2.0, available at +https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by [Mozilla's code of conduct +enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/LICENSE b/LICENSE index fd08f21..2a60ede 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2024 oblomov +Copyright (c) 2024 abap2UI5 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 89c0d6e..01e5ed4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +[![ABAP_STANDARD](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_STANDARD.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_STANDARD.yaml) +[![ABAP_CLOUD](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_CLOUD.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_CLOUD.yaml) +
+[![rename_test](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml) + # Table Content Loader Upload, Edit & Download Table Content

_Supported Formats: JSON, CSV, XLSX..._ diff --git a/abaplint.jsonc b/abaplint.jsonc index 5770d75..a69d278 100644 --- a/abaplint.jsonc +++ b/abaplint.jsonc @@ -41,6 +41,8 @@ "parser_error": true, "superclass_final": true, "unknown_types": true, - "xml_consistency": true + "xml_consistency": true, + "exporting": true, + "omit_parameter_name": true } } diff --git a/src/01/z2ui5_cl_tcl_xlsx_api.clas.abap b/src/01/z2ui5_cl_tcl_xlsx_api.clas.abap index 57ac78b..bbff0e9 100644 --- a/src/01/z2ui5_cl_tcl_xlsx_api.clas.abap +++ b/src/01/z2ui5_cl_tcl_xlsx_api.clas.abap @@ -51,7 +51,7 @@ CLASS z2ui5_cl_tcl_xlsx_api IMPLEMENTATION. lt_field_catalog = fieldcatalog. IF lt_field_catalog IS INITIAL. - lt_field_catalog = zcl_excel_common=>get_fieldcatalog( ip_table = val ). + lt_field_catalog = zcl_excel_common=>get_fieldcatalog( val ). ENDIF. ls_table_settings = settings. diff --git a/src/z2ui5_cl_tcl_app_01.clas.abap b/src/z2ui5_cl_tcl_app_01.clas.abap index a064c7a..254cd29 100644 --- a/src/z2ui5_cl_tcl_app_01.clas.abap +++ b/src/z2ui5_cl_tcl_app_01.clas.abap @@ -100,7 +100,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. client->view_model_update( ). CATCH cx_root. - client->message_box_display( `DB Table not found, check input: ` && ms_app-db_table ). + client->message_box_display( |DB Table not found, check input: { ms_app-db_table }| ). ENDTRY. WHEN `PROCESS`. @@ -142,7 +142,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. client->nav_app_call( z2ui5_cl_popup_file_ul=>factory( ) ). WHEN 'BUTTON_CANCEL'. - client->message_toast_display( |cancel| ). + client->message_toast_display( `Cancelled` ). WHEN 'BACK'. client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ). diff --git a/src/z2ui5_cl_tcl_app_03.clas.abap b/src/z2ui5_cl_tcl_app_03.clas.abap index ff8416a..aacc2f5 100644 --- a/src/z2ui5_cl_tcl_app_03.clas.abap +++ b/src/z2ui5_cl_tcl_app_03.clas.abap @@ -88,7 +88,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. client->view_model_update( ). CATCH cx_root. - client->message_box_display( `DB Table not found, check input: ` && ms_app-db_table ). + client->message_box_display( |DB Table not found, check input: { ms_app-db_table }| ). ENDTRY. WHEN `PROCESS`. @@ -128,7 +128,7 @@ CLASS z2ui5_cl_tcl_app_03 IMPLEMENTATION. client->nav_app_call( z2ui5_cl_popup_file_dl=>factory( ms_app-file ) ). WHEN 'BUTTON_CANCEL'. - client->message_toast_display( |cancel| ). + client->message_toast_display( `Cancelled` ). WHEN 'BACK'. client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ). diff --git a/src/z2ui5_cl_tcl_app_04.clas.abap b/src/z2ui5_cl_tcl_app_04.clas.abap index 71952d0..b13b56d 100644 --- a/src/z2ui5_cl_tcl_app_04.clas.abap +++ b/src/z2ui5_cl_tcl_app_04.clas.abap @@ -106,7 +106,7 @@ CLASS Z2UI5_CL_TCL_APP_04 IMPLEMENTATION. ASSIGN mr_table->* TO . DATA(tab) = page->table( - items = client->_bind_edit( ) + client->_bind_edit( ) )->header_toolbar( )->overflow_toolbar( )->title( 'CSV Content' @@ -139,7 +139,7 @@ CLASS Z2UI5_CL_TCL_APP_04 IMPLEMENTATION. footer->_z2ui5( )->file_uploader( value = client->_bind_edit( mv_value ) path = client->_bind_edit( mv_path ) - placeholder = 'filepath here...' + placeholder = `File path here...` upload = client->_event( 'UPLOAD' ) ). footer->toolbar_spacer( diff --git a/src/z2ui5_cl_tcl_app_05.clas.abap b/src/z2ui5_cl_tcl_app_05.clas.abap index a267d3c..f932193 100644 --- a/src/z2ui5_cl_tcl_app_05.clas.abap +++ b/src/z2ui5_cl_tcl_app_05.clas.abap @@ -91,7 +91,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. ASSIGN mr_table->* TO . DATA(tab) = page->table( - items = client->_bind_edit( ) + client->_bind_edit( ) )->header_toolbar( )->overflow_toolbar( )->title( 'XLSX Content' @@ -123,7 +123,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. footer->_z2ui5( )->file_uploader( value = client->_bind_edit( mv_value ) path = client->_bind_edit( mv_path ) - placeholder = 'filepath here...' + placeholder = `File path here...` upload = client->_event( 'UPLOAD' ) ). footer->toolbar_spacer( diff --git a/src/z2ui5_cl_tcl_app_06.clas.abap b/src/z2ui5_cl_tcl_app_06.clas.abap index 46659bb..ed7961c 100644 --- a/src/z2ui5_cl_tcl_app_06.clas.abap +++ b/src/z2ui5_cl_tcl_app_06.clas.abap @@ -130,7 +130,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. FIELD-SYMBOLS TYPE table. ASSIGN ms_draft-t_tab->* TO . - ms_draft-t_fcat = zcl_excel_common=>get_fieldcatalog( ip_table = ). + ms_draft-t_fcat = zcl_excel_common=>get_fieldcatalog( ). DATA ls_table_settings TYPE zexcel_s_table_settings. ls_table_settings-table_style = zcl_excel_table=>builtinstyle_medium5. INSERT ls_table_settings INTO TABLE ms_draft-t_config. @@ -222,7 +222,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. IF ms_draft-t_tab IS BOUND. FIELD-SYMBOLS TYPE table. ASSIGN ms_draft-t_tab->* TO . - ms_draft-t_fcat = zcl_excel_common=>get_fieldcatalog( ip_table = ). + ms_draft-t_fcat = zcl_excel_common=>get_fieldcatalog( ). ENDIF. set_view( ). @@ -332,7 +332,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. ). DATA(tab) = cont->table( - items = client->_bind_edit( ms_draft-t_config ) + client->_bind_edit( ms_draft-t_config ) )->header_toolbar( )->overflow_toolbar( )->title( `Excel Configuration` @@ -360,7 +360,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. ). tab = cont->table( - items = client->_bind_edit( ms_draft-t_config_head ) + client->_bind_edit( ms_draft-t_config_head ) )->header_toolbar( )->overflow_toolbar( )->title( `Parameter` @@ -393,7 +393,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. ). DATA(tab) = cont->table( - items = client->_bind_edit( ms_draft-t_fcat ) + client->_bind_edit( ms_draft-t_fcat ) )->header_toolbar( )->overflow_toolbar( )->title( `Excel Fieldcatalog` @@ -430,7 +430,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. editable = `true` ). content->label( `Activate Row Limitation` - )->checkbox( selected = client->_bind_edit( ms_draft-check_file_row_limit ) + )->checkbox( client->_bind_edit( ms_draft-check_file_row_limit ) )->label( `Rows` )->input( value = client->_bind_edit( ms_draft-file_max_rows ) enabled = client->_bind_edit( ms_draft-check_file_row_limit ) width = `10%` )->label( `Prepare File with abap2xlsx` @@ -460,7 +460,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. ). DATA(tab) = cont->table( - items = client->_bind( ) + client->_bind( ) )->header_toolbar( )->overflow_toolbar( )->title( `(1) Data Preview - ` && ms_draft-table_name From 81f589c00c63a6f67f126de0964058f703045064 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 14:15:20 +0000 Subject: [PATCH 11/16] docs: uniform CI badge block; rename the rename check to 'renaming' Give the README the same six-badge block as the other addons (ABAP_STANDARD, ABAP_CLOUD, ABAP_702, auto_cloud, auto_downport, renaming) so badges stay grey where a workflow is not part of this repo and go green/red where it runs. The rename_test workflow is renamed to 'renaming' so its badge reads that. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/workflows/rename_test.yaml | 2 +- README.md | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml index b332209..a47d39e 100644 --- a/.github/workflows/rename_test.yaml +++ b/.github/workflows/rename_test.yaml @@ -1,4 +1,4 @@ -name: rename_test +name: renaming on: push: diff --git a/README.md b/README.md index 01e5ed4..e4a1a8f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ [![ABAP_STANDARD](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_STANDARD.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_STANDARD.yaml) [![ABAP_CLOUD](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_CLOUD.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_CLOUD.yaml) +[![ABAP_702](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_702.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/ABAP_702.yaml)
-[![rename_test](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml) +[![auto_cloud](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/auto_cloud.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/auto_cloud.yaml) +[![auto_downport](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/auto_downport.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/auto_downport.yaml) +
+[![renaming](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml/badge.svg)](https://github.com/abap2UI5-addons/table-content-loader/actions/workflows/rename_test.yaml) # Table Content Loader Upload, Edit & Download Table Content

From 0d7698674ae06c77c1ed1a5ac246432e1698cd50 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 14:21:47 +0000 Subject: [PATCH 12/16] docs: add AGENTS.md Single agent-instruction file documenting the current state: structure, the vendored utility-copy model, dependencies, security notes, coding style and how to validate (abaplint + CI workflows). Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- AGENTS.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..29dda86 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,67 @@ +# AGENTS.md — AI Assistant Guide for abap2UI5 table-content-loader + +> This file follows the cross-tool AGENTS.md convention and is the single +> agent instruction file of this repository — Claude Code reads `AGENTS.md` +> natively, there is no separate `CLAUDE.md`. + +## Project Overview + +Upload, edit and download table content (JSON, CSV, XLSX) for +[abap2UI5](https://github.com/abap2UI5/abap2UI5) (`z2ui5_cl_tcl_*`). + +**Language:** English — all code, comments, commit messages, PRs, issues and +documentation must be in English. + +## Package Structure + +| Package | Content | +|---|---| +| `src/` | App classes `z2ui5_cl_tcl_app_00` … `_06` | +| `src/01/z2ui5_cl_tcl_xlsx_api` | XLSX helper | +| `src/z2ui5_cl_tcl_context` | Vendored utility copy — **see below** | + +## The Utility Copy Principle + +`z2ui5_cl_tcl_context` is a **trimmed, renamed copy** of the abap2UI5 utility +class (`z2ui5_cl_util` in the core), carrying only the methods this addon uses +(conv/itab/json/xml/rtti helpers) plus the private helpers and char constants +those need. The app calls `z2ui5_cl_tcl_context=>…`, never `z2ui5_cl_util=>…` +directly. This keeps the install dependency-free (abapGit has no dependency +management). The core and the other addons use the same pattern. When a new +utility method is needed, copy it from the core utility class (with its private +helpers) into the context copy rather than adding a dependency. + +## Dependencies + +Installed alongside via abapGit; declared in the abaplint configs: + +* [abap2UI5](https://github.com/abap2UI5/abap2UI5) +* [popups](https://github.com/abap2UI5-addons/popups) +* [abap2xlsx](https://github.com/abap2xlsx/abap2xlsx) + +## Security + +This is a developer tool. It reads from and writes to any table the user names, +without an authorization check of its own (the Z/Y namespace hint on write is +only a warning, not enforced). Before using it beyond a development system, add +your own `AUTHORITY-CHECK`s and restrict who may run the app. + +## Coding Style + +Follows the abap2UI5 core conventions (see its +[AGENTS.md](https://github.com/abap2UI5/abap2UI5/blob/main/AGENTS.md)): Clean +ABAP with Hungarian prefixes, backtick string literals, string templates +(`|…{ }…|`) instead of `&&`. + +## Validation + +Run `npx abaplint` before considering changes complete (config `abaplint.jsonc`, +0 issues expected). CI: + +* `ABAP_STANDARD` / `ABAP_CLOUD` — lint against Standard ABAP and ABAP Cloud +* `renaming` (`rename_test.yaml`) — namespace-rename check +* `build_rename` — manual workflow that pushes a namespace-renamed branch + `rename_` for a parallel install + +There is no 702 downport: the abap2xlsx dependency has no `702` branch. +All `.abap`/`.xml`/config files are LF-only (`.gitattributes` enforces it). From ee8b448d38d1c3d740678778a113c4010d1f228d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 15:01:19 +0000 Subject: [PATCH 13/16] Fix XLSX MIME type, remove dead fields, tidy docs and config - Serve XLSX downloads with the correct spreadsheetml MIME type instead of text/csv in app_05 and app_06 - Remove unused ms_app fields (max_rows, file_size, file_entries) and convert event char literals to string literals in app_01/app_03 - Add prefix_is_current_class to abaplint.jsonc (0 findings) - README: correct compatibility wording and unify Contribution section - Quote node-version in workflows, extend .gitignore, add engines to package.json Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- .github/workflows/ABAP_CLOUD.yaml | 2 +- .github/workflows/ABAP_STANDARD.yaml | 2 +- .github/workflows/rename_test.yaml | 2 +- .gitignore | 3 +++ README.md | 4 ++-- abaplint.jsonc | 3 ++- package.json | 3 +++ src/z2ui5_cl_tcl_app_01.clas.abap | 17 ++++++++--------- src/z2ui5_cl_tcl_app_03.clas.abap | 3 --- src/z2ui5_cl_tcl_app_05.clas.abap | 2 +- src/z2ui5_cl_tcl_app_06.clas.abap | 2 +- 11 files changed, 23 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ABAP_CLOUD.yaml b/.github/workflows/ABAP_CLOUD.yaml index 3f72411..b5bdebd 100644 --- a/.github/workflows/ABAP_CLOUD.yaml +++ b/.github/workflows/ABAP_CLOUD.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-node@v5 with: - node-version: 22 + node-version: '22' cache: 'npm' - run: npm ci - run: npx abaplint .github/abaplint/abap_cloud.jsonc diff --git a/.github/workflows/ABAP_STANDARD.yaml b/.github/workflows/ABAP_STANDARD.yaml index 640df49..68dec42 100644 --- a/.github/workflows/ABAP_STANDARD.yaml +++ b/.github/workflows/ABAP_STANDARD.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-node@v5 with: - node-version: 22 + node-version: '22' cache: 'npm' - run: npm ci - run: npx abaplint ./abaplint.jsonc diff --git a/.github/workflows/rename_test.yaml b/.github/workflows/rename_test.yaml index a47d39e..d063063 100644 --- a/.github/workflows/rename_test.yaml +++ b/.github/workflows/rename_test.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v5 - uses: actions/setup-node@v5 with: - node-version: 22 + node-version: '22' cache: 'npm' - run: npm ci - run: npm run rename diff --git a/.gitignore b/.gitignore index 1406277..970868c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ node_modules output +.github/out/ +.github/abaplint/output/ +.github/abaplint/rename_run.json diff --git a/README.md b/README.md index e4a1a8f..688f8fe 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ _Supported Formats: JSON, CSV, XLSX..._ * Data Preview #### Compatibility -* S/4 Public Cloud ABAP and BTP ABAP Environment (ABAP for Cloud) +* S/4 Public Cloud and BTP ABAP Environment (ABAP for Cloud) * S/4 Private Cloud or On-Premise (ABAP for Cloud, Standard ABAP) * SAP NetWeaver AS ABAP 7.50 or higher (Standard ABAP) @@ -38,4 +38,4 @@ This is a developer tool. It reads from and writes to any table the user names, Table Content Loader start page with tiles for JSON, CSV and XLSX upload and download #### Contribution & Support -Pull Requests are welcome! Whether you're fixing a bug, adding new functionality, or improving the documentation, your contributions are always appreciated. If you run into problems, feel free to open an issue. +Pull requests are welcome! Whether you're fixing bugs, adding new functionality, or improving documentation, your contributions are highly appreciated. If you encounter any issues, feel free to open an issue. diff --git a/abaplint.jsonc b/abaplint.jsonc index a69d278..4516ff5 100644 --- a/abaplint.jsonc +++ b/abaplint.jsonc @@ -43,6 +43,7 @@ "unknown_types": true, "xml_consistency": true, "exporting": true, - "omit_parameter_name": true + "omit_parameter_name": true, + "prefix_is_current_class": true } } diff --git a/package.json b/package.json index 7c95b71..2a8469d 100644 --- a/package.json +++ b/package.json @@ -17,5 +17,8 @@ "homepage": "https://github.com/abap2UI5-addons/table-content-loader#readme", "devDependencies": { "@abaplint/cli": "^2.119.14" + }, + "engines": { + "node": ">=22" } } diff --git a/src/z2ui5_cl_tcl_app_01.clas.abap b/src/z2ui5_cl_tcl_app_01.clas.abap index 254cd29..b34552f 100644 --- a/src/z2ui5_cl_tcl_app_01.clas.abap +++ b/src/z2ui5_cl_tcl_app_01.clas.abap @@ -9,7 +9,6 @@ CLASS z2ui5_cl_tcl_app_01 DEFINITION DATA: BEGIN OF ms_app, check_initialized TYPE abap_bool, - max_rows TYPE string, file TYPE string, file_size TYPE string, file_entries TYPE string, @@ -85,7 +84,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. CASE client->get( )-event. - WHEN 'DB_CHECK'. + WHEN `DB_CHECK`. TRY. ms_app-db_table = to_upper( ms_app-db_table ). @@ -94,7 +93,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. FROM (ms_app-db_table) INTO ms_app-db_table_entries. - IF to_upper( ms_app-db_table(1) ) <> `Z` AND to_upper( ms_app-db_table(1) ) <> `Y`. + IF to_upper( ms_app-db_table(1) ) <> `Z` AND to_upper( ms_app-db_table(1) ) <> `Y`. client->message_box_display( `Only Tables in namespace Z or Y allowed` ). ENDIF. @@ -135,16 +134,16 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. client->nav_app_call( z2ui5_cl_popup_table=>factory( ) ). - WHEN 'DB_SAVE'. + WHEN `DB_SAVE`. client->nav_app_call( z2ui5_cl_popup_to_confirm=>factory( `Database will be deleted and new entries filled. Are you sure?` ) ). - WHEN 'UPLOAD'. + WHEN `UPLOAD`. client->nav_app_call( z2ui5_cl_popup_file_ul=>factory( ) ). - WHEN 'BUTTON_CANCEL'. + WHEN `BUTTON_CANCEL`. client->message_toast_display( `Cancelled` ). - WHEN 'BACK'. + WHEN `BACK`. client->nav_app_leave( client->get_app( client->get( )-s_draft-id_prev_app_stack ) ). ENDCASE. @@ -165,7 +164,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. DATA(page) = view->shell( appwidthlimited = client->_bind_edit( ms_app-check_appwidthlimited ) )->page( title = 'abap2UI5 - JSON File Upload' - navbuttonpress = client->_event( 'BACK' ) + navbuttonpress = client->_event( `BACK` ) shownavbutton = xsdbool( client->get( )-s_draft-id_prev_app_stack IS NOT INITIAL ) )->header_content( )->overflow_toolbar( @@ -197,7 +196,7 @@ CLASS Z2UI5_CL_TCL_APP_01 IMPLEMENTATION. )->label( `(4) Preview Rows` )->button( text = `Go` width = `10%` press = client->_event( `PREVIEW` ) )->label( `(5) Save Database` - )->text( `Attention - Database Content will be deleted!!!` + )->text( `Attention - Database Content will be deleted!` )->label( )->button( text = `Run` width = `10%` press = client->_event( `DB_SAVE` ) ). diff --git a/src/z2ui5_cl_tcl_app_03.clas.abap b/src/z2ui5_cl_tcl_app_03.clas.abap index aacc2f5..f4044c2 100644 --- a/src/z2ui5_cl_tcl_app_03.clas.abap +++ b/src/z2ui5_cl_tcl_app_03.clas.abap @@ -17,10 +17,7 @@ CLASS z2ui5_cl_tcl_app_03 DEFINITION check_initialized TYPE abap_bool, check_popup TYPE abap_bool, itab TYPE REF TO data, - max_rows TYPE string, file TYPE string, - file_size TYPE string, - file_entries TYPE string, check_appwidthlimited TYPE abap_bool VALUE abap_true, db_table TYPE string VALUE 'SPFLI', db_table_entries TYPE string, diff --git a/src/z2ui5_cl_tcl_app_05.clas.abap b/src/z2ui5_cl_tcl_app_05.clas.abap index f932193..d16f18f 100644 --- a/src/z2ui5_cl_tcl_app_05.clas.abap +++ b/src/z2ui5_cl_tcl_app_05.clas.abap @@ -84,7 +84,7 @@ CLASS Z2UI5_CL_TCL_APP_05 IMPLEMENTATION. mv_check_download = abap_false. DATA(lv_xlsx) = z2ui5_cl_tcl_xlsx_api=>get_xlsx_by_table( ). DATA(lv_base) = z2ui5_cl_tcl_context=>conv_encode_x_base64( lv_xlsx ). - view->_generic( ns = `html` name = `iframe` t_prop = VALUE #( ( n = `src` v = `data:text/csv;base64,` && lv_base ) ( n = `hidden` v = `hidden` ) ) ). + view->_generic( ns = `html` name = `iframe` t_prop = VALUE #( ( n = `src` v = `data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,` && lv_base ) ( n = `hidden` v = `hidden` ) ) ). ENDIF. IF mr_table IS NOT INITIAL. diff --git a/src/z2ui5_cl_tcl_app_06.clas.abap b/src/z2ui5_cl_tcl_app_06.clas.abap index ed7961c..d9ac017 100644 --- a/src/z2ui5_cl_tcl_app_06.clas.abap +++ b/src/z2ui5_cl_tcl_app_06.clas.abap @@ -421,7 +421,7 @@ CLASS Z2UI5_CL_TCL_APP_06 IMPLEMENTATION. IF mv_check_download_file = abap_true. mv_check_download_file = abap_false. - page->_generic( ns = `html` name = `iframe` t_prop = VALUE #( ( n = `src` v = `data:text/csv;base64,` && mv_file ) ( n = `hidden` v = `hidden` ) ) ). + page->_generic( ns = `html` name = `iframe` t_prop = VALUE #( ( n = `src` v = `data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,` && mv_file ) ( n = `hidden` v = `hidden` ) ) ). ENDIF. From 1926c321c6cc7193bac1352cabd1e7186e02e7be Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 15:54:04 +0000 Subject: [PATCH 14/16] chore: update @abaplint/cli to 2.119.66 Align with the version now used in the abap2UI5 core repo. abaplint passes with 0 issues. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- package-lock.json | 11 +++++++---- package.json | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 348dffb..2cfa04e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,13 +9,16 @@ "version": "1.0.0", "license": "MIT", "devDependencies": { - "@abaplint/cli": "^2.119.14" + "@abaplint/cli": "^2.119.66" + }, + "engines": { + "node": ">=22" } }, "node_modules/@abaplint/cli": { - "version": "2.119.65", - "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.119.65.tgz", - "integrity": "sha512-ezPrkiIOd31CR13G7KPGz0Hdhh5/ijx68N6aosOdYFsYEe+actT7N7WmM0xz+NjZkUNRC1xCA90HZv/lUE5hSQ==", + "version": "2.119.66", + "resolved": "https://registry.npmjs.org/@abaplint/cli/-/cli-2.119.66.tgz", + "integrity": "sha512-Anjsm5G0jUnWwEAZrk2Ckm0we+VCrwjc/MOMSSk+774VJ6ka1ovkj981Y8BJdbxcKgKzIvn+D/ddap/tdxMFbw==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index 2a8469d..9c24ff3 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ }, "homepage": "https://github.com/abap2UI5-addons/table-content-loader#readme", "devDependencies": { - "@abaplint/cli": "^2.119.14" + "@abaplint/cli": "^2.119.66" }, "engines": { "node": ">=22" From 283277a13446813f2b88f5765cff79d2931f6077 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 15:57:24 +0000 Subject: [PATCH 15/16] docs: fill in the empty Code of Conduct enforcement contact The Contributor Covenant [INSERT CONTACT METHOD] placeholder had been deleted, leaving a dangling "...responsible for enforcement at ." sentence. Point reporters at the repository's private Security Advisory report form. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- CODE_OF_CONDUCT.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 18c9147..464b9ee 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -59,8 +59,8 @@ representative at an online or offline event. ## Enforcement Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -. +reported to the community leaders responsible for enforcement by opening a +private report via the repository's [Security Advisory form](https://github.com/abap2UI5-addons/table-content-loader/security/advisories/new). All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the From 8c9d018f9fa49d44b9850252026812f9a9fcd895 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 16:35:05 +0000 Subject: [PATCH 16/16] fix: align import segmented_button chain with the export view The import view built the format segmented button with extra ->get( ) hops (which navigate to mo_root->mo_previous), unlike the working export view. Attach items/items directly so both views build the control the same way. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01MEGSbezJEiFoFubnrqATiM --- src/z2ui5_cl_tcl_app_02.clas.abap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/z2ui5_cl_tcl_app_02.clas.abap b/src/z2ui5_cl_tcl_app_02.clas.abap index a4d8f47..7cbda52 100644 --- a/src/z2ui5_cl_tcl_app_02.clas.abap +++ b/src/z2ui5_cl_tcl_app_02.clas.abap @@ -335,8 +335,8 @@ CLASS Z2UI5_CL_TCL_APP_02 IMPLEMENTATION. )->label( 'Table' )->input( 'SPFLI' )->label( 'Format' - )->segmented_button( client->_bind_edit( ms_import-segment_key ) )->get( - )->items( )->get( + )->segmented_button( client->_bind_edit( ms_import-segment_key ) + )->items( )->segmented_button_item( key = 'json' text = 'json' )->segmented_button_item( key = 'csv' text = 'csv' )->segmented_button_item( key = 'xml' text = 'xml' ).