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:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
- 'issue/**'
|
||||||
|
- develop
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@@ -35,7 +37,6 @@ jobs:
|
|||||||
module-build:
|
module-build:
|
||||||
name: Build module.
|
name: Build module.
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [test]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: oven-sh/setup-bun@v2
|
- uses: oven-sh/setup-bun@v2
|
||||||
@@ -60,6 +61,7 @@ jobs:
|
|||||||
release:
|
release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [test, module-build]
|
needs: [test, module-build]
|
||||||
|
if: github.ref == 'refs/heads/master'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
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
|
cd frontend/spa && bun run dev
|
||||||
|
|
||||||
dev-admin:
|
dev-admin:
|
||||||
|
rm -rf module/oc_telegram_shop/upload/admin/view/javascript && \
|
||||||
$(MAKE) link && \
|
$(MAKE) link && \
|
||||||
cd frontend/admin && bun run dev
|
cd frontend/admin && bun run dev
|
||||||
cd frontend/spa && bun run dev
|
cd frontend/spa && bun run dev
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Telecart теперь поддерживает встроенную систем
|
|||||||
• Добавлены автоматические тесты, запускаемые при каждом билде, что значительно снижает количество багов в новых версиях.
|
• Добавлены автоматические тесты, запускаемые при каждом билде, что значительно снижает количество багов в новых версиях.
|
||||||
• Исправлены проблемы с поиском и оформлением заказов, обнаруженные на некоторых магазинах.
|
• Исправлены проблемы с поиском и оформлением заказов, обнаруженные на некоторых магазинах.
|
||||||
• Повышена стабильность работы.
|
• Повышена стабильность работы.
|
||||||
|
• Уменьшен размер архива с модулем примерно в 2 раза.
|
||||||
|
|
||||||
Купить модуль: https://liveopencart.ru/opencart-moduli-shablony/moduli/telecart
|
Купить модуль: https://liveopencart.ru/opencart-moduli-shablony/moduli/telecart
|
||||||
Документация: https://telecart-labs.github.io/docs/
|
Документация: https://telecart-labs.github.io/docs/
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "admin",
|
"name": "admin",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
|
"daisyui": "^5.4.2",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
|
"tailwindcss": "^4.1.16",
|
||||||
"vue": "^3.5.22",
|
"vue": "^3.5.22",
|
||||||
"vue-router": "^4.6.3",
|
"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=="],
|
"@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=="],
|
"@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=="],
|
"@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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],
|
||||||
|
|
||||||
"error-stack-parser-es": ["error-stack-parser-es@1.0.5", "", {}, "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA=="],
|
"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=="],
|
"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=="],
|
"has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
|
||||||
|
|
||||||
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
"hookable": ["hookable@5.5.3", "", {}, "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="],
|
||||||
@@ -470,6 +511,8 @@
|
|||||||
|
|
||||||
"isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
"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-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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"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=="],
|
"@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-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=="],
|
"@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/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tailwindcss/vite": "^4.1.16",
|
||||||
|
"daisyui": "^5.4.2",
|
||||||
"pinia": "^3.0.3",
|
"pinia": "^3.0.3",
|
||||||
|
"tailwindcss": "^4.1.16",
|
||||||
"vue": "^3.5.22",
|
"vue": "^3.5.22",
|
||||||
"vue-router": "^4.6.3"
|
"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>
|
<template>
|
||||||
<div>
|
<div class="oc-image">
|
||||||
<a href="#" data-toggle="image" class="img-thumbnail" :id="`thumb-image-${id}`">
|
<div v-if="isLoaded === false" class="loader">
|
||||||
<img :src="thumb"
|
<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"
|
data-placeholder="/image/cache/no_image-100x100.png"
|
||||||
alt="Image"
|
alt="Image"
|
||||||
|
@load="isLoaded = true"
|
||||||
>
|
>
|
||||||
</a>
|
</a>
|
||||||
<input ref="inputRef" type="hidden" value="" :id="`input-image-${id}`">
|
<input ref="inputRef" type="hidden" value="" :id="`input-image-${id}`">
|
||||||
@@ -17,6 +23,7 @@ const id = useId();
|
|||||||
const model = defineModel();
|
const model = defineModel();
|
||||||
const emit = defineEmits(['update:modelValue']);
|
const emit = defineEmits(['update:modelValue']);
|
||||||
const inputRef = ref(null);
|
const inputRef = ref(null);
|
||||||
|
const isLoaded = ref(false);
|
||||||
|
|
||||||
const thumb = computed(() => {
|
const thumb = computed(() => {
|
||||||
if (!model.value) return '/image/cache/no_image-100x100.png';
|
if (!model.value) return '/image/cache/no_image-100x100.png';
|
||||||
@@ -39,3 +46,18 @@ onMounted(() => {
|
|||||||
observer.observe(input, {attributes: true, attributeFilter: ['value']});
|
observer.observe(input, {attributes: true, attributeFilter: ['value']});
|
||||||
});
|
});
|
||||||
</script>
|
</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
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
name="category"
|
name="category"
|
||||||
:value="`${category?.name}`"
|
:value="`${category?.name || ''}`"
|
||||||
placeholder="Начните вводить название категории..."
|
placeholder="Начните вводить название категории..."
|
||||||
class="form-control"
|
class="form-control"
|
||||||
ref="categoryRef"
|
ref="categoryRef"
|
||||||
@@ -34,18 +34,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import CategorySelect from "@/components/Banners/CategorySelect.vue";
|
import CategorySelect from "@/components/Slider/CategorySelect.vue";
|
||||||
import ProductSelect from "@/components/Banners/ProductSelect.vue";
|
import ProductSelect from "@/components/Slider/ProductSelect.vue";
|
||||||
|
|
||||||
const link = defineModel();
|
const link = defineModel();
|
||||||
|
|
||||||
function setLink(value) {
|
function setLink(value) {
|
||||||
if (Object.is(link.value)) {
|
if (link.value?.value) {
|
||||||
link.value.value.url = value;
|
link.value.value.url = value;
|
||||||
} else {
|
} else {
|
||||||
link.value.value = {
|
link.value.value = { url: value };
|
||||||
url: value,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
:value="`${model?.name}`"
|
:value="`${model?.name || ''}`"
|
||||||
placeholder="Начните вводить название товара..."
|
placeholder="Начните вводить название товара..."
|
||||||
class="form-control"
|
class="form-control"
|
||||||
ref="inputRef"
|
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 './assets/main.css'
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
const app = createApp(App)
|
function onReady(fn) {
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', fn);
|
||||||
|
} else {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
app.use(createPinia())
|
onReady(() => {
|
||||||
app.use(router)
|
const app = createApp(App);
|
||||||
|
app.use(createPinia());
|
||||||
app.mount('#app')
|
app.use(router);
|
||||||
|
app.mount('#app');
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<Banners/>
|
<Slider/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import Banners from "@/components/Banners/Banners.vue";
|
import Slider from "@/components/Slider/Slider.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
import {fileURLToPath, URL} from 'node:url';
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
import {defineConfig} from 'vite';
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue';
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
import vueDevTools from 'vite-plugin-vue-devtools';
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [
|
||||||
vue(),
|
vue(),
|
||||||
vueDevTools(),
|
vueDevTools(),
|
||||||
|
tailwindcss(),
|
||||||
],
|
],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
@@ -19,11 +21,11 @@ export default defineConfig({
|
|||||||
build: {
|
build: {
|
||||||
manifest: true,
|
manifest: true,
|
||||||
sourcemap: 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
|
emptyOutDir: true, // also necessary
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
input: {
|
input: {
|
||||||
bulk_products: '/src/main.js',
|
telecart: '/src/main.js',
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
entryFileNames: `[name].js`,
|
entryFileNames: `[name].js`,
|
||||||
@@ -43,4 +45,4 @@ export default defineConfig({
|
|||||||
protocol: 'ws',
|
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 'swiper/css/bundle';
|
||||||
import AppLoading from "@/AppLoading.vue";
|
import AppLoading from "@/AppLoading.vue";
|
||||||
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
|
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.js";
|
||||||
|
import {useSlidersStore} from "@/stores/SlidersStore.js";
|
||||||
register();
|
register();
|
||||||
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
@@ -26,6 +27,7 @@ app
|
|||||||
.use(VueTelegramPlugin);
|
.use(VueTelegramPlugin);
|
||||||
|
|
||||||
const settings = useSettingsStore();
|
const settings = useSettingsStore();
|
||||||
|
useSlidersStore().fetchMainpageSlider();
|
||||||
|
|
||||||
const appLoading = createApp(AppLoading);
|
const appLoading = createApp(AppLoading);
|
||||||
appLoading.mount('#app');
|
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 {
|
html, body, #app {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
<div ref="goodsRef" class="pb-20">
|
<div ref="goodsRef" class="pb-20">
|
||||||
<CategoriesInline/>
|
<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="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">
|
<div class="flex justify-center">
|
||||||
@@ -31,12 +33,12 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import ProductsList from "@/components/ProductsList.vue";
|
import ProductsList from "@/components/ProductsList.vue";
|
||||||
import CategoriesInline from "../components/CategoriesInline.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 IconFunnel from "@/components/Icons/IconFunnel.vue";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
import ftch from "@/utils/ftch.js";
|
import ftch from "@/utils/ftch.js";
|
||||||
import {useProductFiltersStore} from "@/stores/ProductFiltersStore.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 {useYaMetrikaStore} from "@/stores/yaMetrikaStore.js";
|
||||||
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
import {YA_METRIKA_GOAL} from "@/constants/yaMetrikaGoals.js";
|
||||||
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
import {useSettingsStore} from "@/stores/SettingsStore.js";
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
base: '/image/catalog/tgshopspa/',
|
base: '/image/catalog/tgshopspa/',
|
||||||
build: {
|
build: {
|
||||||
outDir: '../module/oc_telegram_shop/upload/image/catalog/tgshopspa',
|
outDir: '../../module/oc_telegram_shop/upload/image/catalog/tgshopspa',
|
||||||
emptyOutDir: true,
|
emptyOutDir: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
manifest: true,
|
manifest: true,
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ class ControllerExtensionModuleTgshop extends Controller
|
|||||||
$hasConfig = $this->config->get('module_tgshop_app_name') !== null;
|
$hasConfig = $this->config->get('module_tgshop_app_name') !== null;
|
||||||
|
|
||||||
if ($hasConfig) {
|
if ($hasConfig) {
|
||||||
|
$this->cleanUpConfigs();
|
||||||
$this->updateConfigFromDefaults();
|
$this->updateConfigFromDefaults();
|
||||||
$this->cleanUpOldAssets();
|
$this->cleanUpOldAssets();
|
||||||
$this->injectVueJs();
|
$this->injectVueJs();
|
||||||
@@ -109,9 +110,9 @@ class ControllerExtensionModuleTgshop extends Controller
|
|||||||
|
|
||||||
if (($this->request->server['REQUEST_METHOD'] === 'POST') && $this->validate()) {
|
if (($this->request->server['REQUEST_METHOD'] === 'POST') && $this->validate()) {
|
||||||
$postData = $this->request->post;
|
$postData = $this->request->post;
|
||||||
$postData['module_tgshop_mainpage_banners'] = [];
|
$postData['module_tgshop_mainpage_slider'] = [];
|
||||||
if (! empty($_POST['module_tgshop_mainpage_banners'])) {
|
if (! empty($_POST['module_tgshop_mainpage_slider'])) {
|
||||||
$postData['module_tgshop_mainpage_banners'] = $_POST['module_tgshop_mainpage_banners'];
|
$postData['module_tgshop_mainpage_slider'] = $_POST['module_tgshop_mainpage_slider'];
|
||||||
}
|
}
|
||||||
$this->model_setting_setting->editSetting('module_tgshop', $postData);
|
$this->model_setting_setting->editSetting('module_tgshop', $postData);
|
||||||
|
|
||||||
@@ -136,11 +137,11 @@ class ControllerExtensionModuleTgshop extends Controller
|
|||||||
|
|
||||||
$data['settings'] = $this->getSettingsConfig();
|
$data['settings'] = $this->getSettingsConfig();
|
||||||
|
|
||||||
$data['banners'] = [];
|
$data['mainpage_slider'] = [];
|
||||||
$banners = $this->config->get('module_tgshop_mainpage_banners');
|
$banners = $this->config->get('module_tgshop_mainpage_slider');
|
||||||
if ($banners) {
|
if ($banners) {
|
||||||
$banners = html_entity_decode($banners);
|
$banners = html_entity_decode($banners);
|
||||||
$data['banners'] = $banners;
|
$data['mainpage_slider'] = $banners;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($data['settings'] as $configs) {
|
foreach ($data['settings'] as $configs) {
|
||||||
@@ -364,11 +365,20 @@ TEXT,
|
|||||||
'module_tgshop_enable_store' => 1,
|
'module_tgshop_enable_store' => 1,
|
||||||
'module_tgshop_feature_coupons' => 0,
|
'module_tgshop_feature_coupons' => 0,
|
||||||
'module_tgshop_feature_vouchers' => 0,
|
'module_tgshop_feature_vouchers' => 0,
|
||||||
'module_tgshop_home_banner_id' => null,
|
|
||||||
'module_tgshop_text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
'module_tgshop_text_no_more_products' => 'Это всё по текущему запросу. Попробуйте уточнить фильтры или поиск.',
|
||||||
'module_tgshop_text_empty_cart' => 'Ваша корзина пуста',
|
'module_tgshop_text_empty_cart' => 'Ваша корзина пуста',
|
||||||
'module_tgshop_text_order_created_success' => 'Ваш заказ успешно оформлен и будет обработан в ближайшее время.',
|
'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'],
|
'user_token=' . $this->session->data['user_token'],
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
$ocBannersLink = $this->url->link(
|
|
||||||
'design/banner',
|
|
||||||
'user_token=' . $this->session->data['user_token'],
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'general' => [
|
'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
|
private function injectVueJs(): void
|
||||||
{
|
{
|
||||||
$appDir = rtrim(DIR_APPLICATION, '/');
|
$appDir = rtrim(DIR_APPLICATION, '/');
|
||||||
if (file_exists("$appDir/view/javascript/telecart/telecart.js")) {
|
if (file_exists("$appDir/view/javascript/telecart/telecart.js")) {
|
||||||
$this->document->addScript('view/javascript/telecart/telecart.js');
|
$hash = md5(file_get_contents($appDir . '/view/javascript/telecart/manifest.json'));
|
||||||
$this->document->addStyle('view/javascript/telecart/telecart.css');
|
$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")) {
|
} elseif (file_exists("$appDir/view/integration.js")) {
|
||||||
$this->document->addScript('view/integration.js');
|
$this->document->addScript('view/integration.js');
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException('Unable to load Vuejs frontend.');
|
throw new RuntimeException('Unable to load Vuejs frontend.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function cleanUpConfigs(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,7 +452,7 @@
|
|||||||
<script>
|
<script>
|
||||||
window.TeleCart = {
|
window.TeleCart = {
|
||||||
user_token: '{{ user_token }}',
|
user_token: '{{ user_token }}',
|
||||||
banners: '{{ banners }}',
|
mainpage_slider: '{{ mainpage_slider }}',
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<div id="app">App Loading...</div>
|
<div id="app">App Loading...</div>
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class ControllerExtensionTgshopHandle extends Controller
|
|||||||
$this->config->get('module_tgshop_feature_vouchers'),
|
$this->config->get('module_tgshop_feature_vouchers'),
|
||||||
FILTER_VALIDATE_BOOLEAN
|
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' => [
|
'texts' => [
|
||||||
'no_more_products' => $this->config->get('module_tgshop_text_no_more_products'),
|
'no_more_products' => $this->config->get('module_tgshop_text_no_more_products'),
|
||||||
'empty_cart' => $this->config->get('module_tgshop_text_empty_cart'),
|
'empty_cart' => $this->config->get('module_tgshop_text_empty_cart'),
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class ImageTool implements ImageToolInterface
|
|||||||
|
|
||||||
$image = $this->manager->make($fullOldPath)
|
$image = $this->manager->make($fullOldPath)
|
||||||
->fit($width, $height, function ($constraint) {
|
->fit($width, $height, function ($constraint) {
|
||||||
$constraint->upsize();
|
// $constraint->upsize();
|
||||||
}, $position);
|
}, $position);
|
||||||
|
|
||||||
$image->encode($format, 75)->save($fullNewPath, 75, $format);
|
$image->encode($format, 75)->save($fullNewPath, 75, $format);
|
||||||
|
|||||||
@@ -24,13 +24,12 @@ class BannerHandler
|
|||||||
|
|
||||||
public function show(): JsonResponse
|
public function show(): JsonResponse
|
||||||
{
|
{
|
||||||
$data = [];
|
$slider = $this->settings->get('mainpage_slider', []);
|
||||||
$slides = $this->settings->get('mainpage_banners', []);
|
|
||||||
|
|
||||||
if ($slides) {
|
if ($slider && ! empty($slider['slides']) && is_array($slider['slides'])) {
|
||||||
foreach ($slides as $index => $slide) {
|
foreach ($slider['slides'] as $index => $slide) {
|
||||||
if (is_file(DIR_IMAGE . $slide['image'])) {
|
if (is_file(DIR_IMAGE . $slide['image'])) {
|
||||||
$data[] = [
|
$slider['slides'][$index] = [
|
||||||
'id' => $index,
|
'id' => $index,
|
||||||
'title' => $slide['title'],
|
'title' => $slide['title'],
|
||||||
'link' => $slide['link'],
|
'link' => $slide['link'],
|
||||||
@@ -41,7 +40,7 @@ class BannerHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new JsonResponse([
|
return new JsonResponse([
|
||||||
'data' => $data,
|
'data' => $slider,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class SettingsHandler
|
|||||||
'feature_vouchers' => $this->settings->get('feature_vouchers') ?? false,
|
'feature_vouchers' => $this->settings->get('feature_vouchers') ?? false,
|
||||||
'currency_code' => $this->settings->get('oc_default_currency', 'RUB'),
|
'currency_code' => $this->settings->get('oc_default_currency', 'RUB'),
|
||||||
'texts' => $this->settings->get('texts'),
|
'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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Build Telecart Frontend..."
|
echo "Build Telecart SPA Frontend..."
|
||||||
cd "${SRC_PATH}/frontend/spa"
|
cd "${SRC_PATH}/frontend/spa"
|
||||||
bun install
|
bun install
|
||||||
bun run build
|
bun run build
|
||||||
@@ -43,9 +43,18 @@ bun install
|
|||||||
bun run build
|
bun run build
|
||||||
|
|
||||||
echo "Move manifest file"
|
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."
|
echo "Install Composer dependencies."
|
||||||
cd "${SRC_PATH}/module/oc_telegram_shop/upload/oc_telegram_shop"
|
cd "${SRC_PATH}/module/oc_telegram_shop/upload/oc_telegram_shop"
|
||||||
@@ -55,7 +64,8 @@ composer install \
|
|||||||
--optimize-autoloader \
|
--optimize-autoloader \
|
||||||
--no-interaction \
|
--no-interaction \
|
||||||
--no-cache
|
--no-cache
|
||||||
cd - > /dev/null
|
|
||||||
|
cd "$SRC_PATH"
|
||||||
|
|
||||||
echo "Copy .env for production"
|
echo "Copy .env for production"
|
||||||
cp "${SRC_PATH}/module/oc_telegram_shop/upload/oc_telegram_shop/.env.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 \
|
--username admin \
|
||||||
--password admin \
|
--password admin \
|
||||||
--email youremail@example.com \
|
--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"
|
docker compose exec web bash -c "cd /web; composer update"
|
||||||
echo "Moving storage folder outside the system."
|
echo "Moving storage folder outside the system."
|
||||||
|
|||||||
Reference in New Issue
Block a user