Создан поиск, уведомления, настройки, мониторгин, админ-панель
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "7219e565f7400643e10772d84e87d8a5",
|
||||
"content-hash": "f259164a4251a4ef37262d42fbeb40d6",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bower-asset/bootstrap",
|
||||
|
@ -32,7 +32,7 @@
|
|||
"version": "3.3.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:RobinHerbots/Inputmask.git",
|
||||
"url": "https://github.com/RobinHerbots/Inputmask.git",
|
||||
"reference": "5e670ad62f50c738388d4dcec78d2888505ad77b"
|
||||
},
|
||||
"dist": {
|
||||
|
@ -53,7 +53,7 @@
|
|||
"version": "3.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "git@github.com:jquery/jquery-dist.git",
|
||||
"url": "https://github.com/jquery/jquery-dist.git",
|
||||
"reference": "4c0e4becb8263bb5b3e6dadc448d8e7305ef8215"
|
||||
},
|
||||
"dist": {
|
||||
|
@ -643,20 +643,20 @@
|
|||
},
|
||||
{
|
||||
"name": "markbaker/matrix",
|
||||
"version": "2.0.0",
|
||||
"version": "2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MarkBaker/PHPMatrix.git",
|
||||
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a"
|
||||
"reference": "361c0f545c3172ee26c3d596a0aa03f0cef65e6a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
|
||||
"reference": "9567d9c4c519fbe40de01dbd1e4469dbbb66f46a",
|
||||
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/361c0f545c3172ee26c3d596a0aa03f0cef65e6a",
|
||||
"reference": "361c0f545c3172ee26c3d596a0aa03f0cef65e6a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0"
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.0",
|
||||
|
@ -674,22 +674,22 @@
|
|||
"Matrix\\": "classes/src/"
|
||||
},
|
||||
"files": [
|
||||
"classes/src/functions/adjoint.php",
|
||||
"classes/src/functions/antidiagonal.php",
|
||||
"classes/src/functions/cofactors.php",
|
||||
"classes/src/functions/determinant.php",
|
||||
"classes/src/functions/diagonal.php",
|
||||
"classes/src/functions/identity.php",
|
||||
"classes/src/functions/inverse.php",
|
||||
"classes/src/functions/minors.php",
|
||||
"classes/src/functions/trace.php",
|
||||
"classes/src/functions/transpose.php",
|
||||
"classes/src/operations/add.php",
|
||||
"classes/src/operations/directsum.php",
|
||||
"classes/src/operations/subtract.php",
|
||||
"classes/src/operations/multiply.php",
|
||||
"classes/src/operations/divideby.php",
|
||||
"classes/src/operations/divideinto.php"
|
||||
"classes/src/Functions/adjoint.php",
|
||||
"classes/src/Functions/antidiagonal.php",
|
||||
"classes/src/Functions/cofactors.php",
|
||||
"classes/src/Functions/determinant.php",
|
||||
"classes/src/Functions/diagonal.php",
|
||||
"classes/src/Functions/identity.php",
|
||||
"classes/src/Functions/inverse.php",
|
||||
"classes/src/Functions/minors.php",
|
||||
"classes/src/Functions/trace.php",
|
||||
"classes/src/Functions/transpose.php",
|
||||
"classes/src/Operations/add.php",
|
||||
"classes/src/Operations/directsum.php",
|
||||
"classes/src/Operations/subtract.php",
|
||||
"classes/src/Operations/multiply.php",
|
||||
"classes/src/Operations/divideby.php",
|
||||
"classes/src/Operations/divideinto.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
|
@ -711,17 +711,17 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
|
||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/PHP8"
|
||||
"source": "https://github.com/MarkBaker/PHPMatrix/tree/2.1.2"
|
||||
},
|
||||
"time": "2020-08-28T17:11:00+00:00"
|
||||
"time": "2021-01-23T16:37:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mirzaev/yii2-arangodb",
|
||||
"version": "2.1.0.x-dev",
|
||||
"version": "2.1.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://git.hood.su/mirzaev/yii2/arangodb",
|
||||
"reference": "3355611e2008933d647e96316b2a488a7be705c5"
|
||||
"reference": "bf4483291486eb0b991907c3e55e5392f84f2ed9"
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0.0",
|
||||
|
@ -763,7 +763,7 @@
|
|||
"ArangoDb",
|
||||
"yii2"
|
||||
],
|
||||
"time": "2021-01-20T03:59:35+00:00"
|
||||
"time": "2021-01-31T01:36:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "moonlandsoft/yii2-phpexcel",
|
||||
|
@ -2130,25 +2130,26 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "behat/gherkin",
|
||||
"version": "v4.6.2",
|
||||
"version": "v4.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Behat/Gherkin.git",
|
||||
"reference": "51ac4500c4dc30cbaaabcd2f25694299df666a31"
|
||||
"reference": "2391482cd003dfdc36b679b27e9f5326bd656acd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Behat/Gherkin/zipball/51ac4500c4dc30cbaaabcd2f25694299df666a31",
|
||||
"reference": "51ac4500c4dc30cbaaabcd2f25694299df666a31",
|
||||
"url": "https://api.github.com/repos/Behat/Gherkin/zipball/2391482cd003dfdc36b679b27e9f5326bd656acd",
|
||||
"reference": "2391482cd003dfdc36b679b27e9f5326bd656acd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.1"
|
||||
"php": "~7.2|~8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5|~5",
|
||||
"symfony/phpunit-bridge": "~2.7|~3|~4",
|
||||
"symfony/yaml": "~2.3|~3|~4"
|
||||
"cucumber/cucumber": "dev-gherkin-16.0.0",
|
||||
"phpunit/phpunit": "~8|~9",
|
||||
"symfony/phpunit-bridge": "~3|~4|~5",
|
||||
"symfony/yaml": "~3|~4|~5"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "If you want to parse features, represented in YAML files"
|
||||
|
@ -2175,7 +2176,7 @@
|
|||
"homepage": "http://everzet.com"
|
||||
}
|
||||
],
|
||||
"description": "Gherkin DSL parser for PHP 5.3",
|
||||
"description": "Gherkin DSL parser for PHP",
|
||||
"homepage": "http://behat.org/",
|
||||
"keywords": [
|
||||
"BDD",
|
||||
|
@ -2187,22 +2188,22 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Behat/Gherkin/issues",
|
||||
"source": "https://github.com/Behat/Gherkin/tree/master"
|
||||
"source": "https://github.com/Behat/Gherkin/tree/v4.8.0"
|
||||
},
|
||||
"time": "2020-03-17T14:03:26+00:00"
|
||||
"time": "2021-02-04T12:44:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/codeception",
|
||||
"version": "4.1.15",
|
||||
"version": "4.1.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/Codeception.git",
|
||||
"reference": "9b174d18ba58bb2e8cc4cecce619d6124df1d83a"
|
||||
"reference": "c153b1ab289b3e3109e685379aa8847c54ac2b68"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/9b174d18ba58bb2e8cc4cecce619d6124df1d83a",
|
||||
"reference": "9b174d18ba58bb2e8cc4cecce619d6124df1d83a",
|
||||
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/c153b1ab289b3e3109e685379aa8847c54ac2b68",
|
||||
"reference": "c153b1ab289b3e3109e685379aa8847c54ac2b68",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2276,7 +2277,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Codeception/Codeception/issues",
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.15"
|
||||
"source": "https://github.com/Codeception/Codeception/tree/4.1.17"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -2284,7 +2285,7 @@
|
|||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-17T19:19:40+00:00"
|
||||
"time": "2021-02-01T07:30:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/lib-asserts",
|
||||
|
@ -2342,16 +2343,16 @@
|
|||
},
|
||||
{
|
||||
"name": "codeception/lib-innerbrowser",
|
||||
"version": "1.3.6",
|
||||
"version": "1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/lib-innerbrowser.git",
|
||||
"reference": "41b79ba6761001bdb1f373a347400180693ad4e7"
|
||||
"reference": "b7406c710684c255d9b067d7795269a5585a0406"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/41b79ba6761001bdb1f373a347400180693ad4e7",
|
||||
"reference": "41b79ba6761001bdb1f373a347400180693ad4e7",
|
||||
"url": "https://api.github.com/repos/Codeception/lib-innerbrowser/zipball/b7406c710684c255d9b067d7795269a5585a0406",
|
||||
"reference": "b7406c710684c255d9b067d7795269a5585a0406",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -2396,9 +2397,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Codeception/lib-innerbrowser/issues",
|
||||
"source": "https://github.com/Codeception/lib-innerbrowser/tree/1.3.6"
|
||||
"source": "https://github.com/Codeception/lib-innerbrowser/tree/1.4.0"
|
||||
},
|
||||
"time": "2021-01-17T11:21:09+00:00"
|
||||
"time": "2021-01-29T18:17:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/module-asserts",
|
||||
|
@ -3938,16 +3939,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "9.5.1",
|
||||
"version": "9.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360"
|
||||
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e7bdf4085de85a825f4424eae52c99a1cec2f360",
|
||||
"reference": "e7bdf4085de85a825f4424eae52c99a1cec2f360",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||
"reference": "f661659747f2f87f9e72095bb207bceb0f151cb4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4025,7 +4026,7 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.1"
|
||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -4037,7 +4038,7 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-17T07:42:25+00:00"
|
||||
"time": "2021-02-02T14:45:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
|
@ -5152,16 +5153,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/browser-kit",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/browser-kit.git",
|
||||
"reference": "87d6f0a7436b03a57d4cf9a6a9cd0c83a355c49a"
|
||||
"reference": "b03b2057ed53ee4eab2e8f372084d7722b7b8ffd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/87d6f0a7436b03a57d4cf9a6a9cd0c83a355c49a",
|
||||
"reference": "87d6f0a7436b03a57d4cf9a6a9cd0c83a355c49a",
|
||||
"url": "https://api.github.com/repos/symfony/browser-kit/zipball/b03b2057ed53ee4eab2e8f372084d7722b7b8ffd",
|
||||
"reference": "b03b2057ed53ee4eab2e8f372084d7722b7b8ffd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5200,10 +5201,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony BrowserKit Component",
|
||||
"description": "Simulates the behavior of a web browser, allowing you to make requests, click on links and submit forms programmatically",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/browser-kit/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/browser-kit/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5219,20 +5220,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-18T08:03:05+00:00"
|
||||
"time": "2021-01-27T12:56:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "47c02526c532fb381374dab26df05e7313978976"
|
||||
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/47c02526c532fb381374dab26df05e7313978976",
|
||||
"reference": "47c02526c532fb381374dab26df05e7313978976",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||
"reference": "89d4b176d12a2946a1ae4e34906a025b7b6b135a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5291,7 +5292,7 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Console Component",
|
||||
"description": "Eases the creation of beautiful and testable command line interfaces",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"cli",
|
||||
|
@ -5300,7 +5301,7 @@
|
|||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/console/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5316,20 +5317,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-18T08:03:05+00:00"
|
||||
"time": "2021-01-28T22:06:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/css-selector",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/css-selector.git",
|
||||
"reference": "f789e7ead4c79e04ca9a6d6162fc629c89bd8054"
|
||||
"reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/f789e7ead4c79e04ca9a6d6162fc629c89bd8054",
|
||||
"reference": "f789e7ead4c79e04ca9a6d6162fc629c89bd8054",
|
||||
"url": "https://api.github.com/repos/symfony/css-selector/zipball/f65f217b3314504a1ec99c2d6ef69016bb13490f",
|
||||
"reference": "f65f217b3314504a1ec99c2d6ef69016bb13490f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5362,10 +5363,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony CssSelector Component",
|
||||
"description": "Converts CSS selectors to XPath expressions",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/css-selector/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/css-selector/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5381,7 +5382,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-08T17:02:38+00:00"
|
||||
"time": "2021-01-27T10:01:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
|
@ -5452,16 +5453,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/dom-crawler",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/dom-crawler.git",
|
||||
"reference": "ee7cf316fb0de786cfe5ae32ee79502b290c81ea"
|
||||
"reference": "5d89ceb53ec65e1973a555072fac8ed5ecad3384"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/ee7cf316fb0de786cfe5ae32ee79502b290c81ea",
|
||||
"reference": "ee7cf316fb0de786cfe5ae32ee79502b290c81ea",
|
||||
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/5d89ceb53ec65e1973a555072fac8ed5ecad3384",
|
||||
"reference": "5d89ceb53ec65e1973a555072fac8ed5ecad3384",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5503,10 +5504,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony DomCrawler Component",
|
||||
"description": "Eases DOM navigation for HTML and XML documents",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/dom-crawler/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/dom-crawler/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5522,20 +5523,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-18T08:02:46+00:00"
|
||||
"time": "2021-01-27T10:01:46+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||
"reference": "1c93f7a1dff592c252574c79a8635a8a80856042"
|
||||
"reference": "4f9760f8074978ad82e2ce854dff79a71fe45367"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/1c93f7a1dff592c252574c79a8635a8a80856042",
|
||||
"reference": "1c93f7a1dff592c252574c79a8635a8a80856042",
|
||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/4f9760f8074978ad82e2ce854dff79a71fe45367",
|
||||
"reference": "4f9760f8074978ad82e2ce854dff79a71fe45367",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5588,10 +5589,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/event-dispatcher/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5607,7 +5608,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-18T08:03:05+00:00"
|
||||
"time": "2021-01-27T10:36:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/event-dispatcher-contracts",
|
||||
|
@ -5690,16 +5691,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/finder.git",
|
||||
"reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba"
|
||||
"reference": "4adc8d172d602008c204c2e16956f99257248e03"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
|
||||
"reference": "0b9231a5922fd7287ba5b411893c0ecd2733e5ba",
|
||||
"url": "https://api.github.com/repos/symfony/finder/zipball/4adc8d172d602008c204c2e16956f99257248e03",
|
||||
"reference": "4adc8d172d602008c204c2e16956f99257248e03",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -5728,10 +5729,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"description": "Finds files and directories via an intuitive fluent interface",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/finder/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/finder/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -5747,7 +5748,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-08T17:02:38+00:00"
|
||||
"time": "2021-01-28T22:06:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-ctype",
|
||||
|
@ -6073,16 +6074,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/process",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/process.git",
|
||||
"reference": "bd8815b8b6705298beaa384f04fabd459c10bedd"
|
||||
"reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/bd8815b8b6705298beaa384f04fabd459c10bedd",
|
||||
"reference": "bd8815b8b6705298beaa384f04fabd459c10bedd",
|
||||
"url": "https://api.github.com/repos/symfony/process/zipball/313a38f09c77fbcdc1d223e57d368cea76a2fd2f",
|
||||
"reference": "313a38f09c77fbcdc1d223e57d368cea76a2fd2f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6112,10 +6113,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Process Component",
|
||||
"description": "Executes commands in sub-processes",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/process/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/process/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6131,7 +6132,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-08T17:03:37+00:00"
|
||||
"time": "2021-01-27T10:15:41+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
|
@ -6214,16 +6215,16 @@
|
|||
},
|
||||
{
|
||||
"name": "symfony/string",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/string.git",
|
||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed"
|
||||
"reference": "c95468897f408dd0aca2ff582074423dd0455122"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
||||
"reference": "5bd67751d2e3f7d6f770c9154b8fbcb2aa05f7ed",
|
||||
"url": "https://api.github.com/repos/symfony/string/zipball/c95468897f408dd0aca2ff582074423dd0455122",
|
||||
"reference": "c95468897f408dd0aca2ff582074423dd0455122",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6266,7 +6267,7 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony String component",
|
||||
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"grapheme",
|
||||
|
@ -6277,7 +6278,7 @@
|
|||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/string/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6293,20 +6294,20 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-05T07:33:16+00:00"
|
||||
"time": "2021-01-25T15:14:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.2.1",
|
||||
"version": "v5.2.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "290ea5e03b8cf9b42c783163123f54441fb06939"
|
||||
"reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/290ea5e03b8cf9b42c783163123f54441fb06939",
|
||||
"reference": "290ea5e03b8cf9b42c783163123f54441fb06939",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/338cddc6d74929f6adf19ca5682ac4b8e109cdb0",
|
||||
"reference": "338cddc6d74929f6adf19ca5682ac4b8e109cdb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -6349,10 +6350,10 @@
|
|||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony Yaml Component",
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.2.1"
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.2.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
|
@ -6368,7 +6369,7 @@
|
|||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-08T17:02:38+00:00"
|
||||
"time": "2021-02-03T04:42:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
|
@ -6425,12 +6426,12 @@
|
|||
"version": "1.9.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozart/assert.git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389",
|
||||
"shasum": ""
|
||||
},
|
||||
|
@ -6468,8 +6469,8 @@
|
|||
"validate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozart/assert/issues",
|
||||
"source": "https://github.com/webmozart/assert/tree/master"
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/1.9.1"
|
||||
},
|
||||
"time": "2020-07-08T17:02:28+00:00"
|
||||
},
|
||||
|
|
|
@ -26,6 +26,7 @@ class AppAsset extends AssetBundle
|
|||
'css/bootstrap/bootstrap.min.css',
|
||||
'css/main.css',
|
||||
'css/header.css',
|
||||
'css/notification.css',
|
||||
'css/info_panel.css',
|
||||
'css/categories_blocks_panel.css',
|
||||
'css/footer.css'
|
||||
|
@ -39,6 +40,7 @@ class AppAsset extends AssetBundle
|
|||
'js/menu.js',
|
||||
'js/account.js',
|
||||
'js/search.js',
|
||||
'js/notification.js',
|
||||
'js/reinitialization.js'
|
||||
];
|
||||
public $jsOptions = [
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<?php
|
||||
|
||||
$config = [
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'id' => 'skillparts-console',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
|
@ -9,7 +11,6 @@ $config = [
|
|||
'@vendor' => dirname(__DIR__) . '/../../../vendor',
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
'@npm' => '@vendor/npm-asset',
|
||||
'@explosivebit' => '@vendor/explosivebit',
|
||||
'@tests' => '@app/tests',
|
||||
],
|
||||
'components' => [
|
||||
|
@ -28,19 +29,9 @@ $config = [
|
|||
],
|
||||
'params' => require __DIR__ . '/params.php',
|
||||
'controllerMap' => [
|
||||
'arangodb-migrate' => 'explosivebit\arangodb\console\controllers\MigrateController',
|
||||
'arangodb-migrate' => 'mirzaev\yii2\arangodb\console\controllers\MigrateController',
|
||||
'fixture' => [
|
||||
'class' => 'yii\faker\FixtureController',
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
if (YII_ENV_DEV) {
|
||||
// configuration adjustments for 'dev' environment
|
||||
$config['bootstrap'][] = 'gii';
|
||||
$config['modules']['gii'] = [
|
||||
'class' => 'yii\gii\Module',
|
||||
];
|
||||
}
|
||||
|
||||
return $config;
|
||||
|
|
|
@ -49,7 +49,7 @@ class AuthenticationController extends Controller
|
|||
|
||||
// Запись ответа
|
||||
$return = [
|
||||
'menu' => (new AccountForm())->deauthenticationGenHtml(),
|
||||
'menu' => $this->renderPartial('/account/deauthentication'),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
|
@ -93,7 +93,7 @@ class AuthenticationController extends Controller
|
|||
Yii::$app->response->statusCode = 400;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('/account', compact('model')),
|
||||
'main' => $this->renderPartial('/account/index', compact('model')),
|
||||
'redirect' => '/authentication',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
@ -103,7 +103,7 @@ class AuthenticationController extends Controller
|
|||
if (!Yii::$app->user->isGuest) {
|
||||
Yii::$app->response->redirect('/');
|
||||
} else {
|
||||
return $this->render('/account');
|
||||
return $this->render('/account/index');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
use yii\filters\AccessControl;
|
||||
|
@ -34,20 +34,20 @@ class DeauthenticationController extends Controller
|
|||
|
||||
public function actionIndex()
|
||||
{
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
// Выход из аккаунта
|
||||
Yii::$app->user->logout();
|
||||
yii::$app->user->logout();
|
||||
|
||||
// Инициализация
|
||||
$model = new AccountForm(Yii::$app->request->post('AccountForm') ?? Yii::$app->request->get('AccountForm') ?? null);
|
||||
$model = new AccountForm(yii::$app->request->post('AccountForm') ?? yii::$app->request->get('AccountForm') ?? null);
|
||||
|
||||
// Ответа
|
||||
return [
|
||||
'menu' => $model->authenticationGenHtml($this->renderPartial('/account', compact('model'))),
|
||||
'menu' => $this->renderPartial('/account/authentication', compact('model')),
|
||||
'main' => $this->renderPartial('/index'),
|
||||
'redirect' => '/',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ namespace app\controllers;
|
|||
|
||||
use Yii;
|
||||
use yii\web\Controller;
|
||||
use yii\web\ErrorAction;
|
||||
use yii\web\Response;
|
||||
|
||||
class ErrorController extends Controller
|
||||
{
|
||||
|
|
|
@ -1,53 +1,56 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
||||
use app\models\AccountForm;
|
||||
|
||||
class IdentificationController extends Controller
|
||||
{
|
||||
public function actionIndex()
|
||||
{
|
||||
if (Yii::$app->request->isAjax) {
|
||||
// AJAX-POST-запрос
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
if (Yii::$app->user->isGuest) {
|
||||
if (yii::$app->user->isGuest) {
|
||||
// Аккаунт не аутентифицирован
|
||||
|
||||
// Инициализация
|
||||
$model = new AccountForm(Yii::$app->request->post('AccountForm') ?? Yii::$app->request->get('AccountForm') ?? null);
|
||||
$model = new AccountForm(yii::$app->request->post('AccountForm') ?? yii::$app->request->get('AccountForm') ?? null);
|
||||
|
||||
// Запись ответа
|
||||
$return = [
|
||||
'menu' => $model->authenticationGenHtml($this->renderPartial('/account', compact('model'))),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'menu' => $this->renderPartial('/account/authentication', compact('model')),
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
} else {
|
||||
// Аккаунт аутентифицирован
|
||||
|
||||
// Инициализация
|
||||
$model = Yii::$app->user;
|
||||
$model = yii::$app->user;
|
||||
|
||||
// Запись ответа
|
||||
$return = [
|
||||
'menu' => (new AccountForm())->deauthenticationGenHtml(),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'menu' => $this->renderPartial('/account/deauthentication'),
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
if (($cookies = Yii::$app->request->cookies)->has('redirect')) {
|
||||
if (($cookies = yii::$app->request->cookies)->has('redirect')) {
|
||||
// Найдено cookie с переадресацией
|
||||
|
||||
// Запись ответа
|
||||
$return['redirect'] = '/' . $cookies['redirect'];
|
||||
|
||||
// Очистка cookie
|
||||
unset(Yii::$app->response->cookies['redirect']);
|
||||
unset(yii::$app->response->cookies['redirect']);
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use app\models\AccountEdgeNotification;
|
||||
use yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
||||
use app\models\Notification;
|
||||
|
||||
class NotificationController extends Controller
|
||||
{
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
'only' => ['index'],
|
||||
'rules' => [
|
||||
[
|
||||
'allow' => true,
|
||||
'roles' => ['@']
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function actionIndex()
|
||||
{
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
// Инициализация
|
||||
$model = new Notification(yii::$app->request->post('Notification'));
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
$return = [
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
if (yii::$app->request->post('last')) {
|
||||
// Запрос последнего уведомлений (всплывающее окно)
|
||||
|
||||
$limit = 1;
|
||||
} else if (yii::$app->request->post('stream')) {
|
||||
// Запрос последних уведомлений (панель)
|
||||
|
||||
$limit = 5;
|
||||
}
|
||||
|
||||
if (isset($limit)) {
|
||||
// Обработка для всплывающего окна или панель
|
||||
|
||||
// Подзапрос для проверки статуса уведомления относительно пользователя
|
||||
// Поиск рёбер: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ
|
||||
$let = $model::find()
|
||||
->for(['account', $model::collectionName() . '_edge_account'])
|
||||
->traversal($model::collectionName(), 'OUTBOUND')
|
||||
->in('account_edge_' . $model::collectionName())
|
||||
->where(['account._id' => yii::$app->user->id])
|
||||
->select($model::collectionName() . '_edge_account');
|
||||
|
||||
if (yii::$app->request->post('last')) {
|
||||
// Запрос последнего уведомлений (всплывающее окно)
|
||||
|
||||
// Уведомление которое не выводилось на мониторе пользователя
|
||||
$type = 'received';
|
||||
} else if (yii::$app->request->post('stream')) {
|
||||
// Запрос последних уведомлений (панель)
|
||||
|
||||
// Уведомление которое не было прочитано в окне уведомний
|
||||
$type = 'checked';
|
||||
}
|
||||
|
||||
// Генерация подзапроса по перебору ядра
|
||||
$let = $let->createCommand();
|
||||
|
||||
/**
|
||||
* Поиск рёбер: (УВЕДОМЛЕНИЕ)? -> ПОЛЬЗОВАТЕЛЬ
|
||||
*
|
||||
* @param bool $check Активация проверки получения
|
||||
*/
|
||||
$search = function (bool $check = false) use ($model, $type, $let, $limit): array {
|
||||
return $model::searchByAccount(
|
||||
params: $check ? $let->getBindVars() : [],
|
||||
where: [
|
||||
[
|
||||
[
|
||||
'notification.html' => null
|
||||
],
|
||||
'operator' => '!='
|
||||
],
|
||||
[
|
||||
'account_edge_notification.type' => $type
|
||||
]
|
||||
],
|
||||
let: [
|
||||
$model::collectionName() . '_edge_account',
|
||||
'(' . (string) $let . ')'
|
||||
],
|
||||
post_where: $check ? [
|
||||
'account_edge_notification[0]._to' => null
|
||||
] : [],
|
||||
limit: $limit,
|
||||
sort: ['DESC'],
|
||||
direction: 'INBOUND'
|
||||
);
|
||||
};
|
||||
|
||||
// Поиск непрочитанных уведомлений пользователя
|
||||
$notifications = $search(true);
|
||||
|
||||
if (!yii::$app->request->post('last') && empty($notifications)) {
|
||||
// Уведомления не найдены и запрошены НЕ всплывающие уведомления
|
||||
|
||||
// Поиск уведомлений пользователя
|
||||
$notifications = $search();
|
||||
}
|
||||
|
||||
if (empty($notifications)) {
|
||||
// Уведомления не найдены
|
||||
|
||||
yii::$app->response->statusCode = 404;
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
foreach ($notifications as $notification) {
|
||||
// Перебор найденных уведомлений
|
||||
|
||||
// Запись ребра: ПОЛЬЗОВАТЕЛЬ -> УВЕДОМЛЕНИЕ (о том, что уведомление прочитано)
|
||||
AccountEdgeNotification::write(yii::$app->user->id, $notification->readId(), $type);
|
||||
}
|
||||
|
||||
if (yii::$app->request->post('last')) {
|
||||
// Запрос последнего уведомлений (всплывающее окно)
|
||||
|
||||
// Реинициализация
|
||||
$notification = $notifications[0];
|
||||
|
||||
$return['popup'] = [
|
||||
'html' => $this->renderPartial('popup', compact('model', 'notification')),
|
||||
'id' => 'popup/' . $notification->readId()
|
||||
];
|
||||
} else if (yii::$app->request->post('stream')) {
|
||||
// Запрос последних уведомлений (панель)
|
||||
|
||||
$return['panel'] = $this->renderPartial('panel', compact('model', 'notifications'));
|
||||
}
|
||||
} else {
|
||||
// Иначе обрабатывается как запрос страницы уведомлений
|
||||
|
||||
$return['main'] = $this->renderPartial('index', compact('model'));
|
||||
$return['redirect'] = '/notification';
|
||||
}
|
||||
|
||||
end:
|
||||
return $return;
|
||||
}
|
||||
|
||||
return $this->render('index', ['model' => new Notification(yii::$app->request->get('Notification'))]);
|
||||
}
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
use app\models\Product;
|
||||
use yii\web\HttpException;
|
||||
|
||||
use app\models\Product;
|
||||
|
||||
class ProductController extends Controller
|
||||
{
|
||||
/**
|
||||
|
@ -19,20 +22,24 @@ class ProductController extends Controller
|
|||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::class,
|
||||
'only' => ['add'],
|
||||
'rules' => [
|
||||
[
|
||||
'allow' => true,
|
||||
'actions' => ['index'],
|
||||
'roles' => ['@']
|
||||
],
|
||||
[
|
||||
'allow' => false,
|
||||
'roles' => ['?']
|
||||
]
|
||||
],
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public function actionIndex(int $id)
|
||||
public function actionIndex(string $catn)
|
||||
{
|
||||
if ($model = Product::readById($id)) {
|
||||
if ($model = Product::searchByCatn($catn)) {
|
||||
// Товар найден
|
||||
|
||||
// Инициализация
|
||||
|
@ -45,7 +52,7 @@ class ProductController extends Controller
|
|||
|
||||
return [
|
||||
'main' => $this->renderPartial('index', compact('model')),
|
||||
'redirect' => '/product/' . $id,
|
||||
'redirect' => '/product/' . $catn,
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
@ -12,12 +13,13 @@ use yii\web\UploadedFile;
|
|||
|
||||
use app\models\Supply;
|
||||
use app\models\SupplyGroup;
|
||||
use app\models\Search;
|
||||
use app\models\Notification;
|
||||
use app\models\Settings;
|
||||
use app\models\SettingsEdgeSettings;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
|
@ -26,13 +28,20 @@ class ProfileController extends Controller
|
|||
'rules' => [
|
||||
[
|
||||
'allow' => true,
|
||||
'roles' => ['@']
|
||||
'roles' => ['@'],
|
||||
'actions' => ['index', 'supplies', 'import', 'monitoring', 'readGroups'],
|
||||
],
|
||||
[
|
||||
'allow' => false,
|
||||
'roles' => ['?'],
|
||||
'verbs' => ['POST'],
|
||||
'denyCallback' => [$this, 'accessDenied']
|
||||
],
|
||||
[
|
||||
'allow' => true,
|
||||
'actions' => ['trusted', 'trusted-notification-write'],
|
||||
'matchCallback' => function ($rule, $action) {
|
||||
return yii::$app->user->identity->trst;
|
||||
}
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -41,21 +50,32 @@ class ProfileController extends Controller
|
|||
|
||||
public function accessDenied()
|
||||
{
|
||||
$cookies = Yii::$app->response->cookies;
|
||||
// Инициализация
|
||||
$cookies = yii::$app->response->cookies;
|
||||
|
||||
// Запись cookie с редиректом, который выполнится после авторизации
|
||||
$cookies->add(new Cookie([
|
||||
'name' => 'redirect',
|
||||
'value' => Yii::$app->request->pathInfo
|
||||
'value' => yii::$app->request->pathInfo
|
||||
]));
|
||||
|
||||
if (Yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
// Настройка
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
// Проверить переадресацию на уровне сервера
|
||||
// Генерация ответа
|
||||
Yii::$app->response->content = json_encode([
|
||||
'main' => $this->renderPartial('/account'),
|
||||
'main' => $this->renderPartial('/account/index'),
|
||||
'redirect' => '/authentication',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
]);
|
||||
} else if (Yii::$app->request->isGet) {
|
||||
// GET-запрос
|
||||
|
||||
$this->redirect('/authentication');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -64,75 +84,236 @@ class ProfileController extends Controller
|
|||
public function actionIndex(): string|array
|
||||
{
|
||||
// Инициализация
|
||||
$model = Yii::$app->user->identity;
|
||||
$model = yii::$app->user->identity;
|
||||
$attributes = Supply::searchByAccount(yii::$app->user->id);
|
||||
|
||||
if ($vars = yii::$app->request->post('Account') ?? yii::$app->request->get('Account')) {
|
||||
// Обнаружены входные параметры
|
||||
|
||||
if (isset($vars['opts'])) {
|
||||
// Переданы параметры
|
||||
|
||||
// Инициализация
|
||||
is_array($model->opts) || $model->opts = [];
|
||||
|
||||
// Запись
|
||||
$model->opts = array_merge($model->opts, $vars['opts']);
|
||||
|
||||
$model->update();
|
||||
} else {
|
||||
/**
|
||||
* @todo Написать обработчик ошибок
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// Генерация
|
||||
$sidebar = $this->renderPartial('sidebar');
|
||||
|
||||
if (Yii::$app->request->isAjax) {
|
||||
// AJAX-POST-запрос
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('index', compact('model', 'sidebar')),
|
||||
'main' => $this->renderPartial('index', compact('model', 'sidebar', 'attributes')),
|
||||
'redirect' => '/profile',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
return $this->render('index', compact('model', 'sidebar'));
|
||||
return $this->render('index', compact('model', 'sidebar', 'attributes'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Страницка поставок
|
||||
* Страница поставок
|
||||
*/
|
||||
public function actionSupplies(): string|array
|
||||
{
|
||||
// Инициализация
|
||||
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
|
||||
$model = new Supply(yii::$app->request->post('Supply') ?? yii::$app->request->get('Supply'));
|
||||
|
||||
// Генерация
|
||||
$sidebar = $this->renderPartial('sidebar', compact('model'));
|
||||
$sidebar = $this->renderPartial('sidebar');
|
||||
|
||||
if (Yii::$app->request->isAjax) {
|
||||
if (yii::$app->request->isPost) {
|
||||
// AJAX-POST-запрос
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('supplies', compact('model', 'sidebar')),
|
||||
'redirect' => '/profile/supplies',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
return $this->render('supplies', compact('model', 'sidebar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Страница панели управления для доверенных пользователей
|
||||
*/
|
||||
public function actionTrusted(): string|array
|
||||
{
|
||||
// Инициализация
|
||||
$model_notifications = null;
|
||||
$model_settings = Settings::readLast();
|
||||
|
||||
if (!is_null($vars = yii::$app->request->post('Notification') ?? yii::$app->request->get('Notification'))) {
|
||||
// Обнаружены входные параметры из раздела "Уведомления"
|
||||
|
||||
// Реинициализация с новыми параметрами
|
||||
$model_notifications = new Notification($vars);
|
||||
|
||||
// Запись уведомления и отправка (запись ребра до аккаунта)
|
||||
$model_notifications->write();
|
||||
} else if (!is_null($vars = yii::$app->request->post('Settings') ?? yii::$app->request->get('Settings'))) {
|
||||
// Обнаружены входные параметры из раздела "Настройки"
|
||||
|
||||
if ($to = new Settings($vars)) {
|
||||
// Настройки инициализированы
|
||||
|
||||
// Отправка
|
||||
if ($to->save()) {
|
||||
// Сохранено в базе данных
|
||||
|
||||
// Буфер
|
||||
$from = $model_settings;
|
||||
|
||||
// Реинициализация (для представления)
|
||||
$model_settings = $to;
|
||||
|
||||
if ($from) {
|
||||
// Найдена старая версия настроек
|
||||
|
||||
// Запись ребра: НАСТРОЙКИ (старые) -> НАСТРОЙКИ (новые)
|
||||
SettingsEdgeSettings::write($from->readId(), $to->readId(), 'update');
|
||||
}
|
||||
} else {
|
||||
// Не сохранено в базе данных
|
||||
|
||||
// Запись ошибок
|
||||
$model_settings->addErrors($to->getErrors());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Деинициализация
|
||||
unset($vars);
|
||||
|
||||
// Генерация
|
||||
$sidebar = $this->renderPartial('sidebar');
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// AJAX-POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('trusted', compact('model_notifications', 'model_settings', 'sidebar')),
|
||||
'redirect' => '/profile/trusted',
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
return $this->render('trusted', compact('model_notifications', 'model_settings', 'sidebar'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Страницка панели управления для доверенных пользователей
|
||||
*
|
||||
* @todo Перенести в уведомления
|
||||
*/
|
||||
// public function actionTrustedNotificationWrite(): string|array
|
||||
// {
|
||||
// // Инициализация
|
||||
// $model = new Notification(yii::$app->request->post('Notification') ?? yii::$app->request->get('Notification'));
|
||||
|
||||
// $model->write();
|
||||
|
||||
// if (yii::$app->request->isPost) {
|
||||
// // POST-запрос
|
||||
|
||||
// yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
// return [
|
||||
// 'main' => $this->renderPartial('trusted', compact('model', 'sidebar')),
|
||||
// 'redirect' => '/profile/trusted',
|
||||
// '_csrf' => yii::$app->request->getCsrfToken()
|
||||
// ];
|
||||
// }
|
||||
|
||||
// return $this->render('trusted', compact('model', 'sidebar'));
|
||||
// }
|
||||
|
||||
/**
|
||||
* Страницка панели управления для доверенных пользователей
|
||||
*/
|
||||
public function actionMonitoring(): string|array
|
||||
{
|
||||
|
||||
// Инициализация номера страницы
|
||||
$page_search_history = (yii::$app->request->post('search') ?? yii::$app->request->get('search')) - 1;
|
||||
if ($page_search_history <= 0) {
|
||||
$page_search_history = 0;
|
||||
}
|
||||
|
||||
// Инициализация количества строк на одной странице
|
||||
$rows_amount = 10;
|
||||
|
||||
// Генерация
|
||||
$sidebar = $this->renderPartial('sidebar');
|
||||
$search_history = Search::searchByAccount(yii::$app->user->id, $rows_amount, ((int) $page_search_history ?? 0) * $rows_amount);
|
||||
|
||||
if (yii::$app->request->isPost) {
|
||||
// AJAX-POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('monitoring', compact(
|
||||
'sidebar',
|
||||
'search_history',
|
||||
'page_search_history'
|
||||
)),
|
||||
'search' => $page_search_history + 1,
|
||||
'redirect' => '/profile/monitoring',
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
return $this->render('monitoring', compact(
|
||||
'sidebar',
|
||||
'search_history',
|
||||
'page_search_history'
|
||||
));
|
||||
}
|
||||
|
||||
public function actionImport()
|
||||
{
|
||||
// Инициализация
|
||||
$model = new Supply(Yii::$app->request->post('Supply') ?? Yii::$app->request->get('Supply'));
|
||||
$model = new Supply(yii::$app->request->post('Supply') ?? yii::$app->request->get('Supply'));
|
||||
$model->scenario = $model::SCENARIO_IMPORT;
|
||||
|
||||
// Генерация
|
||||
$sidebar = $this->renderPartial('sidebar', compact('model'));
|
||||
$sidebar = $this->renderPartial('sidebar');
|
||||
|
||||
if (Yii::$app->request->isAjax) {
|
||||
if (yii::$app->request->isPost) {
|
||||
// AJAX-POST-запрос
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
$model->file = UploadedFile::getInstances($model, 'file');
|
||||
|
||||
if (!$test = $model->import()) {
|
||||
Yii::$app->response->statusCode = 409;
|
||||
yii::$app->response->statusCode = 409;
|
||||
}
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('supplies', compact('model', 'sidebar')),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,18 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
||||
use app\models\AccountForm;
|
||||
|
||||
class RegistrationController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return [
|
||||
|
@ -31,16 +30,16 @@ class RegistrationController extends Controller
|
|||
|
||||
public function actionIndex()
|
||||
{
|
||||
if (Yii::$app->request->isAjax) {
|
||||
// AJAX-POST-запрос
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
// Инициализация
|
||||
$model = new AccountForm(Yii::$app->request->post('AccountForm'));
|
||||
$model = new AccountForm(yii::$app->request->post('AccountForm'));
|
||||
$model->scenario = $model::SCENARIO_REGISTRATION;
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
if (!Yii::$app->user->isGuest || $model->registration()) {
|
||||
if (!yii::$app->user->isGuest || $model->registration()) {
|
||||
// Данные прошли проверку и аккаунт был создан
|
||||
|
||||
// Аутентификация
|
||||
|
@ -49,11 +48,11 @@ class RegistrationController extends Controller
|
|||
|
||||
// Запись ответа
|
||||
$return = [
|
||||
'menu' => (new AccountForm())->deauthenticationGenHtml(),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'menu' => $this->renderPartial('/account/deauthentication'),
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
if (($cookies = Yii::$app->response->cookies)->has('redirect')) {
|
||||
if (($cookies = yii::$app->response->cookies)->has('redirect')) {
|
||||
// Найдено cookie с переадресацией
|
||||
|
||||
// Запись ответа
|
||||
|
@ -61,11 +60,11 @@ class RegistrationController extends Controller
|
|||
$return['main'] = $this->renderPartial($return['redirect'] . '/index');
|
||||
|
||||
// Очистка cookie
|
||||
unset(Yii::$app->response->cookies['redirect']);
|
||||
unset(yii::$app->response->cookies['redirect']);
|
||||
} else {
|
||||
// Не найдено cookie с переадресацией
|
||||
|
||||
if (Yii::$app->request->pathInfo === 'authentication' || Yii::$app->request->pathInfo === 'registration') {
|
||||
if (yii::$app->request->pathInfo === 'authentication' || yii::$app->request->pathInfo === 'registration') {
|
||||
// Если клиент на промежуточном URI
|
||||
|
||||
// Запись ответа
|
||||
|
@ -78,18 +77,18 @@ class RegistrationController extends Controller
|
|||
} else {
|
||||
// Данные не прошли проверку
|
||||
|
||||
Yii::$app->response->statusCode = 400;
|
||||
yii::$app->response->statusCode = 400;
|
||||
|
||||
return [
|
||||
'main' => $this->renderPartial('/account', compact('model')),
|
||||
'redirect' => '/registration',
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
Yii::$app->response->redirect('/');
|
||||
if (!yii::$app->user->isGuest) {
|
||||
yii::$app->response->redirect('/');
|
||||
} else {
|
||||
return $this->render('/account', compact('model'));
|
||||
}
|
||||
|
|
|
@ -1,45 +1,90 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
|
||||
use app\models\Product;
|
||||
use yii\web\Cookie;
|
||||
use app\models\Search;
|
||||
|
||||
class SearchController extends Controller
|
||||
{
|
||||
/**
|
||||
* @todo Сессию привязать к аккаунту и проверку по нему делать, иначе её можно просто сбрасывать
|
||||
*/
|
||||
public function actionIndex(): array|string
|
||||
{
|
||||
// Инициализация
|
||||
$query = Yii::$app->request->post('request') ?? Yii::$app->request->get('q');
|
||||
$query = yii::$app->request->post('request') ?? yii::$app->request->get('q');
|
||||
|
||||
if (Yii::$app->request->post('type') === 'product' || Yii::$app->request->get('type') === 'product') {
|
||||
if (yii::$app->request->post('type') === 'product' || yii::$app->request->get('type') === 'product') {
|
||||
// Поиск по продуктам
|
||||
|
||||
if (yii::$app->request->post('history')) {
|
||||
// Запрошена история
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return [
|
||||
'search_line_window' => $this->renderPartial('/search/panel', ['history' => true]),
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
}
|
||||
|
||||
// Инициализация сессии
|
||||
$session = Yii::$app->session;
|
||||
$session = yii::$app->session;
|
||||
$session->open();
|
||||
|
||||
// Инициализация ответа
|
||||
$response = null;
|
||||
|
||||
// Инициализация параметров
|
||||
$timer = 0;
|
||||
|
||||
// Период пропуска запросов (в секундах)
|
||||
$period = 1;
|
||||
$period = 3;
|
||||
$keep_connect = true;
|
||||
$sanction = false;
|
||||
$sanction_condition = ($session['last_request'] + $period - time()) < $period;
|
||||
$sanction_time = 2;
|
||||
$query_min = 2;
|
||||
$query_max = 20;
|
||||
|
||||
if (isset($session['last_request'])) {
|
||||
// Данные о времени последнего запроса не найдены
|
||||
|
||||
if ($sanction && $sanction_condition) {
|
||||
// Наказание за повторный запрос при условии задержки
|
||||
|
||||
$session['last_request'] += $sanction_time;
|
||||
}
|
||||
} else {
|
||||
// Это первый запрос
|
||||
|
||||
// Инициализация
|
||||
$session['last_request'] = time();
|
||||
|
||||
goto first_request;
|
||||
}
|
||||
|
||||
keep_connect_wait:
|
||||
|
||||
// Запись времени последнего запроса и вычисление об истечении таймера
|
||||
$timer = ($session['last_request'] ?? $session['last_request'] = time() + $period) - time();
|
||||
$timer = $session['last_request'] + $period - time();
|
||||
|
||||
if ($timer > 0) {
|
||||
// Ожидание перед повторным запросом при условии что старых запросов нет
|
||||
|
||||
Yii::$app->response->statusCode = 202;
|
||||
yii::$app->response->statusCode = 202;
|
||||
|
||||
$return = [
|
||||
'timer' => $timer,
|
||||
'search_line_window' => $this->renderPartial('/loading'),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
} else {
|
||||
// Повторный запрос по истечению ожидания
|
||||
|
@ -47,22 +92,33 @@ class SearchController extends Controller
|
|||
// Очистка времени последнего запроса
|
||||
unset($session['last_request']);
|
||||
|
||||
//
|
||||
// Здесь запись истории запросов (в базе данных)
|
||||
//
|
||||
first_request:
|
||||
|
||||
$limit = Yii::$app->request->isAjax ? 10 : 30;
|
||||
if (strlen($query) < $query_min) {
|
||||
// Выход за ограничения длины с недостатком
|
||||
|
||||
if ($response = Product::searchByCatn($query, $limit)) {
|
||||
goto skip_query;
|
||||
} else if (strlen($query) > $query_max) {
|
||||
// Выход за ограничения длины с превышением
|
||||
|
||||
goto skip_query;
|
||||
}
|
||||
|
||||
// Запись в историю
|
||||
Search::write($query);
|
||||
|
||||
$limit = yii::$app->request->isPost ? 10 : 20;
|
||||
|
||||
if ($response = Product::searchByCatn($query, $limit, [])) {
|
||||
// Данные найдены по поиску в полях Каталожного номера
|
||||
|
||||
// Запись ответа
|
||||
$return = [
|
||||
'search_line_window' => $this->renderPartial('/search/panel', compact('response')),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
|
||||
if ((int) Yii::$app->request->post('advanced')) {
|
||||
if ((int) yii::$app->request->post('advanced')) {
|
||||
// Полноценный поиск
|
||||
|
||||
// Запись ответа
|
||||
|
@ -71,30 +127,40 @@ class SearchController extends Controller
|
|||
$return['redirect'] = '/search?type=product&q=' . $query;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Данные не найдены
|
||||
|
||||
Yii::$app->response->statusCode = 404;
|
||||
yii::$app->response->statusCode = 404;
|
||||
}
|
||||
}
|
||||
|
||||
if (Yii::$app->request->isAjax) {
|
||||
// AJAX-POST-запрос
|
||||
skip_query:
|
||||
|
||||
Yii::$app->response->format = Response::FORMAT_JSON;
|
||||
if (yii::$app->request->isPost) {
|
||||
// POST-запрос
|
||||
|
||||
yii::$app->response->format = Response::FORMAT_JSON;
|
||||
|
||||
return $return ?? [
|
||||
'search_line_window' => $this->renderPartial('/search/panel'),
|
||||
'_csrf' => Yii::$app->request->getCsrfToken()
|
||||
'_csrf' => yii::$app->request->getCsrfToken()
|
||||
];
|
||||
} else {
|
||||
// GET-запрос
|
||||
|
||||
if (empty($return['main']) && $keep_connect && $timer > 0) {
|
||||
// Режим непрерывного соединения
|
||||
|
||||
// Ожидание
|
||||
sleep($timer);
|
||||
|
||||
goto keep_connect_wait;
|
||||
}
|
||||
|
||||
return $this->render('/search/index', compact('response', 'timer'));
|
||||
}
|
||||
}
|
||||
|
||||
if (Yii::$app->user->isGuest) {
|
||||
if (yii::$app->user->isGuest) {
|
||||
return $this->render('/search/index', ['error_auth' => true]);
|
||||
} else {
|
||||
return $this->render('/search/index');
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m201219_074926_create_account_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210101_092505_create_product_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210107_163448_create_supply_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210108_014505_create_account_edge_supply_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210108_212826_create_product_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210108_221446_create_product_edge_product_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210108_222132_create_supply_edge_product_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210108_222740_create_product_edge_product_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210109_214817_create_supply_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210109_214833_create_supply_edge_supply_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210111_044635_create_supply_edge_supply_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210112_010347_create_product_group_edge_product_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210112_010411_create_supply_group_edge_supply_group_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210112_034135_create_requisite_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210112_034232_create_supply_edge_requisite_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210113_021800_create_purchase_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210113_021905_create_account_edge_purchase_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
use explosivebit\arangodb\Migration;
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210113_021917_create_purchase_edge_supply_collection extends Migration
|
||||
{
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210206_154140_create_search_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('search', []);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('search');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210206_154210_create_account_edge_search_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('account_edge_search', ['Type' => 3]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('account_edge_search');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210209_185314_create_notification_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('notification', []);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('notification');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210209_185328_create_account_edge_notification_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('account_edge_notification', ['type' => 3]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('account_edge_notification');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210223_121142_create_settings_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('settings', []);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('settings');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
use mirzaev\yii2\arangodb\Migration;
|
||||
|
||||
class m210223_145042_create_settings_edge_settings_collection extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->createCollection('settings_edge_settings', ['type' => 3]);
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->dropCollection('settings_edge_settings');
|
||||
}
|
||||
}
|
|
@ -16,8 +16,6 @@ use carono\exchange1c\interfaces\PartnerInterface;
|
|||
*/
|
||||
class Account extends Document implements IdentityInterface, PartnerInterface
|
||||
{
|
||||
public $opts;
|
||||
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
|
@ -43,7 +41,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
'comp',
|
||||
'taxn',
|
||||
'onec',
|
||||
'opts'
|
||||
'opts',
|
||||
'trst'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -65,7 +64,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
|
|||
'comp' => 'Компания',
|
||||
'taxn' => 'ИНН',
|
||||
'onec' => 'Данные 1C',
|
||||
'opts' => 'Параметры'
|
||||
'opts' => 'Параметры',
|
||||
'trst' => 'Доверенный пользователь'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class AccountEdgeNotification extends Edge
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'account_edge_notification';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class AccountEdgeSearch extends Edge
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'account_edge_search';
|
||||
}
|
||||
}
|
|
@ -135,38 +135,4 @@ class AccountForm extends Model
|
|||
|
||||
return $this->account;
|
||||
}
|
||||
|
||||
public function authenticationGenHtml(string $dropdown): string
|
||||
{
|
||||
return <<<HTML
|
||||
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
|
||||
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
|
||||
<div class="btn-group">
|
||||
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
|
||||
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
|
||||
<div class="dropdown-menu dropdown-menu-long dropdown-menu-right p-3" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
|
||||
<h5 class="mb-3 text-center">Аутентификация</h5>
|
||||
$dropdown
|
||||
<!-- <a class="dropdown-item-text text-center px-0 py-2" href="#"><small>Восстановление пароля</small></a> -->
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
public function deauthenticationGenHtml(): string
|
||||
{
|
||||
$mail = Yii::$app->user->identity->mail;
|
||||
|
||||
return <<<HTML
|
||||
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
|
||||
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
|
||||
<div class="btn-group">
|
||||
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
|
||||
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
|
||||
<div class="dropdown-menu dropdown-menu-right py-1" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
|
||||
<a class="dropdown-item button_white text-dark" onclick="deauthentication()">Выход ($mail)</a>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
|
||||
use mirzaev\yii2\arangodb\ActiveRecord;
|
||||
|
||||
|
@ -31,7 +31,7 @@ abstract class Document extends ActiveRecord
|
|||
return [
|
||||
'_key',
|
||||
'date',
|
||||
'writer'
|
||||
'wrtr'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,9 @@ abstract class Document extends ActiveRecord
|
|||
public function attributeLabels(): array
|
||||
{
|
||||
return [
|
||||
'_key' => 'Ключ',
|
||||
'date' => 'Дата',
|
||||
'writer' => 'Аккаунт записавшего'
|
||||
'wrtr' => 'Аккаунт записавшего'
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -56,33 +57,22 @@ abstract class Document extends ActiveRecord
|
|||
{
|
||||
return [
|
||||
[
|
||||
'writer',
|
||||
'wrtr',
|
||||
'string'
|
||||
],
|
||||
[
|
||||
'wrtr',
|
||||
'default',
|
||||
'value' => yii::$app->user->id
|
||||
],
|
||||
[
|
||||
'date',
|
||||
'default',
|
||||
'value' => time()
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Перед сохранением
|
||||
*
|
||||
* @todo Подождать обновление от ебаного Yii2 и добавить
|
||||
* проверку типов передаваемых параметров
|
||||
*/
|
||||
public function beforeSave($data): bool
|
||||
{
|
||||
if (parent::beforeSave($data)) {
|
||||
if ($this->isNewRecord) {
|
||||
}
|
||||
|
||||
$this->date = time();
|
||||
$this->writer = $this->writer ?? Yii::$app->user->id;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Чтение идентификатора
|
||||
*/
|
||||
|
@ -99,6 +89,19 @@ abstract class Document extends ActiveRecord
|
|||
return static::findOne(['_id' => $_id]);
|
||||
}
|
||||
|
||||
public static function readLast(): ?static
|
||||
{
|
||||
return static::find()->orderBy(['DESC'])->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* Чтение всех записей
|
||||
*/
|
||||
public static function readAll(): array
|
||||
{
|
||||
return static::find()->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Чтение количества записей
|
||||
*/
|
||||
|
@ -106,4 +109,16 @@ abstract class Document extends ActiveRecord
|
|||
{
|
||||
return static::find()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверка на то, что в свойство передан массив
|
||||
*/
|
||||
protected function arrayValidator(string $attribute, array $params): bool
|
||||
{
|
||||
if (is_array($this->$attribute)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,38 +60,6 @@ abstract class Edge extends Document
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать
|
||||
*/
|
||||
public static function write(string $_from, string $_to, string $type = '', array $data = []): ?static
|
||||
{
|
||||
// Инициализация
|
||||
$edge = new static;
|
||||
|
||||
// Настройка
|
||||
$edge->_from = $_from;
|
||||
$edge->_to = $_to;
|
||||
$edge->type = $type;
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if(is_int($key)) {
|
||||
// Если ключ задан автоматически
|
||||
|
||||
$edge->{$value} = true;
|
||||
} else {
|
||||
// Иначе ключ записан вручную
|
||||
|
||||
$edge->{$key} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Запись
|
||||
$edge->save();
|
||||
|
||||
return $edge;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Перед сохранением
|
||||
*
|
||||
|
@ -111,4 +79,63 @@ abstract class Edge extends Document
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать (с проверкой на существование)
|
||||
*
|
||||
* Создаст ребро только в том случае, если его аналога не существует
|
||||
*/
|
||||
public static function writeSafe(string $_from, string $_to, string $type = '', array $data = []): ?static
|
||||
{
|
||||
if ($edge = self::searchByVertex($_from, $_to, 1)) {
|
||||
// Найдено в базе данных
|
||||
|
||||
return $edge;
|
||||
}
|
||||
|
||||
return self::write($_from, $_to, $type, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Записать
|
||||
*/
|
||||
public static function write(string $_from, string $_to, string $type = '', array $data = []): ?static
|
||||
{
|
||||
// Инициализация
|
||||
$edge = new static;
|
||||
|
||||
// Настройка
|
||||
$edge->_from = $_from;
|
||||
$edge->_to = $_to;
|
||||
$edge->type = $type;
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_int($key)) {
|
||||
// Обычная запись
|
||||
|
||||
$edge->{$value} = true;
|
||||
} else {
|
||||
// Ассоциативная запись
|
||||
|
||||
$edge->{$key} = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Запись
|
||||
return $edge->save() ? $edge : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск ребра по его вершинам
|
||||
*/
|
||||
public static function searchByVertex(string $_from, string $_to, int $limit = 1): static|array|null
|
||||
{
|
||||
$query = self::find()->where(['_from' => $_from, '_to' => $_to]);
|
||||
|
||||
if ($limit <= 1) {
|
||||
return $query->one();
|
||||
} else {
|
||||
return $query->limit($limit)->all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use yii;
|
||||
use yii\web\IdentityInterface;
|
||||
|
||||
use app\models\traits\SearchByAccount;
|
||||
|
||||
/**
|
||||
* Поиск
|
||||
*
|
||||
* @see Product Поиск по товарам
|
||||
*/
|
||||
class Notification extends Document
|
||||
{
|
||||
use SearchByAccount;
|
||||
|
||||
/**
|
||||
* Сценарий для доверенного пользователя с созданием уведомления
|
||||
*/
|
||||
const SCENARIO_TRUSTED_CREATE = 'create';
|
||||
|
||||
/**
|
||||
* Цель для отправки уведомления
|
||||
*
|
||||
* Расшифровывается как $target
|
||||
*
|
||||
* @see SCENARIO_TRUSTED_CREATE
|
||||
*/
|
||||
public IdentityInterface|string|array|null $trgt;
|
||||
|
||||
/**
|
||||
* Текст уведомления
|
||||
*/
|
||||
public string $text;
|
||||
|
||||
/**
|
||||
* Типы уведомлений
|
||||
*/
|
||||
public array $typs = [
|
||||
'notice' => 'Уведомление',
|
||||
'warning' => 'Предупреждение'
|
||||
];
|
||||
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'notification';
|
||||
}
|
||||
|
||||
/**
|
||||
* Свойства
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'html',
|
||||
'type'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метки свойств
|
||||
*/
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'html' => 'HTML',
|
||||
'type' => 'Тип',
|
||||
'trgt' => 'Получатели',
|
||||
'text' => 'Текст',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
'html',
|
||||
'required'
|
||||
],
|
||||
[
|
||||
'type',
|
||||
'default',
|
||||
'value' => 'notice'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись
|
||||
*
|
||||
* @param string $html HTML уведомления
|
||||
* @param IdentityInterface $trgt Получатель уведомления
|
||||
* @param string $type Тип уведомления
|
||||
*
|
||||
* @todo Создать параметр разделителя для администрации
|
||||
*/
|
||||
public function write(string $html = null, IdentityInterface|array|string $trgt = null, string $type = 'notice'): self|array|null
|
||||
{
|
||||
// Инициализация
|
||||
isset($this->html) ? $html = $this->html : null;
|
||||
isset($this->trgt) ? $trgt = $this->trgt : null;
|
||||
isset($this->type) ? $type = $this->type : null;
|
||||
|
||||
// Инициализация уведомления
|
||||
if (isset($html) && (bool) (int) $html) {
|
||||
// Получен текст в формете HTML-кода
|
||||
|
||||
$this->html = $this->text ?? null;
|
||||
} else {
|
||||
// Получен необработанный текст
|
||||
|
||||
$text = htmlspecialchars(strip_tags($this->text ?? null));
|
||||
|
||||
$this->html = <<<HTML
|
||||
<p class="my-2 mx-3">$text</p>
|
||||
HTML;
|
||||
}
|
||||
|
||||
if ($this->save()) {
|
||||
// Уведомление записано
|
||||
|
||||
// Инициализация получателей и создание ребра
|
||||
if (empty($trgt)) {
|
||||
// Получатель не передан
|
||||
|
||||
goto test;
|
||||
} else if (is_string($trgt)) {
|
||||
// Передана необработанная строка
|
||||
|
||||
// Инициализация
|
||||
$delimiter = ',';
|
||||
|
||||
// Конвертация
|
||||
$trgt = array_map('trim', explode($delimiter, $trgt));
|
||||
|
||||
|
||||
if (in_array('@all', $trgt, true)) {
|
||||
// Найден флаг обозначающий отправку всем пользователям
|
||||
|
||||
// Инициализация
|
||||
$return = [];
|
||||
|
||||
foreach (Account::readAll() as $target) {
|
||||
// Перебор всех аккаунтов
|
||||
|
||||
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
|
||||
$return[] = AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
|
||||
}
|
||||
|
||||
return $return ? $return : null;
|
||||
}
|
||||
|
||||
if (in_array('@test', $trgt, true)) {
|
||||
// Найден флаг обозначающий тестирование (отправка самому себе)
|
||||
|
||||
test:
|
||||
return AccountEdgeNotification::writeSafe($this->readId(), yii::$app->user->id, $type) ? $this : null;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($trgt)) {
|
||||
// Несколько получателей
|
||||
|
||||
// Инициализация
|
||||
$return = [];
|
||||
|
||||
foreach ($trgt as $target) {
|
||||
// Перебор получателей
|
||||
|
||||
if ($target instanceof Account) {
|
||||
// Один получатель
|
||||
|
||||
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
|
||||
return AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
|
||||
}
|
||||
|
||||
// "or" имеет приоритет ниже чем у "||" относительно "="
|
||||
//
|
||||
// if ($target = $buffer = Account::searchById($target) or
|
||||
// $target = Account::searchById(Account::collectionName() . '/' . $buffer)
|
||||
// ) {
|
||||
//
|
||||
// if (($target = Account::searchById($target)) ||
|
||||
// ($target = Account::searchById(Account::collectionName() . '/' . $target))
|
||||
// ) {
|
||||
if ($target = Account::searchById(Account::collectionName() . '/' . $target)) {
|
||||
// Аккаунт найден
|
||||
|
||||
echo ($target->readId()) . "\n";
|
||||
|
||||
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
|
||||
$return[] = AccountEdgeNotification::writeSafe($this->readId(), $target->readId(), $type) ? $this : null;
|
||||
}
|
||||
}
|
||||
|
||||
return $return ? $return : null;
|
||||
} else if ($trgt instanceof Account) {
|
||||
// Один получатель
|
||||
|
||||
// Запись ребра: УВЕДОМЛЕНИЕ -> АККАУНТ
|
||||
return AccountEdgeNotification::writeSafe($this->readId(), $trgt->readId(), $type) ? $this : null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ class Product extends Document
|
|||
'name',
|
||||
'ocid',
|
||||
'catn',
|
||||
'imgs',
|
||||
'oemn'
|
||||
// 'data',
|
||||
// 'cost',
|
||||
|
@ -73,6 +74,7 @@ class Product extends Document
|
|||
'name' => 'Название (name)',
|
||||
'ocid' => 'Идентификатор 1C (ocid)',
|
||||
'catn' => 'Каталожный номер (catn)',
|
||||
'imgs' => 'Изображения (imgs)',
|
||||
'oemn' => 'OEM номера (oemn)',
|
||||
// 'data' => 'Данные товара (data)',
|
||||
// 'cost' => 'Цены (cost)',
|
||||
|
@ -92,7 +94,10 @@ class Product extends Document
|
|||
parent::rules(),
|
||||
[
|
||||
[
|
||||
['name', 'catn'],
|
||||
[
|
||||
'name',
|
||||
'catn'
|
||||
],
|
||||
'required',
|
||||
'message' => 'Заполните поля: {attribute}',
|
||||
'on' => self::SCENARIO_WRITE,
|
||||
|
@ -104,8 +109,19 @@ class Product extends Document
|
|||
'message' => 'Заполните поля: {attribute}',
|
||||
'on' => self::SCENARIO_IMPORT
|
||||
],
|
||||
['catn', 'string', 'message' => '{attribute} должен быть строкой'],
|
||||
// ['oemn', 'integer'], Нужна своя проверка на массив
|
||||
[
|
||||
'catn',
|
||||
'string',
|
||||
'message' => '{attribute} должен быть строкой'
|
||||
],
|
||||
[
|
||||
[
|
||||
'oemn',
|
||||
'imgs'
|
||||
],
|
||||
'arrayValidator',
|
||||
'message' => '{attribute} должен быть массивом.'
|
||||
],
|
||||
[
|
||||
'file',
|
||||
'file',
|
||||
|
@ -122,6 +138,86 @@ class Product extends Document
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись
|
||||
*
|
||||
* @param string $catn Артикул, каталожный номер
|
||||
*/
|
||||
public static function initEmpty(string $catn): self|array
|
||||
{
|
||||
$oemn = self::convertOemn2Catn($catn);
|
||||
|
||||
if (count($oemn) === 1) {
|
||||
// Передан только один артикул
|
||||
|
||||
if ($model = self::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
// Запись
|
||||
return self::writeEmpty($catn);
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$models = [];
|
||||
|
||||
foreach ($oemn as $catn) {
|
||||
// Перебор всех найденных артикулов
|
||||
|
||||
if ($model = self::searchByCatn($catn)) {
|
||||
// Продукт уже существует
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись
|
||||
if ($model = self::writeEmpty($catn)) {
|
||||
// Записано
|
||||
|
||||
// Запись в массив сохранённых моделей
|
||||
$models[] = $model;
|
||||
}
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись
|
||||
*/
|
||||
public static function writeEmpty(string $catn): ?self
|
||||
{
|
||||
// Инициализация
|
||||
$model = new self;
|
||||
|
||||
// Настройки
|
||||
$model->catn = $catn;
|
||||
|
||||
// Запись
|
||||
return $model->save() ? $model : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Поиск OEM номеров
|
||||
*
|
||||
* @param string $oemn OEM номера
|
||||
* @param string $delimiters Разделители
|
||||
*
|
||||
* @todo НЕ ЗАБЫТЬ СДЕЛАТЬ НАСТРОЙКУ РАЗДЕЛИТЕЛЕЙ
|
||||
*/
|
||||
public static function convertOemn2Catn(string $oemn, string $delimiters = '\s\+\/,'): array
|
||||
{
|
||||
// Инициализация
|
||||
$catn = [];
|
||||
|
||||
// Конвертация
|
||||
preg_match_all("/[^$delimiters]+/", $oemn, $catn);
|
||||
|
||||
return $catn[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Импорт товаров
|
||||
*
|
||||
|
@ -182,13 +278,33 @@ class Product extends Document
|
|||
|
||||
/**
|
||||
* Поиск по каталожному номеру
|
||||
*
|
||||
* Ищет продукт и возвращает его,
|
||||
* либо выполняет поиск через представление
|
||||
*
|
||||
* @todo Переделать нормально
|
||||
*/
|
||||
public static function searchByCatn(string $query, int $limit = 1): Product|array|null
|
||||
public static function searchByCatn(string $catn, int $limit = 1, array $select = ['catn' => 'catn']): static|array|null
|
||||
{
|
||||
if ($limit <= 1) {
|
||||
return static::findOne(['catn' => $query]);
|
||||
return static::findOne(['catn' => $catn]);
|
||||
}
|
||||
|
||||
return self::find()->limit($limit)->view('product_search', ['id' => '_key', 'catn' => 'catn'], ['catn' => $query], 'START');
|
||||
$query = self::find()
|
||||
->collection('product_search')
|
||||
->search(['catn' => $catn])
|
||||
->limit($limit)
|
||||
->select($select)
|
||||
->createCommand()
|
||||
->execute()
|
||||
->getAll();
|
||||
|
||||
foreach ($query as &$attribute) {
|
||||
// Приведение всех свойств в массив и очистка от лишних данных
|
||||
|
||||
$attribute = $attribute->getAll();
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,11 +154,6 @@ class ProductGroup extends Document implements GroupInterface
|
|||
return $edge->save();
|
||||
}
|
||||
|
||||
public static function readAll()
|
||||
{
|
||||
return static::find()->all();
|
||||
}
|
||||
|
||||
public static function readByName(string $name)
|
||||
{
|
||||
return static::findOne(['name' => $name]);
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use yii;
|
||||
use yii\web\IdentityInterface;
|
||||
|
||||
use app\models\traits\SearchByAccount;
|
||||
|
||||
/**
|
||||
* Поиск
|
||||
*
|
||||
* @see Product Поиск по товарам
|
||||
*/
|
||||
class Search extends Document
|
||||
{
|
||||
use SearchByAccount;
|
||||
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'search';
|
||||
}
|
||||
|
||||
/**
|
||||
* Свойства
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'text',
|
||||
'ipv4',
|
||||
'head'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метки свойств
|
||||
*/
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'text' => 'Текст',
|
||||
'ipv4' => 'IPv4',
|
||||
'head' => 'Заголовки'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
'text',
|
||||
'required'
|
||||
],
|
||||
[
|
||||
'ipv4',
|
||||
'default',
|
||||
'value' => yii::$app->request->userIP
|
||||
],
|
||||
[
|
||||
'head',
|
||||
'default',
|
||||
'value' => yii::$app->request->getHeaders()
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись
|
||||
*
|
||||
* @param string $text Текст запроса
|
||||
* @param IdentityInterface|null $user Пользователь совершивший запрос
|
||||
*/
|
||||
public static function write(string $text, IdentityInterface $user = null): ?self
|
||||
{
|
||||
// Инициализация
|
||||
$vertex = new self;
|
||||
isset($user) && yii::$app->user->isGuest ?: $user = yii::$app->user->identity;
|
||||
|
||||
// Настройки
|
||||
$vertex->text = $text;
|
||||
|
||||
if ($vertex->save()) {
|
||||
// Поиск записан
|
||||
|
||||
// Запись ребра: АККАУНТ -> ПОИСК
|
||||
return $user && AccountEdgeSearch::writeSafe($user->id, $vertex->readId(), 'request') ? $vertex : null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
/**
|
||||
* Настройки
|
||||
*/
|
||||
class Settings extends Document
|
||||
{
|
||||
/**
|
||||
* Имя коллекции
|
||||
*/
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Свойства
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributes(),
|
||||
[
|
||||
'search_period',
|
||||
'search_connect_keep'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Метки свойств
|
||||
*/
|
||||
public function attributeLabels(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::attributeLabels(),
|
||||
[
|
||||
'search_period' => 'Поисковый период',
|
||||
'search_connect_keep' => 'Режим удержания'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Правила
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(
|
||||
parent::rules(),
|
||||
[
|
||||
[
|
||||
[
|
||||
'search_period'
|
||||
],
|
||||
'integer',
|
||||
'message' => '{attribute} должен хранить цифровое значение'
|
||||
],
|
||||
[
|
||||
[
|
||||
'search_connect_keep'
|
||||
],
|
||||
'string',
|
||||
'message' => '{attribute} должен хранить строковый тип'
|
||||
]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models;
|
||||
|
||||
class SettingsEdgeSettings extends Edge
|
||||
{
|
||||
public static function collectionName(): string
|
||||
{
|
||||
return 'settings_edge_settings';
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ use app\models\traits\Xml2Array;
|
|||
|
||||
use carono\exchange1c\interfaces\ProductInterface;
|
||||
|
||||
use exception;
|
||||
|
||||
/**
|
||||
* Поставка (выгрузка товаров от поставщиков)
|
||||
*
|
||||
|
@ -66,9 +68,16 @@ class Supply extends Product implements ProductInterface
|
|||
*/
|
||||
public function afterSave($data, $vars): void
|
||||
{
|
||||
if (AccountEdgeSupply::searchByVertex(Yii::$app->user->id, $this->readId())) {
|
||||
// Ребро уже существует
|
||||
|
||||
} else {
|
||||
// Ребра не существует
|
||||
|
||||
// Запись ребра: АККАУНТ -> ПОСТАВКА
|
||||
(new AccountEdgeSupply)->write(Yii::$app->user->id, $this->readId(), 'import');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись реквизитов из 1С
|
||||
|
@ -97,31 +106,25 @@ class Supply extends Product implements ProductInterface
|
|||
*
|
||||
* Ищет записанные свойства из 1C по их идентификатору и добавляет к ним
|
||||
* недостающие данные. Это костыль оставшийся от реляционных баз данных
|
||||
*
|
||||
* @todo Понять что может храниться внутри "$model->onec['ЗначенияСвойств']['ЗначенияСвойства']" и переписать
|
||||
*/
|
||||
public static function createProperties1c($properties): void
|
||||
{
|
||||
// Инициализация
|
||||
$models = static::searchOnecByAccountId(Yii::$app->user->id, true);
|
||||
$models = self::searchByAccount(Yii::$app->user->id, true);
|
||||
$properties = self::xml2array($properties->xml);
|
||||
|
||||
$fp = fopen('1.txt', 'a');
|
||||
fwrite($fp, print_r(count($models), true) . PHP_EOL);
|
||||
fclose($fp);
|
||||
|
||||
// for ($i = 0; $i <= count($models); $i++)
|
||||
foreach ($models as $model) {
|
||||
// Перебор записей
|
||||
|
||||
$fp = fopen('2.txt', 'a');
|
||||
fwrite($fp, $model->ocid . PHP_EOL);
|
||||
fclose($fp);
|
||||
|
||||
// Инициализация
|
||||
$changes = false;
|
||||
$transit = $model->onec;
|
||||
|
||||
foreach ($model->onec['ЗначенияСвойств'] as $attribute_name => $attribute_value) {
|
||||
// Перебор аттрибутов
|
||||
// Перебор аттрибутовfw
|
||||
|
||||
foreach ($properties as $property) {
|
||||
// Перебор свойств
|
||||
|
@ -149,6 +152,19 @@ class Supply extends Product implements ProductInterface
|
|||
// Настройка ($transit нужен из-за ограничений __set())
|
||||
$model->onec = $transit;
|
||||
|
||||
foreach ($model->onec['ЗначенияСвойств'] as $property) {
|
||||
// Перебор всех свойств
|
||||
|
||||
if (is_array($property)) {
|
||||
if ($property['Ид'] === 'd99622fe-4526-11eb-b7f3-f3e52d0a06a9') {
|
||||
// Если идентификатор свойства совпадает с указанным в настройках свойства хранящего OEM номера
|
||||
|
||||
// Настройка
|
||||
$model->catn = $property['Значение'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Запись
|
||||
$model->save();
|
||||
}
|
||||
|
@ -165,14 +181,61 @@ class Supply extends Product implements ProductInterface
|
|||
|
||||
/**
|
||||
* Запись изображений из 1С
|
||||
*
|
||||
* @todo Добавить параметры в админ-панель
|
||||
* Запретить доступ к изображениям
|
||||
*/
|
||||
public function addImage1c($path, $caption): mixed
|
||||
public function addImage1c($path, $caption): bool
|
||||
{
|
||||
// Инициализация
|
||||
$i = 0;
|
||||
|
||||
if (!file_exists(YII_PATH_PUBLIC . $catalog = '/img/supplies/' . $this->_key)) {
|
||||
// Директория для изображений продукта не найдена
|
||||
|
||||
if (!mkdir(YII_PATH_PUBLIC . $catalog, 0775, true)) {
|
||||
// не удалось записать директорию
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
foreach ($this->imgs ?? [] as $image) {
|
||||
// Перебор имеющихся изображений
|
||||
|
||||
if ($path === $image['sorc']) {
|
||||
// Изображение уже записано на сервер
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$urn = basename($path);
|
||||
|
||||
// Запись
|
||||
copy($path, $path_local = YII_PATH_PUBLIC . $catalog . '/' . $urn);
|
||||
|
||||
// Запись свойства
|
||||
$this->imgs = array_merge(
|
||||
$this->imgs ?? [],
|
||||
[
|
||||
[
|
||||
'desc' => $caption,
|
||||
'path' => $path_local,
|
||||
'sorc' => $path
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
// Отправка в базу данных
|
||||
return $this->update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись ребра (предложения от поставок к продуктам) из 1С
|
||||
*
|
||||
* @todo Разобраться зачем нужно возвращать SupplyEdgeProduct
|
||||
*/
|
||||
public function getOffer1c($offer): SupplyEdgeProduct
|
||||
{
|
||||
|
@ -181,21 +244,46 @@ class Supply extends Product implements ProductInterface
|
|||
|
||||
// Разработчику библеотеки надо дать по жопе
|
||||
return new SupplyEdgeProduct;
|
||||
} else if (!$product = Product::searchByCatn($this->catn)) {
|
||||
// Продукт не найден
|
||||
}
|
||||
|
||||
if (!$this->initProduct()) {
|
||||
// Не удалось инициализировать продукт
|
||||
// Инициализация п̸̨͇͑͋͠р̷̬̂́̀̊о̸̜̯̹̅͒͘͝д̴̨̨̨̟̈́̆у̴̨̭̮̠́͋̈́к̴̭͊̋̎т̵̛̣͈̔̐͆а̵̨͖͑
|
||||
$product = Product::initEmpty($this->catn);
|
||||
|
||||
// Разработчику библеотеки надо дать по жопе
|
||||
return new SupplyEdgeProduct;
|
||||
if (!is_array($product)) {
|
||||
// Создался только один товар и вернулся в виде модели
|
||||
|
||||
$product = [$product];
|
||||
}
|
||||
|
||||
if (is_array($this->oemn)) {
|
||||
// Значение OEM было инициализировано
|
||||
|
||||
foreach ($this->oemn as $oem) {
|
||||
// Перебор артикулов из массива ОЕМ-номеров
|
||||
|
||||
// Инициализация и запись
|
||||
$product[] = Product::initEmpty($oem);
|
||||
}
|
||||
}
|
||||
|
||||
$product = Product::searchByCatn($this->catn);
|
||||
|
||||
|
||||
// $fp = fopen('555.txt', 'a');
|
||||
// fwrite($fp, print_r($property, true) . PHP_EOL);
|
||||
// fclose($fp);
|
||||
|
||||
|
||||
foreach ($product as $product) {
|
||||
// Перебор всех инициализированных продуктов
|
||||
|
||||
if (SupplyEdgeProduct::searchByVertex($this->readId(), $product->readId())) {
|
||||
// Ребро уже существует
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Запись ребра: ПОСТАВКА -> ПРОДУКТ
|
||||
return (new SupplyEdgeProduct)->write(
|
||||
$return = (new SupplyEdgeProduct)->write(
|
||||
$this->readId(),
|
||||
$product->readId(),
|
||||
'sell',
|
||||
|
@ -205,8 +293,15 @@ class Supply extends Product implements ProductInterface
|
|||
);
|
||||
}
|
||||
|
||||
// Возвращает последнее сохранённое ребро
|
||||
// Надо будет с этим разобраться
|
||||
return $return ?? new SupplyEdgeProduct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Запись продукта из 1С
|
||||
*
|
||||
* @todo Понять что может храниться внутри "$model->onec['ЗначенияСвойств']['ЗначенияСвойства']" и переписать
|
||||
*/
|
||||
public static function createModel1c($product): ?self
|
||||
{
|
||||
|
@ -216,38 +311,33 @@ class Supply extends Product implements ProductInterface
|
|||
// Настройка
|
||||
$model->ocid = $id ?? null;
|
||||
$model->catn = (string) $product->Артикул;
|
||||
$model->oemn = null;
|
||||
$model->onec = self::xml2array($product->xml);
|
||||
|
||||
// Запись
|
||||
return $model->save() ? $model : null;
|
||||
if (isset($model->onec['ЗначенияСвойств'])) {
|
||||
// Свойства инициализированы
|
||||
|
||||
foreach ($model->onec['ЗначенияСвойств'] as $property) {
|
||||
// Перебор всех свойств
|
||||
|
||||
if (is_array($property)) {
|
||||
if ($property['Ид'] === 'd99622fe-4526-11eb-b7f3-f3e52d0a06a9') {
|
||||
// Если идентификатор свойства совпадает с указанным в настройках свойства хранящего OEM номера
|
||||
|
||||
// Настройка
|
||||
$model->oemn = array_merge(self::convertOemn2Catn($property['Значение']), self::convertOemn2Catn((string) $product->Артикул));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Инициализация продукта
|
||||
*/
|
||||
protected function initProduct(): ?Product
|
||||
{
|
||||
// Надо не забыть сделать выборку полей и ручное подключение
|
||||
// Запись
|
||||
if ($model->save()) {
|
||||
// Поставка успешно сохранена
|
||||
|
||||
if (empty($this->catn)) {
|
||||
// Не передан каталожный номер
|
||||
|
||||
return false;
|
||||
} else if (Product::searchByCatn($this->catn)) {
|
||||
// Продукт уже был инициализирован
|
||||
|
||||
return true;
|
||||
return $model;
|
||||
}
|
||||
|
||||
// Инициализация
|
||||
$product = new Product();
|
||||
|
||||
// Настройки
|
||||
$product->catn = $this->catn;
|
||||
|
||||
// Запись
|
||||
return $product->save() ? $product : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -294,8 +384,18 @@ class Supply extends Product implements ProductInterface
|
|||
return 'ocid';
|
||||
}
|
||||
|
||||
public static function searchOnecByAccountId(string $id, bool $full = false): array
|
||||
/**
|
||||
* Поиск через связь с аккаунтом
|
||||
*
|
||||
* @param string $id Идентификатор пользователя
|
||||
* @param bool $full Возврат всех значений (иначе только свойства)
|
||||
*/
|
||||
public static function searchByAccount(string $id = null, bool $full = false): array
|
||||
{
|
||||
if (!isset($id)) {
|
||||
$id = yii::$app->user->id ?? throw new exception('Не найден идентификатор');
|
||||
}
|
||||
|
||||
$subquery = static::find()
|
||||
->for(['account', 'account_edge_supply'])
|
||||
->traversal('supply')->in('account_edge_supply')
|
||||
|
@ -304,7 +404,7 @@ class Supply extends Product implements ProductInterface
|
|||
->createCommand();
|
||||
|
||||
$query = static::find()
|
||||
->addParams($subquery->getBindVars())
|
||||
->params($subquery->getBindVars())
|
||||
->let('account_edge_supply', '(' . (string) $subquery . ')')
|
||||
->where('supply._id == account_edge_supply[0]._to')
|
||||
->andWhere('supply.onec["ЗначенияСвойств"] != null');
|
||||
|
@ -317,6 +417,8 @@ class Supply extends Product implements ProductInterface
|
|||
$query = $query->select('supply.onec["ЗначенияСвойств"]')->createCommand()->execute()->getAll();
|
||||
|
||||
foreach ($query as &$attribute) {
|
||||
// Приведение всех свойств в массив и очистка от лишних данных
|
||||
|
||||
$attribute = $attribute->getAll();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models\traits;
|
||||
|
||||
use yii;
|
||||
|
||||
use exception;
|
||||
|
||||
trait SearchByAccount
|
||||
{
|
||||
/**
|
||||
* Поиск через связи рёбрами с аккаунтом
|
||||
*
|
||||
* @param string $id Идентификатор пользователя
|
||||
* @param int $limit Количество
|
||||
* @param int $offset Сдвиг
|
||||
* @param string $sort Сортировка
|
||||
*/
|
||||
public static function searchByAccount(
|
||||
string $id = null,
|
||||
int $limit = 10,
|
||||
int $offset = 0,
|
||||
array $sort = ['ASC'],
|
||||
string|array $where = [],
|
||||
string|array $post_where = [],
|
||||
string $direction = 'ANY',
|
||||
array $let = [],
|
||||
array $params = []
|
||||
): ?array {
|
||||
if (!isset($id)) {
|
||||
$id = yii::$app->user->id ?? throw new exception('Не найден идентификатор');
|
||||
}
|
||||
|
||||
$subquery = static::find()
|
||||
->for(['account', 'account_edge_' . self::collectionName()])
|
||||
->traversal(self::collectionName(), $direction)
|
||||
->in('account_edge_' . self::collectionName())
|
||||
->where(['account._id' => $id]);
|
||||
|
||||
if (!empty($where)) {
|
||||
// Переданы дополнительные условия фильтрации
|
||||
|
||||
$subquery->where($where);
|
||||
}
|
||||
|
||||
$subquery = $subquery->select('account_edge_' . self::collectionName())
|
||||
->createCommand();
|
||||
|
||||
$query = static::find()
|
||||
->params($params, $subquery->getBindVars())
|
||||
->let('account_edge_' . self::collectionName(), '(' . (string) $subquery . ')')
|
||||
->limit($limit)
|
||||
->offset($offset)
|
||||
->orderBy($sort);
|
||||
|
||||
if (!empty($let)) {
|
||||
// Переданы дополнительные условия фильтрации
|
||||
|
||||
$query->let(...$let);
|
||||
}
|
||||
|
||||
if (isset($post_where) && $post_where) {
|
||||
// Если переданы дополнительные условия фильтрации
|
||||
|
||||
$query->where($post_where);
|
||||
} else {
|
||||
$query->where(self::collectionName() . '._id == account_edge_' . self::collectionName() . '[0]._to');
|
||||
}
|
||||
|
||||
return $query->select(self::collectionName())->all();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\models\traits;
|
||||
|
||||
trait Xml2Array {
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
<?
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii;
|
||||
|
||||
?>
|
||||
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
|
||||
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
|
||||
<div class="btn-group my-auto">
|
||||
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
|
||||
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
|
||||
<div class="dropdown-menu dropdown-menu-long dropdown-menu-right p-3" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
|
||||
<h5 class="mb-3 text-center">Аутентификация</h5>
|
||||
<?= yii::$app->controller->renderPartial('/account/index') ?>
|
||||
<!-- <a class="dropdown-item-text text-center px-0 py-2" href="#"><small>Восстановление пароля</small></a> -->
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,28 @@
|
|||
<?
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii;
|
||||
|
||||
if (!yii::$app->user->isGuest) {
|
||||
$popup = yii::$app->controller->renderPartial('/notification/panel');
|
||||
|
||||
echo <<<HTML
|
||||
<a id="notification_button" class="text-dark d-flex h-100 mr-2" title="Уведомления" href="/notification" role="button" data-toggle="dropdown" data-offset="-100%p + 100%" onclick="return notification_stream();">
|
||||
<i class="fas fa-bell my-auto mx-2"></i>
|
||||
</a>
|
||||
<div id="notification_button_panel" class="dropdown-menu py-1" aria-labelledby="notification_button">
|
||||
$popup
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
<a class="text-dark my-auto mr-2" href="/cart"><i class="fas fa-shopping-cart mx-2"></i></a>
|
||||
<a class="text-dark my-auto mr-2" href="/orders"><i class="fas fa-list mx-2"></i></a>
|
||||
<div class="btn-group my-auto">
|
||||
<a class="btn m-0 px-0 text-dark button_clean" title="Личный кабинет" href="/profile" role="button" onclick="return page_profile();">Личный кабинет</a>
|
||||
<button id="profile_button" class="btn pr-0 dropdown-toggle dropdown-toggle-split button_clean" type="button" data-toggle="dropdown" onmouseover="$('#profile_button').dropdown('show')"></button>
|
||||
<div id="profile_button_panel" class="dropdown-menu dropdown-menu-right py-1" aria-labelledby="profile_button" onmouseout="$('#profile_button').dropdown('show')">
|
||||
<a class="dropdown-item button_white text-dark" onclick="deauthentication()">Выход (<?= yii::$app->user->identity->mail ?>)</a>
|
||||
</div>
|
||||
</div>
|
|
@ -12,7 +12,7 @@ $this->title = 'SkillParts';
|
|||
<div class="container h-100 d-flex flex-column justify-content-center">
|
||||
<p class="mb-4 ml-0 gilroy">Проблема с подбором запчастей?</p>
|
||||
<p class="ml-0 d-flex">
|
||||
<span class="p-2 px-3 button_call_icon"><i class="fas fa-phone-alt text-white"></i></span>
|
||||
<span class="p-2 px-3 button_call_icon d-flex"><i class="fas fa-phone-alt my-auto text-white"></i></span>
|
||||
<a class="btn text-white button_clean button_blue button_call" href="/call" role="button">Связаться с менеджером</a>
|
||||
</p>
|
||||
</div>
|
||||
|
@ -22,21 +22,21 @@ $this->title = 'SkillParts';
|
|||
</div>
|
||||
|
||||
<div class="h-100 d-flex ticker">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/cummins.png" alt="Cummins">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/iveco.png" alt="Iveco">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/komatsu.png" alt="Komatsu">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/case.png" alt="Case">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/isuzu.png" alt="Isuzu">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/new_holland.svg" alt="New Holland">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/perkins.png" alt="Perkins">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/john_deere.png" alt="John Deere">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/caterpillar.png" alt="Caterpillar">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/shantui.png" alt="Shantui">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/xcmg.png" alt="XCMG">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/kobelco.png" alt="Kobelco">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/shehwa.png" alt="SHEHWA">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/bomag.png" alt="BOMAG">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h100px/compressed/hitachi.png" alt="Hitachi">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/cummins.png" alt="Cummins">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/iveco.png" alt="Iveco">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/komatsu.png" alt="Komatsu">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/case.png" alt="Case">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/isuzu.png" alt="Isuzu">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/new_holland.png" alt="New Holland">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/perkins.png" alt="Perkins">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/john_deere.png" alt="John Deere">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/caterpillar.png" alt="Caterpillar">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/shantui.png" alt="Shantui">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/xcmg.png" alt="XCMG">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/kobelco.png" alt="Kobelco">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/shehwa.png" alt="SHEHWA">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/bomag.png" alt="BOMAG">
|
||||
<img class="w-auto h-100 mr-3 my-auto" src="/img/logos/h32px/compressed/hitachi.png" alt="Hitachi">
|
||||
</div>
|
||||
|
||||
<div class="container mb-4">
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
|
||||
/* @var $this \yii\web\View */
|
||||
/* @var $content string */
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\assets\AppAsset;
|
||||
|
||||
AppAsset::register($this);
|
||||
|
@ -27,19 +27,21 @@ AppAsset::register($this);
|
|||
<body>
|
||||
<?php $this->beginBody() ?>
|
||||
|
||||
<header class="container pt-2 mt-1 mb-4">
|
||||
<div id="notifications_popup_wrap" class="col-3 m-4"></div>
|
||||
|
||||
<header class="container pt-2 mt-1 mb-2 mb-sm-4">
|
||||
<div class="row h-100">
|
||||
<a class="col-3 h-100 py-2" title="SkillParts" href="/" role="button" onclick="return page_main();">
|
||||
<a id="logo" class="col-3 col-md-4 h-100 py-2" title="SkillParts" href="/" role="button" onclick="return page_main();">
|
||||
<img class="h-100" src="/img/logos/skillparts.svg" alt="SkillParts">
|
||||
</a>
|
||||
<div class="col-6 px-0 mt-auto d-flex">
|
||||
<div class="col px-0 mt-auto d-flex h-title">
|
||||
<div class="ml-auto p-0 h-divider-title-left"></div>
|
||||
<div class="px-4 d-flex flex-column justify-content-center h-divider-title">
|
||||
<h6 class="text-center text-white my-0"><b>Запчасти для спецтехники</b></h6>
|
||||
</div>
|
||||
<div class="mr-auto p-0 h-divider-title-right"></div>
|
||||
</div>
|
||||
<menu class="col-3 mb-0 d-flex justify-content-end"></menu>
|
||||
<menu class="col-auto col-lg-4 mb-0 d-flex justify-content-end"></menu>
|
||||
</div>
|
||||
<div class="h-divider"></div>
|
||||
</header>
|
||||
|
@ -66,11 +68,21 @@ AppAsset::register($this);
|
|||
<input id="catalog_search_panel_button_3" class="btn btn-sm5 text-white button_clean" type="radio" name="catalog_search_panel_buttons" value="catalog_search_panel_button_3">
|
||||
<label class="mb-0 px-3 px-md-4 py-1" for="catalog_search_panel_button_3">Третья кнопка</label> -->
|
||||
<form class="d-flex catalog_search" onsubmit="return false;">
|
||||
<div class="position-relative col-8 col-lg-10 px-0">
|
||||
<input id="search_line" type="text" class="form-control col-12 catalog_search_line button_clean" placeholder="Введите номер запчасти, например: 45223503481" onclick="$('#search_line').dropdown('toggle')" onmouseenter="$('#search_line').dropdown('show')" oninput="$('#search_line').dropdown('hide'); product_search(this);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<div id="search_line_window" class="dropdown-menu w-100" aria-labelledby="search_line" onmouseout="$('#search_line').dropdown('show')">
|
||||
<a class="dropdown-item button_white text-dark inactive">Здесь будет история поиска</a>
|
||||
<div class="position-relative col-sm-8 col-lg-10 px-0">
|
||||
<input id="search_line" type="text" class="form-control col-12 catalog_search_line button_clean" placeholder="Введите номер запчасти, например: 45223503481" oninput="$('#search_line').dropdown('hide'); product_search(this);" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" autocomplete="off">
|
||||
<?
|
||||
if (!yii::$app->user->isGuest && $search_panel = $search_panel ?? yii::$app->controller->renderPartial('/search/panel', ['history' => true])) {
|
||||
echo <<<HTML
|
||||
<div id="search_line_window" class="dropdown-menu w-100" aria-labelledby="search_line">
|
||||
$search_panel
|
||||
</div>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<div id="search_line_window" class="dropdown-menu w-100 d-none" aria-labelledby="search_line"></div>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<button type="submit" class="col btn button_clean catalog_search_button" onclick="product_search(this.parentElement.getElementsByTagName('input')[0], 1)">ПОИСК</button>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<?
|
||||
if (empty($notifications)) {
|
||||
echo <<<HTML
|
||||
<p class="px-2 py-3 text-center">Уведомлений нет</p>
|
||||
HTML;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach($notifications as $notification) {
|
||||
// Перебор уведомлений
|
||||
|
||||
// Инициализация
|
||||
$notification = $notification->getAttributes();
|
||||
|
||||
if ($notification['type'] === 'notice') {
|
||||
// Уведомление
|
||||
|
||||
echo $notification['html'];
|
||||
} else if ($notification['type'] === 'warning') {
|
||||
// Предупреждение
|
||||
|
||||
echo $notification['html'];
|
||||
} else {
|
||||
// Неизвестно
|
||||
|
||||
echo $notification['html'] ?? '<p>ОШИБКА</p>';
|
||||
}
|
||||
}
|
||||
?>
|
|
@ -0,0 +1,10 @@
|
|||
<?
|
||||
$id = 'popup/' . $notification->readId();
|
||||
$html = $notification->html;
|
||||
|
||||
echo <<<HTML
|
||||
<div id="$id" class="mt-3 p-0 notification rounded" onmouseleave="return notification_popup_delete(this);">
|
||||
$html
|
||||
</div>
|
||||
HTML;
|
||||
?>
|
|
@ -1,5 +1,10 @@
|
|||
<?php
|
||||
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\models\Product;
|
||||
|
||||
?>
|
||||
<link href="/css/pages/product.css" rel="stylesheet">
|
||||
|
||||
|
@ -7,11 +12,117 @@
|
|||
<div class="container h-100">
|
||||
<div class="row h-100 py-3">
|
||||
<article class="col-12">
|
||||
<div class="h-100 p-3 rounded">
|
||||
<h4 class="ml-4"><?php echo $model['name'] ?></h4>
|
||||
<div class="dropdown-divider"></div>
|
||||
<p class="ml-4">Дата создания: <time><?php echo date('d.m.Y H:i', $model['date']) ?></time></p>
|
||||
<pre class="ml-4"><?php var_dump($model) ?></pre>
|
||||
<div class="h-100 p-3 d-flex flex-column rounded">
|
||||
<div id="product_slider" class="row px-3 profile_panel">
|
||||
<div class="col-1 product_slider_preview p-0 pr-3 mb-3">
|
||||
<?
|
||||
foreach ($model['imgs'] ?? [null] as $key => $image) {
|
||||
// Перебор изображений
|
||||
|
||||
// Инициализация
|
||||
$name = $image['name'] ?? 'Без названия';
|
||||
$h150 = $image['h150'] ?? '/img/covers/h150/product.png';
|
||||
|
||||
// Генерация предпросмотра изображения
|
||||
echo <<<HTML
|
||||
<label class="p-0 mb-2" for="product_slider_image_$key">
|
||||
<img class="img-fluid rounded" src="$h150"/>
|
||||
</label>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="product_slider_image">
|
||||
<?
|
||||
// Инициализация
|
||||
$imgs = $model['imgs'] ?? [null];
|
||||
$checked = '';
|
||||
|
||||
foreach ($imgs as $key => $image) {
|
||||
// Перебор изображений
|
||||
|
||||
// Инициализация
|
||||
$name = $image['name'] ?? 'Без названия';
|
||||
$orig = $image['orig'] ?? '/img/covers/product.png';
|
||||
$covr = $image['covr'] ?? false;
|
||||
|
||||
if ($covr || count($imgs) < 2) {
|
||||
// Если это изображение является обложкой
|
||||
|
||||
// Реинициализация
|
||||
$checked = 'checked';
|
||||
}
|
||||
|
||||
// Генерация изображения
|
||||
echo <<<HTML
|
||||
<input type="radio" id="product_slider_image_$key" name="slider" $checked/>
|
||||
<div class="col p-0">
|
||||
<img class="img-fluid rounded" src="$orig"/>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
// Деинициализация
|
||||
$checked = '';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="col ml-4 d-flex flex-column">
|
||||
<div class="row mb-1">
|
||||
<h3 class="my-auto">Название товара</h3>
|
||||
<h5 class="ml-auto my-auto"><?= $model['catn'] ?></h5>
|
||||
</div>
|
||||
<div class="dropdown-divider px-0 mb-3"></div>
|
||||
<div class="row mb-3 h-100 product_panel d-flex flex-column">
|
||||
<p class="mt-0">
|
||||
ОЕМ-номера можно сюда добавить с возможностью перехода
|
||||
<?
|
||||
// foreach ($model['catn'] ?? [] as $catn) {
|
||||
// echo <<<HTML
|
||||
// $catn
|
||||
// HTML;
|
||||
// }
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
<?
|
||||
$form = ActiveForm::begin([
|
||||
'id' => 'form_product_cart',
|
||||
'action' => false,
|
||||
'fieldConfig' => [
|
||||
'template' => '{input}',
|
||||
],
|
||||
'options' => [
|
||||
'onsubmit' => 'return false;',
|
||||
'class' => 'row mt-auto'
|
||||
]
|
||||
]);
|
||||
|
||||
// Просто для теста
|
||||
$model = new Product();
|
||||
?>
|
||||
|
||||
<div class="col-6 px-0 mr-4 btn-group">
|
||||
<?= Html::submitButton('В корзину', ['name' => 'cartWrite', 'onclick' => 'product_cart_write(this.parentElement);', 'class' => 'col-10 btn button_blue button_clean py-2 px-5']) ?>
|
||||
<?= $form->field($model, 'amount', ['options' => ['class' => 'col h-100 m-0 form-group']])->textInput(['value' => '1', 'class' => 'form-control h-100 rounded-0 text-center button_clean']); ?>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="mt-0">
|
||||
<strong>Хабаровск: </strong>
|
||||
в наличии
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
Доставим: завтра
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<? ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-auto mx-0">
|
||||
<p class="ml-0">Время для повышения релевантности в поисковиках</p>
|
||||
<time class="ml-auto"><?php echo date('d.m.Y', $model['date']) ?></time>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<?php
|
||||
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use app\models\Supply;
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\models\Notification;
|
||||
|
||||
?>
|
||||
<link href="/css/pages/profile.css" rel="stylesheet">
|
||||
|
@ -10,46 +14,100 @@ use app\models\Supply;
|
|||
<div id="page_profile" class="container h-100">
|
||||
<div class="row h-100 py-3">
|
||||
<nav class="col-3">
|
||||
<?= $sidebar ?? Yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
<?= $sidebar ?? yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
</nav>
|
||||
<article class="col-9">
|
||||
<div class="h-100 p-4 rounded">
|
||||
<h4 class="ml-4 mb-4">Настройки аккаунта</h4>
|
||||
<p>Пока не сделана нормальная панель управления я просто буду добавлять все настройки сюда</p>
|
||||
<?php
|
||||
<div class="p-4 rounded">
|
||||
<h4 class="ml-4 mb-4"><i class="fas fa-sliders-h my-auto mr-2"></i>Настройки</h4>
|
||||
<div id="profile_panel_settings" class="profile_panel">
|
||||
<div class="profile_panel_menu mb-3">
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_settings_account">Аккаунт</label>
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_settings_company">Компания</label>
|
||||
<label class="btn button_white mb-0" for="profile_panel_settings_import">Импорт</label>
|
||||
</div>
|
||||
<div class="profile_panel_content d-flex">
|
||||
<input type="radio" id="profile_panel_settings_account" name="main_panel" />
|
||||
<div class="col">
|
||||
1
|
||||
</div>
|
||||
|
||||
<input type="radio" id="profile_panel_settings_company" name="main_panel" />
|
||||
<div class="col">
|
||||
2
|
||||
</div>
|
||||
|
||||
<input type="radio" id="profile_panel_settings_import" name="main_panel" checked />
|
||||
<div class="col">
|
||||
<h5>Параметры 1C</h5>
|
||||
<div class="dropdown-divider mb-3"></div>
|
||||
<?
|
||||
$form = ActiveForm::begin([
|
||||
'id' => 'form_profile_options',
|
||||
'id' => 'form_profile_settings',
|
||||
'action' => false,
|
||||
'fieldConfig' => [
|
||||
'template' => '{label}{input}',
|
||||
'options' => ['class' => '']
|
||||
],
|
||||
'options' => [
|
||||
'class' => 'mb-3',
|
||||
'onsubmit' => 'return false;'
|
||||
]
|
||||
]);
|
||||
|
||||
$model = $model ?? Yii::$app->user->identity;
|
||||
var_dump($attributes = Supply::searchOnecByAccountId(Yii::$app->user->id));
|
||||
/**
|
||||
* @todo Перенести в модель
|
||||
*/
|
||||
|
||||
// $list = [];
|
||||
// Инициализация
|
||||
isset($model) or $model = yii::$app->user->identity;
|
||||
isset($attributes) or $attributes = Supply::searchByAccount(yii::$app->user->id);
|
||||
$list = [];
|
||||
|
||||
// //
|
||||
// foreach ($attributes as $attribute) {
|
||||
// $id = $attribute['ЗначенияСвойства']['Ид'];
|
||||
// Перебор свойств поставок
|
||||
foreach ($attributes as $attribute) {
|
||||
// Инициализация
|
||||
$id = $attribute['ЗначенияСвойства']['Ид'];
|
||||
|
||||
// if (in_array($id, $list, true)) {
|
||||
// continue;
|
||||
// }
|
||||
if (in_array($id, $list, true)) {
|
||||
// Если встретился дубликат (вызывается очень часто)
|
||||
continue;
|
||||
}
|
||||
|
||||
// $list[] = $id;
|
||||
// }
|
||||
// Генерация
|
||||
$list[$id] = $attribute['ЗначенияСвойства']['Наименование'];
|
||||
}
|
||||
|
||||
// Инициализация текущего значения параметра в начале массива
|
||||
if (isset($model->opts['import_sections_oem'])) {
|
||||
// Параметр 'import_sections_oem' найден в настройках аккаунта
|
||||
|
||||
if (isset($list[$model->opts['import_sections_oem']])) {
|
||||
// Найдено совпадение сохранённого параметра с полученным списком из поставок
|
||||
|
||||
// Буфер для сохранения параметра
|
||||
$buffer = $list[$model->opts['import_sections_oem']];
|
||||
|
||||
// Удаление параметра
|
||||
unset($list[$model->opts['import_sections_oem']]);
|
||||
|
||||
// Сохранение параметра в начале массива
|
||||
$list = array_merge([$model->opts['import_sections_oem'] => $buffer], $list);
|
||||
} else {
|
||||
// Совпадение не найдено
|
||||
|
||||
// Сохранение параметра из данных аккаунта в начале массива
|
||||
$list = array_merge([$model->opts['import_sections_oem'] => $model->opts['import_sections_oem']], $list);
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?= "a" //$form->field($model, 'opts[import_sections_oem]', ['options' => ['class' => "mb-3"]])->dropDownList($list ?? ['Нет данных']); ?>
|
||||
|
||||
<?php ActiveForm::end(); ?>
|
||||
<?= $form->field($model, 'opts[import_sections_oem]', ['options' => ['class' => "mb-1"]])->dropDownList($list ?? ['Нет данных'], ['onChange' => 'page_profile_settings(this.parentElement.parentElement)'])->label('OEM-номера'); ?>
|
||||
<small class="d-block mb-1">Выберите поле в котором хранятся <b>ОЕМ-номера</b> и повторите импорт</small>
|
||||
<small class="d-block">Значения взяты из импортированных товаров</small>
|
||||
<!-- <small class="d-block mb-3">Значения взяты из импортированных товаров</small> -->
|
||||
|
||||
<? ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
?>
|
||||
<link href="/css/pages/profile.css" rel="stylesheet">
|
||||
|
||||
<div id="page_profile" class="container h-100">
|
||||
<div class="row h-100 py-3">
|
||||
<nav class="col-3">
|
||||
<?= $sidebar ?? Yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
</nav>
|
||||
<article class="col-9">
|
||||
<div class="p-4 rounded">
|
||||
<h4 class="ml-3 mb-4"><i class="fas fa-eye my-auto mr-2"></i>Мониторинг</h4>
|
||||
<div id="profile_panel_monitoring" class="profile_panel">
|
||||
<div class="profile_panel_menu mb-3">
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_monitoring_input_orders_history">Заказы</label>
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_monitoring_input_search_history">Поисковые запросы</label>
|
||||
<label class="btn button_white mb-0" for="profile_panel_monitoring_input_log">Журнал действий</label>
|
||||
</div>
|
||||
<div class="profile_panel_content">
|
||||
<input type="radio" id="profile_panel_monitoring_input_orders_history" name="main_panel" />
|
||||
<div class="col p-3">
|
||||
История заказов в разработке
|
||||
</div>
|
||||
|
||||
<input type="radio" id="profile_panel_monitoring_input_search_history" name="main_panel" checked />
|
||||
<div class="col">
|
||||
<div class="row header_blue py-2 text-white">
|
||||
<div class="col-sm-4 col-md-3">IPv4</div>
|
||||
<div class="col-7 col-sm-3 col-md-4 col-lg-6 pr-0 px-sm-0 px-lg-3">Поисковый запрос</div>
|
||||
<div class="col">Время</div>
|
||||
</div>
|
||||
<?
|
||||
foreach ($search_history as $row) {
|
||||
// Инициализация
|
||||
$date = date('H:i d.m.Y', $row->date);
|
||||
|
||||
echo <<<HTML
|
||||
<div class="row py-1">
|
||||
<div class="col-sm-4 col-md-3">$row->ipv4</div>
|
||||
<div class="col-7 col-sm-3 col-md-4 col-lg-6 pr-0 px-sm-0 px-lg-3">$row->text</div>
|
||||
<div class="col">$date</div>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
<div class="mt-3">
|
||||
<?
|
||||
$page = ($page_search_history ?? 0) + 1;
|
||||
|
||||
echo <<<HTML
|
||||
<div class="row">
|
||||
<button class="btn button_clean button_blue" onclick="return page_profile_monitoring(-1);">Назад</button>
|
||||
<p>$page</p>
|
||||
<button class="btn button_clean button_blue" onclick="return page_profile_monitoring(1);">Вперёд</button>
|
||||
<div class="col-8"></div>
|
||||
</div>
|
||||
HTML;
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="radio" id="profile_panel_monitoring_input_log" name="main_panel" />
|
||||
<div class="col p-3">
|
||||
Журнал в разработке
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/profile.js" defer></script>
|
|
@ -2,27 +2,105 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Yii;
|
||||
use yii;
|
||||
|
||||
use app\models\Product;
|
||||
use app\models\Supply;
|
||||
?>
|
||||
use app\models\AccountEdgeSupply;
|
||||
use app\models\SupplyEdgeProduct;
|
||||
|
||||
<div class="p-3 rounded">
|
||||
?>
|
||||
<div class="col py-3 rounded">
|
||||
<div class="row px-3">
|
||||
<p class="ml-0">Почта: </p>
|
||||
<p class="mr-0"><?= Yii::$app->user->identity->mail ?></p>
|
||||
<p class="mr-0"><?= yii::$app->user->identity->mail ?></p>
|
||||
</div>
|
||||
<div class="dropdown-divider my-3"></div>
|
||||
<dl class="m-0">
|
||||
<?
|
||||
if (yii::$app->user->identity->trst) {
|
||||
// Пользователь является доверенным
|
||||
|
||||
// Инициализация
|
||||
$targetUrl = '/profile/trusted';
|
||||
|
||||
if ('/' . yii::$app->request->pathInfo === $targetUrl) {
|
||||
// Запрошена эта страница
|
||||
|
||||
echo <<<HTML
|
||||
<dt>
|
||||
<a class="row text-dark mb-3 px-3 font-weight-normal" href="/profile">Настройки аккаунта</a>
|
||||
<a class="row text-dark button_white button_white_hover px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-sliders-h my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Панель управления</span></a>
|
||||
</dt>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<dt>
|
||||
<a class="row text-dark button_white px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-sliders-h my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Панель управления</span></a>
|
||||
</dt>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
?>
|
||||
<dt>
|
||||
<?
|
||||
// Инициализация
|
||||
$targetUrl = '/profile/supplies';
|
||||
|
||||
if ('/' . yii::$app->request->pathInfo === $targetUrl) {
|
||||
// Запрошена эта страница
|
||||
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white button_white_hover px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-truck my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Поставки</span></a>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-truck my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Поставки</span></a>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
</dt>
|
||||
<dt>
|
||||
<a class="row text-dark px-3 font-weight-normal" href="/profile/supplies">Управление поставками</a>
|
||||
<?
|
||||
// Инициализация
|
||||
$targetUrl = '/profile/monitoring';
|
||||
|
||||
if ('/' . yii::$app->request->pathInfo === $targetUrl) {
|
||||
// Запрошена эта страница
|
||||
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white button_white_hover px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-eye my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Мониторинг</span></a>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-eye my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Мониторинг</span></a>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
</dt>
|
||||
<dt>
|
||||
<?
|
||||
// Инициализация
|
||||
$targetUrl = '/profile';
|
||||
|
||||
if ('/' . yii::$app->request->pathInfo === $targetUrl) {
|
||||
// Запрошена эта страница
|
||||
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white button_white_hover px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-sliders-h my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Настройки</span></a>
|
||||
HTML;
|
||||
} else {
|
||||
echo <<<HTML
|
||||
<a class="row text-dark button_white px-3 py-3 py-lg-2 font-weight-normal" href="$targetUrl"><i class="fas fa-sliders-h my-auto mx-auto mx-lg-0 col-1 pl-0 mr-lg-2"></i><span>Настройки</span></a>
|
||||
HTML;
|
||||
}
|
||||
?>
|
||||
</dt>
|
||||
</dl>
|
||||
<div class="dropdown-divider my-3"></div>
|
||||
<div class="row px-3">
|
||||
<p class="ml-0">Загрузок с аккаунта:</p>
|
||||
<p class="mr-0"><?= AccountEdgeSupply::readAmount() ?></p>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<p class="ml-0">Товары:</p>
|
||||
<p class="mr-0"><?= Product::readAmount() ?></p>
|
||||
|
@ -31,4 +109,8 @@ use app\models\Supply;
|
|||
<p class="ml-0">Поставки:</p>
|
||||
<p class="mr-0"><?= Supply::readAmount() ?></p>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<p class="ml-0">Связано поставок:</p>
|
||||
<p class="mr-0"><?= SupplyEdgeProduct::readAmount() ?></p>
|
||||
</div>
|
||||
</div>
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
|
||||
use app\controllers\ProfileController;
|
||||
|
@ -13,7 +14,7 @@ use app\models\Supply;
|
|||
<div id="page_profile" class="container h-100">
|
||||
<div class="row h-100 py-3">
|
||||
<nav class="col-3">
|
||||
<?= $sidebar ?? Yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
<?= $sidebar ?? yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
</nav>
|
||||
<article class="col-9">
|
||||
<div class="h-100 p-4 rounded">
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use yii;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use yii\helpers\Html;
|
||||
|
||||
use app\models\Notification;
|
||||
use app\models\Settings;
|
||||
|
||||
?>
|
||||
<link href="/css/pages/profile.css" rel="stylesheet">
|
||||
|
||||
<div id="page_profile" class="container h-100">
|
||||
<div class="row h-100 py-3">
|
||||
<nav class="col-3">
|
||||
<?= $sidebar ?? yii::$app->controller->renderPartial('/profile/sidebar') ?>
|
||||
</nav>
|
||||
<article class="col-9">
|
||||
<div class="p-4 rounded">
|
||||
<h4 class="ml-4 mb-4"><i class="fas fa-user-shield my-auto mr-2"></i>Панель управления</h4>
|
||||
<div id="profile_panel_trusted" class="profile_panel">
|
||||
<div class="profile_panel_menu mb-3">
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_trusted_input_notifications">Уведомления</label>
|
||||
<label class="btn button_white mb-0 mr-2" for="profile_panel_trusted_input_settings">Настройки</label>
|
||||
</div>
|
||||
<div class="profile_panel_content">
|
||||
<input type="radio" id="profile_panel_trusted_input_notifications" name="main_panel" />
|
||||
<div class="col">
|
||||
<h5>Отправка уведомления</h5>
|
||||
<div class="dropdown-divider mb-3"></div>
|
||||
<?
|
||||
$form = ActiveForm::begin([
|
||||
'id' => 'form_profile_trusted_notifications',
|
||||
'action' => false,
|
||||
'fieldConfig' => [
|
||||
'template' => '{label}{input}'
|
||||
],
|
||||
'options' => [
|
||||
'onsubmit' => 'return false;'
|
||||
]
|
||||
]);
|
||||
|
||||
// Значения по умолчанию
|
||||
isset($model_notifications) or $model_notifications = new Notification;
|
||||
isset($model_notifications->trgt) or $model_notifications->trgt = null;
|
||||
isset($model_notifications->text) or $model_notifications->text = '';
|
||||
?>
|
||||
|
||||
<?= $form->errorSummary($model_notifications) ?>
|
||||
|
||||
<div class="row">
|
||||
<?= $form->field($model_notifications, 'trgt', ['options' => ['class' => "mb-1 col-9"]])->input('text', ['placeholder' => yii::$app->user->identity->_key]); ?>
|
||||
<?= $form->field($model_notifications, 'type', ['options' => ['class' => "col pl-0"]])->dropDownList($model_notifications->typs); ?>
|
||||
</div>
|
||||
<small class="d-block mb-1"><b>Множественная отправка:</b> @all или перечислить через запятую</small>
|
||||
<small class="d-block mb-3"><b>Тестирование:</b> @test или оставить поле пустым</small>
|
||||
|
||||
<?= $form->field($model_notifications, 'text', ['options' => ['class' => "mb-3"]])->textarea(); ?>
|
||||
|
||||
<?= Html::submitButton('Отправить', ['name' => 'submitNotification', 'onclick' => 'page_profile_trusted_notification_create(this.parentElement);', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
|
||||
<?= Html::submitButton('Отправить как HTML', ['name' => 'submitNotification', 'onclick' => 'page_profile_trusted_notification_create(this.parentElement, 1);', 'class' => 'flex-grow-1 mr-2 btn button_white button_clean']) ?>
|
||||
|
||||
<? ActiveForm::end(); ?>
|
||||
</div>
|
||||
<input type="radio" id="profile_panel_trusted_input_settings" name="main_panel" checked />
|
||||
<div class="col">
|
||||
<?
|
||||
$form = ActiveForm::begin([
|
||||
'id' => 'form_profile_trusted_settings_search_period',
|
||||
'action' => false,
|
||||
'fieldConfig' => [
|
||||
'template' => '{label}{input}',
|
||||
],
|
||||
'options' => [
|
||||
'onsubmit' => 'return false;',
|
||||
'class' => 'mb-4'
|
||||
]
|
||||
]);
|
||||
?>
|
||||
|
||||
<?= $form->errorSummary($model_settings, ['header' => 'Получены ошибки:']) ?>
|
||||
|
||||
<?= $form->field($model_settings, 'search_period', ['options' => ['class' => "mb-1"]])->textInput(['value' => $model_settings['search_period'], 'onChange' => 'page_profile_trusted_settings(this.parentElement.parentElement)']); ?>
|
||||
<small class="d-block mb-1">Время которое надо ждать для повторного поиска в секундах</small>
|
||||
|
||||
<? ActiveForm::end(); ?>
|
||||
|
||||
<?
|
||||
$form = ActiveForm::begin([
|
||||
'id' => 'form_profile_trusted_settings_search_connect_keep',
|
||||
'action' => false,
|
||||
'fieldConfig' => [
|
||||
'template' => '{label}{input}',
|
||||
],
|
||||
'options' => [
|
||||
'onsubmit' => 'return false;'
|
||||
]
|
||||
]);
|
||||
|
||||
$list = ['false' => 'Нет', 'true' => 'Да'];
|
||||
|
||||
if (isset($model_settings->search_connect_keep)) {
|
||||
// Найден ранее записанный параметр
|
||||
|
||||
if (isset($list[$model_settings->search_connect_keep])) {
|
||||
// Совпадение параметра с параметрами списка найдено
|
||||
|
||||
// Буфер для сохранения параметра
|
||||
$buffer = $list[$model_settings->search_connect_keep];
|
||||
|
||||
// Удаление параметра
|
||||
unset($list[$model_settings->search_connect_keep]);
|
||||
|
||||
// Сохранение параметра в начале массива
|
||||
$list = array_merge([$model_settings->search_connect_keep => $buffer], $list);
|
||||
} else {
|
||||
// Совпадение параметра с параметрами списка не найдено
|
||||
|
||||
// Сохранение параметра из данных аккаунта в начале массива
|
||||
$list = array_merge([$model_settings->search_connect_keep => $model_settings->search_connect_keep], $list);
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<?= $form->field($model_settings, 'search_connect_keep', ['options' => ['class' => "mb-1"]])->dropDownList($list, ['onChange' => 'page_profile_trusted_settings(this.parentElement.parentElement)']); ?>
|
||||
<small class="d-block mb-1">Удерживать открытое соединение до истечения срока блокировки поиска?</small>
|
||||
<small class="d-block mb-1">При малой задержке позволяет снизить время загрузки страницы, но при большой будет казаться, что сайт завис</small>
|
||||
|
||||
<? ActiveForm::end(); ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/profile.js" defer></script>
|
||||
<script src="/js/profile_trusted.js" defer></script>
|
|
@ -8,32 +8,71 @@
|
|||
</div>
|
||||
</nav>
|
||||
<article class="col-9">
|
||||
<div class="row p-3 rounded">
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<div class="row mx-0 p-3 rounded">
|
||||
<?php
|
||||
if (isset($timer) && $timer > 0) {
|
||||
echo <<<HTML
|
||||
<p class="d-flex justify-content-center mb-3">Слишком частые запросы, повторите попытку через: $timer секунд</p>
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="px-2 mb-1 text-center d-flex justify-content-center">Слишком частые запросы, повторите попытку через: $timer секунд</p>
|
||||
<small class="mb-3 text-center d-flex justify-content-center">Подождите или нажмите на кнопку вручную</small>
|
||||
<a class="btn text-white button_clean button_blue mx-auto" onclick="window.location.reload();">Повторить</a>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
setTimeout('window.location.reload()', $timer + '000');
|
||||
</script>
|
||||
HTML;
|
||||
} else {
|
||||
if (isset($response) && is_array($response) && $response) {
|
||||
|
||||
$i = 0;
|
||||
$amount = count($response);
|
||||
|
||||
if (isset($response) && $response) {
|
||||
foreach ($response as $row) {
|
||||
$id = $row['id'];
|
||||
$catn = $row['catn'];
|
||||
$covr = $row['covr'] ?? '/img/covers/h150/product.png';
|
||||
$amnt = $row['amnt'] ?? 1;
|
||||
|
||||
|
||||
// <button class="button_clean_full d-flex p-0">
|
||||
// <i class="fas fa-plus-square search_card_cart_icon my-auto"></i>
|
||||
// </button>
|
||||
|
||||
echo <<<HTML
|
||||
<a class="dropdown-item button_white text-dark" href="/product/$id">$catn</a>
|
||||
<div class="col-3 p-2 d-flex flex-column search_card rounded">
|
||||
<div class="col">
|
||||
<div class="row mb-2">
|
||||
<img class="w-100 img-fluid rounded" src="$covr"/>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<a class="mx-auto text-dark" href="/product/$catn"><h5 class="m-0">$catn</h5></a>
|
||||
</div>
|
||||
<div class="row px-2 mb-2">
|
||||
<small class="mt-auto">{$amnt}шт</small>
|
||||
<p class="mr-0">1000р</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button class="btn button_grey button_clean w-100 text-white">В корзину</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML;
|
||||
|
||||
if (++$i % 4 === 0 && $amount - $i !== 0) {
|
||||
echo <<<HTML
|
||||
<div class="dropdown-divider my-3 mx-4 w-100 "></div>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo '<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>';
|
||||
echo <<<HTML
|
||||
<div class="d-flex flex-column mx-auto">
|
||||
<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
|
@ -1,22 +1,38 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
use yii\bootstrap\ActiveForm;
|
||||
use app\models\AccountForm;
|
||||
declare(strict_types=1);
|
||||
|
||||
// var_dump($response);
|
||||
use app\models\Search;
|
||||
|
||||
if (isset($history) && $history) {
|
||||
// Отображение истории
|
||||
|
||||
if (!yii::$app->user->isGuest && $rows = Search::searchByAccount(sort: ['DESC'])) {
|
||||
// История поиска существует
|
||||
|
||||
foreach ($rows as $row) {
|
||||
// Инициализация
|
||||
$date = date('H:i d.m.Y', $row->date);
|
||||
|
||||
echo <<<HTML
|
||||
<a class="dropdown-item d-flex button_white text-dark" href="/search?type=product&q=$row->text">$row->text<span class="ml-auto">$date</span></a>
|
||||
HTML;
|
||||
}
|
||||
}
|
||||
} else if (isset($response) && $response) {
|
||||
// Ответ получен
|
||||
|
||||
if (isset($response) && $response) {
|
||||
foreach ($response as $row) {
|
||||
$id = $row['id'];
|
||||
// Перебор найденных данных
|
||||
|
||||
$catn = $row['catn'];
|
||||
|
||||
echo <<<HTML
|
||||
<a class="dropdown-item button_white text-dark" href="/product/$id">$catn</a>
|
||||
<a class="dropdown-item button_white text-dark" href="/product/$catn">$catn</a>
|
||||
HTML;
|
||||
}
|
||||
} else {
|
||||
echo '<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>';
|
||||
echo <<<HTML
|
||||
<p class="m-0 py-2 d-flex justify-content-center">Ничего не найдено</p>
|
||||
HTML;
|
||||
}
|
||||
|
||||
?>
|
|
@ -1,7 +1,7 @@
|
|||
/*!
|
||||
* Bootstrap Grid v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Bootstrap Grid v4.6.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
html {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*!
|
||||
* Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Bootstrap Reboot v4.6.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
|
@ -24,7 +24,7 @@ article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
|||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
@ -198,9 +198,8 @@ button {
|
|||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/*!
|
||||
* Bootstrap Reboot v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Bootstrap Reboot v4.6.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus:not(:focus-visible){outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([class]){color:inherit;text-decoration:none}a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit;text-align:-webkit-match-parent}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
|
@ -1,7 +1,7 @@
|
|||
/*!
|
||||
* Bootstrap v4.5.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Bootstrap v4.6.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
:root {
|
||||
|
@ -31,7 +31,7 @@
|
|||
--breakpoint-md: 768px;
|
||||
--breakpoint-lg: 992px;
|
||||
--breakpoint-xl: 1200px;
|
||||
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
|
|||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
@ -228,9 +228,8 @@ button {
|
|||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px dotted;
|
||||
outline: 5px auto -webkit-focus-ring-color;
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
|
@ -2241,6 +2240,11 @@ textarea.form-control {
|
|||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.form-row > .col > .valid-tooltip,
|
||||
.form-row > [class*="col-"] > .valid-tooltip {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.was-validated :valid ~ .valid-feedback,
|
||||
.was-validated :valid ~ .valid-tooltip,
|
||||
.is-valid ~ .valid-feedback,
|
||||
|
@ -2270,7 +2274,7 @@ textarea.form-control {
|
|||
.was-validated .custom-select:valid, .custom-select.is-valid {
|
||||
border-color: #28a745;
|
||||
padding-right: calc(0.75em + 2.3125rem);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8'%3e%3cpath fill='%2328a745' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat;
|
||||
}
|
||||
|
||||
.was-validated .custom-select:valid:focus, .custom-select.is-valid:focus {
|
||||
|
@ -2342,6 +2346,11 @@ textarea.form-control {
|
|||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.form-row > .col > .invalid-tooltip,
|
||||
.form-row > [class*="col-"] > .invalid-tooltip {
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.was-validated :invalid ~ .invalid-feedback,
|
||||
.was-validated :invalid ~ .invalid-tooltip,
|
||||
.is-invalid ~ .invalid-feedback,
|
||||
|
@ -2371,7 +2380,7 @@ textarea.form-control {
|
|||
.was-validated .custom-select:invalid, .custom-select.is-invalid {
|
||||
border-color: #dc3545;
|
||||
padding-right: calc(0.75em + 2.3125rem);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px, url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") #fff no-repeat center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem);
|
||||
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat, #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%23dc3545' viewBox='0 0 12 12'%3e%3ccircle cx='6' cy='6' r='4.5'/%3e%3cpath stroke-linejoin='round' d='M5.8 3.6h.4L6 6.5z'/%3e%3ccircle cx='6' cy='8.2' r='.6' fill='%23dc3545' stroke='none'/%3e%3c/svg%3e") center right 1.75rem/calc(0.75em + 0.375rem) calc(0.75em + 0.375rem) no-repeat;
|
||||
}
|
||||
|
||||
.was-validated .custom-select:invalid:focus, .custom-select.is-invalid:focus {
|
||||
|
@ -3388,7 +3397,7 @@ input[type="button"].btn-block {
|
|||
.dropdown-item:hover, .dropdown-item:focus {
|
||||
color: #16181b;
|
||||
text-decoration: none;
|
||||
background-color: #f8f9fa;
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.dropdown-item.active, .dropdown-item:active {
|
||||
|
@ -3398,7 +3407,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
.dropdown-item.disabled, .dropdown-item:disabled {
|
||||
color: #6c757d;
|
||||
color: #adb5bd;
|
||||
pointer-events: none;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
@ -3597,12 +3606,6 @@ input[type="button"].btn-block {
|
|||
z-index: 4;
|
||||
}
|
||||
|
||||
.input-group > .form-control:not(:last-child),
|
||||
.input-group > .custom-select:not(:last-child) {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.input-group > .form-control:not(:first-child),
|
||||
.input-group > .custom-select:not(:first-child) {
|
||||
border-top-left-radius: 0;
|
||||
|
@ -3617,14 +3620,23 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
.input-group > .custom-file:not(:last-child) .custom-file-label,
|
||||
.input-group > .custom-file:not(:last-child) .custom-file-label::after {
|
||||
.input-group > .custom-file:not(:first-child) .custom-file-label {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.input-group:not(.has-validation) > .form-control:not(:last-child),
|
||||
.input-group:not(.has-validation) > .custom-select:not(:last-child),
|
||||
.input-group:not(.has-validation) > .custom-file:not(:last-child) .custom-file-label::after {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.input-group > .custom-file:not(:first-child) .custom-file-label {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
.input-group.has-validation > .form-control:nth-last-child(n + 3),
|
||||
.input-group.has-validation > .custom-select:nth-last-child(n + 3),
|
||||
.input-group.has-validation > .custom-file:nth-last-child(n + 3) .custom-file-label::after {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.input-group-prepend,
|
||||
|
@ -3727,8 +3739,10 @@ input[type="button"].btn-block {
|
|||
|
||||
.input-group > .input-group-prepend > .btn,
|
||||
.input-group > .input-group-prepend > .input-group-text,
|
||||
.input-group > .input-group-append:not(:last-child) > .btn,
|
||||
.input-group > .input-group-append:not(:last-child) > .input-group-text,
|
||||
.input-group:not(.has-validation) > .input-group-append:not(:last-child) > .btn,
|
||||
.input-group:not(.has-validation) > .input-group-append:not(:last-child) > .input-group-text,
|
||||
.input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .btn,
|
||||
.input-group.has-validation > .input-group-append:nth-last-child(n + 3) > .input-group-text,
|
||||
.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),
|
||||
.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {
|
||||
border-top-right-radius: 0;
|
||||
|
@ -3825,7 +3839,7 @@ input[type="button"].btn-block {
|
|||
width: 1rem;
|
||||
height: 1rem;
|
||||
content: "";
|
||||
background: no-repeat 50% / 50% 50%;
|
||||
background: 50% / 50% 50% no-repeat;
|
||||
}
|
||||
|
||||
.custom-checkbox .custom-control-label::before {
|
||||
|
@ -3914,7 +3928,7 @@ input[type="button"].btn-block {
|
|||
line-height: 1.5;
|
||||
color: #495057;
|
||||
vertical-align: middle;
|
||||
background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") no-repeat right 0.75rem center/8px 10px;
|
||||
background: #fff url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='4' height='5' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right 0.75rem center/8px 10px no-repeat;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.25rem;
|
||||
-webkit-appearance: none;
|
||||
|
@ -3983,6 +3997,7 @@ input[type="button"].btn-block {
|
|||
width: 100%;
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
@ -4012,6 +4027,7 @@ input[type="button"].btn-block {
|
|||
z-index: 1;
|
||||
height: calc(1.5em + 0.75rem + 2px);
|
||||
padding: 0.375rem 0.75rem;
|
||||
overflow: hidden;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #495057;
|
||||
|
@ -4048,7 +4064,7 @@ input[type="button"].btn-block {
|
|||
}
|
||||
|
||||
.custom-range:focus {
|
||||
outline: none;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.custom-range:focus::-webkit-slider-thumb {
|
||||
|
@ -4243,11 +4259,8 @@ input[type="button"].btn-block {
|
|||
border-bottom: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-item {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
margin-bottom: -1px;
|
||||
border: 1px solid transparent;
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
|
@ -4403,8 +4416,12 @@ input[type="button"].btn-block {
|
|||
height: 1.5em;
|
||||
vertical-align: middle;
|
||||
content: "";
|
||||
background: no-repeat center center;
|
||||
background-size: 100% 100%;
|
||||
background: 50% / 100% 100% no-repeat;
|
||||
}
|
||||
|
||||
.navbar-nav-scroll {
|
||||
max-height: 75vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
|
@ -4438,6 +4455,9 @@ input[type="button"].btn-block {
|
|||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.navbar-expand-sm .navbar-nav-scroll {
|
||||
overflow: visible;
|
||||
}
|
||||
.navbar-expand-sm .navbar-collapse {
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
|
@ -4480,6 +4500,9 @@ input[type="button"].btn-block {
|
|||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.navbar-expand-md .navbar-nav-scroll {
|
||||
overflow: visible;
|
||||
}
|
||||
.navbar-expand-md .navbar-collapse {
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
|
@ -4522,6 +4545,9 @@ input[type="button"].btn-block {
|
|||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.navbar-expand-lg .navbar-nav-scroll {
|
||||
overflow: visible;
|
||||
}
|
||||
.navbar-expand-lg .navbar-collapse {
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
|
@ -4564,6 +4590,9 @@ input[type="button"].btn-block {
|
|||
-ms-flex-wrap: nowrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.navbar-expand-xl .navbar-nav-scroll {
|
||||
overflow: visible;
|
||||
}
|
||||
.navbar-expand-xl .navbar-collapse {
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
|
@ -4608,6 +4637,10 @@ input[type="button"].btn-block {
|
|||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.navbar-expand .navbar-nav-scroll {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.navbar-expand .navbar-collapse {
|
||||
display: -ms-flexbox !important;
|
||||
display: flex !important;
|
||||
|
@ -4972,17 +5005,12 @@ input[type="button"].btn-block {
|
|||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
padding-right: 0.5rem;
|
||||
color: #6c757d;
|
||||
content: "/";
|
||||
|
@ -5465,8 +5493,8 @@ a.badge-dark:focus, a.badge-dark.focus {
|
|||
}
|
||||
|
||||
.progress-bar-animated {
|
||||
-webkit-animation: progress-bar-stripes 1s linear infinite;
|
||||
animation: progress-bar-stripes 1s linear infinite;
|
||||
-webkit-animation: 1s linear infinite progress-bar-stripes;
|
||||
animation: 1s linear infinite progress-bar-stripes;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
@ -6145,7 +6173,7 @@ a.close.disabled {
|
|||
z-index: 1070;
|
||||
display: block;
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
@ -6258,7 +6286,7 @@ a.close.disabled {
|
|||
z-index: 1060;
|
||||
display: block;
|
||||
max-width: 276px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
|
@ -6546,7 +6574,7 @@ a.close.disabled {
|
|||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: no-repeat 50% / 100% 100%;
|
||||
background: 50% / 100% 100% no-repeat;
|
||||
}
|
||||
|
||||
.carousel-control-prev-icon {
|
||||
|
@ -6635,8 +6663,8 @@ a.close.disabled {
|
|||
border: 0.25em solid currentColor;
|
||||
border-right-color: transparent;
|
||||
border-radius: 50%;
|
||||
-webkit-animation: spinner-border .75s linear infinite;
|
||||
animation: spinner-border .75s linear infinite;
|
||||
-webkit-animation: .75s linear infinite spinner-border;
|
||||
animation: .75s linear infinite spinner-border;
|
||||
}
|
||||
|
||||
.spinner-border-sm {
|
||||
|
@ -6677,8 +6705,8 @@ a.close.disabled {
|
|||
background-color: currentColor;
|
||||
border-radius: 50%;
|
||||
opacity: 0;
|
||||
-webkit-animation: spinner-grow .75s linear infinite;
|
||||
animation: spinner-grow .75s linear infinite;
|
||||
-webkit-animation: .75s linear infinite spinner-grow;
|
||||
animation: .75s linear infinite spinner-grow;
|
||||
}
|
||||
|
||||
.spinner-grow-sm {
|
||||
|
@ -6686,6 +6714,14 @@ a.close.disabled {
|
|||
height: 1rem;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.spinner-border,
|
||||
.spinner-grow {
|
||||
-webkit-animation-duration: 1.5s;
|
||||
animation-duration: 1.5s;
|
||||
}
|
||||
}
|
||||
|
||||
.align-baseline {
|
||||
vertical-align: baseline !important;
|
||||
}
|
||||
|
@ -7954,7 +7990,6 @@ button.bg-dark:focus {
|
|||
.user-select-all {
|
||||
-webkit-user-select: all !important;
|
||||
-moz-user-select: all !important;
|
||||
-ms-user-select: all !important;
|
||||
user-select: all !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,10 @@ nav {
|
|||
margin-bottom: .5rem;
|
||||
}
|
||||
|
||||
#profile_button_panel {
|
||||
z-index: 1500;
|
||||
}
|
||||
|
||||
.h-divider {
|
||||
border-bottom: 4px solid #123EAB;
|
||||
}
|
||||
|
@ -55,7 +59,8 @@ nav {
|
|||
background-color : #ebe9f2;
|
||||
}
|
||||
|
||||
.catalog_button:active, .catalog_button:focus {
|
||||
.catalog_button:active,
|
||||
.catalog_button:focus {
|
||||
border : 1px solid #7b7587;
|
||||
/* background-color: #402d82; */
|
||||
background-color : #d7d4dd;
|
||||
|
@ -97,12 +102,15 @@ nav {
|
|||
display: none;
|
||||
}
|
||||
|
||||
#searchPanel input[type=radio]+label:active, #searchPanel input[type=radio]:checked+label:active {
|
||||
#searchPanel input[type=radio]+label:active,
|
||||
#searchPanel input[type=radio]:checked+label:active {
|
||||
border-bottom : none;
|
||||
background-color: #d7d4dd;
|
||||
}
|
||||
|
||||
#searchPanel input[type=radio]:checked+label, #searchPanel input[type=radio]:checked:hover+label, #searchPanel input[type=radio]:checked:active+label {
|
||||
#searchPanel input[type=radio]:checked+label,
|
||||
#searchPanel input[type=radio]:checked:hover+label,
|
||||
#searchPanel input[type=radio]:checked:active+label {
|
||||
color : #ffffff;
|
||||
background-color: #123EAB;
|
||||
}
|
||||
|
@ -143,55 +151,48 @@ nav {
|
|||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.logotype {
|
||||
display: none !important;
|
||||
}
|
||||
.catalog_search {
|
||||
flex-direction: column;
|
||||
}
|
||||
.catalog_search_line {
|
||||
max-width: 100%;
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
}
|
||||
|
||||
.catalog_search_button {
|
||||
border-radius: 0px 0px 3px 3px;
|
||||
margin: .8rem 0 0 0;
|
||||
height: auto;
|
||||
line-height: 200%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Малые девайсы («ландшафтные телефоны», >= 576px) */
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.tagline {
|
||||
|
||||
#logo,
|
||||
.tagline,
|
||||
.h-divider {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#searchPanel label {
|
||||
width : 100%;
|
||||
text-align: center;
|
||||
}
|
||||
#searchPanel label:not(:nth-child(2)) {
|
||||
border-radius: 0;
|
||||
}
|
||||
.catalog_search {
|
||||
border-radius: 0px 0px 5px 5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Средние девайсы («таблетки», >= 768px) */
|
||||
|
||||
@media (max-width: 768px) {}
|
||||
@media (max-width: 768px) {
|
||||
.dropdownMenuButton_column {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Большие девайсы (десктопы, >= 992px) */
|
||||
|
||||
@media (max-width: 992px) {
|
||||
.h-divider {
|
||||
margin-top: 15px;
|
||||
}
|
||||
.h-divider div {
|
||||
display: none !important;
|
||||
}
|
||||
.dropdownMenuButton_column {
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
#dropdownMenuButton p {
|
||||
display: none;
|
||||
}
|
||||
|
@ -199,4 +200,8 @@ nav {
|
|||
|
||||
/* Экстрабольшие девайсы (большие десктопы, >= 1200px) */
|
||||
|
||||
@media (max-width: 1200px) {}
|
||||
@media (max-width: 1200px) {
|
||||
.h-title>* {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
|
@ -8,6 +8,10 @@
|
|||
font-family: 'Open Sans';
|
||||
}
|
||||
|
||||
*:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
@ -36,25 +40,84 @@ main {
|
|||
background-color: #f0eefb;
|
||||
}
|
||||
|
||||
.button_clean, .button_clean:hover, .button_clean:focus, .button_clean:active {
|
||||
outline: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.inactive, .inactive:hover, .inactive:focus, .inactive:active {
|
||||
.inactive,
|
||||
.inactive:hover,
|
||||
.inactive:focus,
|
||||
.inactive:active {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.button_blue {
|
||||
.button_clean,
|
||||
.button_clean:hover,
|
||||
.button_clean:focus,
|
||||
.button_clean:active,
|
||||
.button_clean_full,
|
||||
.button_clean_full:hover,
|
||||
.button_clean_full:focus,
|
||||
.button_clean_full:active {
|
||||
outline : none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.button_clean_full,
|
||||
.button_clean_full:hover,
|
||||
.button_clean_full:focus,
|
||||
.button_clean_full:active {
|
||||
border : none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.button_blue_simple {
|
||||
color : #eee;
|
||||
background-color: #123EAB;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_blue_simple:hover {
|
||||
color : #fff;
|
||||
transition: 0s;
|
||||
}
|
||||
|
||||
.button_blue_simple:active {
|
||||
color : #ddd;
|
||||
background-color: #391e97;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_blue {
|
||||
color : #eee;
|
||||
background-color: #123EAB;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_blue:hover {
|
||||
background-color: #1b4bc4;
|
||||
color : #fff;
|
||||
background-color: #244db5;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_blue:active {
|
||||
background-color: #402d82;
|
||||
color : #ddd;
|
||||
background-color: #391e97;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_red {
|
||||
color : #eee;
|
||||
background-color: #ab1212;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_red:hover {
|
||||
color : #fff;
|
||||
background-color: #b52424;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_red:active {
|
||||
color : #ddd;
|
||||
background-color: #971e1e;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_white {
|
||||
|
@ -63,10 +126,31 @@ main {
|
|||
|
||||
.button_white:hover {
|
||||
background-color: #eaebee;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_white:active {
|
||||
background-color: #cfd3dd;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_white_hover {
|
||||
background-color: #eaebee !important;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_grey {
|
||||
background-color: #b4bbcc;
|
||||
}
|
||||
|
||||
.button_grey:hover {
|
||||
background-color: #a6aebf;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.button_grey:active {
|
||||
background-color: #8c94a8;
|
||||
transition : 0s;
|
||||
}
|
||||
|
||||
.d-inline-block {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
#notifications_popup_wrap>.notification {
|
||||
min-height : 100px;
|
||||
border : 1px solid #a39bb1;
|
||||
background-color: #fff;
|
||||
opacity: 0;
|
||||
transition: .3s;
|
||||
}
|
||||
|
||||
#notifications_popup_wrap {
|
||||
z-index : 100;
|
||||
bottom : 0;
|
||||
position: fixed;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#notification_button_panel {
|
||||
z-index: 2500;
|
||||
min-width: 250px;
|
||||
}
|
|
@ -1,3 +1,33 @@
|
|||
#page_product nav > div, #page_product article > div {
|
||||
#page_product nav>div,
|
||||
#page_product article>div {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_image>div,
|
||||
#page_product #product_slider>.product_slider_image>input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_image>input:checked+div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_image {
|
||||
max-width: 25vw;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label {
|
||||
border : none;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label:hover>img {
|
||||
cursor: pointer;
|
||||
filter: brightness(0.9) contrast(1.1);
|
||||
}
|
||||
|
||||
#page_product #product_slider>.product_slider_preview>label:active>img,
|
||||
#page_product #product_slider>.product_slider_preview>label:focus>img {
|
||||
cursor: pointer;
|
||||
filter: brightness(0.8) contrast(1.3);
|
||||
}
|
|
@ -1,3 +1,72 @@
|
|||
#page_profile nav > div, #page_profile article > div {
|
||||
#page_profile nav>div,
|
||||
#page_profile article>div {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content {
|
||||
flex-grow : 1;
|
||||
border-radius: 0 3px 3px 3px;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>div,
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>input:checked+div {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>div>.header_blue {
|
||||
background-color: #123EAB;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>div>.header_blue~.row:nth-child(2n) {
|
||||
background-color: #f0f5ff;
|
||||
}
|
||||
|
||||
#page_profile [id^=profile_panel_]>.profile_panel_content>div>.header_blue~.row:nth-child(2n + 1) {
|
||||
background-color: #e7edf9;
|
||||
}
|
||||
|
||||
/* Экстрабольшие девайсы (большие десктопы, >= 1200px) */
|
||||
|
||||
@media (max-width: 1199px) {
|
||||
#page_profile nav dl>dt>a>i {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Большие девайсы (десктопы, >= 992px) */
|
||||
|
||||
@media (max-width: 991px) {
|
||||
#page_profile nav dl>dt>a>span {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#page_profile nav dl>dt>a>i {
|
||||
display: inherit !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* Средние девайсы («таблетки», >= 768px) */
|
||||
|
||||
/* @media (max-width: 768px) {} */
|
||||
|
||||
/* Малые девайсы («ландшафтные телефоны», >= 576px) */
|
||||
|
||||
@media (max-width: 576px) {
|
||||
#page_profile article h4 {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#page_profile #profile_panel_monitoring>.profile_panel_content>div>div>div:first-child {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
#page_profile #profile_panel_monitoring>.profile_panel_content>div>div:last-child>div:first-child {
|
||||
display: flex !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* @media (max-width: 400px) {} */
|
|
@ -1,3 +1,15 @@
|
|||
#page_search nav > div, #page_search article > div {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#page_search .search_card:hover {
|
||||
background-color: #eaeaf0;
|
||||
}
|
||||
|
||||
#page_search .search_card:hover img {
|
||||
border: 1px solid #e1e1ea;
|
||||
}
|
||||
|
||||
#page_search .search_card .search_card_cart_icon {
|
||||
font-size: larger;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/supplies
|
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 980 B |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 588 B |
After Width: | Height: | Size: 780 B |
After Width: | Height: | Size: 781 B |