From 5e01240938c215bfadf6d5d9ea2cb60dfa0bddba Mon Sep 17 00:00:00 2001 From: Arsen Mirzaev Tatyano-Muradovich Date: Mon, 9 Aug 2021 23:48:43 +1000 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=20=D1=81=D0=B0=D0=B9=D1=82=D0=BE=D0=BC=20228?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 1 + composer.lock | 273 +- .../system/config/params.php.example | 23 +- .../skillparts/system/config/web.php.example | 4 +- .../system/controllers/OrderController.php | 51 +- .../system/controllers/ProfileController.php | 338 ++- .../system/controllers/SearchController.php | 9 +- mirzaev/skillparts/system/models/Account.php | 3 +- mirzaev/skillparts/system/models/Edge.php | 6 +- mirzaev/skillparts/system/models/Order.php | 309 ++- mirzaev/skillparts/system/models/Product.php | 1 + mirzaev/skillparts/system/models/Supply.php | 14 + mirzaev/skillparts/system/models/Terminal.php | 35 +- .../system/models/connection/Dellin.php | 2 +- .../skillparts/system/views/account/index.php | 4 +- .../skillparts/system/views/cart/index.php | 218 +- .../skillparts/system/views/orders/index.php | 97 +- .../skillparts/system/views/search/index.php | 11 +- .../skillparts/system/web/css/datepicker.css | 622 +++++ mirzaev/skillparts/system/web/css/main.css | 72 +- .../system/web/js/calendar/datepicker.js | 2236 +++++++++++++++++ .../web/js/calendar/i18n/datepicker.cs.js | 12 + .../web/js/calendar/i18n/datepicker.da.js | 12 + .../web/js/calendar/i18n/datepicker.de.js | 13 + .../web/js/calendar/i18n/datepicker.en.js | 12 + .../web/js/calendar/i18n/datepicker.es.js | 12 + .../web/js/calendar/i18n/datepicker.fi.js | 13 + .../web/js/calendar/i18n/datepicker.fr.js | 12 + .../web/js/calendar/i18n/datepicker.hu.js | 12 + .../web/js/calendar/i18n/datepicker.nl.js | 12 + .../web/js/calendar/i18n/datepicker.pl.js | 13 + .../web/js/calendar/i18n/datepicker.pt-BR.js | 12 + .../web/js/calendar/i18n/datepicker.pt.js | 12 + .../web/js/calendar/i18n/datepicker.ro.js | 13 + .../web/js/calendar/i18n/datepicker.sk.js | 12 + .../web/js/calendar/i18n/datepicker.zh.js | 12 + mirzaev/skillparts/system/web/js/cart.js | 26 +- .../skillparts/system/web/js/geolocation.js | 51 +- mirzaev/skillparts/system/web/js/main.js | 5 +- mirzaev/skillparts/system/web/js/orders.js | 24 +- mirzaev/skillparts/system/web/js/profile.js | 12 +- 41 files changed, 4115 insertions(+), 516 deletions(-) create mode 100644 mirzaev/skillparts/system/web/css/datepicker.css create mode 100644 mirzaev/skillparts/system/web/js/calendar/datepicker.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.cs.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.da.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.de.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.en.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.es.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fi.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fr.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.hu.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.nl.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pl.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt-BR.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.ro.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.sk.js create mode 100644 mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.zh.js diff --git a/composer.json b/composer.json index 006cd4d..0c852c0 100644 --- a/composer.json +++ b/composer.json @@ -14,6 +14,7 @@ ], "require": { "php": "^8.0.0", + "ext-intl": "~8.0", "twbs/bootstrap": "4.6.0", "yiisoft/yii2": "2.*", "yiisoft/yii2-bootstrap": ">=2.0.0", diff --git a/composer.lock b/composer.lock index ba81eda..05d8352 100644 --- a/composer.lock +++ b/composer.lock @@ -4,14 +4,14 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "fcf19d2c1a3e56a85324e01a1c6c55ab", + "content-hash": "1a78355a6b4833b92796884bd4674b5d", "packages": [ { "name": "bower-asset/bootstrap", "version": "v3.4.1", "source": { "type": "git", - "url": "https://github.com/twbs/bootstrap.git", + "url": "git@github.com:twbs/bootstrap.git", "reference": "68b0d231a13201eb14acd3dc84e51543d16e5f7e" }, "dist": { @@ -53,7 +53,7 @@ "version": "3.5.1", "source": { "type": "git", - "url": "https://github.com/jquery/jquery-dist.git", + "url": "git@github.com:jquery/jquery-dist.git", "reference": "4c0e4becb8263bb5b3e6dadc448d8e7305ef8215" }, "dist": { @@ -71,7 +71,7 @@ "version": "v1.3.2", "source": { "type": "git", - "url": "https://github.com/bestiejs/punycode.js.git", + "url": "git@github.com:bestiejs/punycode.js.git", "reference": "38c8d3131a82567bfef18da09f7f4db68c84f8a3" }, "dist": { @@ -1063,7 +1063,7 @@ "source": { "type": "git", "url": "https://git.hood.su/mirzaev/yii2/arangodb", - "reference": "cbc26916ea54bb767306e4c2750e710b08eecc21" + "reference": "8c8d34f5b213b7d28b874f430f44b319baab3e83" }, "require": { "php": "^8.0.0", @@ -1105,7 +1105,7 @@ "ArangoDb", "yii2" ], - "time": "2021-04-11T19:27:43+00:00" + "time": "2021-07-25T19:29:30+00:00" }, { "name": "mirzaev/yii2-arangodb-sessions", @@ -1202,16 +1202,16 @@ }, { "name": "myclabs/php-enum", - "version": "1.8.0", + "version": "1.8.3", "source": { "type": "git", "url": "https://github.com/myclabs/php-enum.git", - "reference": "46cf3d8498b095bd33727b13fd5707263af99421" + "reference": "b942d263c641ddb5190929ff840c68f78713e937" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/php-enum/zipball/46cf3d8498b095bd33727b13fd5707263af99421", - "reference": "46cf3d8498b095bd33727b13fd5707263af99421", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937", + "reference": "b942d263c641ddb5190929ff840c68f78713e937", "shasum": "" }, "require": { @@ -1221,7 +1221,7 @@ "require-dev": { "phpunit/phpunit": "^9.5", "squizlabs/php_codesniffer": "1.*", - "vimeo/psalm": "^4.5.1" + "vimeo/psalm": "^4.6.2" }, "type": "library", "autoload": { @@ -1246,7 +1246,7 @@ ], "support": { "issues": "https://github.com/myclabs/php-enum/issues", - "source": "https://github.com/myclabs/php-enum/tree/1.8.0" + "source": "https://github.com/myclabs/php-enum/tree/1.8.3" }, "funding": [ { @@ -1258,7 +1258,7 @@ "type": "tidelift" } ], - "time": "2021-02-15T16:11:48+00:00" + "time": "2021-07-05T08:18:36+00:00" }, { "name": "npm-asset/jquery", @@ -1959,16 +1959,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1" + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/2df51500adbaebdc4c38dea4c89a2e131c45c8a1", - "reference": "2df51500adbaebdc4c38dea4c89a2e131c45c8a1", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6", + "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6", "shasum": "" }, "require": { @@ -2019,7 +2019,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1" }, "funding": [ { @@ -2035,7 +2035,7 @@ "type": "tidelift" } ], - "time": "2021-05-27T09:27:20+00:00" + "time": "2021-05-27T12:26:48+00:00" }, { "name": "symfony/polyfill-php72", @@ -2115,16 +2115,16 @@ }, { "name": "triagens/arangodb", - "version": "v3.6.0", + "version": "v3.8.0", "source": { "type": "git", "url": "https://github.com/arangodb/arangodb-php.git", - "reference": "d331f1a493772960c4d0e3d1fb753900eb181ce2" + "reference": "5104c4e2803d8b7fab97a0c80a3abe3f3ff3253e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/arangodb/arangodb-php/zipball/d331f1a493772960c4d0e3d1fb753900eb181ce2", - "reference": "d331f1a493772960c4d0e3d1fb753900eb181ce2", + "url": "https://api.github.com/repos/arangodb/arangodb-php/zipball/5104c4e2803d8b7fab97a0c80a3abe3f3ff3253e", + "reference": "5104c4e2803d8b7fab97a0c80a3abe3f3ff3253e", "shasum": "" }, "require": { @@ -2170,9 +2170,9 @@ ], "support": { "issues": "https://github.com/arangodb/arangodb-php/issues", - "source": "https://github.com/arangodb/arangodb-php/tree/v3.6.0" + "source": "https://github.com/arangodb/arangodb-php/tree/v3.8.0" }, - "time": "2019-12-02T13:11:34+00:00" + "time": "2021-06-18T12:06:02+00:00" }, { "name": "twbs/bootstrap", @@ -3383,16 +3383,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.14.1", + "version": "v1.15.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1" + "reference": "89c6201c74db25fa759ff16e78a4d8f32547770e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1", - "reference": "ed22aee8d17c7b396f74a58b1e7fefa4f90d5ef1", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/89c6201c74db25fa759ff16e78a4d8f32547770e", + "reference": "89c6201c74db25fa759ff16e78a4d8f32547770e", "shasum": "" }, "require": { @@ -3442,9 +3442,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v.1.14.1" + "source": "https://github.com/FakerPHP/Faker/tree/v1.15.0" }, - "time": "2021-03-30T06:27:33+00:00" + "time": "2021-07-06T20:39:40+00:00" }, { "name": "myclabs/deep-copy", @@ -3506,16 +3506,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.10.5", + "version": "v4.12.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f" + "reference": "6608f01670c3cc5079e18c1dab1104e002579143" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/4432ba399e47c66624bc73c8c0f811e5c109576f", - "reference": "4432ba399e47c66624bc73c8c0f811e5c109576f", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/6608f01670c3cc5079e18c1dab1104e002579143", + "reference": "6608f01670c3cc5079e18c1dab1104e002579143", "shasum": "" }, "require": { @@ -3556,9 +3556,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.5" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.12.0" }, - "time": "2021-05-03T19:11:20+00:00" + "time": "2021-07-21T10:44:31+00:00" }, { "name": "opis/closure", @@ -3627,16 +3627,16 @@ }, { "name": "phar-io/manifest", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/manifest.git", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133" + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/manifest/zipball/85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", - "reference": "85265efd3af7ba3ca4b2a2c34dbfc5788dd29133", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", "shasum": "" }, "require": { @@ -3681,9 +3681,9 @@ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", "support": { "issues": "https://github.com/phar-io/manifest/issues", - "source": "https://github.com/phar-io/manifest/tree/master" + "source": "https://github.com/phar-io/manifest/tree/2.0.3" }, - "time": "2020-06-27T14:33:11+00:00" + "time": "2021-07-20T11:28:43+00:00" }, { "name": "phar-io/version", @@ -4388,16 +4388,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.5", + "version": "9.5.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276" + "reference": "191768ccd5c85513b4068bdbe99bb6390c7d54fb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/89ff45ea9d70e35522fb6654a2ebc221158de276", - "reference": "89ff45ea9d70e35522fb6654a2ebc221158de276", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/191768ccd5c85513b4068bdbe99bb6390c7d54fb", + "reference": "191768ccd5c85513b4068bdbe99bb6390c7d54fb", "shasum": "" }, "require": { @@ -4409,7 +4409,7 @@ "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.10.1", - "phar-io/manifest": "^2.0.1", + "phar-io/manifest": "^2.0.3", "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", @@ -4427,7 +4427,7 @@ "sebastian/global-state": "^5.0.1", "sebastian/object-enumerator": "^4.0.3", "sebastian/resource-operations": "^3.0.3", - "sebastian/type": "^2.3.2", + "sebastian/type": "^2.3.4", "sebastian/version": "^3.0.2" }, "require-dev": { @@ -4475,7 +4475,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.5" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.8" }, "funding": [ { @@ -4487,7 +4487,7 @@ "type": "github" } ], - "time": "2021-06-05T04:49:07+00:00" + "time": "2021-07-31T15:17:34+00:00" }, { "name": "psr/container", @@ -5553,21 +5553,22 @@ }, { "name": "symfony/browser-kit", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "379984e25eee9811b0a25a2105e1a2b3b8d9b734" + "reference": "c1e3f64fcc631c96e2c5843b666db66679ced11c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/379984e25eee9811b0a25a2105e1a2b3b8d9b734", - "reference": "379984e25eee9811b0a25a2105e1a2b3b8d9b734", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/c1e3f64fcc631c96e2c5843b666db66679ced11c", + "reference": "c1e3f64fcc631c96e2c5843b666db66679ced11c", "shasum": "" }, "require": { "php": ">=7.2.5", - "symfony/dom-crawler": "^4.4|^5.0" + "symfony/dom-crawler": "^4.4|^5.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { "symfony/css-selector": "^4.4|^5.0", @@ -5604,7 +5605,7 @@ "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.3.0" + "source": "https://github.com/symfony/browser-kit/tree/v5.3.4" }, "funding": [ { @@ -5620,20 +5621,20 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-21T12:40:44+00:00" }, { "name": "symfony/console", - "version": "v5.3.0", + "version": "v5.3.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "058553870f7809087fa80fa734704a21b9bcaeb2" + "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/058553870f7809087fa80fa734704a21b9bcaeb2", - "reference": "058553870f7809087fa80fa734704a21b9bcaeb2", + "url": "https://api.github.com/repos/symfony/console/zipball/51b71afd6d2dc8f5063199357b9880cea8d8bfe2", + "reference": "51b71afd6d2dc8f5063199357b9880cea8d8bfe2", "shasum": "" }, "require": { @@ -5641,11 +5642,12 @@ "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", - "symfony/polyfill-php80": "^1.15", + "symfony/polyfill-php80": "^1.16", "symfony/service-contracts": "^1.1|^2", "symfony/string": "^5.1" }, "conflict": { + "psr/log": ">=3", "symfony/dependency-injection": "<4.4", "symfony/dotenv": "<5.1", "symfony/event-dispatcher": "<4.4", @@ -5653,10 +5655,10 @@ "symfony/process": "<4.4" }, "provide": { - "psr/log-implementation": "1.0" + "psr/log-implementation": "1.0|2.0" }, "require-dev": { - "psr/log": "~1.0", + "psr/log": "^1|^2", "symfony/config": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0", "symfony/event-dispatcher": "^4.4|^5.0", @@ -5702,7 +5704,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.3.0" + "source": "https://github.com/symfony/console/tree/v5.3.6" }, "funding": [ { @@ -5718,24 +5720,25 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-27T19:10:22+00:00" }, { "name": "symfony/css-selector", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814" + "reference": "7fb120adc7f600a59027775b224c13a33530dd90" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", - "reference": "fcd0b29a7a0b1bb5bfbedc6231583d77fea04814", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/7fb120adc7f600a59027775b224c13a33530dd90", + "reference": "7fb120adc7f600a59027775b224c13a33530dd90", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -5767,7 +5770,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.3.0" + "source": "https://github.com/symfony/css-selector/tree/v5.3.4" }, "funding": [ { @@ -5783,7 +5786,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:40:38+00:00" + "time": "2021-07-21T12:38:00+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5854,16 +5857,16 @@ }, { "name": "symfony/dom-crawler", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", - "reference": "55fff62b19f413f897a752488ade1bc9c8a19cdd" + "reference": "2dd8890bd01be59a5221999c05ccf0fcafcb354f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/55fff62b19f413f897a752488ade1bc9c8a19cdd", - "reference": "55fff62b19f413f897a752488ade1bc9c8a19cdd", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/2dd8890bd01be59a5221999c05ccf0fcafcb354f", + "reference": "2dd8890bd01be59a5221999c05ccf0fcafcb354f", "shasum": "" }, "require": { @@ -5871,7 +5874,7 @@ "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "conflict": { "masterminds/html5": "<2.6" @@ -5909,7 +5912,7 @@ "description": "Eases DOM navigation for HTML and XML documents", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v5.3.0" + "source": "https://github.com/symfony/dom-crawler/tree/v5.3.4" }, "funding": [ { @@ -5925,27 +5928,27 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-23T15:55:36+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce" + "reference": "f2fd2208157553874560f3645d4594303058c4bd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/67a5f354afa8e2f231081b3fa11a5912f933c3ce", - "reference": "67a5f354afa8e2f231081b3fa11a5912f933c3ce", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f2fd2208157553874560f3645d4594303058c4bd", + "reference": "f2fd2208157553874560f3645d4594303058c4bd", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/deprecation-contracts": "^2.1", "symfony/event-dispatcher-contracts": "^2", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "conflict": { "symfony/dependency-injection": "<4.4" @@ -5955,7 +5958,7 @@ "symfony/event-dispatcher-implementation": "2.0" }, "require-dev": { - "psr/log": "~1.0", + "psr/log": "^1|^2|^3", "symfony/config": "^4.4|^5.0", "symfony/dependency-injection": "^4.4|^5.0", "symfony/error-handler": "^4.4|^5.0", @@ -5994,7 +5997,7 @@ "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.3.0" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.3.4" }, "funding": [ { @@ -6010,7 +6013,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-23T15:55:36+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -6093,20 +6096,21 @@ }, { "name": "symfony/finder", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6" + "reference": "17f50e06018baec41551a71a15731287dbaab186" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", - "reference": "0ae3f047bed4edff6fd35b26a9a6bfdc92c953c6", + "url": "https://api.github.com/repos/symfony/finder/zipball/17f50e06018baec41551a71a15731287dbaab186", + "reference": "17f50e06018baec41551a71a15731287dbaab186", "shasum": "" }, "require": { - "php": ">=7.2.5" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -6134,7 +6138,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.3.0" + "source": "https://github.com/symfony/finder/tree/v5.3.4" }, "funding": [ { @@ -6150,7 +6154,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T12:52:38+00:00" + "time": "2021-07-23T15:54:19+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6233,16 +6237,16 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab" + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/24b72c6baa32c746a4d0840147c9715e42bb68ab", - "reference": "24b72c6baa32c746a4d0840147c9715e42bb68ab", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/16880ba9c5ebe3642d1995ab866db29270b36535", + "reference": "16880ba9c5ebe3642d1995ab866db29270b36535", "shasum": "" }, "require": { @@ -6294,7 +6298,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.23.1" }, "funding": [ { @@ -6310,7 +6314,7 @@ "type": "tidelift" } ], - "time": "2021-05-27T09:17:38+00:00" + "time": "2021-05-27T12:26:48+00:00" }, { "name": "symfony/polyfill-php73", @@ -6393,16 +6397,16 @@ }, { "name": "symfony/polyfill-php80", - "version": "v1.23.0", + "version": "v1.23.1", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0" + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/eca0bf41ed421bed1b57c4958bab16aa86b757d0", - "reference": "eca0bf41ed421bed1b57c4958bab16aa86b757d0", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be", + "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be", "shasum": "" }, "require": { @@ -6456,7 +6460,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1" }, "funding": [ { @@ -6472,25 +6476,25 @@ "type": "tidelift" } ], - "time": "2021-02-19T12:13:01+00:00" + "time": "2021-07-28T13:41:28+00:00" }, { "name": "symfony/process", - "version": "v5.3.0", + "version": "v5.3.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "53e36cb1c160505cdaf1ef201501669c4c317191" + "reference": "d16634ee55b895bd85ec714dadc58e4428ecf030" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/53e36cb1c160505cdaf1ef201501669c4c317191", - "reference": "53e36cb1c160505cdaf1ef201501669c4c317191", + "url": "https://api.github.com/repos/symfony/process/zipball/d16634ee55b895bd85ec714dadc58e4428ecf030", + "reference": "d16634ee55b895bd85ec714dadc58e4428ecf030", "shasum": "" }, "require": { "php": ">=7.2.5", - "symfony/polyfill-php80": "^1.15" + "symfony/polyfill-php80": "^1.16" }, "type": "library", "autoload": { @@ -6518,7 +6522,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.3.0" + "source": "https://github.com/symfony/process/tree/v5.3.4" }, "funding": [ { @@ -6534,7 +6538,7 @@ "type": "tidelift" } ], - "time": "2021-05-26T12:52:38+00:00" + "time": "2021-07-23T15:54:19+00:00" }, { "name": "symfony/service-contracts", @@ -6617,16 +6621,16 @@ }, { "name": "symfony/string", - "version": "v5.3.0", + "version": "v5.3.3", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b" + "reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", - "reference": "a9a0f8b6aafc5d2d1c116dcccd1573a95153515b", + "url": "https://api.github.com/repos/symfony/string/zipball/bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1", + "reference": "bd53358e3eccec6a670b5f33ab680d8dbe1d4ae1", "shasum": "" }, "require": { @@ -6680,7 +6684,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.3.0" + "source": "https://github.com/symfony/string/tree/v5.3.3" }, "funding": [ { @@ -6696,20 +6700,20 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-06-27T11:44:38+00:00" }, { "name": "symfony/yaml", - "version": "v5.3.0", + "version": "v5.3.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11" + "reference": "4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", - "reference": "3bbcf262fceb3d8f48175302e6ba0ac96e3a5a11", + "url": "https://api.github.com/repos/symfony/yaml/zipball/4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7", + "reference": "4500fe63dc9c6ffc32d3b1cb0448c329f9c814b7", "shasum": "" }, "require": { @@ -6755,7 +6759,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v5.3.0" + "source": "https://github.com/symfony/yaml/tree/v5.3.6" }, "funding": [ { @@ -6771,20 +6775,20 @@ "type": "tidelift" } ], - "time": "2021-05-26T17:43:10+00:00" + "time": "2021-07-29T06:20:01+00:00" }, { "name": "theseer/tokenizer", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/theseer/tokenizer.git", - "reference": "75a63c33a8577608444246075ea0af0d052e452a" + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theseer/tokenizer/zipball/75a63c33a8577608444246075ea0af0d052e452a", - "reference": "75a63c33a8577608444246075ea0af0d052e452a", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", "shasum": "" }, "require": { @@ -6813,7 +6817,7 @@ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", "support": { "issues": "https://github.com/theseer/tokenizer/issues", - "source": "https://github.com/theseer/tokenizer/tree/master" + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" }, "funding": [ { @@ -6821,7 +6825,7 @@ "type": "github" } ], - "time": "2020-07-12T23:59:07+00:00" + "time": "2021-07-28T10:34:58+00:00" }, { "name": "webmozart/assert", @@ -7146,7 +7150,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "^8.0.0" + "php": "^8.0.0", + "ext-intl": "~8.0" }, "platform-dev": [], "plugin-api-version": "2.0.0" diff --git a/mirzaev/skillparts/system/config/params.php.example b/mirzaev/skillparts/system/config/params.php.example index 15fead7..8ba1ac7 100644 --- a/mirzaev/skillparts/system/config/params.php.example +++ b/mirzaev/skillparts/system/config/params.php.example @@ -3,25 +3,26 @@ return [ 'captcha' => [ 'suppliers' => [ - 'public' => '', - 'secret' => '' + 'public' => null, + 'secret' => null ] ], 'mail' => [ - 'system' => '', - 'info' => '' + 'system' => null, + 'info' => null ], 'dellin' => [ - 'nickname' => '', - 'password' => '', - 'key' => '' + 'nickname' => null, + 'password' => null, + 'key' => null ], 'cdek' => [ - 'nickname' => '', - 'password' => '', - 'key' => '' + 'nickname' => null, + 'password' => null, + 'key' => null ], 'dadata' => [ - 'key' => '' + 'key' => null, + 'secret' => null ] ]; diff --git a/mirzaev/skillparts/system/config/web.php.example b/mirzaev/skillparts/system/config/web.php.example index 4326101..17cc014 100644 --- a/mirzaev/skillparts/system/config/web.php.example +++ b/mirzaev/skillparts/system/config/web.php.example @@ -96,9 +96,9 @@ $config = [ ], 'product/' => 'product/index', '///' => '
/-', - 'profile/geolocation/' => 'profile/geolocation-', + 'profile/geolocation/' => 'profile/geolocation-', 'orders' => 'order/index', - 'orders/' => 'order/index', + 'orders/' => 'order/index', 'orders//' => 'order/', 'orders/supply//' => 'order/supply-', 'orders/supply///' => 'order/supply--', diff --git a/mirzaev/skillparts/system/controllers/OrderController.php b/mirzaev/skillparts/system/controllers/OrderController.php index 5cbd570..671c35c 100644 --- a/mirzaev/skillparts/system/controllers/OrderController.php +++ b/mirzaev/skillparts/system/controllers/OrderController.php @@ -102,7 +102,7 @@ class OrderController extends Controller // Генерация ответа yii::$app->response->content = json_encode([ 'main' => $this->renderPartial('/account/index'), - 'redirect' => '/order', + 'redirect' => '/orders', '_csrf' => yii::$app->request->getCsrfToken() ]); } else if (yii::$app->request->isGet) { @@ -117,6 +117,9 @@ class OrderController extends Controller // Инициализация cookie $cookies = yii::$app->response->cookies; + // Инициализация открытой панели ("Модерация", "Мои заказы") + $panel = yii::$app->request->post('panel') ?? yii::$app->request->get('panel') ?? 'orders_panel_orders'; + // Инициализация фильтра по типу if ($filter === 'last') { // Запрошено использование прошлых данных о фильтрации по типу @@ -218,7 +221,7 @@ class OrderController extends Controller $to = DateTime::createFromFormat('U', (string) $to)->format('Y-m-d'); return [ - 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders', 'from', 'to')), + 'main' => $this->renderPartial('/orders/index', compact('orders', 'moderator_orders', 'from', 'to', 'panel')), 'title' => 'Заказы', 'redirect' => '/orders', '_csrf' => yii::$app->request->getCsrfToken() @@ -426,26 +429,43 @@ class OrderController extends Controller foreach (isset($targets[0]) && is_array($targets[0]) ? $targets : [$targets] as $target) { // Унификация входных параметров - foreach ($target as $catn => $amount) { + foreach ($target as $catn => $data) { // Перебор целей (переданных объектов в корзине) - foreach ($connections as $connection) { - // Перебор объектов в корзине + foreach ($data as $type => $amount) { + // Перебор данных цели - if ($connection['supply']['catn'] === $catn) { - // Цель найдена + foreach ($connections as $connection) { + // Перебор объектов в корзине + if ($connection['supply']['catn'] === $catn) { + // Цель найдена (продукт) - if ($connection['amount'] > $amount) { - // Запрошено уменьшение количества + foreach ($connection['order_edge_supply'] as $order_edge_supply) { + // Перебор связанных поставок - // Удаление - $order->deleteSupply([$catn => $connection['amount'] - $amount]); - } else if ($connection['amount'] < $amount) { - // Запрошено увеличение количества + if ($order_edge_supply["dlvr"]["type"] === $type) { + // Цель найдена (поставка) - // Запись - $order->writeSupply('supply/' . $connection['supply']['_key'], $connection['order_edge_supply']['dlvr'] ?? 'auto', $amount - $connection['amount']); + if ($connection['amount'][$type] > $amount) { + // Запрошено уменьшение количества + + // Удаление + $order->deleteSupply([ + $catn => [ + $type => $connection['amount'][$type] - $amount + ] + ]); + } else if ($connection['amount'][$type] < $amount) { + // Запрошено увеличение количества + + // Запись + $order->writeSupply('supply/' . $connection['supply']['_key'], $type, $amount - $connection['amount'][$type]); + } + + break; + } + } } } } @@ -681,7 +701,6 @@ class OrderController extends Controller // Удалось найти инстанцию поставки var_dump($supply); - } if ($order_edge_supply = OrderEdgeSupply::searchById($_id = OrderEdgeSupply::collectionName() . '/' . $catn)) { diff --git a/mirzaev/skillparts/system/controllers/ProfileController.php b/mirzaev/skillparts/system/controllers/ProfileController.php index 56b0543..3ef206a 100644 --- a/mirzaev/skillparts/system/controllers/ProfileController.php +++ b/mirzaev/skillparts/system/controllers/ProfileController.php @@ -10,7 +10,9 @@ use yii\web\Controller; use yii\web\Response; use yii\web\Cookie; use yii\web\UploadedFile; +use yii\web\User; +use app\models\Account; use app\models\Supply; use app\models\SupplyGroup; use app\models\Search; @@ -18,8 +20,11 @@ use app\models\Notification; use app\models\Settings; use app\models\Dellin; use app\models\SettingsEdgeSettings; - +use app\models\Terminal; use Dadata\DadataClient as Dadata; +use Exception; +use moonland\phpexcel\Excel; +use Throwable; class ProfileController extends Controller { @@ -43,7 +48,8 @@ class ProfileController extends Controller 'supplies', 'import', 'monitoring', - 'readGroups' + 'readGroups', + 'geolocation-write' ] ], [ @@ -467,64 +473,330 @@ class ProfileController extends Controller * * @param string|null $account * - * @return bool + * @return array|bool JSON, в случае успеха */ - public function actionGeolocationInit(string|null $account = null): bool + public function actionGeolocationInit(): array|bool { if (Yii::$app->request->isPost) { // POST-запрос - if (is_null($account)) { - // Данные аккаунта не переданы + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; - if (yii::$app->user->isGuest) { - // Аккаунт не аутентифицирован + // if (is_null($account)) { + // // Данные аккаунта не переданы - return false; - } else { - // Аккаунт аутентифицирован + // if (yii::$app->user->isGuest) { + // // Аккаунт не аутентифицирован - // Инициализация - $account = yii::$app->user->identity; - } + // return false; + // } else { + // // Аккаунт аутентифицирован + + // // Инициализация + // $account = yii::$app->user->identity; + // } + // } else { + // if (is_int($account)) { + // // Передан идентификатор (_key) аккаунта (подразумевается) + + // // Инициализация (поиск в базе данных) + // if (!$account = Account::searchById(Account::collectionName() . "/$account")) { + // // Не удалось инициализировать аккаунт + + // return false; + // } + // } + // } + + // Инициализация аккаунта + if (yii::$app->user->isGuest) { + // Аккаунт не аутентифицирован + + return false; + } else { + // Аккаунт аутентифицирован + + // Инициализация + $account = yii::$app->user->identity; } - // Инициализация IP-адреса - $ip = yii::$app->request->userIp === 'localhost' || yii::$app->request->userIp === '127.0.0.1' ? '46.226.227.20' : yii::$app->request->userIp; - // Настройка ответа yii::$app->response->format = Response::FORMAT_JSON; + // Инициализация IP-адреса + $ip = yii::$app->request->userIp === 'localhost' || yii::$app->request->userIp === '127.0.0.1' ? '46.226.227.20' : yii::$app->request->userIp; + // Проверка записи геолокации if (isset($account->geol)) { // Удалось найти данные геолокации - - return true; } else { // Не удалось найти данные геолокации + try { + // Инициализация данных геолокации + $dadata = new Dadata(yii::$app->params['dadata']['key'], yii::$app->params['dadata']['secret']); + + // Запись в буфер данных о геолокации + $account->geol = $dadata->iplocate($ip); + } catch (Throwable $t) { + return false; + } + + // Запись в буфер данных о типе геолокации + $account->geol = ['type' => 'ip'] + $account->geol; + + self::syncGeolocationWithDellin($account); + } + + return self::geolocationAccuracyCheck($account); + } + + return false; + } + + /** + * Генерация ответа по данным геолокации + * + * Проверка точности и наличия данных о геолокации + * + * @param Account|string|null $account + * + * @return array|bool JSON, в случае успеха + */ + public static function geolocationAccuracyCheck(Account|int|null $account = null): array|bool + { + if (is_null($account)) { + // Данные аккаунта не переданы + + if (yii::$app->user->isGuest) { + // Аккаунт не аутентифицирован + + return false; + } else { + // Аккаунт аутентифицирован + + // Инициализация + $account = yii::$app->user->identity; + } + } else { + if (is_int($account)) { + // Передан идентификатор (_key) аккаунта (подразумевается) + + // Инициализация (поиск в базе данных) + if (!$account = Account::searchById(Account::collectionName() . "/$account")) { + // Не удалось инициализировать аккаунт + + return false; + } + } + } + + if (isset($account->geol)) { + // Данные о геолокации найдены + + // Генерация ответа + return [ + 'requestGps' => match ($account->geol['type'] ?? null) { + 'gps' => false, + default => true + }, + '_csrf' => yii::$app->request->getCsrfToken() + ]; + } + + return false; + } + + /** + * Запись данных о геолокации по ширине и долготе + * + * @param string|null $account Аккаунт + * + * @return array|bool JSON, в случае успеха + */ + public function actionGeolocationWrite(): array|bool + { + if (Yii::$app->request->isPost) { + // POST-запрос + + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; + + // if (is_null($account)) { + // // Данные аккаунта не переданы + + // if (yii::$app->user->isGuest) { + // // Аккаунт не аутентифицирован + + // return false; + // } else { + // // Аккаунт аутентифицирован + + // // Инициализация + // $account = yii::$app->user->identity; + // } + // } else { + // if (is_int($account)) { + // // Передан идентификатор (_key) аккаунта (подразумевается) + + // // Инициализация (поиск в базе данных) + // if (!$account = Account::searchById(Account::collectionName() . "/$account")) { + // // Не удалось инициализировать аккаунт + + // return false; + // } + // } + // } + + // Инициализация аккаунта + if (yii::$app->user->isGuest) { + // Аккаунт не аутентифицирован + + return false; + } else { + // Аккаунт аутентифицирован + + // Инициализация + $account = yii::$app->user->identity; + } + + // Настройка ответа + yii::$app->response->format = Response::FORMAT_JSON; + + // Инициализация широты + $latitude = yii::$app->request->post('latitude') ?? yii::$app->request->get('latitude'); + + // Инициализация долготы + $longitude = yii::$app->request->post('longitude') ?? yii::$app->request->get('longitude'); + + if (empty($latitude) || empty($longitude)) { + // Широта или долгота не передана + + return false; + } + + try { // Инициализация данных геолокации - $dadata = new Dadata(yii::$app->params['dadata']['key'], null); + $dadata = new Dadata(yii::$app->params['dadata']['key'], yii::$app->params['dadata']['secret']); - // Запись в буфер - $account->geol = $dadata->iplocate($ip); + // Запись в буфер данных о геолокации + $account->geol = $dadata->geolocate("address", $latitude, $longitude)[0]; + } catch (Throwable $t) { + return false; + } - // Синхронизация с базой данных ДеловыеЛинии - if ($dellin = Dellin::searchByCityKladr(str_pad($account->geol['data']['city_kladr_id'], 25, '0000000000000000000000'))) { - // Удалось найти город с терминалами ДеловыеЛинии + // Запись в буфер данных о типе геолокации + $account->geol = ['type' => 'gps'] + $account->geol; - // Запись связанного с городом терминала в настройки пользователя - // !!! Берётся первый попавшийся терминал - $account->opts = [ - 'delivery_to_terminal' => $dellin['data']['terminals']['terminal'][0]['id'] - ] + ($account->opts ?? []); + return self::syncGeolocationWithDellin($account); + } + } - // Отправка данных из буфера в базу данных - return $account->update() >= 1; + /** + * Синхронизация данных о геолокации с данными терминалов ДеловыеЛинии + * + * Присваивает терминал Скиллпартс относительно города пользователя + * + * @param string|null $account Аккаунт + * + * @return bool Статус выполнения + * + * @todo Переделать запись страны как "Россия" в определение по геолокации через DaData + */ + public static function syncGeolocationWithDellin(Account|int|null $account = null): bool + { + if (is_null($account)) { + // Данные аккаунта не переданы + + if (yii::$app->user->isGuest) { + // Аккаунт не аутентифицирован + + return false; + } else { + // Аккаунт аутентифицирован + + // Инициализация + $account = yii::$app->user->identity; + } + } else { + if (is_int($account)) { + // Передан идентификатор (_key) аккаунта (подразумевается) + + // Инициализация (поиск в базе данных) + if (!$account = Account::searchById(Account::collectionName() . "/$account")) { + // Не удалось инициализировать аккаунт + + return false; + } + } + } + + // Синхронизация с базой данных (таблица с ДеловыеЛинии) + if ($dellin = Dellin::searchByCityKladr(str_pad($account->geol['data']['city_kladr_id'], 25, '0000000000000000000000'))) { + // Удалось найти город с терминалами ДеловыеЛинии + + foreach ($dellin['data']['terminals']['terminal'] as $dellin) { + // Перебор терминалов ДеловыеЛинии + + try { + // Поиск терминала SkillParts + if ($skillparts_buffer = Terminal::searchByDellinTerminalId($dellin['id'], 1)) { + // Удалось найти терминал SkillParts + + // Запись данных терминала SkillParts + $skillparts = $skillparts_buffer[0]->dell; + } else { + // Не удалось найти терминал SkillParts + + if ($dellin['default'] && !$dellin['isOffice'] && $dellin['receiveCargo'] && $dellin['giveoutCargo']) { + // Терминал ДеловыеЛинии помечен как основной, не является офисом, принимает и отправляет посылки + + // Инициализация данных геолокации + $dadata = new Dadata(yii::$app->params['dadata']['key'], yii::$app->params['dadata']['secret']); + + // Запись в буфер данных о геолокации + $geolocation = $dadata->geolocate("address", $dellin['latitude'], $dellin['longitude'])[0]; + + // Инициализация терминала SkillParts + $terminal = new Terminal; + + // Настройка + $terminal->cntr = $geolocation['data']['country']; + $terminal->city = $geolocation['data']['city']; + $terminal->comm = 'Недоступен'; + $terminal->dell = $dellin['id']; + + // Запись в базу данных + if ($terminal->save()) { + // Удалось записать терминал в базу данных + + // Запись данных терминала SkillParts + $skillparts = $terminal->dell; + } + } + } + } catch (Throwable $t) { + continue; } } - return false; + if (empty($skillparts)) { + // Не удалось инициализировать терминал SkillParts + + return false; + } else { + // Удалось инициализировать терминал SkillParts + + // Запись связанного с городом терминала в настройки пользователя + // !!! Берётся первый попавшийся терминал + $account->opts = [ + 'delivery_to_terminal' => $skillparts + ] + ($account->opts ?? []); + + // Отправка данных из буфера в базу данных + return $account->update() >= 1; + } } return false; diff --git a/mirzaev/skillparts/system/controllers/SearchController.php b/mirzaev/skillparts/system/controllers/SearchController.php index a632161..89edb26 100644 --- a/mirzaev/skillparts/system/controllers/SearchController.php +++ b/mirzaev/skillparts/system/controllers/SearchController.php @@ -199,9 +199,9 @@ class SearchController extends Controller // Инициализация данных геолокации try { - $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36; + $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; } catch (Exception $e) { - $from = (int) Settings::search()->delivery_from_default ?? 36; + $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; } try { @@ -277,9 +277,9 @@ class SearchController extends Controller } try { - $from = (int) $buffer_delivery_avia['account']['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36; + $from = (int) $buffer_delivery_avia['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; } catch (Exception $e) { - $from = (int) Settings::search()->delivery_from_default ?? 36; + $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default; } try { @@ -325,6 +325,7 @@ class SearchController extends Controller } catch (Exception $e) { $buffer_delivery_avia['delivery']['error'] = true; + // echo '
';
                                 // var_dump($e->getMessage());
                                 // var_dump($e->getTrace());
                                 // var_dump($e->getFile());
diff --git a/mirzaev/skillparts/system/models/Account.php b/mirzaev/skillparts/system/models/Account.php
index 1b8abd9..5b31838 100644
--- a/mirzaev/skillparts/system/models/Account.php
+++ b/mirzaev/skillparts/system/models/Account.php
@@ -486,9 +486,8 @@ class Account extends Document implements IdentityInterface, PartnerInterface
             }
 
             // Запись
-            // empty($terminal->cntr) &&
             empty($terminal->city) && empty($terminal->strt) && empty($terminal->hous)
-                or $list[$terminal->dell] = "$terminal->city ($terminal->strt, $terminal->hous" . (empty($terminal->offs) ? ')' : ", $terminal->offs)");
+                or $list[$terminal->dell] = (empty($terminal->city) ? '' : "г. $terminal->city"). (empty($terminal->strt) ? '' : ", ул. $terminal->strt") . (empty($terminal->hous) ? '' : ", д. $terminal->hous") . (empty($terminal->offs) ? '' : ", оф. $terminal->offs") . (empty($terminal->comm) ? '' : " ($terminal->comm)");
         }
 
         return $this->syncListWithSettings($list, 'delivery_to_terminal');
diff --git a/mirzaev/skillparts/system/models/Edge.php b/mirzaev/skillparts/system/models/Edge.php
index a88cfa7..067a14c 100644
--- a/mirzaev/skillparts/system/models/Edge.php
+++ b/mirzaev/skillparts/system/models/Edge.php
@@ -124,7 +124,7 @@ abstract class Edge extends Document
     /**
      * Поиск ребра по его вершинам
      */
-    public static function searchByVertex(string $_from, string $_to, string|null $type = null, int $limit = 1): array|null
+    public static function searchByVertex(string $_from, string $_to, string|null $type = null, int $limit = 1, array|null $filter = null): array|null
     {
         $query = self::find()->where([
             '_from' => $_from,
@@ -135,6 +135,10 @@ abstract class Edge extends Document
             $query->where(['type' => $type]);
         }
 
+        if (isset($filter)) {
+            $query->where($filter);
+        }
+
         return $query->limit($limit)->all();
     }
 
diff --git a/mirzaev/skillparts/system/models/Order.php b/mirzaev/skillparts/system/models/Order.php
index 147db59..6bdbf83 100644
--- a/mirzaev/skillparts/system/models/Order.php
+++ b/mirzaev/skillparts/system/models/Order.php
@@ -183,11 +183,11 @@ class Order extends Document implements DocumentInterface
     /**
      * Удаление поставки
      *
-     * @param Supply|string|array $supply Товары
+     * @param Supply|array $supply Товары
      *
      * @return int Количество удалённых рёбер
      */
-    public function deleteSupply(Supply|string|array $supply): int
+    public function deleteSupply(Supply|array $supply): int
     {
         // Инициализация
         $amount = 0;
@@ -196,37 +196,61 @@ class Order extends Document implements DocumentInterface
             // Передана инстанция класса поставки или второй элемент массива не является числом
 
             // Унификация входных данных
-            $supply = [$supply->catn => 1];
+            $supply = [
+                $supply->catn => [
+                    'auto' => 1
+                ]
+            ];
         }
 
-        foreach (is_array($supply) ? $supply : [$supply => 1] as $catn => $amount_raw) {
-            // Перебор товаров
+        foreach ($supply as $catn => $data) {
+            // Перебор целей
 
-            if ($supply = Supply::searchByCatn($catn)) {
-                foreach (OrderEdgeSupply::searchByVertex($this->readId(), $supply->readId(), limit: $amount_raw) as $edge) {
-                    // Перебор рёбер до продукта (если товаров в заказе несколько)
+            var_dump('ок');
 
-                    // Удаление
-                    $edge->delete();
+            foreach ($data as $type => $delete_amount) {
+                // Перебор данных цели
 
-                    // Запись в журнал
-                    $this->journal('delete', ['target' => $supply->readId()]);
+                var_dump('да');
+                if ($supply = Supply::searchByCatn($catn)) {
+                    // Поставка найдена
 
-                    // Постинкрементация счётчика удалённых рёбер
-                    $amount++;
+                    $edges = OrderEdgeSupply::searchByVertex($this->readId(), $supply->readId(), limit: $delete_amount, filter: ['order_edge_supply.dlvr.type == \'' . $type . '\'']);
+
+                    for (; count($edges) > $amount; $amount++) {
+
+                        var_dump(count($edges), $amount, $delete_amount);
+                        var_dump(PHP_EOL);
+
+                        // Удаление из базы данных
+                        $edges[$amount]->delete();
+
+                        // Запись в журнал
+                        $this->journal(
+                            'delete',
+                            [
+                                'target' => [
+                                    $supply->readId() => $type
+                                ]
+                            ]
+                        );
+                    }
                 }
             }
         }
 
+        // Генерация вставки текста с типом доставки
+        $type = Supply::DeliveryToRussian($type);
+
         if ($amount === 0) {
             // Отправка уведомления
-            self::notification('Неудачная попытка удалить товар из корзины');
+            self::notification('Не удалось удалить товар из корзины');
         } else if ($amount === 1) {
             // Отправка уведомления
-            self::notification('Товар ' . $supply->catn . ' удалён из корзины');
+            self::notification("Товар $supply->catn c $type удалён из корзины");
         } else {
             // Отправка уведомления
-            self::notification('Удалено ' . $amount . ' товаров из корзины');
+            self::notification("Удалено $amount товаров из корзины");
         }
 
         return $amount;
@@ -464,8 +488,19 @@ class Order extends Document implements DocumentInterface
                 }
             }
 
-            // Запись количества заказанных поставок
-            $connection['amount'] = count($connection['order_edge_supply']);
+            // Инициализация счетчиков
+            $connection['amount'] = [
+                'auto' => 0,
+                'avia' => 0
+            ];
+
+            // Подсчет количества поставок
+            foreach ($connection['order_edge_supply'] as $edge) {
+                // Перебор связанных поставок
+
+                if ($edge['dlvr']['type'] === 'auto') ++$connection['amount']['auto'];
+                if ($edge['dlvr']['type'] === 'avia') ++$connection['amount']['avia'];
+            }
         }
 
         // Инициализация дополнительных данных
@@ -497,133 +532,134 @@ class Order extends Document implements DocumentInterface
             // Поиск привязанного товара
             $connection['product'] = Product::searchBySupplyId($connection['supply']['_id']);
 
-            if (empty(reset($connection['order_edge_supply'])['dlvr']['type']) || reset($connection['order_edge_supply'])['dlvr']['type'] === 'auto') {
-                // Доставка автоматическая
+            // if (empty(reset($connection['order_edge_supply'])['dlvr']['type']) || reset($connection['order_edge_supply'])['dlvr']['type'] === 'auto') {
+            //     // Доставка автоматическая
 
+            try {
+                // Инициализация данных геолокации
                 try {
-                    // Инициализация данных геолокации
-                    try {
-                        $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36;
-                    } catch (Exception $e) {
-                        $from = (int) Settings::search()->delivery_from_default ?? 36;
-                    }
-
-                    try {
-                        $to = (int) yii::$app->user->identity->opts['delivery_to_terminal'] ?? 36;
-                    } catch (Exception $e) {
-                        $to = 36;
-                    }
-
-                    if ($buffer_connection = $connection['product']['bffr']["$from-$to"] ?? false) {
-                        // Найдены данные доставки в буфере
-
-                        if (time() < $buffer_connection['expires']) {
-                            // Срок хранения не превышен, информация актуальна
-
-                            // Запись в буфер вывода
-                            $connection['delivery'] = $buffer_connection['data'];
-                        }
-                    } else {
-                        // Инициализация инстанции продукта в базе данных
-                        $product = Product::searchByCatn($connection['product']['catn']);
-
-                        // Инициализация доставки Dellin (автоматическая)
-                        $product->bffr = ($product->bffr ?? []) + [
-                            "$from-$to" => [
-                                'data' => $connection['delivery'] = Dellin::calcDeliveryAdvanced(
-                                    $from,
-                                    $to,
-                                    (int) ($connection['product']['wght'] ?? 0),
-                                    (int) ($connection['product']['dmns']['x'] ?? 0),
-                                    (int) ($connection['product']['dmns']['y'] ?? 0),
-                                    (int) ($connection['product']['dmns']['z'] ?? 0),
-                                    count($connection['order_edge_supply'])
-                                ),
-                                'expires' => time() + 86400
-                            ]
-                        ];
-
-                        // Отправка в базу данных
-                        $product->update();
-                    }
+                    $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default;
                 } catch (Exception $e) {
-                    $connection['delivery']['error'] = true;
-
-                    // var_dump($e->getMessage());
-                    // var_dump($e->getTrace());
-                    // var_dump($e->getFile());
-                    // die;
-
-                    // var_dump(json_decode($e->getMessage(), true)['errors']); die;
+                    $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default;
                 }
 
-                // Запись цены (цена поставки + цена доставки + наша наценка)
-                $connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price']['all'] ?? $connection['delivery']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
-            } else {
-                // Доставка самолётом
-
                 try {
-                    // Инициализация данных геолокации
-                    try {
-                        $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? Settings::search()->delivery_from_default ?? 36;
-                    } catch (Exception $e) {
-                        $from = (int) Settings::search()->delivery_from_default ?? 36;
-                    }
-
-                    try {
-                        $to = (int) yii::$app->user->identity->opts['delivery_to_terminal'] ?? 36;
-                    } catch (Exception $e) {
-                        $to = 36;
-                    }
-
-                    if ($buffer_connection = $connection['product']['bffr']["$from-$to-avia"] ?? false) {
-                        // Найдены данные доставки в буфере
-
-                        if (time() < $buffer_connection['expires']) {
-                            // Срок хранения не превышен, информация актуальна
-
-                            // Запись в буфер вывода
-                            $connection['delivery'] = $buffer_connection['data'];
-                        }
-                    } else {
-                        // Инициализация инстанции продукта в базе данных
-                        $product = Product::searchByCatn($connection['product']['catn']);
-
-                        // Инициализация доставки Dellin (автоматическая)
-                        $product->bffr = ($product->bffr ?? []) + [
-                            "$from-$to-avia" => [
-                                'data' => $connection['delivery'] = Dellin::calcDeliveryAdvanced(
-                                    $from,
-                                    $to,
-                                    (int) ($connection['product']['wght'] ?? 0),
-                                    (int) ($connection['product']['dmns']['x'] ?? 0),
-                                    (int) ($connection['product']['dmns']['y'] ?? 0),
-                                    (int) ($connection['product']['dmns']['z'] ?? 0),
-                                    count($connection['order_edge_supply']),
-                                    avia: true
-                                ),
-                                'expires' => time() + 86400
-                            ]
-                        ];
-
-                        // Отправка в базу данных
-                        $product->update();
-                    }
+                    $to = (int) yii::$app->user->identity->opts['delivery_to_terminal'] ?? 36;
                 } catch (Exception $e) {
-                    $connection['delivery']['error'] = true;
-
-                    // var_dump($e->getMessage());
-                    // var_dump($e->getTrace());
-                    // var_dump($e->getFile());
-                    // die;
-
-                    // var_dump(json_decode($e->getMessage(), true)['errors']); die;
+                    $to = 36;
                 }
 
-                // Запись цены (цена поставки + цена доставки + наша наценка)
-                $connection['cost'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['price']['all'] ?? $connection['delivery']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
+                if ($buffer_connection = $connection['product']['bffr']["$from-$to"] ?? false) {
+                    // Найдены данные доставки в буфере
+
+                    if (time() < $buffer_connection['expires']) {
+                        // Срок хранения не превышен, информация актуальна
+
+                        // Запись в буфер вывода
+                        $connection['delivery']['auto'] = $buffer_connection['data'];
+                    }
+                } else {
+                    // Инициализация инстанции продукта в базе данных
+                    $product = Product::searchByCatn($connection['product']['catn']);
+
+                    // Инициализация доставки Dellin (автоматическая)
+                    $product->bffr = ($product->bffr ?? []) + [
+                        "$from-$to" => [
+                            'data' => $connection['delivery']['auto'] = Dellin::calcDeliveryAdvanced(
+                                $from,
+                                $to,
+                                (int) ($connection['product']['wght'] ?? 0),
+                                (int) ($connection['product']['dmns']['x'] ?? 0),
+                                (int) ($connection['product']['dmns']['y'] ?? 0),
+                                (int) ($connection['product']['dmns']['z'] ?? 0),
+                                count($connection['order_edge_supply'])
+                            ),
+                            'expires' => time() + 86400
+                        ]
+                    ];
+
+                    // Отправка в базу данных
+                    $product->update();
+                }
+            } catch (Exception $e) {
+                $connection['delivery']['auto']['error'] = true;
+
+                // echo '
';
+                // var_dump($e->getMessage());
+                // var_dump($e->getTrace());
+                // var_dump($e->getFile());
+                // die;
+
+                // var_dump(json_decode($e->getMessage(), true)['errors']); die;
             }
 
+            // Запись цены (цена поставки + цена доставки + наша наценка)
+            $connection['cost']['auto'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['auto']['price']['all'] ?? $connection['delivery']['auto']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
+            // } else {
+            // Доставка самолётом
+
+            try {
+                // Инициализация данных геолокации
+                try {
+                    $from = (int) $connection['account']['opts']['delivery_from_terminal'] ?? empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default;
+                } catch (Exception $e) {
+                    $from = empty(Settings::search()->delivery_from_default) ? 36 : (int) Settings::search()->delivery_from_default;
+                }
+
+                try {
+                    $to = (int) yii::$app->user->identity->opts['delivery_to_terminal'] ?? 36;
+                } catch (Exception $e) {
+                    $to = 36;
+                }
+
+                if ($buffer_connection = $connection['product']['bffr']["$from-$to-avia"] ?? false) {
+                    // Найдены данные доставки в буфере
+
+                    if (time() < $buffer_connection['expires']) {
+                        // Срок хранения не превышен, информация актуальна
+
+                        // Запись в буфер вывода
+                        $connection['delivery']['avia'] = $buffer_connection['data'];
+                    }
+                } else {
+                    // Инициализация инстанции продукта в базе данных
+                    $product = Product::searchByCatn($connection['product']['catn']);
+
+                    // Инициализация доставки Dellin (автоматическая)
+                    $product->bffr = ($product->bffr ?? []) + [
+                        "$from-$to-avia" => [
+                            'data' => $connection['delivery']['avia'] = Dellin::calcDeliveryAdvanced(
+                                $from,
+                                $to,
+                                (int) ($connection['product']['wght'] ?? 0),
+                                (int) ($connection['product']['dmns']['x'] ?? 0),
+                                (int) ($connection['product']['dmns']['y'] ?? 0),
+                                (int) ($connection['product']['dmns']['z'] ?? 0),
+                                count($connection['order_edge_supply']),
+                                avia: true
+                            ),
+                            'expires' => time() + 86400
+                        ]
+                    ];
+
+                    // Отправка в базу данных
+                    $product->update();
+                }
+            } catch (Exception $e) {
+                $connection['delivery']['avia']['error'] = true;
+
+                // var_dump($e->getMessage());
+                // var_dump($e->getTrace());
+                // var_dump($e->getFile());
+                // die;
+
+                // var_dump(json_decode($e->getMessage(), true)['errors']); die;
+            }
+
+            // Запись цены (цена поставки + цена доставки + наша наценка)
+            $connection['cost']['avia'] = ($cost['ЦенаЗаЕдиницу'] ?? $connection['supply']->onec['Цены']['Цена']['ЦенаЗаЕдиницу']) + ($connection['delivery']['avia']['price']['all'] ?? $connection['delivery']['avia']['price']['one'] ?? 0) + ($settings['increase'] ?? 0) ?? 0;
+            // }
+
             // Запись валюты
             $connection['currency'] = $cost['Валюта'];
         }
@@ -638,7 +674,8 @@ class Order extends Document implements DocumentInterface
      *
      * @return bool Статус подтверждения всех поставок (true если все и false если хотя бы одна из них не подтверждена)
      */
-    public static function checkSuppliesStts(array $order_edge_supply): bool {
+    public static function checkSuppliesStts(array $order_edge_supply): bool
+    {
         foreach ($order_edge_supply as $edge) {
             // Перебор поставок
 
diff --git a/mirzaev/skillparts/system/models/Product.php b/mirzaev/skillparts/system/models/Product.php
index e4739ce..55912ba 100644
--- a/mirzaev/skillparts/system/models/Product.php
+++ b/mirzaev/skillparts/system/models/Product.php
@@ -445,6 +445,7 @@ class Product extends Document
             ->in('product_search')
             ->filter(['catn' => $catn], 'START_SENSETIVE')
             ->limit($limit)
+            ->orderBy(['catn' => 'ASC'])
             ->select($select)
             ->createCommand()
             ->execute()
diff --git a/mirzaev/skillparts/system/models/Supply.php b/mirzaev/skillparts/system/models/Supply.php
index 0552342..ce2adb0 100644
--- a/mirzaev/skillparts/system/models/Supply.php
+++ b/mirzaev/skillparts/system/models/Supply.php
@@ -601,4 +601,18 @@ class Supply extends Product implements ProductInterface, OfferInterface
     {
         return static::searchAccountById($this->readId());
     }
+
+    public static function DeliveryToRussian(string $dlvr, int $type = 1): string {
+        if ($type === 1) {
+            return match($dlvr) {
+                'avia' => 'доставкой самолётом',
+                default => 'автоматической доставкой'
+            };
+        } else {
+            return match($dlvr) {
+                'avia' => 'Самолёт',
+                default => 'Автоматическая'
+            };
+        }
+    }
 }
diff --git a/mirzaev/skillparts/system/models/Terminal.php b/mirzaev/skillparts/system/models/Terminal.php
index 46c1749..ae12efe 100644
--- a/mirzaev/skillparts/system/models/Terminal.php
+++ b/mirzaev/skillparts/system/models/Terminal.php
@@ -25,6 +25,7 @@ class Terminal extends Document
                 'strt',
                 'hous',
                 'offs',
+                'comm',
                 'dell',
                 'hndl'
             ]
@@ -43,7 +44,8 @@ class Terminal extends Document
                         'city',
                         'strt',
                         'hous',
-                        'offs'
+                        'offs',
+                        'comm'
                     ],
                     'string'
                 ],
@@ -52,20 +54,7 @@ class Terminal extends Document
                         'dell',
                         'hndl'
                     ],
-                    'int'
-                ],
-                [
-                    [
-                        'name',
-                        'cntr',
-                        'city',
-                        'strt',
-                        'hous',
-                        'dell',
-                        'hndl'
-                    ],
-                    'required',
-                    'message' => 'Заполните поле: {attribute}'
+                    'integer'
                 ]
             ]
         );
@@ -82,9 +71,25 @@ class Terminal extends Document
                 'strt' => 'Улица',
                 'hous' => 'Дом',
                 'offs' => 'Офис',
+                'comm' => 'Комментарий',
                 'dell' => 'Терминал ДеловыеЛинии для рассчётов доставки',
                 'hndl' => 'Количество дней для обработки после получения от ДеловыеЛинии'
             ]
         );
     }
+
+    /**
+     * Поиск по индентификатору терминала ДеловыеЛинии
+     *
+     * @param string $dell Идентификатор терминала ДеловыеЛинии
+     * @param int $limit Максимальное количество результатов поиска
+     *
+     * @return array|null Терминалы SkillParts, если найдены
+     *
+     * @todo Сделать привязку терминалов SkillParts к нескольким терминалам ДеловыеЛинии и переделать под это поиск
+     */
+    public static function searchByDellinTerminalId(string $dell, int $limit = 1): ?array
+    {
+        return self::find()->where(['dell' => $dell])->limit($limit)->all();
+    }
 }
diff --git a/mirzaev/skillparts/system/models/connection/Dellin.php b/mirzaev/skillparts/system/models/connection/Dellin.php
index b09dac3..efacab5 100644
--- a/mirzaev/skillparts/system/models/connection/Dellin.php
+++ b/mirzaev/skillparts/system/models/connection/Dellin.php
@@ -86,7 +86,7 @@ class Dellin extends Model
 
             // Значения по умолчанию, если указан 0
             $x === 0 and $x = 25;
-            $y === 0 and $y = 50;
+            $y === 0 and $y = 40;
             $z === 0 and $z = 25;
             $weight === 0 and $weight = 300;
 
diff --git a/mirzaev/skillparts/system/views/account/index.php b/mirzaev/skillparts/system/views/account/index.php
index 857c777..20bab7f 100644
--- a/mirzaev/skillparts/system/views/account/index.php
+++ b/mirzaev/skillparts/system/views/account/index.php
@@ -89,7 +89,7 @@ use app\models\AccountForm;
 
 
 
-    
                     
                 
@@ -187,18 +194,10 @@ if (
                 День
                 Неделя
                 Месяц
-                Год
+                Год
             
-            
-
- - -
-

-

-
- - -
+
+
@@ -378,6 +377,54 @@ if (
+ + user->isGuest && (yii::$app->user->identity->type === 'administrator' diff --git a/mirzaev/skillparts/system/views/search/index.php b/mirzaev/skillparts/system/views/search/index.php index d8dafd3..cd7ee57 100644 --- a/mirzaev/skillparts/system/views/search/index.php +++ b/mirzaev/skillparts/system/views/search/index.php @@ -199,11 +199,10 @@ // Генерация $supplies_html .= << -
- $index + $index $amount $delivery_icon $delivery дн - $price + $price @@ -225,12 +224,12 @@
-
+ +
diff --git a/mirzaev/skillparts/system/web/css/datepicker.css b/mirzaev/skillparts/system/web/css/datepicker.css new file mode 100644 index 0000000..a803fda --- /dev/null +++ b/mirzaev/skillparts/system/web/css/datepicker.css @@ -0,0 +1,622 @@ +.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- { + color: #dedede; } + .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover { + color: #c5c5c5; } + .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- { + color: #dedede; } + .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- { + color: #fff; + background: #a2ddf6; } + .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- { + background: #8ad5f4; } + .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.1); + color: #cccccc; } + .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty { + background: none; + border: none; } + +/* ------------------------------------------------- + Datepicker cells + ------------------------------------------------- */ +.datepicker--cells { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; } + +.datepicker--cell { + border-radius: 4px; + box-sizing: border-box; + cursor: pointer; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + position: relative; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + height: 32px; + z-index: 1; } + .datepicker--cell.-focus- { + background: #f0f0f0; } + .datepicker--cell.-current- { + color: #4EB5E6; } + .datepicker--cell.-current-.-focus- { + color: #4a4a4a; } + .datepicker--cell.-current-.-in-range- { + color: #4EB5E6; } + .datepicker--cell.-in-range- { + background: rgba(92, 196, 239, 0.1); + color: #4a4a4a; + border-radius: 0; } + .datepicker--cell.-in-range-.-focus- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell.-disabled- { + cursor: default; + color: #aeaeae; } + .datepicker--cell.-disabled-.-focus- { + color: #aeaeae; } + .datepicker--cell.-disabled-.-in-range- { + color: #a1a1a1; } + .datepicker--cell.-disabled-.-current-.-focus- { + color: #aeaeae; } + .datepicker--cell.-range-from- { + border: 1px solid rgba(92, 196, 239, 0.5); + background-color: rgba(92, 196, 239, 0.1); + border-radius: 4px 0 0 4px; } + .datepicker--cell.-range-to- { + border: 1px solid rgba(92, 196, 239, 0.5); + background-color: rgba(92, 196, 239, 0.1); + border-radius: 0 4px 4px 0; } + .datepicker--cell.-range-from-.-range-to- { + border-radius: 4px; } + .datepicker--cell.-selected- { + color: #fff; + border: none; + background: #5cc4ef; } + .datepicker--cell.-selected-.-current- { + color: #fff; + background: #5cc4ef; } + .datepicker--cell.-selected-.-focus- { + background: #45bced; } + .datepicker--cell:empty { + cursor: default; } + +.datepicker--days-names { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin: 8px 0 3px; } + +.datepicker--day-name { + color: #FF9A19; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + text-align: center; + text-transform: uppercase; + font-size: .8em; } + +.datepicker--cell-day { + width: 14.28571%; } + +.datepicker--cells-months { + height: 170px; } + +.datepicker--cell-month { + width: 33.33%; + height: 25%; } + +.datepicker--years { + height: 170px; } + +.datepicker--cells-years { + height: 170px; } + +.datepicker--cell-year { + width: 25%; + height: 33.33%; } + +.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- { + color: #dedede; } + .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover { + color: #c5c5c5; } + .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- { + color: #dedede; } + .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- { + color: #fff; + background: #a2ddf6; } + .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- { + background: #8ad5f4; } + .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.1); + color: #cccccc; } + .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty { + background: none; + border: none; } + +/* ------------------------------------------------- + Datepicker + ------------------------------------------------- */ +.datepickers-container { + position: absolute; + left: 0; + top: 0; } + @media print { + .datepickers-container { + display: none; } } + +.datepicker { + background: #fff; + border: 1px solid #dbdbdb; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + border-radius: 4px; + box-sizing: content-box; + font-family: Tahoma, sans-serif; + font-size: 14px; + color: #4a4a4a; + width: 250px; + position: absolute; + left: -100000px; + opacity: 0; + transition: opacity 0.3s ease, left 0s 0.3s, -webkit-transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0.3s; + transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0.3s, -webkit-transform 0.3s ease; + z-index: 100; } + .datepicker.-from-top- { + -webkit-transform: translateY(-8px); + transform: translateY(-8px); } + .datepicker.-from-right- { + -webkit-transform: translateX(8px); + transform: translateX(8px); } + .datepicker.-from-bottom- { + -webkit-transform: translateY(8px); + transform: translateY(8px); } + .datepicker.-from-left- { + -webkit-transform: translateX(-8px); + transform: translateX(-8px); } + .datepicker.active { + opacity: 1; + -webkit-transform: translate(0); + transform: translate(0); + transition: opacity 0.3s ease, left 0s 0s, -webkit-transform 0.3s ease; + transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0s; + transition: opacity 0.3s ease, transform 0.3s ease, left 0s 0s, -webkit-transform 0.3s ease; } + +.datepicker-inline .datepicker { + border-color: #d7d7d7; + box-shadow: none; + position: static; + left: auto; + right: auto; + opacity: 1; + -webkit-transform: none; + transform: none; } + +.datepicker-inline .datepicker--pointer { + display: none; } + +.datepicker--content { + box-sizing: content-box; + padding: 4px; } + .-only-timepicker- .datepicker--content { + display: none; } + +.datepicker--pointer { + position: absolute; + background: #fff; + border-top: 1px solid #dbdbdb; + border-right: 1px solid #dbdbdb; + width: 10px; + height: 10px; + z-index: -1; } + .-top-left- .datepicker--pointer, .-top-center- .datepicker--pointer, .-top-right- .datepicker--pointer { + top: calc(100% - 4px); + -webkit-transform: rotate(135deg); + transform: rotate(135deg); } + .-right-top- .datepicker--pointer, .-right-center- .datepicker--pointer, .-right-bottom- .datepicker--pointer { + right: calc(100% - 4px); + -webkit-transform: rotate(225deg); + transform: rotate(225deg); } + .-bottom-left- .datepicker--pointer, .-bottom-center- .datepicker--pointer, .-bottom-right- .datepicker--pointer { + bottom: calc(100% - 4px); + -webkit-transform: rotate(315deg); + transform: rotate(315deg); } + .-left-top- .datepicker--pointer, .-left-center- .datepicker--pointer, .-left-bottom- .datepicker--pointer { + left: calc(100% - 4px); + -webkit-transform: rotate(45deg); + transform: rotate(45deg); } + .-top-left- .datepicker--pointer, .-bottom-left- .datepicker--pointer { + left: 10px; } + .-top-right- .datepicker--pointer, .-bottom-right- .datepicker--pointer { + right: 10px; } + .-top-center- .datepicker--pointer, .-bottom-center- .datepicker--pointer { + left: calc(50% - 10px / 2); } + .-left-top- .datepicker--pointer, .-right-top- .datepicker--pointer { + top: 10px; } + .-left-bottom- .datepicker--pointer, .-right-bottom- .datepicker--pointer { + bottom: 10px; } + .-left-center- .datepicker--pointer, .-right-center- .datepicker--pointer { + top: calc(50% - 10px / 2); } + +.datepicker--body { + display: none; } + .datepicker--body.active { + display: block; } + +.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- { + color: #dedede; } + .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover { + color: #c5c5c5; } + .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- { + color: #dedede; } + .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- { + color: #fff; + background: #a2ddf6; } + .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- { + background: #8ad5f4; } + .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.1); + color: #cccccc; } + .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty { + background: none; + border: none; } + +/* ------------------------------------------------- + Navigation + ------------------------------------------------- */ +.datepicker--nav { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-justify-content: space-between; + -ms-flex-pack: justify; + justify-content: space-between; + border-bottom: 1px solid #efefef; + min-height: 32px; + padding: 4px; } + .-only-timepicker- .datepicker--nav { + display: none; } + +.datepicker--nav-title, +.datepicker--nav-action { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + cursor: pointer; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; } + +.datepicker--nav-action { + width: 32px; + border-radius: 4px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } + .datepicker--nav-action:hover { + background: #f0f0f0; } + .datepicker--nav-action.-disabled- { + visibility: hidden; } + .datepicker--nav-action svg { + width: 32px; + height: 32px; } + .datepicker--nav-action path { + fill: none; + stroke: #9c9c9c; + stroke-width: 2px; } + +.datepicker--nav-title { + border-radius: 4px; + padding: 0 8px; } + .datepicker--nav-title i { + font-style: normal; + color: #9c9c9c; + margin-left: 5px; } + .datepicker--nav-title:hover { + background: #f0f0f0; } + .datepicker--nav-title.-disabled- { + cursor: default; + background: none; } + +.datepicker--buttons { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 4px; + border-top: 1px solid #efefef; } + +.datepicker--button { + color: #4EB5E6; + cursor: pointer; + border-radius: 4px; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + display: -webkit-inline-flex; + display: -ms-inline-flexbox; + display: inline-flex; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + height: 32px; } + .datepicker--button:hover { + color: #4a4a4a; + background: #f0f0f0; } + +.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- { + color: #dedede; } + .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover { + color: #c5c5c5; } + .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- { + color: #dedede; } + .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- { + color: #fff; + background: #a2ddf6; } + .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- { + background: #8ad5f4; } + .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.1); + color: #cccccc; } + .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty { + background: none; + border: none; } + +/* ------------------------------------------------- + Timepicker + ------------------------------------------------- */ +.datepicker--time { + border-top: 1px solid #efefef; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + padding: 4px; + position: relative; } + .datepicker--time.-am-pm- .datepicker--time-sliders { + -webkit-flex: 0 1 138px; + -ms-flex: 0 1 138px; + flex: 0 1 138px; + max-width: 138px; } + .-only-timepicker- .datepicker--time { + border-top: none; } + +.datepicker--time-sliders { + -webkit-flex: 0 1 153px; + -ms-flex: 0 1 153px; + flex: 0 1 153px; + margin-right: 10px; + max-width: 153px; } + +.datepicker--time-label { + display: none; + font-size: 12px; } + +.datepicker--time-current { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + font-size: 14px; + text-align: center; + margin: 0 0 0 10px; } + +.datepicker--time-current-colon { + margin: 0 2px 3px; + line-height: 1; } + +.datepicker--time-current-hours, +.datepicker--time-current-minutes { + line-height: 1; + font-size: 19px; + font-family: "Century Gothic", CenturyGothic, AppleGothic, sans-serif; + position: relative; + z-index: 1; } + .datepicker--time-current-hours:after, + .datepicker--time-current-minutes:after { + content: ''; + background: #f0f0f0; + border-radius: 4px; + position: absolute; + left: -2px; + top: -3px; + right: -2px; + bottom: -2px; + z-index: -1; + opacity: 0; } + .datepicker--time-current-hours.-focus-:after, + .datepicker--time-current-minutes.-focus-:after { + opacity: 1; } + +.datepicker--time-current-ampm { + text-transform: uppercase; + -webkit-align-self: flex-end; + -ms-flex-item-align: end; + align-self: flex-end; + color: #9c9c9c; + margin-left: 6px; + font-size: 11px; + margin-bottom: 1px; } + +.datepicker--time-row { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + font-size: 11px; + height: 17px; + background: linear-gradient(to right, #dedede, #dedede) left 50%/100% 1px no-repeat; } + .datepicker--time-row:first-child { + margin-bottom: 4px; } + .datepicker--time-row input[type='range'] { + background: none; + cursor: pointer; + -webkit-flex: 1; + -ms-flex: 1; + flex: 1; + height: 100%; + padding: 0; + margin: 0; + -webkit-appearance: none; } + .datepicker--time-row input[type='range']::-webkit-slider-thumb { + -webkit-appearance: none; } + .datepicker--time-row input[type='range']::-ms-tooltip { + display: none; } + .datepicker--time-row input[type='range']:hover::-webkit-slider-thumb { + border-color: #b8b8b8; } + .datepicker--time-row input[type='range']:hover::-moz-range-thumb { + border-color: #b8b8b8; } + .datepicker--time-row input[type='range']:hover::-ms-thumb { + border-color: #b8b8b8; } + .datepicker--time-row input[type='range']:focus { + outline: none; } + .datepicker--time-row input[type='range']:focus::-webkit-slider-thumb { + background: #5cc4ef; + border-color: #5cc4ef; } + .datepicker--time-row input[type='range']:focus::-moz-range-thumb { + background: #5cc4ef; + border-color: #5cc4ef; } + .datepicker--time-row input[type='range']:focus::-ms-thumb { + background: #5cc4ef; + border-color: #5cc4ef; } + .datepicker--time-row input[type='range']::-webkit-slider-thumb { + box-sizing: border-box; + height: 12px; + width: 12px; + border-radius: 3px; + border: 1px solid #dedede; + background: #fff; + cursor: pointer; + transition: background .2s; } + .datepicker--time-row input[type='range']::-moz-range-thumb { + box-sizing: border-box; + height: 12px; + width: 12px; + border-radius: 3px; + border: 1px solid #dedede; + background: #fff; + cursor: pointer; + transition: background .2s; } + .datepicker--time-row input[type='range']::-ms-thumb { + box-sizing: border-box; + height: 12px; + width: 12px; + border-radius: 3px; + border: 1px solid #dedede; + background: #fff; + cursor: pointer; + transition: background .2s; } + .datepicker--time-row input[type='range']::-webkit-slider-thumb { + margin-top: -6px; } + .datepicker--time-row input[type='range']::-webkit-slider-runnable-track { + border: none; + height: 1px; + cursor: pointer; + color: transparent; + background: transparent; } + .datepicker--time-row input[type='range']::-moz-range-track { + border: none; + height: 1px; + cursor: pointer; + color: transparent; + background: transparent; } + .datepicker--time-row input[type='range']::-ms-track { + border: none; + height: 1px; + cursor: pointer; + color: transparent; + background: transparent; } + .datepicker--time-row input[type='range']::-ms-fill-lower { + background: transparent; } + .datepicker--time-row input[type='range']::-ms-fill-upper { + background: transparent; } + .datepicker--time-row span { + padding: 0 12px; } + +.datepicker--time-icon { + color: #9c9c9c; + border: 1px solid; + border-radius: 50%; + font-size: 16px; + position: relative; + margin: 0 5px -1px 0; + width: 1em; + height: 1em; } + .datepicker--time-icon:after, .datepicker--time-icon:before { + content: ''; + background: currentColor; + position: absolute; } + .datepicker--time-icon:after { + height: .4em; + width: 1px; + left: calc(50% - 1px); + top: calc(50% + 1px); + -webkit-transform: translateY(-100%); + transform: translateY(-100%); } + .datepicker--time-icon:before { + width: .4em; + height: 1px; + top: calc(50% + 1px); + left: calc(50% - 1px); } + +.datepicker--cell-day.-other-month-, .datepicker--cell-year.-other-decade- { + color: #dedede; } + .datepicker--cell-day.-other-month-:hover, .datepicker--cell-year.-other-decade-:hover { + color: #c5c5c5; } + .-disabled-.-focus-.datepicker--cell-day.-other-month-, .-disabled-.-focus-.datepicker--cell-year.-other-decade- { + color: #dedede; } + .-selected-.datepicker--cell-day.-other-month-, .-selected-.datepicker--cell-year.-other-decade- { + color: #fff; + background: #a2ddf6; } + .-selected-.-focus-.datepicker--cell-day.-other-month-, .-selected-.-focus-.datepicker--cell-year.-other-decade- { + background: #8ad5f4; } + .-in-range-.datepicker--cell-day.-other-month-, .-in-range-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.1); + color: #cccccc; } + .-in-range-.-focus-.datepicker--cell-day.-other-month-, .-in-range-.-focus-.datepicker--cell-year.-other-decade- { + background-color: rgba(92, 196, 239, 0.2); } + .datepicker--cell-day.-other-month-:empty, .datepicker--cell-year.-other-decade-:empty { + background: none; + border: none; } diff --git a/mirzaev/skillparts/system/web/css/main.css b/mirzaev/skillparts/system/web/css/main.css index b84acfa..dc00591 100644 --- a/mirzaev/skillparts/system/web/css/main.css +++ b/mirzaev/skillparts/system/web/css/main.css @@ -1,7 +1,7 @@ @font-face { font-family: 'Gilroy'; font-weight: 600; - src : local('/fonts/Gilroy/gilroy-semibold.ttf'), url('/fonts/Gilroy/gilroy-semibold.ttf'); + src: local('/fonts/Gilroy/gilroy-semibold.ttf'), url('/fonts/Gilroy/gilroy-semibold.ttf'); } * { @@ -34,14 +34,14 @@ button { } body { - min-height : 100vh; - display : flex; + min-height: 100vh; + display: flex; flex-direction: column; - overflow-x : hidden; + overflow-x: hidden; } main { - flex-grow : 1; + flex-grow: 1; background-color: #f0eefb; } @@ -68,16 +68,24 @@ main { .button_clean_full, .button_clean_full:hover, .button_clean_full:focus, -.button_clean_full:active { - outline : none !important; +.button_clean_full:active, +.form_clean_full, +.form_clean_full:hover, +.form_clean_full:focus, +.form_clean_full:active { + outline: none !important; box-shadow: none !important; } .button_clean_full, .button_clean_full:hover, .button_clean_full:focus, -.button_clean_full:active { - border : none !important; +.button_clean_full:active, +.form_clean_full, +.form_clean_full:hover, +.form_clean_full:focus, +.form_clean_full:active { + border: none !important; background: none !important; } @@ -89,56 +97,56 @@ main { } .button_blue_simple { - color : #eee; + color: #eee; background-color: #123EAB; - transition : 0s; + transition: 0s; } .button_blue_simple:hover { - color : #fff; + color: #fff; transition: 0s; } .button_blue_simple:active { - color : #ddd; + color: #ddd; background-color: #391e97; - transition : 0s; + transition: 0s; } .button_blue { - color : #eee; + color: #eee; background-color: #123EAB; - transition : 0s; + transition: 0s; } .button_blue:hover { - color : #fff; + color: #fff; background-color: #244db5; - transition : 0s; + transition: 0s; } .button_blue:active { - color : #ddd; + color: #ddd; background-color: #391e97; - transition : 0s; + transition: 0s; } .button_red { - color : #eee; + color: #eee; background-color: #c40000; - transition : 0s; + transition: 0s; } .button_red:hover { - color : #fff; + color: #fff; background-color: #d81313; - transition : 0s; + transition: 0s; } .button_red:active { - color : #ddd; + color: #ddd; background-color: #971e1e; - transition : 0s; + transition: 0s; } .button_white { @@ -147,17 +155,17 @@ main { .button_white:hover { background-color: #eaebee; - transition : 0s; + transition: 0s; } .button_white:active { background-color: #cfd3dd; - transition : 0s; + transition: 0s; } .button_white_hover { background-color: #eaebee !important; - transition : 0s; + transition: 0s; } .button_grey { @@ -166,12 +174,12 @@ main { .button_grey:hover { background-color: #a6aebf; - transition : 0s; + transition: 0s; } .button_grey:active { background-color: #8c94a8; - transition : 0s; + transition: 0s; } .alert_white { @@ -190,7 +198,7 @@ main { font-family: 'Gilroy'; } -.form_account .has-error > .checkbox { +.form_account .has-error>.checkbox { color: #d90000 } diff --git a/mirzaev/skillparts/system/web/js/calendar/datepicker.js b/mirzaev/skillparts/system/web/js/calendar/datepicker.js new file mode 100644 index 0000000..ad69b4f --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/datepicker.js @@ -0,0 +1,2236 @@ +;(function (window, $, undefined) { ;(function () { + var VERSION = '2.2.3', + pluginName = 'datepicker', + autoInitSelector = '.datepicker-here', + $body, $datepickersContainer, + containerBuilt = false, + baseTemplate = '' + + '
' + + '' + + '' + + '
' + + '
', + defaults = { + classes: '', + inline: false, + language: 'ru', + startDate: new Date(), + firstDay: '', + weekends: [6, 0], + dateFormat: '', + altField: '', + altFieldDateFormat: '@', + toggleSelected: true, + keyboardNav: true, + + position: 'bottom left', + offset: 12, + + view: 'days', + minView: 'days', + + showOtherMonths: true, + selectOtherMonths: true, + moveToOtherMonthsOnSelect: true, + + showOtherYears: true, + selectOtherYears: true, + moveToOtherYearsOnSelect: true, + + minDate: '', + maxDate: '', + disableNavWhenOutOfRange: true, + + multipleDates: false, // Boolean or Number + multipleDatesSeparator: ',', + range: false, + + todayButton: false, + clearButton: false, + + showEvent: 'focus', + autoClose: false, + + // navigation + monthsField: 'monthsShort', + prevHtml: '', + nextHtml: '', + navTitles: { + days: 'MM, yyyy', + months: 'yyyy', + years: 'yyyy1 - yyyy2' + }, + + // timepicker + timepicker: false, + onlyTimepicker: false, + dateTimeSeparator: ' ', + timeFormat: '', + minHours: 0, + maxHours: 24, + minMinutes: 0, + maxMinutes: 59, + hoursStep: 1, + minutesStep: 1, + + // events + onSelect: '', + onShow: '', + onHide: '', + onChangeMonth: '', + onChangeYear: '', + onChangeDecade: '', + onChangeView: '', + onRenderCell: '' + }, + hotKeys = { + 'ctrlRight': [17, 39], + 'ctrlUp': [17, 38], + 'ctrlLeft': [17, 37], + 'ctrlDown': [17, 40], + 'shiftRight': [16, 39], + 'shiftUp': [16, 38], + 'shiftLeft': [16, 37], + 'shiftDown': [16, 40], + 'altUp': [18, 38], + 'altRight': [18, 39], + 'altLeft': [18, 37], + 'altDown': [18, 40], + 'ctrlShiftUp': [16, 17, 38] + }, + datepicker; + + var Datepicker = function (el, options) { + this.el = el; + this.$el = $(el); + + this.opts = $.extend(true, {}, defaults, options, this.$el.data()); + + if ($body == undefined) { + $body = $('body'); + } + + if (!this.opts.startDate) { + this.opts.startDate = new Date(); + } + + if (this.el.nodeName == 'INPUT') { + this.elIsInput = true; + } + + if (this.opts.altField) { + this.$altField = typeof this.opts.altField == 'string' ? $(this.opts.altField) : this.opts.altField; + } + + this.inited = false; + this.visible = false; + this.silent = false; // Need to prevent unnecessary rendering + + this.currentDate = this.opts.startDate; + this.currentView = this.opts.view; + this._createShortCuts(); + this.selectedDates = []; + this.views = {}; + this.keys = []; + this.minRange = ''; + this.maxRange = ''; + this._prevOnSelectValue = ''; + + this.init() + }; + + datepicker = Datepicker; + + datepicker.prototype = { + VERSION: VERSION, + viewIndexes: ['days', 'months', 'years'], + + init: function () { + if (!containerBuilt && !this.opts.inline && this.elIsInput) { + this._buildDatepickersContainer(); + } + this._buildBaseHtml(); + this._defineLocale(this.opts.language); + this._syncWithMinMaxDates(); + + if (this.elIsInput) { + if (!this.opts.inline) { + // Set extra classes for proper transitions + this._setPositionClasses(this.opts.position); + this._bindEvents() + } + if (this.opts.keyboardNav && !this.opts.onlyTimepicker) { + this._bindKeyboardEvents(); + } + this.$datepicker.on('mousedown', this._onMouseDownDatepicker.bind(this)); + this.$datepicker.on('mouseup', this._onMouseUpDatepicker.bind(this)); + } + + if (this.opts.classes) { + this.$datepicker.addClass(this.opts.classes) + } + + if (this.opts.timepicker) { + this.timepicker = new $.fn.datepicker.Timepicker(this, this.opts); + this._bindTimepickerEvents(); + } + + if (this.opts.onlyTimepicker) { + this.$datepicker.addClass('-only-timepicker-'); + } + + this.views[this.currentView] = new $.fn.datepicker.Body(this, this.currentView, this.opts); + this.views[this.currentView].show(); + this.nav = new $.fn.datepicker.Navigation(this, this.opts); + this.view = this.currentView; + + this.$el.on('clickCell.adp', this._onClickCell.bind(this)); + this.$datepicker.on('mouseenter', '.datepicker--cell', this._onMouseEnterCell.bind(this)); + this.$datepicker.on('mouseleave', '.datepicker--cell', this._onMouseLeaveCell.bind(this)); + + this.inited = true; + }, + + _createShortCuts: function () { + this.minDate = this.opts.minDate ? this.opts.minDate : new Date(-8639999913600000); + this.maxDate = this.opts.maxDate ? this.opts.maxDate : new Date(8639999913600000); + }, + + _bindEvents : function () { + this.$el.on(this.opts.showEvent + '.adp', this._onShowEvent.bind(this)); + this.$el.on('mouseup.adp', this._onMouseUpEl.bind(this)); + this.$el.on('blur.adp', this._onBlur.bind(this)); + this.$el.on('keyup.adp', this._onKeyUpGeneral.bind(this)); + $(window).on('resize.adp', this._onResize.bind(this)); + $('body').on('mouseup.adp', this._onMouseUpBody.bind(this)); + }, + + _bindKeyboardEvents: function () { + this.$el.on('keydown.adp', this._onKeyDown.bind(this)); + this.$el.on('keyup.adp', this._onKeyUp.bind(this)); + this.$el.on('hotKey.adp', this._onHotKey.bind(this)); + }, + + _bindTimepickerEvents: function () { + this.$el.on('timeChange.adp', this._onTimeChange.bind(this)); + }, + + isWeekend: function (day) { + return this.opts.weekends.indexOf(day) !== -1; + }, + + _defineLocale: function (lang) { + if (typeof lang == 'string') { + this.loc = $.fn.datepicker.language[lang]; + if (!this.loc) { + console.warn('Can\'t find language "' + lang + '" in Datepicker.language, will use "ru" instead'); + this.loc = $.extend(true, {}, $.fn.datepicker.language.ru) + } + + this.loc = $.extend(true, {}, $.fn.datepicker.language.ru, $.fn.datepicker.language[lang]) + } else { + this.loc = $.extend(true, {}, $.fn.datepicker.language.ru, lang) + } + + if (this.opts.dateFormat) { + this.loc.dateFormat = this.opts.dateFormat + } + + if (this.opts.timeFormat) { + this.loc.timeFormat = this.opts.timeFormat + } + + if (this.opts.firstDay !== '') { + this.loc.firstDay = this.opts.firstDay + } + + if (this.opts.timepicker) { + this.loc.dateFormat = [this.loc.dateFormat, this.loc.timeFormat].join(this.opts.dateTimeSeparator); + } + + if (this.opts.onlyTimepicker) { + this.loc.dateFormat = this.loc.timeFormat; + } + + var boundary = this._getWordBoundaryRegExp; + if (this.loc.timeFormat.match(boundary('aa')) || + this.loc.timeFormat.match(boundary('AA')) + ) { + this.ampm = true; + } + }, + + _buildDatepickersContainer: function () { + containerBuilt = true; + $body.append('
'); + $datepickersContainer = $('#datepickers-container'); + }, + + _buildBaseHtml: function () { + var $appendTarget, + $inline = $('
'); + + if(this.el.nodeName == 'INPUT') { + if (!this.opts.inline) { + $appendTarget = $datepickersContainer; + } else { + $appendTarget = $inline.insertAfter(this.$el) + } + } else { + $appendTarget = $inline.appendTo(this.$el) + } + + this.$datepicker = $(baseTemplate).appendTo($appendTarget); + this.$content = $('.datepicker--content', this.$datepicker); + this.$nav = $('.datepicker--nav', this.$datepicker); + }, + + _triggerOnChange: function () { + if (!this.selectedDates.length) { + // Prevent from triggering multiple onSelect callback with same argument (empty string) in IE10-11 + if (this._prevOnSelectValue === '') return; + this._prevOnSelectValue = ''; + return this.opts.onSelect('', '', this); + } + + var selectedDates = this.selectedDates, + parsedSelected = datepicker.getParsedDate(selectedDates[0]), + formattedDates, + _this = this, + dates = new Date( + parsedSelected.year, + parsedSelected.month, + parsedSelected.date, + parsedSelected.hours, + parsedSelected.minutes + ); + + formattedDates = selectedDates.map(function (date) { + return _this.formatDate(_this.loc.dateFormat, date) + }).join(this.opts.multipleDatesSeparator); + + // Create new dates array, to separate it from original selectedDates + if (this.opts.multipleDates || this.opts.range) { + dates = selectedDates.map(function(date) { + var parsedDate = datepicker.getParsedDate(date); + return new Date( + parsedDate.year, + parsedDate.month, + parsedDate.date, + parsedDate.hours, + parsedDate.minutes + ); + }) + } + + this._prevOnSelectValue = formattedDates; + this.opts.onSelect(formattedDates, dates, this); + }, + + next: function () { + var d = this.parsedDate, + o = this.opts; + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month + 1, 1); + if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year); + break; + case 'months': + this.date = new Date(d.year + 1, d.month, 1); + if (o.onChangeYear) o.onChangeYear(this.parsedDate.year); + break; + case 'years': + this.date = new Date(d.year + 10, 0, 1); + if (o.onChangeDecade) o.onChangeDecade(this.curDecade); + break; + } + }, + + prev: function () { + var d = this.parsedDate, + o = this.opts; + switch (this.view) { + case 'days': + this.date = new Date(d.year, d.month - 1, 1); + if (o.onChangeMonth) o.onChangeMonth(this.parsedDate.month, this.parsedDate.year); + break; + case 'months': + this.date = new Date(d.year - 1, d.month, 1); + if (o.onChangeYear) o.onChangeYear(this.parsedDate.year); + break; + case 'years': + this.date = new Date(d.year - 10, 0, 1); + if (o.onChangeDecade) o.onChangeDecade(this.curDecade); + break; + } + }, + + formatDate: function (string, date) { + date = date || this.date; + var result = string, + boundary = this._getWordBoundaryRegExp, + locale = this.loc, + leadingZero = datepicker.getLeadingZeroNum, + decade = datepicker.getDecade(date), + d = datepicker.getParsedDate(date), + fullHours = d.fullHours, + hours = d.hours, + ampm = string.match(boundary('aa')) || string.match(boundary('AA')), + dayPeriod = 'am', + replacer = this._replacer, + validHours; + + if (this.opts.timepicker && this.timepicker && ampm) { + validHours = this.timepicker._getValidHoursFromDate(date, ampm); + fullHours = leadingZero(validHours.hours); + hours = validHours.hours; + dayPeriod = validHours.dayPeriod; + } + + switch (true) { + case /@/.test(result): + result = result.replace(/@/, date.getTime()); + case /aa/.test(result): + result = replacer(result, boundary('aa'), dayPeriod); + case /AA/.test(result): + result = replacer(result, boundary('AA'), dayPeriod.toUpperCase()); + case /dd/.test(result): + result = replacer(result, boundary('dd'), d.fullDate); + case /d/.test(result): + result = replacer(result, boundary('d'), d.date); + case /DD/.test(result): + result = replacer(result, boundary('DD'), locale.days[d.day]); + case /D/.test(result): + result = replacer(result, boundary('D'), locale.daysShort[d.day]); + case /mm/.test(result): + result = replacer(result, boundary('mm'), d.fullMonth); + case /m/.test(result): + result = replacer(result, boundary('m'), d.month + 1); + case /MM/.test(result): + result = replacer(result, boundary('MM'), this.loc.months[d.month]); + case /M/.test(result): + result = replacer(result, boundary('M'), locale.monthsShort[d.month]); + case /ii/.test(result): + result = replacer(result, boundary('ii'), d.fullMinutes); + case /i/.test(result): + result = replacer(result, boundary('i'), d.minutes); + case /hh/.test(result): + result = replacer(result, boundary('hh'), fullHours); + case /h/.test(result): + result = replacer(result, boundary('h'), hours); + case /yyyy/.test(result): + result = replacer(result, boundary('yyyy'), d.year); + case /yyyy1/.test(result): + result = replacer(result, boundary('yyyy1'), decade[0]); + case /yyyy2/.test(result): + result = replacer(result, boundary('yyyy2'), decade[1]); + case /yy/.test(result): + result = replacer(result, boundary('yy'), d.year.toString().slice(-2)); + } + + return result; + }, + + _replacer: function (str, reg, data) { + return str.replace(reg, function (match, p1,p2,p3) { + return p1 + data + p3; + }) + }, + + _getWordBoundaryRegExp: function (sign) { + var symbols = '\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;'; + + return new RegExp('(^|>|' + symbols + ')(' + sign + ')($|<|' + symbols + ')', 'g'); + }, + + + selectDate: function (date) { + var _this = this, + opts = _this.opts, + d = _this.parsedDate, + selectedDates = _this.selectedDates, + len = selectedDates.length, + newDate = ''; + + if (Array.isArray(date)) { + date.forEach(function (d) { + _this.selectDate(d) + }); + return; + } + + if (!(date instanceof Date)) return; + + this.lastSelectedDate = date; + + // Set new time values from Date + if (this.timepicker) { + this.timepicker._setTime(date); + } + + // On this step timepicker will set valid values in it's instance + _this._trigger('selectDate', date); + + // Set correct time values after timepicker's validation + // Prevent from setting hours or minutes which values are lesser then `min` value or + // greater then `max` value + if (this.timepicker) { + date.setHours(this.timepicker.hours); + date.setMinutes(this.timepicker.minutes) + } + + if (_this.view == 'days') { + if (date.getMonth() != d.month && opts.moveToOtherMonthsOnSelect) { + newDate = new Date(date.getFullYear(), date.getMonth(), 1); + } + } + + if (_this.view == 'years') { + if (date.getFullYear() != d.year && opts.moveToOtherYearsOnSelect) { + newDate = new Date(date.getFullYear(), 0, 1); + } + } + + if (newDate) { + _this.silent = true; + _this.date = newDate; + _this.silent = false; + _this.nav._render() + } + + if (opts.multipleDates && !opts.range) { // Set priority to range functionality + if (len === opts.multipleDates) return; + if (!_this._isSelected(date)) { + _this.selectedDates.push(date); + } + } else if (opts.range) { + if (len == 2) { + _this.selectedDates = [date]; + _this.minRange = date; + _this.maxRange = ''; + } else if (len == 1) { + _this.selectedDates.push(date); + if (!_this.maxRange){ + _this.maxRange = date; + } else { + _this.minRange = date; + } + // Swap dates if they were selected via dp.selectDate() and second date was smaller then first + if (datepicker.bigger(_this.maxRange, _this.minRange)) { + _this.maxRange = _this.minRange; + _this.minRange = date; + } + _this.selectedDates = [_this.minRange, _this.maxRange] + + } else { + _this.selectedDates = [date]; + _this.minRange = date; + } + } else { + _this.selectedDates = [date]; + } + + _this._setInputValue(); + + if (opts.onSelect) { + _this._triggerOnChange(); + } + + if (opts.autoClose && !this.timepickerIsActive) { + if (!opts.multipleDates && !opts.range) { + _this.hide(); + } else if (opts.range && _this.selectedDates.length == 2) { + _this.hide(); + } + } + + _this.views[this.currentView]._render() + }, + + removeDate: function (date) { + var selected = this.selectedDates, + _this = this; + + if (!(date instanceof Date)) return; + + return selected.some(function (curDate, i) { + if (datepicker.isSame(curDate, date)) { + selected.splice(i, 1); + + if (!_this.selectedDates.length) { + _this.minRange = ''; + _this.maxRange = ''; + _this.lastSelectedDate = ''; + } else { + _this.lastSelectedDate = _this.selectedDates[_this.selectedDates.length - 1]; + } + + _this.views[_this.currentView]._render(); + _this._setInputValue(); + + if (_this.opts.onSelect) { + _this._triggerOnChange(); + } + + return true + } + }) + }, + + today: function () { + this.silent = true; + this.view = this.opts.minView; + this.silent = false; + this.date = new Date(); + + if (this.opts.todayButton instanceof Date) { + this.selectDate(this.opts.todayButton) + } + }, + + clear: function () { + this.selectedDates = []; + this.minRange = ''; + this.maxRange = ''; + this.views[this.currentView]._render(); + this._setInputValue(); + if (this.opts.onSelect) { + this._triggerOnChange() + } + }, + + /** + * Updates datepicker options + * @param {String|Object} param - parameter's name to update. If object then it will extend current options + * @param {String|Number|Object} [value] - new param value + */ + update: function (param, value) { + var len = arguments.length, + lastSelectedDate = this.lastSelectedDate; + + if (len == 2) { + this.opts[param] = value; + } else if (len == 1 && typeof param == 'object') { + this.opts = $.extend(true, this.opts, param) + } + + this._createShortCuts(); + this._syncWithMinMaxDates(); + this._defineLocale(this.opts.language); + this.nav._addButtonsIfNeed(); + if (!this.opts.onlyTimepicker) this.nav._render(); + this.views[this.currentView]._render(); + + if (this.elIsInput && !this.opts.inline) { + this._setPositionClasses(this.opts.position); + if (this.visible) { + this.setPosition(this.opts.position) + } + } + + if (this.opts.classes) { + this.$datepicker.addClass(this.opts.classes) + } + + if (this.opts.onlyTimepicker) { + this.$datepicker.addClass('-only-timepicker-'); + } + + if (this.opts.timepicker) { + if (lastSelectedDate) this.timepicker._handleDate(lastSelectedDate); + this.timepicker._updateRanges(); + this.timepicker._updateCurrentTime(); + // Change hours and minutes if it's values have been changed through min/max hours/minutes + if (lastSelectedDate) { + lastSelectedDate.setHours(this.timepicker.hours); + lastSelectedDate.setMinutes(this.timepicker.minutes); + } + } + + this._setInputValue(); + + return this; + }, + + _syncWithMinMaxDates: function () { + var curTime = this.date.getTime(); + this.silent = true; + if (this.minTime > curTime) { + this.date = this.minDate; + } + + if (this.maxTime < curTime) { + this.date = this.maxDate; + } + this.silent = false; + }, + + _isSelected: function (checkDate, cellType) { + var res = false; + this.selectedDates.some(function (date) { + if (datepicker.isSame(date, checkDate, cellType)) { + res = date; + return true; + } + }); + return res; + }, + + _setInputValue: function () { + var _this = this, + opts = _this.opts, + format = _this.loc.dateFormat, + altFormat = opts.altFieldDateFormat, + value = _this.selectedDates.map(function (date) { + return _this.formatDate(format, date) + }), + altValues; + + if (opts.altField && _this.$altField.length) { + altValues = this.selectedDates.map(function (date) { + return _this.formatDate(altFormat, date) + }); + altValues = altValues.join(this.opts.multipleDatesSeparator); + this.$altField.val(altValues); + } + + value = value.join(this.opts.multipleDatesSeparator); + + this.$el.val(value) + }, + + /** + * Check if date is between minDate and maxDate + * @param date {object} - date object + * @param type {string} - cell type + * @returns {boolean} + * @private + */ + _isInRange: function (date, type) { + var time = date.getTime(), + d = datepicker.getParsedDate(date), + min = datepicker.getParsedDate(this.minDate), + max = datepicker.getParsedDate(this.maxDate), + dMinTime = new Date(d.year, d.month, min.date).getTime(), + dMaxTime = new Date(d.year, d.month, max.date).getTime(), + types = { + day: time >= this.minTime && time <= this.maxTime, + month: dMinTime >= this.minTime && dMaxTime <= this.maxTime, + year: d.year >= min.year && d.year <= max.year + }; + return type ? types[type] : types.day + }, + + _getDimensions: function ($el) { + var offset = $el.offset(); + + return { + width: $el.outerWidth(), + height: $el.outerHeight(), + left: offset.left, + top: offset.top + } + }, + + _getDateFromCell: function (cell) { + var curDate = this.parsedDate, + year = cell.data('year') || curDate.year, + month = cell.data('month') == undefined ? curDate.month : cell.data('month'), + date = cell.data('date') || 1; + + return new Date(year, month, date); + }, + + _setPositionClasses: function (pos) { + pos = pos.split(' '); + var main = pos[0], + sec = pos[1], + classes = 'datepicker -' + main + '-' + sec + '- -from-' + main + '-'; + + if (this.visible) classes += ' active'; + + this.$datepicker + .removeAttr('class') + .addClass(classes); + }, + + setPosition: function (position) { + position = position || this.opts.position; + + var dims = this._getDimensions(this.$el), + selfDims = this._getDimensions(this.$datepicker), + pos = position.split(' '), + top, left, + offset = this.opts.offset, + main = pos[0], + secondary = pos[1]; + + switch (main) { + case 'top': + top = dims.top - selfDims.height - offset; + break; + case 'right': + left = dims.left + dims.width + offset; + break; + case 'bottom': + top = dims.top + dims.height + offset; + break; + case 'left': + left = dims.left - selfDims.width - offset; + break; + } + + switch(secondary) { + case 'top': + top = dims.top; + break; + case 'right': + left = dims.left + dims.width - selfDims.width; + break; + case 'bottom': + top = dims.top + dims.height - selfDims.height; + break; + case 'left': + left = dims.left; + break; + case 'center': + if (/left|right/.test(main)) { + top = dims.top + dims.height/2 - selfDims.height/2; + } else { + left = dims.left + dims.width/2 - selfDims.width/2; + } + } + + this.$datepicker + .css({ + left: left, + top: top + }) + }, + + show: function () { + var onShow = this.opts.onShow; + + this.setPosition(this.opts.position); + this.$datepicker.addClass('active'); + this.visible = true; + + if (onShow) { + this._bindVisionEvents(onShow) + } + }, + + hide: function () { + var onHide = this.opts.onHide; + + this.$datepicker + .removeClass('active') + .css({ + left: '-100000px' + }); + + this.focused = ''; + this.keys = []; + + this.inFocus = false; + this.visible = false; + this.$el.blur(); + + if (onHide) { + this._bindVisionEvents(onHide) + } + }, + + down: function (date) { + this._changeView(date, 'down'); + }, + + up: function (date) { + this._changeView(date, 'up'); + }, + + _bindVisionEvents: function (event) { + this.$datepicker.off('transitionend.dp'); + event(this, false); + this.$datepicker.one('transitionend.dp', event.bind(this, this, true)) + }, + + _changeView: function (date, dir) { + date = date || this.focused || this.date; + + var nextView = dir == 'up' ? this.viewIndex + 1 : this.viewIndex - 1; + if (nextView > 2) nextView = 2; + if (nextView < 0) nextView = 0; + + this.silent = true; + this.date = new Date(date.getFullYear(), date.getMonth(), 1); + this.silent = false; + this.view = this.viewIndexes[nextView]; + + }, + + _handleHotKey: function (key) { + var date = datepicker.getParsedDate(this._getFocusedDate()), + focusedParsed, + o = this.opts, + newDate, + totalDaysInNextMonth, + monthChanged = false, + yearChanged = false, + decadeChanged = false, + y = date.year, + m = date.month, + d = date.date; + + switch (key) { + case 'ctrlRight': + case 'ctrlUp': + m += 1; + monthChanged = true; + break; + case 'ctrlLeft': + case 'ctrlDown': + m -= 1; + monthChanged = true; + break; + case 'shiftRight': + case 'shiftUp': + yearChanged = true; + y += 1; + break; + case 'shiftLeft': + case 'shiftDown': + yearChanged = true; + y -= 1; + break; + case 'altRight': + case 'altUp': + decadeChanged = true; + y += 10; + break; + case 'altLeft': + case 'altDown': + decadeChanged = true; + y -= 10; + break; + case 'ctrlShiftUp': + this.up(); + break; + } + + totalDaysInNextMonth = datepicker.getDaysCount(new Date(y,m)); + newDate = new Date(y,m,d); + + // If next month has less days than current, set date to total days in that month + if (totalDaysInNextMonth < d) d = totalDaysInNextMonth; + + // Check if newDate is in valid range + if (newDate.getTime() < this.minTime) { + newDate = this.minDate; + } else if (newDate.getTime() > this.maxTime) { + newDate = this.maxDate; + } + + this.focused = newDate; + + focusedParsed = datepicker.getParsedDate(newDate); + if (monthChanged && o.onChangeMonth) { + o.onChangeMonth(focusedParsed.month, focusedParsed.year) + } + if (yearChanged && o.onChangeYear) { + o.onChangeYear(focusedParsed.year) + } + if (decadeChanged && o.onChangeDecade) { + o.onChangeDecade(this.curDecade) + } + }, + + _registerKey: function (key) { + var exists = this.keys.some(function (curKey) { + return curKey == key; + }); + + if (!exists) { + this.keys.push(key) + } + }, + + _unRegisterKey: function (key) { + var index = this.keys.indexOf(key); + + this.keys.splice(index, 1); + }, + + _isHotKeyPressed: function () { + var currentHotKey, + found = false, + _this = this, + pressedKeys = this.keys.sort(); + + for (var hotKey in hotKeys) { + currentHotKey = hotKeys[hotKey]; + if (pressedKeys.length != currentHotKey.length) continue; + + if (currentHotKey.every(function (key, i) { return key == pressedKeys[i]})) { + _this._trigger('hotKey', hotKey); + found = true; + } + } + + return found; + }, + + _trigger: function (event, args) { + this.$el.trigger(event, args) + }, + + _focusNextCell: function (keyCode, type) { + type = type || this.cellType; + + var date = datepicker.getParsedDate(this._getFocusedDate()), + y = date.year, + m = date.month, + d = date.date; + + if (this._isHotKeyPressed()){ + return; + } + + switch(keyCode) { + case 37: // left + type == 'day' ? (d -= 1) : ''; + type == 'month' ? (m -= 1) : ''; + type == 'year' ? (y -= 1) : ''; + break; + case 38: // up + type == 'day' ? (d -= 7) : ''; + type == 'month' ? (m -= 3) : ''; + type == 'year' ? (y -= 4) : ''; + break; + case 39: // right + type == 'day' ? (d += 1) : ''; + type == 'month' ? (m += 1) : ''; + type == 'year' ? (y += 1) : ''; + break; + case 40: // down + type == 'day' ? (d += 7) : ''; + type == 'month' ? (m += 3) : ''; + type == 'year' ? (y += 4) : ''; + break; + } + + var nd = new Date(y,m,d); + if (nd.getTime() < this.minTime) { + nd = this.minDate; + } else if (nd.getTime() > this.maxTime) { + nd = this.maxDate; + } + + this.focused = nd; + + }, + + _getFocusedDate: function () { + var focused = this.focused || this.selectedDates[this.selectedDates.length - 1], + d = this.parsedDate; + + if (!focused) { + switch (this.view) { + case 'days': + focused = new Date(d.year, d.month, new Date().getDate()); + break; + case 'months': + focused = new Date(d.year, d.month, 1); + break; + case 'years': + focused = new Date(d.year, 0, 1); + break; + } + } + + return focused; + }, + + _getCell: function (date, type) { + type = type || this.cellType; + + var d = datepicker.getParsedDate(date), + selector = '.datepicker--cell[data-year="' + d.year + '"]', + $cell; + + switch (type) { + case 'month': + selector = '[data-month="' + d.month + '"]'; + break; + case 'day': + selector += '[data-month="' + d.month + '"][data-date="' + d.date + '"]'; + break; + } + $cell = this.views[this.currentView].$el.find(selector); + + return $cell.length ? $cell : $(''); + }, + + destroy: function () { + var _this = this; + _this.$el + .off('.adp') + .data('datepicker', ''); + + _this.selectedDates = []; + _this.focused = ''; + _this.views = {}; + _this.keys = []; + _this.minRange = ''; + _this.maxRange = ''; + + if (_this.opts.inline || !_this.elIsInput) { + _this.$datepicker.closest('.datepicker-inline').remove(); + } else { + _this.$datepicker.remove(); + } + }, + + _handleAlreadySelectedDates: function (alreadySelected, selectedDate) { + if (this.opts.range) { + if (!this.opts.toggleSelected) { + // Add possibility to select same date when range is true + if (this.selectedDates.length != 2) { + this._trigger('clickCell', selectedDate); + } + } else { + this.removeDate(selectedDate); + } + } else if (this.opts.toggleSelected){ + this.removeDate(selectedDate); + } + + // Change last selected date to be able to change time when clicking on this cell + if (!this.opts.toggleSelected) { + this.lastSelectedDate = alreadySelected; + if (this.opts.timepicker) { + this.timepicker._setTime(alreadySelected); + this.timepicker.update(); + } + } + }, + + _onShowEvent: function (e) { + if (!this.visible) { + this.show(); + } + }, + + _onBlur: function () { + if (!this.inFocus && this.visible) { + this.hide(); + } + }, + + _onMouseDownDatepicker: function (e) { + this.inFocus = true; + }, + + _onMouseUpDatepicker: function (e) { + this.inFocus = false; + e.originalEvent.inFocus = true; + if (!e.originalEvent.timepickerFocus) this.$el.focus(); + }, + + _onKeyUpGeneral: function (e) { + var val = this.$el.val(); + + if (!val) { + this.clear(); + } + }, + + _onResize: function () { + if (this.visible) { + this.setPosition(); + } + }, + + _onMouseUpBody: function (e) { + if (e.originalEvent.inFocus) return; + + if (this.visible && !this.inFocus) { + this.hide(); + } + }, + + _onMouseUpEl: function (e) { + e.originalEvent.inFocus = true; + setTimeout(this._onKeyUpGeneral.bind(this),4); + }, + + _onKeyDown: function (e) { + var code = e.which; + this._registerKey(code); + + // Arrows + if (code >= 37 && code <= 40) { + e.preventDefault(); + this._focusNextCell(code); + } + + // Enter + if (code == 13) { + if (this.focused) { + if (this._getCell(this.focused).hasClass('-disabled-')) return; + if (this.view != this.opts.minView) { + this.down() + } else { + var alreadySelected = this._isSelected(this.focused, this.cellType); + + if (!alreadySelected) { + if (this.timepicker) { + this.focused.setHours(this.timepicker.hours); + this.focused.setMinutes(this.timepicker.minutes); + } + this.selectDate(this.focused); + return; + } + this._handleAlreadySelectedDates(alreadySelected, this.focused) + } + } + } + + // Esc + if (code == 27) { + this.hide(); + } + }, + + _onKeyUp: function (e) { + var code = e.which; + this._unRegisterKey(code); + }, + + _onHotKey: function (e, hotKey) { + this._handleHotKey(hotKey); + }, + + _onMouseEnterCell: function (e) { + var $cell = $(e.target).closest('.datepicker--cell'), + date = this._getDateFromCell($cell); + + // Prevent from unnecessary rendering and setting new currentDate + this.silent = true; + + if (this.focused) { + this.focused = '' + } + + $cell.addClass('-focus-'); + + this.focused = date; + this.silent = false; + + if (this.opts.range && this.selectedDates.length == 1) { + this.minRange = this.selectedDates[0]; + this.maxRange = ''; + if (datepicker.less(this.minRange, this.focused)) { + this.maxRange = this.minRange; + this.minRange = ''; + } + this.views[this.currentView]._update(); + } + }, + + _onMouseLeaveCell: function (e) { + var $cell = $(e.target).closest('.datepicker--cell'); + + $cell.removeClass('-focus-'); + + this.silent = true; + this.focused = ''; + this.silent = false; + }, + + _onTimeChange: function (e, h, m) { + var date = new Date(), + selectedDates = this.selectedDates, + selected = false; + + if (selectedDates.length) { + selected = true; + date = this.lastSelectedDate; + } + + date.setHours(h); + date.setMinutes(m); + + if (!selected && !this._getCell(date).hasClass('-disabled-')) { + this.selectDate(date); + } else { + this._setInputValue(); + if (this.opts.onSelect) { + this._triggerOnChange(); + } + } + }, + + _onClickCell: function (e, date) { + if (this.timepicker) { + date.setHours(this.timepicker.hours); + date.setMinutes(this.timepicker.minutes); + } + this.selectDate(date); + }, + + set focused(val) { + if (!val && this.focused) { + var $cell = this._getCell(this.focused); + + if ($cell.length) { + $cell.removeClass('-focus-') + } + } + this._focused = val; + if (this.opts.range && this.selectedDates.length == 1) { + this.minRange = this.selectedDates[0]; + this.maxRange = ''; + if (datepicker.less(this.minRange, this._focused)) { + this.maxRange = this.minRange; + this.minRange = ''; + } + } + if (this.silent) return; + this.date = val; + }, + + get focused() { + return this._focused; + }, + + get parsedDate() { + return datepicker.getParsedDate(this.date); + }, + + set date (val) { + if (!(val instanceof Date)) return; + + this.currentDate = val; + + if (this.inited && !this.silent) { + this.views[this.view]._render(); + this.nav._render(); + if (this.visible && this.elIsInput) { + this.setPosition(); + } + } + return val; + }, + + get date () { + return this.currentDate + }, + + set view (val) { + this.viewIndex = this.viewIndexes.indexOf(val); + + if (this.viewIndex < 0) { + return; + } + + this.prevView = this.currentView; + this.currentView = val; + + if (this.inited) { + if (!this.views[val]) { + this.views[val] = new $.fn.datepicker.Body(this, val, this.opts) + } else { + this.views[val]._render(); + } + + this.views[this.prevView].hide(); + this.views[val].show(); + this.nav._render(); + + if (this.opts.onChangeView) { + this.opts.onChangeView(val) + } + if (this.elIsInput && this.visible) this.setPosition(); + } + + return val + }, + + get view() { + return this.currentView; + }, + + get cellType() { + return this.view.substring(0, this.view.length - 1) + }, + + get minTime() { + var min = datepicker.getParsedDate(this.minDate); + return new Date(min.year, min.month, min.date).getTime() + }, + + get maxTime() { + var max = datepicker.getParsedDate(this.maxDate); + return new Date(max.year, max.month, max.date).getTime() + }, + + get curDecade() { + return datepicker.getDecade(this.date) + } + }; + + // Utils + // ------------------------------------------------- + + datepicker.getDaysCount = function (date) { + return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); + }; + + datepicker.getParsedDate = function (date) { + return { + year: date.getFullYear(), + month: date.getMonth(), + fullMonth: (date.getMonth() + 1) < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1, // One based + date: date.getDate(), + fullDate: date.getDate() < 10 ? '0' + date.getDate() : date.getDate(), + day: date.getDay(), + hours: date.getHours(), + fullHours: date.getHours() < 10 ? '0' + date.getHours() : date.getHours() , + minutes: date.getMinutes(), + fullMinutes: date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() + } + }; + + datepicker.getDecade = function (date) { + var firstYear = Math.floor(date.getFullYear() / 10) * 10; + + return [firstYear, firstYear + 9]; + }; + + datepicker.template = function (str, data) { + return str.replace(/#\{([\w]+)\}/g, function (source, match) { + if (data[match] || data[match] === 0) { + return data[match] + } + }); + }; + + datepicker.isSame = function (date1, date2, type) { + if (!date1 || !date2) return false; + var d1 = datepicker.getParsedDate(date1), + d2 = datepicker.getParsedDate(date2), + _type = type ? type : 'day', + + conditions = { + day: d1.date == d2.date && d1.month == d2.month && d1.year == d2.year, + month: d1.month == d2.month && d1.year == d2.year, + year: d1.year == d2.year + }; + + return conditions[_type]; + }; + + datepicker.less = function (dateCompareTo, date, type) { + if (!dateCompareTo || !date) return false; + return date.getTime() < dateCompareTo.getTime(); + }; + + datepicker.bigger = function (dateCompareTo, date, type) { + if (!dateCompareTo || !date) return false; + return date.getTime() > dateCompareTo.getTime(); + }; + + datepicker.getLeadingZeroNum = function (num) { + return parseInt(num) < 10 ? '0' + num : num; + }; + + /** + * Returns copy of date with hours and minutes equals to 0 + * @param date {Date} + */ + datepicker.resetTime = function (date) { + if (typeof date != 'object') return; + date = datepicker.getParsedDate(date); + return new Date(date.year, date.month, date.date) + }; + + $.fn.datepicker = function ( options ) { + return this.each(function () { + if (!$.data(this, pluginName)) { + $.data(this, pluginName, + new Datepicker( this, options )); + } else { + var _this = $.data(this, pluginName); + + _this.opts = $.extend(true, _this.opts, options); + _this.update(); + } + }); + }; + + $.fn.datepicker.Constructor = Datepicker; + + $.fn.datepicker.language = { + ru: { + days: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'], + daysShort: ['Вос','Пон','Вто','Сре','Чет','Пят','Суб'], + daysMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'], + months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'], + monthsShort: ['Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'], + today: 'Сегодня', + clear: 'Очистить', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 + } + }; + + $(function () { + $(autoInitSelector).datepicker(); + }) + +})(); + +;(function () { + var templates = { + days:'' + + '
' + + '
' + + '
' + + '
', + months: '' + + '
' + + '
' + + '
', + years: '' + + '
' + + '
' + + '
' + }, + datepicker = $.fn.datepicker, + dp = datepicker.Constructor; + + datepicker.Body = function (d, type, opts) { + this.d = d; + this.type = type; + this.opts = opts; + this.$el = $(''); + + if (this.opts.onlyTimepicker) return; + this.init(); + }; + + datepicker.Body.prototype = { + init: function () { + this._buildBaseHtml(); + this._render(); + + this._bindEvents(); + }, + + _bindEvents: function () { + this.$el.on('click', '.datepicker--cell', $.proxy(this._onClickCell, this)); + }, + + _buildBaseHtml: function () { + this.$el = $(templates[this.type]).appendTo(this.d.$content); + this.$names = $('.datepicker--days-names', this.$el); + this.$cells = $('.datepicker--cells', this.$el); + }, + + _getDayNamesHtml: function (firstDay, curDay, html, i) { + curDay = curDay != undefined ? curDay : firstDay; + html = html ? html : ''; + i = i != undefined ? i : 0; + + if (i > 7) return html; + if (curDay == 7) return this._getDayNamesHtml(firstDay, 0, html, ++i); + + html += '
' + this.d.loc.daysMin[curDay] + '
'; + + return this._getDayNamesHtml(firstDay, ++curDay, html, ++i); + }, + + _getCellContents: function (date, type) { + var classes = "datepicker--cell datepicker--cell-" + type, + currentDate = new Date(), + parent = this.d, + minRange = dp.resetTime(parent.minRange), + maxRange = dp.resetTime(parent.maxRange), + opts = parent.opts, + d = dp.getParsedDate(date), + render = {}, + html = d.date; + + switch (type) { + case 'day': + if (parent.isWeekend(d.day)) classes += " -weekend-"; + if (d.month != this.d.parsedDate.month) { + classes += " -other-month-"; + if (!opts.selectOtherMonths) { + classes += " -disabled-"; + } + if (!opts.showOtherMonths) html = ''; + } + break; + case 'month': + html = parent.loc[parent.opts.monthsField][d.month]; + break; + case 'year': + var decade = parent.curDecade; + html = d.year; + if (d.year < decade[0] || d.year > decade[1]) { + classes += ' -other-decade-'; + if (!opts.selectOtherYears) { + classes += " -disabled-"; + } + if (!opts.showOtherYears) html = ''; + } + break; + } + + if (opts.onRenderCell) { + render = opts.onRenderCell(date, type) || {}; + html = render.html ? render.html : html; + classes += render.classes ? ' ' + render.classes : ''; + } + + if (opts.range) { + if (dp.isSame(minRange, date, type)) classes += ' -range-from-'; + if (dp.isSame(maxRange, date, type)) classes += ' -range-to-'; + + if (parent.selectedDates.length == 1 && parent.focused) { + if ( + (dp.bigger(minRange, date) && dp.less(parent.focused, date)) || + (dp.less(maxRange, date) && dp.bigger(parent.focused, date))) + { + classes += ' -in-range-' + } + + if (dp.less(maxRange, date) && dp.isSame(parent.focused, date)) { + classes += ' -range-from-' + } + if (dp.bigger(minRange, date) && dp.isSame(parent.focused, date)) { + classes += ' -range-to-' + } + + } else if (parent.selectedDates.length == 2) { + if (dp.bigger(minRange, date) && dp.less(maxRange, date)) { + classes += ' -in-range-' + } + } + } + + + if (dp.isSame(currentDate, date, type)) classes += ' -current-'; + if (parent.focused && dp.isSame(date, parent.focused, type)) classes += ' -focus-'; + if (parent._isSelected(date, type)) classes += ' -selected-'; + if (!parent._isInRange(date, type) || render.disabled) classes += ' -disabled-'; + + return { + html: html, + classes: classes + } + }, + + /** + * Calculates days number to render. Generates days html and returns it. + * @param {object} date - Date object + * @returns {string} + * @private + */ + _getDaysHtml: function (date) { + var totalMonthDays = dp.getDaysCount(date), + firstMonthDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(), + lastMonthDay = new Date(date.getFullYear(), date.getMonth(), totalMonthDays).getDay(), + daysFromPevMonth = firstMonthDay - this.d.loc.firstDay, + daysFromNextMonth = 6 - lastMonthDay + this.d.loc.firstDay; + + daysFromPevMonth = daysFromPevMonth < 0 ? daysFromPevMonth + 7 : daysFromPevMonth; + daysFromNextMonth = daysFromNextMonth > 6 ? daysFromNextMonth - 7 : daysFromNextMonth; + + var startDayIndex = -daysFromPevMonth + 1, + m, y, + html = ''; + + for (var i = startDayIndex, max = totalMonthDays + daysFromNextMonth; i <= max; i++) { + y = date.getFullYear(); + m = date.getMonth(); + + html += this._getDayHtml(new Date(y, m, i)) + } + + return html; + }, + + _getDayHtml: function (date) { + var content = this._getCellContents(date, 'day'); + + return '
' + content.html + '
'; + }, + + /** + * Generates months html + * @param {object} date - date instance + * @returns {string} + * @private + */ + _getMonthsHtml: function (date) { + var html = '', + d = dp.getParsedDate(date), + i = 0; + + while(i < 12) { + html += this._getMonthHtml(new Date(d.year, i)); + i++ + } + + return html; + }, + + _getMonthHtml: function (date) { + var content = this._getCellContents(date, 'month'); + + return '
' + content.html + '
' + }, + + _getYearsHtml: function (date) { + var d = dp.getParsedDate(date), + decade = dp.getDecade(date), + firstYear = decade[0] - 1, + html = '', + i = firstYear; + + for (i; i <= decade[1] + 1; i++) { + html += this._getYearHtml(new Date(i , 0)); + } + + return html; + }, + + _getYearHtml: function (date) { + var content = this._getCellContents(date, 'year'); + + return '
' + content.html + '
' + }, + + _renderTypes: { + days: function () { + var dayNames = this._getDayNamesHtml(this.d.loc.firstDay), + days = this._getDaysHtml(this.d.currentDate); + + this.$cells.html(days); + this.$names.html(dayNames) + }, + months: function () { + var html = this._getMonthsHtml(this.d.currentDate); + + this.$cells.html(html) + }, + years: function () { + var html = this._getYearsHtml(this.d.currentDate); + + this.$cells.html(html) + } + }, + + _render: function () { + if (this.opts.onlyTimepicker) return; + this._renderTypes[this.type].bind(this)(); + }, + + _update: function () { + var $cells = $('.datepicker--cell', this.$cells), + _this = this, + classes, + $cell, + date; + $cells.each(function (cell, i) { + $cell = $(this); + date = _this.d._getDateFromCell($(this)); + classes = _this._getCellContents(date, _this.d.cellType); + $cell.attr('class',classes.classes) + }); + }, + + show: function () { + if (this.opts.onlyTimepicker) return; + this.$el.addClass('active'); + this.acitve = true; + }, + + hide: function () { + this.$el.removeClass('active'); + this.active = false; + }, + + // Events + // ------------------------------------------------- + + _handleClick: function (el) { + var date = el.data('date') || 1, + month = el.data('month') || 0, + year = el.data('year') || this.d.parsedDate.year, + dp = this.d; + // Change view if min view does not reach yet + if (dp.view != this.opts.minView) { + dp.down(new Date(year, month, date)); + return; + } + // Select date if min view is reached + var selectedDate = new Date(year, month, date), + alreadySelected = this.d._isSelected(selectedDate, this.d.cellType); + + if (!alreadySelected) { + dp._trigger('clickCell', selectedDate); + return; + } + + dp._handleAlreadySelectedDates.bind(dp, alreadySelected, selectedDate)(); + + }, + + _onClickCell: function (e) { + var $el = $(e.target).closest('.datepicker--cell'); + + if ($el.hasClass('-disabled-')) return; + + this._handleClick.bind(this)($el); + } + }; +})(); + +;(function () { + var template = '' + + '
#{prevHtml}
' + + '
#{title}
' + + '
#{nextHtml}
', + buttonsContainerTemplate = '
', + button = '#{label}', + datepicker = $.fn.datepicker, + dp = datepicker.Constructor; + + datepicker.Navigation = function (d, opts) { + this.d = d; + this.opts = opts; + + this.$buttonsContainer = ''; + + this.init(); + }; + + datepicker.Navigation.prototype = { + init: function () { + this._buildBaseHtml(); + this._bindEvents(); + }, + + _bindEvents: function () { + this.d.$nav.on('click', '.datepicker--nav-action', $.proxy(this._onClickNavButton, this)); + this.d.$nav.on('click', '.datepicker--nav-title', $.proxy(this._onClickNavTitle, this)); + this.d.$datepicker.on('click', '.datepicker--button', $.proxy(this._onClickNavButton, this)); + }, + + _buildBaseHtml: function () { + if (!this.opts.onlyTimepicker) { + this._render(); + } + this._addButtonsIfNeed(); + }, + + _addButtonsIfNeed: function () { + if (this.opts.todayButton) { + this._addButton('today') + } + if (this.opts.clearButton) { + this._addButton('clear') + } + }, + + _render: function () { + var title = this._getTitle(this.d.currentDate), + html = dp.template(template, $.extend({title: title}, this.opts)); + this.d.$nav.html(html); + if (this.d.view == 'years') { + $('.datepicker--nav-title', this.d.$nav).addClass('-disabled-'); + } + this.setNavStatus(); + }, + + _getTitle: function (date) { + return this.d.formatDate(this.opts.navTitles[this.d.view], date) + }, + + _addButton: function (type) { + if (!this.$buttonsContainer.length) { + this._addButtonsContainer(); + } + + var data = { + action: type, + label: this.d.loc[type] + }, + html = dp.template(button, data); + + if ($('[data-action=' + type + ']', this.$buttonsContainer).length) return; + this.$buttonsContainer.append(html); + }, + + _addButtonsContainer: function () { + this.d.$datepicker.append(buttonsContainerTemplate); + this.$buttonsContainer = $('.datepicker--buttons', this.d.$datepicker); + }, + + setNavStatus: function () { + if (!(this.opts.minDate || this.opts.maxDate) || !this.opts.disableNavWhenOutOfRange) return; + + var date = this.d.parsedDate, + m = date.month, + y = date.year, + d = date.date; + + switch (this.d.view) { + case 'days': + if (!this.d._isInRange(new Date(y, m-1, 1), 'month')) { + this._disableNav('prev') + } + if (!this.d._isInRange(new Date(y, m+1, 1), 'month')) { + this._disableNav('next') + } + break; + case 'months': + if (!this.d._isInRange(new Date(y-1, m, d), 'year')) { + this._disableNav('prev') + } + if (!this.d._isInRange(new Date(y+1, m, d), 'year')) { + this._disableNav('next') + } + break; + case 'years': + var decade = dp.getDecade(this.d.date); + if (!this.d._isInRange(new Date(decade[0] - 1, 0, 1), 'year')) { + this._disableNav('prev') + } + if (!this.d._isInRange(new Date(decade[1] + 1, 0, 1), 'year')) { + this._disableNav('next') + } + break; + } + }, + + _disableNav: function (nav) { + $('[data-action="' + nav + '"]', this.d.$nav).addClass('-disabled-') + }, + + _activateNav: function (nav) { + $('[data-action="' + nav + '"]', this.d.$nav).removeClass('-disabled-') + }, + + _onClickNavButton: function (e) { + var $el = $(e.target).closest('[data-action]'), + action = $el.data('action'); + + this.d[action](); + }, + + _onClickNavTitle: function (e) { + if ($(e.target).hasClass('-disabled-')) return; + + if (this.d.view == 'days') { + return this.d.view = 'months' + } + + this.d.view = 'years'; + } + } + +})(); + +;(function () { + var template = '
' + + '
' + + ' #{hourVisible}' + + ' :' + + ' #{minValue}' + + '
' + + '
' + + '
' + + ' ' + + '
' + + '
' + + ' ' + + '
' + + '
' + + '
', + datepicker = $.fn.datepicker, + dp = datepicker.Constructor; + + datepicker.Timepicker = function (inst, opts) { + this.d = inst; + this.opts = opts; + + this.init(); + }; + + datepicker.Timepicker.prototype = { + init: function () { + var input = 'input'; + this._setTime(this.d.date); + this._buildHTML(); + + if (navigator.userAgent.match(/trident/gi)) { + input = 'change'; + } + + this.d.$el.on('selectDate', this._onSelectDate.bind(this)); + this.$ranges.on(input, this._onChangeRange.bind(this)); + this.$ranges.on('mouseup', this._onMouseUpRange.bind(this)); + this.$ranges.on('mousemove focus ', this._onMouseEnterRange.bind(this)); + this.$ranges.on('mouseout blur', this._onMouseOutRange.bind(this)); + }, + + _setTime: function (date) { + var _date = dp.getParsedDate(date); + + this._handleDate(date); + this.hours = _date.hours < this.minHours ? this.minHours : _date.hours; + this.minutes = _date.minutes < this.minMinutes ? this.minMinutes : _date.minutes; + }, + + /** + * Sets minHours and minMinutes from date (usually it's a minDate) + * Also changes minMinutes if current hours are bigger then @date hours + * @param date {Date} + * @private + */ + _setMinTimeFromDate: function (date) { + this.minHours = date.getHours(); + this.minMinutes = date.getMinutes(); + + // If, for example, min hours are 10, and current hours are 12, + // update minMinutes to default value, to be able to choose whole range of values + if (this.d.lastSelectedDate) { + if (this.d.lastSelectedDate.getHours() > date.getHours()) { + this.minMinutes = this.opts.minMinutes; + } + } + }, + + _setMaxTimeFromDate: function (date) { + this.maxHours = date.getHours(); + this.maxMinutes = date.getMinutes(); + + if (this.d.lastSelectedDate) { + if (this.d.lastSelectedDate.getHours() < date.getHours()) { + this.maxMinutes = this.opts.maxMinutes; + } + } + }, + + _setDefaultMinMaxTime: function () { + var maxHours = 23, + maxMinutes = 59, + opts = this.opts; + + this.minHours = opts.minHours < 0 || opts.minHours > maxHours ? 0 : opts.minHours; + this.minMinutes = opts.minMinutes < 0 || opts.minMinutes > maxMinutes ? 0 : opts.minMinutes; + this.maxHours = opts.maxHours < 0 || opts.maxHours > maxHours ? maxHours : opts.maxHours; + this.maxMinutes = opts.maxMinutes < 0 || opts.maxMinutes > maxMinutes ? maxMinutes : opts.maxMinutes; + }, + + /** + * Looks for min/max hours/minutes and if current values + * are out of range sets valid values. + * @private + */ + _validateHoursMinutes: function (date) { + if (this.hours < this.minHours) { + this.hours = this.minHours; + } else if (this.hours > this.maxHours) { + this.hours = this.maxHours; + } + + if (this.minutes < this.minMinutes) { + this.minutes = this.minMinutes; + } else if (this.minutes > this.maxMinutes) { + this.minutes = this.maxMinutes; + } + }, + + _buildHTML: function () { + var lz = dp.getLeadingZeroNum, + data = { + hourMin: this.minHours, + hourMax: lz(this.maxHours), + hourStep: this.opts.hoursStep, + hourValue: this.hours, + hourVisible: lz(this.displayHours), + minMin: this.minMinutes, + minMax: lz(this.maxMinutes), + minStep: this.opts.minutesStep, + minValue: lz(this.minutes) + }, + _template = dp.template(template, data); + + this.$timepicker = $(_template).appendTo(this.d.$datepicker); + this.$ranges = $('[type="range"]', this.$timepicker); + this.$hours = $('[name="hours"]', this.$timepicker); + this.$minutes = $('[name="minutes"]', this.$timepicker); + this.$hoursText = $('.datepicker--time-current-hours', this.$timepicker); + this.$minutesText = $('.datepicker--time-current-minutes', this.$timepicker); + + if (this.d.ampm) { + this.$ampm = $('') + .appendTo($('.datepicker--time-current', this.$timepicker)) + .html(this.dayPeriod); + + this.$timepicker.addClass('-am-pm-'); + } + }, + + _updateCurrentTime: function () { + var h = dp.getLeadingZeroNum(this.displayHours), + m = dp.getLeadingZeroNum(this.minutes); + + this.$hoursText.html(h); + this.$minutesText.html(m); + + if (this.d.ampm) { + this.$ampm.html(this.dayPeriod); + } + }, + + _updateRanges: function () { + this.$hours.attr({ + min: this.minHours, + max: this.maxHours + }).val(this.hours); + + this.$minutes.attr({ + min: this.minMinutes, + max: this.maxMinutes + }).val(this.minutes) + }, + + /** + * Sets minHours, minMinutes etc. from date. If date is not passed, than sets + * values from options + * @param [date] {object} - Date object, to get values from + * @private + */ + _handleDate: function (date) { + this._setDefaultMinMaxTime(); + if (date) { + if (dp.isSame(date, this.d.opts.minDate)) { + this._setMinTimeFromDate(this.d.opts.minDate); + } else if (dp.isSame(date, this.d.opts.maxDate)) { + this._setMaxTimeFromDate(this.d.opts.maxDate); + } + } + + this._validateHoursMinutes(date); + }, + + update: function () { + this._updateRanges(); + this._updateCurrentTime(); + }, + + /** + * Calculates valid hour value to display in text input and datepicker's body. + * @param date {Date|Number} - date or hours + * @param [ampm] {Boolean} - 12 hours mode + * @returns {{hours: *, dayPeriod: string}} + * @private + */ + _getValidHoursFromDate: function (date, ampm) { + var d = date, + hours = date; + + if (date instanceof Date) { + d = dp.getParsedDate(date); + hours = d.hours; + } + + var _ampm = ampm || this.d.ampm, + dayPeriod = 'am'; + + if (_ampm) { + switch(true) { + case hours == 0: + hours = 12; + break; + case hours == 12: + dayPeriod = 'pm'; + break; + case hours > 11: + hours = hours - 12; + dayPeriod = 'pm'; + break; + default: + break; + } + } + + return { + hours: hours, + dayPeriod: dayPeriod + } + }, + + set hours (val) { + this._hours = val; + + var displayHours = this._getValidHoursFromDate(val); + + this.displayHours = displayHours.hours; + this.dayPeriod = displayHours.dayPeriod; + }, + + get hours() { + return this._hours; + }, + + // Events + // ------------------------------------------------- + + _onChangeRange: function (e) { + var $target = $(e.target), + name = $target.attr('name'); + + this.d.timepickerIsActive = true; + + this[name] = $target.val(); + this._updateCurrentTime(); + this.d._trigger('timeChange', [this.hours, this.minutes]); + + this._handleDate(this.d.lastSelectedDate); + this.update() + }, + + _onSelectDate: function (e, data) { + this._handleDate(data); + this.update(); + }, + + _onMouseEnterRange: function (e) { + var name = $(e.target).attr('name'); + $('.datepicker--time-current-' + name, this.$timepicker).addClass('-focus-'); + }, + + _onMouseOutRange: function (e) { + var name = $(e.target).attr('name'); + if (this.d.inFocus) return; // Prevent removing focus when mouse out of range slider + $('.datepicker--time-current-' + name, this.$timepicker).removeClass('-focus-'); + }, + + _onMouseUpRange: function (e) { + this.d.timepickerIsActive = false; + } + }; +})(); + })(window, jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.cs.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.cs.js new file mode 100644 index 0000000..a89db7c --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.cs.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['cs'] = { + days: ['Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota'], + daysShort: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'], + daysMin: ['Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So'], + months: ['Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec'], + monthsShort: ['Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čvn', 'Čvc', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro'], + today: 'Dnes', + clear: 'Vymazat', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.da.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.da.js new file mode 100644 index 0000000..f34456e --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.da.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['da'] = { + days: ['Søndag', 'Mandag', 'Tirsdag', 'Onsdag', 'Torsdag', 'Fredag', 'Lørdag'], + daysShort: ['Søn', 'Man', 'Tir', 'Ons', 'Tor', 'Fre', 'Lør'], + daysMin: ['Sø', 'Ma', 'Ti', 'On', 'To', 'Fr', 'Lø'], + months: ['Januar','Februar','Marts','April','Maj','Juni', 'Juli','August','September','Oktober','November','December'], + monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Maj', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'], + today: 'I dag', + clear: 'Nulstil', + dateFormat: 'dd/mm/yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.de.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.de.js new file mode 100644 index 0000000..fd9f8ff --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.de.js @@ -0,0 +1,13 @@ +;(function ($) { $.fn.datepicker.language['de'] = { + days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], + daysShort: ['Son', 'Mon', 'Die', 'Mit', 'Don', 'Fre', 'Sam'], + daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'], + months: ['Januar','Februar','März','April','Mai','Juni', 'Juli','August','September','Oktober','November','Dezember'], + monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], + today: 'Heute', + clear: 'Aufräumen', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; + })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.en.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.en.js new file mode 100644 index 0000000..32072f6 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.en.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['en'] = { + days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + daysShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + daysMin: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'], + months: ['January','February','March','April','May','June', 'July','August','September','October','November','December'], + monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + today: 'Today', + clear: 'Clear', + dateFormat: 'mm/dd/yyyy', + timeFormat: 'hh:ii aa', + firstDay: 0 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.es.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.es.js new file mode 100644 index 0000000..a8b6af5 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.es.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['es'] = { + days: ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'], + daysShort: ['Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab'], + daysMin: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'], + months: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Augosto','Septiembre','Octubre','Noviembre','Diciembre'], + monthsShort: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'], + today: 'Hoy', + clear: 'Limpiar', + dateFormat: 'dd/mm/yyyy', + timeFormat: 'hh:ii aa', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fi.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fi.js new file mode 100644 index 0000000..9619705 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fi.js @@ -0,0 +1,13 @@ +;(function ($) { $.fn.datepicker.language['fi'] = { + days: ['Sunnuntai', 'Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai'], + daysShort: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'], + daysMin: ['Su', 'Ma', 'Ti', 'Ke', 'To', 'Pe', 'La'], + months: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kesäkuu', 'Heinäkuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'], + monthsShort: ['Tammi', 'Helmi', 'Maalis', 'Huhti', 'Touko', 'Kesä', 'Heinä', 'Elo', 'Syys', 'Loka', 'Marras', 'Joulu'], + today: 'Tänään', + clear: 'Tyhjennä', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; + })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fr.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fr.js new file mode 100644 index 0000000..0d083b2 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.fr.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['fr'] = { + days: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'], + daysShort: ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'], + daysMin: ['Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa'], + months: ['Janvier','Février','Mars','Avril','Mai','Juin', 'Juillet','Août','Septembre','Octobre','Novembre','Decembre'], + monthsShort: ['Jan', 'Fév', 'Mars', 'Avr', 'Mai', 'Juin', 'Juil', 'Août', 'Sep', 'Oct', 'Nov', 'Dec'], + today: "Aujourd'hui", + clear: 'Effacer', + dateFormat: 'dd/mm/yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.hu.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.hu.js new file mode 100644 index 0000000..7d144b3 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.hu.js @@ -0,0 +1,12 @@ +;(function ($) { ;(function ($) { $.fn.datepicker.language['hu'] = { + days: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'], + daysShort: ['Va', 'Hé', 'Ke', 'Sze', 'Cs', 'Pé', 'Szo'], + daysMin: ['V', 'H', 'K', 'Sz', 'Cs', 'P', 'Sz'], + months: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június', 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'], + monthsShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún', 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'], + today: 'Ma', + clear: 'Törlés', + dateFormat: 'yyyy-mm-dd', + timeFormat: 'hh:ii aa', + firstDay: 1 +}; })(jQuery); })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.nl.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.nl.js new file mode 100644 index 0000000..8d29a5a --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.nl.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['nl'] = { + days: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'], + daysShort: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], + daysMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'], + months: ['Januari', 'Februari', 'Maart', 'April', 'Mei', 'Juni', 'Juli', 'Augustus', 'September', 'Oktober', 'November', 'December'], + monthsShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'], + today: 'Vandaag', + clear: 'Legen', + dateFormat: 'dd-MM-yy', + timeFormat: 'hh:ii', + firstDay: 0 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pl.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pl.js new file mode 100644 index 0000000..3c0f565 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pl.js @@ -0,0 +1,13 @@ +;(function ($) { $.fn.datepicker.language['pl'] = { + days: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'], + daysShort: ['Nie', 'Pon', 'Wto', 'Śro', 'Czw', 'Pią', 'Sob'], + daysMin: ['Nd', 'Pn', 'Wt', 'Śr', 'Czw', 'Pt', 'So'], + months: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec', 'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'], + monthsShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze', 'Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'], + today: 'Dzisiaj', + clear: 'Wyczyść', + dateFormat: 'yyyy-mm-dd', + timeFormat: 'hh:ii:aa', + firstDay: 1 +}; + })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt-BR.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt-BR.js new file mode 100644 index 0000000..13a79f5 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt-BR.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['pt-BR'] = { + days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'], + daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'], + daysMin: ['Do', 'Se', 'Te', 'Qu', 'Qu', 'Se', 'Sa'], + months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], + monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'], + today: 'Hoje', + clear: 'Limpar', + dateFormat: 'dd/mm/yyyy', + timeFormat: 'hh:ii', + firstDay: 0 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt.js new file mode 100644 index 0000000..92a3a08 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.pt.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['pt'] = { + days: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado'], + daysShort: ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab'], + daysMin: ['Do', 'Se', 'Te', 'Qa', 'Qi', 'Sx', 'Sa'], + months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], + monthsShort: ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'], + today: 'Hoje', + clear: 'Limpar', + dateFormat: 'dd/mm/yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.ro.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.ro.js new file mode 100644 index 0000000..0034204 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.ro.js @@ -0,0 +1,13 @@ +;(function ($) { $.fn.datepicker.language['ro'] = { + days: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'], + daysShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'], + daysMin: ['D', 'L', 'Ma', 'Mi', 'J', 'V', 'S'], + months: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie','Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'], + monthsShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun', 'Iul', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'], + today: 'Azi', + clear: 'Şterge', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; + })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.sk.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.sk.js new file mode 100644 index 0000000..3312386 --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.sk.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['sk'] = { + days: ['Nedeľa', 'Pondelok', 'Utorok', 'Streda', 'Štvrtok', 'Piatok', 'Sobota'], + daysShort: ['Ned', 'Pon', 'Uto', 'Str', 'Štv', 'Pia', 'Sob'], + daysMin: ['Ne', 'Po', 'Ut', 'St', 'Št', 'Pi', 'So'], + months: ['Január','Február','Marec','Apríl','Máj','Jún', 'Júl','August','September','Október','November','December'], + monthsShort: ['Jan', 'Feb', 'Mar', 'Apr', 'Máj', 'Jún', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dec'], + today: 'Dnes', + clear: 'Vymazať', + dateFormat: 'dd.mm.yyyy', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.zh.js b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.zh.js new file mode 100644 index 0000000..08633cc --- /dev/null +++ b/mirzaev/skillparts/system/web/js/calendar/i18n/datepicker.zh.js @@ -0,0 +1,12 @@ +;(function ($) { $.fn.datepicker.language['zh'] = { + days: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'], + daysShort: ['日', '一', '二', '三', '四', '五', '六'], + daysMin: ['日', '一', '二', '三', '四', '五', '六'], + months: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + monthsShort: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'], + today: '今天', + clear: '清除', + dateFormat: 'yyyy-mm-dd', + timeFormat: 'hh:ii', + firstDay: 1 +}; })(jQuery); \ No newline at end of file diff --git a/mirzaev/skillparts/system/web/js/cart.js b/mirzaev/skillparts/system/web/js/cart.js index 4c740ad..b198d90 100644 --- a/mirzaev/skillparts/system/web/js/cart.js +++ b/mirzaev/skillparts/system/web/js/cart.js @@ -143,13 +143,14 @@ function cart_list_delete(target, amount = 0) { /** * Изменить количество товара в корзине */ -function cart_list_amount_update(target, input) { - if (target !== undefined && input !== undefined) { +function cart_list_amount_update(target, type, input) { + if (target !== undefined && target !== null && type !== undefined && type !== null && input !== undefined && input !== null) { // Обработка входных параметров // Инициализация let targets = {}; - targets[target] = input.value; + targets[target] = {}; + targets[target][type] = input.value; $.ajax({ url: '/order/amount-update', @@ -162,10 +163,10 @@ function cart_list_amount_update(target, input) { success: cart_response_success, error: cart_response_error }); - }; - // Пересчитывание стоимости - cart_cost_calculate(); + // Пересчитывание стоимости + cart_cost_calculate(); + }; return false; }; @@ -191,10 +192,10 @@ function cart_cost_calculate() { /** * Изменить количество товара в корзине */ -function cart_list_comment_edit(catn, element) { - if (catn !== null && catn !== undefined && element !== null && element !== undefined) { +function cart_list_comment_edit(catn, type, element) { + if (catn !== undefined && catn !== null && type !== undefined && type !== null && element !== undefined && element !== null) { // Инициализация textarea - element.innerHTML = ''; + element.innerHTML = ''; element.removeAttribute('onclick'); @@ -242,7 +243,7 @@ function cart_list_comment_edit(catn, element) { function () { let textarea = document.getElementById(element.id + '-textarea'); - textarea.setAttribute('onchange', 'return cart_list_comment_save(\'' + catn + '\', this.parentElement)'); + textarea.setAttribute('onchange', 'return cart_list_comment_save(\'' + catn + '\', \'' + type + '\', this.parentElement)'); }); return false; @@ -251,8 +252,8 @@ function cart_list_comment_edit(catn, element) { return true; }; -function cart_list_comment_save(catn, element) { - if (catn !== null && catn !== undefined && element !== null && element !== undefined) { +function cart_list_comment_save(catn, type, element) { + if (catn !== null && catn !== undefined && type !== null && type !== undefined && element !== null && element !== undefined) { // Инициализация let text = element.children[0].value; @@ -275,6 +276,7 @@ function cart_list_comment_save(catn, element) { dataType: 'json', data: { '_csrf': yii.getCsrfToken(), + 'type': type, 'text': text }, success: function (data, status, xhr) { diff --git a/mirzaev/skillparts/system/web/js/geolocation.js b/mirzaev/skillparts/system/web/js/geolocation.js index 01fbe9c..c75848c 100644 --- a/mirzaev/skillparts/system/web/js/geolocation.js +++ b/mirzaev/skillparts/system/web/js/geolocation.js @@ -1,4 +1,4 @@ -// Инициализация геолокации +// Инициализация геолокации (запись геолокации по айпи, если не существует) function geolocation_init() { $.ajax({ url: '/profile/geolocation/init', @@ -12,6 +12,44 @@ function geolocation_init() { geolocation_init(); +// Запись геолокации (точный режим из браузера по запросу) +function geolocation_gps() { + + // Запрос геолокации у пользователя + navigator.geolocation.getCurrentPosition( + geolocation_gps_success, + geolocation_gps_error, + { + enableHighAccuracy: true + } + ); +}; + +// Получено подтверждение выдачи геолокации от пользователя +function geolocation_gps_success({ coords }) { + + // Инициализация + const { latitude, longitude } = coords; + + // Запрос + $.ajax({ + url: '/profile/geolocation/write', + type: 'post', + dataType: 'json', + data: { + 'latitude': latitude, + 'longitude': longitude, + '_csrf': yii.getCsrfToken() + }, + success: geolocation_success, + error: geolocation_error + }); +}; + +// Не получено подтверждение выдачи геолокации от пользователя +function geolocation_gps_error({ message }) { +}; + function geolocation_responce(data, status, xhr) { // Обработка ответов @@ -21,6 +59,17 @@ function geolocation_responce(data, status, xhr) { function geolocation_success(data, status, xhr) { // Обработка ответов от удавшихся запросов + if (data !== undefined) { + // Получены данные с сервера + + + // Запрос более точной геолокации + if (data.requestGps !== undefined && data.requestGps === true) { + + geolocation_gps(); + } + }; + geolocation_responce(data, status, xhr); }; diff --git a/mirzaev/skillparts/system/web/js/main.js b/mirzaev/skillparts/system/web/js/main.js index 232d328..f95ed1a 100644 --- a/mirzaev/skillparts/system/web/js/main.js +++ b/mirzaev/skillparts/system/web/js/main.js @@ -6,6 +6,7 @@ function main_response(data, status, xhr) { // Основной блок if (data.main !== undefined) { + // Инициализация main = document.getElementsByTagName('main')[0]; @@ -18,18 +19,21 @@ function main_response(data, status, xhr) { // Заголовок if (data.title !== undefined) { + // Запись document.title = data.title; }; // Перенаправление if (data.redirect !== undefined) { + // Перенаправление history.pushState({}, document.title, data.redirect); }; // CSRF-токен if (data._csrf !== undefined) { + // Обновление документа $('meta[name=csrf-token]').prop("content", data._csrf); }; @@ -41,7 +45,6 @@ var page_loaded_for_history = window.history.state; window.addEventListener('popstate', function() { if (page_loaded_for_history) { - console.log('сработало'); window.location.reload(); }; }, false); diff --git a/mirzaev/skillparts/system/web/js/orders.js b/mirzaev/skillparts/system/web/js/orders.js index b74b1a1..3fd51f8 100644 --- a/mirzaev/skillparts/system/web/js/orders.js +++ b/mirzaev/skillparts/system/web/js/orders.js @@ -1,5 +1,5 @@ // Запросить заказы -function orders_read(type = 'all', from, to) { +function orders_read(type = 'all', from, to, panel = 'orders_panel_orders') { // type = 'last' (оставить без изменений и взять данные из cookie // Пустые from и to тоже возьмутся из текущих значений в cookie @@ -10,14 +10,16 @@ function orders_read(type = 'all', from, to) { data = { '_csrf': yii.getCsrfToken(), 'from': from, - 'to': to + 'to': to, + 'panel': panel }; } else { // Данные периода не переданы // Инициализация буфера с данными запроса data = { - '_csrf': yii.getCsrfToken() + '_csrf': yii.getCsrfToken(), + 'panel': panel }; }; @@ -31,11 +33,21 @@ function orders_read(type = 'all', from, to) { error: orders_response_error }); - // Пересчитывание стоимости - cart_cost_calculate(); + // // Пересчитывание стоимости + // cart_cost_calculate(); return false; -} +}; + +function orders_calendar_select(formattedDate, date, inst) { + if (orders_calendar_ready === true && date[0] !== undefined && date[1] !== undefined) { + // Обе даты получены + + // Поиск заказов + orders_read('last', date[0] / 1000, date[1] / 1000); + } + +}; function orders_response(data, status, xhr) { // Обработка ответов diff --git a/mirzaev/skillparts/system/web/js/profile.js b/mirzaev/skillparts/system/web/js/profile.js index 47decc0..9b14042 100644 --- a/mirzaev/skillparts/system/web/js/profile.js +++ b/mirzaev/skillparts/system/web/js/profile.js @@ -136,12 +136,6 @@ function page_profile_monitoring(change = 1, panel) { function page_profile_response(data, status, xhr) { // Обработка ответов - main_response(data, status, xhr); -}; - -function page_profile_response_success(data, status, xhr) { - // Обработка ответов от удавшихся запросов - if (data !== undefined) { // Получены данные с сервера @@ -152,6 +146,12 @@ function page_profile_response_success(data, status, xhr) { }; }; + main_response(data, status, xhr); +}; + +function page_profile_response_success(data, status, xhr) { + // Обработка ответов от удавшихся запросов + page_profile_response(data, status, xhr); };