feat(slider): add slider feature
This commit is contained in:
18
.github/workflows/main.yaml
vendored
18
.github/workflows/main.yaml
vendored
@@ -4,6 +4,8 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- 'issue/**'
|
||||
- develop
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
@@ -35,7 +37,6 @@ jobs:
|
||||
module-build:
|
||||
name: Build module.
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: oven-sh/setup-bun@v2
|
||||
@@ -60,6 +61,7 @@ jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test, module-build]
|
||||
if: github.ref == 'refs/heads/master'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -156,4 +158,16 @@ jobs:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [release]
|
||||
if: github.ref == 'refs/heads/master'
|
||||
steps:
|
||||
- name: Trigger deployment
|
||||
run: |
|
||||
curl --fail-with-body -X POST "${{ secrets.SERVER_URL }}/index.php?route=github_deploy/deploy" \
|
||||
-d "token=${{ secrets.OC_API_KEY }}"
|
||||
|
||||
1
Makefile
1
Makefile
@@ -35,6 +35,7 @@ dev:
|
||||
cd frontend/spa && bun run dev
|
||||
|
||||
dev-admin:
|
||||
rm -rf module/oc_telegram_shop/upload/admin/view/javascript && \
|
||||
$(MAKE) link && \
|
||||
cd frontend/admin && bun run dev
|
||||
cd frontend/spa && bun run dev
|
||||
|
||||
@@ -36,6 +36,7 @@ Telecart теперь поддерживает встроенную систем
|
||||
• Добавлены автоматические тесты, запускаемые при каждом билде, что значительно снижает количество багов в новых версиях.
|
||||
• Исправлены проблемы с поиском и оформлением заказов, обнаруженные на некоторых магазинах.
|
||||
• Повышена стабильность работы.
|
||||
• Уменьшен размер архива с модулем примерно в 2 раза.
|
||||
|
||||
Купить модуль: https://liveopencart.ru/opencart-moduli-shablony/moduli/telecart
|
||||
Документация: https://telecart-labs.github.io/docs/
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
"": {
|
||||
"name": "admin",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.16",
|
||||
"daisyui": "^5.4.2",
|
||||
"pinia": "^3.0.3",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"vue": "^3.5.22",
|
||||
"vue-router": "^4.6.3",
|
||||
},
|
||||
@@ -282,6 +285,36 @@
|
||||
|
||||
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.52.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg=="],
|
||||
|
||||
"@tailwindcss/node": ["@tailwindcss/node@4.1.16", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.19", "source-map-js": "^1.2.1", "tailwindcss": "4.1.16" } }, "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw=="],
|
||||
|
||||
"@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.16", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.16", "@tailwindcss/oxide-darwin-arm64": "4.1.16", "@tailwindcss/oxide-darwin-x64": "4.1.16", "@tailwindcss/oxide-freebsd-x64": "4.1.16", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16", "@tailwindcss/oxide-linux-arm64-musl": "4.1.16", "@tailwindcss/oxide-linux-x64-gnu": "4.1.16", "@tailwindcss/oxide-linux-x64-musl": "4.1.16", "@tailwindcss/oxide-wasm32-wasi": "4.1.16", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16", "@tailwindcss/oxide-win32-x64-msvc": "4.1.16" } }, "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg=="],
|
||||
|
||||
"@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.16", "", { "os": "android", "cpu": "arm64" }, "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA=="],
|
||||
|
||||
"@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg=="],
|
||||
|
||||
"@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.16", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16", "", { "os": "linux", "cpu": "arm" }, "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.16", "", { "os": "linux", "cpu": "x64" }, "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew=="],
|
||||
|
||||
"@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.16", "", { "os": "linux", "cpu": "x64" }, "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.16", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.7", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A=="],
|
||||
|
||||
"@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.16", "", { "os": "win32", "cpu": "x64" }, "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg=="],
|
||||
|
||||
"@tailwindcss/vite": ["@tailwindcss/vite@4.1.16", "", { "dependencies": { "@tailwindcss/node": "4.1.16", "@tailwindcss/oxide": "4.1.16", "tailwindcss": "4.1.16" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-bbguNBcDxsRmi9nnlWJxhfDWamY3lmcyACHcdO1crxfzuLpOhHLLtEIN/nCbbAtj5rchUgQD17QVAKi1f7IsKg=="],
|
||||
|
||||
"@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
|
||||
@@ -372,6 +405,8 @@
|
||||
|
||||
"csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="],
|
||||
|
||||
"daisyui": ["daisyui@5.4.2", "", {}, "sha512-yLoRFlx5hKvn5ODpT7CVb9oU/fAF2X1BGuLmVZo4LN33r7hcmO8v+gcxB6l33mcMas5jut3lZwHj9erqbMvvEA=="],
|
||||
|
||||
"debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
|
||||
|
||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||
@@ -382,8 +417,12 @@
|
||||
|
||||
"define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
|
||||
|
||||
"detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
|
||||
|
||||
"electron-to-chromium": ["electron-to-chromium@1.5.243", "", {}, "sha512-ZCphxFW3Q1TVhcgS9blfut1PX8lusVi2SvXQgmEEnK4TCmE1JhH2JkjJN+DNt0pJJwfBri5AROBnz2b/C+YU9g=="],
|
||||
|
||||
"enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="],
|
||||
|
||||
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||
|
||||
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
||||
@@ -446,6 +485,8 @@
|
||||
|
||||
"globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
|
||||
|
||||
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
|
||||
|
||||
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||
|
||||
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
||||
@@ -470,6 +511,8 @@
|
||||
|
||||
"isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
||||
|
||||
"jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
|
||||
|
||||
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
||||
|
||||
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
|
||||
@@ -494,6 +537,30 @@
|
||||
|
||||
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
|
||||
|
||||
"lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
|
||||
|
||||
"lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
|
||||
|
||||
"lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
|
||||
|
||||
"lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
|
||||
|
||||
"lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
|
||||
|
||||
"lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
|
||||
|
||||
"lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
|
||||
|
||||
"lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
|
||||
|
||||
"lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
|
||||
|
||||
"lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
|
||||
|
||||
"lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
|
||||
|
||||
"lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
|
||||
|
||||
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
|
||||
|
||||
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
|
||||
@@ -600,6 +667,10 @@
|
||||
|
||||
"synckit": ["synckit@0.11.11", "", { "dependencies": { "@pkgr/core": "^0.2.9" } }, "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw=="],
|
||||
|
||||
"tailwindcss": ["tailwindcss@4.1.16", "", {}, "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA=="],
|
||||
|
||||
"tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
|
||||
|
||||
"tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
|
||||
|
||||
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
||||
@@ -660,6 +731,18 @@
|
||||
|
||||
"@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
|
||||
|
||||
"@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||
|
||||
"@vue/devtools-api/@vue/devtools-kit": ["@vue/devtools-kit@7.7.7", "", { "dependencies": { "@vue/devtools-shared": "^7.7.7", "birpc": "^2.3.0", "hookable": "^5.5.3", "mitt": "^3.0.1", "perfect-debounce": "^1.0.0", "speakingurl": "^14.0.1", "superjson": "^2.2.2" } }, "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA=="],
|
||||
|
||||
"@vue/devtools-core/nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="],
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
"format": "prettier --write src/"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.1.16",
|
||||
"daisyui": "^5.4.2",
|
||||
"pinia": "^3.0.3",
|
||||
"tailwindcss": "^4.1.16",
|
||||
"vue": "^3.5.22",
|
||||
"vue-router": "^4.6.3"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
@layer theme, base, components, utilities;
|
||||
@import "tailwindcss/theme.css" layer(theme) prefix(tw);
|
||||
@import "tailwindcss/utilities.css" layer(utilities) prefix(tw);
|
||||
@plugin "daisyui" {
|
||||
prefix: 'd-'
|
||||
}
|
||||
|
||||
@layer components {
|
||||
.tw\:d-toggle {
|
||||
width: calc((var(--d-size) * 2) - (var(--border) + var(--d-toggle-p)) * 2) !important;
|
||||
height: var(--d-size) !important;
|
||||
border: var(--border) solid currentColor !important;
|
||||
color: var(--d-input-color) !important;
|
||||
border-radius: calc(var(--radius-selector) + min(var(--d-toggle-p), var(--radius-selector-max)) + min(var(--border), var(--radius-selector-max))) !important;
|
||||
padding: var(--d-toggle-p) !important;
|
||||
}
|
||||
|
||||
.tw\:d-toggle:after {
|
||||
all: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<template>
|
||||
<section>
|
||||
<pre>{{ banners }}</pre>
|
||||
<input type="text" name="module_tgshop_mainpage_banners" :value="JSON.stringify(banners)">
|
||||
<table id="banners" class="table table-striped table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-left">Заголовок</td>
|
||||
<td class="text-left">Ссылка</td>
|
||||
<td class="text-center">Изображение</td>
|
||||
<td>Действия</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(banner, index) in banners">
|
||||
<td class="text-left">
|
||||
<input v-model="banner.title" type="text" placeholder="Заголовок слайда"
|
||||
class="form-control"/>
|
||||
</td>
|
||||
<td class="text-left" style="width: 30%;">
|
||||
<LinkSelector v-model="banner.link"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<OcImagePIcker v-model="banner.image"/>
|
||||
|
||||
<div class="alert alert-info">
|
||||
Минимальный размер: 370×200 <br>
|
||||
Рекомендуется: 740×400 или больше, в тех же пропорциях (1.85:1) <br>
|
||||
Картинка будет автоматически обрезана под нужный формат.
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
<button type="button" class="btn btn-danger" @click="removeBanner(index)">
|
||||
<i class="fa fa-minus-circle"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
<td class="text-left">
|
||||
<button @click="addBanner" type="button" class="btn btn-primary">
|
||||
<i class="fa fa-plus-circle"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import OcImagePIcker from "@/components/OcImagePIcker.vue";
|
||||
import LinkSelector from "@/components/Banners/LinkSelector.vue";
|
||||
|
||||
const banners = ref([]);
|
||||
|
||||
function removeBanner(index) {
|
||||
banners.value.splice(index, 1);
|
||||
}
|
||||
|
||||
function addBanner() {
|
||||
banners.value.push({
|
||||
title: '',
|
||||
link: {
|
||||
type: 'none',
|
||||
value: null,
|
||||
},
|
||||
image: '',
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
banners.value = JSON.parse(window.TeleCart.banners || '[]');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -1,9 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<a href="#" data-toggle="image" class="img-thumbnail" :id="`thumb-image-${id}`">
|
||||
<img :src="thumb"
|
||||
<div class="oc-image">
|
||||
<div v-if="isLoaded === false" class="loader">
|
||||
<i class="fa fa-spinner fa-spin"></i>
|
||||
</div>
|
||||
|
||||
<a v-show="isLoaded" href="#" data-toggle="image" class="img-thumbnail" :id="`thumb-image-${id}`">
|
||||
<img
|
||||
:src="thumb"
|
||||
data-placeholder="/image/cache/no_image-100x100.png"
|
||||
alt="Image"
|
||||
@load="isLoaded = true"
|
||||
>
|
||||
</a>
|
||||
<input ref="inputRef" type="hidden" value="" :id="`input-image-${id}`">
|
||||
@@ -17,6 +23,7 @@ const id = useId();
|
||||
const model = defineModel();
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
const inputRef = ref(null);
|
||||
const isLoaded = ref(false);
|
||||
|
||||
const thumb = computed(() => {
|
||||
if (!model.value) return '/image/cache/no_image-100x100.png';
|
||||
@@ -39,3 +46,18 @@ onMounted(() => {
|
||||
observer.observe(input, {attributes: true, attributeFilter: ['value']});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.oc-image {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.loader {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
26
frontend/admin/src/components/SettingsItem.vue
Normal file
26
frontend/admin/src/components/SettingsItem.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="module_tgshop_status">
|
||||
{{ label }}
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<slot name="default"></slot>
|
||||
<div class="help-block">
|
||||
<slot name="help"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -3,7 +3,7 @@
|
||||
<input
|
||||
type="search"
|
||||
name="category"
|
||||
:value="`${category?.name}`"
|
||||
:value="`${category?.name || ''}`"
|
||||
placeholder="Начните вводить название категории..."
|
||||
class="form-control"
|
||||
ref="categoryRef"
|
||||
@@ -34,18 +34,16 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import CategorySelect from "@/components/Banners/CategorySelect.vue";
|
||||
import ProductSelect from "@/components/Banners/ProductSelect.vue";
|
||||
import CategorySelect from "@/components/Slider/CategorySelect.vue";
|
||||
import ProductSelect from "@/components/Slider/ProductSelect.vue";
|
||||
|
||||
const link = defineModel();
|
||||
|
||||
function setLink(value) {
|
||||
if (Object.is(link.value)) {
|
||||
if (link.value?.value) {
|
||||
link.value.value.url = value;
|
||||
} else {
|
||||
link.value.value = {
|
||||
url: value,
|
||||
};
|
||||
link.value.value = { url: value };
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<input
|
||||
type="search"
|
||||
:value="`${model?.name}`"
|
||||
:value="`${model?.name || ''}`"
|
||||
placeholder="Начните вводить название товара..."
|
||||
class="form-control"
|
||||
ref="inputRef"
|
||||
186
frontend/admin/src/components/Slider/Slider.vue
Normal file
186
frontend/admin/src/components/Slider/Slider.vue
Normal file
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<input type="hidden" name="module_tgshop_mainpage_slider" :value="JSON.stringify(slider)">
|
||||
<div class="alert alert-info">
|
||||
<p>Здесь настраивается слайдер, который выводится на главной странице.</p>
|
||||
<p>Рекомендуемые размеры изображений: <span class="text-bold">370×200px</span>, <span
|
||||
class="text-bold">740×400px</span>,
|
||||
<span class="text-bold">1110×600px</span> либо другие, в тех же пропорциях (1.85:1)<br>
|
||||
Изображение будет автоматически обрезана под нужный формат. <br>
|
||||
Заголовок можно оставить пустым, но рекомендуется заполнить для корректной работы целей
|
||||
Яндекс.Метрики.</p>
|
||||
</div>
|
||||
|
||||
<section>
|
||||
<SettingsItem label="Статус">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.is_enabled"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Показывать слайдер на главной странице.
|
||||
Для отображения слайдера нужно добавить минимум 1 слайд.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Эффект смены слайдов">
|
||||
<template #default>
|
||||
<select v-model="slider.effect" class="form-control">
|
||||
<option value="slide">Слайд</option>
|
||||
<option value="flip">Переворот</option>
|
||||
<option value="cards">Карточки</option>
|
||||
<option value="cube">Куб</option>
|
||||
<option value="coverflow">Перекрывающиеся слайды</option>
|
||||
</select>
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Пагинация">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.pagination"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Показывать точки под слайдером для индикации текущего слайда.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Полоса прокрутки">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.scrollbar"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Показывать полосу прокрутки под слайдером для навигации между слайдами.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Расстояние между слайдами">
|
||||
<template #default>
|
||||
<div class="tw:max-w-2xl">
|
||||
<div class="input-group">
|
||||
<input
|
||||
v-model="slider.space_between"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
class="form-control"
|
||||
placeholder="30"
|
||||
/>
|
||||
<span class="input-group-addon">px</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Расстояние между слайдами в пикселях. По умолчанию - 30.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Свободный режим">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.free_mode"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Позволяет свободно прокручивать слайды без привязки к конкретным позициям.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Бесконечная прокрутка">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.loop"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Включите этот режим, чтобы после последнего слайда слайдер продолжал прокрутку с первого, создавая бесконечный цикл.
|
||||
</template>
|
||||
</SettingsItem>
|
||||
|
||||
<SettingsItem label="Автоматическая прокрутка">
|
||||
<template #default>
|
||||
<Switcher v-model="slider.autoplay"/>
|
||||
</template>
|
||||
|
||||
<template #help>
|
||||
Слайдер будет автоматически листать изображения каждые 3 секунды
|
||||
</template>
|
||||
</SettingsItem>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<table class="table table-striped table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<td class="text-left">Заголовок</td>
|
||||
<td class="text-left">Ссылка</td>
|
||||
<td class="text-center">Изображение</td>
|
||||
<td>Действия</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(slide, index) in slider.slides">
|
||||
<td class="text-left">
|
||||
<input v-model="slide.title" type="text" placeholder="Заголовок слайда"
|
||||
class="form-control"/>
|
||||
</td>
|
||||
<td class="text-left" style="width: 30%;">
|
||||
<LinkSelector v-model="slide.link"/>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<OcImagePicker v-model="slide.image"/>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
<button type="button" class="btn btn-danger" @click="removeSlide(index)">
|
||||
<i class="fa fa-minus-circle"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3"></td>
|
||||
<td class="text-left">
|
||||
<button @click="addSlide" type="button" class="btn btn-primary">
|
||||
<i class="fa fa-plus-circle"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import OcImagePIcker from "@/components/OcImagePIcker.vue";
|
||||
import LinkSelector from "@/components/Slider/LinkSelector.vue";
|
||||
import SettingsItem from "@/components/SettingsItem.vue";
|
||||
import Switcher from "@/components/Switcher.vue";
|
||||
|
||||
const slider = ref({});
|
||||
|
||||
function removeSlide(index) {
|
||||
slider.value.slides.splice(index, 1);
|
||||
}
|
||||
|
||||
function addSlide() {
|
||||
slider.value.slides.push({
|
||||
title: '',
|
||||
link: {
|
||||
type: 'none',
|
||||
value: null,
|
||||
},
|
||||
image: '',
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
slider.value = JSON.parse(window.TeleCart.mainpage_slider);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.text-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
28
frontend/admin/src/components/Switcher.vue
Normal file
28
frontend/admin/src/components/Switcher.vue
Normal file
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<div class="btn-group btn-toggle tw:mt-3">
|
||||
<button
|
||||
class="btn btn-xs"
|
||||
:class="{active: model === true, 'btn-success': model === true, 'btn-default' : model === false }"
|
||||
@click.prevent="model = true"
|
||||
>
|
||||
Вкл
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-xs"
|
||||
:class="{active: model === false, 'btn-danger': model === false, 'btn-default' : model === true }"
|
||||
@click.prevent="model = false"
|
||||
>
|
||||
Выкл
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const model = defineModel({
|
||||
default: false,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
@@ -1,14 +1,20 @@
|
||||
import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
const app = createApp(App)
|
||||
function onReady(fn) {
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', fn);
|
||||
} else {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
|
||||
app.use(createPinia())
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
onReady(() => {
|
||||
const app = createApp(App);
|
||||
app.use(createPinia());
|
||||
app.use(router);
|
||||
app.mount('#app');
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<Banners/>
|
||||
<Slider/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import Banners from "@/components/Banners/Banners.vue";
|
||||
import Slider from "@/components/Slider/Slider.vue";
|
||||
</script>
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import {fileURLToPath, URL} from 'node:url';
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
import {defineConfig} from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueDevTools from 'vite-plugin-vue-devtools';
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
tailwindcss(),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
@@ -19,11 +21,11 @@ export default defineConfig({
|
||||
build: {
|
||||
manifest: true,
|
||||
sourcemap: true,
|
||||
outDir: '../modules/oc_telegram_shop/upload/admin/view/javascript',
|
||||
outDir: '../../module/oc_telegram_shop/upload/admin/view/javascript/telecart',
|
||||
emptyOutDir: true, // also necessary
|
||||
rollupOptions: {
|
||||
input: {
|
||||
bulk_products: '/src/main.js',
|
||||
telecart: '/src/main.js',
|
||||
},
|
||||
output: {
|
||||
entryFileNames: `[name].js`,
|
||||
@@ -43,4 +45,4 @@ export default defineConfig({
|
||||
protocol: 'ws',
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
<template>
|
||||
<div v-if="slides.length > 0" class="app-banner px-4">
|
||||
<Swiper
|
||||
class="select-none"
|
||||
:slides-per-view="1"
|
||||
:space-between="50"
|
||||
pagination
|
||||
:pagination="{ clickable: true }"
|
||||
@swiper="onSwiper"
|
||||
@slideChange="onSlideChange"
|
||||
>
|
||||
<SwiperSlide v-for="slide in slides" :key="slide.id">
|
||||
<RouterLink
|
||||
v-if="slide?.link?.type === 'category'"
|
||||
:to="{name: 'product.categories.show', params: {category_id: slide.link.value.category_id}}"
|
||||
@click="sliderClick(slide)"
|
||||
>
|
||||
<img :src="slide.image" :alt="slide.title">
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink
|
||||
v-else-if="slide?.link?.type === 'product'"
|
||||
:to="{name: 'product.show', params: {id: slide.link.value.product_id}}"
|
||||
@click="sliderClick(slide)"
|
||||
>
|
||||
<img :src="slide.image" :alt="slide.title">
|
||||
</RouterLink>
|
||||
|
||||
<img
|
||||
v-else-if="slide?.link?.type === 'url'"
|
||||
:src="slide.image"
|
||||
:alt="slide.title"
|
||||
@click="openExternalLink(slide.link.value.url, slide)"
|
||||
>
|
||||
|
||||
<img v-else :src="slide.image" :alt="slide.title"/>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {Swiper, SwiperSlide} from 'swiper/vue';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import {onMounted, ref} from "vue";
|
||||
import {fetchBanner} from "@/utils/ftch.js";
|
||||
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
||||
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
|
||||
|
||||
const yaMetrika = useYaMetrikaStore();
|
||||
const slides = ref([]);
|
||||
|
||||
const onSwiper = (swiper) => {
|
||||
console.log(swiper);
|
||||
};
|
||||
const onSlideChange = () => {
|
||||
console.log('slide change');
|
||||
};
|
||||
|
||||
function sliderClick(slide) {
|
||||
yaMetrika.reachGoal(YA_METRIKA_GOAL.SLIDER_HOME_CLICK, {
|
||||
banner: slide.title,
|
||||
});
|
||||
}
|
||||
|
||||
function openExternalLink(link, slide) {
|
||||
if (! link) {
|
||||
return;
|
||||
}
|
||||
|
||||
yaMetrika.reachGoal(YA_METRIKA_GOAL.SLIDER_HOME_CLICK, {
|
||||
banner: slide.title,
|
||||
});
|
||||
|
||||
window.Telegram.WebApp.openLink(link, {try_instant_view: false});
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
const response = await fetchBanner();
|
||||
slides.value = response.data;
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.app-banner .swiper-horizontal > .swiper-pagination-bullets {
|
||||
position: relative;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.app-banner .swiper-horizontal .swiper-slide {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.app-banner .swiper-horizontal .swiper-slide img {
|
||||
border-radius: var(--radius-box);
|
||||
}
|
||||
</style>
|
||||
180
frontend/spa/src/components/MainpageSlider.vue
Normal file
180
frontend/spa/src/components/MainpageSlider.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="sliders.mainpage_slider.is_enabled && sliders.mainpage_slider.slides.length > 0"
|
||||
class="app-banner"
|
||||
:class="classList"
|
||||
>
|
||||
<Swiper
|
||||
:effect="slideEffect"
|
||||
class="select-none"
|
||||
:slides-per-view="1"
|
||||
:space-between="sliders.mainpage_slider.space_between"
|
||||
:pagination="pagination"
|
||||
:lazy="true"
|
||||
:modules="modules"
|
||||
:scrollbar="scrollbar"
|
||||
:free-mode="sliders.mainpage_slider.free_mode"
|
||||
:loop="sliders.mainpage_slider.loop"
|
||||
:autoplay="autoplay"
|
||||
@swiper="onSwiper"
|
||||
@slideChange="onSlideChange"
|
||||
>
|
||||
<SwiperSlide v-for="slide in sliders.mainpage_slider.slides" :key="slide.id">
|
||||
<RouterLink
|
||||
v-if="slide?.link?.type === 'category'"
|
||||
:to="{name: 'product.categories.show', params: {category_id: slide.link.value.category_id}}"
|
||||
@click="sliderClick(slide)"
|
||||
>
|
||||
<img :src="slide.image" :alt="slide.title" loading="lazy">
|
||||
</RouterLink>
|
||||
|
||||
<RouterLink
|
||||
v-else-if="slide?.link?.type === 'product'"
|
||||
:to="{name: 'product.show', params: {id: slide.link.value.product_id}}"
|
||||
@click="sliderClick(slide)"
|
||||
>
|
||||
<img :src="slide.image" :alt="slide.title" loading="lazy">
|
||||
</RouterLink>
|
||||
|
||||
<img
|
||||
v-else-if="slide?.link?.type === 'url'"
|
||||
:src="slide.image"
|
||||
:alt="slide.title"
|
||||
loading="lazy"
|
||||
@click="openExternalLink(slide.link.value.url, slide)"
|
||||
>
|
||||
|
||||
<img v-else :src="slide.image" :alt="slide.title" loading="lazy"/>
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {Swiper, SwiperSlide} from 'swiper/vue';
|
||||
import 'swiper/css';
|
||||
import 'swiper/css/navigation';
|
||||
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
||||
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
|
||||
import {EffectCoverflow, EffectCards, EffectCube, EffectFlip, Scrollbar, Autoplay} from 'swiper/modules';
|
||||
import {computed, onMounted} from "vue";
|
||||
import {useSlidersStore} from "@/stores/SlidersStore.js";
|
||||
|
||||
const sliders = useSlidersStore();
|
||||
const yaMetrika = useYaMetrikaStore();
|
||||
const modules = [
|
||||
Autoplay,
|
||||
EffectCards,
|
||||
EffectFlip,
|
||||
EffectCube,
|
||||
Scrollbar,
|
||||
EffectCoverflow,
|
||||
];
|
||||
|
||||
const classList = computed(() => {
|
||||
if (sliders.mainpage_slider.effect === 'cards') {
|
||||
return ['px-8'];
|
||||
}
|
||||
|
||||
if (sliders.mainpage_slider.effect === 'flip') {
|
||||
return ['px-4', 'pb-4', 'pt-4'];
|
||||
}
|
||||
|
||||
if (sliders.mainpage_slider.effect === 'cube') {
|
||||
return ['px-4', 'pb-10'];
|
||||
}
|
||||
|
||||
return ['px-4'];
|
||||
});
|
||||
|
||||
const onSwiper = (swiper) => {
|
||||
console.log(swiper);
|
||||
};
|
||||
const onSlideChange = () => {
|
||||
console.log('slide change');
|
||||
};
|
||||
|
||||
const slideEffect = computed(() => {
|
||||
if (sliders.mainpage_slider.effect === 'slide') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return sliders.mainpage_slider.effect;
|
||||
});
|
||||
|
||||
const pagination = computed(() => {
|
||||
if (sliders.mainpage_slider.pagination) {
|
||||
return {
|
||||
clickable: true, dynamicBullets: false,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const scrollbar = computed(() => {
|
||||
if (sliders.mainpage_slider.scrollbar) {
|
||||
return {
|
||||
hide: true,
|
||||
};
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const autoplay = computed(() => {
|
||||
if (sliders.mainpage_slider.autoplay) {
|
||||
return {
|
||||
delay: 3000,
|
||||
reverseDirection: false,
|
||||
};
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
function sliderClick(slide) {
|
||||
yaMetrika.reachGoal(YA_METRIKA_GOAL.SLIDER_HOME_CLICK, {
|
||||
banner: slide.title,
|
||||
});
|
||||
}
|
||||
|
||||
function openExternalLink(link, slide) {
|
||||
if (!link) {
|
||||
return;
|
||||
}
|
||||
|
||||
yaMetrika.reachGoal(YA_METRIKA_GOAL.SLIDER_HOME_CLICK, {
|
||||
banner: slide.title,
|
||||
});
|
||||
|
||||
window.Telegram.WebApp.openLink(link, {try_instant_view: false});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
console.debug('[Mainpage Slider] Status: ', sliders.mainpage_slider);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.app-banner {
|
||||
aspect-ratio: 740 / 400;
|
||||
}
|
||||
|
||||
.app-banner .swiper {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.app-banner .swiper-horizontal > .swiper-pagination-bullets {
|
||||
position: relative;
|
||||
bottom: 10px;
|
||||
}
|
||||
|
||||
.app-banner .swiper-horizontal .swiper-slide {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.app-banner .swiper-horizontal .swiper-slide img {
|
||||
border-radius: var(--radius-box);
|
||||
}
|
||||
</style>
|
||||
@@ -16,6 +16,7 @@ import 'swiper/element/bundle';
|
||||
import 'swiper/css/bundle';
|
||||
import AppLoading from "@/AppLoading.vue";
|
||||
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
|
||||
import {useSlidersStore} from "@/stores/SlidersStore.js";
|
||||
register();
|
||||
|
||||
const pinia = createPinia();
|
||||
@@ -26,6 +27,7 @@ app
|
||||
.use(VueTelegramPlugin);
|
||||
|
||||
const settings = useSettingsStore();
|
||||
useSlidersStore().fetchMainpageSlider();
|
||||
|
||||
const appLoading = createApp(AppLoading);
|
||||
appLoading.mount('#app');
|
||||
|
||||
26
frontend/spa/src/stores/SlidersStore.js
Normal file
26
frontend/spa/src/stores/SlidersStore.js
Normal file
@@ -0,0 +1,26 @@
|
||||
import {defineStore} from "pinia";
|
||||
import {fetchBanner} from "@/utils/ftch.js";
|
||||
|
||||
export const useSlidersStore = defineStore('sliders', {
|
||||
state: () => ({
|
||||
mainpage_slider: {
|
||||
is_enabled: false,
|
||||
space_between: 30,
|
||||
autoplay: false,
|
||||
effect: 'cube', // null, flip, cards, cube
|
||||
pagination: false,
|
||||
scrollbar: false,
|
||||
free_mode: false,
|
||||
loop: false,
|
||||
slides: [],
|
||||
},
|
||||
}),
|
||||
|
||||
actions: {
|
||||
async fetchMainpageSlider() {
|
||||
console.debug('[Sliders Store] Fetch mainpage slider from server.');
|
||||
const response = await fetchBanner();
|
||||
this.mainpage_slider = Object.assign({}, this.mainpage_slider, response.data);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -6,6 +6,7 @@
|
||||
html, body, #app {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
html {
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<div ref="goodsRef" class="pb-20">
|
||||
<CategoriesInline/>
|
||||
|
||||
<Banner/>
|
||||
<div class="overflow-hidden">
|
||||
<MainpageSlider/>
|
||||
</div>
|
||||
|
||||
<div class="px-5 fixed z-50 w-full opacity-90" style="bottom: calc(var(--tg-safe-area-inset-bottom, 0px) + 80px);">
|
||||
<div class="flex justify-center">
|
||||
@@ -31,12 +33,12 @@
|
||||
<script setup>
|
||||
import ProductsList from "@/components/ProductsList.vue";
|
||||
import CategoriesInline from "../components/CategoriesInline.vue";
|
||||
import {nextTick, onActivated, onMounted, ref, toRaw} from "vue";
|
||||
import {onActivated, onMounted, ref, toRaw} from "vue";
|
||||
import IconFunnel from "@/components/Icons/IconFunnel.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import ftch from "@/utils/ftch.js";
|
||||
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
|
||||
import Banner from "@/components/Banner.vue";
|
||||
import MainpageSlider from "@/components/MainpageSlider.vue";
|
||||
import {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
|
||||
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
||||
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
||||
|
||||
@@ -17,7 +17,7 @@ export default defineConfig({
|
||||
|
||||
base: '/image/catalog/tgshopspa/',
|
||||
build: {
|
||||
outDir: '../module/oc_telegram_shop/upload/image/catalog/tgshopspa',
|
||||
outDir: '../../module/oc_telegram_shop/upload/image/catalog/tgshopspa',
|
||||
emptyOutDir: true,
|
||||
sourcemap: true,
|
||||
manifest: true,
|
||||
|
||||
@@ -93,6 +93,7 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
$hasConfig = $this->config->get('module_tgshop_app_name') !== null;
|
||||
|
||||
if ($hasConfig) {
|
||||
$this->cleanUpConfigs();
|
||||
$this->updateConfigFromDefaults();
|
||||
$this->cleanUpOldAssets();
|
||||
$this->injectVueJs();
|
||||
@@ -109,9 +110,9 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
|
||||
if (($this->request->server['REQUEST_METHOD'] === 'POST') && $this->validate()) {
|
||||
$postData = $this->request->post;
|
||||
$postData['module_tgshop_mainpage_banners'] = [];
|
||||
if (! empty($_POST['module_tgshop_mainpage_banners'])) {
|
||||
$postData['module_tgshop_mainpage_banners'] = $_POST['module_tgshop_mainpage_banners'];
|
||||
$postData['module_tgshop_mainpage_slider'] = [];
|
||||
if (! empty($_POST['module_tgshop_mainpage_slider'])) {
|
||||
$postData['module_tgshop_mainpage_slider'] = $_POST['module_tgshop_mainpage_slider'];
|
||||
}
|
||||
$this->model_setting_setting->editSetting('module_tgshop', $postData);
|
||||
|
||||
@@ -136,11 +137,11 @@ class ControllerExtensionModuleTgshop extends Controller
|
||||
|
||||
$data['settings'] = $this->getSettingsConfig();
|
||||
|
||||
$data['banners'] = [];
|
||||
$banners = $this->config->get('module_tgshop_mainpage_banners');
|
||||
$data['mainpage_slider'] = [];
|
||||
$banners = $this->config->get('module_tgshop_mainpage_slider');
|
||||
if ($banners) {
|
||||
$banners = html_entity_decode($banners);
|
||||
$data['banners'] = $banners;
|
||||
$data['mainpage_slider'] = $banners;
|
||||
}
|
||||
|
||||
foreach ($data['settings'] as $configs) {
|
||||
@@ -364,11 +365,20 @@ TEXT,
|
||||
'module_tgshop_enable_store' => 1,
|
||||
'module_tgshop_feature_coupons' => 0,
|
||||
'module_tgshop_feature_vouchers' => 0,
|
||||
'module_tgshop_home_banner_id' => null,
|
||||
'module_tgshop_text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||
'module_tgshop_text_empty_cart' => 'Ваша корзина пуста',
|
||||
'module_tgshop_text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.',
|
||||
'module_tgshop_mainpage_banners' => '[]',
|
||||
'module_tgshop_mainpage_slider' => json_encode([
|
||||
'is_enabled' => false,
|
||||
'effect' => 'slide',
|
||||
'pagination' => true,
|
||||
'scrollbar' => false,
|
||||
'free_mode' => false,
|
||||
'space_between' => 30,
|
||||
'autoplay' => false,
|
||||
'loop' => false,
|
||||
'slides' => [],
|
||||
], JSON_THROW_ON_ERROR),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -384,11 +394,6 @@ TEXT,
|
||||
'user_token=' . $this->session->data['user_token'],
|
||||
true
|
||||
);
|
||||
$ocBannersLink = $this->url->link(
|
||||
'design/banner',
|
||||
'user_token=' . $this->session->data['user_token'],
|
||||
true
|
||||
);
|
||||
|
||||
return [
|
||||
'general' => [
|
||||
@@ -698,28 +703,22 @@ HTML,
|
||||
}
|
||||
}
|
||||
|
||||
private function getBannersList(): array
|
||||
{
|
||||
$this->load->model('design/banner');
|
||||
$allBanners = $this->model_design_banner->getBanners();
|
||||
$map = [];
|
||||
foreach ($allBanners as $item) {
|
||||
$map[(int) $item['banner_id']] = $item['name'];
|
||||
}
|
||||
|
||||
return [null => 'Не показывать'] + $map;
|
||||
}
|
||||
|
||||
private function injectVueJs(): void
|
||||
{
|
||||
$appDir = rtrim(DIR_APPLICATION, '/');
|
||||
if (file_exists("$appDir/view/javascript/telecart/telecart.js")) {
|
||||
$this->document->addScript('view/javascript/telecart/telecart.js');
|
||||
$this->document->addStyle('view/javascript/telecart/telecart.css');
|
||||
$hash = md5(file_get_contents($appDir . '/view/javascript/telecart/manifest.json'));
|
||||
$this->document->addScript('view/javascript/telecart/telecart.js?v=' . $hash);
|
||||
$this->document->addStyle('view/javascript/telecart/telecart.css?v=' . $hash);
|
||||
} elseif (file_exists("$appDir/view/integration.js")) {
|
||||
$this->document->addScript('view/integration.js');
|
||||
} else {
|
||||
throw new RuntimeException('Unable to load Vuejs frontend.');
|
||||
}
|
||||
}
|
||||
|
||||
private function cleanUpConfigs(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +452,7 @@
|
||||
<script>
|
||||
window.TeleCart = {
|
||||
user_token: '{{ user_token }}',
|
||||
banners: '{{ banners }}',
|
||||
mainpage_slider: '{{ mainpage_slider }}',
|
||||
};
|
||||
</script>
|
||||
<div id="app">App Loading...</div>
|
||||
|
||||
@@ -94,7 +94,7 @@ class ControllerExtensionTgshopHandle extends Controller
|
||||
$this->config->get('module_tgshop_feature_vouchers'),
|
||||
FILTER_VALIDATE_BOOLEAN
|
||||
),
|
||||
'mainpage_banners' => $this->safeJsonDecode($this->config->get('module_tgshop_mainpage_banners'), []),
|
||||
'mainpage_slider' => $this->safeJsonDecode($this->config->get('module_tgshop_mainpage_slider'), []),
|
||||
'texts' => [
|
||||
'no_more_products' => $this->config->get('module_tgshop_text_no_more_products'),
|
||||
'empty_cart' => $this->config->get('module_tgshop_text_empty_cart'),
|
||||
|
||||
@@ -111,7 +111,7 @@ class ImageTool implements ImageToolInterface
|
||||
|
||||
$image = $this->manager->make($fullOldPath)
|
||||
->fit($width, $height, function ($constraint) {
|
||||
$constraint->upsize();
|
||||
// $constraint->upsize();
|
||||
}, $position);
|
||||
|
||||
$image->encode($format, 75)->save($fullNewPath, 75, $format);
|
||||
|
||||
@@ -24,13 +24,12 @@ class BannerHandler
|
||||
|
||||
public function show(): JsonResponse
|
||||
{
|
||||
$data = [];
|
||||
$slides = $this->settings->get('mainpage_banners', []);
|
||||
$slider = $this->settings->get('mainpage_slider', []);
|
||||
|
||||
if ($slides) {
|
||||
foreach ($slides as $index => $slide) {
|
||||
if ($slider && ! empty($slider['slides']) && is_array($slider['slides'])) {
|
||||
foreach ($slider['slides'] as $index => $slide) {
|
||||
if (is_file(DIR_IMAGE . $slide['image'])) {
|
||||
$data[] = [
|
||||
$slider['slides'][$index] = [
|
||||
'id' => $index,
|
||||
'title' => $slide['title'],
|
||||
'link' => $slide['link'],
|
||||
@@ -41,7 +40,7 @@ class BannerHandler
|
||||
}
|
||||
|
||||
return new JsonResponse([
|
||||
'data' => $data,
|
||||
'data' => $slider,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ class SettingsHandler
|
||||
'feature_vouchers' => $this->settings->get('feature_vouchers') ?? false,
|
||||
'currency_code' => $this->settings->get('oc_default_currency', 'RUB'),
|
||||
'texts' => $this->settings->get('texts'),
|
||||
'mainpage_slider' => $this->settings->get('mainpage_slider'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/CartServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/CartServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/OrderCreateServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/OrderCreateServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/ProductsServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/Integration/Services/ProductsServiceTest.php
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/README.md
Normal file → Executable file
0
module/oc_telegram_shop/upload/oc_telegram_shop/tests/README.md
Normal file → Executable file
0
rebuildgaa
Normal file
0
rebuildgaa
Normal file
@@ -29,7 +29,7 @@ if [ -z "$SRC_PATH" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Build Telecart Frontend..."
|
||||
echo "Build Telecart SPA Frontend..."
|
||||
cd "${SRC_PATH}/frontend/spa"
|
||||
bun install
|
||||
bun run build
|
||||
@@ -43,9 +43,18 @@ bun install
|
||||
bun run build
|
||||
|
||||
echo "Move manifest file"
|
||||
cp "${SRC_PATH}/module/oc_telegram_shop/upload/admin/view/javascript/.vite/manifest.json" "${SRC_PATH}/module/oc_telegram_shop/upload/admin/view/javascript/manifest.json"
|
||||
cp "${SRC_PATH}/module/oc_telegram_shop/upload/admin/view/javascript/telecart/.vite/manifest.json" \
|
||||
"${SRC_PATH}/module/oc_telegram_shop/upload/admin/view/javascript/telecart/manifest.json"
|
||||
|
||||
cd - > /dev/null
|
||||
|
||||
cd "$SRC_PATH"
|
||||
|
||||
echo "Cleanup frontend"
|
||||
rm -v module/oc_telegram_shop/upload/image/catalog/tgshopspa/vite.svg
|
||||
rm -v module/oc_telegram_shop/upload/image/catalog/tgshopspa/assets/*.map
|
||||
rm -v module/oc_telegram_shop/upload/admin/view/integration.js
|
||||
rm -v module/oc_telegram_shop/upload/admin/view/javascript/telecart/telecart.js.map
|
||||
rm -v module/oc_telegram_shop/upload/admin/view/javascript/telecart/favicon.ico
|
||||
|
||||
echo "Install Composer dependencies."
|
||||
cd "${SRC_PATH}/module/oc_telegram_shop/upload/oc_telegram_shop"
|
||||
@@ -55,7 +64,8 @@ composer install \
|
||||
--optimize-autoloader \
|
||||
--no-interaction \
|
||||
--no-cache
|
||||
cd - > /dev/null
|
||||
|
||||
cd "$SRC_PATH"
|
||||
|
||||
echo "Copy .env for production"
|
||||
cp "${SRC_PATH}/module/oc_telegram_shop/upload/oc_telegram_shop/.env.production" \
|
||||
|
||||
@@ -27,7 +27,7 @@ docker compose exec web bash -c '\
|
||||
--username admin \
|
||||
--password admin \
|
||||
--email youremail@example.com \
|
||||
--http_server http://localhost:8000/; exit $?'
|
||||
--http_server https://api.tg.nikitakiselev.ru/; exit $?'
|
||||
|
||||
docker compose exec web bash -c "cd /web; composer update"
|
||||
echo "Moving storage folder outside the system."
|
||||
|
||||
Reference in New Issue
Block a user