diff --git a/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php b/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php new file mode 100644 index 0000000000000000000000000000000000000000..73046749a66bfae1f68a81376c9d2963ba995ae9 --- /dev/null +++ b/app/code/Magento/Captcha/Model/Cart/ConfigPlugin.php @@ -0,0 +1,35 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Captcha\Model\Cart; + +class ConfigPlugin +{ + /** + * @var \Magento\Captcha\Model\Checkout\ConfigProvider + */ + protected $configProvider; + + /** + * @param \Magento\Captcha\Model\Checkout\ConfigProvider $configProvider + */ + public function __construct( + \Magento\Captcha\Model\Checkout\ConfigProvider $configProvider + ) { + $this->configProvider = $configProvider; + } + + /** + * @param \Magento\Checkout\Block\Cart\Sidebar $subject + * @param array $result + * @return array + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterGetConfig(\Magento\Checkout\Block\Cart\Sidebar $subject, array $result) + { + return array_merge_recursive($result, $this->configProvider->getConfig()); + } +} diff --git a/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php b/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php deleted file mode 100644 index eac1d7a74421e4994531d7cc71858d5690609fed..0000000000000000000000000000000000000000 --- a/app/code/Magento/Captcha/Model/Checkout/Plugin/Validation.php +++ /dev/null @@ -1,60 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Captcha\Model\Checkout\Plugin; - -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Exception\InputException; - -class Validation -{ - /** - * @var \Magento\Captcha\Helper\Data - */ - protected $captchaHelper; - - /** - * @var array - */ - protected $formIds; - - /** - * @param \Magento\Captcha\Helper\Data $captchaHelper - * @param array $formIds - */ - public function __construct( - \Magento\Captcha\Helper\Data $captchaHelper, - array $formIds - ) { - $this->captchaHelper = $captchaHelper; - $this->formIds = $formIds; - } - - /** - * @param \Magento\Quote\Model\AddressAdditionalDataProcessor $subject - * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @throws \Magento\Framework\Exception\InputException - * @return void - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function beforeProcess( - \Magento\Quote\Model\AddressAdditionalDataProcessor $subject, - \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData - ) { - $formId = $additionalData->getExtensionAttributes()->getCaptchaFormId(); - $captchaText = $additionalData->getExtensionAttributes()->getCaptchaString(); - - if ($formId !== null && !in_array($formId, $this->formIds)) { - throw new NoSuchEntityException(__('Provided form does not exist')); - } - $captchaModel = $this->captchaHelper->getCaptcha($formId); - if ($captchaModel->isRequired()) { - if (!$captchaModel->isCorrect($captchaText)) { - throw new InputException(__('Incorrect CAPTCHA')); - } - } - } -} diff --git a/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php b/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php index 39edd79861db2de45bc2f3c508c17afb9f3b3cd6..65cb2d8612abd20e6c3cf8a380de5a00f69cdd0c 100644 --- a/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php +++ b/app/code/Magento/Captcha/Model/Customer/Plugin/AjaxLogin.php @@ -26,53 +26,67 @@ class AjaxLogin */ protected $resultJsonFactory; + /** + * @var array + */ + protected $formIds; + /** * @param CaptchaHelper $helper * @param SessionManagerInterface $sessionManager * @param JsonFactory $resultJsonFactory + * @param array $formIds */ public function __construct( CaptchaHelper $helper, SessionManagerInterface $sessionManager, - JsonFactory $resultJsonFactory + JsonFactory $resultJsonFactory, + array $formIds ) { $this->helper = $helper; $this->sessionManager = $sessionManager; $this->resultJsonFactory = $resultJsonFactory; + $this->formIds = $formIds; } /** * @param \Magento\Customer\Controller\Ajax\Login $subject * @param callable $proceed - * @return \Magento\Framework\Controller\ResultInterface + * @return $this + * @throws \Magento\Framework\Exception\NoSuchEntityException * @throws \Zend_Json_Exception + * @SuppressWarnings(PHPMD.NPathComplexity) */ public function aroundExecute( \Magento\Customer\Controller\Ajax\Login $subject, \Closure $proceed ) { - $loginFormId = 'user_login'; + $captchaFormIdField = 'captcha_form_id'; $captchaInputName = 'captcha_string'; /** @var \Magento\Framework\App\RequestInterface $request */ $request = $subject->getRequest(); - /** @var \Magento\Captcha\Model\ModelInterface $captchaModel */ - $captchaModel = $this->helper->getCaptcha($loginFormId); - $loginParams = \Zend_Json::decode($request->getContent()); $username = isset($loginParams['username']) ? $loginParams['username'] : null; - $captchaString = isset($loginParams[$captchaInputName]) - ? $loginParams[$captchaInputName] - : null; + $captchaString = isset($loginParams[$captchaInputName]) ? $loginParams[$captchaInputName] : null; + $loginFormId = isset($loginParams[$captchaFormIdField]) ? $loginParams[$captchaFormIdField] : null; - if ($captchaModel->isRequired($username)) { - $captchaModel->logAttempt($username); - if (!$captchaModel->isCorrect($captchaString)) { - $this->sessionManager->setUsername($username); - /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + foreach ($this->formIds as $formId) { + $captchaModel = $this->helper->getCaptcha($formId); + if ($captchaModel->isRequired($username) && !in_array($loginFormId, $this->formIds)) { $resultJson = $this->resultJsonFactory->create(); - return $resultJson->setData(['errors' => true, 'message' => __('Incorrect CAPTCHA')]); + return $resultJson->setData(['errors' => true, 'message' => __('Provided form does not exist')]); + } + + if ($formId == $loginFormId) { + $captchaModel->logAttempt($username); + if (!$captchaModel->isCorrect($captchaString)) { + $this->sessionManager->setUsername($username); + /** @var \Magento\Framework\Controller\Result\Json $resultJson */ + $resultJson = $this->resultJsonFactory->create(); + return $resultJson->setData(['errors' => true, 'message' => __('Incorrect CAPTCHA')]); + } } } return $proceed(); diff --git a/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php b/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fd47b19ea9038c553c8183b13066421b94236cfa --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Controller/Refresh/IndexTest.php @@ -0,0 +1,122 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Captcha\Test\Unit\Controller\Refresh; + +class IndexTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $requestMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $responseMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $contextMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $viewMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $layoutMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $flagMock; + + /** + * @var \Magento\Captcha\Controller\Refresh\Index + */ + protected $model; + + protected function setUp() + { + $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false); + $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false); + $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + $this->responseMock = $this->getMock('Magento\Framework\App\Response\Http', [], [], '', false); + $this->contextMock = $this->getMock('Magento\Framework\App\Action\Context', [], [], '', false); + $this->viewMock = $this->getMock('Magento\Framework\App\ViewInterface'); + $this->layoutMock = $this->getMock('Magento\Framework\View\LayoutInterface'); + $this->flagMock = $this->getMock('Magento\Framework\App\ActionFlag', [], [], '', false); + + $this->contextMock->expects($this->any())->method('getRequest')->will($this->returnValue($this->requestMock)); + $this->contextMock->expects($this->any())->method('getView')->will($this->returnValue($this->viewMock)); + $this->contextMock->expects($this->any())->method('getResponse')->will($this->returnValue($this->responseMock)); + $this->contextMock->expects($this->any())->method('getActionFlag')->will($this->returnValue($this->flagMock)); + $this->viewMock->expects($this->any())->method('getLayout')->will($this->returnValue($this->layoutMock)); + + $this->model = new \Magento\Captcha\Controller\Refresh\Index($this->contextMock, $this->captchaHelperMock); + } + + /** + * @dataProvider executeDataProvider + * @param int $formId + * @param int $callsNumber + */ + public function testExecute($formId, $callsNumber) + { + $content = ['formId' => $formId]; + + $blockMethods = ['setFormId', 'setIsAjax', 'toHtml']; + $blockMock = $this->getMock('Magento\Captcha\Block\Captcha', $blockMethods, [], '', false); + + $this->requestMock->expects($this->any())->method('getPost')->with('formId')->will($this->returnValue($formId)); + $this->requestMock->expects($this->exactly($callsNumber))->method('getContent') + ->will($this->returnValue(json_encode($content))); + $this->captchaHelperMock->expects($this->any())->method('getCaptcha')->with($formId) + ->will($this->returnValue($this->captchaMock)); + $this->captchaMock->expects($this->once())->method('generate'); + $this->captchaMock->expects($this->once())->method('getBlockName')->will($this->returnValue('block')); + $this->captchaMock->expects($this->once())->method('getImgSrc')->will($this->returnValue('source')); + $this->layoutMock->expects($this->once())->method('createBlock')->with('block') + ->will($this->returnValue($blockMock)); + $blockMock->expects($this->any())->method('setFormId')->with($formId)->will($this->returnValue($blockMock)); + $blockMock->expects($this->any())->method('setIsAjax')->with(true)->will($this->returnValue($blockMock)); + $blockMock->expects($this->once())->method('toHtml'); + $this->responseMock->expects($this->once())->method('representJson')->with(json_encode(['imgSrc' => 'source'])); + $this->flagMock->expects($this->once())->method('set')->with('', 'no-postDispatch', true); + + $this->model->execute(); + } + + /** + * @return array + */ + public function executeDataProvider() + { + return [ + [ + 'formId' => null, + 'callsNumber' => 1, + ], + [ + 'formId' => 1, + 'callsNumber' => 0, + ] + ]; + } +} diff --git a/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php b/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..addc768e6c571efc38a2fa613195b6d6b791a5eb --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Model/Checkout/ConfigProviderTest.php @@ -0,0 +1,121 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Captcha\Test\Unit\Model\Checkout; + +class ConfigProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + + /** + * @var integer + */ + protected $formId = 1; + + /** + * @var \Magento\Captcha\Model\Checkout\ConfigProvider + */ + protected $model; + + protected function setUp() + { + $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false); + $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false); + $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + $formIds = [$this->formId]; + + $this->model = new \Magento\Captcha\Model\Checkout\ConfigProvider( + $this->storeManagerMock, + $this->captchaHelperMock, + $formIds + ); + } + + /** + * @dataProvider getConfigDataProvider + * @param bool $isRequired + * @param integer $captchaGenerations + * @param array $expectedConfig + */ + public function testGetConfig($isRequired, $captchaGenerations, $expectedConfig) + { + $this->captchaHelperMock->expects($this->any())->method('getCaptcha')->with($this->formId) + ->will($this->returnValue($this->captchaMock)); + + $this->captchaMock->expects($this->any())->method('isCaseSensitive')->will($this->returnValue(1)); + $this->captchaMock->expects($this->any())->method('getHeight')->will($this->returnValue('12px')); + $this->captchaMock->expects($this->any())->method('isRequired')->will($this->returnValue($isRequired)); + + $this->captchaMock->expects($this->exactly($captchaGenerations))->method('generate'); + $this->captchaMock->expects($this->exactly($captchaGenerations))->method('getImgSrc') + ->will($this->returnValue('source')); + + $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock)); + $this->storeMock->expects($this->once())->method('isCurrentlySecure')->will($this->returnValue(true)); + $this->storeMock->expects($this->once())->method('getUrl')->with('captcha/refresh', ['_secure' => true]) + ->will($this->returnValue('https://magento.com/captcha')); + + $config = $this->model->getConfig(); + $this->assertEquals($config, $expectedConfig); + } + + /** + * @return array + */ + public function getConfigDataProvider() + { + return [ + [ + 'isRequired' => true, + 'captchaGenerations' => 1, + 'expectedConfig' => [ + 'captcha' => [ + $this->formId => [ + 'isCaseSensitive' => true, + 'imageHeight' => '12px', + 'imageSrc' => 'source', + 'refreshUrl' => 'https://magento.com/captcha', + 'isRequired' => true + ], + ], + ], + ], + [ + 'isRequired' => false, + 'captchaGenerations' => 0, + 'expectedConfig' => [ + 'captcha' => [ + $this->formId => [ + 'isCaseSensitive' => true, + 'imageHeight' => '12px', + 'imageSrc' => '', + 'refreshUrl' => 'https://magento.com/captcha', + 'isRequired' => false + ], + ], + ], + ], + ]; + } +} diff --git a/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php b/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7a79969f8ef4f17c760547f7b7496821b18e9fec --- /dev/null +++ b/app/code/Magento/Captcha/Test/Unit/Model/Customer/Plugin/AjaxLoginTest.php @@ -0,0 +1,173 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Captcha\Test\Unit\Model\Customer\Plugin; + +class AjaxLoginTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $sessionManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $jsonFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $captchaMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $resultJsonMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $requestMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $loginControllerMock; + + /** + * @var array + */ + protected $formIds; + + /** + * @var \Magento\Captcha\Model\Customer\Plugin\AjaxLogin + */ + protected $model; + + protected function setUp() + { + $this->sessionManagerMock = $this->getMock('Magento\Checkout\Model\Session', ['setUsername'], [], '', false); + $this->captchaHelperMock = $this->getMock('Magento\Captcha\Helper\Data', [], [], '', false); + $this->captchaMock = $this->getMock('Magento\Captcha\Model\DefaultModel', [], [], '', false); + $this->jsonFactoryMock = $this->getMock( + 'Magento\Framework\Controller\Result\JsonFactory', + ['create'], + [], + '', + false + ); + $this->resultJsonMock = $this->getMock('Magento\Framework\Controller\Result\Json', [], [], '', false); + $this->requestMock = $this->getMock('Magento\Framework\App\Request\Http', [], [], '', false); + $this->loginControllerMock = $this->getMock('Magento\Customer\Controller\Ajax\Login', [], [], '', false); + + $this->loginControllerMock->expects($this->any())->method('getRequest') + ->will($this->returnValue($this->requestMock)); + $this->captchaHelperMock->expects($this->once())->method('getCaptcha') + ->with('user_login')->will($this->returnValue($this->captchaMock)); + $this->formIds = ['user_login']; + + $this->model = new \Magento\Captcha\Model\Customer\Plugin\AjaxLogin( + $this->captchaHelperMock, + $this->sessionManagerMock, + $this->jsonFactoryMock, + $this->formIds + ); + } + + public function testAroundExecute() + { + $username = 'name'; + $captchaString = 'string'; + $requestContent = json_encode([ + 'username' => $username, + 'captcha_string' => $captchaString, + 'captcha_form_id' => $this->formIds[0] + ]); + + $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent)); + $this->captchaMock->expects($this->once())->method('isRequired')->with($username) + ->will($this->returnValue(true)); + $this->captchaMock->expects($this->once())->method('logAttempt')->with($username); + $this->captchaMock->expects($this->once())->method('isCorrect')->with($captchaString) + ->will($this->returnValue(true)); + + $closure = function () { + return 'result'; + }; + $this->assertEquals('result', $this->model->aroundExecute($this->loginControllerMock, $closure)); + } + + public function testAroundExecuteIncorrectCaptcha() + { + $username = 'name'; + $captchaString = 'string'; + $requestContent = json_encode([ + 'username' => $username, + 'captcha_string' => $captchaString, + 'captcha_form_id' => $this->formIds[0] + ]); + + $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent)); + $this->captchaMock->expects($this->once())->method('isRequired')->with($username) + ->will($this->returnValue(true)); + $this->captchaMock->expects($this->once())->method('logAttempt')->with($username); + $this->captchaMock->expects($this->once())->method('isCorrect') + ->with($captchaString)->will($this->returnValue(false)); + + $this->sessionManagerMock->expects($this->once())->method('setUsername')->with($username); + $this->jsonFactoryMock->expects($this->once())->method('create') + ->will($this->returnValue($this->resultJsonMock)); + + $this->resultJsonMock->expects($this->once())->method('setData') + ->with(['errors' => true, 'message' => __('Incorrect CAPTCHA')])->will($this->returnValue('response')); + + $closure = function () { + }; + $this->assertEquals('response', $this->model->aroundExecute($this->loginControllerMock, $closure)); + } + + /** + * @dataProvider aroundExecuteCaptchaIsNotRequired + * @param string $username + * @param array $requestContent + */ + public function testAroundExecuteCaptchaIsNotRequired($username, $requestContent) + { + $this->requestMock->expects($this->once())->method('getContent')->will($this->returnValue($requestContent)); + + $this->captchaMock->expects($this->once())->method('isRequired')->with($username) + ->will($this->returnValue(false)); + $this->captchaMock->expects($this->never())->method('logAttempt')->with($username); + $this->captchaMock->expects($this->never())->method('isCorrect'); + + $closure = function () { + return 'result'; + }; + $this->assertEquals('result', $this->model->aroundExecute($this->loginControllerMock, $closure)); + } + + /** + * @return array + */ + public function aroundExecuteCaptchaIsNotRequired() + { + return [ + [ + 'username' => 'name', + 'requestContent' => json_encode(['username' => 'name', 'captcha_string' => 'string']), + ], + [ + 'username' => null, + 'requestContent' => json_encode(['captcha_string' => 'string']), + ], + ]; + } +} diff --git a/app/code/Magento/Captcha/composer.json b/app/code/Magento/Captcha/composer.json index 987ef790dfd28fc18a1e0a87488a86213f350154..a52065c0e94a4ddbcde9e27a053311b619e9519d 100644 --- a/app/code/Magento/Captcha/composer.json +++ b/app/code/Magento/Captcha/composer.json @@ -6,7 +6,6 @@ "magento/module-store": "0.74.0-beta15", "magento/module-customer": "0.74.0-beta15", "magento/module-checkout": "0.74.0-beta15", - "magento/module-quote": "0.74.0-beta15", "magento/module-backend": "0.74.0-beta15", "magento/framework": "0.74.0-beta15", "magento/magento-composer-installer": "*" diff --git a/app/code/Magento/Captcha/etc/di.xml b/app/code/Magento/Captcha/etc/di.xml index 2f150515f4ef38c3d2b14eb746aac1409d422dc6..6dfdcd70b2222544e04939b7eb1aa4404dd07083 100644 --- a/app/code/Magento/Captcha/etc/di.xml +++ b/app/code/Magento/Captcha/etc/di.xml @@ -19,16 +19,15 @@ <type name="Magento\Customer\Controller\Ajax\Login"> <plugin name="configurable_product" type="Magento\Captcha\Model\Customer\Plugin\AjaxLogin" sortOrder="50" /> </type> - <type name="Magento\Quote\Model\AddressAdditionalDataProcessor"> - <plugin name="captcha_validation" type="\Magento\Captcha\Model\Checkout\Plugin\Validation" /> - </type> - <type name="Magento\Captcha\Model\Checkout\Plugin\Validation"> + <type name="Magento\Captcha\Model\Customer\Plugin\AjaxLogin"> <arguments> <argument name="formIds" xsi:type="array"> <item name="user_login" xsi:type="string">user_login</item> <item name="guest_checkout" xsi:type="string">guest_checkout</item> - <item name="register_during_checkout" xsi:type="string">register_during_checkout</item> </argument> </arguments> </type> + <type name="Magento\Checkout\Block\Cart\Sidebar"> + <plugin name="login_captcha" type="\Magento\Captcha\Model\Cart\ConfigPlugin" sortOrder="50" /> + </type> </config> diff --git a/app/code/Magento/Captcha/etc/extension_attributes.xml b/app/code/Magento/Captcha/etc/extension_attributes.xml deleted file mode 100644 index e99af65250102d4db36964850c3ee1d602f08b99..0000000000000000000000000000000000000000 --- a/app/code/Magento/Captcha/etc/extension_attributes.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0"?> -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Api/etc/extension_attributes.xsd"> - <extension_attributes for="Magento\Quote\Api\Data\AddressAdditionalDataInterface"> - <attribute code="captcha_string" type="string" /> - <attribute code="captcha_form_id" type="string" /> - </extension_attributes> -</config> - - diff --git a/app/code/Magento/Captcha/etc/frontend/di.xml b/app/code/Magento/Captcha/etc/frontend/di.xml index 4807eb77b726076246107bddfc1acbac299d83a6..a768ffac2f67e372ed36af36133105b7ca909f54 100644 --- a/app/code/Magento/Captcha/etc/frontend/di.xml +++ b/app/code/Magento/Captcha/etc/frontend/di.xml @@ -18,7 +18,6 @@ <argument name="formIds" xsi:type="array"> <item name="user_login" xsi:type="string">user_login</item> <item name="guest_checkout" xsi:type="string">guest_checkout</item> - <item name="register_during_checkout" xsi:type="string">register_during_checkout</item> </argument> </arguments> </type> diff --git a/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml index 3154d7f81876805131083c4912ab3e0fbf93cc87..d7d6fc551c5ff3f777effb8a6cf3b573c60113a1 100644 --- a/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Captcha/view/frontend/layout/checkout_onepage_index.xml @@ -5,7 +5,7 @@ * See COPYING.txt for license details. */ --> -<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> <arguments> @@ -13,30 +13,59 @@ <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> + <item name="authentication" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="captcha" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="formId" xsi:type="string">user_login</item> + <item name="configSource" xsi:type="string">checkoutConfig</item> + </item> + </item> + </item> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="authentication" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="captcha" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item> - <item name="displayArea" xsi:type="string">additional-login-form-fields</item> - <item name="formId" xsi:type="string">user_login</item> + <item name="shippingAddress" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="customer-email" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="additional-login-form-fields" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="captcha" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="formId" xsi:type="string">guest_checkout</item> + <item name="configSource" xsi:type="string">checkoutConfig</item> + </item> + </item> + </item> + </item> + </item> + </item> </item> </item> </item> - <item name="billingAddress" xsi:type="array"> + <item name="billing-step" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="captcha_guest_checkout" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/guestCaptcha</item> - <item name="displayArea" xsi:type="string">additional-fieldsets</item> - <item name="formId" xsi:type="string">guest_checkout</item> - <item name="dataScope" xsi:type="string">additionalAddressData</item> - </item> - <item name="captcha_register_during_checkout" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/registerCaptcha</item> - <item name="displayArea" xsi:type="string">additional-fieldsets</item> - <item name="formId" xsi:type="string">register_during_checkout</item> - <item name="dataScope" xsi:type="string">additionalAddressData</item> + <item name="payment" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="customer-email" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="additional-login-form-fields" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="captcha" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="formId" xsi:type="string">guest_checkout</item> + <item name="configSource" xsi:type="string">checkoutConfig</item> + </item> + </item> + </item> + </item> + </item> + </item> </item> </item> </item> @@ -49,4 +78,4 @@ </arguments> </referenceBlock> </body> -</page> \ No newline at end of file +</page> diff --git a/app/code/Magento/Captcha/view/frontend/layout/default.xml b/app/code/Magento/Captcha/view/frontend/layout/default.xml new file mode 100644 index 0000000000000000000000000000000000000000..9e0bf3cc751c5c0b9fad96ea62e3da31b26ed320 --- /dev/null +++ b/app/code/Magento/Captcha/view/frontend/layout/default.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="minicart"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="minicart_content" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="sign-in-popup" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="captcha" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Captcha/js/view/checkout/loginCaptcha</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="formId" xsi:type="string">user_login</item> + <item name="configSource" xsi:type="string">checkout</item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js b/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js index cc8b2119827216883b9330c5717d5cbf1d460337..b11ae9b1f144aee227da25267b86dd7cc7ed1681 100644 --- a/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js +++ b/app/code/Magento/Captcha/view/frontend/web/js/action/refresh.js @@ -9,9 +9,10 @@ define( function(storage) { "use strict"; return function(refreshUrl, formId, imageSource) { - storage.post( + return storage.post( refreshUrl, - JSON.stringify({'formId': formId}) + JSON.stringify({'formId': formId}), + false ).done( function (response) { if (response.imgSrc) { diff --git a/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js b/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js index a8abae3cc8de7638c7c6414df11a646935e3e715..6a720a8cdeb91879729ecc3ca4aa85f3e497f3bd 100644 --- a/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js +++ b/app/code/Magento/Captcha/view/frontend/web/js/model/captcha.js @@ -6,10 +6,11 @@ /*global alert*/ define( [ + 'jquery', 'ko', 'Magento_Captcha/js/action/refresh' ], - function(ko, refreshAction) { + function($, ko, refreshAction) { return function (captchaData) { return { formId: captchaData.formId, @@ -20,6 +21,7 @@ define( isCaseSensitive: captchaData.isCaseSensitive, imageHeight: captchaData.imageHeight, refreshUrl: captchaData.refreshUrl, + isLoading: ko.observable(false), getFormId: function () { return this.formId; @@ -70,7 +72,14 @@ define( this.captchaValue(value); }, refresh: function() { - refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource()); + var refresh, + self = this; + this.isLoading(true); + + refresh = refreshAction(this.getRefreshUrl(), this.getFormId(), this.getImageSource()); + $.when(refresh).done(function() { + self.isLoading(false); + }); } }; } diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js index 5039e6a56a4d254c1f3763c3ead7d62efc481f81..ddb4a6f84ae57bf22a0c9396a5843658813f0785 100644 --- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js +++ b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/defaultCaptcha.js @@ -7,15 +7,14 @@ define( [ 'jquery', - 'ko', 'uiComponent', - 'Magento_Customer/js/model/customer', 'Magento_Captcha/js/model/captcha', 'Magento_Captcha/js/model/captchaList' ], - function ($, ko, Component, customer, Captcha, captchaList) { - "use strict"; - var captchaConfig = window.checkoutConfig.captcha; + function ($, Component, Captcha, captchaList) { + 'use strict'; + var captchaConfig; + return Component.extend({ defaults: { template: 'Magento_Captcha/checkout/captcha' @@ -26,11 +25,16 @@ define( return this.currentCaptcha.getCaptchaValue(); }, initialize: function() { + this._super(); + captchaConfig = window[this.configSource]['captcha']; + $.each(captchaConfig, function(formId, captchaData) { captchaData.formId = formId; captchaList.add(Captcha(captchaData)); }); - this._super(); + }, + getIsLoading: function() { + return this.currentCaptcha.isLoading }, getCurrentCaptcha: function() { return this.currentCaptcha; diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js deleted file mode 100644 index eb7e9c806e64bd94da1086bf4e92af253ce8027a..0000000000000000000000000000000000000000 --- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/guestCaptcha.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true jquery:true*/ -/*global define*/ -define( - [ - 'Magento_Captcha/js/view/checkout/defaultCaptcha', - 'Magento_Checkout/js/model/quote', - 'Magento_Captcha/js/model/captchaList', - 'Magento_Checkout/js/action/select-shipping-address', - 'Magento_Checkout/js/action/select-billing-address', - 'Magento_Checkout/js/model/step-navigator' - ], - function (defaultCaptcha, quote, captchaList, selectShippingAddress, selectBillingAddress, navigator) { - "use strict"; - return defaultCaptcha.extend({ - initialize: function() { - this._super(); - var self = this; - var currentCaptcha = captchaList.getCaptchaByFormId(this.formId); - if (currentCaptcha != null) { - this.setCurrentCaptcha(currentCaptcha); - quote.getCheckoutMethod().subscribe(function(method) { - if (method == 'guest') { - self.setIsVisible(true); - var callback = function(isSuccessful) { - if (!isSuccessful) { - currentCaptcha.setCaptchaValue(null); - currentCaptcha.refresh(); - navigator.goToStep('billingAddress'); - } - }; - selectShippingAddress.setActionCallback(callback); - selectBillingAddress.setActionCallback(callback); - } else { - self.setIsVisible(false); - } - }); - } - } - }); - } -); diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js index e042e96e850e6558926cd6612a8a9d7526635c77..75f7c4f0071dc96da86f13112f3d8c04190e6a02 100644 --- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js +++ b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/loginCaptcha.js @@ -7,26 +7,25 @@ define( [ 'Magento_Captcha/js/view/checkout/defaultCaptcha', - 'Magento_Customer/js/model/customer', - 'Magento_Captcha/js/model/captchaList' + 'Magento_Captcha/js/model/captchaList', + 'Magento_Customer/js/action/login' ], - function (defaultCaptcha, customer, captchaList) { - "use strict"; + function (defaultCaptcha, captchaList, loginAction) { + 'use strict'; return defaultCaptcha.extend({ initialize: function() { this._super(); - var currentCaptcha = captchaList.getCaptchaByFormId(this.formId); + var currentCaptcha = captchaList.getCaptchaByFormId(this.formId), + self = this; + if (currentCaptcha != null) { currentCaptcha.setIsVisible(true); this.setCurrentCaptcha(currentCaptcha); - this.updateCaptchaOnFailedLogin(); - } - }, - updateCaptchaOnFailedLogin: function () { - if (this.formId == 'user_login') { - var self = this; - customer.getFailedLoginAttempts().subscribe(function() { - self.refresh(); + + loginAction.registerLoginCallback(function(loginData) { + if (loginData.captcha_form_id && loginData.captcha_form_id == self.formId) { + self.refresh(); + } }); } } diff --git a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js b/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js deleted file mode 100644 index ea284b5fe562483669319af1c308409d4e137358..0000000000000000000000000000000000000000 --- a/app/code/Magento/Captcha/view/frontend/web/js/view/checkout/registerCaptcha.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true jquery:true*/ -/*global define*/ -define( - [ - 'Magento_Captcha/js/view/checkout/defaultCaptcha', - 'Magento_Checkout/js/model/quote', - 'Magento_Captcha/js/model/captchaList', - 'Magento_Checkout/js/action/select-shipping-address', - 'Magento_Checkout/js/action/select-billing-address', - 'Magento_Checkout/js/model/step-navigator' - ], - function (defaultCaptcha, quote, captchaList, selectShippingAddress, selectBillingAddress, navigator) { - "use strict"; - return defaultCaptcha.extend({ - initialize: function() { - this._super(); - var self = this; - var currentCaptcha = captchaList.getCaptchaByFormId(this.formId); - if (currentCaptcha != null) { - this.setCurrentCaptcha(currentCaptcha); - quote.getCheckoutMethod().subscribe(function(method) { - if (method == 'register') { - self.setIsVisible(true); - var callback = function(isSuccessful) { - if (!isSuccessful) { - currentCaptcha.setCaptchaValue(null); - currentCaptcha.refresh(); - navigator.goToStep('billingAddress'); - } - }; - selectShippingAddress.setActionCallback(callback); - selectBillingAddress.setActionCallback(callback); - } else { - self.setIsVisible(false); - } - }); - } - } - }); - } -); diff --git a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html index fd345b82386446b5553ef81f3ce56b5e1c70f158..3b294d904b2cbe877dd80763986aa7fa66ecf89b 100644 --- a/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html +++ b/app/code/Magento/Captcha/view/frontend/web/template/checkout/captcha.html @@ -5,7 +5,7 @@ */ --> <!-- ko if: (isRequired() && getIsVisible())--> -<div class="field captcha required"> +<div class="field captcha required" data-bind="blockLoader: getIsLoading()"> <label data-bind="attr: {for: 'captcha_' + formId}" class="label"><span data-bind="text: $t('Please type the letters below')"></span></label> <div class="control captcha"> <input name="captcha_string" type="text" class="input-text required-entry" data-bind="value: captchaValue(), attr: {id: 'captcha_' + formId, 'data-scope': dataScope}" /> diff --git a/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5b0f7dd0f9340b1c33eb6b1ec0d41b749243e620 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Helper/Product/ConfigurationPoolTest.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Helper\Product; + +class ConfigurationPoolTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var array + */ + protected $instancesType; + + /** + * @var \Magento\Catalog\Helper\Product\ConfigurationPool + */ + protected $model; + + protected function setUp() + { + $this->instancesType = ['simple' => 'simple', 'default' => 'default']; + + $objectManagerMock = $this->getMock('Magento\Framework\ObjectManagerInterface'); + $this->model = new \Magento\Catalog\Helper\Product\ConfigurationPool($objectManagerMock, $this->instancesType); + } + + /** + * @dataProvider getByProductTypeDataProvider + * @param string $productType + * @param string $expectedResult + */ + public function testGetByProductType($productType, $expectedResult) + { + $this->assertEquals($expectedResult, $this->model->getByProductType($productType)); + } + + /** + * @return array + */ + public function getByProductTypeDataProvider() + { + return [ + [ + 'productType' => 'simple', + 'expectedResult' => 'simple' + ], + [ + 'productType' => 'custom', + 'expectedResult' => 'default' + ], + ]; + } +} diff --git a/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php b/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ea68c7aa5d85f7b00d7d3c96431c509e8b30388f --- /dev/null +++ b/app/code/Magento/Checkout/Api/Data/PaymentDetailsInterface.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api\Data; + +interface PaymentDetailsInterface +{ + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const PAYMENT_METHODS = 'payment_methods'; + + const TOTALS = 'totals'; + + /**#@-*/ + + /** + * @return \Magento\Quote\Api\Data\PaymentMethodInterface[] + */ + public function getPaymentMethods(); + + /** + * @param \Magento\Quote\Api\Data\PaymentMethodInterface[] $paymentMethods + * @return $this + */ + public function setPaymentMethods($paymentMethods); + + /** + * @return \Magento\Quote\Api\Data\TotalsInterface + */ + public function getTotals(); + + /** + * @param \Magento\Quote\Api\Data\TotalsInterface $totals + * @return $this + */ + public function setTotals($totals); + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php b/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..9b2b3710eb3ae4b521e96712312a2f2718cc53e6 --- /dev/null +++ b/app/code/Magento/Checkout/Api/Data/ShippingInformationInterface.php @@ -0,0 +1,82 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api\Data; + +interface ShippingInformationInterface extends \Magento\Framework\Api\CustomAttributesDataInterface +{ + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const SHIPPING_ADDRESS = 'shipping_address'; + + const SHIPPING_METHOD_CODE = 'shipping_method_code'; + + const SHIPPING_CARRIER_CODE = 'shipping_carrier_code'; + + /**#@-*/ + + /** + * Returns shipping address + * + * @return \Magento\Quote\Api\Data\AddressInterface + */ + public function getShippingAddress(); + + /** + * Set shipping address + * + * @param \Magento\Quote\Api\Data\AddressInterface $address + * @return $this + */ + public function setShippingAddress(\Magento\Quote\Api\Data\AddressInterface $address); + + /** + * Returns shipping method code + * + * @return string + */ + public function getShippingMethodCode(); + + /** + * Set shipping method code + * + * @param string $code + * @return $this + */ + public function setShippingMethodCode($code); + + /** + * Returns carrier code + * + * @return string + */ + public function getShippingCarrierCode(); + + /** + * Set carrier code + * + * @param string $code + * @return $this + */ + public function setShippingCarrierCode($code); + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php b/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..7a2b178aa6691c64a9e00618c30f8717006a0220 --- /dev/null +++ b/app/code/Magento/Checkout/Api/GuestPaymentInformationManagementInterface.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api; + +interface GuestPaymentInformationManagementInterface +{ + /** + * Set payment information and place order for a specified cart. + * + * @param string $cartId + * @param string $email + * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod + * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return int Order ID. + */ + public function savePaymentInformationAndPlaceOrder( + $cartId, + $email, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ); + + /** + * Set payment information for a specified cart. + * + * @param string $cartId + * @param string $email + * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod + * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return int Order ID. + */ + public function savePaymentInformation( + $cartId, + $email, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ); +} diff --git a/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php b/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c52ee4a7766b8b8dfa6e6b55b76a16a4d2e8a786 --- /dev/null +++ b/app/code/Magento/Checkout/Api/GuestShippingInformationManagementInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api; + +interface GuestShippingInformationManagementInterface +{ + /** + * @param string $cartId + * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + * @return \Magento\Checkout\Api\Data\PaymentDetailsInterface + */ + public function saveAddressInformation( + $cartId, + \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + ); +} diff --git a/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php b/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bac301c7ab3695bc691aa74e5b9b764a366427a1 --- /dev/null +++ b/app/code/Magento/Checkout/Api/PaymentInformationManagementInterface.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api; + +interface PaymentInformationManagementInterface +{ + /** + * Set payment information and place order for a specified cart. + * + * @param int $cartId + * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod + * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return int Order ID. + */ + public function savePaymentInformationAndPlaceOrder( + $cartId, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ); + + /** + * Set payment information for a specified cart. + * + * @param int $cartId + * @param \Magento\Quote\Api\Data\PaymentInterface $paymentMethod + * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress + * @throws \Magento\Framework\Exception\CouldNotSaveException + * @return int Order ID. + */ + public function savePaymentInformation( + $cartId, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ); +} diff --git a/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php b/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..4f39b764b35b9c3b7bbedbaf4914b7c6a732d77f --- /dev/null +++ b/app/code/Magento/Checkout/Api/ShippingInformationManagementInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Api; + +interface ShippingInformationManagementInterface +{ + /** + * @param int $cartId + * @param \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + * @return \Magento\Checkout\Api\Data\PaymentDetailsInterface + */ + public function saveAddressInformation( + $cartId, + \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + ); +} diff --git a/app/code/Magento/Checkout/Block/Cart/Sidebar.php b/app/code/Magento/Checkout/Block/Cart/Sidebar.php index 593f1bd35806d975c41fba9806a6586c538a2950..a754a3c6582c58f3a1dcd4ec8f90f234a2ffaeff 100644 --- a/app/code/Magento/Checkout/Block/Cart/Sidebar.php +++ b/app/code/Magento/Checkout/Block/Cart/Sidebar.php @@ -52,6 +52,25 @@ class Sidebar extends AbstractCart $this->imageView = $imageView; } + /** + * Returns minicart config + * + * @return array + */ + public function getConfig() + { + return [ + 'shoppingCartUrl' => $this->getShoppingCartUrl(), + 'checkoutUrl' => $this->getCheckoutUrl(), + 'updateItemQtyUrl' => $this->getUpdateItemQtyUrl(), + 'removeItemUrl' => $this->getRemoveItemUrl(), + 'imageTemplate' => $this->getImageHtmlTemplate(), + 'customerRegisterUrl' => $this->getCustomerRegisterUrlUrl(), + 'customerForgotPasswordUrl' => $this->getCustomerForgotPasswordUrl(), + 'baseUrl' => $this->getBaseUrl() + ]; + } + /** * @return string */ @@ -139,4 +158,34 @@ class Sidebar extends AbstractCart { return $this->getLayout()->getBlock('checkout.cart.minicart.totals')->toHtml(); } + + /** + * Get customer register url + * + * @return string + */ + public function getCustomerRegisterUrlUrl() + { + return $this->getUrl('customer/account/create'); + } + + /** + * Get customer forgot password url + * + * @return string + */ + public function getCustomerForgotPasswordUrl() + { + return $this->getUrl('customer/account/forgotpassword'); + } + + /** + * Return base url. + * + * @return string + */ + public function getBaseUrl() + { + return $this->_storeManager->getStore()->getBaseUrl(); + } } diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php index 224079faff6ff237b82ffa3ddf482d83d486a62f..32609252f0552023241063773f18a2f61c82fe02 100644 --- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php +++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php @@ -125,6 +125,9 @@ class AttributeMerger 'elementTmpl' => isset($additionalConfig['config']['elementTmpl']) ? $additionalConfig['config']['elementTmpl'] : $elementTemplate, + 'tooltip' => isset($additionalConfig['config']['tooltip']) + ? $additionalConfig['config']['tooltip'] + : null ], 'dataScope' => $dataScopePrefix . '.' . $attributeCode, 'label' => $attributeConfig['label'], @@ -141,7 +144,7 @@ class AttributeMerger $defaultValue = $this->getDefaultValue($attributeCode); if (null !== $defaultValue) { - $element['default'] = $defaultValue; + $element['value'] = $defaultValue; } return $element; } diff --git a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php index 9f5ffc3f6ef6dca215aaa6c100d57d4b4009dc8b..20332513a009f078db5fc7cd3468894ccaaac593 100644 --- a/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/Checkout/Block/Checkout/LayoutProcessor.php @@ -60,26 +60,29 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso } // The following code is a workaround for custom address attributes - if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billingAddress'] - ['children']['billing-address-fieldset']['children'] + if (isset($jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children'] )) { - $fields = $jsLayout['components']['checkout']['children']['steps']['children']['billingAddress'] - ['children']['billing-address-fieldset']['children']; - $jsLayout['components']['checkout']['children']['steps']['children']['billingAddress'] - ['children']['billing-address-fieldset']['children'] = $this->merger->merge( - $elements, - 'checkoutProvider', - 'billingAddress', - $fields - ); + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'] = + array_merge_recursive( + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['payments-list']['children'], + $this->processPaymentConfiguration( + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children'] + ['payment']['children']['renders']['children'], + $elements + ) + ); } - if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress'] - ['children']['shipping-address-fieldset']['children'] + + if (isset($jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] + ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] )) { - $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress'] - ['children']['shipping-address-fieldset']['children']; - $jsLayout['components']['checkout']['children']['steps']['children']['shippingAddress'] - ['children']['shipping-address-fieldset']['children'] = $this->merger->merge( + $fields = $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] + ['children']['shippingAddress']['children']['shipping-address-fieldset']['children']; + $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step'] + ['children']['shippingAddress']['children']['shipping-address-fieldset']['children'] = $this->merger->merge( $elements, 'checkoutProvider', 'shippingAddress', @@ -88,4 +91,90 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso } return $jsLayout; } + + /** + * Inject billing address component into every payment component + * + * @param array $configuration list of payment components + * @param array $elements attributes that must be displayed in address form + * @return array + */ + private function processPaymentConfiguration(array &$configuration, array $elements) + { + $output = []; + foreach ($configuration as $paymentGroup => $groupConfig) { + foreach ($groupConfig['methods'] as $paymentCode => $paymentComponent) { + if (empty($paymentComponent['isBillingAddressRequired'])) { + continue; + } + $output[$paymentCode . '-form'] = [ + 'component' => 'Magento_Checkout/js/view/billing-address', + 'displayArea' => 'billing-address-form-' . $paymentCode, + 'provider' => 'checkoutProvider', + 'dataScopePrefix' => 'billingAddress' . $paymentCode, + 'sortOrder' => 1, + 'children' => [ + 'form-fields' => [ + 'component' => 'uiComponent', + 'displayArea' => 'additional-fieldsets', + 'children' => $this->merger->merge( + $elements, + 'checkoutProvider', + 'billingAddress' . $paymentCode, + [ + 'country_id' => [ + 'sortOrder' => 115, + ], + 'region' => [ + 'visible' => false, + ], + 'region_id' => [ + 'component' => 'Magento_Ui/js/form/element/region', + 'config' => [ + 'template' => 'ui/form/field', + 'elementTmpl' => 'ui/form/element/select', + 'customEntry' => 'billingAddress' . $paymentCode . '.region', + ], + 'validation' => [ + 'validate-select' => true, + ], + 'filterBy' => [ + 'target' => '${ $.provider }:${ $.parentScope }.country_id', + 'field' => 'country_id', + ], + ], + 'postcode' => [ + 'component' => 'Magento_Ui/js/form/element/post-code', + 'validation' => [ + 'required-entry' => true, + ], + ], + 'company' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'fax' => [ + 'validation' => [ + 'min_text_length' => 0, + ], + ], + 'telephone' => [ + 'config' => [ + 'tooltip' => [ + 'description' => 'For delivery Questions', + ], + ], + ], + ] + ), + ], + ], + ]; + } + unset($configuration[$paymentGroup]['methods']); + } + + return $output; + } } diff --git a/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php b/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php new file mode 100644 index 0000000000000000000000000000000000000000..af5a8a51dd456490a1e1f66329cb1f83f94cc088 --- /dev/null +++ b/app/code/Magento/Checkout/Block/Checkout/TotalsProcessor.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Block\Checkout; + +use Magento\Framework\App\Config\ScopeConfigInterface; + +class TotalsProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcessorInterface +{ + /** + * Core store config + * + * @var ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @param ScopeConfigInterface $scopeConfig + */ + public function __construct( + ScopeConfigInterface $scopeConfig + ) { + $this->scopeConfig = $scopeConfig; + } + + /** + * {@inheritdoc} + */ + public function process($jsLayout) + { + $configData = $this->scopeConfig->getValue('sales/totals_sort'); + $totals = $jsLayout['components']['checkout']['children']['summary']['children']['totals']['children']; + foreach ($totals as $code => &$total) { + //convert JS naming style to config naming style + $code = str_replace('-', '_', $code); + if (array_key_exists($code, $configData)) { + $total['sortOrder'] = $configData[$code]; + } + } + $jsLayout['components']['checkout']['children']['summary']['children']['totals']['children'] = $totals; + + return array_merge_recursive($jsLayout, $totals); + } +} diff --git a/app/code/Magento/Checkout/Controller/Onepage/Index.php b/app/code/Magento/Checkout/Controller/Onepage/Index.php index 991511fc02267a4d6a250fb78576b0feaa08ad14..7fa9fa794c5fb5ab4441324cc716e26bec15c987 100644 --- a/app/code/Magento/Checkout/Controller/Onepage/Index.php +++ b/app/code/Magento/Checkout/Controller/Onepage/Index.php @@ -15,11 +15,19 @@ class Index extends \Magento\Checkout\Controller\Onepage */ public function execute() { - if (!$this->_objectManager->get('Magento\Checkout\Helper\Data')->canOnepageCheckout()) { + $checkoutHelper = $this->_objectManager->get('Magento\Checkout\Helper\Data'); + if (!$checkoutHelper->canOnepageCheckout()) { $this->messageManager->addError(__('One-page checkout is turned off.')); return $this->resultRedirectFactory->create()->setPath('checkout/cart'); } + $quote = $this->getOnepage()->getQuote(); + + if (!$this->_customerSession->isLoggedIn() && !$checkoutHelper->isAllowedGuestCheckout($quote)) { + $this->messageManager->addError(__('Guest checkout is disabled.')); + return $this->resultRedirectFactory->create()->setPath('checkout/cart'); + } + if (!$quote->hasItems() || $quote->getHasError() || !$quote->validateMinimumAmount()) { return $this->resultRedirectFactory->create()->setPath('checkout/cart'); } diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php index ae306dc9439a26fedb5282ced36980fd55476887..55fd454db8aeb8d42bb6674d6ad0336f9e45c1ff 100644 --- a/app/code/Magento/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Checkout/CustomerData/Cart.php @@ -94,6 +94,7 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface 'possible_onepage_checkout' => $this->isPossibleOnepageCheckout(), 'items' => $this->getRecentItems(), 'extra_actions' => $this->layout->createBlock('Magento\Catalog\Block\ShortcutButtons')->toHtml(), + 'isGuestCheckoutAllowed' => $this->isGuestCheckoutAllowed(), ]; } @@ -173,4 +174,14 @@ class Cart extends \Magento\Framework\Object implements SectionSourceInterface } return $this->getQuote()->getAllVisibleItems(); } + + /** + * Check if guest checkout is allowed + * + * @return bool + */ + public function isGuestCheckoutAllowed() + { + return $this->checkoutHelper->isAllowedGuestCheckout($this->checkoutSession->getQuote()); + } } diff --git a/app/code/Magento/Checkout/Model/Cart/ImageProvider.php b/app/code/Magento/Checkout/Model/Cart/ImageProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..f49b267b88a8ea7441b817fdb5a9fe42fe13b187 --- /dev/null +++ b/app/code/Magento/Checkout/Model/Cart/ImageProvider.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Model\Cart; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ImageProvider +{ + /** + * @var \Magento\Quote\Api\CartItemRepositoryInterface + */ + protected $itemRepository; + + /** + * @var \Magento\Checkout\CustomerData\ItemPoolInterface + */ + protected $itemPool; + + /** + * @param \Magento\Quote\Api\CartItemRepositoryInterface $itemRepository + * @param \Magento\Checkout\CustomerData\ItemPoolInterface $itemPool + */ + public function __construct( + \Magento\Quote\Api\CartItemRepositoryInterface $itemRepository, + \Magento\Checkout\CustomerData\ItemPoolInterface $itemPool + ) { + $this->itemRepository = $itemRepository; + $this->itemPool = $itemPool; + } + + /** + * {@inheritdoc} + */ + public function getImages($cartId) + { + $itemData = []; + + /** @see code/Magento/Catalog/Helper/Product.php */ + $items = $this->itemRepository->getList($cartId); + /** @var \Magento\Quote\Model\Quote\Item $cartItem */ + foreach ($items as $cartItem) { + $allData = $this->itemPool->getItemData($cartItem); + $itemData[$cartItem->getItemId()] = $allData['product_image']; + } + return $itemData; + } +} diff --git a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php index 08de243b3a16294460af5e94807652592114ab90..21911aec850fcdc82c6163d2684fc10869fa8421 100644 --- a/app/code/Magento/Checkout/Model/DefaultConfigProvider.php +++ b/app/code/Magento/Checkout/Model/DefaultConfigProvider.php @@ -6,7 +6,6 @@ namespace Magento\Checkout\Model; use Magento\Checkout\Helper\Data as CheckoutHelper; -use Magento\Checkout\Model\Type\Onepage as OnepageCheckout; use Magento\Checkout\Model\Session as CheckoutSession; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; use Magento\Customer\Model\Context as CustomerContext; @@ -23,6 +22,9 @@ use Magento\Catalog\Helper\Product\ConfigurationPool; use Magento\Quote\Model\QuoteIdMaskFactory; use Magento\Framework\Locale\FormatInterface as LocaleFormat; use Magento\Framework\UrlInterface; +use Magento\Quote\Api\CartTotalRepositoryInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -120,6 +122,53 @@ class DefaultConfigProvider implements ConfigProviderInterface */ protected $viewConfig; + /** + * @var \Magento\Directory\Model\Country\Postcode\ConfigInterface + */ + protected $postCodesConfig; + + /** + * @var \Magento\Directory\Helper\Data + */ + protected $directoryHelper; + + /** + * @var Cart\ImageProvider + */ + protected $imageProvider; + + /** + * @var CartTotalRepositoryInterface + */ + protected $cartTotalRepository; + + /** + * Shipping method data factory. + * + * @var \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory + */ + protected $estimatedAddressFactory; + + /** + * @var ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @var \Magento\Shipping\Model\Config + */ + protected $shippingMethodConfig; + + /** + * @var \Magento\Store\Model\StoreManagerInterface + */ + protected $storeManager; + + /** + * @var \Magento\Quote\Api\PaymentMethodManagementInterface + */ + protected $paymentMethodManagement; + /** * @param CheckoutHelper $checkoutHelper * @param Session $checkoutSession @@ -139,6 +188,15 @@ class DefaultConfigProvider implements ConfigProviderInterface * @param FormKey $formKey * @param \Magento\Catalog\Helper\Image $imageHelper * @param \Magento\Framework\View\ConfigInterface $viewConfig + * @param \Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig + * @param Cart\ImageProvider $imageProvider + * @param \Magento\Directory\Helper\Data $directoryHelper + * @param CartTotalRepositoryInterface $cartTotalRepository + * @param \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory $estimatedAddressFactory + * @param ScopeConfigInterface $scopeConfig + * @param \Magento\Shipping\Model\Config $shippingMethodConfig + * @param \Magento\Store\Model\StoreManagerInterface $storeManager + * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -159,7 +217,16 @@ class DefaultConfigProvider implements ConfigProviderInterface \Magento\Customer\Model\Address\Config $addressConfig, FormKey $formKey, \Magento\Catalog\Helper\Image $imageHelper, - \Magento\Framework\View\ConfigInterface $viewConfig + \Magento\Framework\View\ConfigInterface $viewConfig, + \Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig, + Cart\ImageProvider $imageProvider, + \Magento\Directory\Helper\Data $directoryHelper, + CartTotalRepositoryInterface $cartTotalRepository, + \Magento\Quote\Api\Data\EstimateAddressInterfaceFactory $estimatedAddressFactory, + ScopeConfigInterface $scopeConfig, + \Magento\Shipping\Model\Config $shippingMethodConfig, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement ) { $this->checkoutHelper = $checkoutHelper; $this->checkoutSession = $checkoutSession; @@ -179,6 +246,15 @@ class DefaultConfigProvider implements ConfigProviderInterface $this->formKey = $formKey; $this->imageHelper = $imageHelper; $this->viewConfig = $viewConfig; + $this->postCodesConfig = $postCodesConfig; + $this->imageProvider = $imageProvider; + $this->directoryHelper = $directoryHelper; + $this->cartTotalRepository = $cartTotalRepository; + $this->estimatedAddressFactory = $estimatedAddressFactory; + $this->scopeConfig = $scopeConfig; + $this->shippingMethodConfig = $shippingMethodConfig; + $this->storeManager = $storeManager; + $this->paymentMethodManagement = $paymentMethodManagement; } /** @@ -186,6 +262,7 @@ class DefaultConfigProvider implements ConfigProviderInterface */ public function getConfig() { + $quoteId = $this->checkoutSession->getQuote()->getId(); return [ 'formKey' => $this->formKey->getFormKey(), 'customerData' => $this->getCustomerData(), @@ -207,10 +284,72 @@ class DefaultConfigProvider implements ConfigProviderInterface 'basePriceFormat' => $this->localeFormat->getPriceFormat( null, $this->currencyManager->getDefaultCurrency() - ) + ), + 'postCodes' => $this->postCodesConfig->getPostCodes(), + 'imageData' => $this->imageProvider->getImages($quoteId), + 'countryData' => $this->getCountryData(), + 'totalsData' => $this->getTotalsData(), + 'shippingRates' => $this->getDefaultShippingRates(), + 'shippingPolicy' => [ + 'isEnabled' => $this->scopeConfig->isSetFlag( + 'shipping/shipping_policy/enable_shipping_policy', + ScopeInterface::SCOPE_STORE + ), + 'shippingPolicyContent' => nl2br( + $this->scopeConfig->getValue( + 'shipping/shipping_policy/shipping_policy_content', + ScopeInterface::SCOPE_STORE + ) + ) + ], + 'activeCarriers' => $this->getActiveCarriers(), + 'originCountryCode' => $this->getOriginCountryCode(), + 'paymentMethods' => $this->getPaymentMethods() ]; } + /** + * Get default shipping rates + * + * @return array + */ + private function getDefaultShippingRates() + { + $output = []; + $addressKey = null; + if ($this->checkoutSession->getQuote()->getId()) { + $quote = $this->quoteRepository->get($this->checkoutSession->getQuote()->getId()); + /** @var \Magento\Quote\Api\Data\EstimateAddressInterface $estimatedAddress */ + $estimatedAddress = $this->estimatedAddressFactory->create(); + + $address = $quote->getShippingAddress(); + if ($address && + ($address->getCountryId() + || $address->getPostcode() + || $address->getRegion() + || $address->getRegionId() + ) + ) { + $estimatedAddress->setCountryId($address->getCountryId()); + $estimatedAddress->setPostcode($address->getPostcode()); + $estimatedAddress->setRegion($address->getRegion()); + $estimatedAddress->setRegionId($address->getRegionId()); + } else { + $estimatedAddress->setCountryId($this->directoryHelper->getDefaultCountry()); + } + $rates = $this->shippingMethodManager->estimateByAddress($quote->getId(), $estimatedAddress); + foreach ($rates as $rate) { + $output[] = $rate->__toArray(); + } + + if ($address->getCustomerAddressId()) { + $addressKey = 'customer-address' . $address->getCustomerAddressId(); + } + }; + return ['key' => $addressKey, 'data' => $output]; + + } + /** * Retrieve customer data * @@ -270,13 +409,6 @@ class DefaultConfigProvider implements ConfigProviderInterface $quoteData = []; if ($this->checkoutSession->getQuote()->getId()) { $quote = $this->quoteRepository->get($this->checkoutSession->getQuote()->getId()); - // the following condition is a legacy logic left here for compatibility - if (!$quote->getCustomer()->getId()) { - $this->quoteRepository->save($this->checkoutSession->getQuote()->setCheckoutMethod('guest')); - } else { - $this->quoteRepository->save($this->checkoutSession->getQuote()->setCheckoutMethod(null)); - } - $quoteData = $quote->toArray(); $quoteData['is_virtual'] = $quote->getIsVirtual(); @@ -357,22 +489,21 @@ class DefaultConfigProvider implements ConfigProviderInterface /** * Retrieve selected shipping method * - * @return string + * @return array|null */ private function getSelectedShippingMethod() { - // Shipping method ID contains carrier code and shipping method code - $shippingMethodId = ''; + $shippingMethodData = null; try { $quoteId = $this->checkoutSession->getQuote()->getId(); $shippingMethod = $this->shippingMethodManager->get($quoteId); if ($shippingMethod) { - $shippingMethodId = $shippingMethod->getCarrierCode() . '_' . $shippingMethod->getMethodCode(); + $shippingMethodData = $shippingMethod->__toArray(); } } catch (\Exception $exception) { - $shippingMethodId = ''; + $shippingMethodData = null; } - return $shippingMethodId; + return $shippingMethodData; } /** @@ -434,4 +565,97 @@ class DefaultConfigProvider implements ConfigProviderInterface { return $this->checkoutSession->getQuote()->getStore()->getBaseUrl(UrlInterface::URL_TYPE_STATIC); } + + /** + * Return countries data + * @return array + */ + private function getCountryData() + { + $country = []; + $regionsData = $this->directoryHelper->getRegionData(); + foreach ($this->directoryHelper->getCountryCollection() as $code => $data) { + $country[$code]['name'] = $data->getName(); + if (array_key_exists($code, $regionsData)) { + foreach ($regionsData[$code] as $key => $region) { + $country[$code]['regions'][$key]['code'] = $region['code']; + $country[$code]['regions'][$key]['name'] = $region['name']; + } + } + + } + return $country; + } + + /** + * Return quote totals data + * @return array + */ + private function getTotalsData() + { + /** @var \Magento\Quote\Api\Data\TotalsInterface $totals */ + $totals = $this->cartTotalRepository->get($this->checkoutSession->getQuote()->getId()); + $items = []; + /** @var \Magento\Quote\Model\Cart\Totals\Item $item */ + foreach ($totals->getItems() as $item) { + $items[] = $item->__toArray(); + } + $totalSegmentsData = []; + /** @var \Magento\Quote\Model\Cart\TotalSegment $totalSegment */ + foreach ($totals->getTotalSegments() as $totalSegment) { + $totalSegmentsData[] = $totalSegment->toArray(); + } + $totals->setItems($items); + $totals->setTotalSegments($totalSegmentsData); + $totalsArray = $totals->toArray(); + if (is_object($totals->getExtensionAttributes())) { + $totalsArray['extension_attributes'] = $totals->getExtensionAttributes()->__toArray(); + } + return $totalsArray; + } + + /** + * Returns active carriers codes + * @return array + */ + private function getActiveCarriers() + { + $activeCarriers = []; + foreach ($this->shippingMethodConfig->getActiveCarriers() as $carrier) { + $activeCarriers[] = $carrier->getCarrierCode(); + } + return $activeCarriers; + } + + /** + * Returns origin country code + * @return string + */ + private function getOriginCountryCode() + { + return $this->scopeConfig->getValue( + \Magento\Shipping\Model\Config::XML_PATH_ORIGIN_COUNTRY_ID, + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $this->storeManager->getStore() + ); + } + + /** + * Returns array of payment methods + * @return array + */ + private function getPaymentMethods() + { + $paymentMethods = []; + $quote = $this->checkoutSession->getQuote(); + if ($quote->getIsVirtual()) { + foreach ($this->paymentMethodManagement->getList($quote->getId()) as $paymentMethod) { + $paymentMethods[] = [ + 'code' => $paymentMethod->getCode(), + 'title' => $paymentMethod->getTitle() + ]; + } + } + return $paymentMethods; + } } diff --git a/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php new file mode 100644 index 0000000000000000000000000000000000000000..75e2539835e50cad7c7ff97d185044196423bf5d --- /dev/null +++ b/app/code/Magento/Checkout/Model/GuestPaymentInformationManagement.php @@ -0,0 +1,69 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Model; + +class GuestPaymentInformationManagement implements \Magento\Checkout\Api\GuestPaymentInformationManagementInterface +{ + + /** + * @var \Magento\Quote\Api\GuestBillingAddressManagementInterface + */ + protected $billingAddressManagement; + + /** + * @var \Magento\Quote\Api\GuestPaymentMethodManagementInterface + */ + protected $paymentMethodManagement; + + /** + * @var \Magento\Quote\Api\GuestCartManagementInterface + */ + protected $cartManagement; + + /** + * @param \Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement + * @param \Magento\Quote\Api\GuestPaymentMethodManagementInterface $paymentMethodManagement + * @param \Magento\Quote\Api\GuestCartManagementInterface $cartManagement + */ + public function __construct( + \Magento\Quote\Api\GuestBillingAddressManagementInterface $billingAddressManagement, + \Magento\Quote\Api\GuestPaymentMethodManagementInterface $paymentMethodManagement, + \Magento\Quote\Api\GuestCartManagementInterface $cartManagement + ) { + $this->billingAddressManagement = $billingAddressManagement; + $this->paymentMethodManagement = $paymentMethodManagement; + $this->cartManagement = $cartManagement; + } + + /** + * {@inheritDoc} + */ + public function savePaymentInformationAndPlaceOrder( + $cartId, + $email, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ) { + $this->savePaymentInformation($cartId, $email, $paymentMethod, $billingAddress); + return $this->cartManagement->placeOrder($cartId); + } + + /** + * {@inheritDoc} + */ + public function savePaymentInformation( + $cartId, + $email, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ) { + $billingAddress->setEmail($email); + $this->billingAddressManagement->assign($cartId, $billingAddress); + $this->paymentMethodManagement->set($cartId, $paymentMethod); + return true; + } +} diff --git a/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php b/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php new file mode 100644 index 0000000000000000000000000000000000000000..475bc915bf90ce15e48972dcc03979a02abc3a55 --- /dev/null +++ b/app/code/Magento/Checkout/Model/GuestShippingInformationManagement.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Model; + +class GuestShippingInformationManagement implements \Magento\Checkout\Api\GuestShippingInformationManagementInterface +{ + /** + * @var \Magento\Quote\Model\QuoteIdMaskFactory + */ + protected $quoteIdMaskFactory; + + /** + * @var ShippingInformationManagement + */ + protected $shippingInformationManagement; + + /** + * @param \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory + * @param ShippingInformationManagement $shippingInformationManagement + */ + public function __construct( + \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory, + \Magento\Checkout\Model\ShippingInformationManagement $shippingInformationManagement + ) { + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->shippingInformationManagement = $shippingInformationManagement; + } + + /** + * {@inheritDoc} + */ + public function saveAddressInformation( + $cartId, + \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + ) { + /** @var $quoteIdMask \Magento\Quote\Model\QuoteIdMask */ + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); + return $this->shippingInformationManagement->saveAddressInformation( + $quoteIdMask->getQuoteId(), + $addressInformation + ); + } +} diff --git a/app/code/Magento/Checkout/Model/PaymentDetails.php b/app/code/Magento/Checkout/Model/PaymentDetails.php new file mode 100644 index 0000000000000000000000000000000000000000..add196487ae989ccc195e557ee3c6f5e3de7177e --- /dev/null +++ b/app/code/Magento/Checkout/Model/PaymentDetails.php @@ -0,0 +1,67 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Model; + +/** + * @codeCoverageIgnoreStart + */ +class PaymentDetails extends \Magento\Framework\Model\AbstractExtensibleModel implements + \Magento\Checkout\Api\Data\PaymentDetailsInterface +{ + /** + * @{inheritdoc} + */ + public function getPaymentMethods() + { + return $this->getData(self::PAYMENT_METHODS); + } + + /** + * @{inheritdoc} + */ + public function setPaymentMethods($paymentMethods) + { + return $this->setData(self::PAYMENT_METHODS, $paymentMethods); + } + + /** + * @{inheritdoc} + */ + public function getTotals() + { + return $this->getData(self::TOTALS); + } + + /** + * @{inheritdoc} + */ + public function setTotals($totals) + { + return $this->setData(self::TOTALS, $totals); + } + + /** + * {@inheritdoc} + * + * @return \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface|null + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + * + * @param \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Checkout\Api\Data\PaymentDetailsExtensionInterface $extensionAttributes + ) { + return $this->_setExtensionAttributes($extensionAttributes); + } +} diff --git a/app/code/Magento/Checkout/Model/PaymentInformationManagement.php b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php new file mode 100644 index 0000000000000000000000000000000000000000..ff4b973c6298e3b95265a2d121aa51bac501804f --- /dev/null +++ b/app/code/Magento/Checkout/Model/PaymentInformationManagement.php @@ -0,0 +1,66 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Model; + +class PaymentInformationManagement implements \Magento\Checkout\Api\PaymentInformationManagementInterface +{ + + /** + * @var \Magento\Quote\Api\BillingAddressManagementInterface + */ + protected $billingAddressManagement; + + /** + * @var \Magento\Quote\Api\PaymentMethodManagementInterface + */ + protected $paymentMethodManagement; + + /** + * @var \Magento\Quote\Api\CartManagementInterface + */ + protected $cartManagement; + + /** + * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement + * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement + * @param \Magento\Quote\Api\CartManagementInterface $cartManagement + */ + public function __construct( + \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement, + \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, + \Magento\Quote\Api\CartManagementInterface $cartManagement + ) { + $this->billingAddressManagement = $billingAddressManagement; + $this->paymentMethodManagement = $paymentMethodManagement; + $this->cartManagement = $cartManagement; + } + + /** + * {@inheritDoc} + */ + public function savePaymentInformationAndPlaceOrder( + $cartId, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ) { + $this->savePaymentInformation($cartId, $paymentMethod, $billingAddress); + return $this->cartManagement->placeOrder($cartId); + } + + /** + * {@inheritDoc} + */ + public function savePaymentInformation( + $cartId, + \Magento\Quote\Api\Data\PaymentInterface $paymentMethod, + \Magento\Quote\Api\Data\AddressInterface $billingAddress + ) { + $this->billingAddressManagement->assign($cartId, $billingAddress); + $this->paymentMethodManagement->set($cartId, $paymentMethod); + return true; + } +} diff --git a/app/code/Magento/Checkout/Model/ShippingInformation.php b/app/code/Magento/Checkout/Model/ShippingInformation.php new file mode 100644 index 0000000000000000000000000000000000000000..44d024c7171f587514efb03446cd2480f6b29364 --- /dev/null +++ b/app/code/Magento/Checkout/Model/ShippingInformation.php @@ -0,0 +1,80 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Model; + +use Magento\Framework\Model\AbstractExtensibleModel; +use Magento\Checkout\Api\Data\ShippingInformationInterface; + +/** + * @codeCoverageIgnoreStart + */ +class ShippingInformation extends AbstractExtensibleModel implements ShippingInformationInterface +{ + /** + * {@inheritdoc} + */ + public function getShippingAddress() + { + return $this->getData(self::SHIPPING_ADDRESS); + } + + /** + * {@inheritdoc} + */ + public function setShippingAddress(\Magento\Quote\Api\Data\AddressInterface $address) + { + return $this->setData(self::SHIPPING_ADDRESS, $address); + } + + /** + * {@inheritdoc} + */ + public function getShippingMethodCode() + { + return $this->getData(self::SHIPPING_METHOD_CODE); + } + + /** + * {@inheritdoc} + */ + public function setShippingMethodCode($code) + { + return $this->setData(self::SHIPPING_METHOD_CODE, $code); + } + + /** + * {@inheritdoc} + */ + public function getShippingCarrierCode() + { + return $this->getData(self::SHIPPING_CARRIER_CODE); + } + + /** + * {@inheritdoc} + */ + public function setShippingCarrierCode($code) + { + return $this->setData(self::SHIPPING_CARRIER_CODE, $code); + } + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Checkout\Api\Data\ShippingInformationExtensionInterface $extensionAttributes + ) { + return $this->_setExtensionAttributes($extensionAttributes); + } +} diff --git a/app/code/Magento/Checkout/Model/ShippingInformationManagement.php b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php new file mode 100644 index 0000000000000000000000000000000000000000..4cf21372af8943caf46bafa3812898e5715c57d0 --- /dev/null +++ b/app/code/Magento/Checkout/Model/ShippingInformationManagement.php @@ -0,0 +1,178 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Checkout\Model; + +use Magento\Framework\Exception\InputException; +use Magento\Framework\Exception\StateException; +use Magento\Framework\Exception\NoSuchEntityException; +use Psr\Log\LoggerInterface as Logger; +use \Magento\Quote\Model\QuoteAddressValidator; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class ShippingInformationManagement implements \Magento\Checkout\Api\ShippingInformationManagementInterface +{ + /** + * @var \Magento\Quote\Api\PaymentMethodManagementInterface + */ + protected $paymentMethodManagement; + + /** + * @var PaymentDetailsFactory + */ + protected $paymentDetailsFactory; + + /** + * @var \Magento\Quote\Api\CartTotalRepositoryInterface + */ + protected $cartTotalsRepository; + + /** + * Quote repository. + * + * @var \Magento\Quote\Model\QuoteRepository + */ + protected $quoteRepository; + + /** + * Logger. + * + * @var Logger + */ + protected $logger; + + /** + * Validator. + * + * @var QuoteAddressValidator + */ + protected $addressValidator; + + /** + * @var \Magento\Customer\Api\AddressRepositoryInterface + */ + protected $addressRepository; + + /** + * @var \Magento\Framework\App\Config\ScopeConfigInterface + */ + protected $scopeConfig; + + /** + * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement + * @param \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory + * @param \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository + * @param \Magento\Quote\Model\QuoteRepository $quoteRepository + * @param \Magento\Quote\Model\QuoteAddressValidator $addressValidator + * @param Logger $logger + * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository + * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + */ + public function __construct( + \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, + \Magento\Checkout\Model\PaymentDetailsFactory $paymentDetailsFactory, + \Magento\Quote\Api\CartTotalRepositoryInterface $cartTotalsRepository, + \Magento\Quote\Model\QuoteRepository $quoteRepository, + QuoteAddressValidator $addressValidator, + Logger $logger, + \Magento\Customer\Api\AddressRepositoryInterface $addressRepository, + \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig + ) { + $this->paymentMethodManagement = $paymentMethodManagement; + $this->paymentDetailsFactory = $paymentDetailsFactory; + $this->cartTotalsRepository = $cartTotalsRepository; + $this->quoteRepository = $quoteRepository; + $this->addressValidator = $addressValidator; + $this->logger = $logger; + $this->addressRepository = $addressRepository; + $this->scopeConfig = $scopeConfig; + } + + /** + * {@inheritDoc} + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function saveAddressInformation( + $cartId, + \Magento\Checkout\Api\Data\ShippingInformationInterface $addressInformation + ) { + $address = $addressInformation->getShippingAddress(); + $carrierCode = $addressInformation->getShippingCarrierCode(); + $methodCode = $addressInformation->getShippingMethodCode(); + + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $this->quoteRepository->getActive($cartId); + if ($quote->isVirtual()) { + throw new NoSuchEntityException( + __('Cart contains virtual product(s) only. Shipping address is not applicable.') + ); + } + + if (0 == $quote->getItemsCount()) { + throw new InputException(__('Shipping method is not applicable for empty cart')); + } + + $saveInAddressBook = $address->getSaveInAddressBook() ? 1 : 0; + $sameAsBilling = $address->getSameAsBilling() ? 1 : 0; + $customerAddressId = $address->getCustomerAddressId(); + $this->addressValidator->validate($address); + $quote->setShippingAddress($address); + $address = $quote->getShippingAddress(); + + if ($customerAddressId) { + $addressData = $this->addressRepository->getById($customerAddressId); + $address = $quote->getShippingAddress()->importCustomerAddressData($addressData); + } + $address->setSameAsBilling($sameAsBilling); + $address->setSaveInAddressBook($saveInAddressBook); + $address->setCollectShippingRates(true); + + if (!$address->getCountryId()) { + throw new StateException(__('Shipping address is not set')); + } + + $address->setShippingMethod($carrierCode . '_' . $methodCode); + + try { + $address->save(); + $address->collectTotals(); + } catch (\Exception $e) { + $this->logger->critical($e); + throw new InputException(__('Unable to save address. Please, check input data.')); + } + + if (!$address->getShippingRateByCode($address->getShippingMethod())) { + throw new NoSuchEntityException( + __('Carrier with such method not found: %1, %2', $carrierCode, $methodCode) + ); + } + + if (!$quote->validateMinimumAmount($quote->getIsMultiShipping())) { + throw new InputException($this->scopeConfig->getValue( + 'sales/minimum_order/error_message', + \Magento\Store\Model\ScopeInterface::SCOPE_STORE, + $quote->getStoreId() + )); + } + + try { + $address->save(); + $quote->collectTotals(); + $this->quoteRepository->save($quote); + } catch (\Exception $e) { + $this->logger->critical($e); + throw new InputException(__('Unable to save shipping information. Please, check input data.')); + } + + /** @var \Magento\Checkout\Api\Data\PaymentDetailsInterface $paymentDetails */ + $paymentDetails = $this->paymentDetailsFactory->create(); + $paymentDetails->setPaymentMethods($this->paymentMethodManagement->getList($cartId)); + $paymentDetails->setTotals($this->cartTotalsRepository->get($cartId)); + return $paymentDetails; + } +} diff --git a/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php index f3a3f246ec1ee9acff0150dd74735d03a4be9dc5..5159d70026cbc5c902e6adc3c3b80d21e22ea64e 100644 --- a/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php +++ b/app/code/Magento/Checkout/Test/Unit/Controller/Onepage/IndexTest.php @@ -188,6 +188,7 @@ class IndexTest extends \PHPUnit_Framework_TestCase $this->basicStub($this->quoteMock, 'hasItems')->willReturn(true); $this->basicStub($this->quoteMock, 'getHasError')->willReturn(false); $this->basicStub($this->quoteMock, 'validateMinimumAmount')->willReturn(true); + $this->basicStub($this->sessionMock, 'isLoggedIn')->willReturn(true); //Expected outcomes $this->sessionMock->expects($this->once())->method('regenerateId'); diff --git a/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php b/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..29b91231adb10d532df997da73c74117859b5098 --- /dev/null +++ b/app/code/Magento/Checkout/Test/Unit/Model/Cart/ImageProviderTest.php @@ -0,0 +1,51 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Unit\Model\Cart; + +class ImageProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Checkout\Model\Cart\ImageProvider + */ + public $model; + + /** + * @var \PHPUnit_Framework_Mockobject_Mockobject | \Magento\Quote\Api\CartItemRepositoryInterface + */ + protected $itemRepositoryMock; + + /** + * @var \PHPUnit_Framework_Mockobject_Mockobject | \Magento\Checkout\CustomerData\ItemPoolInterface + */ + protected $itemPoolMock; + + protected function setUp() + { + $this->itemRepositoryMock = $this->getMock('Magento\Quote\Api\CartItemRepositoryInterface', [], [], '', false); + $this->itemPoolMock = $this->getMock('Magento\Checkout\CustomerData\ItemPoolInterface', [], [], '', false); + $this->model = new \Magento\Checkout\Model\Cart\ImageProvider( + $this->itemRepositoryMock, + $this->itemPoolMock + ); + } + + public function testGetImages() + { + $cartId = 42; + $itemId = 74; + $itemData = ['product_image' => 'Magento.png', 'random' => '3.1415926535']; + $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false); + $itemMock->expects($this->once())->method('getItemId')->willReturn($itemId); + + $expectedResult = [$itemId => $itemData['product_image']]; + + $this->itemRepositoryMock->expects($this->once())->method('getList')->with($cartId)->willReturn([$itemMock]); + $this->itemPoolMock->expects($this->once())->method('getItemData')->with($itemMock)->willReturn($itemData); + + $this->assertEquals($expectedResult, $this->model->getImages($cartId)); + } +} diff --git a/app/code/Magento/Checkout/etc/di.xml b/app/code/Magento/Checkout/etc/di.xml index 42d589f77e2dc1d49c5bcfdb09b5f65c3fd331f3..085ff442d7f75790df42f626a68a4cc886154fb4 100644 --- a/app/code/Magento/Checkout/etc/di.xml +++ b/app/code/Magento/Checkout/etc/di.xml @@ -16,4 +16,10 @@ <argument name="storage" xsi:type="object">Magento\Checkout\Model\Session\Storage</argument> </arguments> </type> + <preference for="Magento\Checkout\Api\GuestShippingInformationManagementInterface" type="Magento\Checkout\Model\GuestShippingInformationManagement" /> + <preference for="Magento\Checkout\Api\ShippingInformationManagementInterface" type="Magento\Checkout\Model\ShippingInformationManagement" /> + <preference for="Magento\Checkout\Api\Data\ShippingInformationInterface" type="Magento\Checkout\Model\ShippingInformation" /> + <preference for="Magento\Checkout\Api\Data\PaymentDetailsInterface" type="Magento\Checkout\Model\PaymentDetails" /> + <preference for="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" type="Magento\Checkout\Model\GuestPaymentInformationManagement" /> + <preference for="Magento\Checkout\Api\PaymentInformationManagementInterface" type="Magento\Checkout\Model\PaymentInformationManagement" /> </config> diff --git a/app/code/Magento/Checkout/etc/frontend/di.xml b/app/code/Magento/Checkout/etc/frontend/di.xml index 3399782763bea132a2c807f956f6323ce84016c7..20f146cc353ce63add45e00f3fc083c28cdb2768 100644 --- a/app/code/Magento/Checkout/etc/frontend/di.xml +++ b/app/code/Magento/Checkout/etc/frontend/di.xml @@ -43,6 +43,7 @@ <arguments> <argument name="layoutProcessors" xsi:type="array"> <item name="addressFormAttributes" xsi:type="object">Magento\Checkout\Block\Checkout\LayoutProcessor</item> + <item name="totalsSortOrder" xsi:type="object">Magento\Checkout\Block\Checkout\TotalsProcessor</item> </argument> </arguments> </type> diff --git a/app/code/Magento/Checkout/etc/webapi.xml b/app/code/Magento/Checkout/etc/webapi.xml new file mode 100644 index 0000000000000000000000000000000000000000..28598faec5913a1a3d30af16084b9a2ac0d64bf0 --- /dev/null +++ b/app/code/Magento/Checkout/etc/webapi.xml @@ -0,0 +1,64 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="../../../../../app/code/Magento/Webapi/etc/webapi.xsd"> + + <!-- Managing shipping guest information --> + <route url="/V1/carts/:cartId/shipping-information" method="POST"> + <service class="Magento\Checkout\Api\GuestShippingInformationManagementInterface" method="saveAddressInformation"/> + <resources> + <resource ref="anonymous" /> + </resources> + </route> + + <!-- Managing My shipping information --> + <route url="/V1/carts/mine/shipping-information" method="POST"> + <service class="Magento\Checkout\Api\ShippingInformationManagementInterface" method="saveAddressInformation"/> + <resources> + <resource ref="self" /> + </resources> + <data> + <parameter name="cartId" force="true">%cart_id%</parameter> + </data> + </route> + <!-- Guest place order with payment information saving --> + <route url="/V1/guest-carts/:cartId/payment-information" method="POST"> + <service class="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" method="savePaymentInformationAndPlaceOrder"/> + <resources> + <resource ref="anonymous" /> + </resources> + </route> + <!-- My place order with payment information saving --> + <route url="/V1/carts/mine/payment-information" method="POST"> + <service class="Magento\Checkout\Api\PaymentInformationManagementInterface" method="savePaymentInformationAndPlaceOrder"/> + <resources> + <resource ref="self" /> + </resources> + <data> + <parameter name="cartId" force="true">%cart_id%</parameter> + </data> + </route> + + <!-- Managing payment guest information --> + <route url="/V1/guest-carts/:cartId/set-payment-information" method="POST"> + <service class="Magento\Checkout\Api\GuestPaymentInformationManagementInterface" method="savePaymentInformation"/> + <resources> + <resource ref="anonymous" /> + </resources> + </route> + <!-- Managing My shipping information --> + <route url="/V1/carts/mine/set-payment-information" method="POST"> + <service class="Magento\Checkout\Api\PaymentInformationManagementInterface" method="savePaymentInformation"/> + <resources> + <resource ref="self" /> + </resources> + <data> + <parameter name="cartId" force="true">%cart_id%</parameter> + </data> + </route> +</routes> diff --git a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml index 5db66984f7812e8bd62978befb585a2eaa8434f9..a40e65477410eef2cfebf8e9c39203ed88070605 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/checkout_onepage_index.xml @@ -23,155 +23,233 @@ </item> <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/onepage</item> + <item name="component" xsi:type="string">uiComponent</item> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">Magento_Checkout/onepage</item> + </item> <item name="children" xsi:type="array"> - <item name="progress" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/progress</item> - <item name="displayArea" xsi:type="string">progress</item> + <item name="errors" xsi:type="array"> + <item name="sortOrder" xsi:type="string">0</item> + <item name="component" xsi:type="string">Magento_Ui/js/view/messages</item> + <item name="displayArea" xsi:type="string">messages</item> + </item> + <item name="authentication" xsi:type="array"> + <item name="sortOrder" xsi:type="string">1</item> + <item name="component" xsi:type="string">Magento_Checkout/js/view/authentication</item> + <item name="displayArea" xsi:type="string">authentication</item> <item name="children" xsi:type="array"> - <item name="shipping" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item> - <item name="displayArea" xsi:type="string">shipping</item> - </item> + <!--Additional authentication fields--> </item> </item> - <item name="errors" xsi:type="array"> + <item name="progressBar" xsi:type="array"> <item name="sortOrder" xsi:type="string">0</item> - <item name="component" xsi:type="string">Magento_Ui/js/view/errors</item> - <item name="displayArea" xsi:type="string">errors</item> + <item name="component" xsi:type="string">Magento_Checkout/js/view/progress-bar</item> + <item name="displayArea" xsi:type="string">progressBar</item> </item> <item name="steps" xsi:type="array"> <item name="component" xsi:type="string">uiComponent</item> <item name="displayArea" xsi:type="string">steps</item> <item name="children" xsi:type="array"> - <item name="authentication" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/authentication</item> + <item name="shipping-step" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> <item name="sortOrder" xsi:type="string">1</item> <item name="children" xsi:type="array"> - <item name="before" xsi:type="array"> + <item name="step-config" xsi:type="array"> <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">before</item> <item name="children" xsi:type="array"> - <!-- merge additional data before authentication here --> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <!--Step configuration components--> + </item> + </item> </item> </item> - </item> - </item> - <item name="billingAddress" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/billing-address</item> - <item name="provider" xsi:type="string">checkoutProvider</item> - <item name="sortOrder" xsi:type="string">2</item> - <item name="children" xsi:type="array"> - <item name="billing-address-fieldset" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">additional-fieldsets</item> - <item name="children" xsi:type="array"> - <!-- The following items override configuration of corresponding address attributes --> - <item name="region" xsi:type="array"> - <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field --> - <item name="visible" xsi:type="boolean">false</item> - </item> - <item name="region_id" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/form/field</item> - <item name="elementTmpl" xsi:type="string">ui/form/element/select</item> - <item name="customEntry" xsi:type="string">billingAddress.region</item> - </item> - <item name="validation" xsi:type="array"> - <item name="validate-select" xsi:type="string">true</item> - </item> - <!-- Value of region_id field is filtered by the value of county_id attribute --> - <item name="filterBy" xsi:type="array"> - <item name="target" xsi:type="string">${ $.provider }:${ $.parentScope }.country_id</item> - <item name="field" xsi:type="string">country_id</item> + <item name="shippingAddress" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="deps" xsi:type="string">checkout.steps.shipping-step.step-config</item> + <item name="popUpForm" xsi:type="array"> + <item name="element" xsi:type="string">#opc-new-shipping-address</item> + <item name="options" xsi:type="array"> + <item name="type" xsi:type="string">popup</item> + <item name="responsive" xsi:type="boolean">true</item> + <item name="innerScroll" xsi:type="boolean">true</item> + <item name="title" xsi:type="string">Shipping Address</item> + <item name="trigger" xsi:type="string">opc-new-shipping-address</item> + <item name="buttons" xsi:type="array"> + <item name="save" xsi:type="array"> + <item name="text" xsi:type="string">Save Address</item> + <item name="class" xsi:type="string">action primary action-save-address</item> + </item> + <item name="cancel" xsi:type="array"> + <item name="text" xsi:type="string">Cancel</item> + <item name="class" xsi:type="string">action secondary action-hide-popup</item> + </item> + </item> </item> </item> - <item name="postcode" xsi:type="array"> - <!-- post-code field has custom UI component --> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item> - <item name="validation" xsi:type="array"> - <item name="required-entry" xsi:type="string">true</item> + </item> + <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping</item> + <item name="provider" xsi:type="string">checkoutProvider</item> + <item name="sortOrder" xsi:type="string">1</item> + <item name="children" xsi:type="array"> + <item name="customer-email" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Customer/js/view/customer-email</item> + <item name="displayArea" xsi:type="string">customer-email</item> + <item name="tooltip" xsi:type="array"> + <item name="description" xsi:type="string">We'll send your order confirmation here.</item> + </item> + <item name="children" xsi:type="array"> + <item name="before-login-form" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">before-login-form</item> + <item name="children" xsi:type="array"> + <!-- before login form fields --> + </item> + </item> + <item name="additional-login-form-fields" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="children" xsi:type="array"> + <!-- additional login form fields --> + </item> + </item> </item> </item> - <item name="company" xsi:type="array"> - <item name="validation" xsi:type="array"> - <item name="min_text_length" xsi:type="number">0</item> + <item name="before-form" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">before-form</item> + <item name="children" xsi:type="array"> + <!-- before form fields --> </item> </item> - <item name="fax" xsi:type="array"> - <item name="validation" xsi:type="array"> - <item name="min_text_length" xsi:type="number">0</item> + <item name="before-fields" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">before-fields</item> + <item name="children" xsi:type="array"> + <!-- before fields --> </item> </item> - <item name="country_id" xsi:type="array"> - <item name="sortOrder" xsi:type="string">115</item> + <item name="address-list" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-address/list</item> + <item name="displayArea" xsi:type="string">address-list</item> </item> - <!-- The following items describe fields that are not directly related to address but must be shown in address form --> - <item name="email" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/form/field</item> - <item name="elementTmpl" xsi:type="string">ui/form/element/email</item> - <item name="customScope" xsi:type="string">customerDetails</item> + <item name="address-list-additional-addresses" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">address-list-additional-addresses</item> + <item name="children" xsi:type="array"> + <!-- address-list-additional-addresses --> </item> - <item name="label" xsi:type="string">Email</item> - <item name="dataScope" xsi:type="string">customerDetails.email</item> - <item name="provider" xsi:type="string">checkoutProvider</item> - <item name="sortOrder" xsi:type="string">45</item> - <item name="validation" xsi:type="array"> - <item name="required-entry" xsi:type="boolean">true</item> - <item name="validate-email" xsi:type="boolean">true</item> + </item> + <item name="before-shipping-method-form" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">before-shipping-method-form</item> + <item name="children" xsi:type="array"> + <!-- address-list-additional-addresses --> </item> </item> - <item name="save_in_address_book" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/form/field</item> - <item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item> + <item name="shipping-address-fieldset" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">additional-fieldsets</item> + <item name="children" xsi:type="array"> + <!-- The following items override configuration of corresponding address attributes --> + <item name="region" xsi:type="array"> + <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field --> + <item name="visible" xsi:type="boolean">false</item> + </item> + <item name="region_id" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">ui/form/field</item> + <item name="elementTmpl" xsi:type="string">ui/form/element/select</item> + <item name="customEntry" xsi:type="string">shippingAddress.region</item> + </item> + <item name="validation" xsi:type="array"> + <item name="validate-select" xsi:type="string">true</item> + </item> + <!-- Value of region_id field is filtered by the value of county_id attribute --> + <item name="filterBy" xsi:type="array"> + <item name="target" xsi:type="string"><![CDATA[${ $.provider }:${ $.parentScope }.country_id]]></item> + <item name="field" xsi:type="string">country_id</item> + </item> + </item> + <item name="postcode" xsi:type="array"> + <!-- post-code field has custom UI component --> + <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item> + <item name="validation" xsi:type="array"> + <item name="required-entry" xsi:type="string">true</item> + </item> + </item> + <item name="company" xsi:type="array"> + <item name="validation" xsi:type="array"> + <item name="min_text_length" xsi:type="number">0</item> + </item> + </item> + <item name="fax" xsi:type="array"> + <item name="validation" xsi:type="array"> + <item name="min_text_length" xsi:type="number">0</item> + </item> + </item> + <item name="country_id" xsi:type="array"> + <item name="sortOrder" xsi:type="string">115</item> + </item> + <item name="telephone" xsi:type="array"> + <item name="config" xsi:type="array"> + <item name="tooltip" xsi:type="array"> + <item name="description" xsi:type="string">For delivery Questions</item> + </item> + </item> + </item> </item> - <item name="description" xsi:type="string">Save in address book</item> - <item name="provider" xsi:type="string">checkoutProvider</item> - <item name="dataScope" xsi:type="string">billingAddress.save_in_address_book</item> </item> </item> </item> - <item name="billing-address-choice" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">additional-field-choice</item> - <item name="children" xsi:type="array"> - <!-- this region for different choice --> - </item> - </item> </item> </item> - <item name="shippingAddress" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-address</item> - <item name="provider" xsi:type="string">checkoutProvider</item> - <item name="sortOrder" xsi:type="string">3</item> + <item name="billing-step" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="sortOrder" xsi:type="string">2</item> <item name="children" xsi:type="array"> - <item name="before-fields" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">before-fields</item> - <item name="children" xsi:type="array"> - <!-- before fields --> + <item name="payment" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/payment</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Payment</item> </item> - </item> - <item name="shipping-address-fieldset" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">additional-fieldsets</item> <item name="children" xsi:type="array"> - <!-- The following items override configuration of corresponding address attributes --> - <item name="region" xsi:type="array"> - <!-- Make region attribute invisible on frontend. Corresponding input element is created by region_id field --> - <item name="visible" xsi:type="boolean">false</item> + <item name="renders" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="children" xsi:type="array"> + <!-- merge payment method renders here --> + </item> </item> - <item name="region_id" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/region</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/form/field</item> - <item name="elementTmpl" xsi:type="string">ui/form/element/select</item> - <item name="customEntry" xsi:type="string">shippingAddress.region</item> + <item name="customer-email" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Customer/js/view/customer-email</item> + <item name="displayArea" xsi:type="string">customer-email</item> + <item name="tooltip" xsi:type="array"> + <item name="description" xsi:type="string">(You can create an account to track your order after checkout)</item> + </item> + <item name="children" xsi:type="array"> + <item name="before-login-form" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">before-login-form</item> + <item name="children" xsi:type="array"> + <!-- before login form fields --> + </item> + </item> + <item name="additional-login-form-fields" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">additional-login-form-fields</item> + <item name="children" xsi:type="array"> + <!-- additional login form fields --> + </item> + </item> + </item> + </item> + <!-- TODO: add billing address form --> + <item name="beforeMethods" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">beforeMethods</item> + <item name="children" xsi:type="array"> + <!-- merge additional data before payment methods here --> </item> <item name="validation" xsi:type="array"> <item name="validate-select" xsi:type="string">true</item> @@ -182,135 +260,107 @@ <item name="field" xsi:type="string">country_id</item> </item> </item> - <item name="postcode" xsi:type="array"> - <!-- post-code field has custom UI component --> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/post-code</item> - <item name="validation" xsi:type="array"> - <item name="required-entry" xsi:type="string">true</item> - </item> - </item> - <item name="company" xsi:type="array"> - <item name="validation" xsi:type="array"> - <item name="min_text_length" xsi:type="number">0</item> + <item name="payments-list" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/payment/list</item> + <item name="displayArea" xsi:type="string">payment-methods-list</item> + <item name="config" xsi:type="array"> + <item name="deps" xsi:type="string">checkout.steps.billing-step.payment.renders</item> </item> </item> - <item name="fax" xsi:type="array"> - <item name="validation" xsi:type="array"> - <item name="min_text_length" xsi:type="number">0</item> + <!-- merge your payment methods here --> + <item name="afterMethods" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">afterMethods</item> + <item name="children" xsi:type="array"> + <!-- merge additional data after payment methods here --> </item> </item> - <item name="country_id" xsi:type="array"> - <item name="sortOrder" xsi:type="string">115</item> - </item> - <item name="save_in_address_book" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Ui/js/form/element/abstract</item> - <item name="config" xsi:type="array"> - <item name="template" xsi:type="string">ui/form/field</item> - <item name="elementTmpl" xsi:type="string">ui/form/element/checkbox</item> - </item> - <item name="description" xsi:type="string">Save in address book</item> - <item name="provider" xsi:type="string">checkoutProvider</item> - <item name="dataScope" xsi:type="string">shippingAddress.save_in_address_book</item> - </item> </item> </item> </item> </item> - <item name="shipping" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-method</item> - <item name="sortOrder" xsi:type="string">4</item> - <item name="additional" xsi:type="array"> - <!-- merge your shipping methods here --> + </item> + </item> + <item name="summary" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary</item> + <item name="displayArea" xsi:type="string">summary</item> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">Magento_Checkout/summary</item> + </item> + <item name="children" xsi:type="array"> + <item name="totals" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="displayArea" xsi:type="string">totals</item> + <item name="config" xsi:type="array"> + <item name="template" xsi:type="string">Magento_Checkout/summary/totals</item> </item> <item name="children" xsi:type="array"> - <item name="afterSelect" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">afterSelect</item> - <item name="children" xsi:type="array"> - <!-- merge additional data after shipping methods here --> + <!-- sort order for this totals is configured on admin panel--> + <!-- Stores->Configuration->SALES->Sales->General->Checkout Totals Sort Order --> + <item name="subtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/subtotal</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Cart Subtotal</item> </item> </item> - </item> - </item> - <item name="payment" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/payment</item> - <item name="sortOrder" xsi:type="string">5</item> - <item name="children" xsi:type="array"> - <item name="beforeMethods" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">beforeMethods</item> - <item name="children" xsi:type="array"> - <!-- merge additional data before payment methods here --> + <item name="shipping" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/shipping</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Shipping</item> + <item name="notCalculatedMessage" xsi:type="string">Not yet calculated</item> </item> </item> - <!-- merge your payment methods here --> - <item name="afterMethods" xsi:type="array"> - <item name="component" xsi:type="string">uiComponent</item> - <item name="displayArea" xsi:type="string">afterMethods</item> - <item name="children" xsi:type="array"> - <!-- merge additional data after payment methods here --> + <item name="grand-total" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/grand-total</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Order Total</item> </item> </item> </item> </item> - <item name="review" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/review</item> - <item name="sortOrder" xsi:type="string">6</item> + <item name="itemsBefore" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> <item name="children" xsi:type="array"> - <item name="columns" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item> - <item name="children" xsi:type="array"> - <item name="name" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/name</item></item> - <item name="price" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/price</item></item> - <item name="qty" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/qty</item></item> - <item name="subtotal" xsi:type="array"><item name="component" xsi:type="string">Magento_Checkout/js/view/review/item/columns/subtotal</item></item> - </item> - </item> - <item name="itemsBefore" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/itemsBefore</item> - <item name="children" xsi:type="array"> - <!-- merge your components here --> - </item> - </item> - <item name="itemsAfter" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/itemsAfter</item> - <item name="children" xsi:type="array"> - <!-- merge your components here --> - </item> - </item> - <item name="beforePlaceOrder" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/beforePlaceOrder</item> - <item name="children" xsi:type="array"> - <!-- merge your components here --> - </item> - </item> - <item name="totals" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/totals</item> + <!-- merge your components here --> + </item> + </item> + <item name="cart_items" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/cart-items</item> + <item name="children" xsi:type="array"> + <item name="details" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details</item> <item name="children" xsi:type="array"> - <item name="subtotal" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/subtotal</item> - </item> - <item name="discount" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/discount</item> + <item name="thumbnail" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/thumbnail</item> + <item name="displayArea" xsi:type="string">before_details</item> </item> - </item> - </item> - <item name="actions" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/review/actions</item> - <item name="children" xsi:type="array"> - <item name="@default" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/review/actions/default</item> - <item name="config" xsi:type="array"> - <item name="isDefault" xsi:type="boolean">true</item> - </item> + <item name="subtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/summary/item/details/subtotal</item> + <item name="displayArea" xsi:type="string">after_details</item> </item> - <!-- merge your components here --> </item> </item> + + </item> + </item> + <item name="itemsAfter" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="children" xsi:type="array"> + <!-- merge your components here --> </item> </item> </item> </item> + <item name="shipping-information" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-information</item> + <item name="displayArea" xsi:type="string">shipping-information</item> + <item name="children" xsi:type="array"> + <item name="ship-to" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/shipping-information/list</item> + <item name="displayArea" xsi:type="string">ship-to</item> + </item> + </item> + </item> </item> </item> <item name="checkoutProvider" xsi:type="array"> @@ -321,5 +371,6 @@ </arguments> </block> </referenceContainer> + <remove name="page.messages" /> </body> </page> diff --git a/app/code/Magento/Checkout/view/frontend/layout/default.xml b/app/code/Magento/Checkout/view/frontend/layout/default.xml index 2ac27890ca18a2a79b604c647abe24eb95f14625..da1007040f6a19ab02d2f794b2df8ac4e93df719 100644 --- a/app/code/Magento/Checkout/view/frontend/layout/default.xml +++ b/app/code/Magento/Checkout/view/frontend/layout/default.xml @@ -51,6 +51,19 @@ <item name="displayArea" xsi:type="string">promotion</item> </item> </item> + <item name="sign-in-popup" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/cart/authentication</item> + <item name="config" xsi:type="array"> + <item name="displayArea" xsi:type="string">sign-in-popup</item> + <item name="template" xsi:type="string">Magento_Checkout/cart/authentication</item> + </item> + <item name="children" xsi:type="array"> + <item name="messages" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ui/js/view/messages</item> + <item name="displayArea" xsi:type="string">messages</item> + </item> + </item> + </item> </item> </item> </item> diff --git a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml index d515d34169278ca83c7d361c5e43fcd51f9840ae..6d08bcb4bbf500ef2f823c46e8074640099f07d6 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/cart/minicart.phtml @@ -42,18 +42,15 @@ </div> <?php endif ?> <script> - window.checkout = { - shoppingCartUrl: '<?=$block->getShoppingCartUrl()?>', - checkoutUrl: '<?=$block->getCheckoutUrl()?>', - updateItemQtyUrl: '<?=$block->getUpdateItemQtyUrl()?>', - removeItemUrl: '<?=$block->getRemoveItemUrl()?>', - imageTemplate: '<?= $block->getImageHtmlTemplate()?>' - }; + window.checkout = <?php echo \Zend_Json::encode($block->getConfig()); ?>; </script> <script type="text/x-magento-init"> { "[data-block='minicart']": { "Magento_Ui/js/core/app": <?php echo $block->getJsLayout();?> + }, + "*": { + "Magento_Ui/js/block-loader": "<?php echo $block->getViewFileUrl('images/loader-1.gif'); ?>" } } </script> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml index 7e8fe0c43edb0dd18ac6ac63ceae182267a1de08..1f05ef68ff3a41b882e7342dc6c271ea2a9eb670 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage.phtml @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ ?> - <div id="checkout" data-bind="scope:'checkout'"> + <div id="checkout" data-bind="scope:'checkout'" class="checkout-container"> <!-- ko template: getTemplate() --><!-- /ko --> <script type="text/x-magento-init"> { @@ -20,8 +20,13 @@ window.customerData = window.checkoutConfig.customerData; </script> <script> - require(['mage/url', 'Magento_Checkout/js/model/step-loader'], function(url, loader) { + require([ + 'mage/url', + 'Magento_Checkout/js/model/step-loader', + 'Magento_Ui/js/block-loader' + ], function(url, loader, blockLoader) { loader.registerLoader(); + blockLoader("<?php echo $block->getViewFileUrl('images/loader-1.gif'); ?>"); return url.setBaseUrl('<?php echo $block->getBaseUrl();?>'); }) </script> diff --git a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml index 25d144d746d4a42020cce13217abb4b831e90d81..72b8a5bf5023ad578385467538fdb88299bce81e 100644 --- a/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml +++ b/app/code/Magento/Checkout/view/frontend/templates/onepage/link.phtml @@ -5,18 +5,14 @@ */ // @codingStandardsIgnoreFile - -/** - * @deprecated - * @removeCandidate - */ ?> <?php if ($block->isPossibleOnepageCheckout()):?> <button type="button" + data-role="proceed-to-checkout" title="<?php echo __('Proceed to Checkout') ?>" + data-mage-init='{"Magento_Checkout/js/proceed-to-checkout":{}}' class="action primary checkout<?php echo($block->isDisabled()) ? ' disabled' : ''; ?>" - <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?> - onclick="window.location='<?php echo $block->getCheckoutUrl() ?>';"> - <span><?php echo __('Proceed to Checkout') ?></span> + <?php if ($block->isDisabled()):?>disabled="disabled"<?php endif; ?>> + <span><?php echo __('Proceed to Checkout') ?></span> </button> <?php endif?> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js new file mode 100644 index 0000000000000000000000000000000000000000..a48f92659f46a3f0d2d8bb76d5cb2920182643be --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-billing-address.js @@ -0,0 +1,17 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Checkout/js/model/address-converter' + ], + function(addressConverter) { + "use strict"; + return function(addressData) { + var address = addressConverter.formAddressDataToQuoteAddress(addressData); + return address; + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js new file mode 100644 index 0000000000000000000000000000000000000000..d4225a3166057fabbcc83ebf01530ffae7601167 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/create-shipping-address.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Customer/js/model/address-list', + 'Magento_Checkout/js/model/address-converter' + ], + function(addressList, addressConverter) { + "use strict"; + return function(addressData) { + var address = addressConverter.formAddressDataToQuoteAddress(addressData); + var isAddressUpdated = addressList().some(function(currentAddress, index, addresses) { + if (currentAddress.getKey() == address.getKey()) { + addresses[index] = address; + return true; + } + return false; + }); + if (!isAddressUpdated) { + addressList.push(address); + } else { + addressList.valueHasMutated(); + } + return address; + }; + } +); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js b/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js new file mode 100644 index 0000000000000000000000000000000000000000..57524a7cb404576bc19da11b30b54452833f5ab9 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/get-totals.js @@ -0,0 +1,47 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/*global define,alert*/ +define( + [ + 'jquery', + '../model/quote', + 'Magento_Checkout/js/model/resource-url-manager', + 'Magento_Ui/js/model/messageList', + 'mage/storage', + 'Magento_Checkout/js/model/totals' + ], + function ($, quote, resourceUrlManager, messageList, storage, totals) { + "use strict"; + return function (callbacks, deferred) { + deferred = deferred || $.Deferred(); + totals.isLoading(true); + return storage.get( + resourceUrlManager.getUrlForCartTotals(quote), + false + ).done( + function (response) { + totals.isLoading(false); + var proceed = true; + $.each(callbacks, function(index, callback) { + proceed = proceed && callback(); + }); + if (proceed) { + quote.setTotals(response); + deferred.resolve(); + } + } + ).error( + function (response) { + totals.isLoading(false); + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + deferred.reject(); + } + ); + + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js index ee6bf6d67d3396bf764b2f39ac1c275ab464b1f5..eabe01078de5e0bbeb9a788c30c21f6e313977ec 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/place-order.js @@ -2,48 +2,56 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*global define*/ define( [ - '../model/quote', - '../model/url-builder', - '../model/payment-service', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/url-builder', 'mage/storage', 'mage/url', - 'Magento_Ui/js/model/errorlist', + 'Magento_Ui/js/model/messageList', 'Magento_Customer/js/model/customer', 'underscore' ], - function(quote, urlBuilder, paymentService, storage, url, errorList, customer, _) { - "use strict"; - return function(customParams, callback) { - var payload; - customParams = customParams || { - cartId: quote.getQuoteId(), - paymentMethod: paymentService.getSelectedPaymentData() - }; + function (quote, urlBuilder, storage, url, messageList, customer, _) { + 'use strict'; + + return function (paymentData, redirectOnSuccess) { + var serviceUrl, payload; + + redirectOnSuccess = redirectOnSuccess === false ? false : true; /** * Checkout for guest and registered customer. */ - var serviceUrl; - if (quote.getCheckoutMethod()() === 'guest') { - serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/order', {quoteId: quote.getQuoteId()}); + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/payment-information', { + quoteId: quote.getQuoteId() + }); + payload = { + cartId: quote.getQuoteId(), + email: quote.guestEmail, + paymentMethod: paymentData, + billingAddress: quote.billingAddress() + }; } else { - serviceUrl = urlBuilder.createUrl('/carts/mine/order', {}); + serviceUrl = urlBuilder.createUrl('/carts/mine/payment-information', {}); + payload = { + cartId: quote.getQuoteId(), + paymentMethod: paymentData, + billingAddress: quote.billingAddress() + }; } - payload = customParams; - storage.put( + storage.post( serviceUrl, JSON.stringify(payload) ).done( - function() { - if (!_.isFunction(callback) || callback()) { + function () { + if (redirectOnSuccess) { window.location.replace(url.build('checkout/onepage/success/')); } } ).fail( - function(response) { + function (response) { var error = JSON.parse(response.responseText); - errorList.add(error); + messageList.addErrorMessage(error); } ); }; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js index 635f6797f40750b26511d8c686c4227b7420b433..da290fc1aa214d38d38deb8ca5b68805e66962f5 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-billing-address.js @@ -2,88 +2,15 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true*/ -/*global define, alert*/ +/*global define*/ define( [ - '../model/quote', - '../model/addresslist', - '../model/step-navigator', - './select-shipping-address', - 'uiRegistry', - '../model/url-builder', - 'mage/storage', - '../model/payment-service', - 'underscore' + '../model/quote' ], - function (quote, addressList, navigator, selectShippingAddress, registry, urlBuilder, storage, paymentService, _) { + function(quote) { "use strict"; - var actionCallback; - var result = function (billingAddress, useForShipping, additionalData) { - var copyBillingToShipping = function() { - var shippingAddressSource = registry.get('checkoutProvider'), - shippingAddress = shippingAddressSource.get('shippingAddress'); - for (var property in billingAddress) { - if (billingAddress.hasOwnProperty(property) && shippingAddress.hasOwnProperty(property)) { - if (typeof billingAddress[property] === 'string') { - shippingAddressSource.set('shippingAddress.' + property, billingAddress[property]); - } else { - shippingAddressSource.set('shippingAddress.' + property, _.clone(billingAddress[property])); - } - } - } - }; - additionalData = additionalData || {}; - quote.setBillingAddress(billingAddress); - if (useForShipping() === '1' && !quote.isVirtual()) { - if (!billingAddress.customerAddressId) { - copyBillingToShipping(); - } - selectShippingAddress(billingAddress, useForShipping, additionalData); - } else if (quote.isVirtual()) { - var serviceUrl; - if (quote.getCheckoutMethod()() === 'guest') { - serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/addresses', {quoteId: quote.getQuoteId()}); - } else { - serviceUrl = urlBuilder.createUrl('/carts/mine/addresses', {}); - } - storage.post( - serviceUrl, - JSON.stringify({ - billingAddress: quote.getBillingAddress()(), - additionalData: {extensionAttributes : additionalData}, - checkoutMethod: quote.getCheckoutMethod()() - }) - ).done( - function (result) { - paymentService.setPaymentMethods(result.payment_methods); - quote.setFormattedBillingAddress(result.formatted_billing_address); - quote.setTotals(result.totals); - navigator.setCurrent('billingAddress').goNext(); - if (typeof actionCallback == 'function') { - actionCallback(true); - } - } - ).fail( - function (response) { - var error = JSON.parse(response.responseText); - errorList.add(error); - quote.setBillingAddress(null); - if (typeof actionCallback == 'function') { - actionCallback(false); - } - } - ); - } else { - navigator.setCurrent('billingAddress').goNext(); - if (addressList.isBillingSameAsShipping) { - copyBillingToShipping(); - } - } + return function(billingAddress) { + quote.billingAddress(billingAddress); }; - result.setActionCallback = function (value) { - actionCallback = value; - }; - return result; } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js index f0fe5a55aa3af0016a1a4e78dd15d7ae66295400..c6d9c56528efb47d0364a769b3a0a56d7d2d0016 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-payment-method.js @@ -5,96 +5,12 @@ /*global define*/ define( [ - '../model/quote', - '../model/url-builder', - '../model/step-navigator', - '../model/payment-service', - 'Magento_Ui/js/model/errorlist', - 'mage/storage', - 'underscore' + '../model/quote' ], - function(quote, urlBuilder, navigator, service, errorList, storage, _) { - "use strict"; - return function (methodData, methodInfo, callbacks) { - var paymentMethodData = { - "cartId": quote.getQuoteId(), - "paymentMethod": methodData - }; - - var shippingMethodCode = quote.getSelectedShippingMethod()().slice(0).split("_"), - shippingMethodData = { - "shippingCarrierCode" : shippingMethodCode.shift(), - "shippingMethodCode" : shippingMethodCode.join('_') - }, - serviceUrl; - if (quote.getCheckoutMethod()() === 'guest') { - serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/collect-totals', {quoteId: quote.getQuoteId()}); - } else { - serviceUrl = urlBuilder.createUrl('/carts/mine/collect-totals', {}); - } - - if (quote.isVirtual()) { - return storage.put( - serviceUrl, - JSON.stringify(paymentMethodData) - ).done( - function (response) { - var proceed = true; - _.each(callbacks, function(callback) { - proceed = proceed && callback(); - }); - if (proceed) { - quote.setPaymentMethod(methodData.method); - service.setSelectedPaymentData(methodData); - service.setSelectedPaymentInfo(methodInfo); - quote.setTotals(response); - navigator.setCurrent('paymentMethod').goNext(); - } - } - ).error( - function (response) { - var error = JSON.parse(response.responseText); - errorList.add(error); - quote.setPaymentMethod(null); - } - ); - } else { - if (!_.isEmpty(quote.getShippingCustomOptions()())) { - shippingMethodData = _.extend( - shippingMethodData, - { - additionalData: { - extension_attributes: quote.getShippingCustomOptions()() - } - } - ); - } - return storage.put( - serviceUrl, - JSON.stringify(_.extend(paymentMethodData, shippingMethodData)) - ).done( - function (response) { - var proceed = true; - _.each(callbacks, function(callback) { - proceed = proceed && callback(); - }); - if (proceed) { - quote.setPaymentMethod(methodData.method); - //set the totals before setting PaymentData - quote.setTotals(response); - service.setSelectedPaymentData(methodData); - service.setSelectedPaymentInfo(methodInfo); - navigator.setCurrent('paymentMethod').goNext(); - } - } - ).error( - function (response) { - var error = JSON.parse(response.responseText); - errorList.add(error); - quote.setPaymentMethod(null); - } - ); - } - }; + function(quote) { + 'use strict'; + return function (paymentMethod) { + quote.paymentMethod(paymentMethod); + } } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js index c9f87d1594b7aa201bee919e37ba79ca4c3d21a6..5247cef00fb03ac61bf36e29f7e6655fee7605cd 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-address.js @@ -4,69 +4,16 @@ */ /*global define*/ define( - [ - '../model/quote', - '../model/addresslist', - '../model/url-builder', - '../model/step-navigator', - '../model/shipping-service', - '../model/payment-service', - 'mage/storage', - 'Magento_Ui/js/model/errorlist' + ['../model/quote', + 'Magento_Checkout/js/model/shipping-rate-service' ], - function(quote, addressList, urlBuilder, navigator, shippingService, paymentService, storage, errorList) { + function(quote, shippingRateService) { "use strict"; - var actionCallback; - var result = function(shippingAddress, sameAsBilling, additionalData) { - var serviceUrl; - if (quote.getCheckoutMethod()() === 'guest') { - serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/addresses', {quoteId: quote.getQuoteId()}); - } else { - serviceUrl = urlBuilder.createUrl('/carts/mine/addresses', {}); - } - - errorList.clear(); - additionalData = additionalData || {}; - shippingAddress['same_as_billing'] = (sameAsBilling) ? 1 : 0; - quote.setShippingAddress(shippingAddress); - - storage.post( - serviceUrl, - JSON.stringify({ - shippingAddress: quote.getShippingAddress()(), - billingAddress: quote.getBillingAddress()(), - additionalData: {extensionAttributes : additionalData}, - checkoutMethod: quote.getCheckoutMethod()() - }) - ).done( - function(result) { - shippingService.setShippingRates(result.shipping_methods); - paymentService.setPaymentMethods(result.payment_methods); - quote.setFormattedBillingAddress(result.formatted_billing_address); - quote.setFormattedShippingAddress(result.formatted_shipping_address); - quote.setTotals(result.totals); - navigator.setCurrent('shippingAddress').goNext(); - if (typeof actionCallback == 'function') { - actionCallback(true); - } - } - ).fail( - function(response) { - var error = JSON.parse(response.responseText); - errorList.add(error); - quote.setShippingAddress(null); - quote.setBillingAddress(null); - quote.setFormattedBillingAddress(null); - quote.setFormattedShippingAddress(null); - if (typeof actionCallback == 'function') { - actionCallback(false); - } - } - ); + quote.shippingAddress.subscribe(function () { + shippingRateService.getRates(quote.shippingAddress()) + }); + return function(shippingAddress) { + quote.shippingAddress(shippingAddress); }; - result.setActionCallback = function (value) { - actionCallback = value; - }; - return result; } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js index f00e2e86670c8e145fc67b33ec8a3fe7f1bcbf47..30f629cfc09e52343b5fe41343c8229f3e0e9abf 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/select-shipping-method.js @@ -5,36 +5,12 @@ /*global define,alert*/ define( [ - '../model/quote', - '../model/url-builder', - '../model/step-navigator', - 'Magento_Checkout/js/model/shipping-service', - 'mage/translate', - 'ko' + '../model/quote' ], - function (quote, urlBuilder, navigator, shippingService, $t, ko) { + function (quote) { "use strict"; - return function (code, customOptions, callbacks) { - if (!code) { - alert($t('Please specify a shipping method')); - return; - } - - var proceed = true; - _.each(callbacks, function (callback) { - proceed = proceed && callback(); - }); - - if (proceed) { - var shippingMethodCode = code.split("_"), - shippingRate = shippingService.getRateByCode(shippingMethodCode)[0]; - - quote.setShippingMethod(shippingMethodCode); - quote.setSelectedShippingMethod(code); - quote.setShippingCustomOptions(customOptions); - quote.setCollectedTotals('shipping', shippingRate.amount); - navigator.setCurrent('shippingMethod').goNext(); - } - }; + return function (shippingMethod) { + quote.shippingMethod(shippingMethod) + } } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js new file mode 100644 index 0000000000000000000000000000000000000000..4f1167970a41e3af06ac108be3e60aa44d63ad20 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-payment-information.js @@ -0,0 +1,56 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/url-builder', + 'mage/storage', + 'Magento_Ui/js/model/messageList', + 'Magento_Customer/js/model/customer' + ], + function (quote, urlBuilder, storage, messageList, customer) { + 'use strict'; + + return function () { + var serviceUrl, + payload, + paymentData = quote.paymentMethod(); + + /** + * Checkout for guest and registered customer. + */ + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:quoteId/set-payment-information', { + quoteId: quote.getQuoteId() + }); + payload = { + cartId: quote.getQuoteId(), + email: quote.guestEmail, + paymentMethod: paymentData, + billingAddress: quote.billingAddress() + }; + } else { + serviceUrl = urlBuilder.createUrl('/carts/mine/set-payment-information', {}); + payload = { + cartId: quote.getQuoteId(), + paymentMethod: paymentData, + billingAddress: quote.billingAddress() + }; + } + return storage.post( + serviceUrl, JSON.stringify(payload) + ).done( + function () { + //do nothing + } + ).fail( + function (response) { + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + } + ); + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js b/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js new file mode 100644 index 0000000000000000000000000000000000000000..918f5201012f1eb933940b8a10e817b3a67387b4 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/action/set-shipping-information.js @@ -0,0 +1,17 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define,alert*/ +define( + [ + '../model/quote', + 'Magento_Checkout/js/model/shipping-save-processor' + ], + function (quote, shippingSaveProcessor) { + 'use strict'; + return function () { + return shippingSaveProcessor.saveShippingInformation(quote.shippingAddress().getType()); + } + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js new file mode 100644 index 0000000000000000000000000000000000000000..896f38b9648aa27bee9050378c445d6a7e664ce5 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/address-converter.js @@ -0,0 +1,85 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'jquery', + 'Magento_Checkout/js/model/new-customer-address', + 'mage/utils/objects' + ], + function($, address, mageUtils) { + 'use strict'; + var countryData = window.checkoutConfig.countryData; + + return { + /** + * Convert address form data to Address object + * @param {Object} formData + * @returns {Object} + */ + formAddressDataToQuoteAddress: function(formData) { + // clone address form data to new object + var addressData = $.extend(true, {}, formData), + region; + + if (mageUtils.isObject(addressData.street)) { + addressData.street = this.objectToArray(addressData.street); + } + + addressData.region = { + region_id: null, + region_code: null, + region: null + }; + + if (addressData.region_id) { + region = countryData[addressData.country_id]['regions'][addressData.region_id]; + if (region) { + addressData.region.region_id = addressData['region_id']; + addressData.region.region_code = region['code']; + addressData.region.region = region['name']; + } + } + delete addressData.region_id; + + return address(addressData); + }, + + formDataProviderToFlatData: function(formProviderData, formIndex) { + var addressData = {}; + $.each(formProviderData, function(path, value) { + var pathComponents = path.split('.'); + pathComponents.splice(pathComponents.indexOf(formIndex), 1); + pathComponents.reverse(); + var dataObject = {}; + $.each(pathComponents, function(index, pathPart) { + if (index == 0) { + dataObject[pathPart] = value; + } else { + var parent = {}; + parent[pathPart] = dataObject; + dataObject = parent; + } + }); + $.extend(true, addressData, dataObject); + }); + return addressData; + }, + + /** + * Convert object to array + * @param {Object} object + * @returns {Array} + */ + objectToArray: function (object) { + var convertedArray = []; + $.each(object, function (key) { + return object[key].length ? convertedArray.push(object[key]) : false; + }); + + return convertedArray.slice(0); + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js b/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js deleted file mode 100644 index 62bc28d2527638c59a8f629f09448279187a74d4..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/addresslist.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true*/ -/*global define*/ -define(['jquery'], function($) { - "use strict"; - var addresses = []; - return { - add: function (address) { - addresses.push(address); - }, - getAddressById: function(id) { - var address = null; - $.each(addresses, function(key, item) { - if (id === item.customerAddressId) { - address = item; - return false; - } - }); - return address; - }, - getAddresses: function() { - return addresses.slice(0); - }, - isBillingSameAsShipping: false - }; -}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js new file mode 100644 index 0000000000000000000000000000000000000000..e448a1c30b07da31ae1f26aaecb0477bade09b65 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/cart/authentication-popup.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'Magento_Ui/js/modal/modal' + ], + function ($, modal) { + 'use strict'; + return { + modalWindow: null, + + /** Create popUp window for provided element */ + createPopUp: function(element) { + this.modalWindow = element; + var options = { + 'type': 'popup', + 'modalClass': 'popup-authentication', + 'responsive': true, + 'innerScroll': true, + 'trigger': '.proceed-to-checkout', + 'buttons': [] + }; + modal(options, $(this.modalWindow)); + }, + + /** Show login popup window */ + showModal: function() { + $(this.modalWindow).modal('openModal'); + } + } + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js new file mode 100644 index 0000000000000000000000000000000000000000..7f64f87e3e4c6cb7308f6a441faed2e13a74589a --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/new-customer-address.js @@ -0,0 +1,58 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define([], function() { + /** + * @param addressData + * Returns new address object + */ + return function (addressData) { + var identifier = Date.now(); + return { + email: addressData.email, + countryId: addressData.country_id, + regionId: (addressData.region) ? addressData.region.region_id : null, + regionCode: (addressData.region) ? addressData.region.region_code : null, + region: (addressData.region) ? addressData.region.region : null, + customerId: addressData.customer_id, + street: addressData.street, + company: addressData.company, + telephone: addressData.telephone, + fax: addressData.fax, + postcode: addressData.postcode, + city: addressData.city, + firstname: addressData.firstname, + lastname: addressData.lastname, + middlename: addressData.middlename, + prefix: addressData.prefix, + suffix: addressData.suffix, + vatId: addressData.vat_id, + sameAsBilling: addressData.same_as_billing, + saveInAddressBook: addressData.save_in_address_book, + isDefaultShipping: function() { + return addressData.default_shipping; + }, + isDefaultBilling: function() { + return addressData.default_billing; + }, + getType: function() { + return 'new-customer-address' + }, + getKey: function() { + return this.getType(); + }, + getCacheKey: function() { + return this.getType() + identifier; + }, + isEditable: function() { + return true; + }, + canUseForBilling: function() { + return true; + } + } + } +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js index 9b6fc75a216c506964c20ee938f60ee1677de823..77841ad3b0632b0d155c7618039ea15fdc5776e9 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment-service.js @@ -2,67 +2,72 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true jquery:true*/ -/*global alert*/ define( [ - 'ko', - 'jquery', - 'Magento_Checkout/js/model/quote' + 'underscore', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/payment/method-list', + 'Magento_Checkout/js/action/select-payment-method' ], - function (ko, $, quote) { + function (_, quote, methodList, selectPaymentMethod) { + 'use strict'; + var freeMethodCode = 'free'; + return { - paymentMethods: ko.observableArray([]), - availablePaymentMethods: ko.observableArray([]), - selectedPaymentData: ko.observableArray(), - selectedPaymentInfo: ko.observableArray([]), - setPaymentMethods: function(methods) { - this.paymentMethods(methods); + isFreeAvailable: false, + /** + * Populate the list of payment methods + * @param {Array} methods + */ + setPaymentMethods: function (methods) { + var self = this, + freeMethod, + filteredMethods, + methodIsAvailable; + + freeMethod = _.find(methods, function (method) { + return method.method === freeMethodCode; + }); + this.isFreeAvailable = freeMethod ? true : false; + + if (self.isFreeAvailable && freeMethod && quote.totals().grand_total <= 0) { + methods.splice(0, methods.length, freeMethod); + selectPaymentMethod(freeMethod); + } + filteredMethods = _.without(methods, freeMethod); + + if (filteredMethods.length === 1) { + selectPaymentMethod(filteredMethods[0]); + } else if (quote.paymentMethod()) { + methodIsAvailable = methods.some(function (item) { + return item.method === quote.paymentMethod().method; + }); + //Unset selected payment method if not available + if (!methodIsAvailable) { + selectPaymentMethod(null); + } + } + methodList(methods); }, + /** + * Get the list of available payment methods. + * @returns {Array} + */ getAvailablePaymentMethods: function () { var methods = [], self = this; - $.each(this.paymentMethods(), function (key, method) { - if (self.isFreeMethodActive() && ( - quote.getCalculatedTotal() <= 0 && method['code'] == 'free' - || quote.getCalculatedTotal() > 0 && method['code'] != 'free' - ) || !self.isFreeMethodActive() + _.each(methodList(), function (method) { + if (self.isFreeAvailable && ( + quote.totals().grand_total <= 0 && method.method === freeMethodCode || + quote.totals().grand_total > 0 && method.method !== freeMethodCode + ) || !self.isFreeAvailable ) { methods.push(method); } }); + return methods; - }, - isFreeMethodActive: function () { - var isAvailable = false; - $.each(this.paymentMethods(), function (key, method) { - if (method['code'] == 'free') { - isAvailable = true; - } - }); - return isAvailable; - }, - setSelectedPaymentData: function(data) { - this.selectedPaymentData(data); - }, - getSelectedPaymentData: function () { - return this.selectedPaymentData(); - }, - setSelectedPaymentInfo: function(data) { - this.selectedPaymentInfo(data); - }, - getSelectedPaymentInfo: function () { - return this.selectedPaymentInfo(); - }, - getTitleByCode: function(code) { - var methodTitle = ''; - $.each(this.getAvailablePaymentMethods(), function (key, entity) { - if (entity['code'] == code) { - methodTitle = entity['title']; - } - }); - return methodTitle; } - } + }; } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js new file mode 100644 index 0000000000000000000000000000000000000000..794f7d9a38b01fc043414adb8fdb2714f0aeac42 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-converter.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'underscore' + ], + function (_) { + 'use strict'; + + return function (methods) { + _.each(methods, function(method) { + if (method.hasOwnProperty('code')) { + method.method = method.code; + delete method.code; + } + }); + + return methods; + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js new file mode 100644 index 0000000000000000000000000000000000000000..9b234d7572c8efdfafc4c71456491edfb811b71d --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/method-list.js @@ -0,0 +1,13 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'ko' + ], + function(ko) { + 'use strict'; + return ko.observableArray([]); + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js similarity index 51% rename from app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js rename to app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js index 44285074df09ad9fa0d14f8f94a69c8c8782ba11..1966d296a9ef06c2df54a5c22c6cbe1364e74655 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/free-method.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/payment/renderer-list.js @@ -2,14 +2,13 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*browser:true*/ /*global define*/ define( [ - 'Magento_Checkout/js/view/payment/method-info' + 'ko' ], - function (method) { - return method.extend({ - }); + function(ko) { + 'use strict'; + return ko.observableArray([]); } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..1cc970630a39c7c4509450c921c98cab0886db7f --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/postcode-validator.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define(['mageUtils'], function (utils) { + 'use strict'; + return { + validatedPostCodeExample: [], + validate: function(postCode, countryId) { + var patterns = window.checkoutConfig.postCodes[countryId]; + this.validatedPostCodeExample = []; + + if (!utils.isEmpty(postCode) && !utils.isEmpty(patterns)) { + for (var pattern in patterns) { + if (patterns.hasOwnProperty(pattern)) { + this.validatedPostCodeExample.push(patterns[pattern]['example']); + var regex = new RegExp(patterns[pattern]['pattern']); + if (regex.test(postCode)) { + return true; + } + } + } + return false; + } + return true; + } + } +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js index 650a8b053f7a2c14d07cce94e578e3b1dde6c48f..2ba260a0495c1bd483b291d90988a68cffc48f8d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/quote.js @@ -2,11 +2,10 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true jquery:true*/ -/*global alert*/ define( ['ko'], - function(ko) { + function (ko) { + 'use strict'; var billingAddress = ko.observable(null); var shippingAddress = ko.observable(null); var shippingMethod = ko.observable(null); @@ -14,15 +13,21 @@ define( var quoteData = window.checkoutConfig.quoteData; var basePriceFormat = window.checkoutConfig.basePriceFormat; var priceFormat = window.checkoutConfig.priceFormat; - var selectedShippingMethod = ko.observable(window.checkoutConfig.selectedShippingMethod); var storeCode = window.checkoutConfig.storeCode; - var totals = ko.observable({}); - var checkoutMethod = ko.observable(null); + var totalsData = window.checkoutConfig.totalsData; + var totals = ko.observable(totalsData); var shippingCustomOptions = ko.observable(null); var formattedShippingAddress = ko.observable(null); var formattedBillingAddress = ko.observable(null); var collectedTotals = ko.observable({}); return { + totals: totals, + shippingAddress: shippingAddress, + shippingMethod: shippingMethod, + billingAddress: billingAddress, + paymentMethod: paymentMethod, + guestEmail: null, + getQuoteId: function() { return quoteData.entity_id; }, @@ -39,7 +44,7 @@ define( return window.checkoutConfig.quoteItemData; }, getTotals: function() { - return totals + return totals; }, setTotals: function(totalsData) { if (_.isObject(totalsData.extension_attributes)) { @@ -50,18 +55,6 @@ define( totals(totalsData); this.setCollectedTotals('subtotal_with_discount', parseFloat(totalsData.subtotal_with_discount)); }, - setBillingAddress: function (address) { - billingAddress(address); - }, - getBillingAddress: function() { - return billingAddress; - }, - setShippingAddress: function (address) { - shippingAddress(address); - }, - getShippingAddress: function() { - return shippingAddress; - }, setFormattedBillingAddress: function (address) { formattedBillingAddress(address); }, @@ -80,27 +73,9 @@ define( getPaymentMethod: function() { return paymentMethod; }, - setShippingMethod: function(shippingMethodCode) { - shippingMethod(shippingMethodCode); - }, - getShippingMethod: function() { - return shippingMethod; - }, - getSelectedShippingMethod: function() { - return selectedShippingMethod; - }, - setSelectedShippingMethod: function(shippingMethod) { - selectedShippingMethod(shippingMethod); - }, getStoreCode: function() { return storeCode; }, - getCheckoutMethod: function() { - return checkoutMethod; - }, - setCheckoutMethod: function(method) { - checkoutMethod(method); - }, setShippingCustomOptions: function(customOptions) { shippingCustomOptions(customOptions); }, diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js new file mode 100644 index 0000000000000000000000000000000000000000..b84e16a80bff26af12a7698631259f901cc5dd4f --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js @@ -0,0 +1,90 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'Magento_Customer/js/model/customer', + 'Magento_Checkout/js/model/url-builder', + 'mageUtils' + ], + function(customer, urlBuilder, utils) { + "use strict"; + return { + getUrlForEstimationShippingMethodsForNewAddress: function(quote) { + var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {}; + var urls = { + 'guest': '/guest-carts/:quoteId/estimate-shipping-methods', + 'customer': '/carts/mine/estimate-shipping-methods' + }; + return this.getUrl(urls, params); + }, + + getUrlForEstimationShippingMethodsByAddressId: function(quote) { + var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {}; + var urls = { + 'default': '/carts/mine/estimate-shipping-methods-by-address-id' + }; + return this.getUrl(urls, params); + }, + + getApplyCouponUrl: function(couponCode, quoteId) { + var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quoteId} : {}; + var urls = { + 'guest': '/guest-carts/' + quoteId + '/coupons/' + couponCode, + 'customer': '/carts/mine/coupons/' + couponCode + }; + return this.getUrl(urls, params); + }, + + getCancelCouponUrl: function(quoteId) { + var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quoteId} : {}; + var urls = { + 'guest': '/guest-carts/' + quoteId + '/coupons/', + 'customer': '/carts/mine/coupons/' + }; + return this.getUrl(urls, params); + }, + + getUrlForCartTotals: function(quote) { + var params = (this.getCheckoutMethod() == 'guest') ? {quoteId: quote.getQuoteId()} : {}; + var urls = { + 'guest': '/guest-carts/:quoteId/totals', + 'customer': '/carts/mine/totals' + }; + return this.getUrl(urls, params); + }, + + getUrlForSetShippingInformation: function(quote) { + var params = (this.getCheckoutMethod() == 'guest') ? {cartId: quote.getQuoteId()} : {}; + var urls = { + 'guest': '/carts/:cartId/shipping-information', + 'customer': '/carts/mine/shipping-information' + }; + return this.getUrl(urls, params); + }, + + /** Get url for service */ + getUrl: function(urls, urlParams) { + var url; + + if (utils.isEmpty(urls)) { + return 'Provided service call does not exist.'; + } + + if (!utils.isEmpty(urls['default'])) { + url = urls['default']; + } else { + url = urls[this.getCheckoutMethod()]; + } + return urlBuilder.createUrl(url, urlParams); + }, + + getCheckoutMethod: function() { + return customer.isLoggedIn() ? 'customer' : 'guest'; + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js new file mode 100644 index 0000000000000000000000000000000000000000..d23e82ca703bab7e787a5f47b0027612b4111998 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-address/form-popup-state.js @@ -0,0 +1,16 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'ko' + ], + function(ko) { + 'use strict'; + return { + isVisible: ko.observable(false) + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js new file mode 100644 index 0000000000000000000000000000000000000000..068891a5286964d5dedb4b8812669e45a6f3b5ca --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/customer-address.js @@ -0,0 +1,51 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Checkout/js/model/resource-url-manager', + 'Magento_Checkout/js/model/quote', + 'mage/storage', + 'Magento_Checkout/js/model/shipping-service', + 'Magento_Checkout/js/model/shipping-rate-registry', + 'Magento_Ui/js/model/messageList' + ], + function (resourceUrlManager, quote, storage, shippingService, rateRegistry, messageList) { + "use strict"; + return { + getRates: function(address) { + var cache = rateRegistry.get(address.getKey()); + if (cache) { + shippingService.setShippingRates(cache); + } else { + shippingService.isLoading(true); + storage.post( + resourceUrlManager.getUrlForEstimationShippingMethodsByAddressId(), + JSON.stringify({ + addressId: address.customerAddressId + }), + false + ).done( + function(result) { + rateRegistry.set(address.getKey(), result); + shippingService.setShippingRates(result); + } + + ).fail( + function(response) { + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + shippingService.setShippingRates([]) + } + ).always( + function () { + shippingService.isLoading(false); + } + ); + } + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js new file mode 100644 index 0000000000000000000000000000000000000000..db5052ca0c39f44ddf2ed115ac1d7d94631f2c34 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-processor/new-address.js @@ -0,0 +1,61 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'Magento_Checkout/js/model/resource-url-manager', + 'Magento_Checkout/js/model/quote', + 'mage/storage', + 'Magento_Checkout/js/model/shipping-service', + 'Magento_Checkout/js/model/shipping-rate-registry', + 'Magento_Ui/js/model/messageList' + ], + function (resourceUrlManager, quote, storage, shippingService, rateRegistry, messageList) { + 'use strict'; + + return { + /** + * Get shipping rates for specified address. + * @param {Object} address + */ + getRates: function (address) { + var cache = rateRegistry.get(address.getCacheKey()), + serviceUrl = resourceUrlManager.getUrlForEstimationShippingMethodsForNewAddress(quote), + payload = JSON.stringify({ + address: { + country_id: address.countryId, + region_id: address.regionId, + region: address.region, + postcode: address.postcode + } + } + ); + + if (cache) { + shippingService.setShippingRates(cache); + } else { + shippingService.isLoading(true); + storage.post( + serviceUrl, payload, false + ).done( + function (result) { + rateRegistry.set(address.getCacheKey(), result); + shippingService.setShippingRates(result); + } + ).fail( + function (response) { + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + shippingService.setShippingRates([]); + } + ).always( + function () { + shippingService.isLoading(false); + } + ); + } + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js new file mode 100644 index 0000000000000000000000000000000000000000..e5bd1104b1714d89fa4db7bc2893e604e3ea633a --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-registry.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function() { + "use strict"; + var cache = []; + return { + get: function(addressKey) { + if (cache[addressKey]) { + return cache[addressKey]; + } + return false; + }, + set: function(addressKey, data) { + cache[addressKey] = data; + } + }; + } +); \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js new file mode 100644 index 0000000000000000000000000000000000000000..68bc173215923fff08510790811e5270f4ef5328 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rate-service.js @@ -0,0 +1,34 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/model/shipping-rate-processor/new-address', + 'Magento_Checkout/js/model/shipping-rate-processor/customer-address' + ], + function(defaultProcessor, customerAddressProcessor) { + "use strict"; + var processors = []; + processors['default'] = defaultProcessor; + processors['customer-address'] = customerAddressProcessor; + + return { + registerProcessor: function(type, processor) { + processors[type] = processor; + }, + getRates: function (address) { + var type = address.getType(); + var rates = []; + if (processors[type]) { + rates = processors[type].getRates(address); + } else { + rates = processors['default'].getRates(address); + } + return rates; + } + } + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js new file mode 100644 index 0000000000000000000000000000000000000000..e6eafeee848e544635b8bb1b97ac345b76b52854 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -0,0 +1,35 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + ['jquery'], + function ($) { + "use strict"; + var ratesRules = {}; + var checkoutConfig = window.checkoutConfig; + return { + registerRules: function(carrier, rules) { + if (checkoutConfig.activeCarriers.indexOf(carrier) != -1) { + ratesRules[carrier] = rules.getRules(); + } + }, + getRules: function() { + return ratesRules; + }, + getObservableFields: function() { + var self = this; + var observableFields = []; + $.each(self.getRules(), function(carrier, fields) { + $.each(fields, function(field, rules) { + if (observableFields.indexOf(field) == -1) { + observableFields.push(field); + } + }); + }); + return observableFields; + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..7bd072008705968c57080a089666f07968355fb8 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-rates-validator.js @@ -0,0 +1,122 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'ko', + './shipping-rates-validation-rules', + '../model/address-converter', + '../action/select-shipping-address', + './postcode-validator', + 'mage/translate' + ], + function ($, ko, shippingRatesValidationRules, addressConverter, selectShippingAddress, postcodeValidator, $t) { + 'use strict'; + var checkoutConfig = window.checkoutConfig; + var validators = []; + var observedElements = []; + var postcodeElement = null; + + return { + validateAddressTimeout: 0, + validateDelay: 2000, + + registerValidator: function(carrier, validator) { + if (checkoutConfig.activeCarriers.indexOf(carrier) != -1) { + validators.push(validator); + } + }, + + validateAddressData: function(address) { + return validators.some(function(validator) { + return validator.validate(address); + }); + }, + + bindChangeHandlers: function(elements) { + var self = this; + var observableFields = shippingRatesValidationRules.getObservableFields(); + $.each(elements, function(index, elem) { + if (elem && observableFields.indexOf(elem.index) != -1) { + if (elem.index !== 'postcode') { + self.bindHandler(elem); + } + } + + if (elem.index === 'postcode') { + self.bindHandler(elem); + postcodeElement = elem; + } + }); + }, + + bindHandler: function(element) { + var self = this; + if (element.component.indexOf('/group') != -1) { + $.each(element.elems(), function(index, elem) { + self.bindHandler(elem); + }); + } else { + element.on('value', function() { + clearTimeout(self.validateAddressTimeout); + self.validateAddressTimeout = setTimeout(function() { + if (self.postcodeValidation()) { + self.validateFields(); + } + }, self.validateDelay); + }); + observedElements.push(element); + } + }, + + postcodeValidation: function() { + if (postcodeElement == null || postcodeElement.value() == null) { + return true; + } + + var countryId = $('select[name="shippingAddress[country_id]"]').val(); + var validationResult = postcodeValidator.validate(postcodeElement.value(), countryId); + + postcodeElement.error(null); + if (!validationResult) { + var errorMessage = $t('Invalid Zip/Postal code for current country!'); + if (postcodeValidator.validatedPostCodeExample.length) { + errorMessage += $t(' Example: ') + postcodeValidator.validatedPostCodeExample.join('; '); + } + postcodeElement.error(errorMessage); + } + return validationResult; + }, + + /** + * Convert form data to quote address and validate fields for shipping rates + */ + validateFields: function() { + var addressFlat = addressConverter.formDataProviderToFlatData( + this.collectObservedData(), + 'shippingAddress' + ); + if (this.validateAddressData(addressFlat)) { + var address = addressConverter.formAddressDataToQuoteAddress(addressFlat); + selectShippingAddress(address); + } + }, + + /** + * Collect observed fields data to object + * + * @returns {*} + */ + collectObservedData: function() { + var observedValues = {}; + $.each(observedElements, function(index, field) { + observedValues[field.dataScope] = field.value(); + }); + return observedValues; + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js new file mode 100644 index 0000000000000000000000000000000000000000..8789ad0ccb38841da2fa7c900e1bee380fbc19e7 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/model/shipping-save-processor/default' + ], + function(defaultProcessor) { + 'use strict'; + var processors = []; + processors['default'] = defaultProcessor; + + return { + registerProcessor: function(type, processor) { + processors[type] = processor; + }, + saveShippingInformation: function (type) { + var rates = []; + if (processors[type]) { + rates = processors[type].saveShippingInformation(); + } else { + rates = processors['default'].saveShippingInformation(); + } + return rates; + } + } + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js new file mode 100644 index 0000000000000000000000000000000000000000..7233d429dc0691907a04b174452db883dbdc24df --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-save-processor/default.js @@ -0,0 +1,46 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define,alert*/ +define( + [ + 'ko', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/resource-url-manager', + 'mage/storage', + 'Magento_Checkout/js/model/payment-service', + 'Magento_Checkout/js/model/payment/method-converter', + 'Magento_Ui/js/model/messageList' + ], + function (ko, quote, resourceUrlManager, storage, paymentService, methodConverter, messageList) { + 'use strict'; + + return { + saveShippingInformation: function() { + var payload = { + addressInformation: { + shipping_address: quote.shippingAddress(), + shipping_method_code: quote.shippingMethod().method_code, + shipping_carrier_code: quote.shippingMethod().carrier_code + } + }; + + return storage.post( + resourceUrlManager.getUrlForSetShippingInformation(quote), + JSON.stringify(payload) + ).done( + function (response) { + quote.setTotals(response.totals); + paymentService.setPaymentMethods(methodConverter(response.payment_methods)); + } + ).fail( + function (response) { + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + } + ); + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js index 8bb0366111a7aa7002bf81a1932cbea8ec1582de..f03da90e2fade9119bbfb16dbcced239f13572c8 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/shipping-service.js @@ -4,46 +4,63 @@ */ /*global define*/ define( - ['ko', 'jquery'], - function (ko, $) { + [ + 'ko', + 'Magento_Checkout/js/action/select-shipping-method', + 'Magento_Checkout/js/model/quote', + 'jquery' + ], + function (ko, selectShippingMethodAction, quote, $) { "use strict"; - var rates = ko.observable([]); + var shippingRates = ko.observableArray([]); return { - shippingRates: ko.observableArray([]), + isLoading: ko.observable(false), + /** + * Set shipping rates + * + * @param ratesData + */ setShippingRates: function(ratesData) { - var self = this; - rates(ratesData); - self.shippingRates([]); - $.each(ratesData, function (key, entity) { - var rateEntity = {}; - rateEntity.items = []; - if (!ratesData.hasOwnProperty(entity.carrier_code)) { - rateEntity['carrier_code'] = entity.carrier_code; - rateEntity['carrier_title'] = entity.carrier_title; - } - rateEntity.items.push(entity); - self.shippingRates.push(rateEntity); - }); + shippingRates(ratesData); + shippingRates.valueHasMutated(); + if (ratesData.length == 1) { + //set shipping rate if we have only one available shipping rate + selectShippingMethodAction(ratesData[0]); + } else if(quote.shippingMethod()) { + var rateIsAvailable = ratesData.some(function (rate) { + if (rate.carrier_code == quote.shippingMethod().carrier_code + && rate.method_code == quote.shippingMethod().method_code) { + return true; + } + return false; + }); + //Unset selected shipping shipping method if not available + if (!rateIsAvailable) { + selectShippingMethodAction(null); + } + } }, + + /** + * Get shipping rates + * + * @returns {*} + */ getSippingRates: function() { - return this.shippingRates; + return shippingRates; }, - getTitleByCode: function(methodCodeParts) { - var shippingMethodTitle = '', shippingMethodCode, carrierCode, methodCode; - if (!methodCodeParts) { - return shippingMethodTitle; - } - shippingMethodCode = methodCodeParts.slice(0); - carrierCode = shippingMethodCode.shift(); - methodCode = shippingMethodCode.join('_'); - $.each(rates(), function (key, entity) { - if (entity['carrier_code'] === carrierCode && entity['method_code'] === methodCode) { - shippingMethodTitle = entity['carrier_title'] + " - " + entity['method_title']; - } - }); - return shippingMethodTitle; + + /** + * Get shipping method title + * + * @param shippingMethod + * @returns {string} + */ + getTitleByCode: function(shippingMethod) { + return shippingMethod ? shippingMethod.carrier_title + " - " + shippingMethod.method_title : ''; }, + getRateByCode : function(methodCodeParts) { var shippingRates = [], shippingMethodCode = methodCodeParts.slice(0), diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js index 44a48fa893285ea45161b23c6a402466921a1f06..0ce40c7999a80c32cfdb08b3c0ece8a261df3bdb 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/step-navigator.js @@ -7,198 +7,89 @@ define( [ 'jquery', - 'ko', - 'Magento_Customer/js/model/customer', - 'Magento_Ui/js/model/errorlist' + 'ko' ], - function($, ko, customer, errorList) { - var customerIsLoggedIn = customer.isLoggedIn()(); - var defaultStepClass = 'section'; - var allowedStepClass = 'allow'; - var activeStepClass = 'active'; + function($, ko) { + var steps = ko.observableArray(); + return { - currentStep: null, - steps: [ - { - name: 'authentication', - isVisible: ko.observable(!customerIsLoggedIn), - isEnabled: true, - number: ko.observable(1), - classAttributes: ko.observable(defaultStepClass) - }, - { - name: 'billingAddress', - isVisible: ko.observable(customerIsLoggedIn), - isEnabled: true, - number: ko.observable(2), - classAttributes: ko.observable(defaultStepClass) - }, - { - name: 'shippingAddress', - isVisible: ko.observable(false), - isEnabled: true, - number: ko.observable(3), - classAttributes: ko.observable(defaultStepClass) - }, - { - name: 'shippingMethod', - isVisible: ko.observable(false), - isEnabled: true, - number: ko.observable(4), - classAttributes: ko.observable(defaultStepClass) - }, - { - name: 'paymentMethod', - isVisible: ko.observable(false), - isEnabled: true, - number: ko.observable(5), - classAttributes: ko.observable(defaultStepClass) - }, - { - name: 'review', - isVisible: ko.observable(false), - isEnabled: true, - number: ko.observable(6), - classAttributes: ko.observable(defaultStepClass) - } - ], - setCurrent: function(step) { - this.currentStep = step; - return this; - }, - getCurrentStep: function() { - if (!this.currentStep) { - alert('Current step not set.'); - return; - } - var self = this; - var currentStep = null; - $.each(this.steps, function(key, step) { - if (self.currentStep == step.name) { - currentStep = step; - } + steps: steps, + stepCodes: [], + registerStep: function(code, title, isVisible, sortOrder) { + steps.push({ + code: code, + title : title, + isVisible: isVisible, + sortOrder: sortOrder }); - return currentStep; - }, - goNext: function() { - var currentStep = this.getCurrentStep(); - var nextStepOrder = currentStep.number() + 1; - var nextStep = null; - $.each(this.steps, function(key, item) { - if (nextStepOrder == item.number()) { - nextStep = item; - return false; + this.stepCodes.push(code); + }, + + sortItems: function(itemOne, itemTwo) { + return itemOne.sortOrder > itemTwo.sortOrder ? 1 : -1 + }, + + getActiveItemIndex: function() { + var activeIndex = 0; + steps.sort(this.sortItems).forEach(function(element, index) { + if (element.isVisible()) { + activeIndex = index; } }); - if (nextStep) { - this.toStep(nextStep.name); - } - }, - goBack: function() { - var currentStep = this.getCurrentStep(); - var prevStepOrder = currentStep.number() - 1; - var previousStep = null; - $.each(this.steps, function(key, item) { - if (prevStepOrder == item.number()) { - previousStep = item; - return false; - } - }); - if (previousStep) { - this.toStep(previousStep.name); - } - }, - getStepClassAttributes: function(name) { - return this.findStepByName(name).classAttributes; - }, - setStepClassAttributes: function(name) { - var stepClass = defaultStepClass; - var step = this.findStepByName(name); - if (step.isVisible()) { - stepClass += ' ' + activeStepClass; - } - if (this.isStepAvailable(step.name)) { - stepClass += ' ' + allowedStepClass; - } - step.classAttributes(stepClass); - }, - updateStepsClassAttributes: function() { - var self = this; - $.each(this.steps, function(key, step) { - var stepClass = defaultStepClass; - if (step.isVisible()) { - stepClass += ' ' + activeStepClass; - } - if (self.isStepAvailable(step.name)) { - stepClass += ' ' + allowedStepClass; + return activeIndex; + }, + + isProcessed: function(code) { + var activeItemIndex = this.getActiveItemIndex(); + var sortedItems = steps.sort(this.sortItems); + var requestedItemIndex = -1; + sortedItems.forEach(function(element, index) { + if (element.code == code) { + requestedItemIndex = index; } - step.classAttributes(stepClass); }); + return activeItemIndex > requestedItemIndex; }, - isStepAvailable: function(name) { - var visibleStep = this.getCurrentVisibleStep(); - var step = this.findStepByName(name); - return (step.number() < visibleStep.number()); - }, - goToStep: function(name) { - if (this.isStepAvailable(name)) { - this.toStep(name); - } - }, - toStep: function(name) { - if (name) { - $.each(this.steps, function(key, step) { - step.isVisible(false); - }); - this.findStepByName(name).isVisible(true); - this.updateStepsClassAttributes(); - errorList.clear(); + + navigateTo: function(step) { + var sortedItems = steps.sort(this.sortItems); + if (!this.isProcessed(step.code)) { + return; } - }, - findStepByName: function(name) { - var step = null; - $.each(this.steps, function(key, currentStep) { - if (name == currentStep.name) { - step = currentStep; - return false; + sortedItems.forEach(function(element) { + if (element.code == step.code) { + element.isVisible(true); + } else { + element.isVisible(false); } + }); - return step; }, - isStepVisible: function(step) { - this.setStepClassAttributes(step); - return this.findStepByName(step).isVisible; - }, - setStepVisible: function(step, flag) { - this.findStepByName(step).isVisible(flag); - }, - getCurrentVisibleStep: function() { - var step = null; - $.each(this.steps, function(key, currentStep) { - if (currentStep.isVisible()) { - step = currentStep; - return false; + + next: function() { + var activeIndex = 0; + steps.sort(this.sortItems).forEach(function(element, index) { + if (element.isVisible()) { + element.isVisible(false); + activeIndex = index; } }); - return step; - }, - setStepEnabled: function(step, flag) { - this.findStepByName(step).isEnabled = flag; - this.refreshStepsNumbers(); + if (steps().length > activeIndex + 1) { + steps()[activeIndex + 1].isVisible(true); + } }, - refreshStepsNumbers: function() { - var numb = 1; - $.each(this.steps, function(key, item) { - if (item.isEnabled) { - item.number(numb); - numb++; - } else { - item.number(null); + + back: function() { + var activeIndex = 0; + steps.sort(this.sortItems).forEach(function(element, index) { + if (element.isVisible()) { + element.isVisible(false); + activeIndex = index; } }); - }, - getStepNumber: function(name) { - return this.findStepByName(name).number; + if (steps()[activeIndex - 1]) { + steps()[activeIndex - 1].isVisible(true); + } } }; } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js b/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js new file mode 100644 index 0000000000000000000000000000000000000000..f32c0d2c15f3c40a2ea1468ac5c13d0e4b74da90 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/model/totals.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'ko', + 'Magento_Checkout/js/model/quote' + ], + function(ko, quote) { + + return { + totals: quote.totals, + isLoading: ko.observable(false), + getItems: function() { + if (!this.totals() || !this.totals().items) { + return []; + } + return this.totals().items; + }, + getSegment: function(code) { + if (!this.totals()) { + return null; + } + for (var i in this.totals().total_segments) { + var total = this.totals().total_segments[i]; + if (total.code == code) { + return total; + } + } + return null; + } + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js new file mode 100644 index 0000000000000000000000000000000000000000..87794967ddff9501e2fba69a01fa8644decf056c --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/proceed-to-checkout.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Checkout/js/model/cart/authentication-popup', + 'Magento_Customer/js/customer-data' + ], + function($, authenticationPopup, customerData) { + return function (config, element) { + $(element).click(function(event) { + event.preventDefault(); + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + if (customer() == false && !cart().isGuestCheckoutAllowed) { + authenticationPopup.showModal(); + return false; + } + location.href = window.checkout.checkoutUrl; + }); + + }; + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js index 2455c3932eabaeee72ba2ec5997a0ed9a35b5732..5f93022da11a9089f3ef90ebef20ef2057529a56 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/sidebar.js @@ -6,9 +6,11 @@ /*global confirm:true*/ define([ "jquery", + 'Magento_Checkout/js/model/cart/authentication-popup', + 'Magento_Customer/js/customer-data', "jquery/ui", "mage/decorate" -], function($){ +], function($, authenticationPopup, customerData){ $.widget('mage.sidebar', { options: { @@ -32,6 +34,13 @@ define([ }); $(this.options.button.checkout).on('click', $.proxy(function() { + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + if (customer() == false && !cart().isGuestCheckoutAllowed) { + authenticationPopup.showModal(); + return false; + } location.href = this.options.url.checkout; }, this)); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js index 44018161f3eeabaf1969bd9e06558db266b13fd7..b921592e718ca5fc134113209f8a39e2624f68d3 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/authentication.js @@ -6,66 +6,43 @@ /*global alert*/ define( [ - "jquery", - 'ko', + 'jquery', 'Magento_Ui/js/form/form', 'Magento_Customer/js/action/login', 'Magento_Customer/js/model/customer', - 'Magento_Checkout/js/model/step-navigator', - '../model/quote', 'mage/validation' ], - function($, ko, Component, login, customer, navigator, quote) { - "use strict"; - var stepName = 'authentication'; + function($, Component, loginAction, customer) { + 'use strict'; + var checkoutConfig = window.checkoutConfig; + return Component.extend({ - stepNumber: navigator.getStepNumber(stepName), - isGuestCheckoutAllowed: window.checkoutConfig.isGuestCheckoutAllowed, - isCustomerLoginRequired: window.checkoutConfig.isCustomerLoginRequired, - registerUrl: window.checkoutConfig.registerUrl, - forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl, - username: '', - password: '', - isVisible: navigator.isStepVisible(stepName), + isGuestCheckoutAllowed: checkoutConfig.isGuestCheckoutAllowed, + isCustomerLoginRequired: checkoutConfig.isCustomerLoginRequired, + registerUrl: checkoutConfig.registerUrl, + forgotPasswordUrl: checkoutConfig.forgotPasswordUrl, defaults: { template: 'Magento_Checkout/authentication' }, + + /** Is login form enabled for current customer */ + isActive: function() { + return !customer.isLoggedIn(); + }, + + /** Provide login action */ login: function(loginForm) { - var loginData = {}; - var formDataArray = $(loginForm).serializeArray(); - var loginFormSelector = 'form[data-role=login]'; + var loginData = {}, + formDataArray = $(loginForm).serializeArray(); + formDataArray.forEach(function (entry) { loginData[entry.name] = entry.value; }); - if($(loginFormSelector).validation() && $(loginFormSelector).validation('isValid')) { - login(loginData); - } - }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - isActive: function() { - if (customer.isLoggedIn()()) { - navigator.setStepEnabled(stepName, false); - } - return !customer.isLoggedIn()(); - }, - isChecked: function() { - if (!isGuestCheckoutAllowed) { - return 'register'; - } - return false; - }, - setCheckoutMethod: function() { - quote.setCheckoutMethod('guest'); - $('[name="customerDetails.password"]').hide(); - $('[name="customerDetails.confirm_password"]').hide(); - $('[name*=".save_in_address_book"]').hide(); - navigator.setCurrent('authentication').goNext(); - }, - navigateToCurrentStep: function() { - if (!navigator.isStepVisible(stepName)()) { - navigator.goToStep(stepName); + + if($(loginForm).validation() + && $(loginForm).validation('isValid') + ) { + loginAction(loginData); } } }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js b/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js index b84bed5619b32ec51ddd662dee71f4c65926f0c7..8424c7a9161db3a2eaefb81515920bc1d8202b9f 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/beforePlaceOrder.js @@ -9,7 +9,6 @@ define( "use strict"; return Component.extend({ defaults: { - template: 'Magento_Checkout/review/iterator', displayArea: 'beforePlaceOrder' } }); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js index ebb20378def25789c4011acbd530a9b6e62da8ee..2ca86001d726002b81df9f2c6adc83bac7443080 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/billing-address.js @@ -6,127 +6,112 @@ /*global define*/ define( [ - "jquery", - 'Magento_Ui/js/form/form', 'ko', + 'Magento_Ui/js/form/form', 'Magento_Customer/js/model/customer', - '../action/select-billing-address', - '../model/step-navigator', - '../model/quote', - '../model/addresslist' + 'Magento_Customer/js/model/address-list', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/action/create-billing-address', + 'Magento_Checkout/js/action/select-billing-address', + 'mage/translate' ], - function ($, Component, ko, customer, selectBillingAddress, navigator, quote, addressList) { + function (ko, Component, customer, addressList, quote, createBillingAddress, selectBillingAddress, $t) { "use strict"; - var stepName = 'billingAddress'; - var newAddressSelected = ko.observable(false); - var billingFormSelector = '#co-billing-form'; + + var newAddressOption = { + getAddressInline: function() { + return $t('New Address'); + }, + customerAddressId: null + }; + var addressOptions = addressList().filter(function(address, index, addresses) { + return address.getType() == 'customer-address'; + }); + addressOptions.push(newAddressOption); return Component.extend({ defaults: { template: 'Magento_Checkout/billing-address' }, + initObservable: function () { - this._super().observe('useForShipping'); + this._super() + .observe({ + selectedAddress: null, + isAddressDetailsVisible: quote.shippingAddress() != null, + isAddressFormVisible: !customer.isLoggedIn() || addressOptions.length == 1, + isAddressSameAsShipping: false + }); + quote.billingAddress.subscribe(function(newAddress) { + this.isAddressSameAsShipping(newAddress == quote.shippingAddress() && !quote.isVirtual()); + this.isAddressDetailsVisible(true); + }, this); return this; }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - stepNumber: navigator.getStepNumber(stepName), - billingAddresses: function() { - var newAddress = { - getAddressInline: function() { - return $.mage.__('New address'); - }, - customerAddressId: null - }, - addresses = addressList.getAddresses(); - addresses.push(newAddress); - return addresses; - }, - selectedBillingAddressId: ko.observable( - addressList.getAddresses().length ? addressList.getAddresses()[0].customerAddressId : null - ), - isVisible: navigator.isStepVisible(stepName), - useForShipping: "1", - quoteIsVirtual: quote.isVirtual(), - billingAddressesOptionsText: function(item) { - return item.getAddressInline(); + + canUseShippingAddress: ko.computed(function(){ + return !quote.isVirtual() && quote.shippingAddress() + && quote.shippingAddress().canUseForBilling(); + }), + + saveInAddressBook: true, + + currentBillingAddress: quote.billingAddress, + + addressOptions: addressOptions, + + customerHasAddresses: addressOptions.length > 1, + + addressOptionsText: function(address) { + return address.getAddressInline(); }, - checkUseForShipping: function(useForShipping) { - var additionalData = {}; - if (useForShipping() instanceof Object) { - additionalData = useForShipping().getAdditionalData(); - useForShipping('1'); + + useShippingAddress: function () { + if (this.isAddressSameAsShipping()) { + selectBillingAddress(quote.shippingAddress()); + this.isAddressDetailsVisible(true); + } else { + this.isAddressDetailsVisible(false); } - return additionalData; + return true; }, - submitBillingAddress: function() { - var additionalData = this.checkUseForShipping(this.useForShipping); - if (this.selectedBillingAddressId()) { - selectBillingAddress( - addressList.getAddressById(this.selectedBillingAddressId()), - this.useForShipping, - additionalData - ); + + updateAddress: function () { + if (this.selectedAddress() && this.selectedAddress() != newAddressOption) { + selectBillingAddress(this.selectedAddress()); } else { - this.validate(); + this.source.set('params.invalid', false); + this.source.trigger(this.dataScopePrefix + '.data.validate'); if (!this.source.get('params.invalid')) { - var addressData = this.source.get('billingAddress'); - /** - * All the the input fields that are not a part of the address (e. g. CAPTCHA) but need to be - * submitted in the same request must have data-scope attribute set - */ - var additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray(); - additionalFields.forEach(function (field) { - additionalData[field.name] = field.value; - }); - if (quote.getCheckoutMethod()() && !customer.isLoggedIn()()) { - addressData.email = this.source.get('customerDetails.email'); - } - if($(billingFormSelector).validation() && $(billingFormSelector).validation('isValid')) { - selectBillingAddress(addressData, this.useForShipping, additionalData); + var addressData = this.source.get(this.dataScopePrefix); + + if (this.isCustomerLoggedIn && !this.customerHasAddresses) { + this.saveInAddressBook = true; } + addressData.save_in_address_book = this.saveInAddressBook; + + // New address must be selected as a billing address + selectBillingAddress(createBillingAddress(addressData)); } } }, - navigateToCurrentStep: function() { - if (!navigator.isStepVisible(stepName)()) { - navigator.goToStep(stepName); - } - }, - isNewAddressSelected: function() { - if (!this.customerAddressCount) { - return true; - } - return newAddressSelected(); - }, - onAddressChange: function (value) { - value() === null ? newAddressSelected(true) : newAddressSelected(false); + + editAddress: function () { + this.isAddressDetailsVisible(false); }, - validate: function() { - var fields = $(billingFormSelector).find('input, select'); - - this.source.set('params.invalid', false); - fields.trigger('change'); - this.source.trigger('billingAddress.data.validate'); - if (!customer.isLoggedIn()()) { - this.source.trigger('customerDetails.data.validate'); + + cancelAddressEdit: function () { + if (quote.billingAddress()) { + // restore 'Same As Shipping' checkbox state + this.isAddressSameAsShipping( + !quote.isVirtual() && (quote.shippingAddress() == quote.billingAddress()) + ); + this.isAddressDetailsVisible(true); } - this.validateAdditionalAddressFields(); }, - validateAdditionalAddressFields: function() { - $(billingFormSelector).validation(); - $(billingFormSelector + ' input[data-scope="additionalAddressData"]').each(function(key, item) { - $(item).valid(); - }); - }, - isCustomerLoggedIn: customer.isLoggedIn(), - customerAddressCount: window.checkoutConfig.customerAddressCount, - hideExtraFields: function() { - if (!quote.getCheckoutMethod()() && customer.isLoggedIn()()) { - $('[name="customerDetails.email"]').hide(); - } + + onAddressChange: function (address) { + this.isAddressFormVisible(address == newAddressOption); } }); } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js new file mode 100644 index 0000000000000000000000000000000000000000..0985d990a697bde35a780beb7d318895548e9103 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/authentication.js @@ -0,0 +1,71 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'ko', + 'Magento_Ui/js/form/form', + 'Magento_Customer/js/action/login', + 'Magento_Customer/js/customer-data', + 'Magento_Checkout/js/model/cart/authentication-popup', + 'mage/translate', + 'mage/validation' + ], + function($, ko, Component, loginAction, customerData, authenticationPopup, $t) { + 'use strict'; + return Component.extend({ + registerUrl: window.checkout.customerRegisterUrl, + forgotPasswordUrl: window.checkout.customerForgotPasswordUrl, + modalWindow: null, + isLoading: ko.observable(false), + + initialize: function() { + var self = this; + this._super(); + loginAction.registerLoginCallback(function() { + self.isLoading(false); + }); + }, + + /** Init popup login window */ + setModalElement: function (element) { + authenticationPopup.createPopUp(element); + }, + + /** Is login form enabled for current customer */ + isActive: function() { + var customer = customerData.get('customer'); + return customer() == false; + }, + + /** Show login popup window */ + showModal: function() { + if (this.modalWindow) { + $(this.modalWindow).modal('openModal'); + } else { + alert($t('Guest checkout is disabled.')); + } + }, + + /** Provide login action */ + login: function(loginForm) { + var loginData = {}, + formDataArray = $(loginForm).serializeArray(); + formDataArray.forEach(function (entry) { + loginData[entry.name] = entry.value; + }); + + if($(loginForm).validation() + && $(loginForm).validation('isValid') + ) { + this.isLoading(true); + loginAction(loginData); + } + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js b/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js deleted file mode 100644 index 85a2097532024573de71c8f0295bd0f6a2e8dc45..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/columns.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent' - ], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/iterator', - displayArea: 'columns' - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js b/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js deleted file mode 100644 index f2a959dfcdb510885a209738efc74ef0b8372cf4..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/discount.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define( - [ - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' - ], - function (Component, quote, priceUtils) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/discount', - displayArea: 'totals' - }, - colspan: 3, - style: '', - fieldName: 'Discount', - totals: quote.getTotals(), - getPureValue: function() { - var price = 0; - if (this.totals()) { - price = this.totals().discount_amount; - } - return price; - }, - getValue: function() { - var price = 0; - if (this.totals()) { - price = this.totals().discount_amount; - } - return priceUtils.formatPrice(price, quote.getPriceFormat()); - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js b/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js deleted file mode 100644 index ee96966658f05bc7ffb0bbe2aabd5cecb9decdb2..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsAfter.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent' - ], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/iterator', - displayArea: 'itemsAfter' - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js b/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js deleted file mode 100644 index 9d2e10ce0a87aeb5bb847e5eb83e11321d9d3c79..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/itemsBefore.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent' - ], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/iterator', - displayArea: 'itemsBefore' - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js index 373056b389e955be7f910313faf38af2e83cddbb..51e59d8ff6bb31bfb06222c8ef965cbdf19f835d 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/minicart.js @@ -6,11 +6,13 @@ define([ 'uiComponent', 'Magento_Customer/js/customer-data', 'jquery', - 'ko' -], function (Component, customerData, $, ko) { + 'ko', + 'mage/url' +], function (Component, customerData, $, ko, url) { 'use strict'; var sidebarInitialized = false; + url.setBaseUrl(window.checkout.baseUrl); function initSidebar() { var minicart = $("[data-block='minicart']"); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js index 313ba3b923d06aa5caf03cef5330f719244471af..cde7e59dad6483cd2f2c95c55b1764403f80f035 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment.js @@ -6,154 +6,35 @@ /*global alert*/ define( [ - 'jquery', 'uiComponent', - '../model/quote', - '../action/select-payment-method', + 'ko', + 'Magento_Checkout/js/model/quote', 'Magento_Checkout/js/model/step-navigator', 'Magento_Checkout/js/model/payment-service', - 'mage/translate', - 'mageUtils' + 'Magento_Checkout/js/model/payment/method-converter' ], - function ($, Component, quote, selectPaymentMethod, navigator, paymentService, $t, utils) { - var stepName = 'paymentMethod'; + function (Component, ko, quote, stepNavigator, paymentService, methodConverter) { + 'use strict'; + + /** Set payment methods to collection */ + paymentService.setPaymentMethods(methodConverter(window.checkoutConfig.paymentMethods)); + return Component.extend({ defaults: { template: 'Magento_Checkout/payment', activeMethod: '' }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - stepNumber: navigator.getStepNumber(stepName), - isVisible: navigator.isStepVisible(stepName), - paymentForm: '#co-payment-form', - initObservable: function () { - this._super() - .observe('activeMethod'); - return this; - }, - quoteHasShippingMethod: function() { - return quote.isVirtual() || quote.getShippingMethod(); - }, - setPaymentMethod: function() { - if (!this.activeMethod()) { - alert($t('Please choose a payment method.')); - return; - } - - if (this.isFormValid()) { - selectPaymentMethod( - this.getPaymentMethodData(), - this.getPaymentMethodInfo(), - this.getPaymentMethodCallbacks() - ); - } - }, - getPaymentMethodData: function() { - var data = { - "method": this.activeMethod(), - "po_number": null, - "cc_owner": null, - "cc_number": null, - "cc_type": null, - "cc_exp_year": null, - "cc_exp_month": null, - "additional_data": null - }; - utils.extend(data, this.getActiveMethodView().getData()); - - _.each(this.getAdditionalMethods(), function(elem) { - if (elem.isActive()) { - utils.extend(data, elem.getData()); - } - }); - - return data; - }, - getPaymentMethodInfo: function() { - var info = this.getActiveMethodView().getInfo(); - - _.each(this.getAdditionalMethods(), function(elem) { - if (elem.isActive()) { - info = _.union(info, elem.getInfo()); - } - }); - - return info; - }, - getPaymentMethodCallbacks: function() { - var callbacks = [this.getActiveMethodView().afterSave.bind(this.getActiveMethodView())]; - - _.each(this.getAdditionalMethods(), function(elem) { - if (elem.isActive()) { - callbacks = _.union(callbacks, [elem.afterSave.bind(elem)]); - } - }); + isVisible: ko.observable(quote.isVirtual()), + quoteIsVirtual: quote.isVirtual(), - return callbacks; + initialize: function () { + this._super(); + stepNavigator.registerStep('billing', 'Review & Payments', this.isVisible, 20); + return this; }, - getAvailableViews: function () { - var sortedElems = [], - self = this; - - _.each(this.getAvailableMethods(), function (originElem) { - var method = self.getMethodViewByCode(originElem.code); - if (method && method.isAvailable()) { - sortedElems.push(method); - } - }); - if (sortedElems.length == 1) { - this.activeMethod(sortedElems[0].getCode()); - } - - return sortedElems; - }, - getAvailableMethods: function() { - return paymentService.getAvailablePaymentMethods(); - }, - getAvailableCodes: function() { - return _.pluck(this.getAvailableMethods(), 'code'); - }, - getMethodViewByCode: function(code) { - return _.find(this.getRegion('paymentMethods')(), function(elem) { - return elem.getCode() == code; - }); - }, - getActiveMethodView: function() { - return this.getMethodViewByCode(this.activeMethod()); - }, - backToShippingMethod: function() { - navigator.setCurrent(stepName).goBack(); - }, - navigateToCurrentStep: function() { - if (!navigator.isStepVisible(stepName)()) { - navigator.goToStep(stepName); - } - }, - isMethodActive: function(code) { - return this.activeMethod() === code; - }, - isFormValid: function() { - $(this.paymentForm).validation(); - return $(this.paymentForm).validation('isValid'); - }, getFormKey: function() { return window.checkoutConfig.formKey; - }, - getAdditionalMethods: function() { - var methods = []; - _.each(this.getRegion('beforeMethods')(), function(elem) { - methods = _.union(methods, elem.elems()); - }); - _.each(this.getRegion('afterMethods')(), function(elem) { - methods = _.union(methods, elem.elems()); - }); - return methods; - }, - getMethodControlAdditionalClass: function() { - return this.getAvailableViews().length == 1 ? ' hidden' : ''; } }); } diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js new file mode 100644 index 0000000000000000000000000000000000000000..7fa9e10b69a781d1f9afc86bc79ae7cc39c388d7 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js @@ -0,0 +1,110 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'ko', + 'jquery', + 'uiComponent', + 'Magento_Checkout/js/action/place-order', + 'Magento_Checkout/js/action/select-payment-method', + 'Magento_Checkout/js/model/quote', + 'Magento_Customer/js/model/customer', + 'Magento_Checkout/js/model/payment-service' + ], + function (ko, $, Component, placeOrderAction, selectPaymentMethodAction, quote, customer, paymentService) { + 'use strict'; + return Component.extend({ + redirectAfterPlaceOrder: true, + /** + * Initialize view. + * + * @returns {Component} Chainable. + */ + initialize: function () { + this._super().initChildren(); + return this; + }, + + /** + * Initialize child elements + * + * @returns {Component} Chainable. + */ + initChildren: function () { + return this; + }, + + /** + * Place order. + */ + placeOrder: function () { + var emailValidationResult = customer.isLoggedIn(), + loginFormSelector = 'form[data-role=email-with-possible-login]'; + if (!customer.isLoggedIn()) { + $(loginFormSelector).validation(); + emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid()); + } + if (emailValidationResult && this.validate()) { + placeOrderAction(this.getData(), this.redirectAfterPlaceOrder); + } + }, + + selectPaymentMethod: function() { + selectPaymentMethodAction(this.getData()); + return true; + }, + + isChecked: ko.computed(function () { + return quote.paymentMethod() ? quote.paymentMethod().method : null; + }), + + isRadioButtonVisible: ko.computed(function () { + return paymentService.getAvailablePaymentMethods().length !== 1; + }), + + /** + * Get payment method data + */ + getData: function() { + return { + "method": this.item.method, + "po_number": null, + "cc_owner": null, + "cc_number": null, + "cc_type": null, + "cc_exp_year": null, + "cc_exp_month": null, + "additional_data": null + }; + }, + + /** + * Get payment method type. + */ + getTitle: function () { + return this.item.title; + }, + + /** + * Get payment method code. + */ + getCode: function () { + return this.item.method; + }, + + validate: function () { + return true; + }, + + getBillingAddressFormName: function() { + return 'billing-address-form-' + this.item.method; + }, + + disposeSubscriptions: function () { + // dispose all active subscriptions + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js deleted file mode 100644 index 64833500f70a1919a513cb7b6362bf5cc1655be6..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/generic.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent' - ], - function (Component) { - return Component.extend({ - getCode: function() { - return this.index; - }, - isActive: function(parent) { - return false; - }, - getData: function() { - return {}; - }, - getInfo: function() { - return []; - }, - afterSave: function() { - return true; - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js new file mode 100644 index 0000000000000000000000000000000000000000..78faf6ba156658108f4820978fba27190f2cc9a3 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/list.js @@ -0,0 +1,119 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'underscore', + 'ko', + 'mageUtils', + 'uiComponent', + 'Magento_Checkout/js/model/payment/method-list', + 'Magento_Checkout/js/model/payment/renderer-list', + 'Magento_Ui/js/core/renderer/layout' +], function (_, ko, utils, Component, paymentMethods, rendererList, layout) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/payment-methods/list', + visible: paymentMethods().length > 0 + }, + + /** + * Initialize view. + * + * @returns {Component} Chainable. + */ + initialize: function () { + this._super().initChildren(); + paymentMethods.subscribe( + function (changes) { + _.each(changes, function (change) { + if (change.status === 'added') { + this.createRenderer(change.value); + } else if (change.status === 'deleted') { + this.removeRenderer(change.value.method); + } + }, this); + }, this, 'arrayChange'); + + return this; + }, + + /** + * Create renders for child payment methods. + * + * @returns {Component} Chainable. + */ + initChildren: function () { + var self = this; + _.each(paymentMethods(), function (paymentMethodData) { + self.createRenderer(paymentMethodData); + }); + + return this; + }, + + /** + * Create renderer. + * + * @param {Object} paymentMethodData + */ + createRenderer: function (paymentMethodData) { + var renderer = this.getRendererByType(paymentMethodData.method), + rendererTemplate, + rendererComponent, + templateData; + + if (renderer) { + templateData = { + parentName: this.name, + name: paymentMethodData.method + }; + rendererTemplate = { + parent: '${ $.$data.parentName }', + name: '${ $.$data.name }', + displayArea: 'payment-method-items', + component: renderer.component + }; + rendererComponent = utils.template(rendererTemplate, templateData); + utils.extend(rendererComponent, { + item: paymentMethodData + }); + layout([rendererComponent]); + } + }, + + /** + * Get renderer for payment method type. + * + * @param {String} paymentMethodCode + * @returns {Object} + */ + getRendererByType: function (paymentMethodCode) { + var compatibleRenderer; + _.find(rendererList(), function (renderer) { + if (renderer.type === paymentMethodCode) { + compatibleRenderer = renderer; + } + }); + + return compatibleRenderer; + }, + + /** + * Remove view renderer. + * + * @param {String} paymentMethodCode + */ + removeRenderer: function (paymentMethodCode) { + var items = this.getRegion('payment-method-items'); + _.find(items(), function (value) { + if (value.item.method === paymentMethodCode) { + value.disposeSubscriptions(); + this.removeChild(value); + } + }, this); + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js deleted file mode 100644 index c653d3f54111d7f52b031e3376bdc8db84c4dce0..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/method-info.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'Magento_Checkout/js/view/payment/generic', - '../../model/payment-service' - ], - function (generic, paymentService) { - return generic.extend({ - defaults: { - titleTemplate: 'Magento_Checkout/payment/generic-title', - displayArea: 'paymentMethods', - isEnabled: true - }, - initObservable: function () { - this._super() - .observe('isEnabled'); - return this; - }, - getMethod: function() { - var paymentMethods = _.indexBy(paymentService.getAvailablePaymentMethods(), 'code'); - - return paymentMethods[this.getCode()]; - }, - isAvailable: function() { - return this.getMethod() != null; - }, - getTitle: function() { - return this.isAvailable() ? this.getMethod()['title'] : ''; - }, - isActive: function(parent) { - return this.isAvailable() && parent.isMethodActive(this.getCode()); - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js b/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js deleted file mode 100644 index ec20c4d42179aeee395bec21babff8eda2849516..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/payment/virtual.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true*/ -/*global define*/ -define( - [ - 'ko', - 'Magento_Checkout/js/view/payment/generic', - 'Magento_Checkout/js/model/quote' - ], - function (ko, generic, quote) { - return generic.extend({ - defaults: { - isChecked: false - }, - isAvailable: function() { - return false; - }, - isOn: function() { - return false; - }, - getBalance: function() { - return 0; - }, - initObservable: function () { - this._super() - .observe('isChecked'); - - var self = this; - this.isChecked.subscribe( - function(isChecked) { - if (isChecked) { - quote.setCollectedTotals(self.getCode(), -parseFloat(self.getBalance())); - } else { - quote.setCollectedTotals(self.getCode(), 0); - } - } - ); - this.isChecked(this.isOn()); - - return this; - }, - isActive: function() { - return this.isChecked(); - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js new file mode 100644 index 0000000000000000000000000000000000000000..626171c589d3d3aaf6ab2a06e5b3b0884fd8322a --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js @@ -0,0 +1,35 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'ko', + 'uiComponent', + 'Magento_Checkout/js/model/step-navigator' + ], + function (ko, Component, stepNavigator) { + var steps = stepNavigator.steps; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/progress-bar', + visible: true + }, + steps: steps, + + sortItems: function(itemOne, itemTwo) { + return stepNavigator.sortItems(itemOne, itemTwo); + }, + + navigateTo: function(step) { + stepNavigator.navigateTo(step); + }, + + isProcessed: function(item) { + return stepNavigator.isProcessed(item.code); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js b/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js deleted file mode 100644 index 1017f9f160eeaa55c9c306bf42b1c98fd8f6d8f5..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/progress.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'ko', - 'uiComponent', - 'Magento_Checkout/js/model/step-navigator', - 'Magento_Checkout/js/model/quote', - 'Magento_Checkout/js/model/shipping-service', - 'Magento_Checkout/js/model/payment-service' - ], - function (ko, Component, navigator, quote, shippingService, paymentService) { - var className = ko.observable(); - return Component.extend({ - defaults: { - template: 'Magento_Checkout/progress' - }, - getClassName: function() - { - className('opc-block-progress'); - if(quote.getBillingAddress()() && (quote.getShippingAddress()()) || quote.isVirtual()) { - className('opc-block-progress active') - } - if (quote.getPaymentMethod()()) { - className('opc-block-progress order-review-step') - } - return className() - }, - - isShowStep: function (stepName) { - switch(stepName){ - case 'shippingAddress': - if (quote.isVirtual()) { - return false - } - return navigator.findStepByName(stepName).isEnabled; - break; - case 'shippingMethod': - if (quote.isVirtual()) { - return false - } - return navigator.findStepByName(stepName).isEnabled; - break; - default: - return navigator.findStepByName(stepName).isEnabled; - } - }, - isStepComplete: function(stepName) { - switch(stepName){ - case 'billingAddress': - return quote.getFormattedBillingAddress()|| false; - break; - case 'shippingAddress': - return quote.getFormattedShippingAddress()||false; - break; - case 'shippingMethod': - return quote.getShippingMethod()||false; - break; - case 'paymentMethod': - return quote.getPaymentMethod()||false; - break; - default: - return false; - } - }, - getBillingAddress: function() { - return quote.getFormattedBillingAddress()(); - }, - getShippingAddress: function() { - return quote.getFormattedShippingAddress(); - }, - getShippingMethod: function() { - return quote.getShippingMethod() - }, - getPaymentMethod: function() { - return quote.getPaymentMethod(); - }, - getPaymentMethodTitle: function() { - var code = this.getPaymentMethod()(); - return paymentService.getTitleByCode(code) - }, - getPaymentMethodInfo: function() { - return paymentService.getSelectedPaymentInfo() - }, - goToStep: function(stepName) { - navigator.goToStep(stepName); - }, - getShippingMethodTitle: function() { - var code = this.getShippingMethod()(); - return shippingService.getTitleByCode(code) - }, - getShippingRates: function() { - var code = this.getShippingMethod()(); - return shippingService.getRateByCode(code) - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review.js deleted file mode 100644 index c2c9c58333f9f990073680f12e449cb67fd96471..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true jquery:true*/ -/*global define*/ -define( - [ - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'mage/url', - 'Magento_Checkout/js/model/step-navigator', - 'Magento_Checkout/js/action/place-order', - 'underscore' - ], - function (Component, quote, url, navigator, orderAction, _) { - "use strict"; - var stepName = 'review'; - var itemsBefore = []; - var itemsAfter = []; - var beforePlaceOrder = {}; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review' - }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - stepNumber: navigator.getStepNumber(stepName), - quoteHasPaymentMethod: quote.getPaymentMethod(), - itemsBefore: itemsBefore, - itemsAfter: itemsAfter, - beforePlaceOrder: beforePlaceOrder, - getItems: function() { - return quote.getTotals()().items; - }, - getColHeaders: function() { - return ['name', 'price', 'qty', 'subtotal']; - }, - isVisible: navigator.isStepVisible(stepName), - cartUrl: url.build('checkout/cart/'), - placeOrder: function(callback) { - var component, - isValid = false; - if (_.isEmpty(this.beforePlaceOrder)) { - orderAction(null, callback); - } else { - for (component in this.beforePlaceOrder) { - if (this.beforePlaceOrder.hasOwnProperty(component) && !this.beforePlaceOrder[component].validate()) { - isValid = true; - } - } - if (isValid) { - orderAction(this.beforePlaceOrder[component].getSubmitParams(), callback); - } - } - }, - // get recalculated totals when all data set - getTotals: quote.getTotals() - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js index e160151929985e6a859950e7c33141c7bead36a1..595871bc061e3c513341892fa5f83300e5a8836f 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/review/actions.js @@ -17,7 +17,7 @@ define( displayArea: 'actions' }, getActiveView: function() { - var view = this.getViewByCode(quote.getPaymentMethod()()); + var view = this.getViewByCode(quote.paymentMethod()); return view ? view : this.getDefaultView(); }, getViewByCode: function(code) { diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js deleted file mode 100644 index 3c80b6595f9ef83703676ed7f2c5954da1fd4ac8..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/column.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent', - '../../../model/quote', - 'Magento_Catalog/js/price-utils' - ], - function (Component, quote, priceUtils) { - "use strict"; - var ownClass = ''; - var columnTitle = ''; - return Component.extend({ - defaults: { - headerClass: null, - ownClass: ownClass, - columnTitle: columnTitle, - template: 'Magento_Checkout/review/item/column' - }, - getClass: function() { - return 'col ' + this.ownClass; - }, - getHeaderClass: function() { - if (this.headerClass) { - return this.headerClass; - } - return 'col ' + this.ownClass; - }, - getColName: function() { - return this.columnTitle; - }, - getValue: function(quoteItem) { - return quoteItem.name; - }, - getFormattedPrice: function (price) { - return priceUtils.formatPrice(price, quote.getPriceFormat()); - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js deleted file mode 100644 index 0066f8cce1c0c39607ece39310b05a4226aba5a0..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/price.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - '../column' - ], - function (column) { - "use strict"; - return column.extend({ - defaults: { - ownClass: 'price', - columnTitle: 'Price', - template: 'Magento_Checkout/review/item/columns/price' - }, - getValue: function(quoteItem) { - return this.getFormattedPrice(quoteItem.price); - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js b/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js deleted file mode 100644 index c3352464d34e2e54cad7c2ed67b2bf314801915e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/qty.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - '../column' - ], - function (column) { - "use strict"; - return column.extend({ - defaults: { - ownClass: 'qty', - columnTitle: 'Qty', - template: 'Magento_Checkout/review/item/columns/qty' - }, - getValue: function(quoteItem) { - return quoteItem.qty; - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js deleted file mode 100644 index aaa5529851d792e13ed91dcb28c29f66773efd24..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address.js +++ /dev/null @@ -1,165 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define( - [ - "jquery", - 'Magento_Ui/js/form/form', - 'ko', - 'Magento_Checkout/js/action/select-shipping-address', - 'Magento_Customer/js/model/customer', - '../model/quote', - 'Magento_Checkout/js/model/step-navigator', - '../model/addresslist', - 'underscore' - ], - function($, Component, ko, selectShippingAddress, customer, quote, navigator, addressList, _) { - 'use strict'; - var stepName = 'shippingAddress'; - var newAddressSelected = ko.observable(false); - return Component.extend({ - defaults: { - template: 'Magento_Checkout/shipping-address', - visible: true, - formVisible: customer.getShippingAddressList().length === 0 - }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - stepNumber: navigator.getStepNumber(stepName), - addresses: function() { - var newAddress = { - getAddressInline: function() { - return $.mage.__('New address'); - }, - customerAddressId: null - }, - addresses = addressList.getAddresses(); - addresses.push(newAddress); - return addresses; - }, - selectedAddressId: ko.observable( - addressList.getAddresses().length ? addressList.getAddresses()[0].customerAddressId : null - ), - sameAsBilling: ko.observable(null), - quoteHasBillingAddress: quote.getBillingAddress(), - isVisible: navigator.isStepVisible(stepName), - initObservable: function () { - this._super() - .observe('visible'); - return this; - }, - isActive: function() { - if (quote.isVirtual()) { - navigator.setStepEnabled(stepName, false); - } - return !quote.isVirtual(); - }, - selectShippingAddress: function() { - var additionalFields, - addressData, - additionalData = {}, - billingAddress = quote.getBillingAddress()(); - - if (!billingAddress.customerAddressId || !this.visible()) { - /** - * All the the input fields that are not a part of the address but need to be submitted - * in the same request must have data-scope attribute set - */ - additionalFields = $('input[data-scope="additionalAddressData"]').serializeArray(); - additionalFields.forEach(function (field) { - additionalData[field.name] = field.value; - }); - } - - if (!newAddressSelected()) { - selectShippingAddress( - addressList.getAddressById(this.selectedAddressId()), - this.sameAsBilling(), - additionalData - ); - } else { - if (this.visible()) { - this.validate(); - } - - if (!this.source.get('params.invalid')) { - addressData = this.source.get('shippingAddress'); - selectShippingAddress(addressData, this.sameAsBilling(), additionalData); - } - } - }, - sameAsBillingClick: function() { - var billingAddress, - shippingAddress, - property; - - addressList.isBillingSameAsShipping = !addressList.isBillingSameAsShipping; - - if (this.sameAsBilling()) { - billingAddress = quote.getBillingAddress()(); - - if (billingAddress.customerAddressId) { - this.selectedAddressId(billingAddress.customerAddressId); - newAddressSelected(false); - - } else { - // copy billing address data to shipping address form if customer uses new address for billing - shippingAddress = this.source.get('shippingAddress'); - - for (property in billingAddress) { - if (billingAddress.hasOwnProperty(property) && shippingAddress.hasOwnProperty(property)) { - if (typeof billingAddress[property] === 'string') { - this.source.set('shippingAddress.' + property, billingAddress[property]); - } else { - this.source.set('shippingAddress.' + property, _.clone(billingAddress[property])); - } - } - } - - this.selectedAddressId(null); - newAddressSelected(true); - } - } - return true; - }, - onAddressChange: function() { - var billingAddress = quote.getBillingAddress(); - - if (this.selectedAddressId() !== billingAddress().customerAddressId) { - this.sameAsBilling(false); - } - - if (this.selectedAddressId() === null) { - newAddressSelected(true); - } else { - newAddressSelected(false); - } - }, - // Checkout step navigation - backToBilling: function() { - navigator.setCurrent(stepName).goBack(); - }, - navigateToCurrentStep: function() { - if (!navigator.isStepVisible(stepName)()) { - navigator.goToStep(stepName); - } - }, - isNewAddressSelected: function() { - if (!this.customerAddressCount) { - newAddressSelected(true); - return true; - } - return newAddressSelected(); - }, - validate: function() { - this.source.set('params.invalid', false); - this.source.trigger('shippingAddress.data.validate'); - }, - isCustomerLoggedIn: customer.isLoggedIn(), - customerAddressCount: window.checkoutConfig.customerAddressCount - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js new file mode 100644 index 0000000000000000000000000000000000000000..16ed0dbabc78b5ca4141a2c946b6dec97ed34c69 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/address-renderer/default.js @@ -0,0 +1,53 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define([ + 'jquery', + 'ko', + 'uiComponent', + 'Magento_Checkout/js/action/select-shipping-address', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/shipping-address/form-popup-state' +], function($, ko, Component, selectShippingAddressAction, quote, formPopUpState) { + 'use strict'; + var countryData = window.checkoutConfig.countryData; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping-address/address-renderer/default' + }, + + initProperties: function () { + this._super(); + this.isSelected = ko.computed(function() { + var isSelected = false; + var shippingAddress = quote.shippingAddress(); + if (shippingAddress) { + isSelected = shippingAddress.getKey() == this.address().getKey(); + } + return isSelected; + }, this); + + return this; + }, + + getCountryName: function(countryId) { + return (countryData[countryId] != undefined) ? countryData[countryId].name : ""; + }, + + /** Set selected customer shipping address */ + selectAddress: function() { + selectShippingAddressAction(this.address()); + }, + + editAddress: function() { + formPopUpState.isVisible(true); + this.showPopup(); + + }, + showPopup: function() { + $('[data-open-modal="opc-new-shipping-address"]').trigger('click'); + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js new file mode 100644 index 0000000000000000000000000000000000000000..352d8e628e37f4a598115181c8a3c576e56b8ed2 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-address/list.js @@ -0,0 +1,84 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define([ + 'underscore', + 'ko', + 'mageUtils', + 'uiComponent', + 'Magento_Ui/js/core/renderer/layout', + 'Magento_Customer/js/model/address-list' +], function (_, ko, utils, Component, layout, addressList) { + 'use strict'; + var defaultRendererTemplate = { + parent: '${ $.$data.parentName }', + name: '${ $.$data.name }', + component: 'Magento_Checkout/js/view/shipping-address/address-renderer/default' + }; + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping-address/list', + visible: addressList().length > 0, + rendererTemplates: [] + }, + + initialize: function () { + this._super() + .initChildren(); + + addressList.subscribe( + function(changes) { + var self = this; + changes.forEach(function(change) { + if (change.status === 'added') { + self.createRendererComponent(change.value, change.index); + } + }); + }, + this, + 'arrayChange' + ); + return this; + }, + + initProperties: function () { + this._super(); + // the list of child components that are responsible for address rendering + this.rendererComponents = []; + return this; + }, + + initChildren: function () { + _.each(addressList(), this.createRendererComponent, this); + return this; + }, + + /** + * Create new component that will render given address in the address list + * + * @param address + * @param index + */ + createRendererComponent: function (address, index) { + if (index in this.rendererComponents) { + this.rendererComponents[index].address(address); + } else { + // rendererTemplates are provided via layout + var rendererTemplate = (address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined) + ? utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()]) + : defaultRendererTemplate; + var templateData = { + parentName: this.name, + name: index + }; + var rendererComponent = utils.template(rendererTemplate, templateData); + utils.extend(rendererComponent, {address: ko.observable(address)}); + layout([rendererComponent]); + this.rendererComponents[index] = rendererComponent; + } + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js new file mode 100644 index 0000000000000000000000000000000000000000..d33dd69762f9ca3fab4c12c0ea05108d91e61764 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information.js @@ -0,0 +1,37 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'uiComponent', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/shipping-service', + 'Magento_Checkout/js/model/step-navigator' + ], + function($, Component, quote, shippingService, stepNavigator) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping-information' + }, + + isVisible: function() { + return !quote.isVirtual() && stepNavigator.isProcessed('shipping'); + }, + + getShippingMethodTitle: function() { + return shippingService.getTitleByCode(quote.shippingMethod()) + }, + + back: function() { + // Temp solution for closing summary sliding panel on mobile MAGETWO-3864 + $('#opc-sidebar').modal('toggleModal'); + stepNavigator.back(); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js new file mode 100644 index 0000000000000000000000000000000000000000..9df85f97d84c402e33a2dad71ad1e48bf5b643eb --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/address-renderer/default.js @@ -0,0 +1,20 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define([ + 'uiComponent' +], function(Component) { + 'use strict'; + var countryData = window.checkoutConfig.countryData; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping-information/address-renderer/default' + }, + + getCountryName: function(countryId) { + return (countryData[countryId] != undefined) ? countryData[countryId].name : ""; + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js new file mode 100644 index 0000000000000000000000000000000000000000..36342149c66e6fcc140e5c1d6ab9316c45e26958 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-information/list.js @@ -0,0 +1,84 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define([ + 'jquery', + 'ko', + 'mageUtils', + 'uiComponent', + 'Magento_Ui/js/core/renderer/layout', + 'Magento_Checkout/js/model/quote' +], function ($, ko, utils, Component, layout, quote) { + 'use strict'; + var defaultRendererTemplate = { + parent: '${ $.$data.parentName }', + name: '${ $.$data.name }', + component: 'Magento_Checkout/js/view/shipping-information/address-renderer/default' + }; + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping-information/list', + rendererTemplates: {} + }, + + initialize: function () { + this._super() + .initChildren(); + + var self = this; + quote.shippingAddress.subscribe(function(address) { + self.createRendererComponent(address); + }); + return this; + }, + + initProperties: function () { + this._super(); + // the list of child components that are responsible for address rendering + this.rendererComponents = {}; + return this; + }, + + initChildren: function () { + return this; + }, + + /** + * Create new component that will render given address in the address list + * + * @param address + */ + createRendererComponent: function (address) { + + $.each(this.rendererComponents, function(index, component) { + component.visible(false); + }); + + if (this.rendererComponents[address.getType()]) { + this.rendererComponents[address.getType()].address(address); + this.rendererComponents[address.getType()].visible(true); + } else { + // rendererTemplates are provided via layout + var rendererTemplate = + (address.getType() != undefined && this.rendererTemplates[address.getType()] != undefined) + ? utils.extend({}, defaultRendererTemplate, this.rendererTemplates[address.getType()]) + : defaultRendererTemplate; + var templateData = { + parentName: this.name, + name: address.getType() + }; + + var rendererComponent = utils.template(rendererTemplate, templateData); + utils.extend( + rendererComponent, + {address: ko.observable(address), visible: ko.observable(true)} + ); + layout([rendererComponent]); + this.rendererComponents[address.getType()] = rendererComponent; + } + } + }); +}); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js deleted file mode 100644 index 29f4ebbca2a04b3d8d9eba738a9c734b3abd112b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping-method.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'jquery', - 'underscore', - 'uiComponent', - '../model/quote', - '../model/shipping-service', - '../action/select-shipping-method', - 'Magento_Catalog/js/price-utils', - 'Magento_Checkout/js/model/step-navigator' - ], - function ($, _, Component, quote, shippingService, selectShippingMethod, priceUtils, navigator) { - var stepName = 'shippingMethod'; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/shipping-method' - }, - stepClassAttributes: function() { - return navigator.getStepClassAttributes(stepName); - }, - stepNumber: navigator.getStepNumber(stepName), - rates: shippingService.getSippingRates(), - // Checkout step navigation - isVisible: navigator.isStepVisible(stepName), - quoteHasShippingAddress: function() { - return quote.isVirtual() || quote.getShippingAddress(); - }, - - selectedMethod: quote.getSelectedShippingMethod(), - verifySelectedMethodCode: function (data) { - if (this.selectedMethod() == data) { - return data; - } - return false; - }, - - setShippingMethod: function (form) { - var item, - customOptions = {}; - for (item in this.elems()) { - if ('submit' in this.elems()[item]) { - customOptions = _.extend(customOptions, this.elems()[item].submit()); - } - } - form = $(form); - var code = form.find("input[name='shipping_method']:checked").val(); - selectShippingMethod(code, customOptions, this.getAfterSelectCallbacks()); - }, - getAfterSelectCallbacks: function() { - var callbacks = []; - _.each(this.getAdditionalMethods(), function(view) { - if (typeof view.afterSelect === 'function') { - callbacks.push(view.afterSelect); - } - }); - return callbacks; - }, - getAdditionalMethods: function() { - var methods = []; - _.each(this.getRegion('afterSelect')(), function(elem) { - methods = _.union(methods, elem.elems()); - }); - return methods; - }, - isActive: function() { - if (quote.isVirtual()) { - navigator.setStepEnabled(stepName, false); - } - return !quote.isVirtual(); - }, - backToShippingAddress: function () { - navigator.setCurrent(stepName).goBack(); - }, - navigateToCurrentStep: function() { - if (!navigator.isStepVisible(stepName)()) { - navigator.goToStep(stepName); - } - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js new file mode 100644 index 0000000000000000000000000000000000000000..7a0b60c760956737ff6d178faaa8528a8754d470 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -0,0 +1,241 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'Magento_Ui/js/form/form', + 'ko', + 'Magento_Customer/js/model/customer', + 'Magento_Customer/js/model/address-list', + 'Magento_Checkout/js/model/address-converter', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/action/create-shipping-address', + 'Magento_Checkout/js/action/select-shipping-address', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-address/form-popup-state', + 'Magento_Checkout/js/model/shipping-service', + 'Magento_Checkout/js/action/select-shipping-method', + 'Magento_Checkout/js/model/shipping-rate-registry', + 'Magento_Checkout/js/action/set-shipping-information', + 'Magento_Checkout/js/model/new-customer-address', + 'Magento_Checkout/js/model/step-navigator', + 'Magento_Ui/js/modal/modal', + 'mage/translate' + ], + function( + $, + Component, + ko, + customer, + addressList, + addressConverter, + quote, + createShippingAddress, + selectShippingAddress, + shippingRatesValidator, + formPopUpState, + shippingService, + selectShippingMethodAction, + rateRegistry, + setShippingInformationAction, + newAddress, + stepNavigator, + modal, + $t + ) { + 'use strict'; + var rates = window.checkoutConfig.shippingRates.data, + rateKey = window.checkoutConfig.shippingRates.key; + var popUp = null; + if (addressList().length == 0) { + var address = new newAddress({}); + rateRegistry.set(address.getCacheKey(), rates); + shippingService.setShippingRates(rates); + selectShippingAddress(address); + } + + if (rateKey) { + rateRegistry.set(rateKey, rates); + } + + selectShippingMethodAction(window.checkoutConfig.selectedShippingMethod); + shippingService.setShippingRates(rates); + + return Component.extend({ + defaults: { + template: 'Magento_Checkout/shipping' + }, + visible: ko.observable(!quote.isVirtual()), + isCustomerLoggedIn: customer.isLoggedIn, + isFormPopUpVisible: formPopUpState.isVisible, + isFormInline: addressList().length == 0, + isNewAddressAdded: ko.observable(false), + saveInAddressBook: true, + quoteIsVirtual: quote.isVirtual(), + + initialize: function () { + var self = this; + this._super(); + var shippingAddress = quote.shippingAddress(); + if (!shippingAddress) { + var isShippingAddressInitialized = addressList.some(function (address) { + if (address.isDefaultShipping()) { + selectShippingAddress(address); + return true; + } + return false; + }); + if (!isShippingAddressInitialized && addressList().length == 1) { + selectShippingAddress(addressList()[0]); + } + } + if (rates.length == 1) { + selectShippingMethodAction(rates[0]) + } + + if (!quote.isVirtual()) { + stepNavigator.registerStep('shipping', 'Shipping', this.visible, 10); + } + + this.isFormPopUpVisible.subscribe(function(value) { + if (value) { + self.getPopUp().openModal(); + } + }); + + return this; + }, + + initElement: function(element) { + if (element.index === 'shipping-address-fieldset') { + shippingRatesValidator.bindChangeHandlers(element.elems()); + } + }, + + getPopUp: function() { + var self = this; + if (!popUp) { + var buttons = this.popUpForm.options.buttons; + this.popUpForm.options.buttons = [ + { + text: buttons.save.text ? buttons.save.text : $t('Save Address'), + class: buttons.save.class ? buttons.save.class : 'action primary action-save-address', + click: self.saveNewAddress.bind(self) + }, + { + text: buttons.cancel.text ? buttons.cancel.text: $t('Cancel'), + class: buttons.cancel.class ? buttons.cancel.class : 'action secondary action-hide-popup', + click: function() { + this.closeModal(); + } + } + ]; + this.popUpForm.options.closed = function() { + self.isFormPopUpVisible(false); + }; + popUp = modal(this.popUpForm.options, $(this.popUpForm.element)); + } + return popUp; + }, + + /** Show address form popup */ + showFormPopUp: function() { + this.isFormPopUpVisible(true); + }, + + + /** Save new shipping address */ + saveNewAddress: function() { + this.source.set('params.invalid', false); + this.source.trigger('shippingAddress.data.validate'); + + if (!this.source.get('params.invalid')) { + var addressData = this.source.get('shippingAddress'); + addressData.save_in_address_book = this.saveInAddressBook; + + // New address must be selected as a shipping address + selectShippingAddress(createShippingAddress(addressData)); + this.getPopUp().closeModal(); + this.isNewAddressAdded(true); + } + }, + + /** Shipping Method View **/ + rates: shippingService.getSippingRates(), + isLoading: shippingService.isLoading, + isSelected: ko.computed(function () { + return quote.shippingMethod() + ? quote.shippingMethod().carrier_code + '_' + quote.shippingMethod().method_code + : null; + } + ), + + selectShippingMethod: function(shippingMethod) { + selectShippingMethodAction(shippingMethod); + return true; + }, + + setShippingInformation: function () { + if (this.validateShippingInformation()) { + setShippingInformationAction().done( + function() { + stepNavigator.next(); + } + ); + } + }, + + validateShippingInformation: function() { + var shippingAddress, + addressData, + loginFormSelector = 'form[data-role=email-with-possible-login]', + emailValidationResult = customer.isLoggedIn(); + + if (!quote.shippingMethod()) { + alert($t('Please specify a shipping method')); + return false; + } + + if (!customer.isLoggedIn()) { + $(loginFormSelector).validation(); + emailValidationResult = Boolean($(loginFormSelector + ' input[name=username]').valid()); + } + + if (this.isFormInline) { + this.source.set('params.invalid', false); + this.source.trigger('shippingAddress.data.validate'); + if (this.source.get('params.invalid') + || !quote.shippingMethod().method_code + || !quote.shippingMethod().carrier_code + || !emailValidationResult + ) { + return false; + } + shippingAddress = quote.shippingAddress(); + addressData = addressConverter.formAddressDataToQuoteAddress( + this.source.get('shippingAddress') + ); + + //Copy form data to quote shipping address object + for (var field in addressData) { + if (addressData.hasOwnProperty(field) + && shippingAddress.hasOwnProperty(field) + && typeof addressData[field] != 'function' + ) { + shippingAddress[field] = addressData[field]; + } + } + + if (customer.isLoggedIn()) { + shippingAddress.save_in_address_book = true; + } + selectShippingAddress(shippingAddress); + } + return true; + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js deleted file mode 100644 index 227129562f0e58471263236a60dff85ce8a26b0b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/subtotal.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define( - ['uiComponent'], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/iterator', - displayArea: 'totals' - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary.js similarity index 53% rename from app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary.js index 1d8f713edc4c829a97086f3df4b7b69a150ec92a..7a97079de6bcdf291c0bddacdf8b9e77efed2ac6 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/onepage.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary.js @@ -2,17 +2,16 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*browser:true jquery:true*/ /*global define*/ define( [ - 'uiComponent' + 'uiComponent', + 'Magento_Checkout/js/model/totals' ], - function (Component) { + function(Component, totals) { + 'use strict'; return Component.extend({ - defaults: { - template: 'Magento_Checkout/onepage' - } + isLoading: totals.isLoading }); } ); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js new file mode 100644 index 0000000000000000000000000000000000000000..35a4b0071d724572aefb3cc1faaeee68123f3606 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/abstract-total.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/quote', + 'Magento_Catalog/js/price-utils', + 'Magento_Checkout/js/model/totals', + 'Magento_Checkout/js/model/step-navigator' + ], + function (Component, quote, priceUtils, totals, stepNavigator) { + "use strict"; + return Component.extend({ + getFormattedPrice: function (price) { + return priceUtils.formatPrice(price, quote.getPriceFormat()); + }, + getTotals: function() { + return totals.totals(); + }, + isFullMode: function() { + if (!this.getTotals()) { + return false; + } + return stepNavigator.isProcessed('shipping'); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js new file mode 100644 index 0000000000000000000000000000000000000000..0a41d2b46f2bfe4ec67d75d470b261e7fe7f3626 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/cart-items.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'ko', + 'Magento_Checkout/js/model/totals', + 'uiComponent', + 'Magento_Checkout/js/model/step-navigator', + 'Magento_Checkout/js/model/quote' + ], + function (ko, totals, Component, stepNavigator, quote) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/summary/cart-items' + }, + totals: totals.totals(), + getItems: totals.getItems(), + getItemsQty: function() { + return parseInt(this.totals.items_qty) || 0; + }, + isItemsBlockExpanded: function () { + return quote.isVirtual() || stepNavigator.isProcessed('shipping'); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js new file mode 100644 index 0000000000000000000000000000000000000000..0f341a847edc1f10af2ed256c115573212899d75 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/grand-total.js @@ -0,0 +1,32 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote' + ], + function (Component, quote) { + "use strict"; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/summary/grand-total' + }, + isDisplayed: function() { + return this.isFullMode(); + }, + getPureValue: function() { + var totals = quote.getTotals()(); + if (totals) { + return totals.grand_total; + } + return quote.grand_total; + }, + getValue: function() { + return this.getFormattedPrice(this.getPureValue()); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js similarity index 59% rename from app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js index 7e04d856621c69cb54018ea1aa937ddfad943163..1c965b0d5701be6269b412b9e825d1499531acca 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/name.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details.js @@ -6,15 +6,15 @@ /*global alert*/ define( [ - '../column' + 'uiComponent', + '../../../model/quote', + 'Magento_Catalog/js/price-utils' ], - function (column) { + function (Component, quote, priceUtils) { "use strict"; - return column.extend({ + return Component.extend({ defaults: { - ownClass: 'name', - columnTitle: 'Product Name', - template: 'Magento_Checkout/review/item/columns/name' + template: 'Magento_Checkout/summary/item/details' }, getValue: function(quoteItem) { return quoteItem.name; diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js similarity index 61% rename from app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js rename to app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js index f08fb4830a0db1ab8aa6e6e474fc0d83d90e03df..30d43f7369298743b79f1fb9d9d76e0de6c93044 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/review/item/columns/subtotal.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/subtotal.js @@ -6,15 +6,14 @@ /*global alert*/ define( [ - '../column' + 'Magento_Checkout/js/view/summary/abstract-total' ], - function (column) { + function (viewModel) { "use strict"; - return column.extend({ + return viewModel.extend({ defaults: { - ownClass: 'subtotal', - columnTitle: 'Subtotal', - template: 'Magento_Checkout/review/item/columns/price' + displayArea: 'after_details', + template: 'Magento_Checkout/summary/item/details/subtotal' }, getValue: function(quoteItem) { return this.getFormattedPrice(quoteItem.row_total); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js new file mode 100644 index 0000000000000000000000000000000000000000..2efdc4f91f4b071b79cd916c5cc2e090981e5a29 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/item/details/thumbnail.js @@ -0,0 +1,52 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'uiComponent' + ], + function (Component) { + "use strict"; + var imageData = window.checkoutConfig.imageData; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/summary/item/details/thumbnail' + }, + displayArea: 'before_details', + imageData: imageData, + getImageItem: function(item) { + if (this.imageData[item.item_id]) { + return this.imageData[item.item_id]; + } + return []; + }, + getSrc: function(item) { + if (this.imageData[item.item_id]) { + return this.imageData[item.item_id]['src']; + } + return null; + }, + getWidth: function(item) { + if (this.imageData[item.item_id]) { + return this.imageData[item.item_id]['width']; + } + return null; + }, + getHeight: function(item) { + if (this.imageData[item.item_id]) { + return this.imageData[item.item_id]['height']; + } + return null; + }, + getAlt: function(item) { + if (this.imageData[item.item_id]) { + return this.imageData[item.item_id]['alt']; + } + return null; + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js new file mode 100644 index 0000000000000000000000000000000000000000..fdce6d6d37db2bb914517a0dfae21b31e63cdf0f --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/shipping.js @@ -0,0 +1,39 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/shipping-service' + ], + function ($, Component, quote, shippingService) { + return Component.extend({ + defaults: { + template: 'Magento_Checkout/summary/shipping' + }, + quoteIsVirtual: quote.isVirtual(), + totals: quote.getTotals(), + getShippingMethodTitle: function() { + if (!this.isCalculated()) { + return ''; + } + return shippingService.getTitleByCode(quote.shippingMethod()) + }, + isCalculated: function() { + return this.totals() && this.isFullMode() && null != quote.shippingMethod(); + }, + getValue: function() { + if (!this.isCalculated()) { + return this.notCalculatedMessage; + } + var price = this.totals().shipping_amount; + return this.getFormattedPrice(price); + } + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js new file mode 100644 index 0000000000000000000000000000000000000000..b5929a2b60562611adeac62ade8f95608d31ff32 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/summary/subtotal.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote' + ], + function (Component, quote) { + "use strict"; + return Component.extend({ + defaults: { + template: 'Magento_Checkout/summary/subtotal' + }, + getPureValue: function() { + var totals = quote.getTotals()(); + if (totals) { + return totals.subtotal; + } + return quote.subtotal; + }, + getValue: function () { + return this.getFormattedPrice(this.getPureValue()); + } + + }); + } +); diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js b/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js deleted file mode 100644 index caca53e801396ac04e93ebbba53ebe2d4815bbfb..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/totals.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent' - ], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Checkout/review/totals', - displayArea: 'totals' - } - }); - } -); diff --git a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html index 263249c03824174fbc03630df6581d5e256b0909..f6a1e6e73a2bfcdb356a85b00747775a7d094ed4 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/authentication.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/authentication.html @@ -4,92 +4,81 @@ * See COPYING.txt for license details. */ --> -<li id="opc-billing" - data-bind="visible: isActive(), attr: {'class': stepClassAttributes() }" - role="presentation" - data-collapsible="true"> - <div class="step-title" - data-role="title" - data-bind="click: navigateToCurrentStep" - aria-controls="checkout-step-login" - role="tab"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Checkout Method')"></h2> - </div> - <div id="checkout-step-authentication" class="step-content" data-role="content" data-bind="fadeVisible: isVisible()" > +<div class="authentication-wrapper" data-block="authentication" data-bind="visible: isActive()"> + <button + type="button" + class="action action-auth-toggle" + data-trigger="authentication"> + <span data-bind="text: $t('Sign In')"></span> + </button> + <div class="block-authentication" + style="display: none" + data-bind="mageInit: { + 'Magento_Ui/js/modal/modal':{ + 'type': 'custom', + 'modalClass': 'authentication-dropdown', + 'trigger': '[data-trigger=authentication]', + 'wrapperClass': 'authentication-wrapper', + 'parentModalClass': '_has-modal-custom _has-auth-shown', + 'responsive': true, + 'responsiveClass': 'custom-slide', + 'overlayClass': 'dropdown-overlay modal-custom-overlay', + 'buttons': [] + }}"> <!-- ko foreach: getRegion('before') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> - <div class="login-wrapper"> - <!-- ko if: (isGuestCheckoutAllowed) --> - <div class="block block-guest"> - <div class="block-title"> - <strong id="block-guest-heading" role="heading" aria-level="2"> - <!--ko text: $t('Check Out as a Guest')--><!--/ko--> - </strong> - </div> - <div class="block-content" aria-labelledby="block-guest-heading"> + <div class="block block-customer-login" + data-bind="attr: {'data-label': $t('or')}"> + <div class="block-title"> + <strong id="block-customer-login-heading" + role="heading" + aria-level="2" + data-bind="text: $t('Sign In')"></strong> + </div> + <div class="block-content" aria-labelledby="block-customer-login-heading"> + <form data-role="login" + data-bind="submit:login" + method="post"> + <div class="fieldset" + data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> + <div class="field field-email required"> + <label class="label" for="login-email"><span data-bind="text: $t('Email Address')"></span></label> + <div class="control"> + <input type="email" + class="input-text" + id="login-email" + name="username" + data-validate="{required:true, 'validate-email':true}" /> + </div> + </div> + <div class="field field-password required"> + <label for="login-password" class="label"><span data-bind="text: $t('Password')"></span></label> + <div class="control"> + <input type="password" + class="input-text" + id="login-password" + name="password" + data-validate="{required:true, 'validate-password':true}"/> + </div> + </div> + <!-- ko foreach: getRegion('additional-login-form-fields') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> <div class="actions-toolbar"> + <input name="context" type="hidden" value="checkout" /> <div class="primary"> - <!-- ko if: (isGuestCheckoutAllowed)--> - <button data-bind="visible: isGuestCheckoutAllowed, click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action continue primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span data-bind="text: $t('Continue')"></span></button> - <!-- /ko --> - <!-- ko ifnot: isGuestCheckoutAllowed --> - <!-- ko if: isCustomerLoginRequired --> - <input type="checkbox" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register" checked="checked" style="display: none"/> - <button data-bind="click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":false, "registrationUrl":"registerUrl"}'><span data-bind="text: $t('Create an Account')"></span></button> - <!-- /ko --> - <!-- ko ifnot: isCustomerLoginRequired --> - <input type="checkbox" name="checkout_method" data-role="checkout-method-register" id="login:register" value="register" checked="checked" style="display: none"/> - <button data-bind="click: setCheckoutMethod" data-role="opc-continue" id="onepage-guest-register-button" type="button" class="action register primary" data-checkout='{"isGuestCheckoutAllowed":true}'><span data-bind="text: $t('Create an Account')"></span></button> - <!-- /ko --> - <!-- /ko --> + <button type="submit" class="action action-login secondary"><span data-bind="text: $t('Sign In')"></span></button> + </div> + <div class="secondary"> + <a class="action action-remind" data-bind="attr: { href: forgotPasswordUrl }"> + <span data-bind="text: $t('Forgot Password')"></span> + </a> </div> </div> - </div> - </div> - <!-- /ko --> - <div class="block block-customer-login"> - <div class="block-title"> - <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="text: $t('Login')"></strong> - </div> - <div class="block-content" aria-labelledby="block-customer-login-heading"> - <form class="form login" data-role="login" - data-bind="submit:login" - method="post" - data-mage-init='{"validation":{}}'> - <fieldset class="fieldset login" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> - <div class="field note" data-bind="text: $t('Already registered? Please sign in below:')"></div> - <div class="field email required"> - <label class="label" for="login-email"><span data-bind="text: $t('Email')"></span></label> - <div class="control"> - <input type="email" class="input-text" id="login-email" name="username" data-validate="{required:true, 'validate-email':true}" data-bind="value: username" /> - </div> - </div> - <div class="field password required"> - <label for="login-password" class="label"><span data-bind="text: $t('Password')"></span></label> - <div class="control"> - <input type="password" class="input-text" id="login-password" name="password" data-bind="value:password" data-validate="{required:true, 'validate-password':true}"/> - </div> - </div> - <!-- ko foreach: getRegion('additional-login-form-fields') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - <div class="actions-toolbar"> - <input name="context" type="hidden" value="checkout" /> - <div class="primary"> - <button type="submit" class="action login primary" data-action="checkout-method-login"><span data-bind="text: $t('Login')"></span></button> - </div> - <div class="secondary"> - <a class="action remind" data-bind="attr: { href: forgotPasswordUrl }"> - <span data-bind="text: $t('Forgot Your Password?')"></span> - </a> - </div> - </div> - </fieldset> - </form> - </div> + </form> </div> </div> </div> -</li> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html index baed4c7b53edbfb4715f8ddc7b3d9d8fe817074c..895f94e4cbd9404a667524f3e5cf29ba142371cd 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address.html @@ -4,54 +4,23 @@ * See COPYING.txt for license details. */ --> -<li id="opc-billing" data-bind="attr: {'class': stepClassAttributes() }" role="presentation"> - <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Billing Information')"></h2> - </div> - <div id="checkout-step-billing" class="step-content" data-role="content" data-bind="fadeVisible: isVisible()"> - <form class="form billing" id="co-billing-form" data-hasrequired="* Required Fields"> - <!-- ko if: (customerAddressCount)--> - <div class="field addresses"> - <label class="label" for="billing:address-select"><span data-bind="text: $t('Select a billing address from your address book or enter a new address.')"></span></label> - <div class="control"> - <select name="billing_address_id" id="billing:address-select" data-bind=" - options: billingAddresses(), - optionsText: billingAddressesOptionsText, - optionsValue: 'customerAddressId', - value: selectedBillingAddressId, - event: {change: onAddressChange(selectedBillingAddressId)}; - "></select> - </div> - </div> - <!--/ko--> - <fieldset id="billing-new-address-form" class="fieldset address" - data-bind="fadeVisible: isNewAddressSelected(), event {change: hideExtraFields()}"> - - <!-- ko foreach: getRegion('additional-fieldsets') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!--/ko--> - </fieldset> - <!-- ko if: quoteIsVirtual == 0 --> - <div class="field choice"> - <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_yes" value="1" checked="checked" class="radio" data-bind="checked: useForShipping" /> - <label class="label" for="billing:use_for_shipping_yes"><span><!-- ko text: $t('Ship to this address')--><!-- /ko --> </span></label> - </div> - <div class="field choice"> - <input type="radio" name="billing[use_for_shipping]" id="billing:use_for_shipping_no" value="0" class="radio" data-bind="checked: useForShipping" /> - <label class="label" for="billing:use_for_shipping_no"><span><!-- ko text: $t('Ship to different address')--><!-- /ko --></span></label> - </div> - <!-- ko foreach: getRegion('additional-field-choice') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - <!-- /ko --> +<div class="billing-address-same-as-shipping-block field choice" data-bind="visible: canUseShippingAddress()"> + <input type="checkbox" name="billing-address-same-as-shipping" data-bind="checked: isAddressSameAsShipping, click: useShippingAddress, attr: {id: 'billing-address-same-as-shipping-' + $parent.getCode()}"/> + <label data-bind="text: $t('My billing and shipping address are the same'), attr: {for: 'billing-address-same-as-shipping-' + $parent.getCode()}"></label> +</div> - <input type="hidden" name="billing[use_for_shipping]" value="1" /> - <div class="actions" id="billing-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="button" class="action continue primary" data-bind="click: submitBillingAddress"><span><!-- ko text: $t('Continue')--><!-- /ko --></span></button> - </div> - </div> - </form> +<!-- ko template: 'Magento_Checkout/billing-address/details' --><!-- /ko --> +<fieldset class="fieldset" data-bind="visible: !isAddressDetailsVisible()"> + <!-- ko template: 'Magento_Checkout/billing-address/list' --><!-- /ko --> + <!-- ko template: 'Magento_Checkout/billing-address/form' --><!-- /ko --> + <div class="actions-toolbar"> + <div class="primary"> + <button class="action action-update" type="button" data-bind="click: updateAddress"> + <span data-bind="text: $t('Update')"></span> + </button> + <button class="action action-cancel" type="button" data-bind="click: cancelAddressEdit"> + <span data-bind="text: $t('Cancel')"></span> + </button> + </div> </div> -</li> +</fieldset> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html new file mode 100644 index 0000000000000000000000000000000000000000..3d7d38a0f4aa80de63c750c37b0c489572300055 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/details.html @@ -0,0 +1,18 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="billing-address-details" data-bind="if: isAddressDetailsVisible() && currentBillingAddress()"> + <!-- ko text: currentBillingAddress().firstname --><!-- /ko --> <!-- ko text: currentBillingAddress().lastname --><!-- /ko --><br/> + <!-- ko text: currentBillingAddress().street --><!-- /ko --><br/> + <!-- ko text: currentBillingAddress().city --><!-- /ko -->, <!-- ko text: currentBillingAddress().region --><!-- /ko --> <!-- ko text: currentBillingAddress().postcode --><!-- /ko --><br/> + + <!-- ko text: currentBillingAddress().telephone --><!-- /ko --><br/> + <button type="button" + class="action action-edit-address" + data-bind="visible: !isAddressSameAsShipping(), click: editAddress"> + <span data-bind="text: $t('Edit')"></span> + </button> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html new file mode 100644 index 0000000000000000000000000000000000000000..4174aa194d635afdd5220f2076a8ac71e985a0a7 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/form.html @@ -0,0 +1,26 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="billing-address-form" data-bind="fadeVisible: isAddressFormVisible"> + <!-- ko foreach: getRegion('before-fields') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <form data-hasrequired="* Required Fields"> + <fieldset id="billing-new-address-form" class="fieldset address"> + <!-- ko foreach: getRegion('additional-fieldsets') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <!-- ko if: (isCustomerLoggedIn && customerHasAddresses) --> + <div class="choice field"> + <input type="checkbox" class="checkbox" id="billing-save-in-address-book" data-bind="checked: saveInAddressBook" /> + <label class="label" for="billing-save-in-address-book"> + <span data-bind="text: $t('Save in address book')"></span> + </label> + </div> + <!-- /ko --> + </fieldset> + </form> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html new file mode 100644 index 0000000000000000000000000000000000000000..f826ede448372134c8e7084dadbc973443492ed0 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/billing-address/list.html @@ -0,0 +1,17 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="field field-select-billing"> + <label class="label"><span data-bind="text: $t('My billing and shipping address are the same')"></span></label> + <div class="control" data-bind="if: (addressOptions.length > 1)"> + <select class="select" name="billing_address_id" data-bind=" + options: addressOptions, + optionsText: addressOptionsText, + value: selectedAddress, + event: {change: onAddressChange(selectedAddress())}; + "></select> + </div> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html new file mode 100644 index 0000000000000000000000000000000000000000..a2d2941754ff84e19bd81ff0acecce2056ee83d5 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/cart/authentication.html @@ -0,0 +1,89 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<div class="block-authentication" + data-bind="afterRender: setModalElement, blockLoader: isLoading" + style="display: none"> + <div class="block block-new-customer" + data-label="or"> + <div class="block-title"> + <strong id="block-new-customer-heading" role="heading" aria-level="2" data-bind="text: $t('Checkout out as a new customer')"></strong> + </div> + <div class="block-content" aria-labelledby="block-new-customer-heading"> + <p data-bind="text: $t('Creating an account has many benefits:')"></p> + <ul> + <li data-bind="text: $t('See order and shipping status')"></li> + <li data-bind="text: $t('Track order history')"></li> + <li data-bind="text: $t('Check out faster')"></li> + </ul> + <div class="actions-toolbar"> + <div class="primary"> + <a class="action action-register primary" data-bind="attr: {href: registerUrl}"> + <span data-bind="text: $t('Create Account')"></span> + </a> + </div> + </div> + </div> + </div> + <div class="block block-customer-login" + data-label="or"> + <div class="block-title"> + <strong id="block-customer-login-heading" role="heading" aria-level="2" data-bind="text:$t('Checkout out using your account')"></strong> + </div> + <!-- ko foreach: getRegion('messages') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <!-- ko foreach: getRegion('before') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <div class="block-content" aria-labelledby="block-customer-login-heading"> + <form class="form form-login" + method="post" + data-bind="submit:login" + id="login-form"> + <div class="fieldset login" data-hasrequired="* Required Fields"> + <div class="field email required"> + <label class="label" for="email"><span data-bind="text: $t('Email Address')"></span></label> + <div class="control"> + <input name="username" + id="email" + type="email" + class="input-text" + data-validate="{required:true, 'validate-email':true}"> + </div> + </div> + <div class="field password required"> + <label for="pass" class="label"><span data-bind="text: $t('Password')"></span></label> + <div class="control"> + <input name="password" + type="password" + class="input-text" + id="pass" + data-validate="{required:true, 'validate-password':true}"> + </div> + </div> + <!-- ko foreach: getRegion('additional-login-form-fields') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + <div class="actions-toolbar"> + <input name="context" type="hidden" value="checkout" /> + <div class="primary"> + <button type="submit" class="action action-login secondary" name="send" id="send2"> + <span data-bind="text: $t('Sign In')"></span> + </button> + </div> + <div class="secondary"> + <a class="action" data-bind="attr: {href: forgotPasswordUrl}"> + <span data-bind="text: $t('Forgot Your Password?')"></span> + </a> + </div> + </div> + </div> + </form> + </div> + </div> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html index 82475d90a25234b62a37c5e8c73fd01e5d0d61b8..a2fe08baaa52a4265d71b256b2d675514a380047 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/content.html @@ -98,3 +98,6 @@ <!-- /ko --> </div> </div> +<!-- ko foreach: getRegion('sign-in-popup') --> +<!-- ko template: getTemplate() --><!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html index 7a5432c380b5579dff032a888203426d61ae03ea..ee9b97ccd8ab3441c0f7942baf948799ea2aba9c 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/minicart/item/default.html @@ -33,9 +33,9 @@ <!-- ko if: options.length --> <div class="product options" data-mage-init='{"collapsible":{"openedState": "active", "saveState": false}}'> - <span data-role="title" class="more toggle"><!-- ko text: $t('See Details') --><!-- /ko --></span> + <span data-role="title" class="toggle"><!-- ko text: $t('See Details') --><!-- /ko --></span> - <div data-role="content" class="product options details content"> + <div data-role="content" class="content"> <strong class="subtitle"><!-- ko text: $t('Options Details') --><!-- /ko --></strong> <dl class="product options list"> <!-- ko foreach: { data: options, as: 'option' } --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/onepage.html b/app/code/Magento/Checkout/view/frontend/web/template/onepage.html index b05de111621164ef6ff48603fa307eb087c49812..51b80426e5dd4a8fc930916241602f4d28da9681 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/onepage.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/onepage.html @@ -4,19 +4,70 @@ * See COPYING.txt for license details. */ --> +<!-- ko foreach: getRegion('authentication') --> +<!-- ko template: getTemplate() --><!-- /ko --> +<!--/ko--> -<!-- ko foreach: getRegion('errors') --> +<!-- ko foreach: getRegion('progressBar') --> <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> + +<!-- Temp MAGETWO-36025 markup --> +<div class="opc-estimated-wrapper"> +<!-- Markup for MAGETWO-38644 --> + <div class="estimated-block"> + <span class="estimated-label" data-bind="text: $t('Estimated Total')"></span> + <span class="estimated-price">$100.00</span> + </div> + <div class="minicart-wrapper"> + <button type="button" class="action showcart" data-toggle="opc-summary"> + <span class="counter qty"> + <span class="counter-number">6</span> + </span> + </button> + </div> + <!-- Temp MAGETWO-36025 markup + <button + type="button" + class="action showcart" + data-toggle="opc-summary"> + <span data-bind="text: $t('View order summary')"></span> + </button>--> +</div> +<!-- /Temp MAGETWO-36025 markup --> + +<!-- ko foreach: getRegion('messages') --> + <!-- ko template: getTemplate() --><!-- /ko --> +<!--/ko--> <div class="opc-wrapper"> <ol class="opc" id="checkoutSteps"> <!-- ko foreach: getRegion('steps') --> - <!-- ko template: getTemplate() --><!-- /ko --> + <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> </ol> </div> -<div id="checkout-progress-wrapper" class="opc-block-progress-wrapper"> - <!-- ko foreach: getRegion('progress') --> - <!-- ko template: getTemplate() --><!-- /ko --> + +<div id="opc-sidebar" + data-bind="mageInit: { + 'Magento_Ui/js/modal/modal':{ + 'type': 'custom', + 'modalClass': 'opc-sidebar opc-summary-wrapper', + 'trigger': '[data-toggle=opc-summary]', + 'wrapperClass': 'checkout-container', + 'parentModalClass': '_has-modal-custom', + 'responsive': true, + 'responsiveClass': 'custom-slide', + 'overlayClass': 'modal-custom-overlay', + 'buttons': [] + }}"> + + <!-- ko foreach: getRegion('summary') --> + <!-- ko template: getTemplate() --><!-- /ko --> <!--/ko--> + + <div class="opc-block-shipping-information"> + <!-- ko foreach: getRegion('shipping-information') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> </div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html new file mode 100644 index 0000000000000000000000000000000000000000..386f34af57ecc0486acaca9b73b2f62cf4fe4f5e --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/payment-methods/list.html @@ -0,0 +1,12 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<div class="items payment-methods"> + <!-- ko foreach: { data: getRegion('payment-method-items'), as: 'element'} --> + <!-- ko template: element.getTemplate() --><!-- /ko --> + <!-- /ko --> +</div> +<!-- ko ifnot: getRegion('payment-method-items')().length > 0 --><div class="no-payments-block"><!-- ko text: $t('No Payment Methods')--><!-- /ko --></div><!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/payment.html b/app/code/Magento/Checkout/view/frontend/web/template/payment.html index af29231586341e0e2f2cb46ab944a52f6823b77b..d289eacc124401c39893b337149972af7245254e 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/payment.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/payment.html @@ -4,59 +4,33 @@ * See COPYING.txt for license details. */ --> -<li id="opc-payment" data-bind=", attr: {'class': stepClassAttributes() }" role="presentation"> - <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Payment Information')"></h2> - </div> +<li id="opc-payment" role="presentation" class="checkout-payment-method" data-bind="fadeVisible: isVisible"> + <div class="step-title" data-bind="text: $t(title)" data-role="title"></div> <div id="checkout-step-payment" class="step-content" data-role="content" role="tabpanel" - aria-hidden="false" - data-bind="fadeVisible: isVisible() && quoteHasShippingMethod()"> - <form id="co-payment-form" class="form payments" novalidate="novalidate" data-bind="submit: setPaymentMethod"> + aria-hidden="false"> + <!-- ko if: (quoteIsVirtual) --> + <!-- ko foreach: getRegion('customer-email') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <!--/ko--> + <form id="co-payment-form" class="form payments" novalidate="novalidate"> <input data-bind='attr: {value: getFormKey()}' type="hidden" name="form_key"/> <fieldset class="fieldset"> - <legend class="legend payments-title"> - <span><!-- ko text: $t('Payment Information')--><!-- /ko --></span>` - </legend> - <br> <!-- ko foreach: getRegion('beforeMethods') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> <div id="checkout-payment-method-load" class="opc-payment"> - <dl class="items methods-payment"> - <!-- ko foreach: getAvailableViews() --> - <dt data-bind='attr: {class: "item-title " + getCode()}'> - <input data-bind='attr: {id: "p_method_" + getCode(), value: getCode(), title: getTitle(), class: "radio" + $parent.getMethodControlAdditionalClass()}, checked: $parent.activeMethod, enable: isEnabled' type="radio" name="payment[method]"/> - <label data-bind='attr: {for: "p_method_" + getCode()}'><!-- ko template: titleTemplate --><!--/ko--></label> - </dt> - <!-- ko if: $data.formTemplate --> - <dd data-bind='attr: {class: "item-content " + getCode()}, visible: $parent.isMethodActive(getCode()), enable: isEnabled'><!-- ko template: formTemplate --><!--/ko--></dd> - <!-- /ko --> - <!-- /ko --> - <!-- ko ifnot: getAvailableViews().length > 0 --> - <dt class="item-title"><!-- ko text: $t('No Payment Methods')--><!-- /ko --></dt> - <!-- /ko --> - </dl> + <!-- ko foreach: getRegion('payment-methods-list') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> </div> <!-- ko foreach: getRegion('afterMethods') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </fieldset> - <div class="actions-toolbar" id="payment-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" - type="submit" - class="button action continue primary"> - <span><!-- ko text: $t('Continue')--><!-- /ko --></span> - </button> - </div> - <div class="secondary"> - <a class="action back" href="#" data-bind="click: backToShippingMethod"><span>Back</span></a> - </div> - </div> </form> </div> </li> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html new file mode 100644 index 0000000000000000000000000000000000000000..6c13c80261d707b2e8b8930ff8e5642035231b11 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/progress-bar.html @@ -0,0 +1,13 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<ul class="opc-progress-bar"> + <!-- ko foreach: { data: steps().sort(sortItems), as: 'item' } --> + <li class="opc-progress-bar-item" data-bind="css: item.isVisible() ? '_active' : ($parent.isProcessed(item) ? '_complete' : '')"> + <span data-bind="text: $t(item.title), click: $parent.navigateTo"></span> + </li> + <!-- /ko --> +</ul> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/progress.html b/app/code/Magento/Checkout/view/frontend/web/template/progress.html deleted file mode 100644 index 2831a845897496816dd57d0fefadecd98b44390d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/progress.html +++ /dev/null @@ -1,146 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - <div data-bind = "attr: {'class': getClassName()}"> - <div class="title"> - <strong data-bind="text: $t('Your Checkout Progress')"></strong> - </div> - <div class="content"> - <dl class="items"> - <!-- ko if: isShowStep('billingAddress') --> - <!-- ko if: isStepComplete('billingAddress') --> - <dt class="item-title complete"> - <span id="billing-address-label" data-bind="text: $t('Billing Address')"></span> - <a href="#billing" - data-goto-section="billing" - class="action billing" - aria-describedby="billing-address-label" data-bind="text: $t('Change'), click: goToStep('billingAddress')"> - </a> - </dt> - <dd class="item-content complete"> - <address data-bind="html:getBillingAddress()"></address> - </dd> - <!--/ko--> - <!-- ko ifnot: isStepComplete('billingAddress') --> - <dt class="item-title" data-bind="text: $t('Billing Address')"></dt> - <!--/ko--> - <!--/ko--> - - <!-- ko if: isShowStep('shippingAddress') --> - <!-- ko if: isStepComplete('shippingAddress') --> - <dt class="item-title complete"> - <span id="shipping-address-label" data-bind="text: $t('Shipping Address')"></span> - <a href="#payment" - data-goto-section="shipping" - class="action shipping address" - aria-describedby="shipping-address-label" data-bind="text:$t('Change'), click: goToStep('shippingAddress')"> - </a> - </dt> - <dd class="item-content complete"> - <address data-bind="html:getShippingAddress()"></address> - </dd> - <!--/ko--> - <!-- ko ifnot: isStepComplete('shippingAddress') --> - <dt class="item-title"> - <span data-bind="text:$t('Shipping Address')"></span> - </dt> - <!--/ko--> - <!--/ko--> - - <!-- ko if: isShowStep('shippingMethod') --> - <!-- ko if: isStepComplete('shippingMethod') --> - <dt class="item-title complete"> - <span id="shipping-method-label" data-bind="text:$t('Shipping Method')"></span> - <a href="#shipping_method" - data-goto-section="shipping_method" - class="action shipping method" - aria-describedby="shipping-method-label" data-bind="text:$t('Change'), click: goToStep('shippingMethod')"> - </a> - </dt> - <dd class="item-content complete"> - <!--<?php if ($block->getShippingMethod()): ?>--> - - <!-- ko text: getShippingMethodTitle() --><!--/ko--> - - <!--shipping method price rendering--> - - <!-- ko foreach: {data: getShippingRates(), as: 'item'} --> - <!-- ko foreach: $parent.getRegion('shipping') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!--/ko--> - <!--/ko--> - - <!-- ko ifnot : (getShippingRates().length > 0) --> - <!-- ko text: $t('Please choose a shipping method.') --><!--/ko--> - <!--/ko--> - </dd> - <!--/ko--> - <!-- ko ifnot: isStepComplete('shippingMethod') --> - <dt class="item-title"> - <span data-bind="text:$t('Shipping Method')"></span> - </dt> - <!--/ko--> - <!--/ko--> - - <!-- ko if: isShowStep('paymentMethod') --> - <!-- ko if: isStepComplete('paymentMethod') --> - <dt class="item-title complete"> - <span id="payment-method-label" data-bind="text:$t('Payment Method')"></span> - <a href="#payment" - data-goto-section="payment" - class="action payment method" - aria-describedby="payment-method-label" data-bind="text:$t('Change'), click: goToStep('paymentMethod')"> - </a> - </dt> - <dd class="item-content complete"> - <dl class="payment-method"> - <dt class="title"><!-- ko text: getPaymentMethodTitle() --><!--/ko--></dt> - <dd class="content"> - <!-- ko if: getPaymentMethodInfo().length > 0 --> - <table class="data table"> - <tbody data-bind="foreach: {data: getPaymentMethodInfo(), as: 'item'}"> - <!-- ko if: item.name && (item.value || item.html) --> - <tr> - <th scope="row" data-bind="html: $t(item.name)"></th> - <!-- ko if: item.value --> - <td data-bind="text: $t(item.value)"></td> - <!--/ko--> - <!-- ko if: !item.value && item.html --> - <td data-bind="html: $t(item.html)"></td> - <!--/ko--> - </tr> - <!--/ko--> - <!-- ko if: item.name && !item.value && !item.html --> - <tr> - <th colspan="2" scope="row"><!-- ko text: $t(item.name) --><!--/ko--></th> - </tr> - <!--/ko--> - <!-- ko if: !item.name && (item.value || item.html) --> - <tr> - <!-- ko if: item.value --> - <td colspan="2" data-bind="text: $t(item.value)"></td> - <!--/ko--> - <!-- ko if: !item.value && item.html --> - <td colspan="2" data-bind="html: $t(item.html)"></td> - <!--/ko--> - </tr> - <!--/ko--> - </tbody> - </table> - <!--/ko--> - </dd> - </dl> - </dd> - <!--/ko--> - <!-- ko ifnot: isStepComplete('paymentMethod') --> - <dt class="item-title"> - <span data-bind="text:$t('Payment Method')"></span> - </dt> - <!--/ko--> - <!--/ko--> - </dl> - </div> -</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review.html b/app/code/Magento/Checkout/view/frontend/web/template/review.html deleted file mode 100644 index 2258e50fd37a2a127040dbc0f3595e80c280012b..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review.html +++ /dev/null @@ -1,63 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<li id="opc-review" data-bind="attr: {'class': stepClassAttributes() }" role="presentation"> - <div class="step-title" data-role="title"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Order Review')"></h2> - </div> - <div id="checkout-step-review" - class="step-content" - data-role="content" - role="tabpanel" - aria-hidden="false" - data-bind="fadeVisible: isVisible() && quoteHasPaymentMethod()"> - <div class="order-review" id="checkout-review-load"> - <!-- ko foreach: getRegion('itemsBefore') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - <div id="checkout-review-table-wrapper" class="order-review-wrapper table-wrapper"> - <table class="data table table-order-review items" id="checkout-review-table"> - <caption class="table-caption" data-bind="text: $t('Order Review')"></caption> - <thead> - <tr> - <!-- ko foreach: getRegion('columns') --> - <!-- ko foreach: elems() --> - <th class="col" scope="col" data-bind=" text: $t(getColName()) , attr: { class: getHeaderClass() }" ></th> - <!-- /ko --> - <!-- /ko --> - </tr> - </thead> - <tbody> - <!-- ko foreach: {data: getItems(), as: 'item'} --> - <tr> - <!-- ko foreach: $parent.getRegion('columns') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </tr> - <!-- /ko --> - </tbody> - <tfoot> - <!-- ko foreach: getRegion('totals') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </tfoot> - </table> - </div> - <!-- ko foreach: getRegion('itemsAfter') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - <div id="checkout-review-submit" data-mage-init='{"paymentAuthentication":{}}' class="checkout-submit-order"> - <!-- ko foreach: getRegion('beforePlaceOrder') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - <!-- ko foreach: getRegion('actions') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </div> - </div> - </div> -</li> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html b/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html deleted file mode 100644 index 3123b421025ed575861d20ea2b6ebc5902df48dd..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/discount.html +++ /dev/null @@ -1,13 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: getPureValue() != 0 --> -<tr class="totals"> - <th data-bind="text: $t(fieldName) , attr: {'style':style, 'colspan': colspan}" class="mark" scope="row"> - </th> - <td data-bind="text: getValue(), attr: {'style': style, 'data-th': $t(name) }" class="amount"></td> -</tr> -<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html deleted file mode 100644 index c32d4991c36b0bcacca083ee241d5ca5149f1fa9..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/column.html +++ /dev/null @@ -1,9 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-bind="attr: { 'data-th': getColName(), class: getClass() }"> - <span data-bind="text: getValue($parents[1])"></span> -</td> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html deleted file mode 100644 index 54f6daf92fd94f087ab5c8aba02fe9b7d9585391..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/name.html +++ /dev/null @@ -1,25 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td class="col item" data-th="Product Name"><strong class="product name product-item-name" data-bind="text: $t(item.name)"></strong> - <!-- ko foreach: elems() --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - - <!-- ko if: (JSON.parse(item.options).length > 0)--> - <dl class="item-options"> - <!--ko foreach: JSON.parse(item.options)--> - <dt data-bind="text: $t(label)"></dt> - <!-- ko if: ($data.full_view)--> - <dd data-bind="html: full_view"></dd> - <!-- /ko --> - <!-- ko ifnot: ($data.full_view)--> - <dd data-bind="html: value"></dd> - <!-- /ko --> - <!-- /ko --> - </dl> - <!-- /ko --> -</td> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html deleted file mode 100644 index 25e9e79a35d89d2487140d9b3b5db518927be2e5..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/price.html +++ /dev/null @@ -1,11 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-bind="attr: { 'data-th': getColName(), class: getClass() }"> - <span class="cart-price"> - <span class="price" data-bind="text: getValue($parents[1])"></span> - </span> -</td> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html b/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html deleted file mode 100644 index cc5e4d63f7890acb036bb3adb5a681e689df3743..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/item/columns/qty.html +++ /dev/null @@ -1,7 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td class="col qty" data-th="Qty"><span class="qty" data-bind="text: item.qty"></span></td> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html b/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html deleted file mode 100644 index 3e2032f2c631a6bebe2e29d02589aa44cae5c0dc..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/iterator.html +++ /dev/null @@ -1,10 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<!-- ko foreach: elems() --> - <!-- ko template: getTemplate() --><!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html deleted file mode 100644 index acd04e1fca45cfca1ead82a33c4d7c34de5637f0..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<li id="opc-shipping" data-bind="fadeVisible: isActive(), attr: {'class': stepClassAttributes() }"> - <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Shipping Information')"></h2> - </div> - <div id="checkout-step-shipping" - class="step-content" - data-role="content" - data-bind="fadeVisible: isVisible() && quoteHasBillingAddress()"> - <form class="form shipping address" id="co-shipping-form" data-hasrequired="* Required Fields"> - <!-- ko foreach: getRegion('before-fields') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!--/ko--> - <!-- ko if: (customerAddressCount)--> - <div class="field addresses" data-bind="visible: visible"> - <label class="label" for="shipping:address-select"><span data-bind="text: $t('Select a shipping address from your address book or enter a new address.')"></span></label> - <div class="control"> - <select name="shipping_address_id" id="shipping:address-select" data-bind=" - options: addresses(), - optionsText: function(item) { return item.getAddressInline(); }, - optionsValue: 'customerAddressId', - value: selectedAddressId, - event: {change: onAddressChange} - "> - </select> - </div> - </div> - <!-- /ko --> - <fieldset id="shipping-new-address-form" class="fieldset address" - data-bind="fadeVisible: isNewAddressSelected(), visible: formVisible"> - <!-- ko foreach: getRegion('additional-fieldsets') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!--/ko--> - </fieldset> - - <div class="choice field" data-bind="visible: visible"> - <input type="checkbox" - name="shipping[same_as_billing]" - id="shipping:same_as_billing" - value="1" - checked="checked" - class="checkbox" - data-bind="checked: sameAsBilling, click: sameAsBillingClick"/> - <label class="label" for="shipping:same_as_billing"> - <span data-bind="text: $t('Use Billing Address')"></span> - </label> - </div> - <div class="actions-toolbar" id="shipping-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="button" class="action continue primary" data-bind="click: selectShippingAddress"><span data-bind="text: $t('Continue')"></span></button> - </div> - <div class="secondary"><a href="#" class="action back" data-bind="click: backToBilling"><span data-bind="text: $t('Back')"></span></a></div> - </div> - </form> - </div> -</li> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html new file mode 100644 index 0000000000000000000000000000000000000000..af87b5805b51e16afb0fec1d006c170325f1675c --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/address-renderer/default.html @@ -0,0 +1,21 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="shipping-address-item" data-bind="css: isSelected() ? 'selected-item' : 'not-selected-item'"> + <!-- ko text: address().firstname --><!-- /ko --> <!-- ko text: address().lastname --><!-- /ko --><br/> + <!-- ko text: address().street --><!-- /ko --><br/> + <!-- ko text: address().city --><!-- /ko -->, <!-- ko text: address().region --><!-- /ko --> <!-- ko text: address().postcode --><!-- /ko --><br/> + <!-- ko text: getCountryName(address().countryId) --><!-- /ko --><br/> + <!-- ko text: address().telephone --><!-- /ko --><br/> + <button type="button" + class="action edit-address-link" + data-bind="click: editAddress, visible: address().isEditable()"> + <span data-bind="text: $t('Edit')"></span> + </button> + <button type="button" data-bind="click: selectAddress" class="action action-select-shipping-item"> + <span data-bind="text: $t('Ship Here')"></span> + </button> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html new file mode 100644 index 0000000000000000000000000000000000000000..e450ee3fd9c3d04ae0c99208a64b244f3811c055 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/form.html @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<form class="form form-shipping-address" id="co-shipping-form" data-bind="attr: {'data-hasrequired': $t('* Required Fields')}"> + <!-- ko foreach: getRegion('before-fields') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <fieldset id="shipping-new-address-form" class="fieldset address"> + <!-- ko foreach: getRegion('additional-fieldsets') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <!-- ko if: (isCustomerLoggedIn) --> + <div class="field choice" data-bind="visible: !isFormInline"> + <input type="checkbox" class="checkbox" id="shipping-save-in-address-book" data-bind="checked: saveInAddressBook" /> + <label class="label" for="shipping-save-in-address-book"> + <span data-bind="text: $t('Save in address book')"></span> + </label> + </div> + <!-- /ko --> + </fieldset> +</form> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html new file mode 100644 index 0000000000000000000000000000000000000000..84b0b3679c69f0b1d3efbf0cdf633bd0ca0519e0 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-address/list.html @@ -0,0 +1,18 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- ko if: (visible)--> +<div class="field addresses"> + <div class="control"> + <div class="shipping-address-items"> + <!-- ko foreach: { data: elems, as: 'element' } --> + <!-- ko template: element.getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + </div> +</div> +<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html new file mode 100644 index 0000000000000000000000000000000000000000..6d262c39d9f0cd0bf99259e870819e6ddc63dafe --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information.html @@ -0,0 +1,35 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- ko if: (isVisible()) --> +<div class="shipping-information"> + <div class="ship-to"> + <div class="shipping-information-title"> + <span data-bind="text: $t('Ship To')"></span> + <button class="action action-edit" data-bind="click: back"> + <span data-bind="text: $t('edit')"></span> + </button> + </div> + <div class="shipping-information-content"> + <!-- ko foreach: getRegion('ship-to') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + </div> + <div class="ship-via"> + <div class="shipping-information-title"> + <span data-bind="text: $t('Ship Via')"></span> + <button class="action action-edit" data-bind="click: back"> + <span data-bind="text: $t('edit')"></span> + </button> + </div> + <div class="shipping-information-content"> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </div> + </div> +</div> +<!--/ko--> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html new file mode 100644 index 0000000000000000000000000000000000000000..32d832ca3092a32e8b8687325903880ce9274ee6 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/address-renderer/default.html @@ -0,0 +1,13 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: (visible()) --> + <!-- ko text: address().firstname --><!-- /ko --> <!-- ko text: address().lastname --><!-- /ko --><br/> + <!-- ko text: address().street --><!-- /ko --><br/> + <!-- ko text: address().city --><!-- /ko -->, <!-- ko text: address().region --><!-- /ko --> <!-- ko text: address().postcode --><!-- /ko --><br/> + <!-- ko text: getCountryName(address().countryId) --><!-- /ko --><br/> + <!-- ko text: address().telephone --><!-- /ko --><br/> +<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/review/totals.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html similarity index 53% rename from app/code/Magento/Checkout/view/frontend/web/template/review/totals.html rename to app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html index 3e2032f2c631a6bebe2e29d02589aa44cae5c0dc..c7a1eb499da7079fc81eaf82513fa59a3c3346de 100644 --- a/app/code/Magento/Checkout/view/frontend/web/template/review/totals.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping-information/list.html @@ -5,6 +5,6 @@ */ --> -<!-- ko foreach: elems() --> - <!-- ko template: getTemplate() --><!-- /ko --> +<!-- ko foreach: { data: elems, as: 'element' } --> +<!-- ko template: element.getTemplate() --><!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html deleted file mode 100644 index 523c1eb3b34f4c2c47d692b4401f945bbe422471..0000000000000000000000000000000000000000 --- a/app/code/Magento/Checkout/view/frontend/web/template/shipping-method.html +++ /dev/null @@ -1,94 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<li id="opc-shipping_method" data-bind="fadeVisible: isActive(), attr: {'class': stepClassAttributes() }" role="presentation"> - <div class="step-title" data-role="title" data-bind="click: navigateToCurrentStep"> - <span class="number" data-bind="text: stepNumber()"></span> - <h2 data-bind="text: $t('Shipping Method')"></h2> - </div> - <div id="checkout-step-shipping_method" - class="step-content" - data-role="content" - role="tabpanel" - aria-hidden="false" - data-bind="fadeVisible: isVisible() && quoteHasShippingAddress()"> - <!-- ko if: rates().length == 0 --> - <!-- ko text: $t('Sorry, no quotes are available for this order right now.')--><!-- /ko --> - <!-- /ko --> - <!-- ko if: rates().length --> - <form class="form methods-shipping" id="co-shipping-method-form" data-bind="submit: setShippingMethod" novalidate="novalidate"> - <div id="checkout-shipping-method-load"> - <dl class="items methods-shipping"> - <!--ko foreach: { data: rates(), as: 'method'}--> - <dt data-bind="text: $t(method.carrier_title), attr: {'class': 'item-title ' + method.carrier_code}"></dt> - <dd data-bind="attr: {'class': 'item-content ' + method.carrier_code}"> - <fieldset class="fieldset"> - <legend class="legend"><span data-bind="text: $t(method.carrier_title)"></span></legend> - <br> - <!--ko foreach: { data: items, as: 'item'}--> - <div class="field choice"> - <!-- ko if: item.error_message --> - <div class="message error"> - <div data-bind="text: $t(item.error_message)"></div> - </div> - <span class="no-display"> - <input name="shipping_method" type="radio" data-bind="attr: {'value' : item.method_code, 'id': 's_method_' + item.method_code}"/> - </span> - <!-- /ko --> - <!-- ko ifnot: item.error_message --> - <!-- ko if: $parent.items.length && $parents[1].rates().length == 1 --> - <span class="no-display"> - <input data-bind="attr: {'value' : item.carrier_code + '_' + item.method_code, 'id': 's_method_' + item.method_code}" - name="shipping_method" class="radio" type="radio" checked="checked"/> - </span> - <!-- /ko --> - <!--ko ifnot: ($parent.items.length && $parents[1].rates().length == 1)--> - <div class="control"> - <input name="shipping_method" type="radio" - data-bind="checked:$parents[1].verifySelectedMethodCode(item.carrier_code + '_' + item.method_code), attr: {'value': item.carrier_code + '_' + item.method_code, 'id': 's_method_' + item.carrier_code + '_' + item.method_code}" - class="radio"/> - </div> - <!--/ko--> - <label class="label" data-bind="attr: {'for': 's_method_' + item.carrier_code + '_' + item.method_code}"> - <span> - <!-- ko text: $t(item.method_title) --><!-- /ko --> - <!-- ko foreach: $parents[1].getRegion('price') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </span> - </label> - <!-- /ko --> - </div> - <!-- /ko --> - </fieldset> - </dd> - - <!-- /ko --> - </dl> - - </div> - - <div id="onepage-checkout-shipping-method-additional-load"> - <!-- ko foreach: getRegion('shippingAdditional') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </div> - <div class="actions-toolbar" id="shipping-method-buttons-container"> - <div class="primary"> - <button data-role="opc-continue" type="submit" class="button action continue primary"> - <span><!-- ko text: $t('Continue')--><!-- /ko --></span> - </button> - </div> - <div class="secondary"> - <a class="action back" href="#" data-bind="click: backToShippingAddress"> - <span><!-- ko text: $t('Back')--><!-- /ko --></span> - </a> - </div> - </div> - </form> - <!-- /ko --> - </div> -</li> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html new file mode 100644 index 0000000000000000000000000000000000000000..a62f3634547c53e3aa887261e137761c78394705 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/shipping.html @@ -0,0 +1,141 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<li id="opc-shipping" data-bind="fadeVisible: visible()"> + <div class="step-title" data-bind="text: $t('Shipping Address')" data-role="title"></div> + <div id="checkout-step-shipping" + class="step-content" + data-role="content"> + + <!-- ko if: (!quoteIsVirtual) --> + <!-- ko foreach: getRegion('customer-email') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + <!--/ko--> + + <!-- ko foreach: getRegion('address-list') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + + <!-- ko foreach: getRegion('address-list-additional-addresses') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + + <!-- Address form pop up --> + <!-- ko if: (!isFormInline) --> + <button type="button" + data-bind="click: showFormPopUp, visible: !isNewAddressAdded()" + class="action action-show-popup"> + <span data-bind="text: $t('New Address')"></span></button> + <div id="opc-new-shipping-address" data-bind="visible: isFormPopUpVisible()"> + <!-- ko template: 'Magento_Checkout/shipping-address/form' --><!-- /ko --> + </div> + <!-- /ko --> + + <!-- ko foreach: getRegion('before-form') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + + <!-- Inline address form --> + <!-- ko if: (isFormInline) --> + <!-- ko template: 'Magento_Checkout/shipping-address/form' --><!-- /ko --> + <!-- /ko --> + </div> +</li> + + +<!--Shipping method template--> +<li id="opc-shipping_method" data-bind="fadeVisible: visible(), blockLoader: isLoading" role="presentation"> + <div class="checkout-shipping-method"> + <div class="step-title" data-bind="text: $t('Shipping Method')" data-role="title"></div> + <!-- ko foreach: getRegion('before-shipping-method-form') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <div id="checkout-step-shipping_method" + class="step-content" + data-role="content" + role="tabpanel" + aria-hidden="false"> + <!-- ko if: rates().length --> + <form class="form methods-shipping" id="co-shipping-method-form" data-bind="submit: setShippingInformation" novalidate="novalidate"> + <div id="checkout-shipping-method-load"> + <table class="table-checkout-shipping-method"> + <thead> + <tr class="row"> + <th class="col"> </th> + <th class="col col-price" data-bind="text: $t('Price')"></th> + <th class="col col-method" data-bind="text: $t('Method Title')"></th> + <th class="col col-carrier" data-bind="text: $t('Carrier Title')"></th> + </tr> + </thead> + <tbody> + + <!--ko foreach: { data: rates(), as: 'method'}--> + <tr class="row" data-bind="click: $parent.selectShippingMethod"> + <td class="col"> + <!-- ko ifnot: method.error_message --> + <!-- ko if: $parent.rates().length == 1 --> + <input name="shipping_method" + class="radio" + type="radio" + data-bind="attr: {checked: $parent.rates().length == 1, 'value' : method.carrier_code + '_' + method.method_code, 'id': 's_method_' + method.method_code}" /> + <!-- /ko --> + <!--ko ifnot: ($parent.rates().length == 1)--> + <input name="shipping_method" type="radio" + data-bind=" + value: method.carrier_code + '_' + method.method_code, + checked: $parent.isSelected, + attr: {'id': 's_method_' + method.carrier_code + '_' + method.method_code}, + click: $parent.selectShippingMethod" + class="radio"/> + <!--/ko--> + <!-- /ko --> + </td> + <td class="col col-price"> + <!-- ko foreach: $parent.getRegion('price') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </td> + <td class="col col-method" data-bind="text: $t(method.method_title)"></td> + <td class="col col-carrier" data-bind="text: $t(method.carrier_title)"></td> + </tr> + + <!-- ko if: method.error_message --> + <tr class="row row-error"> + <td class="col col-error" colspan="4"> + <div class="message error"> + <div data-bind="text: $t(method.error_message)"></div> + </div> + <span class="no-display"> + <input name="shipping_method" type="radio" data-bind="attr: {'value' : method.method_code, 'id': 's_method_' + method.method_code}"/> + </span> + </td> + </tr> + <!-- /ko --> + + <!-- /ko --> + </tbody> + </table> + </div> + + <div id="onepage-checkout-shipping-method-additional-load"> + <!-- ko foreach: getRegion('shippingAdditional') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + <div class="actions-toolbar" id="shipping-method-buttons-container"> + <div class="primary"> + <button data-role="opc-continue" type="submit" class="button action continue primary"> + <span><!-- ko text: $t('Next')--><!-- /ko --></span> + </button> + </div> + </div> + </form> + <!-- /ko --> + <!-- ko ifnot: rates().length > 0 --><div class="no-quotes-block"><!-- ko text: $t('Sorry, no quotes are available for this order at this time')--><!-- /ko --></div><!-- /ko --> + </div> + </div> +</li> diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html b/app/code/Magento/Checkout/view/frontend/web/template/summary.html similarity index 55% rename from app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html rename to app/code/Magento/Checkout/view/frontend/web/template/summary.html index 7de21298dcc66e6e6d094e5be4d5b9163fb5830a..322ef76b8f053604505b4f054ceedde082c362e0 100644 --- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/review/agreements.html +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary.html @@ -4,8 +4,9 @@ * See COPYING.txt for license details. */ --> -<ol id="checkout-agreements" class="agreements checkout items"> +<div class="opc-block-summary" data-bind="blockLoader: isLoading"> + <span data-bind="text: $t('Order Summary')" class="title"></span> <!-- ko foreach: elems() --> <!-- ko template: getTemplate() --><!-- /ko --> - <!--/ko--> -</ol> + <!-- /ko --> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html new file mode 100644 index 0000000000000000000000000000000000000000..b262445e97dcaaf4972312823ea20b772a9cca7f --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/cart-items.html @@ -0,0 +1,54 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko ifnot: isItemsBlockExpanded() --> +<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}"> + <div class="title" data-role="title"> + <strong role="heading"><span data-bind="text: getItemsQty()"></span> + <!-- ko text: $t('Items in cart') --><!-- /ko --> + </strong> + </div> + <div class="content minicart-items" data-role="content"> + <div class="minicart-items-wrapper overflowed"> + <ol class="minicart-items"> + <!-- ko foreach: getItems --> + <li class="product-item"> + <div class="product"> + <!-- ko foreach: $parent.elems() --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + </li> + <!-- /ko --> + </ol> + </div> + </div> +</div> +<!-- /ko --> +<!-- ko if: isItemsBlockExpanded() --> +<div class="block items-in-cart" data-bind="mageInit: {'collapsible':{'openedState': 'active', 'active': true}}"> + <div class="title" data-role="title"> + <strong role="heading"><span data-bind="text: getItemsQty()"></span> + <!-- ko text: $t('Items in cart') --><!-- /ko --> + </strong> + </div> + <div class="content minicart-items" data-role="content"> + <div class="minicart-items-wrapper overflowed"> + <ol class="minicart-items"> + <!-- ko foreach: getItems --> + <li class="product-item"> + <div class="product"> + <!-- ko foreach: $parent.elems() --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + </li> + <!-- /ko --> + </ol> + </div> + </div> +</div> +<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html new file mode 100644 index 0000000000000000000000000000000000000000..78954c0a4feff1a869912afebbb6051c57f34922 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/grand-total.html @@ -0,0 +1,17 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: isDisplayed() --> +<tr> + <td colspan="2" data-bind="text: $t(title)"></td> + <td class="col grandtotal"> + <span data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span> + <!-- ko foreach: elems() --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </td> +</tr> +<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html new file mode 100644 index 0000000000000000000000000000000000000000..dab4d8393326c266bbdff3cf1f54883b6b218c73 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details.html @@ -0,0 +1,45 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<!-- ko foreach: getRegion('before_details') --> + <!-- ko template: getTemplate() --><!-- /ko --> +<!-- /ko --> +<div class="product-item-details"> + + <div class="product-item-inner"> + <div class="product-item-name-block"> + <strong class="product-item-name" data-bind="text: $t($parent.name)"></strong> + <div class="details-qty"> + <span class="label"><!-- ko text: $t('Qty') --><!-- /ko --></span> + <span class="value" data-bind="text: $parent.qty"></span> + </div> + </div> + <!-- ko foreach: getRegion('after_details') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </div> + + <!-- ko if: (JSON.parse($parent.options).length > 0)--> + <div class="product options" data-bind="mageInit: {'collapsible':{'openedState': 'active'}}"> + <span data-role="title" class="toggle"><!-- ko text: $t('View Details') --><!-- /ko --></span> + <div data-role="content" class="content"> + <strong class="subtitle"><!-- ko text: $t('Options Details') --><!-- /ko --></strong> + <dl class="item-options"> + <!--ko foreach: JSON.parse($parent.options)--> + <dt class="label" data-bind="text: $t(label)"></dt> + <!-- ko if: ($data.full_view)--> + <dd class="values" data-bind="html: full_view"></dd> + <!-- /ko --> + <!-- ko ifnot: ($data.full_view)--> + <dd class="values" data-bind="html: value"></dd> + <!-- /ko --> + <!-- /ko --> + </dl> + </div> + </div> + <!-- /ko --> +</div> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/item.js b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html similarity index 54% rename from app/code/Magento/Checkout/view/frontend/web/js/model/item.js rename to app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html index d1927d19e9288d2b244ff8f5761bc12556b605a2..f90013fcebbca354cb4ee7c7d3a0c756145ace6a 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/model/item.js +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/subtotal.html @@ -1,9 +1,7 @@ +<!-- /** * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define([], function() { - -}); +--> +<span class="subtotal" data-bind="text: getValue($parents[1])"></span> \ No newline at end of file diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html new file mode 100644 index 0000000000000000000000000000000000000000..1b8cb1fada8c6d21332167f59d4a5cf68d342ca0 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/item/details/thumbnail.html @@ -0,0 +1,13 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<span class="product-image-container" + data-bind="attr: {'style': 'height: ' + getHeight($parents[1]) + 'px; width: ' + getWidth($parents[1]) + 'px;' }"> + <span class="product-image-wrapper"> + <img + data-bind="attr: {'src': getSrc($parents[1]), 'width': getWidth($parents[1]), 'height': getHeight($parents[1]), 'alt': getAlt($parents[1]) }"/> + </span> +</span> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html new file mode 100644 index 0000000000000000000000000000000000000000..34707698e61b6d43a73c743b908c3b4c8c246fbc --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/shipping.html @@ -0,0 +1,24 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: quoteIsVirtual == 0 --> + <tr class="totals shipping excl"> + <th class="mark" scope="row"> + <span class="label" data-bind="text: $t(title)"></span> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </th> + <td class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + </td> + </tr> +<!-- /ko --> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html new file mode 100644 index 0000000000000000000000000000000000000000..f241430924ac88f2a773699f978c33228d9beb9c --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/subtotal.html @@ -0,0 +1,16 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<tr class="totals"> + <th class="mark" scope="row" data-bind="text: $t(title)"></th> + <td class="amount"> + <span class="price" data-bind ="text: getValue(), attr:{'data-label': $t(title)}"></span> + <!-- ko foreach: elems() --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </td> +</tr> diff --git a/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html new file mode 100644 index 0000000000000000000000000000000000000000..074024dee00d9d0bdd55fef06c933f6df9d94330 --- /dev/null +++ b/app/code/Magento/Checkout/view/frontend/web/template/summary/totals.html @@ -0,0 +1,14 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<table class="data table table-totals"> + <caption class="table-caption" data-bind="text: $t('Order Summary')"></caption> + <tbody> + <!-- ko foreach: elems() --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + </tbody> +</table> diff --git a/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php b/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php index b13012ae47336a32c14f4f96ca9c22cdaa1a5914..ad8bdfc822cd6cf47021150f599f6e43320d709d 100644 --- a/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php +++ b/app/code/Magento/CheckoutAgreements/Block/Checkout/LayoutProcessor.php @@ -34,34 +34,22 @@ class LayoutProcessor implements \Magento\Checkout\Block\Checkout\LayoutProcesso */ public function process($jsLayout) { - $form = []; + $agreementConfiguration = []; $agreementsList = $this->checkoutAgreementsRepository->getList(); + foreach ($agreementsList as $agreement) { - $name = $agreement->getAgreementId(); - $form[$name] = [ - 'component' => 'Magento_Ui/js/form/element/abstract', - 'config' => [ - 'customScope' => 'checkoutAgreements', - 'customEntry' => 'checkoutAgreements.' . $name, - 'template' => 'Magento_CheckoutAgreements/form/element/agreement' - ], - 'agreementConfiguration' => [ - 'content' => $agreement->getIsHtml() - ? $agreement->getContent() - : nl2br($this->escaper->escapeHtml($agreement->getContent())), - 'height' => $agreement->getContentHeight(), - 'checkboxText' => $agreement->getCheckboxText() - ], - 'dataScope' => $name, - 'provider' => 'checkoutProvider', - 'validation' => ['checked' => true], - 'customEntry' => null, - 'visible' => true + $agreementConfiguration[] = [ + 'content' => $agreement->getIsHtml() + ? $agreement->getContent() + : nl2br($this->escaper->escapeHtml($agreement->getContent())), + 'height' => $agreement->getContentHeight(), + 'checkboxText' => $agreement->getCheckboxText() ]; } - $result['components']['checkout']['children']['steps']['children']['review']['children'] - ['beforePlaceOrder']['children']['checkoutAgreements']['children'] = $form; + $jsLayout['components']['checkout']['children']['steps']['children']['billing-step']['children']['payment'] + ['children']['payments-list']['children']['before-place-order']['children']['checkout-agreements-modal'] + ['config']['agreementConfiguration'] = $agreementConfiguration; - return array_merge_recursive($jsLayout, $result); + return $jsLayout; } } diff --git a/app/code/Magento/CheckoutAgreements/composer.json b/app/code/Magento/CheckoutAgreements/composer.json index 13f10a6560e989f70548019e6eb5b043740c431b..1c9182b3add4bac268176432b51c4704d97b8cd9 100644 --- a/app/code/Magento/CheckoutAgreements/composer.json +++ b/app/code/Magento/CheckoutAgreements/composer.json @@ -6,7 +6,6 @@ "magento/module-checkout": "0.74.0-beta15", "magento/module-store": "0.74.0-beta15", "magento/module-backend": "0.74.0-beta15", - "magento/module-ui": "0.74.0-beta15", "magento/framework": "0.74.0-beta15", "magento/magento-composer-installer": "*" }, diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml index b80bfc39aef43beb4d75914c654e68171d66a546..5f883201ee2dc7a65fb206b071dea0216d7c8b3b 100644 --- a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_index.xml @@ -15,16 +15,25 @@ <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="review" xsi:type="array"> + <item name="billing-step" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="beforePlaceOrder" xsi:type="array"> + <item name="payment" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="checkoutAgreements" xsi:type="array"> - <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkoutAgreements</item> - <item name="dataScope" xsi:type="string">checkoutAgreements</item> - <item name="displayArea" xsi:type="string">checkoutAgreements</item> - <item name="provider" xsi:type="string">checkoutProvider</item> + <item name="payments-list" xsi:type="array"> <item name="children" xsi:type="array"> + <item name="before-place-order" xsi:type="array"> + <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements-link</item> + <item name="displayArea" xsi:type="string">before-place-order</item> + <item name="dataScope" xsi:type="string">checkoutAgreements</item> + <item name="provider" xsi:type="string">checkoutProvider</item> + <item name="children" xsi:type="array"> + <item name="checkout-agreements-modal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkout-agreements-modal</item> + <item name="dataScope" xsi:type="string">checkoutAgreements</item> + <item name="provider" xsi:type="string">checkoutProvider</item> + </item> + </item> + </item> </item> </item> </item> diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml new file mode 100644 index 0000000000000000000000000000000000000000..89eb6278a7646836ff461eb6955899faae9b5fb9 --- /dev/null +++ b/app/code/Magento/CheckoutAgreements/view/frontend/layout/checkout_onepage_original.xml @@ -0,0 +1,44 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- TODO remove this file as soon as enhanced checkout is implemented --> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="review" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="beforePlaceOrder" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="checkoutAgreements" xsi:type="array"> + <item name="component" xsi:type="string">Magento_CheckoutAgreements/js/view/checkoutAgreements</item> + <item name="dataScope" xsi:type="string">checkoutAgreements</item> + <item name="displayArea" xsi:type="string">checkoutAgreements</item> + <item name="provider" xsi:type="string">checkoutProvider</item> + <item name="children" xsi:type="array"> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js new file mode 100644 index 0000000000000000000000000000000000000000..071602c254c40f864b7654cfb56293d1c250d2dc --- /dev/null +++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-link.js @@ -0,0 +1,24 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'uiComponent' + ], function (ko, Component) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_CheckoutAgreements/checkout/payment/checkout-agreements-link' + }, + isVisible: window.checkoutConfig.checkoutAgreementsEnabled, + /** + * Opens modal window with Terms&Conditions + */ + showAgreements: function () { + this.elems()[0].showAgreements(); + } + }); + } +); diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js new file mode 100644 index 0000000000000000000000000000000000000000..e7762f7ea5b9f1c2448110c50be7ec42d28733a9 --- /dev/null +++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkout-agreements-modal.js @@ -0,0 +1,56 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'uiComponent', + 'Magento_Ui/js/modal/modal' + ], function (ko, Component, modal) { + 'use strict'; + + /** + * Provides an empty div to force load template into. + * @todo MAGETWO-39170 Refactor this as soon as modal component is updated to support ko view models. + * @returns {HTMLElement} + */ + function createTemporayContainer() { + var temporaryDiv = document.createElement('div'); + temporaryDiv.style.display = 'none'; + document.body.appendChild(temporaryDiv); + + return temporaryDiv; + } + + return Component.extend({ + defaults: { + template: 'Magento_CheckoutAgreements/checkout/modal/agreements-modal' + }, + /** + * Initialize view and render it's template to temporary div. This will be refactored as soon as + * modal component is integrated with uiComponent. + * @returns {*} + */ + initialize: function () { + var temporaryContainer = createTemporayContainer(); + + this._super(); + ko.renderTemplate(this.template, this, {}, temporaryContainer); + temporaryContainer.parentNode.removeChild(temporaryContainer); + + return this; + }, + modal: modal({ + responsive: true, + innerScroll: true, + buttons: [] + }), + /** + * Show Terms&Conditions pop-up + */ + showAgreements: function () { + ko.renderTemplate(this.template, this, {}, this.modal.openModal(), 'replaceNode'); + } + }); + } +); diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js b/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js deleted file mode 100644 index 094136c756467124a11a6c509263af55c8bd69c1..0000000000000000000000000000000000000000 --- a/app/code/Magento/CheckoutAgreements/view/frontend/web/js/view/checkoutAgreements.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define( - ['Magento_Ui/js/form/form', 'Magento_Checkout/js/view/review', 'underscore'], - function (Component, review, _) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_CheckoutAgreements/checkout/review/agreements' - }, - initialize: function() { - this._super(); - if (window.checkoutConfig.checkoutAgreementsEnabled) { - review.prototype.beforePlaceOrder.checkoutAgreements = this; - } - }, - validate: function() { - this.source.set('params.invalid', false); - this.source.trigger('checkoutAgreements.data.validate'); - return this.source.get('params.invalid'); - }, - getSubmitParams: function() { - return { - agreements: _.keys(this.source.get('checkoutAgreements')) - }; - } - }); - } -); diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html new file mode 100644 index 0000000000000000000000000000000000000000..0129cab3aebd3c2d9aaba585274e4bfc70413ccb --- /dev/null +++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/modal/agreements-modal.html @@ -0,0 +1,15 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<ol class="checkout-agreements-items"> + <!-- ko foreach: agreementConfiguration --> + <li class="checkout-agreements-item"> + <div class="checkout-agreements-item-title" data-bind="html: checkboxText"></div> + <div class="checkout-agreements-item-content" + data-bind="style: { height: height || null }, html: content"></div> + </li> + <!-- /ko --> +</ol> diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html new file mode 100644 index 0000000000000000000000000000000000000000..315bc47af7dac0607ace233f00b8dce7273a96db --- /dev/null +++ b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/checkout/payment/checkout-agreements-link.html @@ -0,0 +1,14 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<div class="checkout-agreements" data-bind="visible: isVisible"> + <!-- ko text: $t('You automatically accept') --><!-- /ko --> + <button type="button" class="action action-show" data-bind="click: showAgreements"> + <span><!-- ko text: $t('terms and conditions') --><!-- /ko --></span> + </button> + <!-- ko text: $t('before placing the order') --><!-- /ko --> +</div> diff --git a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html b/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html deleted file mode 100644 index 0f029cfe2f3b4113a83c4b7256f867ce8e5ca592..0000000000000000000000000000000000000000 --- a/app/code/Magento/CheckoutAgreements/view/frontend/web/template/form/element/agreement.html +++ /dev/null @@ -1,18 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<li class="item"> - <div class="agreement content" data-bind="style: { height: agreementConfiguration.height || null }, html: agreementConfiguration.content"></div> - <form class="field choice agree required" id="checkout-agreements"> - <input type="checkbox" class="control-checkbox" data-bind="checked: value, attr: { id: uid, disabled: disabled, name: inputName }, hasFocus: focused"> - <label class="field-label" data-bind="checked: value, attr: { for: uid }"> - <span data-bind="html: agreementConfiguration.checkboxText"></span> - </label> - </form> - <!-- ko if: error() --> - <div class="mage-error" data-bind="attr: { for: uid }, text: error" generated="true"></div> - <!-- /ko --> -</li> diff --git a/app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js b/app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js similarity index 66% rename from app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js rename to app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js index f25cd3f00ac28fb40a4a560426d5644e2f7855ba..6c658bace739f0f4343fe2b74836a7cab053febf 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/action/check-email-availability.js +++ b/app/code/Magento/Customer/view/frontend/web/js/action/check-email-availability.js @@ -2,22 +2,21 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*jshint browser:true*/ -/*global define*/ define( [ 'mage/storage', - '../model/url-builder', - 'Magento_Customer/js/model/customer' + 'Magento_Checkout/js/model/url-builder' ], - function(storage, urlBuilder, customer) { - "use strict"; - return function(deferred) { - storage.post( + function (storage, urlBuilder) { + 'use strict'; + + return function (deferred, email) { + return storage.post( urlBuilder.createUrl('/customers/isEmailAvailable', {}), JSON.stringify({ - customerEmail: customer.customerData.email - }) + customerEmail: email + }), + false ).done( function (isEmailAvailable) { if (isEmailAvailable) { diff --git a/app/code/Magento/Customer/view/frontend/web/js/action/login.js b/app/code/Magento/Customer/view/frontend/web/js/action/login.js index 11dcaeec5cb4b0943bd8b5d043bb59238a4df1c5..31d928825415b94304ca8b6f57fb912f6760a8cd 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/action/login.js +++ b/app/code/Magento/Customer/view/frontend/web/js/action/login.js @@ -7,30 +7,45 @@ define( [ 'jquery', 'mage/storage', - 'Magento_Ui/js/model/errorlist', - 'Magento_Customer/js/model/customer' + 'Magento_Ui/js/model/messageList', + 'Magento_Customer/js/customer-data' ], - function($, storage, errorlist, customer) { - "use strict"; - return function(loginData, redirectUrl) { - return storage.post( - 'customer/ajax/login', - JSON.stringify(loginData) - ).done(function (response) { - if (response.errors) { - customer.increaseFailedLoginAttempt(); - errorlist.add(response); - } else { - if (redirectUrl) { - window.location.href = redirectUrl; + function($, storage, messageList, customerData) { + 'use strict'; + var callbacks = [], + action = function(loginData, redirectUrl) { + return storage.post( + 'customer/ajax/login', + JSON.stringify(loginData) + ).done(function (response) { + if (response.errors) { + messageList.addErrorMessage(response); + callbacks.forEach(function(callback) { + callback(loginData); + }); } else { - location.reload(); + callbacks.forEach(function(callback) { + callback(loginData); + }); + customerData.invalidate(['customer']); + if (redirectUrl) { + window.location.href = redirectUrl; + } else { + location.reload(); + } } - } - }).fail(function () { - customer.increaseFailedLoginAttempt(); - errorlist.add({'message': 'Could not authenticate. Please try again later'}); - }); + }).fail(function () { + messageList.addErrorMessage({'message': 'Could not authenticate. Please try again later'}); + callbacks.forEach(function(callback) { + callback(loginData); + }); + }); + }; + + action.registerLoginCallback = function(callback) { + callbacks.push(callback); }; + + return action; } ); diff --git a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js index 2f5c1181ea10d44c4a4e99294dac2ee068822387..bfb277c067d57bb85961c7824bdaf3919f1340b1 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/customer-data.js +++ b/app/code/Magento/Customer/view/frontend/web/js/customer-data.js @@ -9,7 +9,6 @@ define([ 'Magento_Customer/js/section-config', 'jquery/jquery-storageapi', 'jquery/jquery.cookie' - ], function ($, _, ko, sectionConfig) { 'use strict'; diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js b/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js new file mode 100644 index 0000000000000000000000000000000000000000..a67a3e0b693973ad41af5205b6887abef0ffa797 --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/model/address-list.js @@ -0,0 +1,15 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'ko', + './customer-addresses' + ], + function(ko, defaultProvider) { + "use strict"; + return ko.observableArray(defaultProvider.getAddressItems()); + } +); \ No newline at end of file diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js new file mode 100644 index 0000000000000000000000000000000000000000..c14cffb2c59e3e8edb233a90f34e25a374688d65 --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer-addresses.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'ko', + './customer/address' + ], + function($, ko, address) { + "use strict"; + var isLoggedIn = ko.observable(window.isCustomerLoggedIn); + return { + getAddressItems: function() { + var items = []; + if (isLoggedIn) { + var customerData = window.customerData; + if (Object.keys(customerData).length) { + $.each(customerData.addresses, function (key, item) { + items.push(new address(item)); + }); + } + } + return items; + } + } + } +); \ No newline at end of file diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer.js index 28a43254db2efdcf3e2e6e5d52b1eeca3841f9d4..25654444d6cc5ee783b134afdf41c44eaac28bdf 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer.js @@ -9,46 +9,31 @@ define( 'ko', 'underscore', 'mage/storage', - 'Magento_Checkout/js/model/addresslist', - './customer/address' + './address-list' ], - function($, ko, _, storage, addressList, address) { + function($, ko, _, storage, addressList) { "use strict"; var isLoggedIn = ko.observable(window.isCustomerLoggedIn), - failedLoginAttempts = ko.observable(0), customerData = {}; if (isLoggedIn()) { customerData = window.customerData; - if (Object.keys(customerData).length) { - $.each(customerData.addresses, function (key, item) { - addressList.add(new address(item)); - }); - } } else { customerData = {}; } + return { customerData: customerData, customerDetails: {}, - isLoggedIn: function() { - return isLoggedIn; - }, + isLoggedIn: isLoggedIn, setIsLoggedIn: function (flag) { isLoggedIn(flag); }, - getFailedLoginAttempts: function() { - return failedLoginAttempts; - }, - increaseFailedLoginAttempt: function() { - var oldAttempts = failedLoginAttempts(); - failedLoginAttempts(++oldAttempts); - }, getBillingAddressList: function () { - return addressList.getAddresses(); + return addressList(); }, getShippingAddressList: function () { - return addressList.getAddresses(); + return addressList(); }, setDetails: function (fieldName, value) { if (fieldName) { diff --git a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js index 104655e0f2224625ceb03f07e78453fa9cfb9e14..c3f656411450d8f6a9603d7688a93d5e8f788fd7 100644 --- a/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js +++ b/app/code/Magento/Customer/view/frontend/web/js/model/customer/address.js @@ -5,6 +5,10 @@ /*jshint browser:true jquery:true*/ /*global alert*/ define([], function() { + /** + * @param addressData + * Returns new address object + */ return function (addressData) { return { customerAddressId: addressData.id, @@ -26,9 +30,28 @@ define([], function() { prefix: addressData.prefix, suffix: addressData.suffix, vatId: addressData.vat_id, - sameAsBilling: null, + sameAsBilling: addressData.same_as_billing, + saveInAddressBook: addressData.save_in_address_book, + isDefaultShipping: function() { + return addressData.default_shipping; + }, + isDefaultBilling: function() { + return addressData.default_billing; + }, getAddressInline: function() { return addressData.inline; + }, + getType: function() { + return 'customer-address' + }, + getKey: function() { + return this.getType() + this.customerAddressId; + }, + isEditable: function() { + return false; + }, + canUseForBilling: function() { + return true; } } } diff --git a/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js b/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js new file mode 100644 index 0000000000000000000000000000000000000000..ae864756661c84ffe7ab65d320d6b80d32822bca --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/js/view/customer-email.js @@ -0,0 +1,116 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'jquery', + 'uiComponent', + 'ko', + 'Magento_Customer/js/model/customer', + 'Magento_Customer/js/action/check-email-availability', + 'Magento_Customer/js/action/login', + 'Magento_Checkout/js/model/quote', + 'mage/validation' + ], + function ($, Component, ko, customer, checkEmailAvailability, loginAction, quote) { + "use strict"; + return Component.extend({ + defaults: { + template: 'Magento_Customer/customer-email', + email: '', + isLoading: false, + isPasswordVisible: false + }, + checkDelay: 2000, + checkRequest: null, + isEmailCheckComplete: null, + isCustomerLoggedIn: customer.isLoggedIn, + forgotPasswordUrl: window.checkoutConfig.forgotPasswordUrl, + emailCheckTimeout: 0, + + initialize: function() { + this._super(); + var self = this; + this.email.subscribe(function() { + self.emailHasChanged(); + }); + }, + + /** Initialize observable properties */ + initObservable: function () { + this._super() + .observe(['email', 'isLoading', 'isPasswordVisible']); + return this; + }, + + emailHasChanged: function () { + var self = this; + clearTimeout(this.emailCheckTimeout); + this.emailCheckTimeout = setTimeout(function () { + if (self.validateEmail()) { + self.checkEmailAvailability(); + quote.guestEmail = self.email(); + } else { + self.isPasswordVisible(false); + } + }, self.checkDelay); + + }, + + checkEmailAvailability: function() { + var self = this; + this.validateRequest(); + this.isEmailCheckComplete = $.Deferred(); + this.isLoading(true); + this.checkRequest = checkEmailAvailability(this.isEmailCheckComplete, this.email()); + + $.when(this.isEmailCheckComplete).done(function() { + self.isPasswordVisible(false); + }).fail( function() { + self.isPasswordVisible(true); + }).always(function () { + self.isLoading(false); + }); + }, + + validateRequest: function() { + /* + * If request has been sent -> abort it. + * ReadyStates for request aborting: + * 1 - The request has been set up + * 2 - The request has been sent + * 3 - The request is in process + */ + if (this.checkRequest != null && $.inArray(this.checkRequest.readyState, [1, 2, 3])) { + this.checkRequest.abort(); + this.checkRequest = null; + } + }, + + validateEmail: function() { + var loginFormSelector = 'form[data-role=email-with-possible-login]'; + $(loginFormSelector).validation(); + var validationResult = $(loginFormSelector + ' input[name=username]').valid(); + return Boolean(validationResult); + }, + + login: function(loginForm) { + var loginData = {}, + formDataArray = $(loginForm).serializeArray(); + + formDataArray.forEach(function (entry) { + loginData[entry.name] = entry.value; + }); + if (this.isPasswordVisible() + && $(loginForm).validation() + && $(loginForm).validation('isValid') + ) { + loginAction(loginData); + } + } + }); + } +); diff --git a/app/code/Magento/Customer/view/frontend/web/template/customer-email.html b/app/code/Magento/Customer/view/frontend/web/template/customer-email.html new file mode 100644 index 0000000000000000000000000000000000000000..898a3300ed78e3e2262baaf6fbf040fef297620c --- /dev/null +++ b/app/code/Magento/Customer/view/frontend/web/template/customer-email.html @@ -0,0 +1,67 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko ifnot: isCustomerLoggedIn() --> + +<!-- ko foreach: getRegion('before-login-form') --> +<!-- ko template: getTemplate() --><!-- /ko --> +<!-- /ko --> +<form class="form form-login" data-role="email-with-possible-login" + data-bind="submit:login" + method="post"> + <fieldset id="customer-email-fieldset" class="fieldset" data-bind="blockLoader: isLoading"> + <div class="field required"> + <label class="label" for="customer-email"> + <span data-bind="text: $t('Email Address')"></span> + </label> + <div class="control _with-tooltip"> + <input class="input-text" + type="email" + data-bind="textInput: email" + name="username" + data-validate="{required:true, 'validate-email':true}" + id="customer-email" /> + <!-- ko template: 'ui/form/element/helper/tooltip' --><!-- /ko --> + <span class="note"><!-- ko text: $t("(You can create an account after checkout)")--><!-- /ko --></span> + </div> + </div> + + <!--Hidden fields --> + <fieldset class="fieldset hidden-fields" data-bind="fadeVisible: isPasswordVisible"> + <div class="field"> + <label class="label" for="customer-password"> + <span data-bind="text: $t('Password')"></span> + </label> + <div class="control"> + <input class="input-text" + placeholder="optional" + type="password" + name="password" + id="customer-password" + data-validate="{required:true, 'validate-password':true}" /> + <span class="note" data-bind="text: $t('You already have an account with us. Sign in or continue as guest.')"></span> + </div> + + </div> + <!-- ko foreach: getRegion('additional-login-form-fields') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!-- /ko --> + <div class="actions-toolbar"> + <input name="context" type="hidden" value="checkout" /> + <div class="primary"> + <button type="submit" class="action login primary" data-action="checkout-method-login"><span data-bind="text: $t('Login')"></span></button> + </div> + <div class="secondary"> + <a class="action remind" data-bind="attr: { href: forgotPasswordUrl }"> + <span data-bind="text: $t('Forgot Your Password?')"></span> + </a> + </div> + </div> + </fieldset> + <!--Hidden fields --> + </fieldset> +</form> +<!-- /ko --> diff --git a/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac3abe1cd6cb6fa38d82426add0139152f4b1e5b --- /dev/null +++ b/app/code/Magento/Dhl/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="step-config" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="dhl-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Dhl/js/view/shipping-rates-validation</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js new file mode 100644 index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557 --- /dev/null +++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'postcode': { + 'required': true + }, + 'country_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1 --- /dev/null +++ b/app/code/Magento/Dhl/view/frontend/web/js/model/shipping-rates-validator.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + './shipping-rates-validation-rules', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js new file mode 100644 index 0000000000000000000000000000000000000000..de18ca91237cd6affd9e4f56b167bcdbcfd056ef --- /dev/null +++ b/app/code/Magento/Dhl/view/frontend/web/js/view/shipping-rates-validation.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../model/shipping-rates-validator', + '../model/shipping-rates-validation-rules' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + dhlShippingRatesValidator, + dhlShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('dhl', dhlShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('dhl', dhlShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/Directory/Helper/Data.php b/app/code/Magento/Directory/Helper/Data.php index 1f7bae3fd00d0910f2c2c9589c180bd1be37cf16..fbd071c13824eb155d3adbd91b6ee9595beb8a5c 100644 --- a/app/code/Magento/Directory/Helper/Data.php +++ b/app/code/Magento/Directory/Helper/Data.php @@ -160,28 +160,7 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper $cacheKey = 'DIRECTORY_REGIONS_JSON_STORE' . $this->_storeManager->getStore()->getId(); $json = $this->_configCacheType->load($cacheKey); if (empty($json)) { - $countryIds = []; - foreach ($this->getCountryCollection() as $country) { - $countryIds[] = $country->getCountryId(); - } - $collection = $this->_regCollectionFactory->create(); - $collection->addCountryFilter($countryIds)->load(); - $regions = [ - 'config' => [ - 'show_all_regions' => $this->isShowNonRequiredState(), - 'regions_required' => $this->getCountriesWithStatesRequired(), - ], - ]; - foreach ($collection as $region) { - /** @var $region \Magento\Directory\Model\Region */ - if (!$region->getRegionId()) { - continue; - } - $regions[$region->getCountryId()][$region->getRegionId()] = [ - 'code' => $region->getCode(), - 'name' => (string)__($region->getName()), - ]; - } + $regions = $this->getRegionData(); $json = $this->jsonHelper->jsonEncode($regions); if ($json === false) { $json = 'false'; @@ -324,4 +303,36 @@ class Data extends \Magento\Framework\App\Helper\AbstractHelper $store ); } + + /** + * Retrieve regions data + * + * @return array + */ + public function getRegionData() + { + $countryIds = []; + foreach ($this->getCountryCollection() as $country) { + $countryIds[] = $country->getCountryId(); + } + $collection = $this->_regCollectionFactory->create(); + $collection->addCountryFilter($countryIds)->load(); + $regions = [ + 'config' => [ + 'show_all_regions' => $this->isShowNonRequiredState(), + 'regions_required' => $this->getCountriesWithStatesRequired(), + ], + ]; + foreach ($collection as $region) { + /** @var $region \Magento\Directory\Model\Region */ + if (!$region->getRegionId()) { + continue; + } + $regions[$region->getCountryId()][$region->getRegionId()] = [ + 'code' => $region->getCode(), + 'name' => (string)__($region->getName()), + ]; + } + return $regions; + } } diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config.php b/app/code/Magento/Directory/Model/Country/Postcode/Config.php new file mode 100644 index 0000000000000000000000000000000000000000..344938c4aaf54bc448544d2439235adddcd0700d --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config.php @@ -0,0 +1,30 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode; + +class Config implements ConfigInterface +{ + /** + * @var Config\Data + */ + protected $dataStorage; + + /** + * @param Config\Data $dataStorage + */ + public function __construct(\Magento\Directory\Model\Country\Postcode\Config\Data $dataStorage) + { + $this->dataStorage = $dataStorage; + } + + /** + * {@inheritdoc} + */ + public function getPostCodes() + { + return $this->dataStorage->get(); + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php new file mode 100644 index 0000000000000000000000000000000000000000..be9ee4dca475c8be5b5be9364a3741f1b0cde6cd --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Converter.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode\Config; + +class Converter implements \Magento\Framework\Config\ConverterInterface +{ + /** + * @var \Magento\Framework\Stdlib\BooleanUtils + */ + protected $booleanUtils; + + /** + * @param \Magento\Framework\Stdlib\BooleanUtils $booleanUtils + */ + public function __construct(\Magento\Framework\Stdlib\BooleanUtils $booleanUtils) + { + $this->booleanUtils = $booleanUtils; + } + + /** + * Convert dom node tree to array + * + * @param \DOMDocument $source + * @return array + */ + public function convert($source) + { + $result = []; + /** @var \DOMNode $zipNode */ + foreach ($source->documentElement->childNodes as $zipNode) { + if ($zipNode->nodeType != XML_ELEMENT_NODE) { + continue; + } + $groupName = $zipNode->attributes->getNamedItem('countryCode')->nodeValue; + /** @var \DOMNode $codesNode */ + foreach ($zipNode->childNodes as $codesNode) { + if ($codesNode->nodeType != XML_ELEMENT_NODE) { + continue; + } + /** @var \DOMNode $code */ + foreach ($codesNode->childNodes as $code) { + if ($code->nodeType != XML_ELEMENT_NODE + || !$this->booleanUtils->toBoolean($code->attributes->getNamedItem('active')->nodeValue) + ) { + continue; + } + $result[$groupName][$code->attributes->getNamedItem('id')->nodeValue] = [ + 'example' => $code->attributes->getNamedItem('example')->nodeValue, + 'pattern' => $code->nodeValue + ]; + } + } + } + return $result; + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php new file mode 100644 index 0000000000000000000000000000000000000000..b3dc1a7a6c7a3c575172f6d2ddc8e87efff99488 --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Data.php @@ -0,0 +1,20 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode\Config; + +class Data extends \Magento\Framework\Config\Data +{ + /** + * @param \Magento\Directory\Model\Country\Postcode\Config\Reader $reader + * @param \Magento\Framework\Config\CacheInterface $cache + */ + public function __construct( + \Magento\Directory\Model\Country\Postcode\Config\Reader $reader, + \Magento\Framework\Config\CacheInterface $cache + ) { + parent::__construct($reader, $cache, 'country_postcodes'); + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php new file mode 100644 index 0000000000000000000000000000000000000000..7fb5878318dccc009756dc4feacf15ab015f22fd --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/Reader.php @@ -0,0 +1,43 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode\Config; + +class Reader extends \Magento\Framework\Config\Reader\Filesystem +{ + /** + * Construct the FileSystem Reader Class + * + * @param \Magento\Framework\Config\FileResolverInterface $fileResolver + * @param Converter $converter + * @param SchemaLocator $schemaLocator + * @param \Magento\Framework\Config\ValidationStateInterface $validationState + * @param string $fileName + * @param array $idAttributes + * @param string $domDocumentClass + * @param string $defaultScope + */ + public function __construct( + \Magento\Framework\Config\FileResolverInterface $fileResolver, + Converter $converter, + \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator $schemaLocator, + \Magento\Framework\Config\ValidationStateInterface $validationState, + $fileName = 'zip_codes.xml', + $idAttributes = [], + $domDocumentClass = 'Magento\Framework\Config\Dom', + $defaultScope = 'global' + ) { + parent::__construct( + $fileResolver, + $converter, + $schemaLocator, + $validationState, + $fileName, + $idAttributes, + $domDocumentClass, + $defaultScope + ); + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php b/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php new file mode 100644 index 0000000000000000000000000000000000000000..5984a2e501b71983b6c9c6a00bdf546e7f81827a --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Config/SchemaLocator.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode\Config; + +class SchemaLocator implements \Magento\Framework\Config\SchemaLocatorInterface +{ + /** + * Path to corresponding XSD file with validation rules for both individual and merged configs + * + * @var string + */ + private $schema; + + /** + * @param \Magento\Framework\Module\Dir\Reader $moduleReader + */ + public function __construct(\Magento\Framework\Module\Dir\Reader $moduleReader) + { + $this->schema = $moduleReader->getModuleDir('etc', 'Magento_Directory') . '/zip_codes.xsd'; + } + + /** + * {@inheritdoc} + */ + public function getSchema() + { + return $this->schema; + } + + /** + * {@inheritdoc} + */ + public function getPerFileSchema() + { + return $this->schema; + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php b/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..ac1d487d47575c814c8c364f3e4d438494aaca87 --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/ConfigInterface.php @@ -0,0 +1,17 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode; + +interface ConfigInterface +{ + + /** + * Returns array of postcodes validation patterns + * + * @return array + */ + public function getPostCodes(); +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/Validator.php b/app/code/Magento/Directory/Model/Country/Postcode/Validator.php new file mode 100644 index 0000000000000000000000000000000000000000..a57d379683b3c802f1ac7060e5f8460a88416907 --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/Validator.php @@ -0,0 +1,41 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode; + +class Validator implements ValidatorInterface +{ + /** + * @var ConfigInterface + */ + protected $postCodesConfig; + + /** + * @param ConfigInterface $postCodesConfig + */ + public function __construct(\Magento\Directory\Model\Country\Postcode\ConfigInterface $postCodesConfig) + { + $this->postCodesConfig = $postCodesConfig; + } + + /** + * {@inheritdoc} + */ + public function validate($postcode, $countryId) + { + $postCodes = $this->postCodesConfig->getPostCodes(); + if (isset($postCodes[$countryId]) && is_array($postCodes[$countryId])) { + $patterns = $postCodes[$countryId]; + foreach ($patterns as $pattern) { + preg_match('/' . $pattern['pattern'] . '/', $postcode, $matches); + if (count($matches)) { + return true; + } + } + return false; + } + throw new \InvalidArgumentException('Provided countryId does not exist.'); + } +} diff --git a/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php b/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b6517be656a31a4ace53ffec657867ae22360ace --- /dev/null +++ b/app/code/Magento/Directory/Model/Country/Postcode/ValidatorInterface.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode; + +interface ValidatorInterface +{ + /** + * Validate postcode for selected country by mask + * + * @param string $postcode + * @param string $countryId + * @return bool + * @throws \InvalidArgumentException + */ + public function validate($postcode, $countryId); +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a4f4d4b5bbd79536735e3a78a5b1b99bf0ef7893 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ConverterTest.php @@ -0,0 +1,34 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config; + +class ConverterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Customer\Model\Address\Config\Converter + */ + protected $model; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $booleanUtilsMock; + + public function setUp() + { + $this->booleanUtilsMock = $this->getMock('Magento\Framework\Stdlib\BooleanUtils', [], [], '', false); + $this->model = new \Magento\Directory\Model\Country\Postcode\Config\Converter($this->booleanUtilsMock); + } + + public function testConvert() + { + $inputData = new \DOMDocument(); + $this->booleanUtilsMock->expects($this->any())->method('toBoolean')->willReturn(true); + $inputData->load(__DIR__ . '/../../../../_files/zip_codes.xml'); + $expectedResult = require __DIR__ . '/../../../../_files/zip_codes.php'; + $this->assertEquals($expectedResult, $this->model->convert($inputData)); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php new file mode 100644 index 0000000000000000000000000000000000000000..18663e83e74f9c63b1a2ca9f51e9b84cc8d82882 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/DataTest.php @@ -0,0 +1,38 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config; + +class DataTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $readerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $cacheMock; + + protected function setUp() + { + $this->readerMock = $this->getMockBuilder( + 'Magento\Directory\Model\Country\Postcode\Config\Reader' + )->disableOriginalConstructor()->getMock(); + $this->cacheMock = $this->getMockBuilder( + 'Magento\Framework\App\Cache\Type\Config' + )->disableOriginalConstructor()->getMock(); + } + + public function testGet() + { + $expected = ['someData' => ['someValue', 'someKey' => 'someValue']]; + $this->cacheMock->expects($this->any())->method('load')->will($this->returnValue(serialize($expected))); + $configData = new \Magento\Directory\Model\Country\Postcode\Config\Data($this->readerMock, $this->cacheMock); + + $this->assertEquals($expected, $configData->get()); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..066dcbcbd6668e319b1ea9c9e9b2a5c728f69064 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/ReaderTest.php @@ -0,0 +1,47 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config; + +class ReaderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Sales\Model\Config\Reader + */ + protected $reader; + + /** + * Prepare parameters + */ + public function setUp() + { + $fileResolver = $this->getMockBuilder( + 'Magento\Framework\App\Config\FileResolver' + )->disableOriginalConstructor()->getMock(); + $converter = $this->getMockBuilder( + 'Magento\Directory\Model\Country\Postcode\Config\Converter' + )->disableOriginalConstructor()->getMock(); + $schema = $this->getMockBuilder( + 'Magento\Directory\Model\Country\Postcode\Config\SchemaLocator' + )->disableOriginalConstructor()->getMock(); + $validator = $this->getMockBuilder( + 'Magento\Framework\Config\ValidationStateInterface' + )->disableOriginalConstructor()->getMock(); + $this->reader = new \Magento\Directory\Model\Country\Postcode\Config\Reader( + $fileResolver, + $converter, + $schema, + $validator + ); + } + + /** + * Test creating object + */ + public function testInstanceof() + { + $this->assertInstanceOf('Magento\Directory\Model\Country\Postcode\Config\Reader', $this->reader); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..794dc5a1ce9fe90129b8e8f47e8f73a004d1f2e6 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/Config/SchemaLocatorTest.php @@ -0,0 +1,46 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode\Config; + +class SchemaLocatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $moduleReaderMock; + + /** + * @var \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator + */ + protected $model; + + protected function setUp() + { + $this->moduleReaderMock = $this->getMock('Magento\Framework\Module\Dir\Reader', [], [], '', false); + $this->moduleReaderMock->expects( + $this->any() + )->method( + 'getModuleDir' + )->with( + 'etc', + 'Magento_Directory' + )->will( + $this->returnValue('schema_dir') + ); + + $this->model = new \Magento\Directory\Model\Country\Postcode\Config\SchemaLocator($this->moduleReaderMock); + } + + public function testGetSchema() + { + $this->assertEquals('schema_dir/zip_codes.xsd', $this->model->getSchema()); + } + + public function testGetPerFileSchema() + { + $this->assertEquals('schema_dir/zip_codes.xsd', $this->model->getPerFileSchema()); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d24ead182cb394c290616125b3084a466eb8a385 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ConfigTest.php @@ -0,0 +1,33 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode; + +class ConfigTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $dataStorageMock; + + protected function setUp() + { + $this->dataStorageMock = $this->getMock( + '\Magento\Directory\Model\Country\Postcode\Config\Data', + [], + [], + '', + false + ); + } + + public function testGet() + { + $expected = ['US' => ['pattern_01' => 'pattern_01', 'pattern_02' => 'pattern_02']]; + $this->dataStorageMock->expects($this->once())->method('get')->willReturn($expected); + $configData = new \Magento\Directory\Model\Country\Postcode\Config($this->dataStorageMock); + $this->assertEquals($expected, $configData->getPostCodes()); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7bf2562a6ed01b9f0d725a50ba9ce6eae6bf9c01 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/Model/Country/Postcode/ValidatorTest.php @@ -0,0 +1,63 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Test\Unit\Model\Country\Postcode; + +class ValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $postcodesConfigMock; + + /** + * @var \Magento\Directory\Model\Country\Postcode\Validator + */ + protected $model; + + protected function setUp() + { + $this->postcodesConfigMock = $this->getMock( + '\Magento\Directory\Model\Country\Postcode\Config', + [], + [], + '', + false + ); + $postCodes = [ + 'US' => [ + 'pattern_1' => ['pattern' => '^[0-9]{5}\-[0-9]{4}$'], + 'pattern_2' => ['pattern' => '^[0-9]{5}$'] + ] + ]; + $this->postcodesConfigMock->expects($this->once())->method('getPostCodes')->willReturn($postCodes); + $this->model = new \Magento\Directory\Model\Country\Postcode\Validator($this->postcodesConfigMock); + } + + public function testValidatePositive() + { + $postcode = '12345-6789'; + $countryId = 'US'; + $this->assertTrue($this->model->validate($postcode, $countryId)); + } + + public function testValidateNegative() + { + $postcode = 'POST-CODE'; + $countryId = 'US'; + $this->assertFalse($this->model->validate($postcode, $countryId)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Provided countryId does not exist. + */ + public function testValidateThrowExceptionIfCountryDoesNotExist() + { + $postcode = '12345-6789'; + $countryId = 'QQ'; + $this->assertFalse($this->model->validate($postcode, $countryId)); + } +} diff --git a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php new file mode 100644 index 0000000000000000000000000000000000000000..7a151e73a3e72cd6b7c86874441aeaa2a1106c87 --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +return [ + 'US' => [ + 'pattern_1' => [ + 'example' => 12345, + 'pattern' => '^[0-9]{5}\-[0-9]{4}$' + ], + 'pattern_2' => [ + 'example' => 12345, + 'pattern' => '^[0-9]{5}$' + ] + ] +]; diff --git a/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml new file mode 100644 index 0000000000000000000000000000000000000000..bbe7582ea62c267702eb25b4415ea01ac9585e8f --- /dev/null +++ b/app/code/Magento/Directory/Test/Unit/_files/zip_codes.xml @@ -0,0 +1,15 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../Directory/etc/zip_codes.xsd"> + <zip countryCode="US"> + <codes> + <code id="pattern_1" example="12345" active="true">^[0-9]{5}\-[0-9]{4}$</code> + <code id="pattern_2" example="12345" active="true">^[0-9]{5}$</code> + </codes> + </zip> +</config> diff --git a/app/code/Magento/Directory/etc/di.xml b/app/code/Magento/Directory/etc/di.xml index 36d16743f8363c39e4aa87e8019fcb0a51014af5..c1e11e69808025b7013f0e5837ec784ca0f40be3 100644 --- a/app/code/Magento/Directory/etc/di.xml +++ b/app/code/Magento/Directory/etc/di.xml @@ -27,4 +27,6 @@ <argument name="helperData" xsi:type="object">DirectoryHelperDataProxy</argument> </arguments> </type> + <preference for="Magento\Directory\Model\Country\Postcode\ConfigInterface" type="Magento\Directory\Model\Country\Postcode\Config" /> + <preference for="Magento\Directory\Model\Country\Postcode\ValidatorInterface" type="Magento\Directory\Model\Country\Postcode\Validator" /> </config> diff --git a/app/code/Magento/Directory/etc/zip_codes.xml b/app/code/Magento/Directory/etc/zip_codes.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfca9b740fa036ae66a94aaac0fc60154a79a626 --- /dev/null +++ b/app/code/Magento/Directory/etc/zip_codes.xml @@ -0,0 +1,487 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Directory/etc/zip_codes.xsd"> + <zip countryCode="DZ"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="AS"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="AR"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="AM"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="AU"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="AT"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="AZ"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + <code id="pattern_2" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="BD"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="BY"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="BE"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="BA"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="BR"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + <code id="pattern_2" active="true" example="12345-678">^[0-9]{5}\-[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="BN"> + <codes> + <code id="pattern_1" active="true" example="AB1234">^[a-zA-z]{2}[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="BG"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="CA"> + <codes> + <code id="pattern_1" active="true" example="A1B 2C3">^[a-zA-z]{1}[0-9]{1}[a-zA-z]{1}\s[0-9]{1}[a-zA-z]{1}[0-9]{1}$</code> + </codes> + </zip> + <zip countryCode="IC"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="CN"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="HR"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="CU"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="CY"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="CZ"> + <codes> + <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code> + </codes> + </zip> + <zip countryCode="DK"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="EE"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="FI"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="FR"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GF"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GE"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="DE"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GR"> + <codes> + <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code> + </codes> + </zip> + <zip countryCode="GL"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="GP"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GU"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GG"> + <codes> + <code id="pattern_1" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + </codes> + </zip> + <zip countryCode="HU"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="IS"> + <codes> + <code id="pattern_1" active="true" example="123">^[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="IN"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="ID"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="IL"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="IT"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="JP"> + <codes> + <code id="pattern_1" active="true" example="123-4567">^[0-9]{3}-[0-9]{4}$</code> + <code id="pattern_2" active="true" example="123">^[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="JE"> + <codes> + <code id="pattern_1" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + </codes> + </zip> + <zip countryCode="KZ"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="KE"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="KR"> + <codes> + <code id="pattern_1" active="true" example="123-456">^[0-9]{3}-[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="KG"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="LV"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="LI"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="LT"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="LU"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="MK"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="MG"> + <codes> + <code id="pattern_1" active="true" example="123">^[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="MY"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="MV"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + <code id="pattern_2" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="MT"> + <codes> + <code id="pattern_1" active="true" example="ABC 123">^[a-zA-Z]{3}\s[0-9]{3}$</code> + <code id="pattern_2" active="true" example="ABC 12">^[a-zA-Z]{3}\s[0-9]{2}$</code> + </codes> + </zip> + <zip countryCode="MH"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="MQ"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="MX"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="MD"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="MC"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="MN"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="MA"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="NL"> + <codes> + <code id="pattern_1" active="true" example="1234 AB">^[0-9]{4}\s[a-zA-Z]{2}$</code> + </codes> + </zip> + <zip countryCode="NO"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="PK"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="PH"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="PL"> + <codes> + <code id="pattern_1" active="true" example="12-345">^[0-9]{2}-[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="PT"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + <code id="pattern_2" active="true" example="1234-567">^[0-9]{4}-[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="PR"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="RE"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="RO"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="RU"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="MP"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="CS"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="SG"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="SK"> + <codes> + <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code> + </codes> + </zip> + <zip countryCode="SI"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="ZA"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="ES"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="XY"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="SZ"> + <codes> + <code id="pattern_1" active="true" example="A123">^[a-zA-Z]{1}[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="SE"> + <codes> + <code id="pattern_1" active="true" example="123 45">^[0-9]{3}\s[0-9]{2}$</code> + </codes> + </zip> + <zip countryCode="CH"> + <codes> + <code id="pattern_1" active="true" example="1234">^[0-9]{4}$</code> + </codes> + </zip> + <zip countryCode="TW"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + <code id="pattern_2" active="true" example="123">^[0-9]{3}$</code> + </codes> + </zip> + <zip countryCode="TJ"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="TH"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="TR"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="TM"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="UA"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="GB"> + <codes> + <code id="pattern_1" active="true" example="AB12 3CD">^[a-zA-Z]{2}[0-9]{2}\s[0-9]{1}[a-zA-Z]{2}$</code> + <code id="pattern_2" active="true" example="A1B 2CD">^[a-zA-Z]{1}[0-9]{1}[a-zA-Z]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + <code id="pattern_3" active="true" example="AB1 2CD">^[a-zA-Z]{2}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + <code id="pattern_4" active="true" example="AB1C 2DF">^[a-zA-Z]{2}[0-9]{1}[a-zA-Z]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + <code id="pattern_5" active="true" example="A12 3BC">^[a-zA-Z]{1}[0-9]{2}\s[0-9]{1}[a-zA-Z]{2}$</code> + <code id="pattern_6" active="true" example="A1 2BC">^[a-zA-Z]{1}[0-9]{1}\s[0-9]{1}[a-zA-Z]{2}$</code> + </codes> + </zip> + <zip countryCode="US"> + <codes> + <code id="pattern_1" active="true" example="12345-6789">^[0-9]{5}\-[0-9]{4}$</code> + <code id="pattern_2" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="UY"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> + <zip countryCode="UZ"> + <codes> + <code id="pattern_1" active="true" example="123456">^[0-9]{6}$</code> + </codes> + </zip> + <zip countryCode="VI"> + <codes> + <code id="pattern_1" active="true" example="12345">^[0-9]{5}$</code> + </codes> + </zip> +</config> diff --git a/app/code/Magento/Directory/etc/zip_codes.xsd b/app/code/Magento/Directory/etc/zip_codes.xsd new file mode 100644 index 0000000000000000000000000000000000000000..5400633a0df327bc20546c074d4b5b89d6ccdd12 --- /dev/null +++ b/app/code/Magento/Directory/etc/zip_codes.xsd @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <xs:element name="config" type="configType"> + </xs:element> + + <xs:complexType name="zipType"> + <xs:sequence> + <xs:element type="codesType" name="codes"/> + </xs:sequence> + <xs:attribute type="xs:string" name="countryCode" use="required"/> + </xs:complexType> + + <xs:complexType name="codesType"> + <xs:sequence> + <xs:element type="codeType" name="code" maxOccurs="unbounded" minOccurs="0"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="configType"> + <xs:sequence> + <xs:element type="zipType" name="zip" maxOccurs="unbounded" minOccurs="1"/> + </xs:sequence> + </xs:complexType> + + <xs:complexType name="codeType"> + <xs:simpleContent> + <xs:extension base="xs:string"> + <xs:attribute type="xs:string" name="id" use="required"/> + <xs:attribute type="xs:string" name="example" use="required"/> + <xs:attribute type="xs:boolean" name="active" use="optional"/> + </xs:extension> + </xs:simpleContent> + </xs:complexType> +</xs:schema> \ No newline at end of file diff --git a/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..541e46a36a627814c6989c5c8d237e7d1e83aaf5 --- /dev/null +++ b/app/code/Magento/Fedex/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="step-config" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="fedex-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Fedex/js/view/shipping-rates-validation</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js new file mode 100644 index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557 --- /dev/null +++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'postcode': { + 'required': true + }, + 'country_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1 --- /dev/null +++ b/app/code/Magento/Fedex/view/frontend/web/js/model/shipping-rates-validator.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + './shipping-rates-validation-rules', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js new file mode 100644 index 0000000000000000000000000000000000000000..dc9bc66b93e5ee503719ef80794bf1fb91a9acfe --- /dev/null +++ b/app/code/Magento/Fedex/view/frontend/web/js/view/shipping-rates-validation.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../model/shipping-rates-validator', + '../model/shipping-rates-validation-rules' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + fedexShippingRatesValidator, + fedexShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('fedex', fedexShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('fedex', fedexShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js index 4896aeb00b5b87c57ad90cdcc86c26e68da0b794..51e72540458efd1cd3a3f8fe564f148e9357a0b7 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js +++ b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js @@ -7,10 +7,10 @@ define( [ '../model/url-builder', 'mage/storage', - 'Magento_Ui/js/model/errorlist', + 'Magento_Ui/js/model/messageList', 'mage/url' ], - function(urlBuilder, storage, errorList, url) { + function(urlBuilder, storage, messageList, url) { "use strict"; return function(giftMessage, remove) { url.setBaseUrl(giftMessage.getConfigValue('baseUrl')); @@ -30,7 +30,7 @@ define( ); } } - errorList.clear(); + messageList.clear(); storage.post( serviceUrl, @@ -49,7 +49,7 @@ define( ).fail( function(response) { var error = JSON.parse(response.responseText); - errorList.add(error); + messageList.addErrorMessage(error); } ); }; diff --git a/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml index c6140255ab7f1141c453b557d25a282a92abc897..8e1eb709250e00164ef7c62f3dc6468334b0ef73 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/OfflinePayments/view/frontend/layout/checkout_onepage_index.xml @@ -15,30 +15,34 @@ <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="payment" xsi:type="array"> + <item name="billing-step" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="sortOrder" xsi:type="string">2</item> <item name="children" xsi:type="array"> - <item name="checkmo" xsi:type="array"> - <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/checkmo-method</item> - <item name="config" xsi:type="array"> - <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/checkmo-form</item> - </item> - </item> - <item name="cashondelivery" xsi:type="array"> - <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/instructions-method</item> - <item name="config" xsi:type="array"> - <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/instructions-form</item> - </item> - </item> - <item name="banktransfer" xsi:type="array"> - <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/instructions-method</item> - <item name="config" xsi:type="array"> - <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/instructions-form</item> - </item> - </item> - <item name="purchaseorder" xsi:type="array"> - <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/purchaseorder-method</item> - <item name="config" xsi:type="array"> - <item name="formTemplate" xsi:type="string">Magento_OfflinePayments/payment/purchaseorder-form</item> + <item name="payment" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="renders" xsi:type="array"> + <!-- merge payment method renders here --> + <item name="children" xsi:type="array"> + <item name="offline-payments" xsi:type="array"> + <item name="component" xsi:type="string">Magento_OfflinePayments/js/view/payment/offline-payments</item> + <item name="methods" xsi:type="array"> + <item name="checkmo" xsi:type="array"> + <item name="isBillingAddressRequired" xsi:type="boolean">true</item> + </item> + <item name="banktransfer" xsi:type="array"> + <item name="isBillingAddressRequired" xsi:type="boolean">true</item> + </item> + <item name="cashondelivery" xsi:type="array"> + <item name="isBillingAddressRequired" xsi:type="boolean">true</item> + </item> + <item name="purchaseorder" xsi:type="array"> + <item name="isBillingAddressRequired" xsi:type="boolean">true</item> + </item> + </item> + </item> + </item> + </item> </item> </item> </item> @@ -52,4 +56,4 @@ </arguments> </referenceBlock> </body> -</page> +</page> \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js deleted file mode 100644 index 5093e525aaea7e12e2e138f33884d33217120b54..0000000000000000000000000000000000000000 --- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/checkmo-method.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'Magento_Checkout/js/view/payment/method-info', - 'mage/translate' - ], - function (methodInfo, $t) { - return methodInfo.extend({ - getMailingAddress: function() { - return window.checkoutConfig.payment.checkmo.mailingAddress; - }, - getPayableTo: function() { - return window.checkoutConfig.payment.checkmo.payableTo; - }, - getInfo: function() { - var info = []; - if (this.getPayableTo()) { - info.push({name: $t('Make Check payable to')}); - info.push({value: this.getPayableTo()}); - } - if (this.getMailingAddress()) { - info.push({name: $t('Send Check to')}); - info.push({html: this.getMailingAddress()}); - } - return info; - } - }); - } -); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js deleted file mode 100644 index a3d9e9cdbae67265888a71dfe8aaae79fdbf778c..0000000000000000000000000000000000000000 --- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/instructions-method.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'Magento_Checkout/js/view/payment/method-info' - ], - function (methodInfo) { - return methodInfo.extend({ - getInstructions: function() { - return window.checkoutConfig.payment.instructions[this.getCode()]; - }, - getInfo: function() { - var info = []; - if (this.getInstructions()) { - info.push({html: this.getInstructions()}); - } - return info; - } - }); - } -); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js new file mode 100644 index 0000000000000000000000000000000000000000..e139bbf2fa4b1d5148317167bc8d4a1ae2392bc9 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/banktransfer-method.js @@ -0,0 +1,26 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'ko', + 'Magento_Checkout/js/view/payment/default' + ], + function (ko, Component) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_OfflinePayments/payment/banktransfer' + }, + /** + * Get value of instruction field. + * @returns {String} + */ + getInstructions: function () { + return window.checkoutConfig.payment.instructions[this.item.method]; + } + }); + } +); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js new file mode 100644 index 0000000000000000000000000000000000000000..9dea96883c3235d087e106bc20b728f9fc8315da --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/cashondelivery-method.js @@ -0,0 +1,24 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/payment/default' + ], + function (Component) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Magento_OfflinePayments/payment/cashondelivery' + }, + + /** Returns payment method instructions */ + getInstructions: function() { + return window.checkoutConfig.payment.instructions[this.item.method]; + } + }); + } +); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js new file mode 100644 index 0000000000000000000000000000000000000000..6eb00662593f1e0a2213af36b50fc6ca29f271c7 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/checkmo-method.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/payment/default' + ], + function (Component) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_OfflinePayments/payment/checkmo' + }, + + /** Returns send check to info */ + getMailingAddress: function() { + return window.checkoutConfig.payment.checkmo.mailingAddress; + }, + + /** Returns payable to info */ + getPayableTo: function() { + return window.checkoutConfig.payment.checkmo.payableTo; + } + }); + } +); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js new file mode 100644 index 0000000000000000000000000000000000000000..a5d09084f5cb8c5fefdb256cfdf94079f2b9e9e6 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/method-renderer/purchaseorder-method.js @@ -0,0 +1,44 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/payment/default', + 'jquery', + "mage/validation" + ], + function (Component, $) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Magento_OfflinePayments/payment/purchaseorder-form', + purchaseOrderNumber: '' + }, + initObservable: function () { + this._super() + .observe('purchaseOrderNumber'); + return this; + }, + getData: function () { + return { + "method": this.item.method, + 'po_number': this.purchaseOrderNumber(), + "cc_owner": null, + "cc_number": null, + "cc_type": null, + "cc_exp_year": null, + "cc_exp_month": null, + "additional_data": null + }; + + }, + validate: function () { + var form = '#purchaseorder'; + return $(form).validation() && $(form).validation('isValid'); + } + }); + } +); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js new file mode 100644 index 0000000000000000000000000000000000000000..809df962245fb2c225f117b2866c6b3d4c70a5bd --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/offline-payments.js @@ -0,0 +1,38 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + rendererList.push( + { + type: 'checkmo', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/checkmo-method' + }, + { + type: 'banktransfer', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/banktransfer-method' + }, + { + type: 'cashondelivery', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/cashondelivery-method' + }, + { + type: 'purchaseorder', + component: 'Magento_OfflinePayments/js/view/payment/method-renderer/purchaseorder-method' + } + ); + /** Add view logic here if needed */ + return Component.extend({}); + } +); \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js b/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js deleted file mode 100644 index 1233199cc2d862f2048fb7bcf1f0f05e72502a2a..0000000000000000000000000000000000000000 --- a/app/code/Magento/OfflinePayments/view/frontend/web/js/view/payment/purchaseorder-method.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'jquery', - "mage/translate", - 'Magento_Checkout/js/view/payment/method-info' - ], - function ($, $t, methodInfo) { - return methodInfo.extend({ - defaults: { - purchaseOrderNumber: '' - }, - initObservable: function () { - this._super() - .observe('purchaseOrderNumber'); - return this; - }, - getData: function() { - return {'po_number': this.purchaseOrderNumber()}; - }, - getInfo: function() { - return [ - {'name': 'Purchase Order Number', value: this.purchaseOrderNumber()} - ]; - } - }); - } -); diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html new file mode 100644 index 0000000000000000000000000000000000000000..dfcbf3131970749bfec9ab0537c3ef12f689fae7 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/banktransfer.html @@ -0,0 +1,40 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + --> +<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"> + <div class="payment-method-title field choice"> + <input type="radio" + name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()" /> + <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label> + </div> + + <div class="payment-method-content"> + <div class="payment-method-billing-address"> + <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <p data-bind="text: getInstructions()"></p> + <div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <button class="action primary checkout" + type="submit" + data-bind="click: placeOrder, attr: {'title': $t('Place Order')}, enable: (getCode() == isChecked())" + disabled> + <span data-bind="text: $t('Place Order')"></span> + </button> + </div> + </div> + </div> +</div> + \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html new file mode 100644 index 0000000000000000000000000000000000000000..569d5b0a48eb368622fee51306a8d9c30b075cf7 --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/cashondelivery.html @@ -0,0 +1,41 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"> + <div class="payment-method-title field choice"> + <input type="radio" + name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> + <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label> + </div> + + <div class="payment-method-content"> + <div class="payment-method-billing-address"> + <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <p data-bind="text: getInstructions()"></p> + <div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <button class="action primary checkout" + type="submit" + data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())" + disabled> + <span data-bind="text: $t('Place Order')"></span> + </button> + </div> + </div> + + </div> +</div> + \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html deleted file mode 100644 index 92c84f0662ddda6acf0fdff41ed3233ff69fe447..0000000000000000000000000000000000000000 --- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo-form.html +++ /dev/null @@ -1,20 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: getMailingAddress() || getPayableTo() --> -<dl class="items check payable" id="payment_form_<?php echo $block->getMethodCode() ?>"> - <!-- ko if: getPayableTo() --> - <dt class="title"><!-- ko text: $t('Make Check payable to:') --><!-- /ko --></dt> - <dd class="content"><!-- ko text: $t(getPayableTo()) --><!-- /ko --></dd> - <!-- /ko --> - <!-- ko if: getMailingAddress() --> - <dt class="title"><!-- ko text: $t('Send Check to:') --><!-- /ko --></dt> - <dd class="content"> - <address class="checkmo mailing address" data-bind="html: $t(getMailingAddress())"></address> - </dd> - <!-- /ko --> -</dl> -<!-- /ko --> diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html new file mode 100644 index 0000000000000000000000000000000000000000..58f85845434792ab778b177461ac493a743d649d --- /dev/null +++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/checkmo.html @@ -0,0 +1,52 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"> + <div class="payment-method-title field choice"> + <input type="radio" + name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> + <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label> + </div> + <div class="payment-method-content"> + <div class="payment-method-billing-address"> + <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <!-- ko if: getMailingAddress() || getPayableTo() --> + <dl class="items check payable"> + <!-- ko if: getPayableTo() --> + <dt class="title"><!-- ko text: $t('Make Check payable to:') --><!-- /ko --></dt> + <dd class="content"><!-- ko text: $t(getPayableTo()) --><!-- /ko --></dd> + <!-- /ko --> + <!-- ko if: getMailingAddress() --> + <dt class="title"><!-- ko text: $t('Send Check to:') --><!-- /ko --></dt> + <dd class="content"> + <address class="checkmo mailing address" data-bind="html: $t(getMailingAddress())"></address> + </dd> + <!-- /ko --> + </dl> + <!-- /ko --> + <div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <button class="action primary checkout" + type="submit" + data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())" + disabled> + <span data-bind="text: $t('Place Order')"></span> + </button> + </div> + </div> + </div> +</div> + \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html deleted file mode 100644 index 56f30d9cc42c14d7997f02c5c51b0dd22624fb21..0000000000000000000000000000000000000000 --- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/instructions-form.html +++ /dev/null @@ -1,9 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: getInstructions() --> -<div data-bind="attr: {class: 'items ' + getCode() + ' instructions agreement content', id: 'payment_form_' + getCode()}, html: $t(getInstructions())"></div> -<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html index 828045b5b7321a6893dc0493cb48d2e5ea14341e..585d61feae7d7c7423285c3db12f5351adc2d385 100644 --- a/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html +++ b/app/code/Magento/OfflinePayments/view/frontend/web/template/payment/purchaseorder-form.html @@ -4,19 +4,59 @@ * See COPYING.txt for license details. */ --> -<fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'> - <div class="field field-number required"> - <label for="po_number" class="label"><span><!-- ko text: $t('Purchase Order Number')--><!-- /ko --></span></label> - <div class="control"> - <input type="text" - id="po_number" - name="payment[po_number]" - data-validate="{required:true}" - data-bind=' - attr: {title: $t("Purchase Order Number")}, - value: purchaseOrderNumber, - enable: isActive($parent)' - class="input-text"/> +<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}"> + <form id="purchaseorder-form" class="form form-purchase-order"> + + <div class="payment-method-title field choice"> + <input type="radio" + name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> + <label data-bind="attr: {'for': getCode()}" class="label"> + <span data-bind="text: getTitle()"></span> + </label> </div> - </div> -</fieldset> \ No newline at end of file + + <div class="payment-method-content"> + <div class="payment-method-billing-address"> + <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + + <fieldset class="fieldset payment method" data-bind='attr: {id: "payment_form_" + getCode()}'> + <div class="field field-number required"> + <label for="po_number" class="label"> + <span><!-- ko text: $t('Purchase Order Number')--><!-- /ko --></span> + </label> + <div class="control"> + <input type="text" + id="po_number" + name="payment[po_number]" + data-validate="{required:true}" + data-bind=' + attr: {title: $t("Purchase Order Number")}, + value: purchaseOrderNumber' + class="input-text"/> + </div> + </div> + <div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="actions-toolbar" id="review-buttons-container"> + <div class="primary"> + <button class="action primary checkout" + type="submit" + data-bind="click: placeOrder, attr: {title: $t('Place Order')}, enable: (getCode() == isChecked())" + data-role="review-save"> + <span data-bind="text: $t('Place Order')"></span> + </button> + </div> + </div> + </fieldset> + </div> + </form> +</div> + \ No newline at end of file diff --git a/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..f97709a21bd0aa5313a6bdc0f44ef0167205a1e1 --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,48 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="step-config" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="freeshipping-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/freeshipping</item> + </item> + <item name="flatrate-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/flatrate</item> + </item> + <item name="tablerate-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_OfflineShipping/js/view/shipping-rates-validation/tablerate</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js new file mode 100644 index 0000000000000000000000000000000000000000..f45450e5359e06c86e85badb235aa193797c3a48 --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/flatrate.js @@ -0,0 +1,20 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'country_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js new file mode 100644 index 0000000000000000000000000000000000000000..f45450e5359e06c86e85badb235aa193797c3a48 --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/freeshipping.js @@ -0,0 +1,20 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'country_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js new file mode 100644 index 0000000000000000000000000000000000000000..174ca5d9b9506d9c7ea4d39d45b4bf1502ba6104 --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validation-rules/tablerate.js @@ -0,0 +1,26 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'postcode': { + 'required': true + }, + 'country_id': { + 'required': true + }, + 'region_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js new file mode 100644 index 0000000000000000000000000000000000000000..39faae263931600a6eec596c1e127ce6098b595d --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/flatrate.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + '../shipping-rates-validation-rules/flatrate', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js new file mode 100644 index 0000000000000000000000000000000000000000..d3e970cc8f7676a446ab94bc1c727cc7ad7a11cf --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/freeshipping.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + '../shipping-rates-validation-rules/freeshipping', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js new file mode 100644 index 0000000000000000000000000000000000000000..3a04b4cf03756da06de7a377ef65df08fe8599de --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/model/shipping-rates-validator/tablerate.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + '../shipping-rates-validation-rules/tablerate', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js new file mode 100644 index 0000000000000000000000000000000000000000..c7cd3490469ad1b1c18a30fb1873ee7b2d9b9e2b --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/flatrate.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../../model/shipping-rates-validator/flatrate', + '../../model/shipping-rates-validation-rules/flatrate' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + flatrateShippingRatesValidator, + flatrateShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('flatrate', flatrateShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('flatrate', flatrateShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js new file mode 100644 index 0000000000000000000000000000000000000000..a58024dcff35edb777ec6f6da89a3707364ae75f --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/freeshipping.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../../model/shipping-rates-validator/freeshipping', + '../../model/shipping-rates-validation-rules/freeshipping' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + freeshippingShippingRatesValidator, + freeshippingShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('freeshipping', freeshippingShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('freeshipping', freeshippingShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js new file mode 100644 index 0000000000000000000000000000000000000000..9f9754eedd202d1a8fb6c766d44de4e91f66bdd3 --- /dev/null +++ b/app/code/Magento/OfflineShipping/view/frontend/web/js/view/shipping-rates-validation/tablerate.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../../model/shipping-rates-validator/tablerate', + '../../model/shipping-rates-validation-rules/tablerate' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + tablerateShippingRatesValidator, + tablerateShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('tablerate', tablerateShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('tablerate', tablerateShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml index c6a429a0fbe08f624c53f03d7998879281dfde27..a2cf8e3a6383311ba7b2e20bd57c858fa88d368f 100644 --- a/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml +++ b/app/code/Magento/Payment/view/adminhtml/templates/transparent/form.phtml @@ -7,14 +7,22 @@ <?php // @codingStandardsIgnoreFile -/** @var \Magento\Payment\Block\Transparent\Form $block*/ +/** @var \Magento\Payment\Block\Transparent\Form $block */ $code = $block->getMethodCode(); ?> <!-- IFRAME for request to Payment Gateway --> -<iframe id="<?php echo $code ?>-transparent-iframe" data-container="<?php echo $code ?>-transparent-iframe" allowtransparency="true" frameborder="0" name="iframeTransparent" style="display:none;width:100%;background-color:transparent" src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe> -<div id="payment_form_<?php echo $code ?>" - data-mage-init='{ +<iframe id="<?php echo $code ?>-transparent-iframe" + data-container="<?php echo $code ?>-transparent-iframe" + allowtransparency="true" + frameborder="0" + name="iframeTransparent" + style="display: none; width: 100%; background-color: transparent;" + src="<?php echo $block->getViewFileUrl('blank.html') ?>"></iframe> +<fieldset + id="payment_form_<?php echo $code ?>" + class="admin__fieldset" + data-mage-init='{ "transparent":{ "controller":"<?php echo $block->getRequest()->getControllerName() ?>", "gateway":"<?php echo $block->getMethodCode() ?>", @@ -25,71 +33,96 @@ $code = $block->getMethodCode(); "expireYearLength":"<?php echo $block->getMethodConfigData('cc_year_length') ?>", "nativeAction":"<?php echo $block->getUrl('*/*/save', ['_secure' => $block->getRequest()->isSecure()]) ?>" }, "validation":[]}' - style="display:none;"> + style="display: none;"> + <div class="admin__field _required"> + <label for="<?php echo $code ?>_cc_type" class="admin__field-label"> + <span><?php echo __('Credit Card Type') ?></span> + </label> - <div class="field required type"> - <label for="<?php echo $code ?>_cc_type" class="label"><span><?php echo __('Credit Card Type') ?></span></label> - <div class="control"> - <select id="<?php echo $code ?>_cc_type" data-container="<?php echo $code ?>-cc-type" name="payment[cc_type]" data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}'> - <option value=""><?php echo __('--Please Select--')?></option> - <?php $_ccType = $block->getInfoData('cc_type') ?> - <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?> - <option value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option> - <?php endforeach ?> - </select> - </div> + <div class="admin__field-control"> + <select id="<?php echo $code ?>_cc_type" + data-container="<?php echo $code ?>-cc-type" + name="payment[cc_type]" + data-validate='{required:true, "validate-cc-type-select":"#<?php echo $code ?>_cc_number"}' + class="admin__control-select"> + <option value=""><?php echo __('Please Select') ?></option> + <?php $_ccType = $block->getInfoData('cc_type') ?> + <?php foreach ($block->getCcAvailableTypes() as $_typeCode => $_typeName): ?> + <option + value="<?php echo $_typeCode ?>"<?php if ($_typeCode == $_ccType): ?> selected="selected"<?php endif ?>><?php echo $_typeName ?></option> + <?php endforeach ?> + </select> </div> + </div> - <div class="field required number"> - <label for="<?php echo $code ?>_cc_number" class="label"><span><?php echo __('Credit Card Number') ?></span></label> - <div class="control"> - <input type="number" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number" name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>" class="input-text" value="" data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> - </div> + <div class="admin__field _required field-number"> + <label for="<?php echo $code ?>_cc_number" class="admin__field-label"> + <span><?php echo __('Credit Card Number') ?></span> + </label> + + <div class="admin__field-control"> + <input type="text" id="<?php echo $code ?>_cc_number" data-container="<?php echo $code ?>-cc-number" + name="payment[cc_number]" title="<?php echo __('Credit Card Number') ?>" + class="admin__control-text" + value="" + data-validate='{"required-number":true, "validate-cc-number":"#<?php echo $code ?>_cc_type", "validate-cc-type":"#<?php echo $code ?>_cc_type"}' + autocomplete="off"/> </div> + </div> - <div class="field required date" id="<?php echo $code ?>_cc_type_exp_div"> - <label for="<?php echo $code ?>_expiration" class="label"><span><?php echo __('Expiration Date') ?></span></label> - <div class="control"> - <div class="fields group group-2"> - <div class="field no-label month"> - <div class="control"> - <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]" data-container="<?php echo $code ?>-cc-month" class="month" data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'> - <?php $_ccExpMonth = $block->getInfoData('cc_exp_month') ?> - <?php foreach ($block->getCcMonths() as $k => $v): ?> - <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> - <?php endforeach ?> - </select> - </div> - </div> - <div class="field no-label year"> - <div class="control"> - <?php $_ccExpYear = $block->getInfoData('cc_exp_year') ?> - <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]" class="year" data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'> - <?php foreach ($block->getCcYears() as $k => $v): ?> - <option value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> - <?php endforeach ?> - </select> - </div> - </div> - </div> - </div> + <div class="admin__field _required field-date" id="<?php echo $code ?>_cc_type_exp_div"> + <label for="<?php echo $code ?>_expiration" class="admin__field-label"> + <span><?php echo __('Expiration Date') ?></span> + </label> + + <div class="admin__field-control"> + <select id="<?php echo $code ?>_expiration" name="payment[cc_exp_month]" + data-container="<?php echo $code ?>-cc-month" + class="admin__control-select admin__control-select-month" + data-validate='{required:true, "validate-cc-exp":"#<?php echo $code ?>_expiration_yr"}'> + <?php $_ccExpMonth = $block->getInfoData('cc_exp_month') ?> + <?php foreach ($block->getCcMonths() as $k => $v): ?> + <option + value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpMonth): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> + + <?php $_ccExpYear = $block->getInfoData('cc_exp_year') ?> + <select id="<?php echo $code ?>_expiration_yr" name="payment[cc_exp_year]" + class="admin__control-select admin__control-select-year" + data-container="<?php echo $code ?>-cc-year" data-validate='{required:true}'> + <?php foreach ($block->getCcYears() as $k => $v): ?> + <option + value="<?php echo $k ? $k : '' ?>"<?php if ($k == $_ccExpYear): ?> selected="selected"<?php endif ?>><?php echo $v ?></option> + <?php endforeach ?> + </select> </div> - <?php if ($block->hasVerification()): ?> - <div class="field required cvv" id="<?php echo $code ?>_cc_type_cvv_div"> - <label for="<?php echo $code ?>_cc_cid" class="label"><span><?php echo __('Card Verification Number') ?></span></label> - <div class="control"> - <input type="number" title="<?php echo __('Card Verification Number') ?>" data-container="<?php echo $code ?>-cc-cvv" class="input-text cvv" id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]" value="" data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}' autocomplete="off"/> - </div> + </div> + <?php if ($block->hasVerification()): ?> + <div class="admin__field _required field-cvv" id="<?php echo $code ?>_cc_type_cvv_div"> + <label for="<?php echo $code ?>_cc_cid" class="admin__field-label"> + <span><?php echo __('Card Verification Number') ?></span> + </label> + + <div class="admin__field-control"> + <input type="text" title="<?php echo __('Card Verification Number') ?>" + data-container="<?php echo $code ?>-cc-cvv" + class="admin__control-text cvv" + id="<?php echo $code ?>_cc_cid" name="payment[cc_cid]" + value="" + data-validate='{"required-number":true, "validate-cc-cvn":"#<?php echo $code ?>_cc_type"}' + autocomplete="off"/> </div> - <?php endif; ?> - <?php echo $block->getChildHtml() ?> -</div> + </div> + <?php endif; ?> + <?php echo $block->getChildHtml() ?> +</fieldset> <script> /** * Disable card server validation in admin */ - require(["Magento_Sales/order/create/form"], function(){ + require(["Magento_Sales/order/create/form"], function () { order.addExcludedPaymentMethod('<?php echo $code ?>'); }); </script> diff --git a/app/code/Magento/Payment/view/base/web/images/cc/ae.png b/app/code/Magento/Payment/view/base/web/images/cc/ae.png new file mode 100644 index 0000000000000000000000000000000000000000..f72ae5c26c314ac95ebfabb5887f3a1daf4cdd22 Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/ae.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/di.png b/app/code/Magento/Payment/view/base/web/images/cc/di.png new file mode 100644 index 0000000000000000000000000000000000000000..130d5a4aec88e9eec99e435f94f75725bf5728c7 Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/di.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/dn.png b/app/code/Magento/Payment/view/base/web/images/cc/dn.png new file mode 100644 index 0000000000000000000000000000000000000000..3444db7ea5945a86ac9ca506a5ff25939bb49c6b Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/dn.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/jc.png b/app/code/Magento/Payment/view/base/web/images/cc/jc.png new file mode 100644 index 0000000000000000000000000000000000000000..86df1caa5da6e869e462941402e1129213e9f05c Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/jc.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/mc.png b/app/code/Magento/Payment/view/base/web/images/cc/mc.png new file mode 100644 index 0000000000000000000000000000000000000000..bf0a4c2b8727fa824f3e902e88ee31d4d144a474 Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/mc.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/sm.png b/app/code/Magento/Payment/view/base/web/images/cc/sm.png new file mode 100644 index 0000000000000000000000000000000000000000..d239695ab2a41091981b4f34732276281bf8c992 Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/sm.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/un.png b/app/code/Magento/Payment/view/base/web/images/cc/un.png new file mode 100644 index 0000000000000000000000000000000000000000..b60791a0900184b6aea16155e06777ea7646158c Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/un.png differ diff --git a/app/code/Magento/Payment/view/base/web/images/cc/vi.png b/app/code/Magento/Payment/view/base/web/images/cc/vi.png new file mode 100644 index 0000000000000000000000000000000000000000..0885f78a93765fa61e350c60641302b498b109c0 Binary files /dev/null and b/app/code/Magento/Payment/view/base/web/images/cc/vi.png differ diff --git a/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml index 3f89143cb971ba996a0a3298a3807bec96d2d958..979a1c039cfedda69eb2821b528ad9c246824b68 100644 --- a/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Payment/view/frontend/layout/checkout_onepage_index.xml @@ -15,10 +15,26 @@ <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="payment" xsi:type="array"> + <item name="billing-step" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="sortOrder" xsi:type="string">2</item> <item name="children" xsi:type="array"> - <item name="free" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Payment/js/view/payment/free-method</item> + <item name="payment" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="renders" xsi:type="array"> + <!-- merge payment method renders here --> + <item name="children" xsi:type="array"> + <item name="free-payments" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Payment/js/view/payment/payments</item> + <item name="methods" xsi:type="array"> + <item name="free" xsi:type="array"> + <item name="isBillingAddressRequired" xsi:type="boolean">true</item> + </item> + </item> + </item> + </item> + </item> + </item> </item> </item> </item> @@ -31,4 +47,4 @@ </arguments> </referenceBlock> </body> -</page> +</page> \ No newline at end of file diff --git a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml index 93ac9970e145338451895c1d54d29a977e19f7bc..f71a9bdd9fa412d02330b38ad6cb347b409bfd19 100644 --- a/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml +++ b/app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml @@ -26,9 +26,15 @@ $params = $block->getParams(); window.top.location = "<?php echo $params['order_success'] ?>"; <?php else: ?> var require = window.top.require; - require(['jquery'], function($) { - $('#originalPlaceOrder').click(); - }); + require( + [ + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/action/place-order' + ], + function(quote, placeOrderAction) { + placeOrderAction(quote.paymentMethod(), true); + } + ); <?php endif; ?> </script> </head> diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js new file mode 100644 index 0000000000000000000000000000000000000000..ef6dd82c179b4591a89a43987f72ca91ca974478 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-data.js @@ -0,0 +1,19 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + return { + creditCard: null, + creditCardNumber: null, + expirationMonth: null, + expirationYear: null, + cvvCode: null + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..1f13a5af7c60a297dd13867daa9e1ba4694fbe5d --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator.js @@ -0,0 +1,72 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'mageUtils', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator/credit-card-type' + ], + function (utils, luhn10, creditCardTypes) { + 'use strict'; + + function resultWrapper(card, isPotentiallyValid, isValid) { + return { + card: card, + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function (value) { + var potentialTypes, + cardType, + valid, + i, + maxLength; + + if (utils.isEmpty(value)) { + return resultWrapper(null, false, false); + } + + value = value.replace(/\-|\s/g, ''); + + if (!/^\d*$/.test(value)) { + return resultWrapper(null, false, false); + } + + potentialTypes = creditCardTypes.getCardTypes(value); + + if (potentialTypes.length === 0) { + return resultWrapper(null, false, false); + } else if (potentialTypes.length !== 1) { + return resultWrapper(null, true, false); + } + + cardType = potentialTypes[0]; + + if (cardType.type === 'unionpay') { // UnionPay is not Luhn 10 compliant + valid = true; + } else { + valid = luhn10(value); + } + + for (i = 0; i < cardType.lengths.length; i++) { + if (cardType.lengths[i] === value.length) { + return resultWrapper(cardType, valid, valid); + } + } + + maxLength = Math.max.apply(null, cardType.lengths); + + if (value.length < maxLength) { + return resultWrapper(cardType, true, false); + } + + return resultWrapper(cardType, false, false); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js new file mode 100644 index 0000000000000000000000000000000000000000..71e0e57c5c16e71a394d1fa948f35ed807c75495 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/credit-card-type.js @@ -0,0 +1,144 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'mageUtils' + ], + function ($, utils) { + 'use strict'; + var types = [ + { + title: 'Visa', + type: 'VI', + pattern: '^4\\d*$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVV', + size: 3 + } + }, + { + title: 'MasterCard', + type: 'MC', + pattern: '^5([1-5]\\d*)?$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVC', + size: 3 + } + }, + { + title: 'American Express', + type: 'AE', + pattern: '^3([47]\\d*)?$', + isAmex: true, + gaps: [4, 10], + lengths: [15], + code: { + name: 'CID', + size: 4 + } + }, + { + title: 'Diners', + type: 'DN', + pattern: '^3((0([0-5]\\d*)?)|[689]\\d*)?$', + gaps: [4, 10], + lengths: [14], + code: { + name: 'CVV', + size: 3 + } + }, + { + title: 'Discover', + type: 'DI', + pattern: '^6(0|01|011\\d*|5\\d*|4|4[4-9]\\d*)?$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CID', + size: 3 + } + }, + { + title: 'JCB', + type: 'JC', + pattern: '^((2|21|213|2131\\d*)|(1|18|180|1800\\d*)|(3|35\\d*))$', + gaps: [4, 8, 12], + lengths: [16], + code: { + name: 'CVV', + size: 3 + } + }, + { + title: 'UnionPay', + type: 'UN', + pattern: '^6(2\\d*)?$', + gaps: [4, 8, 12], + lengths: [16, 17, 18, 19], + code: { + name: 'CVN', + size: 3 + } + }, + { + title: 'Maestro', + type: 'SM', + pattern: '(^(5[0678])[0-9]{11,18}$)' + + '|(^(6[^05])[0-9]{11,18}$)' + + '|(^(601)[^1][0-9]{9,16}$)' + + '|(^(6011)[0-9]{9,11}$)' + + '|(^(6011)[0-9]{13,16}$)' + + '|(^(65)[0-9]{11,13}$)' + + '|(^(65)[0-9]{15,18}$)' + + '|(^(49030)[2-9]([0-9]{10}$' + + '|[0-9]{12,13}$))' + + '|(^(49033)[5-9]([0-9]{10}$' + + '|[0-9]{12,13}$))' + + '|(^(49110)[1-2]([0-9]{10}$' + + '|[0-9]{12,13}$))' + + '|(^(49117)[4-9]([0-9]{10}$|[0-9]{12,13}$))' + + '|(^(49118)[0-2]([0-9]{10}$|[0-9]{12,13}$))' + + '|(^(4936)([0-9]{12}$|[0-9]{14,15}$))', + gaps: [4, 8, 12], + lengths: [12, 13, 14, 15, 16, 17, 18, 19], + code: { + name: 'CVC', + size: 3 + } + } + ]; + return { + getCardTypes: function (cardNumber) { + var i, value, + result = []; + + if (utils.isEmpty(cardNumber)) { + return result; + } + + if (cardNumber === '') { + return $.extend(true, {}, types); + } + + for (i = 0; i < types.length; i++) { + value = types[i]; + + if (new RegExp(value.pattern).test(cardNumber)) { + result.push($.extend(true, {}, value)); + } + } + return result; + } + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..38e93f084a25c72c8be813e52fa4f75b44c46622 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/credit-card-number-validator/luhn10-validator.js @@ -0,0 +1,22 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + /** + * Luhn algorithm verification + */ + return function(a, b, c, d, e) { + for(d = +a[b = a.length-1], e = 0; b--;) { + c = +a[b]; + d += ++e % 2 ? 2 * c % 10 + (c > 4) : c; + } + return !(d%10) + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..45733c9f8ff4623727ba757c88f0cd92ad346f21 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/cvv-validator.js @@ -0,0 +1,41 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + + function resultWrapper(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + /** + * CVV number validation + * validate digit count fot CVV code + */ + return function(value, maxLength) { + var DEFAULT_LENGTH = 3; + maxLength = maxLength || DEFAULT_LENGTH; + + if (!/^\d*$/.test(value)) { + return resultWrapper(false, false); + } + if (value.length === maxLength) { + return resultWrapper(true, true); + } + if (value.length < maxLength) { + return resultWrapper(false, true); + } + if (value.length > maxLength) { + return resultWrapper(false, false); + } + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..f7266a282740c6eb258839a7746bf57dbb1b329b --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator.js @@ -0,0 +1,51 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'mageUtils', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/parse-date', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator' + ], + function(utils, parseDate, expirationMonth, expirationYear) { + 'use strict'; + + function resultWrapper(isValid, isPotentiallyValid, month, year) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid, + month: month, + year: year + }; + } + + return function(value) { + var date, + monthValid, + yearValid; + + if (utils.isEmpty(value)) { + return resultWrapper(false, false, null, null); + } + + value = value.replace(/^(\d\d) (\d\d(\d\d)?)$/, '$1/$2'); + date = parseDate(value); + monthValid = expirationMonth(date.month); + yearValid = expirationYear(date.year); + + if (monthValid.isValid && yearValid.isValid) { + return resultWrapper(true, true, date.month, date.year); + } + + if (monthValid.isPotentiallyValid && yearValid.isPotentiallyValid) { + return resultWrapper(false, true, null, null); + } + + return resultWrapper(false, false, null, null); + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..c41ad14a459dbe7f788b8b0e21dd07a62150561c --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator.js @@ -0,0 +1,41 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function () { + 'use strict'; + + function resultWrapper(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function (value) { + var month, + monthValid; + + if ((value.replace(/\s/g, '') === '') || (value === '0')) { + return resultWrapper(false, true); + } + + if (!/^\d*$/.test(value)) { + return resultWrapper(false, false); + } + + if (isNaN(value)) { + return resultWrapper(false, false); + } + + month = parseInt(value, 10); + monthValid = month > 0 && month < 13; + + return resultWrapper(monthValid, monthValid); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..132c8dc42e9f2675647eb4112d09100fae84f7dd --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator.js @@ -0,0 +1,42 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + + function resultWrapper(isValid, isPotentiallyValid) { + return { + isValid: isValid, + isPotentiallyValid: isPotentiallyValid + }; + } + + return function(value) { + var currentYear = new Date().getFullYear(), + len = value.length, + valid, + expMaxLifetime = 19; + + if (value.replace(/\s/g, '') === '') { + return resultWrapper(false, true); + } + + if (!/^\d*$/.test(value)) { + return resultWrapper(false, false); + } + + if (len !== 4) { + return resultWrapper(false, true); + } + + value = parseInt(value, 10); + valid = value >= currentYear && value <= currentYear + expMaxLifetime; + return resultWrapper(valid, valid); + }; + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js new file mode 100644 index 0000000000000000000000000000000000000000..119bfa698732ecb0bf8895dad4ec75d8edeac063 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/expiration-date-validator/parse-date.js @@ -0,0 +1,32 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [], + function() { + 'use strict'; + return function(value) { + var month, len; + + if (value.match('/')) { + value = value.split(/\s*\/\s*/g); + + return { + month: value[0], + year: value.slice(1).join() + }; + } + + len = (value[0] === '0' || value.length > 5 || value.length === 4 || value.length === 3) ? 2 : 1; + month = value.substr(0, len); + + return { + month: month, + year: value.substr(month.length, 4) + }; + } + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js new file mode 100644 index 0000000000000000000000000000000000000000..660f3e3c0471f40d168481723d316bfcf792c0ed --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/model/credit-card-validation/validator.js @@ -0,0 +1,74 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +(function (factory) { + if (typeof define === 'function' && define.amd) { + define([ + 'jquery', + 'Magento_Payment/js/model/credit-card-validation/cvv-validator', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-year-validator', + 'Magento_Payment/js/model/credit-card-validation/expiration-date-validator/expiration-month-validator', + 'Magento_Payment/js/model/credit-card-validation/credit-card-data' + ], factory); + } else { + factory(jQuery); + } +}(function ($, cvvValidator, creditCardNumberValidator, expirationDateValidator, monthValidator, creditCardData) { + "use strict"; + + $.each({ + 'validate-card-number': [ + /** + * Validate credit card number based on mod 10 + * @param number - credit card number + * @return {boolean} + */ + function (number) { + return creditCardNumberValidator(number).isValid; + }, + 'Please enter a valid credit card number.' + ], + 'validate-card-date': [ + /** + * Validate credit card number based on mod 10 + * @param date - month + * @return {boolean} + */ + function (date) { + return monthValidator(date).isValid; + }, + 'Incorrect credit card expiration month.' + ], + 'validate-card-cvv': [ + /** + * Validate credit card number based on mod 10 + * @param cvv - month + * @return {boolean} + */ + function (cvv) { + var maxLength = creditCardData.creditCard ? creditCardData.creditCard.code.size : 3; + return cvvValidator(cvv, maxLength).isValid; + }, + 'Please enter a valid credit card verification number.' + ], + 'validate-card-year': [ + /** + * Validate credit card number based on mod 10 + * @param date - month + * @return {boolean} + */ + function (date) { + return monthValidator(date).isValid; + }, + 'Incorrect credit card expiration year.' + ] + + }, function (i, rule) { + rule.unshift(i); + $.validator.addMethod.apply($.validator, rule); + }); +})); \ No newline at end of file diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js index 8e6e53f0ae7e5061322e0a525bc733c057d938e2..5c1abc1e3c75b1721a889badee6e364009bd448f 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/cc-form.js @@ -7,21 +7,24 @@ define( [ 'underscore', - 'uiComponent', + 'Magento_Checkout/js/view/payment/default', + 'Magento_Payment/js/model/credit-card-validation/credit-card-data', + 'Magento_Payment/js/model/credit-card-validation/credit-card-number-validator', 'mage/translate' ], - function (_, component, $t) { - return component.extend({ + function (_, Component, creditCardData, cardNumberValidator, $t) { + return Component.extend({ defaults: { - template: 'Magento_Payment/payment/cc-form', creditCardType: '', creditCardExpYear: '', creditCardExpMonth: '', creditCardNumber: '', creditCardSsStartMonth: '', creditCardSsStartYear: '', - creditCardVerificationNumber: '' + creditCardVerificationNumber: '', + selectedCardType: null }, + initObservable: function () { this._super() .observe([ @@ -31,15 +34,62 @@ define( 'creditCardNumber', 'creditCardVerificationNumber', 'creditCardSsStartMonth', - 'creditCardSsStartYear' + 'creditCardSsStartYear', + 'selectedCardType' ]); return this; }, + + initialize: function() { + var self = this; + this._super(); + + //Set credit card number to credit card data object + this.creditCardNumber.subscribe(function(value) { + var result; + self.selectedCardType(null); + + if (value == '' || value == null) { + return false; + } + result = cardNumberValidator(value); + + if (!result.isPotentiallyValid && !result.isValid) { + return false; + } + if (result.card !== null) { + self.selectedCardType(result.card.type); + creditCardData.creditCard = result.card; + } + + if (result.isValid) { + creditCardData.creditCardNumber = value; + self.creditCardType(result.card.type); + } + }); + + //Set expiration year to credit card data object + this.creditCardExpYear.subscribe(function(value) { + creditCardData.expirationYear = value; + }); + + //Set expiration month to credit card data object + this.creditCardExpMonth.subscribe(function(value) { + creditCardData.expirationYear = value; + }); + + //Set cvv code to credit card data object + this.creditCardVerificationNumber.subscribe(function(value) { + creditCardData.cvvCode = value; + }); + }, + getCode: function() { return 'cc'; }, getData: function() { return { + 'method': this.item.method, 'cc_type': this.creditCardType(), 'cc_exp_year': this.creditCardExpYear(), 'cc_exp_month': this.creditCardExpMonth(), diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js similarity index 90% rename from app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js rename to app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js index 5349dab7b4d93202a4dec1f9924de97d0c564645..83a229af3bfbea8019ea0897b206b91f768377ee 100644 --- a/app/code/Magento/Payment/view/frontend/web/js/view/review/actions/iframe.js +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/iframe.js @@ -6,12 +6,12 @@ /*global define*/ define( [ - 'uiComponent' + 'Magento_Payment/js/view/payment/cc-form' ], function (Component) { return Component.extend({ defaults: { - template: 'Magento_Payment/review/actions/iframe' + template: 'Magento_Payment/payment/iframe' }, getSource: function () { return window.checkoutConfig.payment.iframe.source[this.getCode()]; @@ -34,9 +34,6 @@ define( getCardFieldsMap: function() { return window.checkoutConfig.payment.iframe.cardFieldsMap[this.getCode()]; }, - getCode: function() { - return this.index; - }, originalPlaceOrder: function(parent) { return parent.placeOrder.bind(parent); }, diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js new file mode 100644 index 0000000000000000000000000000000000000000..72c249027684b153892f992c3ce14cdd47aa84ad --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/method-renderer/free-method.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'Magento_Checkout/js/view/payment/default', + 'Magento_Checkout/js/model/quote' + ], + function (Component, quote) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Magento_Payment/payment/free' + }, + + /** Returns is method available */ + isAvailable: function() { + return quote.totals().grand_total <= 0; + } + }); + } +); diff --git a/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js b/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js new file mode 100644 index 0000000000000000000000000000000000000000..cff4f3810842e9ce77510d4b95da261e9475392b --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/js/view/payment/payments.js @@ -0,0 +1,26 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + rendererList.push( + { + type: 'free', + component: 'Magento_Payment/js/view/payment/method-renderer/free-method' + } + ); + /** Add view logic here if needed */ + return Component.extend({}); + } +); \ No newline at end of file diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html index 96fd1446d2cf33028c3f63f07d6400b1ef82a342..49d1d57f958bdd938284aaeaf11abf1ca926fb3d 100644 --- a/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html +++ b/app/code/Magento/Payment/view/frontend/web/template/payment/cc-form.html @@ -4,20 +4,36 @@ * See COPYING.txt for license details. */ --> + <fieldset data-bind="attr: {class: 'fieldset payment items ccard ' + getCode(), id: 'payment_form_' + getCode()}"> <!-- ko if: (isShowLegend())--> - <legend class="legend"><span><!-- ko text: $t('Credit Card Information')--><!-- /ko --></span></legend><br /> + <legend class="legend"> + <span><!-- ko text: $t('Credit Card Information')--><!-- /ko --></span> + </legend><br /> <!-- /ko --> <div class="field type required"> <label data-bind="attr: {for: getCode() + '_cc_type'}" class="label"> <span><!-- ko text: $t('Credit Card Type')--><!-- /ko --></span> </label> <div class="control"> - <select name="payment[cc_type]" class="select" - data-bind="attr: {id: getCode() + '_cc_type', 'data-container': getCode() + '-cc-type', 'data-validate': JSON.stringify({required:true, 'validate-cc-type-select':'#' + getCode() + '_cc_number'})}, - mageInit: {creditCardType:{creditCardTypeContainer:'#' + getCode() + '_cc_type_ss_div'}}, - enable: isActive($parents), options: getCcAvailableTypesValues(), optionsValue: 'value', optionsText: 'type', optionsCaption: $t('--Please Select--'), value: creditCardType"> - </select> + <ul class="credit-card-types"> + <!-- ko foreach: {data: getCcAvailableTypesValues(), as: 'item'} --> + <li class="item" data-bind="css: {_active: $parent.selectedCardType() == item.value} "> + <!-- if picture --> + <img data-bind="attr: { + 'src': 'Magento_Payment::images/cc/'+ item.value + '.png', + 'alt': item.type + }"> + <!-- if NOpicture --> + <span><!-- ko text: item.type --><!-- /ko --></span> + </li> + <!--/ko--> + </ul> + <input type="hidden" + name="payment[cc_number]" + class="input-text" + value="" + data-bind="attr: {id: getCode() + '_cc_type'}, value: creditCardType"> </div> </div> <div class="field number required"> @@ -25,9 +41,15 @@ <span><!-- ko text: $t('Credit Card Number')--><!-- /ko --></span> </label> <div class="control"> - <input type="number" name="payment[cc_number]" class="input-text" value="" - data-bind="attr: {id: getCode() + '_cc_number', title: $t('Credit Card Number'), 'data-container': getCode() + '-cc-number', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, - enable: isActive($parents), value: creditCardNumber"/> + <input type="text" name="payment[cc_number]" class="input-text" value="" + data-bind="attr: { + id: getCode() + '_cc_number', + title: $t('Credit Card Number'), + 'data-container': getCode() + '-cc-number', + 'data-validate': JSON.stringify({'required-number':true, 'validate-card-number':'#' + getCode() + '_cc_type', 'validate-cc-type':'#' + getCode() + '_cc_type'})}, + enable: isActive($parents), + value: creditCardNumber, + valueUpdate: 'keyup' "/> </div> </div> <div class="field date required" data-bind="attr: {id: getCode() + '_cc_type_exp_div'}"> @@ -38,17 +60,29 @@ <div class="fields group group-2"> <div class="field no-label month"> <div class="control"> - <select name="payment[cc_exp_month]" class="select month" - data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})}, - enable: isActive($parents), options: getCcMonthsValues(), optionsValue: 'value', optionsText: 'month', optionsCaption: $t('Month'), value: creditCardExpMonth"> + <select name="payment[cc_exp_month]" + class="select select-month" + data-bind="attr: {id: getCode() + '_expiration', 'data-container': getCode() + '-cc-month', 'data-validate': JSON.stringify({required:true, 'validate-cc-exp':'#' + getCode() + '_expiration_yr'})}, + enable: isActive($parents), + options: getCcMonthsValues(), + optionsValue: 'value', + optionsText: 'month', + optionsCaption: $t('Month'), + value: creditCardExpMonth"> </select> </div> </div> <div class="field no-label year"> <div class="control"> - <select name="payment[cc_exp_year]" class="select year" - data-bind="attr: {id: getCode() + '_expiration_yr', 'data-container': getCode() + '-cc-year', 'data-validate': JSON.stringify({required:true})}, - enable: isActive($parents), options: getCcYearsValues(), optionsValue: 'value', optionsText: 'year', optionsCaption: $t('Year'), value: creditCardExpYear"> + <select name="payment[cc_exp_year]" + class="select select-year" + data-bind="attr: {id: getCode() + '_expiration_yr', 'data-container': getCode() + '-cc-year', 'data-validate': JSON.stringify({required:true})}, + enable: isActive($parents), + options: getCcYearsValues(), + optionsValue: 'value', + optionsText: 'year', + optionsCaption: $t('Year'), + value: creditCardExpYear"> </select> </div> </div> @@ -60,11 +94,16 @@ <label data-bind="attr: {for: getCode() + '_cc_cid'}" class="label"> <span><!-- ko text: $t('Card Verification Number')--><!-- /ko --></span> </label> - <div class="control"> - <input type="number" class="input-text cvv" name="payment[cc_cid]" value="" - data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-cc-cvn':'#' + getCode() + '_cc_type'})}, enable: isActive($parents), value: creditCardVerificationNumber"/> - <div class="note"> - <a href="#" class="action cvv" data-bind="attr: {title: $t('What is this?')}, mageInit:{'tooltip': {'content': getCvvImageHtml()}}"><span><!-- ko text: $t('What is this?')--><!-- /ko --></span></a> + <div class="control _with-tooltip"> + <input type="text" class="input-text cvv" name="payment[cc_cid]" value="" + data-bind="attr: {id: getCode() + '_cc_cid', title: $t('Card Verification Number'), 'data-container': getCode() + '-cc-cvv', 'data-validate': JSON.stringify({'required-number':true, 'validate-card-cvv':'#' + getCode() + '_cc_type'})}, + enable: isActive($parents), + value: creditCardVerificationNumber"/> + <div class="field-tooltip toggle"> + <span class="field-tooltip-action action-cvv" data-bind="attr: {title: $t('What is this?')}"> + <span><!-- ko text: $t('What is this?')--><!-- /ko --></span> + </span> + <div class="field-tooltip-content" data-bind="html: getCvvImageHtml()"></div> </div> </div> </div> @@ -72,33 +111,55 @@ <!-- ko if: (hasSsCardType())--> <div class="field switch solo required" data-bind="attr: {id: getCode() + '_cc_type_ss_div'}"> <div class="nested"> - <div class="field switch solo required"> - <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"><span><!-- ko text: $t('Switch/Solo/Maestro Only')--><!-- /ko --></span></label> + <div class="field switch-solo required"> + <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"> + <span><!-- ko text: $t('Switch/Solo/Maestro Only')--><!-- /ko --></span> + </label> </div> <div class="field number required"> - <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"><span><!-- ko text: $t('Issue Number')--><!-- /ko --></span></label> + <label data-bind="attr: {for: getCode() + '_cc_issue'}" class="label"> + <span><!-- ko text: $t('Issue Number')--><!-- /ko --></span> + </label> <div class="control"> - <input type="text" name="payment[cc_ss_issue]" value="" class="input-text cvv" data-bind="attr: {id: getCode() + '_cc_issue', title: $t('Issue Number'), 'data-container': getCode() + '-cc-issue', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, enable: isActive($parents)"/> + <input type="text" name="payment[cc_ss_issue]" + value="" + class="input-text cvv" + data-bind="attr: {id: getCode() + '_cc_issue', title: $t('Issue Number'), 'data-container': getCode() + '-cc-issue', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, enable: isActive($parents)"/> </div> </div> <div class="field date required"> - <label data-bind="attr: {for: getCode() + '_start_month'}" class="label"><span><!-- ko text: $t('Start Date')--><!-- /ko --></span></label> + <label data-bind="attr: {for: getCode() + '_start_month'}" class="label"> + <span><!-- ko text: $t('Start Date')--><!-- /ko --></span> + </label> <div class="control"> <div class="fields group group-2"> - <div class="field no-label"> + <div class="field no-label month"> <div class="control"> - <select name="payment[cc_ss_start_month]" class="select month" + <select name="payment[cc_ss_start_month]" + class="select select-month" data-bind="attr: {id: getCode() + '_start_month', 'data-container': getCode() + '-cc-start-month', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, - enable: isActive($parents), options: getCcMonthsValues(), optionsValue: 'value', optionsText: 'month', optionsCaption: $t('Month'), value: creditCardSsStartMonth"> + enable: isActive($parents), + options: getCcMonthsValues(), + optionsValue: 'value', + optionsText: 'month', + optionsCaption: $t('Month'), + value: creditCardSsStartMonth"> </select> </div> </div> - <div class="field no-label"> + <div class="field no-label year"> <div class="control"> - <select name="payment[cc_ss_start_year]" class="select year" - data-bind="attr: {id: getCode() + '_start_year', 'data-container': getCode() + '-cc-start-year', 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, - enable: isActive($parents), options: getSsStartYearsValues(), optionsValue: 'value', optionsText: 'year', optionsCaption: $t('Year'), value: creditCardSsStartYear"> + <select name="payment[cc_ss_start_year]" + class="select select-year" + data-bind="attr: {id: getCode() + '_start_year', 'data-container': getCode() + '-cc-start-year', + 'data-validate': JSON.stringify({'validate-cc-ukss':true})}, + enable: isActive($parents), + options: getSsStartYearsValues(), + optionsValue: 'value', + optionsText: 'year', + optionsCaption: $t('Year'), + value: creditCardSsStartYear"> </select> </div> </div> diff --git a/app/code/Magento/Payment/view/frontend/web/template/payment/free.html b/app/code/Magento/Payment/view/frontend/web/template/payment/free.html new file mode 100644 index 0000000000000000000000000000000000000000..fb33eafd3cfbb59e8fffe9983692fe3d2fad1050 --- /dev/null +++ b/app/code/Magento/Payment/view/frontend/web/template/payment/free.html @@ -0,0 +1,36 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="payment-method" data-bind="css: {'_active': (getCode() == isChecked())}, visible: isAvailable()"> + <div class="payment-method-title field choice"> + <input type="radio" + name="payment[method]" + class="radio" + data-bind="attr: {'id': getCode()}, value: getCode(), checked: isChecked, click: selectPaymentMethod, visible: isRadioButtonVisible()"/> + <label data-bind="attr: {'for': getCode()}" class="label"><span data-bind="text: getTitle()"></span></label> + </div> + <div class="payment-method-content"> + <div class="payment-method-billing-address"> + <!-- ko foreach: $parent.getRegion(getBillingAddressFormName()) --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <button class="action primary checkout" + type="submit" + data-bind="click: placeOrder, attr: {title: $t('Place Order')}"> + <span data-bind="text: $t('Place Order')"></span> + </button> + </div> + </div> + </div> +</div> diff --git a/app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html b/app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html similarity index 91% rename from app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html rename to app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html index df5212f51e03f9a2b54332ca117c38d7abb0d5ba..2fec488a491cb1787d622de53a3c4764c404c4c4 100644 --- a/app/code/Magento/Payment/view/frontend/web/template/review/actions/iframe.html +++ b/app/code/Magento/Payment/view/frontend/web/template/payment/iframe.html @@ -21,6 +21,11 @@ <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </form> +<div class="checkout-agreements-block"> + <!-- ko foreach: $parent.getRegion('before-place-order') --> + <!-- ko template: getTemplate() --><!-- /ko --> + <!--/ko--> +</div> <div class="actions-toolbar" id="review-buttons-container"> <div class="primary"> <button data-role="review-save" type="submit" diff --git a/app/code/Magento/Payment/view/frontend/web/transparent.js b/app/code/Magento/Payment/view/frontend/web/transparent.js index 6394cf38fee739a4667b1845efc4e11f4582b913..2060ca7c8ea5e5a344329c0e48ad935859f77f8a 100644 --- a/app/code/Magento/Payment/view/frontend/web/transparent.js +++ b/app/code/Magento/Payment/view/frontend/web/transparent.js @@ -6,12 +6,14 @@ define([ "jquery", "mage/template", - "jquery/ui" + "jquery/ui", + "Magento_Payment/js/model/credit-card-validation/validator" ], function($, mageTemplate){ - "use strict"; + 'use strict'; $.widget('mage.transparent', { options: { + context: null, placeOrderSelector: '[data-role="review-save"]', paymentFormSelector: '#co-payment-form', updateSelectorPrefix: '#checkout-', @@ -34,9 +36,24 @@ define([ _create: function() { this.hiddenFormTmpl = mageTemplate(this.options.hiddenFormTmpl); - $(this.options.placeOrderSelector) - .off('click') - .on('click', $.proxy(this._placeOrderHandler, this)); + + if (this.options.context) { + this.options.context.setPlaceOrderHandler($.proxy(this._orderSave, this)); + this.options.context.setValidateHandler($.proxy(this._validateHandler, this)); + } else { + $(this.options.placeOrderSelector) + .off('click') + .on('click', $.proxy(this._placeOrderHandler, this)); + } + }, + + /** + * handler for credit card validation + * @return {Boolean} + * @private + */ + _validateHandler: function() { + return (this.element.validation && this.element.validation('isValid')); }, /** @@ -45,7 +62,7 @@ define([ * @private */ _placeOrderHandler: function() { - if (this.element.validation && this.element.validation('isValid')) { + if (this._validateHandler()) { this._orderSave(); } return false; @@ -65,7 +82,7 @@ define([ '[data-container="' + this.options.gateway + '-cc-type"]' ).val(); - $.ajax({ + return $.ajax({ url: this.options.orderSaveUrl, type: 'post', context: this, @@ -110,7 +127,6 @@ define([ inputs: data } }); - $(tmpl).appendTo($(iframeSelector)).submit(); }, diff --git a/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml similarity index 97% rename from app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml rename to app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml index 80989653fc335a36a6ebf2298af1ebab84a33a53..6d8cd9506b3907770cbb9e49e44996503a4337bd 100644 --- a/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Persistent/view/frontend/layout/checkout_onepage_original.xml @@ -5,6 +5,7 @@ * See COPYING.txt for license details. */ --> +<!-- TODO remove this file as soon as enhanced checkout is implemented --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> diff --git a/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php b/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php deleted file mode 100644 index a721e539ddf505abedd92f68433c26e917833a75..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Api/AddressDetailsManagementInterface.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Api; - -interface AddressDetailsManagementInterface -{ - /** - * Save billing and shipping addresses - * - * @param int $cartId - * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress - * @param \Magento\Quote\Api\Data\AddressInterface $shippingAddress - * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface|null $additionalData - * @param string|null $checkoutMethod - * @return \Magento\Quote\Api\Data\AddressDetailsInterface - */ - public function saveAddresses( - $cartId, - \Magento\Quote\Api\Data\AddressInterface $billingAddress, - \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null, - \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null, - $checkoutMethod = null - ); -} diff --git a/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php b/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php deleted file mode 100644 index 843d5faa1e38723531baed4c6f1ad6c564f6b674..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Api/Data/AddressDetailsInterface.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Api\Data; - -interface AddressDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface -{ - /**#@+ - * Constants defined for keys of array, makes typos less likely - */ - const SHIPPING_METHODS = 'shipping_methods'; - - const PAYMENT_METHODS = 'payment_methods'; - - const FORMATTED_BILLING_ADDRESS = 'formatted_billing_address'; - - const FORMATTED_SHIPPING_ADDRESS = 'formatted_shipping_address'; - - const TOTALS = 'totals'; - - /**#@-*/ - - /** - * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] - */ - public function getShippingMethods(); - - /** - * @return \Magento\Quote\Api\Data\PaymentMethodInterface[] - */ - public function getPaymentMethods(); - - /** - * @param \Magento\Quote\Api\Data\ShippingMethodInterface[] $shippingMethods - * @return $this - */ - public function setShippingMethods($shippingMethods); - - /** - * @param \Magento\Quote\Api\Data\PaymentMethodInterface[] $paymentMethods - * @return $this - */ - public function setPaymentMethods($paymentMethods); - - /** - * @return string|null - */ - public function getFormattedShippingAddress(); - - /** - * @return string - */ - public function getFormattedBillingAddress(); - - /** - * @param string $formattedBillingAddress - * @return $this - */ - public function setFormattedBillingAddress($formattedBillingAddress); - - /** - * @param string $formattedShippingAddress - * @return $this - */ - public function setFormattedShippingAddress($formattedShippingAddress); - - - /** - * Retrieve existing extension attributes object or create a new one. - * - * @return \Magento\Quote\Api\Data\AddressDetailsExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * Set an extension attributes object. - * - * @param \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes - ); - - /** - * @return \Magento\Quote\Api\Data\TotalsInterface - */ - public function getTotals(); - - /** - * @param \Magento\Quote\Api\Data\TotalsInterface $totals - * @return $this - */ - public function setTotals($totals); -} diff --git a/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php b/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..6ab64d64cf93fe303ff96b15eccceeef0a898045 --- /dev/null +++ b/app/code/Magento/Quote/Api/Data/TotalSegmentInterface.php @@ -0,0 +1,99 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Quote\Api\Data; + +/** + * Interface TotalsInterface + * @api + */ +interface TotalSegmentInterface extends \Magento\Framework\Api\ExtensibleDataInterface +{ + /**#@+ + * Constants defined for keys of array, makes typos less likely + */ + const CODE = 'code'; + const TITLE = 'title'; + const VALUE = 'value'; + const AREA = 'area'; + /**#@-*/ + + /** + * Total code + * + * @return string + */ + public function getCode(); + + /** + * Set total code + * + * @param string $code + * @return $this + */ + public function setCode($code); + + /** + * Get total title + * + * @return string|null + */ + public function getTitle(); + + /** + * Set total title + * + * @param string|null $title + * @return $this + */ + public function setTitle($title = null); + + /** + * Get total value + * + * @return float + */ + public function getValue(); + + /** + * Set total value + * + * @param float $value + * @return $this + */ + public function setValue($value); + + /** + * Get display area code. + * + * @return string|null + */ + public function getArea(); + + /** + * Set display area code + * + * @param string|null $area + * @return $this + */ + public function setArea($area = null); + + /** + * Retrieve existing extension attributes object or create a new one. + * + * @return \Magento\Quote\Api\Data\TotalSegmentExtensionInterface|null + */ + public function getExtensionAttributes(); + + /** + * Set an extension attributes object. + * + * @param \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes + * @return $this + */ + public function setExtensionAttributes( + \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes + ); +} diff --git a/app/code/Magento/Quote/Api/Data/TotalsInterface.php b/app/code/Magento/Quote/Api/Data/TotalsInterface.php index 5e8d5349ba1c13ee7c06603ba275131f570649fb..d11e5260c459ac3c706f5f347c91f236384785d9 100644 --- a/app/code/Magento/Quote/Api/Data/TotalsInterface.php +++ b/app/code/Magento/Quote/Api/Data/TotalsInterface.php @@ -42,6 +42,8 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface const KEY_BASE_TAX_AMOUNT = 'base_tax_amount'; + const KEY_WEEE_TAX_APPLIED_AMOUNT = 'weee_tax_applied_amount'; + const KEY_SHIPPING_TAX_AMOUNT = 'shipping_tax_amount'; const KEY_BASE_SHIPPING_TAX_AMOUNT = 'base_shipping_tax_amount'; @@ -58,8 +60,14 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface const KEY_QUOTE_CURRENCY_CODE = 'quote_currency_code'; + const KEY_COUPON_CODE = 'coupon_code'; + const KEY_ITEMS = 'items'; + const KEY_TOTAL_SEGMENTS = 'total_segments'; + + const KEY_ITEMS_QTY = 'items_qty'; + /**#@-*/ /** @@ -272,6 +280,21 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setBaseTaxAmount($baseTaxAmount); + /** + * Returns the total weee tax applied amount in quote currency. + * + * @return float Item weee tax applied amount in quote currency. + */ + public function getWeeeTaxAppliedAmount(); + + /** + * Sets the total weee tax applied amount in quote currency. + * + * @param float $weeeTaxAppliedAmount + * @return $this + */ + public function setWeeeTaxAppliedAmount($weeeTaxAppliedAmount); + /** * Get shipping tax amount in quote currency * @@ -392,6 +415,36 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setQuoteCurrencyCode($quoteCurrencyCode); + /** + * Get applied coupon code + * + * @return string|null + */ + public function getCouponCode(); + + /** + * Set applied coupon code + * + * @param string $couponCode + * @return $this + */ + public function setCouponCode($couponCode); + + /** + * Get items qty + * + * @return int||null + */ + public function getItemsQty(); + + /** + * Set items qty + * + * @param int $itemsQty + * @return $this + */ + public function setItemsQty($itemsQty = null); + /** * Get totals by items * @@ -407,6 +460,21 @@ interface TotalsInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ public function setItems(array $items = null); + /** + * Get dynamically calculated totals + * + * @return \Magento\Quote\Api\Data\TotalSegmentInterface[] + */ + public function getTotalSegments(); + + /** + * Set dynamically calculated totals + * + * @param \Magento\Quote\Api\Data\TotalSegmentInterface[] $totals + * @return $this + */ + public function setTotalSegments($totals = []); + /** * Retrieve existing extension attributes object or create a new one. * diff --git a/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php b/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php deleted file mode 100644 index a4eea1464145c613a5c06acdfb164bd9de819527..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Api/GuestAddressDetailsManagementInterface.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Api; - -interface GuestAddressDetailsManagementInterface -{ - /** - * Save billing and shipping addresses for guest. - * - * @param string $cartId - * @param \Magento\Quote\Api\Data\AddressInterface $billingAddress - * @param \Magento\Quote\Api\Data\AddressInterface|null $shippingAddress - * @param \Magento\Quote\Api\Data\AddressAdditionalDataInterface|null $additionalData - * @return \Magento\Quote\Api\Data\AddressDetailsInterface - */ - public function saveAddresses( - $cartId, - \Magento\Quote\Api\Data\AddressInterface $billingAddress, - \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null, - \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null - ); -} diff --git a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php index 10bd639cf93c5e30ddb57fde13595a67f2a5f945..29c4a07ca8d46c9d85d9f1a901c9303a86eaec3e 100644 --- a/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php +++ b/app/code/Magento/Quote/Api/GuestShippingMethodManagementInterface.php @@ -45,4 +45,13 @@ interface GuestShippingMethodManagementInterface * @throws \Magento\Framework\Exception\StateException The shipping address is not set. */ public function getList($cartId); + + /** + * Estimate shipping + * + * @param string $cartId The shopping cart ID. + * @param \Magento\Quote\Api\Data\EstimateAddressInterface $address The estimate address + * @return \Magento\Quote\Api\Data\ShippingMethodInterface[] An array of shipping methods. + */ + public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address); } diff --git a/app/code/Magento/Quote/Model/AddressDetails.php b/app/code/Magento/Quote/Model/AddressDetails.php deleted file mode 100644 index ba3e3bf697708ee8c0d9fc6c0b5c161c6adb3ab3..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Model/AddressDetails.php +++ /dev/null @@ -1,117 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Model; - -/** - * @codeCoverageIgnoreStart - */ -class AddressDetails extends \Magento\Framework\Model\AbstractExtensibleModel implements - \Magento\Quote\Api\Data\AddressDetailsInterface -{ - //@codeCoverageIgnoreStart - /** - * @{inheritdoc} - */ - public function getShippingMethods() - { - return $this->getData(self::SHIPPING_METHODS); - } - - /** - * @{inheritdoc} - */ - public function setShippingMethods($shippingMethods) - { - return $this->setData(self::SHIPPING_METHODS, $shippingMethods); - } - - /** - * @{inheritdoc} - */ - public function getPaymentMethods() - { - return $this->getData(self::PAYMENT_METHODS); - } - - /** - * @{inheritdoc} - */ - public function setPaymentMethods($paymentMethods) - { - return $this->setData(self::PAYMENT_METHODS, $paymentMethods); - } - - /** - * @{inheritdoc} - */ - public function getFormattedShippingAddress() - { - return $this->getData(self::FORMATTED_SHIPPING_ADDRESS); - } - - /** - * @{inheritdoc} - */ - public function getFormattedBillingAddress() - { - return $this->getData(self::FORMATTED_BILLING_ADDRESS); - } - - /** - * @{inheritdoc} - */ - public function setFormattedBillingAddress($formattedBillingAddress) - { - return $this->setData(self::FORMATTED_BILLING_ADDRESS, $formattedBillingAddress); - } - - /** - * @{inheritdoc} - */ - public function setFormattedShippingAddress($formattedShippingAddress) - { - return $this->setData(self::FORMATTED_SHIPPING_ADDRESS, $formattedShippingAddress); - } - - /** - * @{inheritdoc} - */ - public function getTotals() - { - return $this->getData(self::TOTALS); - } - - /** - * @{inheritdoc} - */ - public function setTotals($totals) - { - return $this->setData(self::TOTALS, $totals); - } - //@codeCoverageIgnoreEnd - - /** - * {@inheritdoc} - * - * @return \Magento\Quote\Api\Data\AddressDetailsExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Quote\Api\Data\AddressDetailsExtensionInterface $extensionAttributes - ) { - return $this->_setExtensionAttributes($extensionAttributes); - } -} diff --git a/app/code/Magento/Quote/Model/AddressDetailsManagement.php b/app/code/Magento/Quote/Model/AddressDetailsManagement.php deleted file mode 100644 index 84c6492510a6d02f6b668612047585920dc1bb75..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Model/AddressDetailsManagement.php +++ /dev/null @@ -1,122 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Model; - -use Magento\Quote\Api\CartTotalRepositoryInterface; -use Magento\Quote\Model\AddressAdditionalDataProcessor; - -class AddressDetailsManagement implements \Magento\Quote\Api\AddressDetailsManagementInterface -{ - /** - * @var \Magento\Quote\Api\BillingAddressManagementInterface - */ - protected $billingAddressManagement; - - /** - * @var \Magento\Quote\Api\ShippingAddressManagementInterface - */ - protected $shippingAddressManagement; - - /** - * @var \Magento\Quote\Api\PaymentMethodManagementInterface - */ - protected $paymentMethodManagement; - - /** - * @var \Magento\Quote\Api\ShippingMethodManagementInterface - */ - protected $shippingMethodManagement; - - /** - * @var AddressDetailsFactory - */ - protected $addressDetailsFactory; - - /** - * @var AddressAdditionalDataProcessor - */ - protected $dataProcessor; - - /** - * @var QuoteRepository - */ - protected $quoteRepository; - - /** - * @var CartTotalRepositoryInterface - */ - protected $cartTotalsRepository; - - /** - * @param \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement - * @param \Magento\Quote\Api\ShippingAddressManagementInterface $shippingAddressManagement - * @param \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement - * @param \Magento\Quote\Api\ShippingMethodManagementInterface $shippingMethodManagement - * @param AddressDetailsFactory $addressDetailsFactory - * @param AddressAdditionalDataProcessor $dataProcessor - * @param QuoteRepository $quoteRepository - * @param CartTotalRepositoryInterface $cartTotalsRepository - */ - public function __construct( - \Magento\Quote\Api\BillingAddressManagementInterface $billingAddressManagement, - \Magento\Quote\Api\ShippingAddressManagementInterface $shippingAddressManagement, - \Magento\Quote\Api\PaymentMethodManagementInterface $paymentMethodManagement, - \Magento\Quote\Api\ShippingMethodManagementInterface $shippingMethodManagement, - \Magento\Quote\Model\AddressDetailsFactory $addressDetailsFactory, - AddressAdditionalDataProcessor $dataProcessor, - QuoteRepository $quoteRepository, - CartTotalRepositoryInterface $cartTotalsRepository - ) { - $this->billingAddressManagement = $billingAddressManagement; - $this->shippingAddressManagement = $shippingAddressManagement; - $this->paymentMethodManagement = $paymentMethodManagement; - $this->shippingMethodManagement = $shippingMethodManagement; - $this->addressDetailsFactory = $addressDetailsFactory; - $this->dataProcessor = $dataProcessor; - $this->quoteRepository = $quoteRepository; - $this->cartTotalsRepository = $cartTotalsRepository; - } - - /** - * @{inheritdoc} - */ - public function saveAddresses( - $cartId, - \Magento\Quote\Api\Data\AddressInterface $billingAddress, - \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null, - \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null, - $checkoutMethod = null - ) { - $this->billingAddressManagement->assign($cartId, $billingAddress); - - /** @var \Magento\Quote\Api\Data\AddressDetailsInterface $addressDetails */ - $addressDetails = $this->addressDetailsFactory->create(); - if ($shippingAddress) { - $this->shippingAddressManagement->assign($cartId, $shippingAddress); - $addressDetails->setFormattedShippingAddress( - $this->shippingAddressManagement->get($cartId)->format('html') - ); - $addressDetails->setShippingMethods($this->shippingMethodManagement->getList($cartId)); - } - $addressDetails->setPaymentMethods($this->paymentMethodManagement->getList($cartId)); - if ($additionalData !== null) { - $this->dataProcessor->process($additionalData); - } - if ($checkoutMethod != null) { - $this->quoteRepository->save( - $this->quoteRepository->getActive($cartId) - ->setCheckoutMethod($checkoutMethod) - ); - } - - $addressDetails->setFormattedBillingAddress( - $this->billingAddressManagement->get($cartId)->format('html') - ); - - $addressDetails->setTotals($this->cartTotalsRepository->get($cartId)); - return $addressDetails; - } -} diff --git a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php index 78bdf6da18569990d10fe5ac97330780b6bd14ed..88906928f9a72034da279a9d51c51e7f6944d1a3 100644 --- a/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php +++ b/app/code/Magento/Quote/Model/Cart/CartTotalRepository.php @@ -11,6 +11,7 @@ use Magento\Quote\Api\CartTotalRepositoryInterface; use Magento\Catalog\Helper\Product\ConfigurationPool; use Magento\Framework\Api\DataObjectHelper; use Magento\Quote\Model\Cart\Totals\ItemConverter; +use Magento\Quote\Api\CouponManagementInterface; /** * Cart totals data object. @@ -39,24 +40,40 @@ class CartTotalRepository implements CartTotalRepositoryInterface /** * @var ConfigurationPool */ - private $converter; + private $itemConverter; + + /** + * @var CouponManagementInterface + */ + protected $couponService; + + /** + * @var TotalsConverter + */ + protected $totalsConverter; /** * @param Api\Data\TotalsInterfaceFactory $totalsFactory * @param QuoteRepository $quoteRepository * @param DataObjectHelper $dataObjectHelper + * @param CouponManagementInterface $couponService + * @param TotalsConverter $totalsConverter * @param ItemConverter $converter */ public function __construct( Api\Data\TotalsInterfaceFactory $totalsFactory, QuoteRepository $quoteRepository, DataObjectHelper $dataObjectHelper, + CouponManagementInterface $couponService, + TotalsConverter $totalsConverter, ItemConverter $converter ) { $this->totalsFactory = $totalsFactory; $this->quoteRepository = $quoteRepository; $this->dataObjectHelper = $dataObjectHelper; - $this->converter = $converter; + $this->couponService = $couponService; + $this->totalsConverter = $totalsConverter; + $this->itemConverter = $converter; } /** @@ -82,11 +99,19 @@ class CartTotalRepository implements CartTotalRepositoryInterface $totals = $this->totalsFactory->create(); $this->dataObjectHelper->populateWithArray($totals, $totalsData, '\Magento\Quote\Api\Data\TotalsInterface'); $items = []; + $weeeTaxAppliedAmount = 0; foreach ($quote->getAllVisibleItems() as $index => $item) { - $items[$index] = $this->converter->modelToDataObject($item); + $items[$index] = $this->itemConverter->modelToDataObject($item); + $weeeTaxAppliedAmount += $item->getWeeeTaxAppliedAmount(); } + $totals->setCouponCode($this->couponService->get($cartId)); + $calculatedTotals = $this->totalsConverter->process($quote->getTotals()); + $amount = $totals->getGrandTotal() - $totals->getTaxAmount(); + $amount = $amount > 0 ? $amount : 0; + $totals->setGrandTotal($amount); + $totals->setTotalSegments($calculatedTotals); $totals->setItems($items); - + $totals->setWeeeTaxAppliedAmount($weeeTaxAppliedAmount); return $totals; } } diff --git a/app/code/Magento/Quote/Model/Cart/TotalSegment.php b/app/code/Magento/Quote/Model/Cart/TotalSegment.php new file mode 100644 index 0000000000000000000000000000000000000000..203c8996f5fb2e55b92580cb86a41f93c0dba7e5 --- /dev/null +++ b/app/code/Magento/Quote/Model/Cart/TotalSegment.php @@ -0,0 +1,98 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Quote\Model\Cart; + +use Magento\Quote\Api\Data\TotalSegmentInterface; +use Magento\Framework\Model\AbstractExtensibleModel; + +/** + * Extensible Cart Totals + * + * @codeCoverageIgnore + */ +class TotalSegment extends AbstractExtensibleModel implements TotalSegmentInterface +{ + /** + * {@inheritdoc} + */ + public function getCode() + { + return $this->getData(self::CODE); + } + + /** + * {@inheritdoc} + */ + public function setCode($code) + { + return $this->setData(self::CODE, $code); + } + + /** + * {@inheritdoc} + */ + public function getValue() + { + return $this->getData(self::VALUE); + } + + /** + * {@inheritdoc} + */ + public function setValue($value) + { + return $this->setData(self::VALUE, $value); + } + + /** + * {@inheritdoc} + */ + public function getTitle() + { + return $this->getData(self::TITLE); + } + + /** + * {@inheritdoc} + */ + public function setTitle($title = null) + { + return $this->setData(self::TITLE, $title); + } + + /** + * {@inheritdoc} + */ + public function getArea() + { + return $this->getData(self::AREA); + } + + /** + * {@inheritdoc} + */ + public function setArea($area = null) + { + return $this->setData(self::AREA, $area); + } + + /** + * {@inheritdoc} + */ + public function getExtensionAttributes() + { + return $this->_getExtensionAttributes(); + } + + /** + * {@inheritdoc} + */ + public function setExtensionAttributes( + \Magento\Quote\Api\Data\TotalSegmentExtensionInterface $extensionAttributes + ) { + return $this->_setExtensionAttributes($extensionAttributes); + } +} diff --git a/app/code/Magento/Quote/Model/Cart/Totals.php b/app/code/Magento/Quote/Model/Cart/Totals.php index 4612824f9cebb05dc6c4dedbb00bd8827e4019a3..742f27d4df5497d6adbafdf6e1dd7fd6ddb791c0 100644 --- a/app/code/Magento/Quote/Model/Cart/Totals.php +++ b/app/code/Magento/Quote/Model/Cart/Totals.php @@ -310,6 +310,27 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface return $this->setData(self::KEY_BASE_TAX_AMOUNT, $baseTaxAmount); } + /** + * Returns the total weee tax applied amount in quote currency. + * + * @return float Item weee tax applied amount in quote currency. + */ + public function getWeeeTaxAppliedAmount() + { + return $this->getData(self::KEY_WEEE_TAX_APPLIED_AMOUNT); + } + + /** + * Sets the total weee tax applied amount in quote currency. + * + * @param float $weeeTaxAppliedAmount + * @return $this + */ + public function setWeeeTaxAppliedAmount($weeeTaxAppliedAmount) + { + return $this->setData(self::KEY_WEEE_TAX_APPLIED_AMOUNT, $weeeTaxAppliedAmount); + } + /** * Get shipping tax amount in quote currency * @@ -478,6 +499,43 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface return $this->setData(self::KEY_QUOTE_CURRENCY_CODE, $quoteCurrencyCode); } + /** + * {@inheritdoc} + */ + public function getCouponCode() + { + return $this->getData(self::KEY_COUPON_CODE); + } + + /** + * {@inheritdoc} + */ + public function setCouponCode($couponCode) + { + return $this->setData(self::KEY_COUPON_CODE, $couponCode); + } + + /** + * Get items qty + * + * @return int||null + */ + public function getItemsQty() + { + return $this->getData(self::KEY_ITEMS_QTY); + } + + /** + * Set items qty + * + * @param int $itemsQty + * @return $this + */ + public function setItemsQty($itemsQty = null) + { + return $this->setData(self::KEY_ITEMS_QTY, $itemsQty); + } + /** * Get totals by items * @@ -499,6 +557,22 @@ class Totals extends AbstractExtensibleModel implements TotalsInterface return $this->setData(self::KEY_ITEMS, $items); } + /** + * {@inheritdoc} + */ + public function getTotalSegments() + { + return $this->getData(self::KEY_TOTAL_SEGMENTS); + } + + /** + * {@inheritdoc} + */ + public function setTotalSegments($totals = []) + { + return $this->setData(self::KEY_TOTAL_SEGMENTS, $totals); + } + /** * {@inheritdoc} * diff --git a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php index f569f8478b09d566bb3e65131436214d772a3b94..2b4792d2e44a2d884e8bf2f99b444abbc6a3ae43 100644 --- a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php +++ b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php @@ -86,10 +86,12 @@ class ItemConverter private function getFormattedOptionValue($item) { $optionsData = []; + + /* @var $helper \Magento\Catalog\Helper\Product\Configuration */ + $helper = $this->configurationPool->getByProductType('default'); + $options = $this->configurationPool->getByProductType($item->getProductType())->getOptions($item); foreach ($options as $index => $optionValue) { - /* @var $helper \Magento\Catalog\Helper\Product\Configuration */ - $helper = $this->configurationPool->getByProductType('default'); $params = [ 'max_length' => 55, 'cut_replacer' => ' <a href="#" class="dots tooltip toggle" onclick="return false">...</a>' diff --git a/app/code/Magento/Quote/Model/Cart/TotalsConverter.php b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php new file mode 100644 index 0000000000000000000000000000000000000000..a041844c8ed5023dd4884459a0a95e222d3a882a --- /dev/null +++ b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Quote\Model\Cart; + +use Magento\Quote\Api\Data\TotalSegmentInterface; +use Magento\Quote\Api\Data\TotalSegmentInterfaceFactory; + +/** + * Cart totals data objects converter. + */ +class TotalsConverter +{ + /** + * @var TotalSegmentInterfaceFactory + */ + protected $factory; + + /** + * @param TotalSegmentInterfaceFactory $factory + */ + public function __construct( + TotalSegmentInterfaceFactory $factory + ) { + $this->factory = $factory; + } + + + /** + * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals + * @return \Magento\Quote\Api\Data\TotalSegmentInterface[] + */ + public function process($addressTotals) + { + $data = []; + /** @var \Magento\Quote\Model\Quote\Address\Total $addressTotal */ + foreach ($addressTotals as $addressTotal) { + $pureData = [ + TotalSegmentInterface::CODE => $addressTotal->getCode(), + TotalSegmentInterface::TITLE => '', + TotalSegmentInterface::VALUE => $addressTotal->getValue(), + TotalSegmentInterface::AREA => $addressTotal->getArea(), + ]; + if (is_object($addressTotal->getTitle())) { + $pureData[TotalSegmentInterface::TITLE] = $addressTotal->getTitle()->getText(); + } + /** @var \Magento\Quote\Model\Cart\TotalSegment $total */ + $total = $this->factory->create(); + $total->setData($pureData); + $data[] = $total; + } + return $data; + } +} diff --git a/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php b/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php deleted file mode 100644 index 2671a1ccb7665ebddf0b526f923090d6440c85f4..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Model/GuestCart/GuestAddressDetailsManagement.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Model\GuestCart; - -use Magento\Quote\Model\QuoteIdMaskFactory; - -class GuestAddressDetailsManagement implements \Magento\Quote\Api\GuestAddressDetailsManagementInterface -{ - /** - * @var \Magento\Quote\Api\AddressDetailsManagementInterface - */ - protected $addressDetailsManagement; - - /** - * @var QuoteIdMaskFactory - */ - protected $quoteIdMaskFactory; - - /** - * @param \Magento\Quote\Api\AddressDetailsManagementInterface $addressDetailsManagement - * @param QuoteIdMaskFactory $quoteIdMaskFactory - */ - public function __construct( - \Magento\Quote\Api\AddressDetailsManagementInterface $addressDetailsManagement, - QuoteIdMaskFactory $quoteIdMaskFactory - ) { - $this->addressDetailsManagement = $addressDetailsManagement; - $this->quoteIdMaskFactory = $quoteIdMaskFactory; - } - - /** - * @{inheritdoc} - */ - public function saveAddresses( - $cartId, - \Magento\Quote\Api\Data\AddressInterface $billingAddress, - \Magento\Quote\Api\Data\AddressInterface $shippingAddress = null, - \Magento\Quote\Api\Data\AddressAdditionalDataInterface $additionalData = null - ) { - $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); - return $this->addressDetailsManagement->saveAddresses( - $quoteIdMask->getQuoteId(), - $billingAddress, - $shippingAddress, - $additionalData - ); - } -} diff --git a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php index 0687ca395de869030d97dbb780f474bf1ebc1733..6026ff8f8da0406a98dcc1beaf5212c816e81df6 100644 --- a/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/GuestCart/GuestShippingMethodManagement.php @@ -69,4 +69,14 @@ class GuestShippingMethodManagement implements GuestShippingMethodManagementInte $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); return $this->shippingMethodManagement->set($quoteIdMask->getQuoteId(), $carrierCode, $methodCode); } + + /** + * {@inheritDoc} + */ + public function estimateByAddress($cartId, \Magento\Quote\Api\Data\EstimateAddressInterface $address) + { + /** @var $quoteIdMask QuoteIdMask */ + $quoteIdMask = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id'); + return $this->shippingMethodManagement->estimateByAddress($quoteIdMask->getQuoteId(), $address); + } } diff --git a/app/code/Magento/Quote/Model/Quote/Item.php b/app/code/Magento/Quote/Model/Quote/Item.php index 56ea708036533251670e39c59ed59569732de0b2..51694e5f68864efedb456e3628e2c0d66d2d557e 100644 --- a/app/code/Magento/Quote/Model/Quote/Item.php +++ b/app/code/Magento/Quote/Model/Quote/Item.php @@ -20,7 +20,6 @@ use Magento\Framework\Api\ExtensionAttributesFactory; * @method \Magento\Quote\Model\Quote\Item setCreatedAt(string $value) * @method string getUpdatedAt() * @method \Magento\Quote\Model\Quote\Item setUpdatedAt(string $value) - * @method \Magento\Quote\Model\Quote\Item setProductId(int $value) * @method int getStoreId() * @method \Magento\Quote\Model\Quote\Item setStoreId(int $value) * @method int getParentItemId() diff --git a/app/code/Magento/Quote/Model/QuoteAddressValidator.php b/app/code/Magento/Quote/Model/QuoteAddressValidator.php index e92780f4056dba9f10a7158e9abd6cdae5470a4a..13df66e5f9f2513a5b176abb3c90d2b641a8ea88 100644 --- a/app/code/Magento/Quote/Model/QuoteAddressValidator.php +++ b/app/code/Magento/Quote/Model/QuoteAddressValidator.php @@ -13,7 +13,7 @@ class QuoteAddressValidator * * @var \Magento\Customer\Api\AddressRepositoryInterface */ - protected $addressReporitory; + protected $addressRepository; /** * Customer repository. @@ -39,7 +39,7 @@ class QuoteAddressValidator \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, \Magento\Customer\Model\Session $customerSession ) { - $this->addressReporitory = $addressRepository; + $this->addressRepository = $addressRepository; $this->customerRepository = $customerRepository; $this->customerSession = $customerSession; } @@ -67,7 +67,7 @@ class QuoteAddressValidator // validate address id if ($addressData->getId()) { try { - $address = $this->addressReporitory->getById($addressData->getId()); + $address = $this->addressRepository->getById($addressData->getId()); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { throw new \Magento\Framework\Exception\NoSuchEntityException( __('Invalid address id %1', $addressData->getId()) diff --git a/app/code/Magento/Quote/Model/QuoteManagement.php b/app/code/Magento/Quote/Model/QuoteManagement.php index f341b5894b9fb0a5a5da68f92c6a5b04e79fe2ca..8efb0a3794ddc6a584f1b4ae333c14a12ccac911 100644 --- a/app/code/Magento/Quote/Model/QuoteManagement.php +++ b/app/code/Magento/Quote/Model/QuoteManagement.php @@ -297,11 +297,6 @@ class QuoteManagement implements \Magento\Quote\Api\CartManagementInterface */ public function placeOrder($cartId, $agreements = null, PaymentInterface $paymentMethod = null) { - if (!$this->agreementsValidator->isValid($agreements)) { - throw new \Magento\Framework\Exception\CouldNotSaveException( - __('Please agree to all the terms and conditions before placing the order.') - ); - } $quote = $this->quoteRepository->getActive($cartId); if ($paymentMethod) { $paymentMethod->setChecks([ diff --git a/app/code/Magento/Quote/Model/ShippingMethodManagement.php b/app/code/Magento/Quote/Model/ShippingMethodManagement.php index f8a39533b4233cf77b9365821857ca0e973ada0c..f54ab223a9d55f23a7610bbd204064ac86c0ac97 100644 --- a/app/code/Magento/Quote/Model/ShippingMethodManagement.php +++ b/app/code/Magento/Quote/Model/ShippingMethodManagement.php @@ -46,7 +46,6 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface * @param QuoteRepository $quoteRepository Quote repository. * @param \Magento\Quote\Model\Cart\ShippingMethodConverter $converter Shipping method converter. * @param \Magento\Customer\Api\AddressRepositoryInterface $addressRepository Customer Address repository - * */ public function __construct( QuoteRepository $quoteRepository, @@ -80,6 +79,9 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface $shippingAddress->collectShippingRates(); /** @var \Magento\Quote\Model\Quote\Address\Rate $shippingRate */ $shippingRate = $shippingAddress->getShippingRateByCode($shippingMethod); + if (!$shippingRate) { + return null; + } return $this->converter->modelToDataObject($shippingRate, $quote->getQuoteCurrencyCode()); } @@ -140,10 +142,6 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface if (!$shippingAddress->getCountryId()) { throw new StateException(__('Shipping address is not set')); } - $billingAddress = $quote->getBillingAddress(); - if (!$billingAddress->getCountryId()) { - throw new StateException(__('Billing address is not set')); - } $shippingAddress->setShippingMethod($carrierCode . '_' . $methodCode); if (!$shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod())) { throw new NoSuchEntityException( @@ -222,7 +220,7 @@ class ShippingMethodManagement implements ShippingMethodManagementInterface $shippingAddress->setRegionId($regionId); $shippingAddress->setRegion($region); $shippingAddress->setCollectShippingRates(true); - $shippingAddress->collectShippingRates(); + $shippingAddress->collectTotals(); $shippingRates = $shippingAddress->getGroupedAllShippingRates(); foreach ($shippingRates as $carrierRates) { foreach ($carrierRates as $rate) { diff --git a/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php deleted file mode 100644 index ab1e0e6c18be2874a5fbc5f5af17ffd48452e028..0000000000000000000000000000000000000000 --- a/app/code/Magento/Quote/Test/Unit/Model/AddressDetailsManagementTest.php +++ /dev/null @@ -1,151 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Test\Unit\Model; - -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; - -class AddressDetailsManagementTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\Quote\Model\AddressDetailsManagement - */ - protected $model; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $billingAddressManagement; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $shippingAddressManagement; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $paymentMethodManagement; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $shippingMethodManagement; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $addressDetailsFactory; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $dataProcessor; - - /** @var \Magento\Quote\Model\QuoteRepository|\PHPUnit_Framework_MockObject_MockObject */ - protected $quoteRepository; - - /** - * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager - */ - protected $objectManager; - - protected function setUp() - { - $this->objectManager = new ObjectManager($this); - $this->billingAddressManagement = $this->getMock('Magento\Quote\Api\BillingAddressManagementInterface'); - $this->shippingAddressManagement = $this->getMock('Magento\Quote\Api\ShippingAddressManagementInterface'); - $this->paymentMethodManagement = $this->getMock('Magento\Quote\Api\PaymentMethodManagementInterface'); - $this->shippingMethodManagement = $this->getMock('Magento\Quote\Api\ShippingMethodManagementInterface'); - $this->addressDetailsFactory = $this->getMock( - 'Magento\Quote\Model\AddressDetailsFactory', - ['create'], - [], - '', - false - ); - $this->dataProcessor = $this->getMock('Magento\Quote\Model\AddressAdditionalDataProcessor', [], [], '', false); - $this->quoteRepository = $this->getMock('Magento\Quote\Model\QuoteRepository', [], [], '', false); - - $this->model = $this->objectManager->getObject( - 'Magento\Quote\Model\AddressDetailsManagement', - [ - 'billingAddressManagement' => $this->billingAddressManagement, - 'shippingAddressManagement' => $this->shippingAddressManagement, - 'paymentMethodManagement' => $this->paymentMethodManagement, - 'shippingMethodManagement' => $this->shippingMethodManagement, - 'addressDetailsFactory' => $this->addressDetailsFactory, - 'dataProcessor' => $this->dataProcessor, - 'quoteRepository' => $this->quoteRepository, - ] - ); - } - - public function testSaveAddresses() - { - $cartId = 100; - $additionalData = $this->getMock('\Magento\Quote\Api\Data\AddressAdditionalDataInterface'); - $billingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', [], [], '', false); - $shippingAddressMock = $this->getMock('\Magento\Quote\Model\Quote\Address', [], [], '', false); - - $this->billingAddressManagement->expects($this->once()) - ->method('assign') - ->with($cartId, $billingAddressMock) - ->willReturn(1); - - $billingAddressMock->expects($this->once())->method('format')->with('html'); - $this->billingAddressManagement->expects($this->once()) - ->method('get') - ->with($cartId) - ->willReturn($billingAddressMock); - - $this->shippingAddressManagement->expects($this->once()) - ->method('assign') - ->with($cartId, $shippingAddressMock) - ->willReturn(1); - - $shippingAddressMock->expects($this->once())->method('format')->with('html'); - $this->shippingAddressManagement->expects($this->once()) - ->method('get') - ->with($cartId) - ->willReturn($shippingAddressMock); - - $shippingMethodMock = $this->getMock('\Magento\Quote\Api\Data\ShippingMethodInterface'); - $this->shippingMethodManagement->expects($this->once()) - ->method('getList') - ->with($cartId) - ->willReturn([$shippingMethodMock]); - $paymentMethodMock = $this->getMock('\Magento\Quote\Api\Data\PaymentMethodInterface'); - $this->paymentMethodManagement->expects($this->once()) - ->method('getList') - ->with($cartId) - ->willReturn([$paymentMethodMock]); - - $addressDetailsMock = $this->getMock('\Magento\Quote\Model\AddressDetails', [], [], '', false); - $this->addressDetailsFactory->expects($this->once())->method('create')->willReturn($addressDetailsMock); - - $addressDetailsMock->expects($this->once()) - ->method('setShippingMethods') - ->with([$shippingMethodMock]) - ->willReturnSelf(); - $addressDetailsMock->expects($this->once()) - ->method('setPaymentMethods') - ->with([$paymentMethodMock]) - ->willReturnSelf(); - $this->dataProcessor->expects($this->once())->method('process')->with($additionalData); - - $quote = $this->getMock('Magento\Quote\Model\Quote', [], [], '', false); - $quote->expects($this->once()) - ->method('setCheckoutMethod') - ->willReturnSelf(); - - $this->quoteRepository - ->expects($this->once()) - ->method('getActive') - ->willReturn($quote); - - $this->model->saveAddresses($cartId, $billingAddressMock, $shippingAddressMock, $additionalData, 'register'); - } -} diff --git a/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php b/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b9770ab17fc4d02eb7d75838f4104acf4f41735b --- /dev/null +++ b/app/code/Magento/Quote/Test/Unit/Model/Cart/Totals/ItemConverterTest.php @@ -0,0 +1,91 @@ +<?php +/** + * + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Quote\Test\Unit\Model\Cart\Totals; + +class ItemConverterTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $configPoolMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $totalsFactoryMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $dataObjectHelperMock; + + /** + * @var \Magento\Quote\Model\Cart\Totals\ItemConverter + */ + private $model; + + public function setUp() + { + $this->configPoolMock = $this->getMock('Magento\Catalog\Helper\Product\ConfigurationPool', [], [], '', false); + $this->eventManagerMock = $this->getMock('Magento\Framework\Event\ManagerInterface'); + $this->dataObjectHelperMock = $this->getMock('Magento\Framework\Api\DataObjectHelper', [], [], '', false); + $this->totalsFactoryMock = $this->getMock( + 'Magento\Quote\Api\Data\TotalsItemInterfaceFactory', + ['create'], + [], + '', + false + ); + + $this->model = new \Magento\Quote\Model\Cart\Totals\ItemConverter( + $this->configPoolMock, + $this->eventManagerMock, + $this->totalsFactoryMock, + $this->dataObjectHelperMock + ); + } + + public function testModelToDataObject() + { + $productType = 'simple'; + + $itemMock = $this->getMock('Magento\Quote\Model\Quote\Item', [], [], '', false); + $itemMock->expects($this->once())->method('toArray')->will($this->returnValue(['options' => []])); + $itemMock->expects($this->any())->method('getProductType')->will($this->returnValue($productType)); + + $simpleConfigMock = $this->getMock('Magento\Catalog\Helper\Product\Configuration', [], [], '', false); + $defaultConfigMock = $this->getMock('Magento\Catalog\Helper\Product\Configuration', [], [], '', false); + + $this->configPoolMock->expects($this->any())->method('getByProductType') + ->will($this->returnValueMap([['simple', $simpleConfigMock], ['default', $defaultConfigMock]])); + + $options = ['1' => ['label' => 'option1'], '2' => ['label' => 'option2']]; + $simpleConfigMock->expects($this->once())->method('getOptions')->with($itemMock) + ->will($this->returnValue($options)); + + $option = ['data' => 'optionsData', 'label' => '']; + $defaultConfigMock->expects($this->any())->method('getFormattedOptionValue')->will($this->returnValue($option)); + + $this->eventManagerMock->expects($this->once())->method('dispatch') + ->with('items_additional_data', ['item' => $itemMock]); + + $this->totalsFactoryMock->expects($this->once())->method('create'); + + $expectedData = [ + 'options' => '{"1":{"data":"optionsData","label":"option1"},"2":{"data":"optionsData","label":"option2"}}' + ]; + $this->dataObjectHelperMock->expects($this->once())->method('populateWithArray') + ->with(null, $expectedData, '\Magento\Quote\Api\Data\TotalsItemInterface'); + + $this->model->modelToDataObject($itemMock); + } +} diff --git a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php index 56885a81d78648500927d8b77992e9cddea8a2ee..287aaaa980f7ae354b3726adaea44f2e893cdbfc 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/QuoteManagementTest.php @@ -717,47 +717,10 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase $this->checkoutSessionMock->expects($this->once())->method('setLastSuccessQuoteId')->with($cartId); $this->checkoutSessionMock->expects($this->once())->method('setLastOrderId')->with($orderId); $this->checkoutSessionMock->expects($this->once())->method('setLastRealOrderId')->with($orderIncrementId); - $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(true); $this->assertEquals($orderId, $service->placeOrder($cartId)); } - /** - * @expectedException \Magento\Framework\Exception\CouldNotSaveException - */ - public function testPlaceOrderIfAgreementsIsNotValid() - { - $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(false); - - /** @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Quote\Model\QuoteManagement $service */ - $service = $this->getMock( - '\Magento\Quote\Model\QuoteManagement', - ['submit'], - [ - 'eventManager' => $this->eventManager, - 'quoteValidator' => $this->quoteValidator, - 'orderFactory' => $this->orderFactory, - 'orderManagement' => $this->orderManagement, - 'customerManagement' => $this->customerManagement, - 'quoteAddressToOrder' => $this->quoteAddressToOrder, - 'quoteAddressToOrderAddress' => $this->quoteAddressToOrderAddress, - 'quoteItemToOrderItem' => $this->quoteItemToOrderItem, - 'quotePaymentToOrderPayment' => $this->quotePaymentToOrderPayment, - 'userContext' => $this->userContextMock, - 'quoteRepository' => $this->quoteRepositoryMock, - 'customerRepository' => $this->customerRepositoryMock, - 'customerModelFactory' => $this->customerFactoryMock, - 'dataObjectHelper' => $this->dataObjectHelperMock, - 'storeManager' => $this->storeManagerMock, - 'checkoutSession' => $this->checkoutSessionMock, - 'customerSession' => $this->customerSessionMock, - 'accountManagement' => $this->accountManagementMock, - 'agreementsValidator' => $this->agreementsValidatorMock, - ] - ); - $service->placeOrder(45); - } - public function testPlaceOrder() { $cartId = 323; @@ -829,7 +792,6 @@ class QuoteManagementTest extends \PHPUnit_Framework_TestCase $this->checkoutSessionMock->expects($this->once())->method('setLastSuccessQuoteId')->with($cartId); $this->checkoutSessionMock->expects($this->once())->method('setLastOrderId')->with($orderId); $this->checkoutSessionMock->expects($this->once())->method('setLastRealOrderId')->with($orderIncrementId); - $this->agreementsValidatorMock->expects($this->once())->method('isValid')->willReturn(true); $paymentMethod = $this->getMock('Magento\Quote\Model\Quote\Payment', ['setChecks', 'getData'], [], '', false); $paymentMethod->expects($this->once())->method('setChecks'); diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php index 4c5bffe80077615734f94e7df2f3cee0f0c61f4d..2fea9a5b9a15c1c67d7bcf85e49814f90162f5f6 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingAddressManagementTest.php @@ -32,6 +32,11 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase */ protected $validatorMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $scopeConfigMock; + /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ @@ -41,6 +46,7 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->quoteRepositoryMock = $this->getMock('\Magento\Quote\Model\QuoteRepository', [], [], '', false); + $this->scopeConfigMock = $this->getMock('Magento\Framework\App\Config\ScopeConfigInterface'); $this->quoteAddressMock = $this->getMock( '\Magento\Quote\Model\Quote\Address', @@ -66,7 +72,8 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase [ 'quoteRepository' => $this->quoteRepositoryMock, 'addressValidator' => $this->validatorMock, - 'logger' => $this->getMock('\Psr\Log\LoggerInterface') + 'logger' => $this->getMock('\Psr\Log\LoggerInterface'), + 'scopeConfig' => $this->scopeConfigMock ] ); } @@ -167,6 +174,28 @@ class ShippingAddressManagementTest extends \PHPUnit_Framework_TestCase $this->service->assign('cart867', $this->quoteAddressMock); } + /** + * @expectedException \Magento\Framework\Exception\InputException + */ + public function testSetAddressWithViolationOfMinimumAmount() + { + $storeId = 12; + $this->quoteAddressMock->expects($this->once())->method('collectTotals')->willReturnSelf(); + $this->quoteAddressMock->expects($this->once())->method('save'); + + $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false); + $this->quoteRepositoryMock->expects($this->once())->method('getActive')->with('cart123') + ->will($this->returnValue($quoteMock)); + $quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); + $quoteMock->expects($this->once())->method('getShippingAddress')->willReturn($this->quoteAddressMock); + $quoteMock->expects($this->any())->method('getStoreId')->will($this->returnValue($storeId)); + + $this->scopeConfigMock->expects($this->once())->method('getValue') + ->with('sales/minimum_order/error_message', \Magento\Store\Model\ScopeInterface::SCOPE_STORE, $storeId); + + $this->service->assign('cart123', $this->quoteAddressMock); + } + public function testGetAddress() { $quoteMock = $this->getMock('\Magento\Quote\Model\Quote', [], [], '', false); diff --git a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php index ef5992e11f7af3c0dbedf4f7b8d263a12cf1804e..fd760977a6c89f57308b2142d4acd827af06bfa4 100644 --- a/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php +++ b/app/code/Magento/Quote/Test/Unit/Model/ShippingMethodManagementTest.php @@ -316,39 +316,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase $this->model->set($cartId, $carrierCode, $methodCode); } - /** - * @expectedException \Magento\Framework\Exception\StateException - * @expectedExceptionMessage Billing address is not set - */ - public function testSetMethodWithoutBillingAddress() - { - $cartId = 12; - $carrierCode = 34; - $methodCode = 56; - $countryId = 1; - - $this->quoteRepositoryMock->expects($this->once()) - ->method('getActive')->with($cartId)->will($this->returnValue($this->quoteMock)); - $this->quoteMock->expects($this->once())->method('getItemsCount')->will($this->returnValue(1)); - $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); - $this->quoteMock->expects($this->once()) - ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock)); - $this->shippingAddressMock->expects($this->once()) - ->method('getCountryId')->will($this->returnValue($countryId)); - $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', - ['getCountryId', '__wakeup'], - [], - '', - false - ); - $this->quoteMock->expects($this->once()) - ->method('getBillingAddress')->will($this->returnValue($billingAddressMock)); - $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(null)); - - $this->model->set($cartId, $carrierCode, $methodCode); - } - /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException * @expectedExceptionMessage Carrier with such method not found: 34, 56 @@ -365,16 +332,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); $this->quoteMock->expects($this->once()) ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock)); - $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', - ['getCountryId', '__wakeup'], - [], - '', - false - ); - $this->quoteMock->expects($this->once()) - ->method('getBillingAddress')->will($this->returnValue($billingAddressMock)); - $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23)); $this->shippingAddressMock->expects($this->once()) ->method('getCountryId')->will($this->returnValue($countryId)); $this->shippingAddressMock->expects($this->once()) @@ -405,19 +362,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock)); $this->shippingAddressMock->expects($this->once()) ->method('getCountryId')->will($this->returnValue($countryId)); - $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', - [ - 'getCountryId', - '__wakeup' - ], - [], - '', - false - ); - $this->quoteMock->expects($this->once()) - ->method('getBillingAddress')->will($this->returnValue($billingAddressMock)); - $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23)); $this->shippingAddressMock->expects($this->once()) ->method('setShippingMethod')->with($carrierCode . '_' . $methodCode); $this->shippingAddressMock->expects($this->once()) @@ -464,19 +408,6 @@ class ShippingMethodManagementTest extends \PHPUnit_Framework_TestCase $this->quoteMock->expects($this->once())->method('isVirtual')->will($this->returnValue(false)); $this->quoteMock->expects($this->once()) ->method('getShippingAddress')->will($this->returnValue($this->shippingAddressMock)); - $billingAddressMock = $this->getMock( - '\Magento\Quote\Model\Quote\Address', - [ - 'getCountryId', - '__wakeup' - ], - [], - '', - false - ); - $this->quoteMock->expects($this->once()) - ->method('getBillingAddress')->will($this->returnValue($billingAddressMock)); - $billingAddressMock->expects($this->once())->method('getCountryId')->will($this->returnValue(23)); $this->shippingAddressMock->expects($this->once()) ->method('getCountryId')->will($this->returnValue($countryId)); $this->shippingAddressMock->expects($this->once()) diff --git a/app/code/Magento/Quote/etc/di.xml b/app/code/Magento/Quote/etc/di.xml index 66cae592e21018589902a907529cbcc87007c8e4..0c3b51e3a5ddc2e2a5c3b6991de7eb92629c999b 100644 --- a/app/code/Magento/Quote/etc/di.xml +++ b/app/code/Magento/Quote/etc/di.xml @@ -24,6 +24,7 @@ <preference for="Magento\Quote\Api\CartTotalRepositoryInterface" type="\Magento\Quote\Model\Cart\CartTotalRepository" /> <preference for="Magento\Quote\Api\CartTotalManagementInterface" type="\Magento\Quote\Model\Cart\CartTotalManagement" /> <preference for="Magento\Quote\Api\Data\TotalsInterface" type="\Magento\Quote\Model\Cart\Totals" /> + <preference for="Magento\Quote\Api\Data\TotalSegmentInterface" type="\Magento\Quote\Model\Cart\TotalSegment" /> <preference for="Magento\Quote\Api\Data\TotalsItemInterface" type="\Magento\Quote\Model\Cart\Totals\Item" /> <preference for="Magento\Quote\Api\Data\CurrencyInterface" type="\Magento\Quote\Model\Cart\Currency" /> <preference for="Magento\Quote\Api\GuestCartManagementInterface" type="Magento\Quote\Model\GuestCart\GuestCartManagement" /> @@ -35,7 +36,6 @@ <preference for="Magento\Quote\Api\GuestShippingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingAddressManagement" /> <preference for="Magento\Quote\Api\GuestShippingMethodManagementInterface" type="Magento\Quote\Model\GuestCart\GuestShippingMethodManagement" /> <preference for="Magento\Quote\Api\GuestBillingAddressManagementInterface" type="Magento\Quote\Model\GuestCart\GuestBillingAddressManagement" /> - <preference for="Magento\Quote\Api\GuestAddressDetailsManagementInterface" type="Magento\Quote\Model\GuestCart\GuestAddressDetailsManagement" /> <preference for="Magento\Quote\Api\GuestCartTotalManagementInterface" type="\Magento\Quote\Model\GuestCart\GuestCartTotalManagement" /> <preference for="Magento\Quote\Api\Data\EstimateAddressInterface" type="Magento\Quote\Model\EstimateAddress" /> <type name="Magento\Webapi\Controller\Rest\ParamsOverrider"> @@ -55,8 +55,6 @@ <argument name="addressConfig" xsi:type="object">Magento\Customer\Model\Address\Config\Proxy</argument> </arguments> </type> - <preference for="Magento\Quote\Api\AddressDetailsManagementInterface" type="Magento\Quote\Model\AddressDetailsManagement" /> - <preference for="Magento\Quote\Api\Data\AddressDetailsInterface" type="Magento\Quote\Model\AddressDetails" /> <preference for="Magento\Quote\Api\Data\AddressAdditionalDataInterface" type="Magento\Quote\Model\AddressAdditionalData" /> <preference for="Magento\Quote\Api\Data\TotalsAdditionalDataInterface" type="Magento\Quote\Model\Cart\TotalsAdditionalData" /> <preference for="\Magento\Quote\Model\Quote\Address\CustomAttributeListInterface" type="\Magento\Quote\Model\Quote\Address\CustomAttributeList" /> diff --git a/app/code/Magento/Quote/etc/webapi.xml b/app/code/Magento/Quote/etc/webapi.xml index 9b6ca15468d654d70622b0dba27d47a02f5f806d..8e5e097a995cd6aa38aa77f568f2c0ba97f1d9cd 100644 --- a/app/code/Magento/Quote/etc/webapi.xml +++ b/app/code/Magento/Quote/etc/webapi.xml @@ -145,6 +145,24 @@ <parameter name="cartId" force="true">%cart_id%</parameter> </data> </route> + <route url="/V1/carts/mine/estimate-shipping-methods" method="POST"> + <service class="Magento\Quote\Api\ShippingMethodManagementInterface" method="estimateByAddress"/> + <resources> + <resource ref="self" /> + </resources> + <data> + <parameter name="cartId" force="true">%cart_id%</parameter> + </data> + </route> + <route url="/V1/carts/mine/estimate-shipping-methods-by-address-id" method="POST"> + <service class="Magento\Quote\Api\ShippingMethodManagementInterface" method="estimateByAddressId"/> + <resources> + <resource ref="self" /> + </resources> + <data> + <parameter name="cartId" force="true">%cart_id%</parameter> + </data> + </route> <!-- Managing Guest Cart Shipment Method --> <route url="/V1/guest-carts/:cartId/selected-shipping-method" method="PUT"> @@ -165,6 +183,12 @@ <resource ref="anonymous" /> </resources> </route> + <route url="/V1/guest-carts/:cartId/estimate-shipping-methods" method="POST"> + <service class="Magento\Quote\Api\GuestShippingMethodManagementInterface" method="estimateByAddress"/> + <resources> + <resource ref="anonymous" /> + </resources> + </route> <!-- Managing Cart Items --> <route url="/V1/carts/:cartId/items" method="GET"> @@ -352,12 +376,6 @@ <resource ref="anonymous" /> </resources> </route> - <route url="/V1/guest-carts/:cartId/addresses" method="POST"> - <service class="Magento\Quote\Api\GuestAddressDetailsManagementInterface" method="saveAddresses"/> - <resources> - <resource ref="anonymous" /> - </resources> - </route> <!-- Managing My Cart Billing address --> <route url="/V1/carts/mine/billing-address" method="GET"> @@ -495,15 +513,6 @@ <parameter name="cartId" force="true">%cart_id%</parameter> </data> </route> - <route url="/V1/carts/mine/addresses" method="POST"> - <service class="Magento\Quote\Api\AddressDetailsManagementInterface" method="saveAddresses"/> - <resources> - <resource ref="self" /> - </resources> - <data> - <parameter name="cartId" force="true">%cart_id%</parameter> - </data> - </route> <!-- Managing Cart Order --> <route url="/V1/carts/:cartId/order" method="PUT"> diff --git a/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..b9ba81bfaa8ec98f6f906d86cc704b184ee417ff --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="billing-step" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="children" xsi:type="array"> + <item name="payment" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="afterMethods" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="store-credit" xsi:type="array"> + <item name="component" xsi:type="string">Magento_SalesRule/js/view/payment/discount</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + <item name="summary" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="totals" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="discount" xsi:type="array"> + <item name="component" xsi:type="string">Magento_SalesRule/js/view/summary/discount</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Discount</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> \ No newline at end of file diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js new file mode 100644 index 0000000000000000000000000000000000000000..80a6488fb285a34fcf91dc07693843ce731ed85f --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/cancel-coupon.js @@ -0,0 +1,51 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Customer store credit(balance) application + */ +/*global define,alert*/ +define( + [ + 'ko', + 'jquery', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/resource-url-manager', + 'Magento_Checkout/js/model/payment-service', + 'Magento_Ui/js/model/messageList', + 'mage/storage', + 'Magento_Checkout/js/action/get-totals' + ], + function (ko, $, quote, urlManager, paymentService, messageList, storage, getTotalsAction) { + 'use strict'; + return function (isApplied, isLoading) { + var quoteId = quote.getQuoteId(); + var url = urlManager.getCancelCouponUrl(quoteId); + return storage.delete( + url, + false + ).done( + function (response) { + isLoading(false); + var deferred = $.Deferred(); + + getTotalsAction([], deferred); + $.when(deferred).done(function() { + isApplied(false); + paymentService.setPaymentMethods( + paymentService.getAvailablePaymentMethods() + ); + }); + } + ).error( + function (response) { + isLoading(false); + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + } + ); + }; + } +); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js new file mode 100644 index 0000000000000000000000000000000000000000..a76500e4517208b0a166af5a7162b17ddcad9099 --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/action/set-coupon-code.js @@ -0,0 +1,54 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +/** + * Customer store credit(balance) application + */ +/*global define,alert*/ +define( + [ + 'ko', + 'jquery', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/resource-url-manager', + 'Magento_Checkout/js/model/payment-service', + 'Magento_Ui/js/model/messageList', + 'mage/storage', + 'Magento_Checkout/js/action/get-totals' + ], + function (ko, $, quote, urlManager, paymentService, messageList, storage, getTotalsAction) { + 'use strict'; + return function (couponCode, isApplied, isLoading) { + var quoteId = quote.getQuoteId(); + var url = urlManager.getApplyCouponUrl(couponCode, quoteId); + return storage.put( + url, + {}, + false + ).done( + function (response) { + if (response) { + isLoading(false); + isApplied(true); + var deferred = $.Deferred(); + + getTotalsAction([], deferred); + $.when(deferred).done(function() { + paymentService.setPaymentMethods( + paymentService.getAvailablePaymentMethods() + ); + }); + } + } + ).error( + function (response) { + isLoading(false); + var error = JSON.parse(response.responseText); + messageList.addErrorMessage(error); + } + ); + }; + } +); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js new file mode 100644 index 0000000000000000000000000000000000000000..ddbce5003a402df4de8db9b23a181beed36c7a59 --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/payment/discount.js @@ -0,0 +1,63 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define( + [ + 'jquery', + 'ko', + 'uiComponent', + 'Magento_Checkout/js/model/quote', + 'Magento_SalesRule/js/action/set-coupon-code', + 'Magento_SalesRule/js/action/cancel-coupon' + ], + function ($, ko, Component, quote, setCouponCodeAction, cancelCouponAction) { + 'use strict'; + var totals = quote.getTotals(); + var couponCode = ko.observable(null); + if (totals()) { + couponCode(totals()['coupon_code']); + } + var isApplied = ko.observable(couponCode() != null); + var isLoading = ko.observable(false); + return Component.extend({ + defaults: { + template: 'Magento_SalesRule/payment/discount' + }, + couponCode: couponCode, + /** + * Applied flag + */ + isApplied: isApplied, + isLoading: isLoading, + /** + * Coupon code application procedure + */ + apply: function() { + if (this.validate()) { + isLoading(true); + setCouponCodeAction(couponCode(), isApplied, isLoading); + } + }, + /** + * Cancel using coupon + */ + cancel: function() { + if (this.validate()) { + isLoading(true); + couponCode(''); + cancelCouponAction(isApplied, isLoading); + } + }, + /** + * Coupon form validation + * + * @returns {boolean} + */ + validate: function() { + var form = '#discount-form'; + return $(form).validation() && $(form).validation('isValid'); + } + }); + } +); diff --git a/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js new file mode 100644 index 0000000000000000000000000000000000000000..8558966cd71e5aa7af00dc70ba339179ce9d4917 --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/js/view/summary/discount.js @@ -0,0 +1,39 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote', + ], + function (Component, quote) { + "use strict"; + return Component.extend({ + defaults: { + template: 'Magento_SalesRule/summary/discount' + }, + totals: quote.getTotals(), + isDisplayed: function() { + return this.isFullMode() && this.getPureValue() != 0; + }, + getCouponCode: function() { + if (!this.totals()) { + return null; + } + return this.totals()['coupon_code']; + }, + getPureValue: function() { + var price = 0; + if (this.totals() && this.totals().discount_amount) { + price = parseFloat(this.totals().discount_amount); + } + return price; + }, + getValue: function() { + return this.getFormattedPrice(this.getPureValue()); + } + }); + } +); diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html new file mode 100644 index 0000000000000000000000000000000000000000..92041308eada737fc81f6ab15b7bad6e0e041e8f --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/template/payment/discount.html @@ -0,0 +1,47 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="payment-option _collapsible opc-payment-additional discount-code" + data-bind="mageInit: {'collapsible':{'openedState': '_active'}}"> + <div class="payment-option-title field choice" data-role="title"> + <span class="action action-toggle" id="block-discount-heading" role="heading" aria-level="2"> + <!-- ko text: $t('Apply promo code')--><!-- /ko --> + </span> + </div> + <div class="payment-option-content" data-role="content"> + <form class="form form-discount" id="discount-form" data-bind="blockLoader: isLoading"> + <div class="payment-option-inner"> + <div class="field"> + <label class="label" for="discount-code"> + <span data-bind="text: $t('Enter promo code')"></span> + </label> + <div class="control"> + <input class="input-text" + type="text" + id="discount-code" + name="discount_code" + data-validate="{'required-entry':true}" + data-bind="value: couponCode, attr:{placeholder: $t('Enter promo code')} " /> + </div> + </div> + </div> + <div class="actions-toolbar"> + <div class="primary"> + <!-- ko ifnot: isApplied() --> + <button class="action action-apply" type="submit" data-bind="'value': $t('Apply'), click: apply"> + <span><!-- ko text: $t('Apply')--><!-- /ko --></span> + </button> + <!-- /ko --> + <!-- ko if: isApplied() --> + <button class="action action-cancel" type="submit" data-bind="'value': $t('Cancel'), click: cancel"> + <span><!-- ko text: $t('Cancel coupon')--><!-- /ko --></span> + </button> + <!-- /ko --> + </div> + </div> + </form> + </div> +</div> diff --git a/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html new file mode 100644 index 0000000000000000000000000000000000000000..60ac9c7982a5f6a0a510abd25fb67e4ee11dc13a --- /dev/null +++ b/app/code/Magento/SalesRule/view/frontend/web/template/summary/discount.html @@ -0,0 +1,17 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: isDisplayed() --> +<tr class="totals discount"> + <th class="mark" scope="row"> + <span class="title" data-bind="text: title"></span> + <span class="discount coupon" data-bind="text: getCouponCode()"></span> + </th> + <td class="amount"> + <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(name) }"></span> + </td> +</tr> +<!-- /ko --> diff --git a/app/code/Magento/Shipping/etc/acl.xml b/app/code/Magento/Shipping/etc/acl.xml index 74811607f3d06fbc8d002fa03dc27d47a0be0f59..feacd4d501dc3da36c629f277754c456eb7f6762 100644 --- a/app/code/Magento/Shipping/etc/acl.xml +++ b/app/code/Magento/Shipping/etc/acl.xml @@ -13,6 +13,7 @@ <resource id="Magento_Backend::stores_settings"> <resource id="Magento_Config::config"> <resource id="Magento_Shipping::config_shipping" title="Shipping Settings Section" sortOrder="5" /> + <resource id="Magento_Shipping::shipping_policy" title="Shipping Policy Parameters Section" sortOrder="5" /> <resource id="Magento_Shipping::carriers" title="Shipping Methods Section" sortOrder="5" /> </resource> </resource> diff --git a/app/code/Magento/Shipping/etc/adminhtml/system.xml b/app/code/Magento/Shipping/etc/adminhtml/system.xml index 40e4568907c17aa71bd790790b3ea912932eb260..5b56b96f719b7fbd3270e7b253dab0b1f862205d 100644 --- a/app/code/Magento/Shipping/etc/adminhtml/system.xml +++ b/app/code/Magento/Shipping/etc/adminhtml/system.xml @@ -7,7 +7,7 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../Config/etc/system_file.xsd"> <system> - <section id="shipping" translate="label" type="text" sortOrder="310" showInDefault="1" showInWebsite="1" showInStore="0"> + <section id="shipping" translate="label" type="text" sortOrder="310" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Shipping Settings</label> <tab>sales</tab> <resource>Magento_Shipping::config_shipping</resource> @@ -34,6 +34,19 @@ <label>Street Address Line 2</label> </field> </group> + <group id="shipping_policy" translate="label" type="text" sortOrder="120" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Shipping Policy Parameters</label> + <field id="enable_shipping_policy" translate="label" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0"> + <label>Apply custom Shipping Policy</label> + <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> + </field> + <field id="shipping_policy_content" translate="label" type="textarea" sortOrder="2" showInDefault="1" showInWebsite="1" showInStore="1"> + <label>Shipping Policy</label> + <depends> + <field id="enable_shipping_policy">1</field> + </depends> + </field> + </group> </section> <section id="carriers" translate="label" type="text" sortOrder="320" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Shipping Methods</label> diff --git a/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..14a25393667d7b7bfe54cce7ba0b750f65b0cfd6 --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shippingAddress" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="before-shipping-method-form" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping_policy" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Shipping/js/view/checkout/shipping/shipping-policy</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Shipping/view/frontend/web/js/model/config.js b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js new file mode 100644 index 0000000000000000000000000000000000000000..d69bd10ae7c674ea543ddd0cb30d97b567ef3056 --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/web/js/model/config.js @@ -0,0 +1,13 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define([], function () { + "use strict"; + return function () { + return window.checkoutConfig.shippingPolicy + } + } +); diff --git a/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js new file mode 100644 index 0000000000000000000000000000000000000000..1a41b1ae5770388c85fa13b76b3fa4abdf2689a7 --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/web/js/view/checkout/shipping/shipping-policy.js @@ -0,0 +1,18 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'uiComponent', + 'Magento_Shipping/js/model/config' + +], function (Component, config) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Magento_Shipping/checkout/shipping/shipping-policy' + }, + config: config() + }); +}); diff --git a/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html new file mode 100644 index 0000000000000000000000000000000000000000..1c0cc5c80e2efc4a25ad4c7f9e52266b569bbb82 --- /dev/null +++ b/app/code/Magento/Shipping/view/frontend/web/template/checkout/shipping/shipping-policy.html @@ -0,0 +1,14 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="shipping-policy-block field-tooltip" data-bind="visible: config.isEnabled"> + <span class="field-tooltip-action"> + <!-- ko text: $t('See our shipping policy') --><!-- /ko --> + </span> + <div class="field-tooltip-content"> + <span data-bind="html: config.shippingPolicyContent"></span> + </div> +</div> diff --git a/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php b/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php index 3fb1e6fd5b28ea248de75a35a11bf4336d10684c..e36af22d214c62161943940fd4e7439596ca4b56 100644 --- a/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php +++ b/app/code/Magento/Tax/Api/Data/GrandTotalDetailsInterface.php @@ -3,11 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Tax\Api\Data; - -interface GrandTotalDetailsInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface GrandTotalDetailsInterface { /** * Get tax amount value @@ -47,21 +45,4 @@ interface GrandTotalDetailsInterface extends \Magento\Framework\Api\ExtensibleDa * @return $this */ public function setGroupId($id); - - /** - * {@inheritdoc} - * - * @return \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * {@inheritdoc} - * - * @param \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes - ); } diff --git a/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php b/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php index f6d39a9d385d5add5389df19846d273fd42f31c9..39dda8c3536fc456bf9ac4d9d22dd9c46d9d2d22 100644 --- a/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php +++ b/app/code/Magento/Tax/Api/Data/GrandTotalRatesInterface.php @@ -3,11 +3,9 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ - namespace Magento\Tax\Api\Data; - -interface GrandTotalRatesInterface extends \Magento\Framework\Api\ExtensibleDataInterface +interface GrandTotalRatesInterface { /** * Get tax percentage value @@ -34,21 +32,4 @@ interface GrandTotalRatesInterface extends \Magento\Framework\Api\ExtensibleData * @return $this */ public function setTitle($title); - - /** - * Retrieve existing extension attributes object or create a new one. - * - * @return \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface|null - */ - public function getExtensionAttributes(); - - /** - * Set an extension attributes object. - * - * @param \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes - ); } diff --git a/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php b/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php index 79cc180e80fceddbf6fde95b704b79c5c09e143b..a3301eb85796a2163d3435005b0a11c80ee6d83a 100644 --- a/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php +++ b/app/code/Magento/Tax/Model/Calculation/GrandTotalDetails.php @@ -7,19 +7,19 @@ namespace Magento\Tax\Model\Calculation; use Magento\Tax\Api\Data\GrandTotalDetailsInterface; -use Magento\Framework\Model\AbstractExtensibleModel; +use Magento\Framework\Api\AbstractSimpleObject; /** * Grand Total Tax Details Model */ -class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDetailsInterface +class GrandTotalDetails extends AbstractSimpleObject implements GrandTotalDetailsInterface { /**#@+ * Constants defined for keys of array, makes typos less likely */ - const AMOUNT = 'amount'; - const RATES = 'rates'; - const GROUP_ID = 'group_id'; + const AMOUNT = 'amount'; + const RATES = 'rates'; + const GROUP_ID = 'group_id'; /**#@-*/ /** @@ -27,7 +27,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet */ public function getGroupId() { - return $this->getData(self::GROUP_ID); + return $this->_get(self::GROUP_ID); } /** @@ -43,7 +43,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet */ public function getAmount() { - return $this->getData(self::AMOUNT); + return $this->_get(self::AMOUNT); } /** @@ -59,7 +59,7 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet */ public function getRates() { - return $this->getData(self::RATES); + return $this->_get(self::RATES); } /** @@ -69,26 +69,4 @@ class GrandTotalDetails extends AbstractExtensibleModel implements GrandTotalDet { return $this->setData(self::RATES, $rates); } - - /** - * {@inheritdoc} - * - * @return \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Tax\Api\Data\GrandTotalDetailsExtensionInterface $extensionAttributes - ) { - return $this->_setExtensionAttributes($extensionAttributes); - } } diff --git a/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php b/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php index 4c23c6444d7236a25ebf661b9d5d75a53f0fa829..b7be0cc4a3d36ab0aa5ae35cd8286245064d62d8 100644 --- a/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php +++ b/app/code/Magento/Tax/Model/Calculation/GrandTotalRates.php @@ -7,12 +7,12 @@ namespace Magento\Tax\Model\Calculation; use Magento\Tax\Api\Data\GrandTotalRatesInterface; -use Magento\Framework\Model\AbstractExtensibleModel; +use Magento\Framework\Api\AbstractSimpleObject; /** * Grand Total Tax Details Model */ -class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRatesInterface +class GrandTotalRates extends AbstractSimpleObject implements GrandTotalRatesInterface { /**#@+ * Constants defined for keys of array, makes typos less likely @@ -26,7 +26,7 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates */ public function getTitle() { - return $this->getData(self::TITLE); + return $this->_get(self::TITLE); } /** @@ -42,7 +42,7 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates */ public function getPercent() { - return $this->getData(self::PERCENT); + return $this->_get(self::PERCENT); } /** @@ -52,26 +52,4 @@ class GrandTotalRates extends AbstractExtensibleModel implements GrandTotalRates { return $this->setData(self::PERCENT, $percent); } - - /** - * {@inheritdoc} - * - * @return \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface|null - */ - public function getExtensionAttributes() - { - return $this->_getExtensionAttributes(); - } - - /** - * {@inheritdoc} - * - * @param \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes - * @return $this - */ - public function setExtensionAttributes( - \Magento\Tax\Api\Data\GrandTotalRatesExtensionInterface $extensionAttributes - ) { - return $this->_setExtensionAttributes($extensionAttributes); - } } diff --git a/app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php similarity index 87% rename from app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php rename to app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php index e20684a73b880754f7285dbe561485e298361d28..1de7b6d223d5648f009b1598917b54d46dc6643c 100644 --- a/app/code/Magento/Tax/Model/Quote/GrandTotalDetails.php +++ b/app/code/Magento/Tax/Model/Quote/GrandTotalDetailsPlugin.php @@ -6,8 +6,9 @@ namespace Magento\Tax\Model\Quote; use Magento\Quote\Model\Cart\CartTotalRepository; +use Magento\Quote\Api\Data\TotalsExtensionFactory; -class GrandTotalDetails +class GrandTotalDetailsPlugin { /** * @var \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory @@ -20,7 +21,7 @@ class GrandTotalDetails protected $ratesFactory; /** - * @var \Magento\Framework\Api\ExtensionAttributesFactory + * @var TotalsExtensionFactory */ protected $extensionFactory; @@ -42,7 +43,7 @@ class GrandTotalDetails /** * @param \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory $detailsFactory * @param \Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory $ratesFactory - * @param \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory + * @param TotalsExtensionFactory $extensionFactory * @param \Magento\Tax\Model\Config $taxConfig * @param \Magento\Quote\Model\Quote\Address\Total\Tax $taxTotal * @param \Magento\Quote\Model\QuoteRepository $quoteRepository @@ -50,7 +51,7 @@ class GrandTotalDetails public function __construct( \Magento\Tax\Api\Data\GrandTotalDetailsInterfaceFactory $detailsFactory, \Magento\Tax\Api\Data\GrandTotalRatesInterfaceFactory $ratesFactory, - \Magento\Framework\Api\ExtensionAttributesFactory $extensionFactory, + TotalsExtensionFactory $extensionFactory, \Magento\Tax\Model\Config $taxConfig, \Magento\Quote\Model\Quote\Address\Total\Tax $taxTotal, \Magento\Quote\Model\QuoteRepository $quoteRepository @@ -81,7 +82,7 @@ class GrandTotalDetails /** * @param CartTotalRepository $subject - * @param callable $proceed + * @param \Closure $proceed * @param int $cartId * @return \Magento\Quote\Model\Cart\Totals * @throws \Magento\Framework\Exception\NoSuchEntityException @@ -119,11 +120,13 @@ class GrandTotalDetails $finalData[] = $taxDetails; $detailsId++; } - $taxInfo = $this->extensionFactory->create('\\Magento\\Quote\\Model\\Cart\\Totals', []); - $taxInfo->setTaxGrandtotalDetails($finalData); + $attributes = $result->getExtensionAttributes(); + if ($attributes === null) { + $attributes = $this->extensionFactory->create(); + } + $attributes->setTaxGrandtotalDetails($finalData); /** @var $result \Magento\Quote\Model\Cart\Totals */ - $result->setExtensionAttributes($taxInfo); - $result->setTaxAmount($taxes['value']); + $result->setExtensionAttributes($attributes); return $result; } } diff --git a/app/code/Magento/Tax/Model/TaxConfigProvider.php b/app/code/Magento/Tax/Model/TaxConfigProvider.php index 4f40850d8bfb1657011a84f9d135076b82b4f9a4..8ce354850537f39125869c4f4baf5b01161c19ee 100644 --- a/app/code/Magento/Tax/Model/TaxConfigProvider.php +++ b/app/code/Magento/Tax/Model/TaxConfigProvider.php @@ -43,6 +43,7 @@ class TaxConfigProvider implements ConfigProviderInterface 'reviewTotalsDisplayMode' => $this->getReviewTotalsDisplayMode(), 'includeTaxInGrandTotal' => $this->isTaxDisplayedInGrandTotal(), 'isFullTaxSummaryDisplayed' => $this->isFullTaxSummaryDisplayed(), + 'isZeroTaxDisplayed' => $this->taxConfig->displayCartZeroTax(), ]; } diff --git a/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cad8010f39cf0056c67efb00f98d427cdbbc9d9a --- /dev/null +++ b/app/code/Magento/Tax/Test/Unit/Model/TaxConfigProviderTest.php @@ -0,0 +1,197 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Tax\Test\Unit\Model; + +class TaxConfigProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $taxHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $taxConfigMock; + + /** + * @var \Magento\Tax\Model\TaxConfigProvider + */ + protected $model; + + protected function setUp() + { + $this->taxHelperMock = $this->getMock('Magento\Tax\Helper\Data', [], [], '', false); + $this->taxConfigMock = $this->getMock('Magento\Tax\Model\Config', [], [], '', false); + + $this->model = new \Magento\Tax\Model\TaxConfigProvider($this->taxHelperMock, $this->taxConfigMock); + } + + /** + * @dataProvider getConfigDataProvider + * @param array $expectedResult + * @param int $cartShippingBoth + * @param int $cartShippingExclTax + * @param int $cartBothPrices + * @param int $cartPriceExclTax + * @param int $cartSubTotalBoth + * @param int $cartSubTotalExclTax + */ + public function testGetConfig( + $expectedResult, + $cartShippingBoth, + $cartShippingExclTax, + $cartBothPrices, + $cartPriceExclTax, + $cartSubTotalBoth, + $cartSubTotalExclTax + ) { + $this->taxConfigMock->expects($this->any())->method('displayCartShippingBoth') + ->will($this->returnValue($cartShippingBoth)); + $this->taxConfigMock->expects($this->any())->method('displayCartShippingExclTax') + ->will($this->returnValue($cartShippingExclTax)); + + $this->taxHelperMock->expects($this->any())->method('displayCartBothPrices') + ->will($this->returnValue($cartBothPrices)); + $this->taxHelperMock->expects($this->any())->method('displayCartPriceExclTax') + ->will($this->returnValue($cartPriceExclTax)); + + $this->taxConfigMock->expects($this->any())->method('displayCartSubtotalBoth') + ->will($this->returnValue($cartSubTotalBoth)); + $this->taxConfigMock->expects($this->any())->method('displayCartSubtotalExclTax') + ->will($this->returnValue($cartSubTotalExclTax)); + + $this->taxHelperMock->expects(($this->any()))->method('displayShippingPriceExcludingTax') + ->will($this->returnValue(1)); + $this->taxHelperMock->expects(($this->any()))->method('displayShippingBothPrices') + ->will($this->returnValue(1)); + $this->taxHelperMock->expects(($this->any()))->method('displayFullSummary') + ->will($this->returnValue(1)); + $this->taxConfigMock->expects(($this->any()))->method('displayCartTaxWithGrandTotal') + ->will($this->returnValue(1)); + $this->taxConfigMock->expects(($this->any()))->method('displayCartZeroTax') + ->will($this->returnValue(1)); + $this->assertEquals($expectedResult, $this->model->getConfig()); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function getConfigDataProvider() + { + return [ + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'both', + 'reviewItemPriceDisplayMode' => 'both', + 'reviewTotalsDisplayMode' => 'both', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 1, + 'cartShippingExclTax' => 1, + 'cartBothPrices' => 1, + 'cartPriceExclTax' => 1, + 'cartSubTotalBoth' => 1, + 'cartSubTotalExclTax' => 1 + ], + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'excluding', + 'reviewItemPriceDisplayMode' => 'excluding', + 'reviewTotalsDisplayMode' => 'excluding', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 0, + 'cartShippingExclTax' => 1, + 'cartBothPrices' => 0, + 'cartPriceExclTax' => 1, + 'cartSubTotalBoth' => 0, + 'cartSubTotalExclTax' => 1 + ], + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'including', + 'reviewItemPriceDisplayMode' => 'including', + 'reviewTotalsDisplayMode' => 'including', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 0, + 'cartShippingExclTax' => 0, + 'cartBothPrices' => 0, + 'cartPriceExclTax' => 0, + 'cartSubTotalBoth' => 0, + 'cartSubTotalExclTax' => 0 + ], + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'including', + 'reviewItemPriceDisplayMode' => 'including', + 'reviewTotalsDisplayMode' => 'including', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 0, + 'cartShippingExclTax' => 0, + 'cartBothPrices' => 0, + 'cartPriceExclTax' => 0, + 'cartSubTotalBoth' => 0, + 'cartSubTotalExclTax' => 0 + ], + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'both', + 'reviewItemPriceDisplayMode' => 'both', + 'reviewTotalsDisplayMode' => 'both', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 1, + 'cartShippingExclTax' => 0, + 'cartBothPrices' => 1, + 'cartPriceExclTax' => 0, + 'cartSubTotalBoth' => 1, + 'cartSubTotalExclTax' => 0 + ], + [ + 'expectedResult' => [ + 'isDisplayShippingPriceExclTax' => 1, + 'isDisplayShippingBothPrices' => 1, + 'reviewShippingDisplayMode' => 'excluding', + 'reviewItemPriceDisplayMode' => 'including', + 'reviewTotalsDisplayMode' => 'both', + 'includeTaxInGrandTotal' => 1, + 'isFullTaxSummaryDisplayed' => 1, + 'isZeroTaxDisplayed' => 1 + ], + 'cartShippingBoth' => 0, + 'cartShippingExclTax' => 1, + 'cartBothPrices' => 0, + 'cartPriceExclTax' => 0, + 'cartSubTotalBoth' => 1, + 'cartSubTotalExclTax' => 0 + ], + ]; + } +} diff --git a/app/code/Magento/Tax/etc/di.xml b/app/code/Magento/Tax/etc/di.xml index 48b3173d60f09e739305f3c68cf501be8315be96..12dd5b270fc3c2740cf0f272bcd38fdb812d9b0d 100644 --- a/app/code/Magento/Tax/etc/di.xml +++ b/app/code/Magento/Tax/etc/di.xml @@ -65,7 +65,7 @@ <plugin name="add_tax_to_order" type="Magento\Tax\Model\Quote\ToOrderConverter"/> </type> <type name="Magento\Quote\Model\Cart\CartTotalRepository"> - <plugin name="add_tax_details" type="Magento\Tax\Model\Quote\GrandTotalDetails"/> + <plugin name="add_tax_details" type="Magento\Tax\Model\Quote\GrandTotalDetailsPlugin"/> </type> <type name="Magento\Tax\Model\Resource\Report\Tax\Createdat"> <arguments> diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml index 85969a844c674559ccb839ed2d3d092807e691bf..db20c4572b1d90cde9ed306a8e68a06ae42a6ada 100644 --- a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_index.xml @@ -15,52 +15,71 @@ <item name="children" xsi:type="array"> <item name="steps" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="shipping" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="price" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item> - <item name="displayArea" xsi:type="string">price</item> + <item name="shippingAddress" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="price" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item> + <item name="displayArea" xsi:type="string">price</item> + </item> + </item> </item> </item> </item> - <item name="review" xsi:type="array"> + </item> + </item> + <item name="summary" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="totals" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="columns" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item> + <!-- sort order for this totals is configured on admin panel--> + <!-- Stores->Configuration->SALES->Sales->General->Checkout Totals Sort Order --> + <item name="subtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/subtotal</item> + <item name="config" xsi:type="array"> + <item name="excludingTaxMessage" xsi:type="string">Excl. Tax</item> + <item name="includingTaxMessage" xsi:type="string">Incl. Tax</item> + </item> + </item> + <item name="shipping" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/shipping</item> + <item name="sortOrder" xsi:type="string">20</item> + <item name="config" xsi:type="array"> + <item name="excludingTaxMessage" xsi:type="string">Excl. Tax</item> + <item name="includingTaxMessage" xsi:type="string">Incl. Tax</item> + </item> + </item> + <item name="before_grandtotal" xsi:type="array"> + <item name="component" xsi:type="string">uiComponent</item> + <item name="sortOrder" xsi:type="string">30</item> <item name="children" xsi:type="array"> - <item name="price" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/price</item> - </item> - <item name="subtotal" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/subtotal</item> - </item> + <!-- merge your components here --> + </item> + </item> + <item name="tax" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/tax</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">Tax</item> + </item> + </item> + <item name="grand-total" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/grand-total</item> + <item name="config" xsi:type="array"> + <item name="exclTaxLabel" xsi:type="string">Order Total Excl. Tax</item> + <item name="inclTaxLabel" xsi:type="string">Order Total Incl. Tax</item> + <item name="basicCurrencyMessage" xsi:type="string">Your credit card will be charged for</item> + <item name="title" xsi:type="string">Order Total</item> </item> </item> - <item name="totals" xsi:type="array"> + </item> + </item> + <item name="cart_items" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="details" xsi:type="array"> <item name="children" xsi:type="array"> <item name="subtotal" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/subtotal</item> - <item name="sortOrder" xsi:type="string">10</item> - </item> - <item name="shipping" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/shipping</item> - <item name="sortOrder" xsi:type="string">20</item> - </item> - <item name="before_grandtotal" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/before_grandtotal</item> - <item name="sortOrder" xsi:type="string">30</item> - <item name="children" xsi:type="array"> - <!-- merge your components here --> - </item> - </item> - <item name="grandtotal" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/grandtotal</item> - <item name="sortOrder" xsi:type="string">40</item> - <item name="children" xsi:type="array"> - <item name="grandtotal_tax" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/tax_total</item> - </item> - </item> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/item/details/subtotal</item> </item> </item> </item> diff --git a/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml new file mode 100644 index 0000000000000000000000000000000000000000..012d3de66d1ddaf42f7320f1cb3c064b9f2c4486 --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/layout/checkout_onepage_original.xml @@ -0,0 +1,79 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- TODO remove this file as soon as enhanced checkout is implemented --> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="price" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/shipping_method/price</item> + <item name="displayArea" xsi:type="string">price</item> + </item> + </item> + </item> + <item name="review" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="columns" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Checkout/js/view/columns</item> + <item name="children" xsi:type="array"> + <item name="price" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/price</item> + </item> + <item name="subtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/item/columns/subtotal</item> + </item> + </item> + </item> + <item name="totals" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="subtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/subtotal</item> + <item name="sortOrder" xsi:type="string">10</item> + </item> + <item name="shipping" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/shipping</item> + <item name="sortOrder" xsi:type="string">20</item> + </item> + <item name="before_grandtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/before_grandtotal</item> + <item name="sortOrder" xsi:type="string">30</item> + <item name="children" xsi:type="array"> + <!-- merge your components here --> + </item> + </item> + <item name="grandtotal" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/grandtotal</item> + <item name="sortOrder" xsi:type="string">40</item> + <item name="children" xsi:type="array"> + <item name="grandtotal_tax" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/review/tax_total</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> \ No newline at end of file diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js deleted file mode 100644 index 72f01914f2df6bd4afd9e0478616f8c2a9474373..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/before_grandtotal.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'uiComponent' - ], - function (Component) { - "use strict"; - return Component.extend({ - defaults: { - template: 'Magento_Tax/checkout/review/before_grandtotal' - } - }); - } -); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js deleted file mode 100644 index 839e4a1be856e3fcd8ea4ae7dafaa25ea6030066..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/price.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'Magento_Checkout/js/view/review/item/column' - ], - function (column) { - "use strict"; - var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including'; - return column.extend({ - defaults: { - displayPriceMode: displayPriceMode, - ownClass: 'price', - columnTitle: 'Price', - template: 'Magento_Tax/checkout/review/item/columns/price' - }, - isPriceInclTaxDisplayed: function() { - return 'both' == this.displayPriceMode || 'including' == this.displayPriceMode; - }, - isPriceExclTaxDisplayed: function() { - return 'both' == this.displayPriceMode || 'excluding' == this.displayPriceMode; - }, - isBothPricesDisplayed: function() { - return 'both' == this.displayPriceMode; - }, - getPriceExclTax: function(quoteItem) { - return this.getFormattedPrice(quoteItem.price); - }, - getPriceInclTax: function(quoteItem) { - return this.getFormattedPrice(quoteItem.price_incl_tax); - } - }); - } -); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js deleted file mode 100644 index 2d1bee80d8fb585c4bd0f7277cdec70cb24da129..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/item/columns/subtotal.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'Magento_Tax/js/view/checkout/review/item/columns/price' - ], - function (Price) { - "use strict"; - var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including'; - return Price.extend({ - defaults: { - displayPriceMode: displayPriceMode, - ownClass: 'subtotal', - columnTitle: 'Subtotal', - template: 'Magento_Tax/checkout/review/item/columns/subtotal' - } - }); - } -); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js deleted file mode 100644 index 1fc18683237bb750ea9ca55548be418378c1d5cb..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/shipping.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'jquery', - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils', - 'Magento_Checkout/js/model/shipping-service' - ], - function ($, Component, quote, priceUtils, shippingService) { - var displayMode = window.checkoutConfig.reviewShippingDisplayMode; - return Component.extend({ - defaults: { - displayMode: displayMode, - template: 'Magento_Tax/checkout/review/shipping' - }, - getColspan: 3, - style: "", - quoteIsVirtual: quote.isVirtual(), - selectedShippingMethod: quote.getShippingMethod(), - getTitle: function() { - return "Shipping & Handling" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")"; - }, - getExcludingLabel: function() { - return "Shipping Excl. Tax" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")"; - }, - getIncludingLabel: function() { - return "Shipping Incl. Tax" + "(" + shippingService.getTitleByCode(this.selectedShippingMethod()) + ")"; - }, - totals: quote.getTotals(), - isBothPricesDisplayed: function() { - return 'both' == this.displayMode - }, - isIncludingDisplayed: function() { - return 'including' == this.displayMode; - }, - isExcludingDisplayed: function() { - return 'excluding' == this.displayMode; - }, - getValue: function() { - var price = 0; - if (this.totals()) { - price = this.totals().shipping_amount; - } - return priceUtils.formatPrice(price, quote.getPriceFormat()); - }, - getIncludingValue: function() { - var price = 0; - if (this.totals()) { - price = this.totals().shipping_incl_tax; - } - return priceUtils.formatPrice(price, quote.getPriceFormat()); - }, - getExcludingValue: function() { - var price = 0; - if (this.totals()) { - price = this.totals().shipping_amount; - } - return priceUtils.formatPrice(price, quote.getPriceFormat()); - } - }); - } -); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js deleted file mode 100644 index 56f70a8993f977d833331dd7c3d76c44d61c37cc..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/tax_total.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*jshint browser:true jquery:true*/ -/*global alert*/ -define( - [ - 'ko', - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' - ], - function (ko, Component, quote, priceUtils) { - "use strict"; - var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal; - var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed; - return Component.extend({ - defaults: { - isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal, - template: 'Magento_Tax/checkout/review/tax_total' - }, - colspan: 3, - totals: quote.getTotals(), - style: "", - isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed, - lastTaxGroupId: null, - isDetailsVisible: ko.observable(), - getTitle: function() { - return "Tax"; - }, - getValue: function() { - var amount = 0; - if (this.totals()) { - amount = this.totals().tax_amount; - } - return priceUtils.formatPrice(amount, quote.getPriceFormat()); - }, - formatPrice: function(amount) { - return priceUtils.formatPrice(amount, quote.getPriceFormat()); - }, - getDetails: function() { - var totals = this.totals(); - if (totals.extension_attributes) { - return totals.extension_attributes.tax_grandtotal_details; - } - return []; - }, - toggleDetails: function() { - this.isDetailsVisible(!this.isDetailsVisible()); - } - }); - } -); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js index bdb1256f25678a1a3ac005965ebc90ddc69682c4..018eb3b9d3ef7ea9206f43f5ac1efb2562c1779d 100644 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/shipping_method/price.js @@ -14,7 +14,7 @@ define( "use strict"; return Component.extend({ defaults: { - template: 'Magento_Tax/checkout/shipping_method/price', + template: 'Magento_Tax/checkout/shipping_method/price' }, isDisplayShippingPriceExclTax: window.checkoutConfig.isDisplayShippingPriceExclTax, diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js similarity index 51% rename from app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js rename to app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js index 214e16f531e78aee0aec37621fbbd41ffc62f5e6..2ad991e704ed63d83dd1d3c91bd9e8a69dc63e7c 100644 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/grandtotal.js +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/grand-total.js @@ -6,34 +6,29 @@ /*global alert*/ define( [ - 'uiComponent', + 'Magento_Checkout/js/view/summary/abstract-total', 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' + 'Magento_Catalog/js/price-utils', + 'Magento_Checkout/js/model/totals' ], - function (Component, quote, priceUtils) { + function (Component, quote, priceUtils, totals) { "use strict"; - var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal || false; - var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed || false; return Component.extend({ defaults: { - isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed, - template: 'Magento_Tax/checkout/review/grandtotal' - }, - getColspan: 3, - style: "", - exclTaxLabel: 'Grand Total Excl. Tax', - inclTaxLabel: 'Grand Total Incl. Tax', - basicCurrencyMessage: 'Your credit card will be charged for', - getTitle: function() { - return "Grand Total"; + isFullTaxSummaryDisplayed: window.checkoutConfig.isFullTaxSummaryDisplayed || false, + template: 'Magento_Tax/checkout/summary/grand-total' }, totals: quote.getTotals(), + isTaxDisplayedInGrandTotal: window.checkoutConfig.includeTaxInGrandTotal || false, + isDisplayed: function() { + return this.isFullMode(); + }, getValue: function() { var price = 0; if (this.totals()) { - price = this.totals().grand_total; + price = totals.getSegment('grand_total').value; } - return priceUtils.formatPrice(price, quote.getPriceFormat()); + return this.getFormattedPrice(price); }, getBaseValue: function() { var price = 0; @@ -42,17 +37,12 @@ define( } return priceUtils.formatPrice(price, quote.getBasePriceFormat()); }, - isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal, getGrandTotalExclTax: function() { var totals = this.totals(); if (!totals) { return 0; } - var amount = totals.grand_total - totals.tax_amount; - if (amount < 0) { - return 0; - } - return priceUtils.formatPrice(amount, quote.getPriceFormat()); + return this.getFormattedPrice(totals.grand_total); }, isBaseGrandTotalDisplayNeeded: function() { var totals = this.totals(); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js new file mode 100644 index 0000000000000000000000000000000000000000..f75c7733bab9a9aa72776d85af6dedf7d5442225 --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/item/details/subtotal.js @@ -0,0 +1,34 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'Magento_Checkout/js/view/summary/item/details/subtotal' + ], + function (subtotal) { + "use strict"; + var displayPriceMode = window.checkoutConfig.reviewItemPriceDisplayMode || 'including'; + return subtotal.extend({ + defaults: { + displayPriceMode: displayPriceMode, + template: 'Magento_Tax/checkout/summary/item/details/subtotal' + }, + isPriceInclTaxDisplayed: function() { + return 'both' == displayPriceMode || 'including' == displayPriceMode; + }, + isPriceExclTaxDisplayed: function() { + return 'both' == displayPriceMode || 'excluding' == displayPriceMode; + }, + getValueInclTax: function(quoteItem) { + return this.getFormattedPrice(quoteItem['row_total_incl_tax']); + }, + getValueExclTax: function(quoteItem) { + return this.getFormattedPrice(quoteItem['row_total']); + } + + }); + } +); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js new file mode 100644 index 0000000000000000000000000000000000000000..b6c3631c7869d1b912a046c8b3a097897a973eeb --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/shipping.js @@ -0,0 +1,48 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'jquery', + 'Magento_Checkout/js/view/summary/shipping', + 'Magento_Checkout/js/model/quote' + ], + function ($, Component, quote) { + var displayMode = window.checkoutConfig.reviewShippingDisplayMode; + return Component.extend({ + defaults: { + displayMode: displayMode, + template: 'Magento_Tax/checkout/summary/shipping' + }, + isBothPricesDisplayed: function() { + return 'both' == this.displayMode + }, + isIncludingDisplayed: function() { + return 'including' == this.displayMode; + }, + isExcludingDisplayed: function() { + return 'excluding' == this.displayMode; + }, + isCalculated: function() { + return this.totals() && this.isFullMode() && null != quote.shippingMethod(); + }, + getIncludingValue: function() { + if (!this.isCalculated()) { + return this.notCalculatedMessage; + } + var price = this.totals().shipping_incl_tax; + return this.getFormattedPrice(price); + }, + getExcludingValue: function() { + if (!this.isCalculated()) { + return this.notCalculatedMessage; + } + var price = this.totals().shipping_amount; + return this.getFormattedPrice(price); + } + }); + } +); diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js similarity index 63% rename from app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js rename to app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js index 06a169784c3f625b7784a67dec4b79905c8d1bad..e9e86cd9fa03119f034eb91a70b48227ad169987 100644 --- a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/review/subtotal.js +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/subtotal.js @@ -6,23 +6,15 @@ /*global alert*/ define( [ - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote' ], - function (Component, quote, priceUtils) { + function (Component, quote) { var displaySubtotalMode = window.checkoutConfig.reviewTotalsDisplayMode; return Component.extend({ defaults: { displaySubtotalMode: displaySubtotalMode, - template: 'Magento_Tax/checkout/review/subtotal' - }, - getColspan: 3, - style: "", - excludingTaxMessage: 'Subtotal (Excl. Tax)', - includingTaxMessage: 'Subtotal (Incl. Tax)', - getTitle: function() { - return "Subtotal" + template: 'Magento_Tax/checkout/summary/subtotal' }, totals: quote.getTotals(), getValue: function () { @@ -30,7 +22,7 @@ define( if (this.totals()) { price = this.totals().subtotal; } - return priceUtils.formatPrice(price, quote.getPriceFormat()); + return this.getFormattedPrice(price); }, isBothPricesDisplayed: function() { return 'both' == this.displaySubtotalMode; @@ -43,7 +35,7 @@ define( if (this.totals()) { price = this.totals().subtotal_incl_tax; } - return priceUtils.formatPrice(price, quote.getPriceFormat()); + return this.getFormattedPrice(price); } }); } diff --git a/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js new file mode 100644 index 0000000000000000000000000000000000000000..019b0717c70afdebf57d04f73e75e6fdb6564956 --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/js/view/checkout/summary/tax.js @@ -0,0 +1,77 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*jshint browser:true jquery:true*/ +/*global alert*/ +define( + [ + 'ko', + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/totals' + ], + function (ko, Component, quote, totals) { + "use strict"; + var isTaxDisplayedInGrandTotal = window.checkoutConfig.includeTaxInGrandTotal; + var isFullTaxSummaryDisplayed = window.checkoutConfig.isFullTaxSummaryDisplayed; + var isZeroTaxDisplayed = window.checkoutConfig.isZeroTaxDisplayed; + return Component.extend({ + defaults: { + isTaxDisplayedInGrandTotal: isTaxDisplayedInGrandTotal, + notCalculatedMessage: 'Not yet calculated', + template: 'Magento_Tax/checkout/summary/tax' + }, + totals: quote.getTotals(), + isFullTaxSummaryDisplayed: isFullTaxSummaryDisplayed, + ifShowValue: function() { + if (!isTaxDisplayedInGrandTotal) { + return false; + } + if (!this.totals() || null == totals.getSegment('tax')) { + return true; + } + if (this.getPureValue() == 0) { + return isZeroTaxDisplayed; + } + return true; + }, + ifShowDetails: function() { + if (!this.isFullMode()) { + return false; + } + return isTaxDisplayedInGrandTotal && this.getPureValue() > 0 && isFullTaxSummaryDisplayed; + }, + getPureValue: function() { + var amount = 0; + if (this.totals()) { + var taxTotal = totals.getSegment('tax'); + if (taxTotal) { + amount = taxTotal.value; + } + } + return amount; + }, + isCalculated: function() { + return this.totals() && this.isFullMode() && null != totals.getSegment('tax'); + }, + getValue: function() { + if (!this.isCalculated()) { + return this.notCalculatedMessage; + } + var amount = totals.getSegment('tax').value; + return this.getFormattedPrice(amount); + }, + formatPrice: function(amount) { + return this.getFormattedPrice(amount); + }, + getDetails: function() { + var totals = this.totals(); + if (totals.extension_attributes) { + return totals.extension_attributes.tax_grandtotal_details; + } + return []; + } + }); + } +); diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html deleted file mode 100644 index 237b692b59a6f20c62fab5b3c9c5ef157ffe37ab..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/before_grandtotal.html +++ /dev/null @@ -1,10 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<!-- ko foreach: elems() --> -<!-- ko template: getTemplate() --><!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html deleted file mode 100644 index 8c533bcae6fca5bb34f84282e33adcf595e4167d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/grandtotal.html +++ /dev/null @@ -1,43 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: isTaxDisplayedInGrandTotal --> -<tr class="grand totals excl"> - <th data-bind="attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"> - <strong data-bind="text: exclTaxLabel"></strong> - </th> - <td data-bind="attr: {'style': style, 'data-th': exclTaxLabel }" class="amount"> - <strong data-bind="text: getGrandTotalExclTax()"></strong> - </td> -</tr> - <!-- ko foreach: elems() --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> -<tr class="grand totals incl"> - <th data-bind="attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"> - <strong data-bind="text: $t(inclTaxLabel)"></strong> - </th> - <td data-bind="attr: {'style': style, 'data-th': $t(inclTaxLabel) }" class="amount"> - <strong data-bind="text: getValue()"></strong> - </td> -</tr> -<!-- /ko --> -<!-- ko if: !isTaxDisplayedInGrandTotal --> -<tr class="grand totals"> - <th data-bind="attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"> - <strong data-bind="text: $t(getTitle())"></strong> - </th> - <td data-bind="attr: {'style':style, 'data-th': getTitle()}" class="amount"> - <strong data-bind="text: getValue()"></strong> - </td> -</tr> -<!-- /ko --> -<!-- ko if: isBaseGrandTotalDisplayNeeded() --> -<tr class="totals charge"> - <th class="mark" data-bind="text: $t(basicCurrencyMessage), attr: { 'colspan': getColspan }" scope="row"></th> - <td class="amount" data-bind="text: getBaseValue(), attr: {'data-th': $t(basicCurrencyMessage)}"></td> -</tr> -<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html deleted file mode 100644 index fc596c7d1ac5e35a6d6590ecf2231b0fc88b52e9..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/price.html +++ /dev/null @@ -1,23 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<td data-bind="attr: { 'data-th': $t(getColName()), class: getClass() }"> - <!-- ko if: isPriceInclTaxDisplayed() --> - <span class="price-including-tax" data-bind ="attr:{'data-label': $t('Incl. Tax')}"> - <!-- ko foreach: getRegion('unit_incl_tax') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </span> - - <!-- /ko --> - <!-- ko if: isPriceExclTaxDisplayed() --> - <span class="price-excluding-tax" data-bind ="attr:{'data-label': $t('Excl. Tax')}"> - <!-- ko foreach: getRegion('unit_excl_tax') --> - <!-- ko template: getTemplate() --><!-- /ko --> - <!-- /ko --> - </span> - <!-- /ko --> -</td> \ No newline at end of file diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html deleted file mode 100644 index 6c7900d23315bdf25c4b3ad02a2382295cc1a90d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/shipping.html +++ /dev/null @@ -1,31 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: quoteIsVirtual == 0 --> - <!-- ko if: isBothPricesDisplayed() --> - <tr class="totals shipping excl"> - <th data-bind="text: $t(getExcludingLabel()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th> - <td class="amount" data-bind="text: getExcludingValue(), attr: {'style':style, 'data-th': $t(getExcludingLabel())}"></td> - </tr> - <tr class="totals shipping incl"> - <th data-bind="text: $t(getIncludingLabel()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th> - <td class="amount" data-bind="text: getIncludingValue(), attr: {'style':style, 'data-th': $t(getIncludingLabel())}"></td> - </tr> - <!-- /ko --> - <!-- ko if: isIncludingDisplayed() --> - <tr class="totals shipping incl"> - <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th> - <td class="amount" data-bind="text: getIncludingValue(), attr: {'style':style, 'data-th': $t(getTitle())}"></td> - </tr> - <!-- /ko --> - <!-- ko if: isExcludingDisplayed() --> - <tr class="totals shipping excl"> - <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan }" class="mark" scope="row"></th> - <td data-bind="text: getValue(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td> - </tr> - <!-- /ko --> -<!-- /ko --> - diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html deleted file mode 100644 index 022131d8a0cc957a96ea074f4fe05c1292e4616d..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/subtotal.html +++ /dev/null @@ -1,31 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: isBothPricesDisplayed() --> -<tr class="totals sub excl"> - <th data-bind="text: excludingTaxMessage, attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"> - </th> - <td data-bind="text: getValue(), attr: {'style': style, 'data-th': $t(excludingTaxMessage) }" class="amount"></td> -</tr> -<tr class="totals sub incl"> - <th data-bind="text: includingTaxMessage, attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"> - </th> - <td data-bind="text: getValueInclTax(), attr: {'style': style, 'data-th': $t(includingTaxMessage) }" class="amount"> - </td> -</tr> -<!-- /ko --> -<!-- ko if: !isBothPricesDisplayed() && isIncludingTaxDisplayed() --> -<tr class="totals sub"> - <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"></th> - <td data-bind="text: getValueInclTax(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td> -</tr> -<!-- /ko --> -<!-- ko if: !isBothPricesDisplayed() && !isIncludingTaxDisplayed() --> -<tr class="totals sub"> - <th data-bind="text: $t(getTitle()), attr: {'style':style, 'colspan': getColspan}" class="mark" scope="row"></th> - <td data-bind="text: getValue(), attr: {'style':style, 'data-th': $t(getTitle())}" class="amount"></td> -</tr> -<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html deleted file mode 100644 index e22db68f36617b6c3ceb614fcf4fc1d250bf62ed..0000000000000000000000000000000000000000 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/tax_total.html +++ /dev/null @@ -1,42 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko ifnot: isFullTaxSummaryDisplayed --> -<tr class="totals-tax"> - <th data-bind="text: getTitle(), attr: {'style':style, 'colspan': colspan}" class="mark" scope="row"> - </th> - <td data-bind="attr: {'style': style, 'data-th': $t(getTitle()) }" class="amount"> - <span class="price" data-bind="text: getValue()"></span> - </td> -</tr> -<!-- /ko --> -<!-- ko if: isFullTaxSummaryDisplayed --> - <tr class="totals-tax-summary" data-bind="click: toggleDetails()"> - <th data-bind="text: getTitle(), attr: {'style':style, 'colspan': colspan}" class="mark" scope="row"> - </th> - <td data-bind="attr: {'style': style, 'data-th': $t(getTitle()) }" class="amount"> - <span class="price" data-bind="text: getValue()"></span> - </td> - </tr> - <!-- ko foreach: getDetails() --> - <!-- ko foreach: rates --> - <tr class="totals-tax-details" data-bind="visible: $parents[1].isDetailsVisible"> - <!-- ko if: percent --> - <th class="mark" scope="row" data-bind="text: title + ' (' + percent + '%)', attr: {'style': $parents[1].style, 'colspan': $parents[1].colspan}"> - </th> - <!-- /ko --> - <!-- ko if: !percent --> - <th class="mark" scope="row" data-bind="text: title, attr: {'style': $parents[1].style, 'colspan': $parents[1].colspan}"> - </th> - <!-- /ko --> - <!-- ko if: $index() == 0 --> - <td class="amount" data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'style': $parents[1].style, 'rowspan': $parents[0].rates.length }"> - </td> - <!-- /ko --> - </tr> - <!-- /ko --> - <!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html index e854b9f1e0bc2e4a9a8f50c89ebc77e82f084fce..345b3eea5b0490a15af75cda91627f31bf06ffa6 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/shipping_method/price.html @@ -5,22 +5,22 @@ */ --> <!-- ko if: isDisplayShippingPriceExclTax --> -<span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_excl_tax)"></span></span> +<span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_excl_tax)"></span></span> <!-- /ko --> <!-- ko ifnot: isDisplayShippingPriceExclTax --> -<!-- ko if: (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))--> +<!-- ko if: (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))--> <span class="price-including-tax" data-bind = "attr: {'data-label': $t('Incl. Tax')}"> - <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span> + <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_incl_tax)"></span></span> </span> <!-- /ko --> -<!-- ko ifnot: (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))--> - <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span> +<!-- ko ifnot: (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))--> + <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_incl_tax)"></span></span> <!-- /ko --> <!-- /ko --> -<!-- ko if: (isDisplayShippingBothPrices && (item.price_excl_tax != item.price_incl_tax))--> +<!-- ko if: (isDisplayShippingBothPrices && (method.price_excl_tax != method.price_incl_tax))--> <span class="price-excluding-tax" data-bind = "attr: {'data-label': $t('Excl. Tax')}"> - <span class="price"><span class="price" data-bind="text: getFormattedPrice(item.price_excl_tax)"></span></span> + <span class="price"><span class="price" data-bind="text: getFormattedPrice(method.price_excl_tax)"></span></span> </span> <!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html new file mode 100644 index 0000000000000000000000000000000000000000..d37e8816ae3e05c1cf806e520ac810e4d7a653b2 --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/grand-total.html @@ -0,0 +1,42 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: isTaxDisplayedInGrandTotal && isDisplayed() --> +<tr class="grand totals incl"> + <th class="mark" scope="row"> + <strong data-bind="text: $t(inclTaxLabel)"></strong> + </th> + <td data-bind="attr: {'data-th': $t(inclTaxLabel) }" class="amount"> + <strong><span class="price" data-bind="text: getValue()"></span></strong> + </td> +</tr> +<tr class="grand totals excl"> + <th class="mark" scope="row"> + <strong data-bind="text: $t(exclTaxLabel)"></strong> + </th> + <td data-bind="attr: {'data-th': exclTaxLabel }" class="amount"> + <strong><span class="price" data-bind="text: getGrandTotalExclTax()"></span></strong> + </td> +</tr> +<!-- /ko --> +<!-- ko if: !isTaxDisplayedInGrandTotal && isDisplayed() --> +<tr class="grand totals"> + <th class="mark" scope="row"> + <strong data-bind="text: $t(title)"></strong> + </th> + <td data-bind="attr: {'data-th': $t(title)}" class="amount"> + <strong><span class="price" data-bind="text: getValue()"></span></strong> + </td> +</tr> +<!-- /ko --> +<!-- ko if: isBaseGrandTotalDisplayNeeded() && isDisplayed() --> +<tr class="totals charge"> + <th class="mark" data-bind="text: $t(basicCurrencyMessage)" scope="row"></th> + <td class="amount"> + <span class="price" data-bind="text: getBaseValue(), attr: {'data-th': $t(basicCurrencyMessage)}"></span> + </td> +</tr> +<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html similarity index 50% rename from app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html rename to app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html index d489e741ba0474ea1af3e1ca0c72e24d8ac4de85..5d555b1b54f50c13ada9f31da8ffce63f85795a3 100644 --- a/app/code/Magento/Tax/view/frontend/web/template/checkout/review/item/columns/subtotal.html +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/item/details/subtotal.html @@ -4,20 +4,29 @@ * See COPYING.txt for license details. */ --> -<td data-bind="attr: { 'data-th': $t(getColName())}" class="col subtotal"> - <!-- ko if: isPriceInclTaxDisplayed() --> +<div class="subtotal"> + <!-- ko if: isPriceInclTaxDisplayed() && !getRegion('row_incl_tax') --> + <span class="price-including-tax" data-bind ="text: getValueInclTax($parents[1]), attr:{'data-label': $t('Incl. Tax')}"> + </span> + <!-- /ko --> + + <!-- ko if: isPriceInclTaxDisplayed() && getRegion('row_incl_tax') --> <span class="price-including-tax" data-bind ="attr:{'data-label': $t('Incl. Tax')}"> <!-- ko foreach: getRegion('row_incl_tax') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </span> + <!-- /ko --> + <!-- ko if: isPriceExclTaxDisplayed() && !getRegion('row_excl_tax') --> + <span class="price-excluding-tax" data-bind ="text: getValueExclTax($parents[1]), attr:{'data-label': $t('Excl. Tax')}"> + </span> <!-- /ko --> - <!-- ko if: isPriceExclTaxDisplayed() --> + <!-- ko if: isPriceExclTaxDisplayed() && getRegion('row_excl_tax') --> <span class="price-excluding-tax" data-bind ="attr:{'data-label': $t('Excl. Tax')}"> <!-- ko foreach: getRegion('row_excl_tax') --> <!-- ko template: getTemplate() --><!-- /ko --> <!-- /ko --> </span> <!-- /ko --> -</td> \ No newline at end of file +</div> \ No newline at end of file diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html new file mode 100644 index 0000000000000000000000000000000000000000..8caba625561dfde89afdef0c04a97dbfb0de6c0e --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/shipping.html @@ -0,0 +1,78 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: quoteIsVirtual == 0 --> + <!-- ko if: isBothPricesDisplayed() --> + <tr class="totals shipping excl"> + <th class="mark" scope="row"> + <span class="label" data-bind="text: $t(title) + ' ' + $t(excludingTaxMessage)"></span> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </th> + <td class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getExcludingValue()), attr: {'data-th': $t(excludingTaxMessage)}"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getExcludingValue()), attr: {'data-th': $t(excludingTaxMessage)}"></span> + <!-- /ko --> + </td> + </tr> + <tr class="totals shipping incl"> + <th class="mark" scope="row"> + <span class="label" data-bind="text: $t(title) + ' ' + $t(includingTaxMessage)"></span> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </th> + <td class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title) + ' ' + $t(excludingTaxMessage)}"></span> + <!-- /ko --> + </td> + </tr> + <!-- /ko --> + <!-- ko if: isIncludingDisplayed() --> + <tr class="totals shipping incl"> + <th class="mark" scope="row"> + <span class="label" data-bind="text: $t(title)"></span> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </th> + <td class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getIncludingValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + </td> + </tr> + <!-- /ko --> + <!-- ko if: isExcludingDisplayed() --> + <tr class="totals shipping excl"> + <th class="mark" scope="row"> + <span class="label" data-bind="text: $t(title)"></span> + <span class="value" data-bind="text: $t(getShippingMethodTitle())"></span> + </th> + <td class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getValue()), attr: {'data-th': $t(title)}"></span> + <!-- /ko --> + </td> + </tr> + <!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html new file mode 100644 index 0000000000000000000000000000000000000000..4652d47e5e35a6b7a868c795ac946999b43b6612 --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/subtotal.html @@ -0,0 +1,42 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: isBothPricesDisplayed() --> +<tr class="totals sub excl"> + <th class="mark" scope="row"> + <span data-bind="text: $t(title)"></span> + <span data-bind="text: $t(excludingTaxMessage)"></span> + </th> + <td class="amount"> + <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(excludingTaxMessage) }"></span> + </td> +</tr> +<tr class="totals sub incl"> + <th class="mark" scope="row"> + <span data-bind="text: $t(title)"></span> + <span data-bind="text: $t(includingTaxMessage)"></span> + </th> + <td class="amount"> + <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(includingTaxMessage) }"></span> + </td> +</tr> +<!-- /ko --> +<!-- ko if: !isBothPricesDisplayed() && isIncludingTaxDisplayed() --> +<tr class="totals sub"> + <th data-bind="text: $t(title)" class="mark" scope="row"></th> + <td class="amount"> + <span class="price" data-bind="text: getValueInclTax(), attr: {'data-th': $t(title)}"></span> + </td> +</tr> +<!-- /ko --> +<!-- ko if: !isBothPricesDisplayed() && !isIncludingTaxDisplayed() --> +<tr class="totals sub"> + <th data-bind="text: $t(title)" class="mark" scope="row"></th> + <td class="amount"> + <span class="price" data-bind="text: getValue(), attr: {'data-th': $t(title)}"></span> + </td> +</tr> +<!-- /ko --> diff --git a/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html new file mode 100644 index 0000000000000000000000000000000000000000..5b2b739402261b01f95e51d363961e015d840c1a --- /dev/null +++ b/app/code/Magento/Tax/view/frontend/web/template/checkout/summary/tax.html @@ -0,0 +1,61 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: ifShowValue() && !ifShowDetails() --> +<tr class="totals-tax"> + <th data-bind="text: $t(title)" class="mark" scope="row"></th> + <td data-bind="attr: {'data-th': $t(title) }" class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getValue())"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getValue())"></span> + <!-- /ko --> + </td> +</tr> +<!-- /ko --> +<!-- ko if: ifShowValue() && ifShowDetails() --> + <tr class="totals-tax-summary" + data-bind="mageInit: {'toggleAdvanced':{'selectorsToggleClass': 'shown', 'baseToggleClass': 'expanded', 'toggleContainers': '.totals-tax-details'}}"> + <th data-bind="text: $t(title)" class="mark" scope="row"></th> + <td data-bind="attr: {'data-th': $t(title) }" class="amount"> + <!-- ko if: isCalculated() --> + <span class="price" + data-bind="text: $t(getValue())"></span> + <!-- /ko --> + <!-- ko ifnot: isCalculated() --> + <span class="not-calculated" + data-bind="text: $t(getValue())"></span> + <!-- /ko --> + </td> + </tr> + <!-- ko foreach: getDetails() --> + <!-- ko foreach: rates --> + <tr class="totals-tax-details"> + <!-- ko if: percent --> + <th class="mark" scope="row" data-bind="text: title + ' (' + percent + '%)'"></th> + <!-- /ko --> + <!-- ko if: !percent --> + <th class="mark" scope="row" data-bind="text: title"></th> + <!-- /ko --> + <!-- ko if: $index() == 0 --> + <td class="amount"> + <!-- ko if: $parents[1].isCalculated() --> + <span class="price" + data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'rowspan': $parents[0].rates.length }"></span> + <!-- /ko --> + <!-- ko ifnot: $parents[1].isCalculated() --> + <span class="not-calculated" + data-bind="text: $parents[1].formatPrice($parents[0].amount), attr: {'data-th': title, 'rowspan': $parents[0].rates.length }"></span> + <!-- /ko --> + </td> + <!-- /ko --> + </tr> + <!-- /ko --> + <!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Ui/view/base/web/js/block-loader.js b/app/code/Magento/Ui/view/base/web/js/block-loader.js new file mode 100644 index 0000000000000000000000000000000000000000..e3cb1b422bb31f070307e26f8f037cb3753f4e99 --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/js/block-loader.js @@ -0,0 +1,90 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'ko', + 'jquery', + 'Magento_Ui/js/lib/loader', + 'mage/template' +], function (ko, $, templateLoader, template) { + 'use strict'; + + var blockLoaderTemplatePath = 'ui/block-loader', + blockContentLoadingClass = '_block-content-loading', + blockLoader, + blockLoaderClass, + loaderImageHref; + + templateLoader.loadTemplate(blockLoaderTemplatePath).done(function (blockLoaderTemplate) { + blockLoader = template($.trim(blockLoaderTemplate), { + loaderImageHref: loaderImageHref + }); + blockLoader = $(blockLoader); + blockLoaderClass = '.' + blockLoader.attr('class'); + }); + + /** + * Helper function to check if blockContentLoading class should be applied. + * @param {Object} element + * @returns {Boolean} + */ + function isLoadingClassRequired(element) { + var position = element.css('position'); + + if (position === 'absolute' || position === 'fixed') { + return false; + } + + return true; + } + + /** + * Add loader to block. + * @param {Object} element + */ + function addBlockLoader(element) { + element.find(':focus').blur(); + element.find('input:disabled, select:disabled').addClass('_disabled'); + element.find('input, select').prop('disabled', true); + + if (isLoadingClassRequired(element)) { + element.addClass(blockContentLoadingClass); + } + element.append(blockLoader.clone()); + } + + /** + * Remove loader from block. + * @param {Object} element + */ + function removeBlockLoader(element) { + if (!element.has(blockLoaderClass).length) { + return; + } + element.find(blockLoaderClass).remove(); + element.find('input:not("._disabled"), select:not("._disabled")').prop('disabled', false); + element.find('input:disabled, select:disabled').removeClass('_disabled'); + element.removeClass(blockContentLoadingClass); + } + + return function (loaderHref) { + loaderImageHref = loaderHref; + ko.bindingHandlers.blockLoader = { + /** + * Process loader for block + * @param {String} element + * @param {Boolean} displayBlockLoader + */ + update: function (element, displayBlockLoader) { + element = $(element); + + if (ko.unwrap(displayBlockLoader())) { + addBlockLoader(element); + } else { + removeBlockLoader(element); + } + } + }; + }; +}); diff --git a/app/code/Magento/Ui/view/base/web/js/modal/modal.js b/app/code/Magento/Ui/view/base/web/js/modal/modal.js index 1b9c0c18860a88b2faccfa8490a5c243746ce6b5..aa415e7aeacebaf5d9ffed007bdc3cbe5a59e9fa 100644 --- a/app/code/Magento/Ui/view/base/web/js/modal/modal.js +++ b/app/code/Magento/Ui/view/base/web/js/modal/modal.js @@ -8,9 +8,10 @@ define([ "mage/template", "text!ui/template/modal/modal-popup.html", "text!ui/template/modal/modal-slide.html", + "text!ui/template/modal/modal-custom.html", "jquery/ui", "mage/translate" -], function($, _, template, popupTpl, slideTpl){ +], function($, _, template, popupTpl, slideTpl, customTpl){ "use strict"; /** @@ -23,6 +24,7 @@ define([ modalClass: '', popupTpl: popupTpl, slideTpl: slideTpl, + customTpl: customTpl, modalVisibleClass: '_show', parentModalClass: '_has-modal', innerScrollClass: '_inner-scroll', @@ -36,6 +38,7 @@ define([ wrapperClass: 'modals-wrapper', overlayClass: 'modals-overlay', responsiveClass: 'modal-slide', + trigger: '', modalLeftMargin: 45, closeText: $.mage.__('Close'), buttons: [{ @@ -56,6 +59,7 @@ define([ this._createButtons(); this.modal.find(this.options.modalCloseBtn).on('click', _.bind(this.closeModal, this)); + $(this.options.trigger).on('click', _.bind(this.toggleModal, this)); this.element.on('openModal', _.bind(this.openModal, this)); this.element.on('closeModal', _.bind(this.closeModal, this)); }, @@ -82,6 +86,13 @@ define([ return elems.filter('.'+this.options.modalVisibleClass).length; }, + toggleModal: function() { + if (this.options.isOpen == true) { + this.closeModal(); + } else { + this.openModal(); + } + }, openModal: function() { var that = this; diff --git a/app/code/Magento/Ui/view/base/web/templates/block-loader.html b/app/code/Magento/Ui/view/base/web/templates/block-loader.html new file mode 100644 index 0000000000000000000000000000000000000000..cc98e6a19688cfc7d3e92d4d7c0753075dcd901c --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/block-loader.html @@ -0,0 +1,11 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div data-role="loader" class="loading-mask" style="position: absolute;"> + <div class="loader"> + <img src="<%= loaderImageHref %>" alt="Loading..." style="position: absolute;"> + </div> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html new file mode 100644 index 0000000000000000000000000000000000000000..990630aa02b9c1ee71088b56bd345ed33e4d3a6e --- /dev/null +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-custom.html @@ -0,0 +1,38 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + +<aside class="modal-<%= data.type %> <%= data.modalClass %> + <% if(data.responsive){ %><%= data.responsiveClass %><% } %> + <% if(data.innerScroll){ %><%= data.innerScrollClass %><% } %>" + data-role="modal" + data-type="<%= data.type %>"> + <div class="modal-inner-wrap"> + <header class="modal-header"> + <% if(data.title){ %> + <h1 class="modal-title" + data-role="title"><%= data.title %></h1> + <% } %> + <button + class="action-close" + data-role="closeBtn" + type="button"> + <span><%= data.closeText %></span> + </button> + </header> + <div class="modal-content" data-role="content"></div> + <% if(data.buttons.length > 0){ %> + <footer class="modal-footer"> + <% _.each(data.buttons, function(button) { %> + <button + class="<%= button.class %>" + type="button" + data-role="action"><span><%= button.text %></span></button> + <% }); %> + </footer> + <% } %> + </div> +</aside> diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html index 7c45aefbb35a66ab80274fa4891f31804b246f93..43ac20b2aeb1e26bce6330232755be77e5c4605c 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-popup.html @@ -13,8 +13,10 @@ data-type="<%= data.type %>"> <div class="modal-inner-wrap"> <header class="modal-header"> + <% if(data.title){ %> <h1 class="modal-title" data-role="title"><%= data.title %></h1> + <% } %> <button class="action-close" data-role="closeBtn" @@ -25,6 +27,7 @@ <div class="modal-content" data-role="content"></div> + <% if(data.buttons.length > 0){ %> <footer class="modal-footer"> <% _.each(data.buttons, function(button) { %> <button @@ -33,5 +36,6 @@ data-role="action"><span><%= button.text %></span></button> <% }); %> </footer> + <% } %> </div> </aside> diff --git a/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html index dbe99544b3e076a5d5fb670caad2ecdd77671437..abffa4573962a7acc129a0f3f0a96c2765240731 100644 --- a/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html +++ b/app/code/Magento/Ui/view/base/web/templates/modal/modal-slide.html @@ -12,14 +12,17 @@ data-type="<%= data.type %>"> <div class="modal-inner-wrap"> <header class="modal-header"> + <% if(data.title){ %> <h1 class="modal-title" data-role="title"><%= data.title %></h1> + <% } %> <button class="action-close" data-role="closeBtn" type="button"> <span><%= data.closeText %></span> </button> + <% if(data.buttons.length > 0){ %> <div class="page-main-actions"> <div class="page-actions"> <div class="page-actions-buttons"> @@ -33,6 +36,7 @@ </div> </div> </div> + <% } %> </header> <div class="modal-content" data-role="content"></div> </div> diff --git a/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js b/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js deleted file mode 100644 index 4eca983e1f4334cc21901eec3b3a95245956c7d9..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/frontend/web/js/model/errorlist.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define(['ko'], function(ko) { - "use strict"; - var errors = ko.observableArray([]); - return { - add: function (error) { - var expr = /([%])\w+/g, - errorMessage; - if (!error.hasOwnProperty('parameters')) { - this.clear(); - errors.push(error.message); - return true; - } - errorMessage = error.message.replace(expr, function(varName) { - varName = varName.substr(1); - if (error.parameters.hasOwnProperty(varName)) { - return error.parameters[varName]; - } - return error.parameters.shift(); - }); - this.clear(); - errors.push(errorMessage); - return true; - }, - remove: function() { - errors.shift(); - }, - getAll: function () { - return errors; - }, - clear: function() { - errors.removeAll(); - } - }; -}); diff --git a/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js b/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js new file mode 100644 index 0000000000000000000000000000000000000000..15da0c25dc7922e8d69a51b5647597c2540c9db0 --- /dev/null +++ b/app/code/Magento/Ui/view/frontend/web/js/model/messageList.js @@ -0,0 +1,78 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define(['ko'], function (ko) { + 'use strict'; + + var errors = ko.observableArray([]); + var success = ko.observableArray([]); + + return { + errors: errors, + success: success, + /** + * Add message to list. + * @param {Object} messageObj + * @param {Object} type + * @returns {Boolean} + */ + add: function (messageObj, type) { + var expr = /([%])\w+/g, + message; + + if (!messageObj.hasOwnProperty('parameters')) { + this.clear(); + type.push(messageObj.message); + + return true; + } + message = messageObj.message.replace(expr, function (varName) { + varName = varName.substr(1); + + if (messageObj.parameters.hasOwnProperty(varName)) { + return messageObj.parameters[varName]; + } + + return messageObj.parameters.shift(); + }); + this.clear(); + errors.push(message); + + return true; + }, + addSuccessMessage: function (message) { + return this.add(message, this.success) + + }, + addErrorMessage: function (message) { + return this.add(message, this.errors) + }, + /** + * Remove first error message in list + */ + remove: function (type) { + type.shift(); + }, + /** + * Get all error messages + * @returns {Object} + */ + getAll: function () { + return errors; + }, + /** + * Clear error list + */ + clear: function () { + errors.removeAll(); + success.removeAll(); + }, + getAllErrors: function () { + return errors; + }, + getAllSuccess: function () { + return success; + } + }; +}); diff --git a/app/code/Magento/Ui/view/frontend/web/js/view/errors.js b/app/code/Magento/Ui/view/frontend/web/js/view/errors.js deleted file mode 100644 index 192a218bb4845cfccbef5d13a1664806bae574c7..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/frontend/web/js/view/errors.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*global define*/ -define(['uiComponent', '../model/errorlist'], function (Component, errors) { - "use strict"; - return Component.extend({ - errorList: errors.getAll(), - defaults: { - template: 'Magento_Ui/errors' - } - }); -}); diff --git a/app/code/Magento/Ui/view/frontend/web/js/view/messages.js b/app/code/Magento/Ui/view/frontend/web/js/view/messages.js new file mode 100644 index 0000000000000000000000000000000000000000..02a5a2e6beb0ec893fd22b10c0a360d0984fa2d8 --- /dev/null +++ b/app/code/Magento/Ui/view/frontend/web/js/view/messages.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define(['uiComponent', '../model/messageList'], function (Component, messages) { + 'use strict'; + + return Component.extend({ + errorList: messages.getAllErrors(), + successList: messages.getAllSuccess(), + + defaults: { + template: 'Magento_Ui/messages' + }, + + /** + * + * @returns {*} + */ + isVisible: function () { + return this.errorList().length || this.successList().length; + }, + /** + * Remove all errors + */ + removeAll: function () { + this.errorList.removeAll(); + this.successList.removeAll(); + } + }); +}); diff --git a/app/code/Magento/Ui/view/frontend/web/template/errors.html b/app/code/Magento/Ui/view/frontend/web/template/errors.html deleted file mode 100644 index 15d1bf5d80d2215869aa676d5acd7950a9c9c591..0000000000000000000000000000000000000000 --- a/app/code/Magento/Ui/view/frontend/web/template/errors.html +++ /dev/null @@ -1,11 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<div class="messages" data-bind="visible: errorList().length"> - <div class="message message-error error" data-bind="foreach: errorList"> - <div data-ui-id="checkout-cart-validationmessages-message-error" data-bind="text: $data"></div> - </div> -</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/frontend/web/template/messages.html b/app/code/Magento/Ui/view/frontend/web/template/messages.html new file mode 100644 index 0000000000000000000000000000000000000000..d842c4b10ff29428a4427ad00f89a7529ece12ae --- /dev/null +++ b/app/code/Magento/Ui/view/frontend/web/template/messages.html @@ -0,0 +1,18 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<div class="messages" data-bind="visible: isVisible(), click: removeAll"> + <!-- ko foreach: errorList --> + <div class="message message-error error"> + <div data-ui-id="checkout-cart-validationmessages-message-error" data-bind="text: $data"></div> + </div> + <!--/ko--> + <!-- ko foreach: successList --> + <div class="message message-success success"> + <div data-ui-id="checkout-cart-validationmessages-message-success" data-bind="text: $data"></div> + </div> + <!--/ko--> +</div> \ No newline at end of file diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html new file mode 100644 index 0000000000000000000000000000000000000000..b2ef214e944a5e63c14f8b00f6d4297280baa284 --- /dev/null +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/helper/tooltip.html @@ -0,0 +1,13 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> + <div class="field-tooltip toggle"> + <a class="field-tooltip-action action-help" target="_blank" data-bind="attr: {href: tooltip.link}"> + </a> + <div class="field-tooltip-content"> + <!-- ko text: tooltip.description --><!-- /ko --> + </div> +</div> diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html b/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html index 75e6ff74dbe80b383441e20d4eea3dd2014d3743..e35184926cadcfd10f8a83883858be2d6e532761 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/element/input.html @@ -6,6 +6,7 @@ --> <input class="input-text" type="text" data-bind=" value: value, + valueUpdate: 'keyup', hasFocus: focused, attr: { name: inputName, diff --git a/app/code/Magento/Ui/view/frontend/web/templates/form/field.html b/app/code/Magento/Ui/view/frontend/web/templates/form/field.html index fef8f712455113ecf7aca9f717e58192e7e0b58f..9f746c7e4542408b4e75475866a8d95676308a15 100644 --- a/app/code/Magento/Ui/view/frontend/web/templates/form/field.html +++ b/app/code/Magento/Ui/view/frontend/web/templates/form/field.html @@ -12,7 +12,7 @@ <!-- /ko --> </label> - <div class="control"> + <div class="control" data-bind="css: {'_with-tooltip': element.tooltip}"> <!-- ko ifnot: element.hasAddons() --> <!-- ko template: element.elementTmpl --><!-- /ko --> <!-- /ko --> diff --git a/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..50df5c58c00ce7af4c6dc661ad541bcdcad91ad4 --- /dev/null +++ b/app/code/Magento/Ups/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="step-config" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="ups-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Ups/js/view/shipping-rates-validation</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js new file mode 100644 index 0000000000000000000000000000000000000000..9f22914a8d29b73f75c2dfc51dfc776ed284e557 --- /dev/null +++ b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'postcode': { + 'required': true + }, + 'country_id': { + 'required': true + } + }; + } + }; + } +); diff --git a/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..71dac1b92c10ff0cab212709c93478227c2262c1 --- /dev/null +++ b/app/code/Magento/Ups/view/frontend/web/js/model/shipping-rates-validator.js @@ -0,0 +1,30 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + './shipping-rates-validation-rules', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + return { + validationErrors: [], + validate: function(address) { + var self = this; + this.validationErrors = []; + $.each(validationRules.getRules(), function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + return !Boolean(this.validationErrors.length); + } + }; + } +); diff --git a/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js new file mode 100644 index 0000000000000000000000000000000000000000..42d6e855218d13fa54bad60bd238a4469bb1a565 --- /dev/null +++ b/app/code/Magento/Ups/view/frontend/web/js/view/shipping-rates-validation.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../model/shipping-rates-validator', + '../model/shipping-rates-validation-rules' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + upsShippingRatesValidator, + upsShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('ups', upsShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('ups', upsShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml new file mode 100644 index 0000000000000000000000000000000000000000..ed6d123a6e4dfc7c7f443a2339a0f5cbfbac3d2f --- /dev/null +++ b/app/code/Magento/Usps/view/frontend/layout/checkout_onepage_index.xml @@ -0,0 +1,42 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> + <body> + <referenceBlock name="checkout.root"> + <arguments> + <argument name="jsLayout" xsi:type="array"> + <item name="components" xsi:type="array"> + <item name="checkout" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="steps" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-step" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="step-config" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="shipping-rates-validation" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="usps-rates-validation" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Usps/js/view/shipping-rates-validation</item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </item> + </argument> + </arguments> + </referenceBlock> + </body> +</page> diff --git a/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js new file mode 100644 index 0000000000000000000000000000000000000000..85ec105f7e4b3ab6886fa28534b0530b44e1a61c --- /dev/null +++ b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validation-rules.js @@ -0,0 +1,23 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [], + function () { + "use strict"; + return { + getRules: function() { + return { + 'country_id': { + 'required': true + }, + 'postcode': { + 'required': false + } + }; + } + }; + } +); diff --git a/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js new file mode 100644 index 0000000000000000000000000000000000000000..b897eb4e83ccde4647aca4f656c4bbc67b261512 --- /dev/null +++ b/app/code/Magento/Usps/view/frontend/web/js/model/shipping-rates-validator.js @@ -0,0 +1,40 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*global define*/ +define( + [ + 'jquery', + 'mageUtils', + './shipping-rates-validation-rules', + 'mage/translate' + ], + function ($, utils, validationRules, $t) { + "use strict"; + var checkoutConfig = window.checkoutConfig; + + return { + validationErrors: [], + validate: function(address) { + var rules = validationRules.getRules(), + self = this; + + $.each(rules, function(field, rule) { + if (rule.required && utils.isEmpty(address[field])) { + var message = $t('Field ') + field + $t(' is required.'); + self.validationErrors.push(message); + } + }); + + if (!Boolean(this.validationErrors.length)) { + if (address.country_id == checkoutConfig.originCountryCode) { + return !utils.isEmpty(address.postcode); + } + return true; + } + return false; + } + }; + } +); diff --git a/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js b/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js new file mode 100644 index 0000000000000000000000000000000000000000..c47818efc2ede4a7aef4c48fcf7a4d58c5c712c9 --- /dev/null +++ b/app/code/Magento/Usps/view/frontend/web/js/view/shipping-rates-validation.js @@ -0,0 +1,27 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/shipping-rates-validator', + 'Magento_Checkout/js/model/shipping-rates-validation-rules', + '../model/shipping-rates-validator', + '../model/shipping-rates-validation-rules' + ], + function ( + Component, + defaultShippingRatesValidator, + defaultShippingRatesValidationRules, + uspsShippingRatesValidator, + uspsShippingRatesValidationRules + ) { + "use strict"; + defaultShippingRatesValidator.registerValidator('usps', uspsShippingRatesValidator); + defaultShippingRatesValidationRules.registerRules('usps', uspsShippingRatesValidationRules); + return Component; + } +); diff --git a/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php b/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php new file mode 100644 index 0000000000000000000000000000000000000000..772907c4b11381c761808f215afbaaba8fa9ae78 --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Model/Total/Observer/Webapi/ItemTest.php @@ -0,0 +1,190 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Weee\Test\Unit\Model\Total\Observer\Webapi; + +class ItemTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $weeeHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + + /** + * @var \Magento\Weee\Model\Total\Observer\Webapi\Item + */ + protected $model; + + protected function setUp() + { + $this->weeeHelperMock = $this->getMock('Magento\Weee\Helper\Data', [], [], '', false); + $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + + $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock)); + + $this->model = new \Magento\Weee\Model\Total\Observer\Webapi\Item( + $this->weeeHelperMock, + $this->storeManagerMock + ); + } + + /** + * @dataProvider processTaxDataDataProvider + * + * @param bool $helperIsEnabled + * @param int $weeeTaxInclTax + * @param int $rowTotal + * @param bool $weeeTaxRowApplied + * @param int $rowTotalInclTax + * @param int $rowWeeeInclTax + * @param int $weeeTaxApplied + * @param int $weeeTaxAppliedAmount + * @param bool $includeWeeeFlag + * @param int $priceIncTax + * @param int $calculationPrice + * @param int $expectedRowTotal + * @param int $expectedRowInclTax + * @param int $expectedPrice + * @param int $expectedPriceInclTax + * + * @SuppressWarnings(PHPMD.ExcessiveParameterList) + */ + public function testProcessTaxData( + $helperIsEnabled, + $weeeTaxInclTax, + $rowTotal, + $weeeTaxRowApplied, + $rowTotalInclTax, + $rowWeeeInclTax, + $weeeTaxApplied, + $weeeTaxAppliedAmount, + $includeWeeeFlag, + $priceIncTax, + $calculationPrice, + $expectedRowTotal, + $expectedRowInclTax, + $expectedPrice, + $expectedPriceInclTax + ) { + $observerMock = $this->getMock('Magento\Framework\Object', ['getEvent'], [], '', false); + $eventMock = $this->getMock('Magento\Framework\Event', ['getItem'], [], '', false); + $itemMock = $this->getMock( + 'Magento\Quote\Model\Quote\Item', + [ + 'setRowTotal', 'setRowTotalInclTax', 'setPrice', 'setPriceInclTax', + 'getPriceInclTax', 'getCalculationPrice', 'getRowTotal', 'getRowTotalInclTax', 'getWeeeTaxApplied', + 'getWeeeTaxAppliedRowAmount', 'getWeeeTaxAppliedAmount' + ], + [], + '', + false + ); + + $eventMock->expects($this->once())->method('getItem')->will($this->returnValue($itemMock)); + $observerMock->expects($this->once())->method('getEvent')->will($this->returnValue($eventMock)); + + $this->weeeHelperMock->expects($this->any())->method('isEnabled') + ->will($this->returnValue($helperIsEnabled)); + $this->weeeHelperMock->expects($this->any())->method('getWeeeTaxInclTax') + ->with($itemMock)->will($this->returnValue($weeeTaxInclTax)); + $this->weeeHelperMock->expects($this->any())->method('getRowWeeeTaxInclTax') + ->will($this->returnValue($rowWeeeInclTax)); + $this->weeeHelperMock->expects($this->any())->method('typeOfDisplay') + ->will($this->returnValue($includeWeeeFlag)); + + $weeeTaxApplied = serialize($weeeTaxApplied); + $itemMock->expects($this->any())->method('getPriceInclTax')->will($this->returnValue($priceIncTax)); + $itemMock->expects($this->any())->method('getCalculationPrice')->will($this->returnValue($calculationPrice)); + $itemMock->expects($this->any())->method('getRowTotal')->will($this->returnValue($rowTotal)); + $itemMock->expects($this->any())->method('getRowTotalInclTax')->will($this->returnValue($rowTotalInclTax)); + $itemMock->expects($this->any())->method('getWeeeTaxApplied')->will($this->returnValue($weeeTaxApplied)); + $itemMock->expects($this->any())->method('getWeeeTaxAppliedAmount') + ->will($this->returnValue($weeeTaxAppliedAmount)); + $itemMock->expects($this->any())->method('getWeeeTaxAppliedRowAmount') + ->will($this->returnValue($weeeTaxRowApplied)); + + $itemMock->expects($this->once())->method('setRowTotal')->with($expectedRowTotal) + ->will($this->returnSelf()); + $itemMock->expects($this->once())->method('setRowTotalInclTax')->with($expectedRowInclTax) + ->will($this->returnSelf()); + $itemMock->expects($this->once())->method('setPrice')->with($expectedPrice) + ->will($this->returnSelf()); + $itemMock->expects($this->once())->method('setPriceInclTax')->with($expectedPriceInclTax) + ->will($this->returnSelf()); + + $this->model->processTaxData($observerMock); + } + + /** + * @return array + */ + public function processTaxDataDataProvider() + { + return [ + [ + 'helperIsEnabled' => false, + 'weeeTaxInclTax' => 10, + 'rowTotal' => 17, + 'weeeTaxRowApplied' => 3, + 'rowTotalInclTax' => 11, + 'rowWeeeInclTax' => 14, + 'weeeTaxApplied' => 4, + 'weeeTaxAppliedAmount' => 4, + 'includeWeeeFlag' => false, + 'priceIncTax' => 5, + 'calculationPrice' => 12, + 'expectedRowTotal' => 17, + 'expectedRowInclTax' => 11, + 'expectedPrice' => 12, + 'expectedPriceInclTax' => 5 + ], + [ + 'helperIsEnabled' => true, + 'weeeTaxInclTax' => 10, + 'rowTotal' => 17, + 'weeeTaxRowApplied' => 3, + 'rowTotalInclTax' => 11, + 'rowWeeeInclTax' => 14, + 'weeeTaxApplied' => 4, + 'weeeTaxAppliedAmount' => 4, + 'includeWeeeFlag' => false, + 'priceIncTax' => 5, + 'calculationPrice' => 12, + 'expectedRowTotal' => 17, + 'expectedRowInclTax' => 11, + 'expectedPrice' => 12, + 'expectedPriceInclTax' => 5 + ], + [ + 'helperIsEnabled' => true, + 'weeeTaxInclTax' => 10, + 'rowTotal' => 17, + 'weeeTaxRowApplied' => 3, + 'rowTotalInclTax' => 11, + 'rowWeeeInclTax' => 14, + 'weeeTaxApplied' => 4, + 'weeeTaxAppliedAmount' => 4, + 'includeWeeeFlag' => true, + 'priceIncTax' => 5, + 'calculationPrice' => 12, + 'expectedRowTotal' => 20, + 'expectedRowInclTax' => 25, + 'expectedPrice' => 16, + 'expectedPriceInclTax' => 15 + ] + ]; + } +} diff --git a/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php b/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..548ad82139b34802fadc77310423804350e08924 --- /dev/null +++ b/app/code/Magento/Weee/Test/Unit/Model/WeeeConfigProviderTest.php @@ -0,0 +1,180 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Weee\Test\Unit\Model; + +class WeeeConfigProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $weeeHelperMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $weeeConfigMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + + /** + * @var \Magento\Weee\Model\WeeeConfigProvider + */ + protected $model; + + protected function setUp() + { + $this->weeeHelperMock = $this->getMock('Magento\Weee\Helper\Data', [], [], '', false); + $this->weeeConfigMock = $this->getMock('Magento\Weee\Model\Config', [], [], '', false); + $this->storeManagerMock = $this->getMock('Magento\Store\Model\StoreManagerInterface'); + $this->storeMock = $this->getMock('Magento\Store\Model\Store', [], [], '', false); + + $this->storeManagerMock->expects($this->any())->method('getStore')->will($this->returnValue($this->storeMock)); + + $this->model = new \Magento\Weee\Model\WeeeConfigProvider( + $this->weeeHelperMock, + $this->storeManagerMock, + $this->weeeConfigMock + ); + } + + /** + * @dataProvider getConfigDataProvider + * @param array $expectedResult + * @param bool $weeeHelperEnabled + * @param bool $displayWeeeDetails + * @param bool $weeeConfigEnabled + * @param bool $includeInSubtotal + */ + public function testGetConfig( + $expectedResult, + $weeeHelperEnabled, + $displayWeeeDetails, + $weeeConfigEnabled, + $includeInSubtotal + ) { + $storeId = 1; + $this->storeMock->expects($this->any())->method('getId')->will($this->returnValue($storeId)); + $this->weeeHelperMock->expects($this->any())->method('isEnabled')->with($storeId) + ->will($this->returnValue($weeeHelperEnabled)); + $this->weeeHelperMock->expects($this->any())->method('typeOfDisplay') + ->will($this->returnValue($displayWeeeDetails)); + + $this->weeeConfigMock->expects($this->any())->method('isEnabled') + ->will($this->returnValue($weeeConfigEnabled)); + $this->weeeConfigMock->expects($this->any())->method('includeInSubtotal') + ->will($this->returnValue($includeInSubtotal)); + + $this->assertEquals($expectedResult, $this->model->getConfig()); + } + + /** + * @return array + */ + public function getConfigDataProvider() + { + return [ + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => true, + 'isWeeeEnabled' => false, + 'isIncludedInSubtotal' => true, + 'getIncludeWeeeFlag' => true, + ], + 'weeeHelperEnabled' => false, + 'displayWeeeDetails' => true, + 'weeeConfigEnabled' => true, + 'includeInSubtotal' => true, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => true, + 'isDisplayFinalPrice' => true, + 'isWeeeEnabled' => true, + 'isIncludedInSubtotal' => true, + 'getIncludeWeeeFlag' => true, + ], + 'weeeHelperEnabled' => true, + 'displayWeeeDetails' => true, + 'weeeConfigEnabled' => true, + 'includeInSubtotal' => true, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => false, + 'isWeeeEnabled' => true, + 'isIncludedInSubtotal' => true, + 'getIncludeWeeeFlag' => false, + ], + 'weeeHelperEnabled' => true, + 'displayWeeeDetails' => false, + 'weeeConfigEnabled' => true, + 'includeInSubtotal' => true, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => false, + 'isWeeeEnabled' => false, + 'isIncludedInSubtotal' => true, + 'getIncludeWeeeFlag' => false, + ], + 'weeeHelperEnabled' => false, + 'displayWeeeDetails' => false, + 'weeeConfigEnabled' => true, + 'includeInSubtotal' => true, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => false, + 'isWeeeEnabled' => false, + 'isIncludedInSubtotal' => false, + 'getIncludeWeeeFlag' => false, + ], + 'weeeHelperEnabled' => false, + 'displayWeeeDetails' => false, + 'weeeConfigEnabled' => false, + 'includeInSubtotal' => true, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => false, + 'isWeeeEnabled' => false, + 'isIncludedInSubtotal' => false, + 'getIncludeWeeeFlag' => false, + ], + 'weeeHelperEnabled' => false, + 'displayWeeeDetails' => false, + 'weeeConfigEnabled' => true, + 'includeInSubtotal' => false, + ], + [ + 'expectedResult' => [ + 'isDisplayPriceWithWeeeDetails' => false, + 'isDisplayFinalPrice' => false, + 'isWeeeEnabled' => false, + 'isIncludedInSubtotal' => false, + 'getIncludeWeeeFlag' => false, + ], + 'weeeHelperEnabled' => false, + 'displayWeeeDetails' => false, + 'weeeConfigEnabled' => false, + 'includeInSubtotal' => false, + ], + ]; + } +} diff --git a/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml b/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml index e5aa37b3c77ed809a449fa828489f38808d2d3fa..6e3439d0775862400bec88a4cf5885f4005358e5 100644 --- a/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml +++ b/app/code/Magento/Weee/view/frontend/layout/checkout_onepage_index.xml @@ -5,6 +5,7 @@ * See COPYING.txt for license details. */ --> +<!-- TODO remove this file as soon as enhanced checkout is implemented --> <page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="../../../../../../../lib/internal/Magento/Framework/View/Layout/etc/page_configuration.xsd"> <body> <referenceBlock name="checkout.root"> @@ -13,50 +14,36 @@ <item name="components" xsi:type="array"> <item name="checkout" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="steps" xsi:type="array"> + <item name="summary" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="review" xsi:type="array"> + <item name="totals" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="columns" xsi:type="array"> + <item name="weee" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/summary/weee</item> + <item name="config" xsi:type="array"> + <item name="title" xsi:type="string">FPT</item> + </item> + </item> + </item> + </item> + <item name="cart_items" xsi:type="array"> + <item name="children" xsi:type="array"> + <item name="details" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="price" xsi:type="array"> - <item name="children" xsi:type="array"> - <item name="unit_incl_tax" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/unit_incl_tax</item> - <item name="displayArea" xsi:type="string">unit_incl_tax</item> - </item> - <item name="unit_excl_tax" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/unit_excl_tax</item> - <item name="displayArea" xsi:type="string">unit_excl_tax</item> - </item> - </item> - </item> <item name="subtotal" xsi:type="array"> <item name="children" xsi:type="array"> - <item name="row_incl_tax" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/row_incl_tax</item> - <item name="displayArea" xsi:type="string">row_incl_tax</item> + <item name="weee_row_incl_tax" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/summary/item/price/row_incl_tax</item> + <item name="displayArea" xsi:type="string">row_incl_tax</item> </item> - <item name="row_excl_tax" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/item/price/row_excl_tax</item> + <item name="weee_row_excl_tax" xsi:type="array"> + <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/summary/item/price/row_excl_tax</item> <item name="displayArea" xsi:type="string">row_excl_tax</item> </item> </item> </item> </item> </item> - <item name="totals" xsi:type="array"> - <item name="children" xsi:type="array"> - <item name="before_grandtotal" xsi:type="array"> - <item name="children" xsi:type="array"> - <item name="weee_total" xsi:type="array"> - <item name="component" xsi:type="string">Magento_Weee/js/view/checkout/review/weee_total</item> - </item> - </item> - </item> - </item> - </item> - </item> </item> </item> diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js deleted file mode 100644 index 484b00bacb94409548202088b0d36b5dce9c113c..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_excl_tax.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'Magento_Weee/js/view/checkout/review/item/price/weee' - ], - function (weee) { - "use strict"; - return weee.extend({ - defaults: { - template: 'Magento_Weee/checkout/review/item/price/unit_excl_tax' - }, - - getFinalUnitDisplayPriceExclTax: function(item) { - var unitExclTax = parseFloat(item.price); - if(!window.checkoutConfig.getIncludeWeeeFlag) { - return unitExclTax + parseFloat(item.weee_tax_applied_amount); - } - return unitExclTax; - } - }); - } -); diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js deleted file mode 100644 index d6e03c37b5e1a9b7c6db4ef86ebd2bb67736a1ce..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/unit_incl_tax.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'Magento_Weee/js/view/checkout/review/item/price/weee' - ], - function (weee) { - "use strict"; - return weee.extend({ - defaults: { - template: 'Magento_Weee/checkout/review/item/price/unit_incl_tax' - }, - getFinalUnitDisplayPriceInclTax: function(item) { - var unitInclTax = parseFloat(item.price_incl_tax); - if(!window.checkoutConfig.getIncludeWeeeFlag) { - return unitInclTax + this.getWeeeTaxInclTax(item); - } - return unitInclTax; - }, - getWeeeTaxInclTax: function(item) { - var weeeTaxAppliedAmounts = JSON.parse(item.weee_tax_applied); - var totalWeeeTaxIncTaxApplied = 0; - weeeTaxAppliedAmounts.forEach(function (weeeTaxAppliedAmount) { - totalWeeeTaxIncTaxApplied+=parseFloat(Math.max(weeeTaxAppliedAmount.amount_incl_tax, 0)); - }); - return totalWeeeTaxIncTaxApplied; - } - }); - } -); diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js deleted file mode 100644 index 41aec2c8475928ad094bd69f433f7f12fe689020..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/weee_total.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -/*browser:true*/ -/*global define*/ -define( - [ - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' - ], - function (Component,quote, priceUtils) { - "use strict"; - return Component.extend({ - defaults: { - colspan: 3, - displayArea: 'before_grandtotal', - title: 'FPT', - template: 'Magento_Weee/checkout/review/weee_total' - }, - isIncludedInSubtotal: window.checkoutConfig.isIncludedInSubtotal, - totals: quote.getTotals(), - getColspan: function() { - return this.colspan; - }, - getTitle: function() { - return this.title; - }, - getPureValue: function() { - var items = quote.getItems(); - var sum = 0; - for (var i = 0; i < items.length; i++) { - sum += parseFloat(items[i].weee_tax_applied_row_amount); - } - return sum; - }, - getValue: function() { - var items = quote.getItems(); - var sum = 0; - for (var i = 0; i < items.length; i++) { - sum += parseFloat(items[i].weee_tax_applied_row_amount); - } - return priceUtils.formatPrice(sum, quote.getPriceFormat()); - } - }); - } -); diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js similarity index 81% rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js index 000d08a5ca07a481989b64f76aa1376ec9cedac8..07c7f94305e991453c0eeb7d8d51550fd94db966 100644 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_excl_tax.js +++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_excl_tax.js @@ -6,13 +6,13 @@ /*global define*/ define( [ - 'Magento_Weee/js/view/checkout/review/item/price/weee' + 'Magento_Weee/js/view/checkout/summary/item/price/weee' ], function (weee) { "use strict"; return weee.extend({ defaults: { - template: 'Magento_Weee/checkout/review/item/price/row_excl_tax' + template: 'Magento_Weee/checkout/summary/item/price/row_excl_tax' }, getFinalRowDisplayPriceExclTax: function(item) { diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js similarity index 88% rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js index 6fc8b67643282d0a8bea4cb700baa37b56dbdff4..15aec47fd0f36c377a513757c4f207d05bd71ed0 100644 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/row_incl_tax.js +++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/row_incl_tax.js @@ -6,13 +6,13 @@ /*global define*/ define( [ - 'Magento_Weee/js/view/checkout/review/item/price/weee' + 'Magento_Weee/js/view/checkout/summary/item/price/weee' ], function (weee) { "use strict"; return weee.extend({ defaults: { - template: 'Magento_Weee/checkout/review/item/price/row_incl_tax', + template: 'Magento_Weee/checkout/summary/item/price/row_incl_tax', displayArea: 'row_incl_tax' }, getFinalRowDisplayPriceInclTax: function(item) { diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js similarity index 77% rename from app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js rename to app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js index f6c146aa688fb67e68d3d82cf383ec3726605ea9..919504bd6270e066a0caa6aacf47506e69ec4e9b 100644 --- a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/review/item/price/weee.js +++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/item/price/weee.js @@ -6,11 +6,10 @@ /*global define*/ define( [ - 'uiComponent', - 'Magento_Checkout/js/model/quote', - 'Magento_Catalog/js/price-utils' + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote' ], - function (Component,quote, priceUtils) { + function (Component,quote) { "use strict"; return Component.extend({ @@ -26,9 +25,6 @@ define( } return window.checkoutConfig.isDisplayFinalPrice; }, - getFormattedPrice: function (price) { - return priceUtils.formatPrice(price, quote.getPriceFormat()); - }, getWeeeTaxApplied: function(item) { if (item.weee_tax_applied) { return JSON.parse(item.weee_tax_applied) diff --git a/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js new file mode 100644 index 0000000000000000000000000000000000000000..22209e41d2028a98c61b8b3876345ff5e1d33f4b --- /dev/null +++ b/app/code/Magento/Weee/view/frontend/web/js/view/checkout/summary/weee.js @@ -0,0 +1,31 @@ +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +/*browser:true*/ +/*global define*/ +define( + [ + 'Magento_Checkout/js/view/summary/abstract-total', + 'Magento_Checkout/js/model/quote', + 'Magento_Checkout/js/model/totals', + 'Magento_Catalog/js/price-utils' + ], + function (Component,quote, totals) { + "use strict"; + return Component.extend({ + defaults: { + template: 'Magento_Weee/checkout/summary/weee' + }, + isIncludedInSubtotal: window.checkoutConfig.isIncludedInSubtotal, + totals: totals.totals, + getValue: function() { + return this.getFormattedPrice(this.totals()['weee_tax_applied_amount']); + }, + isDisplayed: function() { + return this.isFullMode() && this.isIncludedInSubtotal && + this.totals()['weee_tax_applied_amount'] > 0; + } + }); + } +); diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html deleted file mode 100644 index bfaa8c3f176722b4e50b1c0e7ff9f0bff45410af..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_incl_tax.html +++ /dev/null @@ -1,37 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> -<!-- ko if: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+item.item_id}}"> - <span class="price" data-bind="text: getFormattedPrice(item.row_total_incl_tax)"></span> - </span> -<!-- /ko --> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.row_total_incl_tax)"></span></span> -<!-- /ko --> - -<!--ko if: getWeeeTaxApplied(item).length > 0--> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item))--> -<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + item.item_id}" style="display: none;"></span> -<!-- /ko--> -<!-- ko if: (isDisplayPriceWithWeeeDetails(item))--> -<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + item.item_id}" style="display: none;"> - <!-- ko foreach: getWeeeTaxApplied(item)--> - <span class="weee" data-bind="attr:{'data-label':title}"> - <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount_incl_tax)"></span> - </span> - <!-- /ko--> - </span> -<!-- /ko--> - -<!-- ko if: isDisplayFinalPrice(item)--> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+item.item_id}}"> - <span class="weee" data-bind="attr: {'data-label':$t('Total Incl. Tax')}"> - <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceInclTax(item))"></span> - </span> - </span> -<!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html deleted file mode 100644 index eb34f588887cef129456b0c537b5dffc9260bb40..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_excl_tax.html +++ /dev/null @@ -1,40 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<!-- ko if: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-tax-total" data-bind="mageInit:{taxToggle: {itemTaxId : '#eunit-item-tax-details' + item.item_id}}"> - <span class="price" data-bind="text: getFormattedPrice(item.price)"></span> - </span> -<!-- /ko --> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.price)"></span></span> -<!-- /ko --> - - -<!--ko if: (getWeeeTaxApplied(item).length > 0)--> - <!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item))--> - <span class="cart-tax-info" data-bind ="attr: {'id': 'eunit-item-tax-details' + item.item_id}" style="display: none;"></span> - <!-- /ko--> - <!-- ko if: (isDisplayPriceWithWeeeDetails(item))--> - <span class="cart-tax-info" data-bind ="attr: {'id': 'eunit-item-tax-details' + item.item_id}" style="display: none;"> - <!-- ko foreach: getWeeeTaxApplied(item)--> - <span class="weee" data-bind="attr:{'data-label':title}"> - <span class="price" data-bind="text: $parent.getFormattedPrice(amount)"></span> - </span> - <!-- /ko--> - </span> - <!-- /ko--> - - - <!-- ko if: isDisplayFinalPrice(item)--> - <span class="cart-tax-total" data-bind="mageInit:{taxToggle: {itemTaxId : '#eunit-item-tax-details' + item.item_id}}"> - <span class="weee" data-bind="attr: {'data-label':$t('Total')}"> - <span class="price" data-bind="text: getFormattedPrice(getFinalUnitDisplayPriceExclTax(item))"></span> - </span> - </span> - <!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html deleted file mode 100644 index 1a67282073225531a6137bd83361a08d60c2287e..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/unit_incl_tax.html +++ /dev/null @@ -1,38 +0,0 @@ -<!-- -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ ---> - -<!-- ko if: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#unit-item-tax-details'+item.item_id}}"> - <span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span> - </span> -<!-- /ko --> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.price_incl_tax)"></span></span> -<!-- /ko --> - -<!--ko if: (getWeeeTaxApplied(item).length > 0)--> - <!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item))--> - <span class="cart-tax-info" data-bind ="attr: {'id': 'unit-item-tax-details' + item.item_id}" style="display: none;"></span> - <!-- /ko--> - <!-- ko if: (isDisplayPriceWithWeeeDetails(item))--> - <span class="cart-tax-info" data-bind ="attr: {'id': 'unit-item-tax-details' + item.item_id}" style="display: none;"> - <!-- ko foreach: getWeeeTaxApplied(item)--> - <span class="weee" data-bind="attr:{'data-label':title}"> - <span class="price" data-bind="text: $parent.getFormattedPrice(amount_incl_tax)"></span> - </span> - <!-- /ko--> - </span> - <!-- /ko--> - - <!-- ko if: isDisplayFinalPrice(item)--> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#unit-item-tax-details'+item.item_id}}"> - <span class="weee" data-bind="attr: {'data-label':$t('Total Incl. Tax')}"> - <span class="price" data-bind="text: getFormattedPrice(getFinalUnitDisplayPriceInclTax(item))"></span> - </span> - </span> - <!-- /ko --> -<!-- /ko --> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html deleted file mode 100644 index 3e9b25d84db8239da763e6bc4d740bcd6dc947f1..0000000000000000000000000000000000000000 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/weee_total.html +++ /dev/null @@ -1,14 +0,0 @@ -<!-- -/** -* Copyright © 2015 Magento. All rights reserved. -* See COPYING.txt for license details. -*/ ---> -<!-- ko if: isIncludedInSubtotal && getPureValue() > 0 --> -<tr class="totals"> - <th data-bind="text: getTitle(), attr: {'colspan': getColspan()}" class="mark" scope="row"></th> - <td class="amount" data-bind="attr: {'data-th': $t(getTitle()) }"> - <span data-bind="text: getValue()"></span> - </td> -</tr> -<!-- /ko --> \ No newline at end of file diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html similarity index 51% rename from app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html rename to app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html index c1a8590e1fe157967c7490e497ba072389d45399..39e2bfa7815e8d8d5658ae91b0838982ce62636b 100644 --- a/app/code/Magento/Weee/view/frontend/web/template/checkout/review/item/price/row_excl_tax.html +++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_excl_tax.html @@ -4,22 +4,22 @@ * See COPYING.txt for license details. */ --> -<!-- ko if: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+item.item_id}}"> - <span class="price" data-bind="text: getFormattedPrice(item.row_total)"></span> +<!-- ko if: (isDisplayPriceWithWeeeDetails($parents[2])) --> + <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+$parents[2].item_id}}"> + <span class="price" data-bind="text: getFormattedPrice($parents[2].row_total)"></span> </span> <!-- /ko --> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item)) --> - <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice(item.row_total)"></span></span> +<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2])) --> + <span class="cart-price"><span class="price" data-bind="text: getFormattedPrice($parents[2].row_total)"></span></span> <!-- /ko --> -<!--ko if: (getWeeeTaxApplied(item).length > 0)--> -<!-- ko ifnot: (isDisplayPriceWithWeeeDetails(item))--> -<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + item.item_id}" style="display: none;"></span> +<!--ko if: (getWeeeTaxApplied($parents[2]).length > 0)--> +<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2]))--> +<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"></span> <!-- /ko--> -<!-- ko if: (isDisplayPriceWithWeeeDetails(item))--> -<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + item.item_id}" style="display: none;"> - <!-- ko foreach: getWeeeTaxApplied(item)--> +<!-- ko if: (isDisplayPriceWithWeeeDetails($parents[2]))--> +<span class="cart-tax-info" data-bind ="attr: {'id': 'esubtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"> + <!-- ko foreach: getWeeeTaxApplied($parents[2])--> <span class="weee" data-bind="attr:{'data-label':title}"> <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount)"></span> </span> @@ -27,10 +27,10 @@ </span> <!-- /ko--> -<!-- ko if: isDisplayFinalPrice(item)--> - <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+item.item_id}}"> +<!-- ko if: isDisplayFinalPrice($parents[2])--> + <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#esubtotal-item-tax-details'+$parents[2].item_id}}"> <span class="weee" data-bind="attr: {'data-label':$t('Total')}"> - <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceExclTax(item))"> + <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceExclTax($parents[2]))"> </span> </span> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html new file mode 100644 index 0000000000000000000000000000000000000000..562bd3293cf960a41046ebb132d3258c8e5a1651 --- /dev/null +++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/item/price/row_incl_tax.html @@ -0,0 +1,37 @@ +<!-- +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<!-- ko if: (isDisplayPriceWithWeeeDetails($parents[2])) --> + <span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+$parents[2].item_id}}"> + <span class="price" data-bind="text: getFormattedPrice($parents[2].row_total_incl_tax)"></span> + </span> +<!-- /ko --> +<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2])) --> +<span class="cart-price"><span class="price" data-bind="text: getFormattedPrice($parents[2].row_total_incl_tax)"></span></span> +<!-- /ko --> + +<!--ko if: getWeeeTaxApplied($parents[2]).length > 0--> +<!-- ko ifnot: (isDisplayPriceWithWeeeDetails($parents[2]))--> +<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"></span> +<!-- /ko--> +<!-- ko if: (isDisplayPriceWithWeeeDetails($parents[2]))--> +<span class="cart-tax-info" data-bind ="attr: {'id': 'subtotal-item-tax-details' + $parents[2].item_id}" style="display: none;"> + <!-- ko foreach: getWeeeTaxApplied($parents[2])--> + <span class="weee" data-bind="attr:{'data-label':title}"> + <span class="price" data-bind="text: $parent.getFormattedPrice(row_amount_incl_tax)"></span> + </span> + <!-- /ko--> + </span> +<!-- /ko--> + +<!-- ko if: isDisplayFinalPrice($parents[2])--> +<span class="cart-tax-total" data-bind="mageInit: {taxToggle: {itemTaxId : '#subtotal-item-tax-details'+$parents[2].item_id}}"> + <span class="weee" data-bind="attr: {'data-label':$t('Total incl. tax')}"> + <span class="price" data-bind="text: getFormattedPrice(getFinalRowDisplayPriceInclTax($parents[2]))"></span> + </span> + </span> +<!-- /ko --> +<!-- /ko --> diff --git a/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html new file mode 100644 index 0000000000000000000000000000000000000000..7a3696a829ef86c82efc2a53342c25cadbdb451e --- /dev/null +++ b/app/code/Magento/Weee/view/frontend/web/template/checkout/summary/weee.html @@ -0,0 +1,14 @@ +<!-- +/** +* Copyright © 2015 Magento. All rights reserved. +* See COPYING.txt for license details. +*/ +--> +<!-- ko if: isDisplayed() --> +<tr class="totals"> + <th data-bind="text: title" class="mark" scope="row"></th> + <td class="amount" data-bind="attr: {'data-th': $t(title) }"> + <span data-bind="text: getValue()"></span> + </td> +</tr> +<!-- /ko --> \ No newline at end of file diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less index 8795421c0d241fc95cdaf6a43e597fdd2fb8f13e..85932830410a8ee3ef47bc3eabf105116270a9cc 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/_module.less @@ -5,448 +5,4 @@ @import 'module/_cart.less'; @import 'module/_minicart.less'; - -@desktop-form-field-vertical-indent: 29px; - -// -// Common -// _____________________________________________ - -& when (@media-common = true) { - - // - // One Page Checkout - // --------------------------------------------- - - .opc-wrapper:extend(.abs-add-box-sizing all) { - .css(padding-bottom, @indent__xl); - > .opc:extend(.abs-reset-list all) { - } - .section { - &.allow .step-title { - cursor: pointer; - } - &.active { - .step { - &-title { - .css(color, @primary__color__darker); - cursor: default; - } - &-content { - display: block; - } - } - } - } - .step { - &-title { - border-bottom: @border-width__base solid @border-color__base; - .css(color, @primary__color__lighter); - line-height: 50px; - h2, - .number { - display: inline-block; - .heading(h3); - } - .number:after { - content: '.'; - } - } - &-content { - display: none; - padding: @indent__base @indent__s; - position: relative; - .addresses .control { - margin: @indent__base 0; - } - .fieldset { - margin-bottom: 0; - &.login { - .form-hasrequired(bottom); - &:after { - margin-top: 35px; - text-align: center; - } - } - > .field { - margin: @form-field__vertical-indent 0 0; - } - &.address { - .field:first-of-type:not(.additional) { - margin: 0; - } - } - .legend.payments-title:extend(.abs-visually-hidden all) { - } - } - .methods-shipping { - .item-content { - .fieldset { - > .legend:extend(.abs-visually-hidden all) { - } - > .legend + br:extend(.abs-no-display all) { - } - > .field { - margin: @indent__base 0 0; - &:before { - display: none; - } - .control { - display: inline-block; - } - } - br + .field { - margin: 0; - } - } - } - } - .form { - .form-hasrequired(bottom); - &:after { - text-align: center; - } - .field:not(:first-child) { - margin: @indent__base 0 0; - } - > .field.choice { - margin: @form-field__vertical-indent 0 0; - } - .field { - &.month { - padding-right: @indent__s; - } - &.year { - margin-top: 0; - } - } - } - .form:not(.login), - .order-review { - .action.primary:extend(.abs-button-l all) { - } - } - .actions { - margin-top: @indent__base; - } - .field.street { - .field.additional { - .label:extend(.abs-visually-hidden all) { - } - } - } - } - } - - .opc-payment-additional { - margin: 0 0 @indent__xs; - + .opc-payment { - margin: @indent__base 0 0; - } - } - - // - // Order review - // --------------------------------------------- - - .order-review { - .fieldset > .field > .label { - font-weight: @font-weight__regular; - } - .product-item-name { - margin: 0; - } - } - - .data.table:extend(.abs-product-options-list all) { - .col { - &.price, - &.qty { - text-align: center; - white-space: nowrap; - } - } - .item-options:extend(.abs-add-clearfix all) { - font-size: @font-size__s; - margin: @indent__s 0 0; - } - .cart-price:extend(.abs-checkout-cart-price all) { - } - } - - .action.primary.checkout { - margin: 0 0 @indent__base; - } - - .hidden:extend(.abs-no-display all) { - } - - // - // Customer login - // --------------------------------------------- - - .login-wrapper { - .block { - .block-title:extend(.abs-login-block-title all) { - } - .fieldset.guest { - margin-top: @indent__base; - } - .field.choice { - margin-bottom: @indent__s; - } - } - } - - .actions-toolbar { - margin: @indent__xl 0 0; - } - } - - // - // Shipping methods - // --------------------------------------------- - - .methods-shipping { - .item-title:extend(.abs-methods-shipping-title all) { - } - .item-content:extend(.abs-adjustment-incl-excl-tax all) { - margin: 0 0 @indent__xl; - .price { - font-weight: @font-weight__bold; - } - .field.choice { - margin: 0 0 @indent__s; - .control { - float: left; - } - .label { - display: block; - overflow: hidden; - } - } - } - .price-box { - margin-bottom: @indent__xs; - margin-left: @indent__xl; - margin-top: @indent__s; - .label + .price { - font-weight: @font-weight__bold; - } - } - img { - vertical-align: middle; - } - } - - // - // Payment methods - // --------------------------------------------- - - .methods-payment { - .item { - &-title { - font-weight: @font-weight__regular; - } - &-content { - margin: 0 0 0 @indent__base; - .label { - font-weight: @font-weight__regular; - } - } - } - .fieldset { - padding: 15px 0 @indent__m; - } - .fieldset & { - .item-content > .fieldset > .field:first-child { - margin-top: 0; - } - } - .redirect { - .font-size(@font-size__s); - padding: 0 0 15px; - } - img { - margin-right: @indent__xs; - vertical-align: middle; - } - } - - .cart-tax-info + .cart-tax-total { - display: block; - } - - // - // Checkout Progress - // --------------------------------------------- - - .opc-block-progress:extend(.abs-add-box-sizing all) { - margin-bottom: @indent__l; - > .title { - .css(background, @sidebar__background-color); - .heading(h3); - margin: 0; - padding: 15px 15px @indent__base; - strong { - font-weight: @font-weight__regular; - } - } - > .content { - .css(background, @sidebar__background-color); - padding: 0 15px @indent__xs; - .item-content.complete { - margin: 0 0 15px; - overflow: hidden; - } - .action, - .payment-method .title { - font-weight: @font-weight__regular; - } - .data.table { - font-size: @font-size__s; - } - } - .payment-method { - > .title { - font-weight: @font-weight__light; - } - > .content { - margin: 0 0 @indent__s; - &:last-child { - margin-bottom: 0; - } - } - .items-cards { - margin: 0; - > .content { - margin: 0; - } - } - .data.table { - th { - padding: @indent__xs @indent__s @indent__xs 0; - } - td { - padding: @indent__xs 0; - } - } - } - } - - // - // Checkout Success - // --------------------------------------------- - - .checkout-onepage-success { - .page-title-wrapper { - .print:extend(.abs-no-display all) { - } - } - } - - .checkout-success { - .actions-toolbar { - margin-top: @indent__xl; - } - } - - .checkout-onepage-index { - .nav-toggle:extend(.abs-no-display all) { - } - .logo { - margin-left: 0; - } - } -} - -// -// Mobile -// _____________________________________________ - -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { - .opc-wrapper { - table.data.table:extend(.abs-checkout-order-review all) { - } - } -} - -// -// Desktop -// _____________________________________________ - -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { - .checkout-onepage-index .column.main:extend(.abs-add-clearfix-desktop-s all) { - } - - .opc-wrapper:extend(.abs-add-box-sizing-desktop-s all) { - .layout-column(2, 2, @layout-column-checkout__width-main); - .step-content { - padding: @indent__base 18px @indent__xl; - .addresses .control { - margin-bottom: @desktop-form-field-vertical-indent; - } - .form { - &:after { - text-align: right; - } - &:not(.login) { - .actions-toolbar:extend(.abs-reset-left-margin-desktop-s all) { - } - } - > .field.choice, - .fieldset > .field { - margin: @desktop-form-field-vertical-indent 0 0; - } - .fieldset.address { - .field:first-of-type:not(.additional) { - margin: 0; - } - } - } - .fieldset.login:after:extend(.abs-margin-for-forms-desktop-s all) { - text-align: left; - } - } - } - - .opc-block-progress:extend(.abs-add-box-sizing-desktop-s all) { - .layout-column(2, 1, @layout-column-checkout__width-left); - padding-right: @layout-column-main__sidebar-offset; - } - - .login-wrapper:extend(.abs-add-clearfix-desktop-s all) { - .block:extend(.abs-blocks-2columns-s all) { - } - .field.choice:not(.persistent) { - &:before { - display: none; - } - } - .fieldset.login { - .actions:extend(.abs-margin-for-forms-desktop-s all) { - } - } - } - - // - // Checkout success - // --------------------------------------------- - - .checkout-onepage-success { - .page-title-wrapper { - .print { - display: inline-block; - .font-size(14); - margin-left: @indent__xl; - } - } - } - - .table-order-review { - .col.subtotal, - .amount { - text-align: right; - } - } -} +@import 'module/_checkout.less'; diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less index 089a66bff442b12dda09f922093d1e215abc9e43..fa4e5ad9ad23c9e319d9291c51799ce02bb1364c 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_cart.less @@ -9,315 +9,236 @@ & when (@media-common = true) { - // - // Shopping cart - // --------------------------------------------- + // + // Shopping cart + // --------------------------------------------- - .cart { - // Summary block - &-summary { - &:extend(.abs-add-box-sizing all); - .css(background, @sidebar__background-color); - margin-bottom: @indent__m; - padding: 1px 15px @indent__m; - > .title { - display: block; - .heading(h3); - } - .block { - margin-bottom: 0; - > .title { - border-top: @border-width__base solid @border-color__base; - cursor: pointer; - font-weight: @font-weight__semibold; - .icon-font( - @_icon-font-content: @icon-down, - @_icon-font-size: 30px, - @_icon-font-position: after, - @_icon-font-display: block - ); - margin-bottom: 0; - overflow: hidden; - padding: 7px @indent__base 7px @indent__xs; - position: relative; - &:after { - position: absolute; - right: 0; - top: -5px; - } - strong { - .column.main & { - .font-size(18); - font-weight: @font-weight__regular; - } - } - } - > .content { - display: none; - } - &.active { - > .title { - .icon-font-symbol( - @_icon-font-content: @icon-prev, - @_icon-font-position: after - ); - } - > .content { - display: block; - } - } - .item-options { - margin-left: 0; - } - .fieldset { - margin: 15px 0 @indent__m @indent__xs; - .field { - margin: 0 0 @indent__s; - &.note { - font-size: @font-size__s; - } - } - } - .fieldset { - .methods { - .field { - > .label { - display: inline; - } - } - } - } - .fieldset.estimate { - > .legend, - > .legend + br { - &:extend(.abs-no-display all); - } - } - } - .actions-toolbar { - > .primary { - button { - &:extend(.abs-revert-secondary-color all); - } - } - } - &:extend(.abs-adjustment-incl-excl-tax all); + .cart { + // Summary block + &-summary { + &:extend(.abs-add-box-sizing all); + .css(background, @sidebar__background-color); + margin-bottom: @indent__m; + padding: 1px 15px @indent__m; + > .title { + display: block; + .heading(h3); + } + .block { + margin-bottom: 0; + > .title { + border-top: @border-width__base solid @border-color__base; + cursor: pointer; + font-weight: @font-weight__semibold; + .icon-font( + @_icon-font-content: @icon-down, + @_icon-font-size: 30px, + @_icon-font-position: after, + @_icon-font-display: block + ); + margin-bottom: 0; + overflow: hidden; + padding: 7px @indent__base 7px @indent__xs; + position: relative; + &:after { + position: absolute; + right: 0; + top: -5px; + } + strong { + .column.main & { + .font-size(18); + font-weight: @font-weight__regular; + } + } } - - // Totals block - &-totals { - border-top: 1px solid @border-color__base; - padding-top: 10px; - .table-wrapper { - overflow: inherit; - } - .mark { - font-weight: @font-weight__regular; - padding-left: 4px; - strong { - font-weight: @font-weight__regular; - } - } - .amount { - padding-right: 4px; - text-align: right; - strong { - font-weight: @font-weight__regular; - } - } - .grand:last-child { - .mark, - .amount { - padding-top: @indent__base; - } - .amount { - padding-right: 4px; - text-align: right; - strong { - font-weight: @font-weight__bold; - } - } - } - .msrp { - margin-bottom: @indent__s; - } - .totals-tax { - &-summary { - .mark, - .amount { - border-bottom: @border-width__base solid @border-color__base; - border-top: @border-width__base solid @border-color__base; - cursor: pointer; - } - .amount .price { - .icon-font( - @icon-down, - @_icon-font-size: 30px, - @_icon-font-text-hide: true, - @_icon-font-position: after, - @_icon-font-display: block - ); - padding-right: @indent__m; - position: relative; - &:after { - position: absolute; - right: -5px; - top: -12px; - } - } - &.expanded { - .mark, - .amount { - border-bottom: 0; - } - .amount .price { - .icon-font-symbol( - @_icon-font-content: @icon-up, - @_icon-font-position: after - ); - } - } - } - &-details { - border-bottom: @border-width__base solid @border-color__base; - display: none; - &.shown { - display: table-row; - } - } - } - .table-wrapper { - margin-bottom: 0; - } - .table-caption { - &:extend(.abs-no-display all); - } + > .content { + display: none; } + &.active { + > .title { + .icon-font-symbol( + @_icon-font-content: @icon-prev, + @_icon-font-position: after + ); + } + > .content { + display: block; + } + } + .item-options { + margin-left: 0; + } + .fieldset { + margin: 15px 0 @indent__m @indent__xs; + .field { + margin: 0 0 @indent__s; + &.note { + font-size: @font-size__s; + } + } + } + .fieldset { + .methods { + .field { + > .label { + display: inline; + } + } + } + } + .fieldset.estimate { + > .legend, + > .legend + br { + &:extend(.abs-no-display all); + } + } + } + .actions-toolbar { + > .primary { + button { + &:extend(.abs-revert-secondary-color all); + } + } + } + &:extend(.abs-adjustment-incl-excl-tax all); + } - // Products table - &.table-wrapper { - .items { - thead + .item { - border-top: @border-width__base solid @border-color__base; - } - > .item { - border-bottom: @border-width__base solid @border-color__base; - position: relative; - } - } - .col { - padding-top: 20px; - &.qty { - .input-text { - margin-top: -5px; - &:extend(.abs-input-qty all); - } - .label { - &:extend(.abs-visually-hidden all); - } - } - } - .item { - &-actions td { - padding-bottom: @indent__s; - text-align: center; - white-space: normal; - } - .col { - &.item { - display: block; - min-height: 75px; - padding: @indent__m 0 @indent__s 75px; - position: relative; - } - } - } - .actions-toolbar { - &:extend(.abs-add-clearfix all); - > .action { - &:extend(button all); - .link-as-button(); - margin-bottom: @indent__s; - margin-right: @indent__s; - &:last-child { - margin-right: 0; - } - } - } - .action { - &.help.map { - &:extend(.abs-action-button-as-link all); - font-weight: @font-weight__regular; - } - } - .product { - &-item-photo { - display: block; - left: 0; - max-width: 60px; - padding: 0; - position: absolute; - top: 15px; - width: 100%; - } - &-item-details { - white-space: normal; - } - &-item-name { - display: inline-block; - font-weight: @font-weight__regular; - margin-top: -6px; - } - } - .gift-registry-name-label { - &:after { - content: ':'; - } - } - // Product options - .item-options { - font-size: @font-size__s; - margin-bottom: @indent__s; - &:extend(.abs-product-options-list all); - &:extend(.abs-add-clearfix all); - } - - .product-item-name + .item-options { - margin-top: @indent__s; - } + // Totals block + &-totals { + border-top: 1px solid @border-color__base; + padding-top: 10px; + &:extend(.abs-sidebar-totals all); + .table-wrapper { + margin-bottom: 0; + overflow: inherit; + } + } - .product-image-wrapper { - &:extend(.abs-reset-image-wrapper all); - } - .action.configure { - display: inline-block; - margin: 0 0 @indent__base; - } + // Products table + &.table-wrapper { + .items { + thead + .item { + border-top: @border-width__base solid @border-color__base; } - &-container { - .form-cart { - &:extend(.abs-shopping-cart-items all); - } - .checkout-methods-items { - margin-top: @indent__base; - &:extend(.abs-reset-list all); - text-align: center; - .action.primary { - &:extend(.abs-button-l all); - margin-bottom: @indent__s; - width: 100%; - } - } + > .item { + border-bottom: @border-width__base solid @border-color__base; + position: relative; } - } + } + .col { + padding-top: 20px; + &.qty { + .input-text { + margin-top: -5px; + &:extend(.abs-input-qty all); + } + .label { + &:extend(.abs-visually-hidden all); + } + } + } + .item { + &-actions td { + padding-bottom: @indent__s; + text-align: center; + white-space: normal; + } + .col { + &.item { + display: block; + min-height: 75px; + padding: @indent__m 0 @indent__s 75px; + position: relative; + } + } + } + .actions-toolbar { + &:extend(.abs-add-clearfix all); + > .action { + &:extend(button all); + .link-as-button(); + margin-bottom: @indent__s; + margin-right: @indent__s; + &:last-child { + margin-right: 0; + } + } + } + .action { + &.help.map { + &:extend(.abs-action-button-as-link all); + font-weight: @font-weight__regular; + } + } + .product { + &-item-photo { + display: block; + left: 0; + max-width: 60px; + padding: 0; + position: absolute; + top: 15px; + width: 100%; + } + &-item-details { + white-space: normal; + } + &-item-name { + display: inline-block; + font-weight: @font-weight__regular; + margin-top: -6px; + } + } + .gift-registry-name-label { + &:after { + content: ':'; + } + } + // Product options + .item-options { + font-size: @font-size__s; + margin-bottom: @indent__s; + &:extend(.abs-product-options-list all); + &:extend(.abs-add-clearfix all); + } - // - // Cross sell - // --------------------------------------------- + .product-item-name + .item-options { + margin-top: @indent__s; + } - .block.crosssell { - margin-top: 70px; + .product-image-wrapper { + &:extend(.abs-reset-image-wrapper all); + } + .action.configure { + display: inline-block; + margin: 0 0 @indent__base; + } + } + &-container { + .form-cart { + &:extend(.abs-shopping-cart-items all); + } + .checkout-methods-items { + margin-top: @indent__base; + &:extend(.abs-reset-list all); + text-align: center; + .action.primary { + &:extend(.abs-button-l all); + margin-bottom: @indent__s; + width: 100%; + } + } } + } + + // + // Cross sell + // --------------------------------------------- + + .block.crosssell { + margin-top: 70px; + } } // @@ -325,48 +246,48 @@ // _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { - .cart { - &.table-wrapper { - thead { - .col:not(.item) { - display: none; - } - } - .col { - &.qty, - &.price, - &.subtotal, - &.msrp { - box-sizing: border-box; - display: block; - float: left; - text-align: center; - white-space: nowrap; - width: 33%; - &:before { - content: attr(data-th) ':'; - display: block; - font-weight: @font-weight__bold; - padding-bottom: 10px; - } - } - &.msrp { - white-space: normal; - } - } - .item .col.item { - padding-bottom: 0; - } + .cart { + &.table-wrapper { + thead { + .col:not(.item) { + display: none; } - &-container { - .form-cart { - &:extend(.abs-shopping-cart-items-mobile all); - } + } + .col { + &.qty, + &.price, + &.subtotal, + &.msrp { + box-sizing: border-box; + display: block; + float: left; + text-align: center; + white-space: nowrap; + width: 33%; + &:before { + content: attr(data-th) ':'; + display: block; + font-weight: @font-weight__bold; + padding-bottom: 10px; + } } - &.table-wrapper { - overflow: inherit; + &.msrp { + white-space: normal; } + } + .item .col.item { + padding-bottom: 0; + } + } + &-container { + .form-cart { + &:extend(.abs-shopping-cart-items-mobile all); + } } + &.table-wrapper { + overflow: inherit; + } + } } // @@ -374,69 +295,69 @@ // _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { - .cart { - &-container { - &:extend(.abs-add-clearfix-desktop all); - .form-cart { - &:extend(.abs-shopping-cart-items-desktop all); - } - .widget { - float: left; - } + .cart { + &-container { + &:extend(.abs-add-clearfix-desktop all); + .form-cart { + &:extend(.abs-shopping-cart-items-desktop all); + } + .widget { + float: left; + } + } + &-summary { + float: right; + position: relative; + width: 23%; + .actions-toolbar { + .column.main & { + &:extend(.abs-reset-left-margin-desktop all); + > .secondary { + float: none; + } } - &-summary { - float: right; - position: relative; - width: 23%; - .actions-toolbar { - .column.main & { - &:extend(.abs-reset-left-margin-desktop all); - > .secondary { - float: none; - } - } - } - .block { - .fieldset { - .field { - .form-field-type-revert(@_type: block); - margin: 0 0 @indent__s; - } - } - } + } + .block { + .fieldset { + .field { + .form-field-type-revert(@_type: block); + margin: 0 0 @indent__s; + } } + } + } - &.table-wrapper { - .item { - .col { - &.item { - padding: 27px 8px @indent__s; - } - } - &-actions td { - text-align: right; - } - } - .product { - &-item-photo { - display: table-cell; - max-width: 100%; - padding-right: @indent__base; - position: static; - vertical-align: top; - width: 1%; - } - &-item-details { - display: table-cell; - vertical-align: top; - white-space: normal; - width: 99%; - } - } - .item-actions .actions-toolbar { - text-align: left; - &:extend(.abs-reset-left-margin-desktop all); - } + &.table-wrapper { + .item { + .col { + &.item { + padding: 27px 8px @indent__s; + } + } + &-actions td { + text-align: right; + } + } + .product { + &-item-photo { + display: table-cell; + max-width: 100%; + padding-right: @indent__base; + position: static; + vertical-align: top; + width: 1%; + } + &-item-details { + display: table-cell; + vertical-align: top; + white-space: normal; + width: 99%; } + } + .item-actions .actions-toolbar { + text-align: left; + &:extend(.abs-reset-left-margin-desktop all); + } } + } } diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less new file mode 100644 index 0000000000000000000000000000000000000000..db93ffc7fe3f173d56b45df4318ea789099a0b04 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_checkout.less @@ -0,0 +1,26 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Page components +// --------------------------------------------- + +@import 'checkout/_checkout.less'; +@import 'checkout/_estimated-total.less'; +@import 'checkout/_progress-bar.less'; +@import 'checkout/_fields.less'; +@import 'checkout/_modals.less'; +@import 'checkout/_tooltip.less'; +@import 'checkout/_shipping.less'; +@import 'checkout/_shipping-policy.less'; + +@import 'checkout/_sidebar.less'; +@import 'checkout/_sidebar-shipping-information.less'; +@import 'checkout/_order-summary.less'; +@import 'checkout/_authentication.less'; + +@import 'checkout/_payments.less'; +@import 'checkout/_payment-options.less'; +@import 'checkout/_checkout-agreements.less'; diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less index 535a47ff7f9ee5ddad63365a0f0f07f37b1208c9..317c57334f11c36998d524588599196c5d632184 100644 --- a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/_minicart.less @@ -5,93 +5,93 @@ // // Variables -// --------------------------------------------- +// _____________________________________________ @minicart__border-color: @color-gray80; @minicart__padding-horizontal: @indent__base; // // Common -// --------------------------------------------- +// _____________________________________________ & when (@media-common = true) { -// -// Minicart -// --------------------------------------------- + // + // Minicart + // --------------------------------------------- -.block-minicart { - .items-total { - float: left; - margin: 0 @indent__s; - .count { - font-weight: @font-weight__bold; + .block-minicart { + .items-total { + float: left; + margin: 0 @indent__s; + .count { + font-weight: @font-weight__bold; + } } - } - .subtotal { - margin: 0 @indent__s; - text-align: right; - .label { - &:extend(.abs-colon all); + .subtotal { + margin: 0 @indent__s; + text-align: right; + .label { + &:extend(.abs-colon all); + } } - } - .amount { - .price-wrapper { - &:first-child { - .price { - font-size: @font-size__l; - font-weight: @font-weight__bold; + .amount { + .price-wrapper { + &:first-child { + .price { + font-size: @font-size__l; + font-weight: @font-weight__bold; + } } } } - } - .subtitle { - display: none; - } - .subtitle { - &.empty { - display: block; - padding: @indent__l 0 @indent__base; - text-align: center; - font-size: 14px; + .subtitle { + display: none; } - } - .text { - &.empty { - text-align: center; + .subtitle { + &.empty { + display: block; + font-size: 14px; + padding: @indent__l 0 @indent__base; + text-align: center; + } } - } - .block-content { - > .actions { - margin-top: 15px; - text-align: center; - > .primary { - margin: 0 @indent__s 15px; - .action { - &.primary { - &:extend(.abs-button-l all); - display: block; - width: 100%; - margin-bottom: 15px; - &:last-child { - margin-bottom: 0; + .text { + &.empty { + text-align: center; + } + } + .block-content { + > .actions { + margin-top: 15px; + text-align: center; + > .primary { + margin: 0 @indent__s 15px; + .action { + &.primary { + &:extend(.abs-button-l all); + display: block; + margin-bottom: 15px; + width: 100%; + &:last-child { + margin-bottom: 0; + } } } } } } + .block-category-link, + .block-product-link, + .block-cms-link, + .block-banners { + margin: 15px 0 0; + text-align: center; + } } - .block-category-link, - .block-product-link, - .block-cms-link, - .block-banners { - margin: 15px 0 0; - text-align: center; - } -} -.minicart-wrapper { - .dropdown( + .minicart-wrapper { + .dropdown( @_toggle-selector: ~".action.showcart", @_options-selector: ~".block-minicart", @_dropdown-toggle-icon-content: @icon-cart, @@ -104,200 +104,229 @@ @_icon-font-color: @minicart-icons-color, @_icon-font-color-hover: @minicart-icons-color-hover, @_icon-font-color-active: @minicart-icons-color - ); - float: right; - .block-minicart { - .css(padding, 25px @minicart__padding-horizontal); - right: 0; - width: 320px; - .block-title { - display: none; - } - &:after { - left: auto; - right: 25px; - } - &:before { - left: auto; - right: 26px; + ); + float: right; + .block-minicart { + .css(padding, 25px @minicart__padding-horizontal); + right: 0; + width: 320px; + .block-title { + display: none; + } + &:after { + left: auto; + right: 25px; + } + &:before { + left: auto; + right: 26px; + } } - } - .product.actions { - text-align: right; - > .primary, - > .secondary { - display: inline; + .product.actions { + text-align: right; + > .primary, > .secondary { + display: inline; + } } - } - .action { - &.close { - width: 40px; - height: 40px; - top: 0; - right: 0; - position: absolute; - .button-reset(); - .button-icon( + .action { + &.close { + .button-icon( @icon-remove, @_icon-font-size: 32px, @_icon-font-line-height: 32px, @_icon-font-text-hide: true - ); - } - &.showcart { - .text { - &:extend(.abs-visually-hidden all); + ); + .button-reset(); + height: 40px; + position: absolute; + right: 0; + top: 0; + width: 40px; } - white-space: nowrap; - .counter.qty { - &.empty { - display: none; + &.showcart { + white-space: nowrap; + .text { + &:extend(.abs-visually-hidden all); + } + .counter.qty { + border-radius: 2px; + clip: none; + .css(color, @page__background-color); + .css(background, @active__color); + display: inline-block; + height: 24px; + line-height: 24px; + margin: 3px 0 0; + min-width: 18px; + overflow: hidden; + padding: 0 3px; + text-align: center; + white-space: normal; + &.empty { + &:extend(.abs-no-display all); + } + } + .counter-label { + &:extend(.abs-visually-hidden all); } - .css(background, @active__color); - border-radius: 2px; - .css(color, @page__background-color); - clip: none; - display: inline-block; - height: 24px; - line-height: 24px; - min-width: 18px; - margin: 3px 0 0; - padding: 0 3px; - overflow: hidden; - text-align: center; - white-space: normal; - } - .counter-label { - &:extend(.abs-visually-hidden all); } } + .minicart-widgets { + margin-top: 15px; + } } - .minicart-widgets { - margin-top: 15px; - } -} -.minicart-items-wrapper { - .css(border, 1px solid @minicart__border-color); - .css(margin, 0 -@minicart__padding-horizontal); - border-left: 0; - border-right: 0; - overflow-x: auto; - padding: 15px; -} + .minicart-items-wrapper { + border-left: 0; + border-right: 0; + .css(margin, 0 -@minicart__padding-horizontal); + .css(border, 1px solid @minicart__border-color); + overflow-x: auto; + padding: 15px; + } -.minicart-items { - .list-reset-styles(0, 0); - .item { - &:not(:first-child) { - .css(border-top, 1px solid @minicart__border-color); - } - padding: @indent__base 0; - &:first-child { - padding-top: 0; + .minicart-items { + .list-reset-styles(0, 0); + .product-item { + padding: @indent__base 0; + &:not(:first-child) { + .css(border-top, 1px solid @minicart__border-color); + } + &:first-child { + padding-top: 0; + } + > .product { + &:extend(.abs-add-clearfix all); + } } - > .product { - &:extend(.abs-add-clearfix all); + .product-image-wrapper { + &:extend(.abs-reset-image-wrapper all); } - } - .product-image-wrapper { - &:extend(.abs-reset-image-wrapper all); - } - .product-item-pricing { - .label { - display: inline-block; - width: 4.5rem; - } - } - .price-minicart { - margin-bottom: @indent__xs; - } - .product-item-photo { - float: left; - } - .product-item-name { - font-weight: @font-weight__regular; - margin: 0 0 @indent__s; - a { - .css(color, @link__color); + .product-item-pricing { + .label { + display: inline-block; + width: 4.5rem; + } } - } - .product-item-details { - padding-left: 88px; - .price { - font-weight: @font-weight__bold; + .price-minicart { + margin-bottom: @indent__xs; } - .price-including-tax, - .price-excluding-tax { - margin: @indent__xs 0; + .product { + > .product-item-photo, + > .product-image-container { + float: left; + } + .toggle { + .icon-font( + @_icon-font-content: @icon-down, + @_icon-font-size: 28px, + @_icon-font-line-height: 16px, + @_icon-font-text-hide: false, + @_icon-font-position: after, + @_icon-font-display: block + ); + cursor: pointer; + position: relative; + &:after { + position: static; + right: @indent__base; + top: 0; + } + } + &.active { + > .toggle { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } } - .weee[data-label] { - .font-size(11); - .label { - &:extend(.abs-no-display all); + .product-item-name { + font-weight: @font-weight__regular; + margin: 0 0 @indent__s; + a { + .css(color, @link__color); } } - .details-qty { - margin-top: @indent__s; + .product-item-details { + padding-left: 88px; + .price { + font-weight: @font-weight__bold; + } + .price-including-tax, + .price-excluding-tax { + margin: @indent__xs 0 0; + } + .weee[data-label] { + .font-size(11); + .label { + &:extend(.abs-no-display all); + } + } + .details-qty { + margin-top: @indent__s; + } } - } - .product.options { - .tooltip.toggle { - .icon-font( + .product.options { + .tooltip.toggle { + .icon-font( @icon-down, @_icon-font-size: 28px, @_icon-font-line-height: 28px, @_icon-font-text-hide: true, @_icon-font-margin: -3px 0 0 7px, @_icon-font-position: after - ); - .details { - display: none; + ); + .details { + display: none; + } } } - } - .details-qty, - .price-minicart { - .label { - &:extend(.abs-colon all); + .details-qty, + .price-minicart { + .label { + &:extend(.abs-colon all); + } + } + .item-qty { + margin-right: @indent__s; + text-align: center; + width: 40px; + } + .item-update { + .font-size(11); + vertical-align: top; + } + .subtitle { + &:extend(.abs-no-display all); + } + .action { + &.edit, + &.delete { + .icon-font( + @icon-settings, + @_icon-font-size: 28px, + @_icon-font-line-height: 28px, + @_icon-font-text-hide: true, + @_icon-font-color: @color-gray19, + @_icon-font-color-hover: @color-gray19, + @_icon-font-color-active: @color-gray19 + ); + } + &.delete { + .icon-font-symbol( + @_icon-font-content: @icon-trash + ); + } } } - .item-qty { - width: 40px; - text-align: center; - margin-right: @indent__s; - } - .item-update { - vertical-align: top; - .font-size(11); - } - .action { - &.edit, - &.delete { - .icon-font( - @icon-settings, - @_icon-font-size: 28px, - @_icon-font-line-height: 28px, - @_icon-font-text-hide: true, - @_icon-font-color: @color-gray19, - @_icon-font-color-hover: @color-gray19, - @_icon-font-color-active: @color-gray19 - ); - } - &.delete { - .icon-font-symbol( - @_icon-font-content: @icon-trash - ); - } - } -} - } // // Mobile -// --------------------------------------------- +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { .minicart-wrapper .block-minicart { @@ -313,7 +342,7 @@ // // Desktop -// --------------------------------------------- +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .minicart-wrapper { diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less new file mode 100644 index 0000000000000000000000000000000000000000..26c1ac83c04217bc2ad84483a5ec3b608cecf4ae --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_authentication.less @@ -0,0 +1,196 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@block-auth__dropdown__padding: @indent__m; +@block-auth__dropdown__background-color: @color-white; +@block-auth__or-label__size: 36px; +@block-auth__width: 0; +@block-auth__border: 1px solid @color-gray-light3; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .authentication-dropdown { + box-sizing: border-box; + .modal-inner-wrap { + padding: @block-auth__dropdown__padding; + } + } + .authentication-wrapper { + float: right; + margin-top: -1.5*@indent__xl; + max-width: 50%; + position: relative; + z-index: 1; + ._has-auth-shown & { + z-index: @modal__z-index; + } + } + .action-auth-toggle { + &:extend(.abs-action-button-as-link all); + } + .block-authentication { + .block-title { + .font-size(@h3__font-size); + border-bottom: 0; + margin-bottom: @indent__m; + strong { + font-weight: @font-weight__light; + } + } + .field { + .label { + font-weight: @font-weight__regular; + } + } + .actions-toolbar { + margin-bottom: @indent__xs; + > .secondary { + padding-top: @indent__m; + text-align: left; + } + } + .action.action-register, + .action.action-login { + &:extend(.abs-button-l all); + } + .block[class] { + margin: 0; + ul { + list-style: none; + padding-left: @indent__s; + } + .field { + .control, + .label { + float: none; + width: auto; + } + } + & + .block { + border-top: 1px solid @color-gray-light5; + margin-top: @indent__xl; + padding-top: @indent__xl; + position: relative; + &::before { + .css(height, @block-auth__or-label__size); + .css(line-height, @block-auth__or-label__size - 2px); + .css(margin, -(@block-auth__or-label__size/2 + 1px) 0 0 -(@block-auth__or-label__size / 2)); + .css(min-width, @block-auth__or-label__size); + background: @color-white; + border-radius: 50%; + border: 1px solid @color-gray-light5; + box-sizing: border-box; + color: @color-gray-light5; + content: attr(data-label); + display: inline-block; + left: 50%; + letter-spacing: normal; + padding: 0 .2rem; + position: absolute; + text-align: center; + text-transform: uppercase; + top: 0; + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .authentication-dropdown { + .css(background-color, @block-auth__dropdown__background-color); + .css(border, @block-auth__border); + position: absolute; + text-align: left; + top: 100%; + transform-origin: 0 0; + transform: scale(1,0); + transition: transform linear .1s, visibility 0s linear .1s; + visibility: hidden; + width: 100%; + &._show { + .css(z-index, @dropdown-list__z-index); + transform: scale(1,1); + transition: transform linear .1s, visibility 0s linear 0s; + visibility: visible; + } + } + .authentication-wrapper { + .column-width(@checkout-sidebar__columns); + text-align: right; + } + .block-authentication { + .block-title { + .font-size(@h2__font-size); + border-bottom: 0; + margin-bottom: @indent__m; + } + .actions-toolbar { + > .primary { + display: inline; + float: right; + margin-right: 0; + .action { + margin-right: 0; + } + } + > .secondary { + float: left; + margin-right: 2rem; + padding-top: 1rem; + } + } + } + .popup-authentication { + .modal-inner-wrap { + min-width: @screen__m; + width: 60%; + } + .block-authentication { + .vendor-prefix-display(flex); + .vendor-prefix-flex-direction(row); + border-top: 1px solid @color-gray-light5; + } + .block[class], + .form-login, + .fieldset, + .block-content { + .vendor-prefix-display(flex); + .vendor-prefix-flex-direction(column); + .vendor-prefix-flex-grow(1); + } + .block[class] { + box-sizing: border-box; + float: left; + padding: @indent__s @indent__l 0 0; + width: 50%; + & + .block { + border-left: 1px solid @color-gray-light5; + border-top: 0; + margin: 0; + padding: @indent__s 0 0 @indent__xl; + &::before { + left: 0; + top: 50%; + } + } + } + .actions-toolbar { + margin-bottom: 0; + margin-top: auto; + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less new file mode 100644 index 0000000000000000000000000000000000000000..02fbbeb1faa431e4056b78be1daf0cd0c90cffdd --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout-agreements.less @@ -0,0 +1,34 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-agreements-block { + margin-bottom: @indent__base; + + .action-show { + &:extend(.abs-action-button-as-link all); + vertical-align: baseline; + } + } + + // Checkout Agreements in popup + .checkout-agreements-items { + &:extend(.abs-reset-list all); + padding-bottom: @indent__l; + + .checkout-agreements-item { + margin-bottom: @indent__base; + } + + .checkout-agreements-item-title { + &:extend(.abs-checkout-title all); + border-bottom: 0; + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less new file mode 100644 index 0000000000000000000000000000000000000000..6fcaedd24084e3c230ab32cb01186949bfc06b0e --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_checkout.less @@ -0,0 +1,86 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-wrapper__margin: @indent__base; +@checkout-wrapper__columns: 8; + +@checkout-step-title__border: @border-width__base solid @color-gray80; +@checkout-step-title__font-size: 26px; +@checkout-step-title__font-weight: @font-weight__light; +@checkout-step-title__margin-bottom: 28px; +@checkout-step-title__padding: @indent__s; + +@checkout-step-title-mobile__font-size: 18px; +@checkout-step-title-mobile__margin-bottom: @indent__base; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + .checkout-container { + &:extend(.abs-add-clearfix all); + .css(margin, 0 0 @checkout-wrapper__margin); + } + + .opc-wrapper { + .css(margin, 0 0 @checkout-wrapper__margin); + + .opc { + &:extend(.abs-reset-list all); + } + + .step-title { + &:extend(.abs-checkout-title all); + .css(margin, 0 0 @checkout-step-title__margin-bottom); + } + + .step-content { + margin: 0 0 @indent__xl; + } + } + + .checkout-onepage-index { + .nav-sections, + .nav-toggle { + display: none; + } + .logo { + margin-left: 0; + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .opc-wrapper { + .step-title { + .css(font-size, @checkout-step-title-mobile__font-size); + .css(margin-bottom, @checkout-step-title-mobile__margin-bottom); + border-bottom: 0; + padding-bottom: 0; + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-wrapper { + &:extend(.abs-add-box-sizing-desktop-m all); + .layout-column(2, 1, @checkout-wrapper__columns); + padding-right: @indent__l; + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less new file mode 100644 index 0000000000000000000000000000000000000000..5119231620d6ee172e9906402baedc181b3f77fd --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less @@ -0,0 +1,54 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Checkout Estimated Total + // --------------------------------------------- + + .opc-estimated-wrapper { + &:extend(.abs-add-clearfix all); + &:extend(.abs-no-display-desktop all); + .css(border-bottom, @border-width__base solid @color-gray80); + margin: 0 0 15px; + padding: 18px 15px; + + .estimated-block { + .css(font-size, @checkout-step-title-mobile__font-size); + .css(font-weight, @font-weight__bold); + float: left; + + .estimated-label { + margin: 0 0 @indent__xs; + display: block; + } + } + + .minicart-wrapper { + .action { + &.showcart { + &:before { + .css(color, @primary__color); + } + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { + .opc-estimated-wrapper { + display: none; + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less new file mode 100644 index 0000000000000000000000000000000000000000..17fd35ed14fc6f2229338e1bd568d7ee0dcdfdde --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_fields.less @@ -0,0 +1,33 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-field-validation__border-color: @form-element-validation__border-error; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .field { + .control { + &._with-tooltip { + &:extend(.abs-field-tooltip all); + } + } + &._error { + .control { + input, + select, + textarea { + .css(border-color, @checkout-field-validation__border-color); + } + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less new file mode 100644 index 0000000000000000000000000000000000000000..a11423841e94f407b735e34095037f10978ce784 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_modals.less @@ -0,0 +1,61 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-modal-popup__width: 800px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-onepage-index { + .modal-popup { + .field-tooltip { + .field-tooltip-content { + &:extend(.abs-checkout-tooltip-content-position-top all); + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-onepage-index { + .modal-popup { + .form-shipping-address { + .css(max-width, @checkout-shipping-address__max-width); + } + .modal-footer { + .action-save-address { + float: right; + margin: 0 0 0 @indent__s; + } + .action-hide-popup { + &:extend(.abs-action-button-as-link all); + } + } + } + } +} + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { + .checkout-onepage-index { + .modal-popup { + .modal-inner-wrap { + .css(margin-left, -(@checkout-modal-popup__width/2)); + .css(width, @checkout-modal-popup__width); + left: 50%; + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less new file mode 100644 index 0000000000000000000000000000000000000000..0cc46910745bc2c366c049f1fa689ca0c6a7c0e5 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_order-summary.less @@ -0,0 +1,171 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-summary__background-color: @color-white-smoke; +@checkout-summary__padding: 22px @indent__l; + +@checkout-summary-title__margin: @indent__s; +@checkout-summary-mark-value__color: @color-gray60; + +@checkout-summary-items__max-height: 370px; +@checkout-summary-items__padding: 15px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Order Summary + // --------------------------------------------- + + .opc-block-summary { + &:extend(.abs-add-box-sizing all); + .css(background, @checkout-summary__background-color); + .css(padding, @checkout-summary__padding); + margin: 0 0 @indent__base; + + > .title { + &:extend(.abs-checkout-title all); + display: block; + } + + // Totals table + .table-totals { + &:extend(.abs-sidebar-totals all); + } + + .mark { + .value { + .css(color, @checkout-summary-mark-value__color); + display: block; + } + } + + .grand.incl { + & + .grand.excl { + .mark, + .amount { + border-top: 0; + .font-size(14); + padding-top: 0; + strong { + font-weight: @font-weight__regular; + } + } + } + } + + .not-calculated { + font-style: italic; + } + + // + // Items list + // --------------------------------------------- + + // Block title + .items-in-cart { + > .title { + border-bottom: @border-width__base solid @border-color__base; + .css(padding, @indent__s @indent__xl @indent__s 0); + cursor: pointer; + .icon-font( + @icon-down, + @_icon-font-size: 30px, + @_icon-font-line-height: 12px, + @_icon-font-text-hide: true, + @_icon-font-margin: 3px 0 0, + @_icon-font-position: after, + @_icon-font-display: block + ); + margin-bottom: 0; + position: relative; + &:after { + position: absolute; + right: 0; + top: @indent__s; + } + strong { + .font-size(18); + font-weight: @font-weight__light; + margin: 0; + } + } + &.active { + > .title { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + .product { + position: relative; + } + } + + // Cart items + .minicart-items-wrapper { + .css(margin, 0 -(@checkout-summary-items__padding) 0 0); + .css(max-height, @checkout-summary-items__max-height); + .css(padding, @checkout-summary-items__padding @checkout-summary-items__padding 0 0); + border: 0; + } + .column.main & { + .product-item { + margin: 0; + padding-left: 0; + } + } + .product-item { + .product-item-inner { + display: table; + margin: 0 0 @indent__s; + width: 100%; + } + .product-item-name-block { + display: table-cell; + padding-right: @indent__xs; + text-align: left; + } + .subtotal { + display: table-cell; + text-align: right; + } + .price { + .font-size(16); + font-weight: @font-weight__regular; + } + .price-including-tax { + & + .price-excluding-tax { + margin: 0; + .price { + .font-size(10); + } + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-summary-wrapper { + .modal-header { + .action-close { + display: none; + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less new file mode 100644 index 0000000000000000000000000000000000000000..c9741c735bbf296c192f285242f05704190b1515 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payment-options.less @@ -0,0 +1,139 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-payment-option-title__border: @checkout-payment-method-title__border; +@checkout-payment-option-title__color: @link__color; +@checkout-payment-option-title__padding: @checkout-payment-method-title__padding; +@checkout-payment-option-title-mobile__padding: @checkout-payment-method-title-mobile__padding; + +@checkout-payment-option-title-icon__font-size: 32px; +@checkout-payment-option-title-icon__line-height: 16px; +@checkout-payment-option-title-icon__margin: 0; +@checkout-payment-option-title-icon__color: @minicart-icons-color; +@checkout-payment-option-title-icon__hover__color: @primary__color; + +@checkout-payment-option-content__padding__xl: @checkout-payment-method-content__padding__xl; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-payment-method { + .payment-option { + &._active { + .payment-option-title { + .action-toggle { + &:after { + content: @icon-up; + } + } + } + } + &._collapsible { + .payment-option-title { + cursor: pointer; + } + .payment-option-content { + display: none; + } + } + } + + .payment-option-title { + .css(border-top, @checkout-payment-option-title__border); + .css(padding, @checkout-payment-option-title__padding 0); + + .action-toggle { + .css(color, @checkout-payment-option-title__color); + .icon-font( + @icon-down, + @_icon-font-size: @checkout-payment-option-title-icon__font-size, + @_icon-font-line-height: @checkout-payment-option-title-icon__line-height, + @_icon-font-color: @checkout-payment-option-title-icon__color, + @_icon-font-color-hover: @checkout-payment-option-title-icon__hover__color, + @_icon-font-color-active: @checkout-payment-option-title-icon__color, + @_icon-font-margin: @checkout-payment-option-title-icon__margin, + @_icon-font-position: after + ); + } + } + + .payment-option-content { + .css(padding, 0 0 @indent__base @checkout-payment-option-content__padding__xl); + } + + .payment-option-inner { + margin: 0 0 @indent__base; + } + + .credit-card-types { + padding: 0; + .item { + display: inline-block; + list-style: none; + margin: 0 @indent__xs 0 0; + &._active { + font-weight: @font-weight__bold; + img { + -webkit-filter: grayscale(0%); + filter: grayscale(0%); + filter: none; + } + } + } + img { + -webkit-filter: grayscale(100%); // For Webkit browsers + -webkit-transition: all .6s ease; // Fade to color for Chrome and Safari + filter: grayscale(100%); + filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale"); // Firefox 10+, Firefox on Android + filter: gray; // For IE 6 - 9 + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .checkout-payment-method { + .payment-option { + .css(margin, 0 -(@checkout-payment-option-title-mobile__padding)); + + .payment-option-title { + .css(padding, @checkout-payment-option-title-mobile__padding) + } + + .payment-option-content { + .css(padding, 0 @checkout-payment-option-title-mobile__padding @indent__base); + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-payment-method { + .payment-option-title { + .css(padding-left, @checkout-payment-option-content__padding__xl); + } + .payment-option-content { + .payment-option-inner { + + .actions-toolbar { + margin-left: 0; + } + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less new file mode 100644 index 0000000000000000000000000000000000000000..b880027e5493df788807dbbeabfaa94d0c36fb0b --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_payments.less @@ -0,0 +1,198 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-payment-method-title__border: @checkout-shipping-method__border; +@checkout-payment-method-title__padding: @checkout-shipping-method__padding; +@checkout-payment-method-title-mobile__padding: 15px; + +@checkout-payment-method-content__padding__xl: 22px; + +@checkout-billing-address-details__line-height: 27px; +@checkout-billing-address-details__padding: 0 0 0 23px; +@checkout-billing-address-form__max-width: @checkout-shipping-address__max-width; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-payment-method { + .step-title { + margin-bottom: 0; + } + .payment-method { + &:first-child { + .payment-method-title { + border-top: 0; + } + } + &._active { + .payment-method-content { + display: block; + } + } + .action { + &.primary { + &:extend(.abs-button-l all); + } + } + } + + .payment-method-title { + .css(border-top, @checkout-payment-method-title__border); + .css(padding, @checkout-payment-method-title__padding 0); + margin: 0; + + .payment-icon { + display: inline-block; + margin-right: @indent__xs; + vertical-align: middle; + } + + .action-help { + display: inline-block; + margin-left: @indent__xs; + } + } + + .payment-method-content { + display: none; + .css(padding, 0 0 @indent__base @checkout-payment-method-content__padding__xl); + .fieldset { + &:not(:last-child) { + margin: 0 0 @indent__base; + } + > .field { + margin: 0 0 @indent__base; + } + } + } + + .field-select-billing, + .billing-address-form { + .css(max-width, @checkout-billing-address-form__max-width); + } + + .billing-address-same-as-shipping-block { + margin: 0 0 @indent__s; + } + + .payment-method-billing-address { + margin: 0 0 @indent__base; + + .primary { + .action-update { + margin-right: 0; + } + } + + .action-cancel { + &:extend(.abs-action-button-as-link all); + } + + .billing-address-details { + .css(line-height, @checkout-billing-address-details__line-height); + .css(padding, @checkout-billing-address-details__padding); + + .action-edit-address { + &:extend(.abs-action-button-as-link all); + } + } + } + + .payment-method-note { + & + .payment-method-billing-address { + margin-top: @indent__base; + } + } + + .field-select-billing { + > .label { + &:extend(.abs-visually-hidden all); + } + } + .payment-method-iframe { + background-color: transparent; + display: none; + width: 100%; + } + .no-payments-block { + margin: @indent__base 0; + } + .ccard { + .legend { + &:extend(.abs-visually-hidden all); + } + .year { + padding-left: @indent__l; + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .checkout-payment-method { + .payment-methods { + .css(margin, 0 -(@checkout-payment-method-title-mobile__padding)); + } + + .payment-method-title { + .css(padding, @checkout-payment-method-title-mobile__padding) + } + + .payment-method-content { + .css(padding, 0 @checkout-payment-method-title-mobile__padding @indent__base); + } + + .payment-method-billing-address { + .action-cancel { + margin-top: @indent__s; + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-payment-method { + .payment-methods { + .actions-toolbar { + .primary { + float: right; + margin: 0; + } + } + } + .fieldset { + > .field-select-billing { + > .control { + float: none; + width: 100%; + } + } + } + } + .payment-method-billing-address { + .action-update { + float: right; + } + .actions-toolbar { + .action-cancel { + margin: 6px @indent__base 0 0; + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less new file mode 100644 index 0000000000000000000000000000000000000000..386889c75d410cd854fbced42f136d0ce4bb0dd8 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less @@ -0,0 +1,169 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-progress-bar__font-size: 18px; +@checkout-progress-bar__font-weight: @font-weight__light; +@checkout-progress-bar__margin: @indent__base; + +@checkout-progress-bar-item__background-color: @color-gray-middle1; +@checkout-progress-bar-item__border-radius: 6px; +@checkout-progress-bar-item__color: @primary__color; +@checkout-progress-bar-item__margin: @indent__s; +@checkout-progress-bar-item__width: 185px; +@checkout-progress-bar-item__active__background-color: @color-orange-red1; +@checkout-progress-bar-item__complete__color: @link__color; + +@checkout-progress-bar-item-element__height: @checkout-progress-bar-item-element__width; +@checkout-progress-bar-item-element__width: 38px; + +@checkout-progress-bar-item-element-inner__background-color: @page__background-color; +@checkout-progress-bar-item-element-inner__color: @checkout-progress-bar-item__color; +@checkout-progress-bar-item-element-inner__height: @checkout-progress-bar-item-element-inner__width; +@checkout-progress-bar-item-element-inner__width: @checkout-progress-bar-item-element__width - (@checkout-progress-bar-item-element-outer-radius__width * 2); +@checkout-progress-bar-item-element-inner__active__content: @icon-checkmark; +@checkout-progress-bar-item-element-inner__active__font-size: 28px; +@checkout-progress-bar-item-element-inner__active__line-height: 1; + +@checkout-progress-bar-item-element-outer-radius__width: 6px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Checkout Progress Bar + // --------------------------------------------- + + .opc-progress-bar { + &:extend(.abs-reset-list all); + .css(margin, 0 0 @checkout-progress-bar__margin); + counter-reset: i; + font-size: 0; + } + .opc-progress-bar-item { + .css(margin, 0 0 @checkout-progress-bar-item__margin); + display: inline-block; + position: relative; + text-align: center; + vertical-align: top; + width: 50%; + + &:before { // Horizontal line + .css(background, @checkout-progress-bar-item__background-color); + .css(top, @checkout-progress-bar-item-element__width/2); + content: ''; + height: 7px; + left: 0; + position: absolute; + width: 100%; + } + + &:first-child { + &:before { + .css(border-radius, @checkout-progress-bar-item__border-radius 0 0 @checkout-progress-bar-item__border-radius); + } + } + + &:last-child { + &:before { + .css(border-radius, 0 @checkout-progress-bar-item__border-radius @checkout-progress-bar-item__border-radius 0); + } + } + + > span { + display: inline-block; + padding-top: 45px; + width: 100%; + word-wrap: break-word; + + .typography( + @_color: @checkout-progress-bar-item__background-color, + @_font-family: false, + @_font-size: @checkout-progress-bar__font-size, + @_font-style: false, + @_font-weight: @checkout-progress-bar__font-weight, + @_line-height: false + ); + + &:before, // Item element + &:after { + .css(background, @checkout-progress-bar-item__background-color); + .css(height, @checkout-progress-bar-item-element__height); + .css(margin-left, -(@checkout-progress-bar-item-element__width/2)); + .css(width, @checkout-progress-bar-item-element__width); + border-radius: 50%; + content: ''; + left: 50%; + position: absolute; + top: 0; + } + + &:after { // Item element inner + .css(background, @checkout-progress-bar-item-element-inner__background-color); + .css(height, @checkout-progress-bar-item-element-inner__height); + .css(margin-left, -(@checkout-progress-bar-item-element-inner__width/2)); + .css(top, @checkout-progress-bar-item-element-outer-radius__width); + .css(width, @checkout-progress-bar-item-element-inner__width); + content: counter(i); + counter-increment: i; + .typography( + @_color: @checkout-progress-bar-item-element-inner__color, + @_font-family: false, + @_font-size: @checkout-progress-bar__font-size, + @_font-style: false, + @_font-weight: @font-weight__semibold, + @_line-height: false + ); + } + } + + &._active { + &:before { + background: @checkout-progress-bar-item__active__background-color; + } + > span { + .css(color, @checkout-progress-bar-item__color); + &:before { + .css(background, @checkout-progress-bar-item__active__background-color); + } + &:after { + .css(content, @checkout-progress-bar-item-element-inner__active__content); + .css(font-family, @icons__font-name); + .css(line-height, @checkout-progress-bar-item-element-inner__active__line-height); + .font-size(@checkout-progress-bar-item-element-inner__active__font-size); + } + } + } + + &._complete { + cursor: pointer; + > span { + .css(color, @checkout-progress-bar-item__color); + &:after { + .css(content, @checkout-progress-bar-item-element-inner__active__content); + .css(font-family, @icons__font-name); + .css(line-height, @checkout-progress-bar-item-element-inner__active__line-height); + .font-size(@checkout-progress-bar-item-element-inner__active__font-size); + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-progress-bar-item { + .css(width, @checkout-progress-bar-item__width); + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less new file mode 100644 index 0000000000000000000000000000000000000000..adb28706810e8c0f90b112c38936cfe1fc5a9a73 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping-policy.less @@ -0,0 +1,67 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-shipping-policy-action__color: @link__color; +@checkout-shipping-policy-tooltip__width: 420px; +@checkout-shipping-policy-tooltip-mobile__width: 300px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-shipping-method { + position: relative; + } + + .shipping-policy-block { + &.field-tooltip { + top: 12px; + + .field-tooltip-action { + .css(color, @checkout-shipping-policy-action__color); + cursor: pointer; + &:before { + display: none; + } + } + + .field-tooltip-content { + &:extend(.abs-add-box-sizing all); + &:extend(.abs-checkout-tooltip-content-position-top all); + .css(width, @checkout-shipping-policy-tooltip__width); + top: @indent__l; + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .shipping-policy-block { + &.field-tooltip { + margin-bottom: @indent__base; + position: relative; + right: auto; + top: auto; + + .field-tooltip-content { + .css(width, @checkout-shipping-policy-tooltip-mobile__width); + right: auto; + &:before, + &:after { + right: auto; + } + } + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less new file mode 100644 index 0000000000000000000000000000000000000000..3b052c7401101077be3125a7b522953a515acb3b --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_shipping.less @@ -0,0 +1,321 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-shipping-address__max-width: 600px; + +@checkout-shipping-item-icon__background-color: @checkout-shipping-item__active__border-color; +@checkout-shipping-item-icon__color: @color-white; +@checkout-shipping-item-icon__content: @icon-checkmark; + +@checkout-shipping-item__border: 2px solid transparent; +@checkout-shipping-item__line-height: 30px; +@checkout-shipping-item__margin: 0 0 @indent__base; +@checkout-shipping-item__padding: @indent__base (@indent__l + 5px) @indent__base @indent__base; +@checkout-shipping-item__transition: .3s border-color; +@checkout-shipping-item__width: 100%/3; +@checkout-shipping-item-tablet__width: 100%/2; +@checkout-shipping-item-mobile__width: 100%; +@checkout-shipping-item__active__border-color: @color-orange-red1; + +@checkout-shipping-item-icon__selected__height: 27px; +@checkout-shipping-item-icon__selected__width: 29px; + +@checkout-shipping-item-mobile__padding: 0 0 15px; +@checkout-shipping-item-mobile__margin: @checkout-shipping-item-mobile__padding; +@checkout-shipping-item-mobile__active__padding: 15px (@indent__l + 5px) 15px 18px; + +@checkout-shipping-item-before__border-color: @color-gray80; +@checkout-shipping-item-before__height: calc(~"100% - 20px"); + +@checkout-shipping-method__border: @checkout-step-title__border; +@checkout-shipping-method__padding: @indent__base; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + .opc-wrapper { + + // + // Shipping Address + // --------------------------------------------- + + .form-login, + .form-shipping-address { + margin-bottom: @indent__base; + + .fieldset { + .field { + .label { + font-weight: @font-weight__regular; + } + } + .note { + font-size: @font-size__base; + margin-top: @indent__s; + } + } + } + + .shipping-address-items { + font-size: 0; + } + + .shipping-address-item { + &:extend(.abs-add-box-sizing all); + .css(border, @checkout-shipping-item__border); + .css(line-height, @checkout-shipping-item__line-height); + .css(margin, @checkout-shipping-item__margin); + .css(padding, @checkout-shipping-item__padding); + .css(transition, @checkout-shipping-item__transition); + .css(width, @checkout-shipping-item-tablet__width); + display: inline-block; + font-size: @font-size__base; + position: relative; + vertical-align: top; + word-wrap: break-word; + + &.selected-item { + .css(border-color, @checkout-shipping-item__active__border-color); + + &:after { + .css(background, @checkout-shipping-item-icon__background-color); + .css(color, @checkout-shipping-item-icon__color); + .css(content, @checkout-shipping-item-icon__content); + .css(font-family, @icons__font-name); + .css(height, @checkout-shipping-item-icon__selected__height); + .css(width, @checkout-shipping-item-icon__selected__width); + font-size: 27px; + line-height: 21px; + padding-top: 2px; + position: absolute; + right: 0; + text-align: center; + top: 0; + } + + .action-select-shipping-item { + &:extend(.abs-no-display-s all); + visibility: hidden; + } + } + } + + .field { + &.addresses { + &:extend(.abs-add-clearfix all); + } + } + + .action-show-popup { + margin: 0 0 @indent__base; + > span { + &:before { + content: '+'; + padding-right: @indent__xs; + } + } + } + + .action-select-shipping-item { + float: right; + margin: @indent__base 0 0; + } + + .edit-address-link { + &:extend(.abs-action-button-as-link all); + display: block; + float: left; + margin: 26px 5px 0 0; + } + } + + // + // Shipping Methods + // --------------------------------------------- + + .checkout-shipping-method { + .step-title { + margin-bottom: 0; + } + .no-quotes-block { + margin: @indent__base 0; + } + } + + .methods-shipping { + .actions-toolbar { + .action { + &.primary { + &:extend(.abs-button-l all); + margin: @indent__base 0 0; + } + } + } + } + + .table-checkout-shipping-method { + thead { + th { + display: none; + } + } + tbody { + td { + .css(border-top, @checkout-shipping-method__border); + .css(padding-bottom, @checkout-shipping-method__padding); + .css(padding-top, @checkout-shipping-method__padding); + &:first-child { + padding-left: 0; + padding-right: 0; + width: 20px; + } + } + + tr { + &:first-child { + td { + border-top: none; + } + } + } + .row-error { + td { + border-top: none; + padding-bottom: @indent__s; + padding-top: 0; + } + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .opc-wrapper { + .form-login { + .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color); + .css(margin, @checkout-shipping-item-mobile__padding); + .css(padding, @checkout-shipping-item-mobile__padding); + } + .shipping-address-item { + .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color); + .css(margin, @checkout-shipping-item-mobile__margin); + .css(padding, @checkout-shipping-item-mobile__padding); + width: 100%; + &.selected-item { + .css(padding, @checkout-shipping-item-mobile__active__padding); + border-bottom-width: 2px; + + .edit-address-link { + .css(right, @checkout-shipping-item-icon__selected__width + @indent__s); + } + } + } + + .action-select-shipping-item { + float: none; + margin-top: @indent__s; + width: 100%; + } + + .action-show-popup { + width: 100%; + } + + .edit-address-link { + .icon-font( + @icon-settings, + @_icon-font-size: 28px, + @_icon-font-line-height: 28px, + @_icon-font-text-hide: true, + @_icon-font-color: @color-gray19, + @_icon-font-color-hover: @color-gray19, + @_icon-font-color-active: @color-gray19 + ); + margin: 0; + position: absolute; + right: 0; + top: 1px; + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-shipping-method { + .actions-toolbar { + > .primary { + float: right; + } + .action { + &.primary { + margin: 0; + } + } + } + } + + .opc-wrapper { + .form-login, + .form-shipping-address { + .css(max-width, @checkout-shipping-address__max-width); + } + } + .table-checkout-shipping-method { + width: auto; + } +} + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { + .opc-wrapper { + .shipping-address-item { + .css(width, @checkout-shipping-item__width); + + &:before { + .css(background, @checkout-shipping-item-before__border-color); + .css(height, @checkout-shipping-item-before__height); + content: ''; + left: 0; + position: absolute; + top: 0; + width: 1px; + } + + &:nth-child(3n+1) { + &:before { + display: none; + } + } + + &.selected-item { + &:before { + display: none; + } + + + .shipping-address-item { + &:before { + display: none; + } + } + } + } + } + .table-checkout-shipping-method { + min-width: 500px; + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less new file mode 100644 index 0000000000000000000000000000000000000000..ed940f5fd3c4b45ee959dbfa48335ae02c642a7c --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar-shipping-information.less @@ -0,0 +1,69 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-sidebar-shipping-information__padding: @indent__l; +@checkout-sidebar-shipping-information__line-height: @checkout-billing-address-details__line-height; + +@checkout-sidebar-shipping-information-edit-icon__color: @minicart-icons-color; +@checkout-sidebar-shipping-information-edit-icon__content: @icon-settings; +@checkout-sidebar-shipping-information-edit-icon__font-size: 28px; +@checkout-sidebar-shipping-information-edit-icon__line-height: 28px; +@checkout-sidebar-shipping-information-edit-icon__top: 2px; +@checkout-sidebar-shipping-information-edit-icon__hover__color: @primary__color; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Shipping Information + // --------------------------------------------- + + .opc-block-shipping-information { + .css(padding, 0 @checkout-sidebar-shipping-information__padding); + + .shipping-information-title { + &:extend(.abs-checkout-title all); + .css(border-bottom, @checkout-step-title__border); + margin: 0 0 @indent__base; + position: relative; + + .action-edit { + &:extend(.abs-action-button-as-link all); + .css(top, @checkout-sidebar-shipping-information-edit-icon__top); + .icon-font( + @checkout-sidebar-shipping-information-edit-icon__content, + @_icon-font-size: @checkout-sidebar-shipping-information-edit-icon__font-size, + @_icon-font-line-height: @checkout-sidebar-shipping-information-edit-icon__line-height, + @_icon-font-text-hide: true, + @_icon-font-color: @checkout-sidebar-shipping-information-edit-icon__color, + @_icon-font-color-hover: @checkout-sidebar-shipping-information-edit-icon__hover__color, + @_icon-font-color-active: @checkout-sidebar-shipping-information-edit-icon__color + ); + margin: 0; + position: absolute; + right: 0; + } + } + + .shipping-information-content { + .css(line-height, @checkout-sidebar-shipping-information__line-height); + .actions-toolbar { + margin-left: 0; + } + } + + .ship-to, + .ship-via { + margin: 0 0 @indent__base; + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less new file mode 100644 index 0000000000000000000000000000000000000000..83934eaf6aab5185021cf59db52d2ea4f7c69c9a --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_sidebar.less @@ -0,0 +1,23 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-sidebar__margin: @indent__base; +@checkout-sidebar__margin__xl: 46px; +@checkout-sidebar__columns: 4; + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-sidebar { + .css(margin, @checkout-sidebar__margin__xl 0 @checkout-sidebar__margin); + .layout-column(2, 2, @checkout-sidebar__columns); + } +} diff --git a/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less new file mode 100644 index 0000000000000000000000000000000000000000..d867cc3387355f400f35932bbad34242d21c4c06 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_Checkout/web/css/source/module/checkout/_tooltip.less @@ -0,0 +1,137 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-tooltip__hover__z-index: @tooltip__z-index; +@checkout-tooltip-breakpoint__screen-m: @modal-popup-breakpoint-screen__m; + +@checkout-tooltip-icon-arrow__font-size: 10px; +@checkout-tooltip-icon-arrow__left: -( @checkout-tooltip-content__padding + @checkout-tooltip-icon-arrow__font-size - @checkout-tooltip-content__border-width); + +@checkout-tooltip-icon__color: @color-gray-light2; +@checkout-tooltip-icon__content: @icon-help; +@checkout-tooltip-icon__font-size: 24px; +@checkout-tooltip-icon__hover__color: @primary__color; + +@checkout-tooltip-content__background-color: @color-gray-light01; +@checkout-tooltip-content__border-color: @color-gray60; +@checkout-tooltip-content__border-width: 1px; +@checkout-tooltip-content__font-size: @font-size__base; +@checkout-tooltip-content__padding: 12px; +@checkout-tooltip-content__width: 270px; +@checkout-tooltip-content__active__border-color: darken(@checkout-tooltip-content__border-color, 20%); + +@checkout-tooltip-content-mobile-popup__width: 200px; +@checkout-tooltip-content-mobile__right: -(@indent__s); +@checkout-tooltip-content-mobile__top: 30px + @checkout-tooltip-icon-arrow__font-size; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + .field-tooltip { + position: absolute; + right: 0; + top: 1px; + + &:hover { + .css(z-index, @checkout-tooltip__hover__z-index); + cursor: pointer; + .field-tooltip-content { + display: block; + } + .field-tooltip-action { + &:before { + .css(color, @checkout-tooltip-icon__hover__color); + } + } + } + + .field-tooltip-action { + .icon-font( + @checkout-tooltip-icon__content, + @_icon-font-size: @checkout-tooltip-icon__font-size, + @_icon-font-text-hide: true, + @_icon-font-color: @checkout-tooltip-icon__color, + @_icon-font-color-hover: @checkout-tooltip-icon__hover__color, + @_icon-font-color-active: false + ); + &:focus { + &:before { + .css(color, @checkout-tooltip-icon__hover__color); + } + + .field-tooltip-content { + display: block; + } + } + } + + .field-tooltip-content { + .css(background, @checkout-tooltip-content__background-color); + .css(border, @checkout-tooltip-content__border-width solid @checkout-tooltip-content__border-color); + .css(border-radius, @checkout-tooltip-content__border-width); + .css(font-size, @checkout-tooltip-content__font-size); + .css(padding, @checkout-tooltip-content__padding); + .css(width, @checkout-tooltip-content__width); + display: none; + left: 38px; + position: absolute; + text-transform: none; + top: -9px; + word-wrap: break-word; + z-index: 2; + + &:before, + &:after { + .arrow( + @_position: left, + @_size: @checkout-tooltip-icon-arrow__font-size, + @_color: @checkout-tooltip-content__background-color + ); + .css(left, @checkout-tooltip-icon-arrow__left); + .css(top, @checkout-tooltip-content__padding); + content: ''; + display: block; + position: absolute; + z-index: 3; + } + &:before { + .css(border-right-color, @checkout-tooltip-content__active__border-color); + } + &:after { + .css(border-right-color, @checkout-tooltip-content__background-color); + width: 1px; + z-index: 4; + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { + .modal-popup { + .field-tooltip { + .field-tooltip-content { + .css(width, @checkout-tooltip-content-mobile-popup__width); + } + } + } +} + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @checkout-tooltip-breakpoint__screen-m) { + .field-tooltip { + .field-tooltip-content { + &:extend(.abs-checkout-tooltip-content-position-top-mobile all); + } + } +} diff --git a/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less b/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less new file mode 100644 index 0000000000000000000000000000000000000000..8361a32c5e8f3a20e2278ab8896b015237ade8c0 --- /dev/null +++ b/app/design/frontend/Magento/blank/Magento_SalesRule/web/css/source/_module.less @@ -0,0 +1,21 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .opc-wrapper { + .form-discount { + max-width: 500px; + .field { + .label { + &:extend(.abs-visually-hidden all); + } + } + } + } +} diff --git a/app/design/frontend/Magento/blank/web/css/_styles.less b/app/design/frontend/Magento/blank/web/css/_styles.less index e1f7113c61eafb29ebc4494b82ab2269961c86f9..75ff8775d8c8a10a656cc55c1d0bfd163bb4f800 100644 --- a/app/design/frontend/Magento/blank/web/css/_styles.less +++ b/app/design/frontend/Magento/blank/web/css/_styles.less @@ -5,3 +5,4 @@ @import 'source/lib/_lib.less'; // Global lib @import 'source/_sources.less'; // Theme styles +@import 'source/_components.less'; // Components styles (modal/sliding panel) diff --git a/app/design/frontend/Magento/blank/web/css/source/_components.less b/app/design/frontend/Magento/blank/web/css/source/_components.less new file mode 100644 index 0000000000000000000000000000000000000000..9f6db89c38d126d254ae3e4423ed7fccf8d3e1ed --- /dev/null +++ b/app/design/frontend/Magento/blank/web/css/source/_components.less @@ -0,0 +1,11 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Components +// _____________________________________________ + +@import 'components/_modals.less'; // from lib +@import 'components/_modals_extend.less'; // local diff --git a/app/design/frontend/Magento/blank/web/css/source/_extends.less b/app/design/frontend/Magento/blank/web/css/source/_extends.less index df818e7003ce2e68d7f529b31d2af5e2f82e6943..19705339dae3c4f0430aac361f16a2952ef1350c 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_extends.less +++ b/app/design/frontend/Magento/blank/web/css/source/_extends.less @@ -507,6 +507,12 @@ } } +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .abs-add-box-sizing-desktop-m { + @abs-add-box-sizing(); + } +} + // // Revert field type // --------------------------------------------- @@ -1022,9 +1028,176 @@ } // -// Form Field Date Input -//-------------------------------------- +// Form Field Date Input +// --------------------------------------------- + .abs-field-date-input { - margin-right: @indent__s; + .css(margin-right, @indent__s); width: calc(~"100% - (@{icon-calendar__font-size} + @{indent__s})"); } + +// +// Form Field Tooltip +// --------------------------------------------- + +.abs-field-tooltip { + &:extend(.abs-add-box-sizing all); + position: relative; + input { + .css(margin-right, @indent__s); + width: calc(~"100% - (@{checkout-tooltip-icon__font-size} + @{indent__s} + @{indent__xs})"); + &:focus { + + .field-tooltip { + .field-tooltip-action { + &:before { + .css(color, @checkout-tooltip-icon__hover__color); + } + } + .field-tooltip-content { + display: block; + } + } + } + } +} + +// +// Checkout Tooltip Content (position: top) +// --------------------------------------------- + +@abs-checkout-tooltip-content-position-top: { + .css(right, @checkout-tooltip-content-mobile__right); + .css(top, @checkout-tooltip-content-mobile__top); + left: auto; + + &:before, + &:after { + .arrow( + @_position: top, + @_size: @checkout-tooltip-icon-arrow__font-size, + @_color: @checkout-tooltip-content__background-color + ); + .css(margin-top, @checkout-tooltip-icon-arrow__left); + .css(right, @indent__s); + left: auto; + top: 0%; + } + &:before { + .css(border-bottom-color, @checkout-tooltip-content__border-color); + } + &:after { + .css(border-bottom-color, @checkout-tooltip-content__background-color); + top: 1px; + } +}; + +.abs-checkout-tooltip-content-position-top { + @abs-checkout-tooltip-content-position-top(); +} + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) { + .abs-checkout-tooltip-content-position-top-mobile { + @abs-checkout-tooltip-content-position-top(); + } +} + +// +// Checkout title +// --------------------------------------------- + +.abs-checkout-title { + .css(border-bottom, @checkout-step-title__border); + .css(padding-bottom, @checkout-step-title__padding); + .typography( + @_font-size: @checkout-step-title__font-size, + @_font-weight: @checkout-step-title__font-weight, + @_font-family: false, + @_font-style: false, + @_line-height: false + ); +} + +// +// Shopping cart sidebar and checkout sidebar totals +// --------------------------------------------- + +.abs-sidebar-totals { + .mark { + font-weight: @font-weight__regular; + padding-left: 4px; + strong { + font-weight: @font-weight__regular; + } + } + .amount { + padding-right: 4px; + text-align: right; + strong { + font-weight: @font-weight__regular; + } + } + .grand { + .mark, + .amount { + padding-top: @indent__base; + } + .amount { + padding-right: 4px; + text-align: right; + strong { + font-weight: @font-weight__bold; + } + } + } + .msrp { + margin-bottom: @indent__s; + } + .totals-tax { + &-summary { + .mark, + .amount { + .css(border-top, @border-width__base solid @border-color__base); + .css(border-bottom, @border-width__base solid @border-color__base); + cursor: pointer; + } + .amount .price { + position: relative; + padding-right: @indent__m; + .icon-font( + @icon-down, + @_icon-font-size: 30px, + @_icon-font-text-hide: true, + @_icon-font-position: after, + @_icon-font-display: block + ); + &:after { + position: absolute; + right: -5px; + top: -12px; + } + } + &.expanded { + .mark, + .amount { + border-bottom: 0; + } + .amount .price { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + } + &-details { + display: none; + .css(border-bottom, @border-width__base solid @border-color__base); + &.shown { + display: table-row; + } + } + } + .table-caption { + &:extend(.abs-no-display all); + } +} diff --git a/app/design/frontend/Magento/blank/web/css/source/_loaders.less b/app/design/frontend/Magento/blank/web/css/source/_loaders.less index 0c608a402d54782d412ab447990f01e045c00e73..576c7b2ca933ec7e365f24e50e12163c6819dfe5 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_loaders.less +++ b/app/design/frontend/Magento/blank/web/css/source/_loaders.less @@ -9,25 +9,34 @@ & when (@media-common = true) { -.load.indicator { - .loader(); - position: absolute; - > span { - display: none; + .load.indicator { + .loader(); + position: absolute; + > span { + display: none; + } } -} -.loading-mask { - .loading-mask(); - background: rgba(255, 255, 255, .5); - .loader { - > img { - .loading-mask(); + .loading-mask { + .loading-mask(); + background: rgba(255, 255, 255, .5); + .loader { + > img { + .loading-mask(); + } + > p { + display: none; + } } - > p { - display: none; + } + + body { + > .loading-mask { + z-index: @loader-overlay__z-index; } } -} + ._block-content-loading { + position: relative; + } } diff --git a/app/design/frontend/Magento/blank/web/css/source/_navigation.less b/app/design/frontend/Magento/blank/web/css/source/_navigation.less index c16516b0e20bd4069c4f9ee32df098ffb00ac623..f1809aeafb167fec419655d62d4f7969d68b8485 100644 --- a/app/design/frontend/Magento/blank/web/css/source/_navigation.less +++ b/app/design/frontend/Magento/blank/web/css/source/_navigation.less @@ -149,7 +149,7 @@ height: 100%; width: 100%; .page-wrapper { - height:100%; + height: 100%; overflow: hidden; position: relative; left: 0; diff --git a/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less new file mode 100644 index 0000000000000000000000000000000000000000..e4b01ecd0df6e5d9a9c0c10e275d6ccc5098efa1 --- /dev/null +++ b/app/design/frontend/Magento/blank/web/css/source/components/_modals_extend.less @@ -0,0 +1,166 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Components -> Modals +// _____________________________________________ + +// +// Variables +// --------------------------------------------- + +@modal-title__color: @text__color; +@modal-title__border: 1px solid @color-gray-light5; + +@modal-popup-title__font-size: 26px; +@modal-popup-title-mobile__font-size: @font-size__base; +@modal-popup-breakpoint-screen__m: @screen__m + 1; + +@modal-slide__first__indent-left: 44px; +@modal-slide-mobile__background-color: @color-gray-light01; +@modal-overlay__background-color: fade(@color-gray20, 55%); + +@modal-action-close__color: @primary__color; +@modal-action-close__font-size: 32px; +@modal-action-close__hover__color: darken(@primary__color, 10%); + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .modal-custom, + .modal-popup, + .modal-slide { + .action-close { + .button-reset(); + .button-icon( + @icon-remove, + @_icon-font-color: @minicart-icons-color, + @_icon-font-size: @modal-action-close__font-size, + @_icon-font-line-height: @modal-action-close__font-size, + @_icon-font-text-hide: true + ); + position: absolute; + right: 0; + top: 0; + &:hover { + &:before { + color: @modal-action-close__hover__color; + } + } + } + } + .modal-custom { + .action-close { + .css(margin, @indent__m); + } + } + .modal-popup { + .modal-title { + .css(border-bottom, @modal-title__border); + .css(font-weight, @font-weight__light); + .css(padding-bottom, @indent__s); + font-size: @modal-popup-title__font-size; + margin-bottom: 0; + min-height: 1em; + word-wrap: break-word; + } + .action-close { + padding: @modal-popup__padding; + } + } + + .modal-slide { + .action-close { + padding: @modal-slide-header__padding-vertical @modal-slide__padding; + } + .page-main-actions { + margin-top: @modal-slide-header__padding-vertical; + margin-bottom: @modal-slide-header__padding-vertical - (@indent__l/2); + } + } + + .modals-overlay { + .css(background-color, @modal-overlay__background-color); + bottom: 0; + left: 0; + position: fixed; + right: 0; + top: 0; + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @modal-popup-breakpoint-screen__m) { + .modal-popup { + &.modal-slide { + .modal-inner-wrap[class] { + .css(background-color, @modal-slide-mobile__background-color); + } + &._inner-scroll { + &._show { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + } + .modal-inner-wrap { + height: auto; + min-height: 100%; + } + } + } + .modal-title { + .css(font-size, @modal-popup-title-mobile__font-size); + .css(font-weight, @font-weight__bold); + } + } + .custom-slide { + .abs-modal(); + .abs-modal-slide(); + &._show { + -webkit-overflow-scrolling: touch; + overflow-y: auto; + overflow-x: hidden; + } + .modal-inner-wrap { + .css(background-color, @modal-slide-mobile__background-color); + box-sizing: border-box; + height: auto; + min-height: 100%; + } + } + body._has-modal-custom { + height: 100vh; + overflow: hidden; + width: 100vw; + .modal-custom-overlay { + .css(background-color, @modal-overlay__background-color); + height: 100vh; + left: 0; + position: fixed; + top: 0; + width: 100vw; + z-index: @overlay__z-index; + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @modal-popup-breakpoint-screen__m) { + .modal-popup { + &.modal-slide { + .modal-footer { + .css(border-top, @modal-title__border); + text-align: right; + } + } + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less index 9b111f1353784f0f84d6b39f63bd79fc1d246df1..85932830410a8ee3ef47bc3eabf105116270a9cc 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/_module.less @@ -5,647 +5,4 @@ @import 'module/_cart.less'; @import 'module/_minicart.less'; - -@opc-margin-left: 10%; - -// -// Common -// _____________________________________________ - -& when (@media-common = true) { - - // - // One Page Checkout - // --------------------------------------------- - - .opc-wrapper:extend(.abs-add-box-sizing all) { - .field select { - max-width: none; - } - > .opc:extend(.abs-reset-list all) { - } - .section { - &.allow { - .step-title { - cursor: pointer; - .icon-font( - @icon-edit, - @_icon-font-size: 20px, - @_icon-font-display: block, - @_icon-font-position: after - ); - &:after { - position: absolute; - right: 18px; - top: 12px; - } - } - &.active { - .step-title { - cursor: default; - } - .step-title:after { - display: none; - } - } - } - .step-content { - display: none; - } - &.active { - .step-title { - .css(color, @primary__color); - } - .step-content { - display: block; - } - } - } - .step { - &-title { - .css(background, @sidebar__background-color); - .css(color, lighten(@primary__color, 40%)); - margin-bottom: 2px; - padding: 13px @indent__m; - position: relative; - h2 { - .font-size(18); - font-weight: @font-weight__semibold; - margin: 0; - } - .number { - display: none; - } - } - - &-content { - padding: 35px @indent__m 80px; - position: relative; - .addresses .control { - margin: @indent__base 0 @indent__l; - } - .fieldset { - margin-bottom: 0; - &.login { - .form-hasrequired(bottom); - &:after { - margin-top: 35px; - text-align: center; - } - } - .legend.payments-title:extend(.abs-visually-hidden all) { - } - } - .methods-shipping { - .item-content { - .fieldset { - > .legend:extend(.abs-visually-hidden all) { - } - > .legend + br:extend(.abs-no-display all) { - } - > .field { - margin-bottom: 15px; - &:before { - display: none; - } - .control { - display: inline-block; - } - } - } - } - } - .form { - .form-hasrequired(bottom); - &:after { - text-align: center; - } - > .choice { - margin-top: @form-field__vertical-indent; - } - } - .form:not(.login), - .order-review { - .action.primary:extend(.abs-button-l all) { - } - } - .actions { - margin-top: @indent__xl; - } - .field.street { - .field.additional { - .label:extend(.abs-visually-hidden all) { - } - } - } - } - - .fieldset > .field:last-of-type { - margin-bottom: 0; - } - } - - // - // Customer login - // --------------------------------------------- - - .login-wrapper { - .block { - .block-title { - margin-bottom: @indent__l; - strong { - .font-size(22); - font-weight: @font-weight__light; - margin: 0; - } - } - .fieldset.guest { - margin-top: @indent__base; - } - .field { - &.choice { - margin-bottom: @indent__s; - } - &.note { - margin-bottom: @indent__l; - } - } - } - } - - .opc-payment-additional { - margin: 0 0 @indent__s 15px; - + .opc-payment { - margin: @indent__xl 0 0; - } - } - - .action.primary.checkout { - margin: 0 0 @indent__base; - } - - .hidden:extend(.abs-no-display all) { - } - - .actions-toolbar { - margin: @indent__xl 0 0; - } - - .field { - &.month { - padding-right: @indent__s; - .control { - position: relative; - &:after { - color: @primary__color__light; - content: '/'; - position: absolute; - right: -9px; - top: @indent__xs; - } - } - } - &.cvv { - width: 30%; - .control { - position: relative; - } - .note { - position: absolute; - right: -23px; - top: 0; - &:before { - display: none; - } - > a { - .icon-font( - @_icon-font-content: @icon-help, - @_icon-font-size: 16px, - @_icon-font-color: @primary__color__light, - @_icon-font-color-hover: @primary__color, - @_icon-font-text-hide: true - ); - } - } - } - } - } - - // - // Shipping methods - // --------------------------------------------- - - .methods-shipping { - .item-title:extend(.abs-methods-shipping-title all) { - } - .item-content:extend(.abs-adjustment-incl-excl-tax all) { - margin: 0 0 35px; - .field { - margin-bottom: 15px; - .price { - font-weight: @font-weight__bold; - } - &.choice { - .control { - float: left; - } - .label { - display: block; - overflow: hidden; - } - } - } - } - .price.box { - > .price { - display: block; - } - .regular .price, - .price .price { - font-weight: @font-weight__bold; - } - } - .price-box { - margin-bottom: @indent__xs; - margin-left: @indent__base; - margin-top: @indent__s; - } - } - - // - // Payment methods - // --------------------------------------------- - - .methods-payment { - border-bottom: @border-width__base solid @border-color__base; - .item-title { - border-top: @border-width__base solid @border-color__base; - font-weight: @font-weight__regular; - margin: 0; - padding: 16px 15px 15px; - } - .item-content { - margin: 0; - > .fieldset { - padding: 0 @indent__s @indent__xl; - &.redirect { - margin: @indent__s 0 @indent__l 37px; - padding: 0; - width: 80%; - } - } - } - img { - margin-right: @indent__xs; - vertical-align: middle; - } - } - - // - // Order review - // --------------------------------------------- - .table-order-review:extend(.abs-product-options-list all) { - thead tr:first-child th { - padding-top: 0; - } - .col { - &.price, - &.qty { - text-align: center; - white-space: nowrap; - } - &.price:extend(.abs-incl-excl-tax all), - &.subtotal:extend(.abs-incl-excl-tax all) { - } - } - .item-options:extend(.abs-add-clearfix all) { - margin: @indent__base 0 0; - .price { - font-weight: @font-weight__bold; - } - } - .product-item-name:extend(.abs-checkout-product-name all) { - } - .cart-price:extend(.abs-checkout-cart-price all) { - } - .grand.totals { - .font-size(16); - th, - td { - padding: 0 @indent__s; - } - } - } - - .cart-tax-info + .cart-tax-total, - .order-details-items .table-wrapper .cart-tax-info + .cart-tax-total { - display: block; - } - - // - // Checkout Progress - // --------------------------------------------- - - .opc-block-progress-wrapper { - margin-bottom: @indent__l; - margin-top: @indent__base; - } - - .opc-block-progress:extend(.abs-add-box-sizing all) { - display: none; - &.order-review-step { - display: block; - } - > .title { - .css(background, @sidebar__background-color); - .font-size(18); - font-weight: @font-weight__light; - margin: 0; - padding: @indent__s 15px; - strong { - font-weight: @font-weight__regular; - } - } - > .content { - .css(background, @sidebar__background-color); - padding: 0 15px; - .items { - margin: 0; - } - .item-title { - border-top: @border-width__base solid @border-color__base; - display: none; - margin: 0; - padding: 15px 0 7px; - &.complete { - display: block; - } - span { - .font-size(16); - font-weight: @font-weight__semibold; - } - } - .item-content { - display: none; - margin: 0; - overflow: hidden; - padding: 0 0 15px; - &.complete { - display: block; - } - } - .action { - font-weight: @font-weight__regular; - } - .data.table { - font-size: @font-size__s; - } - } - .payment-method { - > .title { - font-weight: @font-weight__light; - } - > .content { - margin: 0 0 @indent__s; - &:last-child { - margin-bottom: 0; - } - } - .items-cards { - margin: 0; - > .content { - margin: 0; - } - } - .data.table { - th { - padding: @indent__xs @indent__s @indent__xs 0; - } - td { - padding: @indent__xs 0; - } - } - } - } - - // - // Checkout Success - // --------------------------------------------- - - .checkout-onepage-success { - .page-title-wrapper { - .print:extend(.abs-no-display all) { - } - } - } - - .checkout-success { - .actions-toolbar { - margin-top: 50px; - } - } - - .checkout-onepage-index { - .nav-toggle:extend(.abs-no-display all) { - } - .logo { - margin-left: 0; - } - } -} - -// -// Mobile -// _____________________________________________ - -.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { - .table-wrapper.order-review-wrapper:extend(.abs-no-border-top all) { - .table.table-order-review:extend(.abs-checkout-order-review all) { - tbody tr { - td { - &:not(:last-child) { - border: none; - } - } - &:first-child td:first-child { - padding-top: 0; - } - } - } - - .table.table-order-review:not(.totals):not(.cart):not(.table-comparison) tbody > tr > td:last-child { - border-bottom: none; - border-top: none; - } - } -} - -// -// Desktop -// _____________________________________________ - -.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { - .checkout-onepage-index .column.main:extend(.abs-add-clearfix-desktop-s all) { - } - - .opc-wrapper:extend(.abs-add-box-sizing-desktop-s all) { - .layout-column(2, 2, @layout-column-checkout__width-main); - .step-content:extend(.abs-form-field-column-2-s all) { - .form { - &.shipping.address, - &.billing, - &.methods-shipping { - margin-left: @opc-margin-left; - width: 80%; - } - &:after { - text-align: right; - } - } - - .field { - &.street, - &.choice { - width: 100%; - } - &.street .field.additional { - padding: 0; - width: 100%; - } - } - - .payments, - .order-review { - .field:extend(.abs-form-field-revert-column-1-s all) { - &:nth-last-child(1), - &:nth-last-child(2) { - margin-bottom: @indent__base; - } - &:last-child { - margin: 0; - } - } - } - - .toolbar { - text-align: left; - } - } - - // - // Login or register - // --------------------------------------------- - - .login-wrapper:extend(.abs-add-clearfix-desktop-s all) { - .block:extend(.abs-blocks-2columns-s all) { - margin-bottom: 0; - } - .fieldset { - .field { - padding: 0; - width: 100%; - } - &.login:after { - text-align: left; - } - } - .field.choice:not(.persistent):before { - display: none; - } - } - - .checkout-submit-order .actions-toolbar > .primary { - float: right; - } - } - - // - // Payment methods - // --------------------------------------------- - - .methods-payment .item-content > .fieldset, - .order-review .fieldset { - margin: @indent__s 0 @indent__l @opc-margin-left; - padding: 0; - width: 46%; - .field .field { - &.cvv { - display: inline-block; - width: 30%; - } - &.date { - display: inline-block; - width: 70%; - } - &.month { - padding-right: 12px; - } - &.month, - &.year { - margin-bottom: 0; - } - } - } - - .checkout-success .subtitle .print { - margin-left: @indent__xl; - } - - .table-order-review { - .col.subtotal, - .amount { - text-align: right; - } - .col.item { - width: 70%; - } - .grand.totals { - .font-size(16); - th, - td { - padding: 0 0 @indent__xl; - } - strong { - border-top: @border-width__base solid @border-color__base; - display: block; - padding-top: 11px; - } - .mark { - strong { - margin-left: @indent__s; - padding-right: @indent__s; - } - } - .amount { - strong { - margin-right: @indent__s; - padding-left: @indent__s; - } - } - } - } - - // - // Checkout success - // --------------------------------------------- - - .checkout-onepage-success { - .page-title-wrapper { - .print:extend(.abs-action-print-s all) { - display: inline-block; - .font-size(14); - margin-left: @indent__xl; - } - } - } - - .opc-block-progress-wrapper:extend(.abs-add-box-sizing-desktop-s all) { - .layout-column(2, 1, @layout-column-checkout__width-left); - margin-top: 0; - padding-right: @layout-column-main__sidebar-offset; - } - - .opc-block-progress.active { - display: block; - } -} +@import 'module/_checkout.less'; diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less index 84fe60c7262910782021ee8c38b2d319cc66efc7..9157adac7398e56430135bd4835ffc768cc3d304 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_cart.less @@ -13,453 +13,366 @@ & when (@media-common = true) { - // - // Shopping cart - // --------------------------------------------- - - .checkout-cart-index { - .page-main { - padding-left: 0; - padding-right: 0; - } - .page-title-wrapper { - padding-left: @layout__width-xs-indent; - padding-right: @layout__width-xs-indent; - } + // + // Shopping cart + // --------------------------------------------- + + .checkout-cart-index { + .page-main { + padding-left: 0; + padding-right: 0; + } + .page-title-wrapper { + padding-left: @layout__width-xs-indent; + padding-right: @layout__width-xs-indent; + } + } + .cart { + // Cart container + &-container { + .form-cart { + &:extend(.abs-shopping-cart-items all); + } } - .cart { - // Cart container - &-container { - .form-cart { - &:extend(.abs-shopping-cart-items all); - } - } - - // Summary block - &-summary { - &:extend(.abs-add-box-sizing all); - .css(background, @sidebar__background-color); - margin-bottom: 25px; - padding: 1px 0 25px; - > .title { - display: none; - .font-size(24); - font-weight: @font-weight__light; - margin: 12px 0; - } - - .block { - form:not(:last-of-type) { - .fieldset { - margin: 0 0 @indent__m; - } - } - - .price { - font-weight: @font-weight__bold; - } - - .field { - margin: 0 0 16px; - &.note { - display: none; - } - } - - .actions-toolbar { - > .primary { - text-align: left; - .action.primary { - &:extend(.abs-revert-to-action-secondary all); - width: auto; - } - } - } - - .fieldset.estimate { - > .legend, - > .legend + br { - &:extend(.abs-no-display all); - } - } - &:extend(.abs-cart-block all); - .title { - strong { - .font-size(14); - font-weight: @font-weight__semibold; - } - } - .item-options { - margin: 0 0 16px; - .field { - .radio { - float: left; - } - .radio { - + .label { - display: block; - margin: 0; - overflow: hidden; - } - } - } - } - } - - .page-main & { - .block { - margin-bottom: 0; - } - } - - .checkout-methods-items { - &:extend(.abs-reset-list all); - margin: 20px 0 0; - padding: 0 @mobile-cart-padding; - text-align: center; - .action.primary.checkout { - &:extend(.abs-button-l all); - width: 100%; - } - .item { - margin-bottom: 25px; - &:last-child { - margin-bottom: 0; - } - } - } - .message { - padding-left: 20px; - > *:first-child:before { - display: none; - } - } - &:extend(.abs-adjustment-incl-excl-tax all); - } - - // Totals block - &-totals { - border-top: 1px solid @border-color__base; - padding-top: 10px; - tbody, - tfoot { - .mark { - border: 0; - font-weight: @font-weight__regular; - padding: 6px 0; - text-align: left; - } - .amount { - border: 0; - font-weight: @font-weight__regular; - padding: 6px 0 6px 14px; - text-align: right; - } - } - .table-caption { - &:extend(.abs-no-display all); - } - .grand { - th, - td { - padding: 11px 0; - } - .mark { - border-top: 1px solid @border-color__base; - .font-size(16); - padding-right: @indent__s; - strong { - display: inline-block; - font-weight: @font-weight__regular; - padding: 3px 0 0; - } - } - .amount { - border-top: 1px solid @border-color__base; - .font-size(18); - } - } - .msrp { - margin-bottom: @indent__s; - } - tbody tr:last-child td { - padding-bottom: 19px; - } - .totals-tax { - &-summary { - .mark, - .amount { - border-bottom: @border-width__base solid @border-color__base; - border-top: @border-width__base solid @border-color__base; - cursor: pointer; - } - .amount .price { - .icon-font( - @icon-down, - @_icon-font-size: 12px, - @_icon-font-line-height: 12px, - @_icon-font-text-hide: true, - @_icon-font-position: after - ); - padding-right: 20px; - position: relative; - &:after { - position: absolute; - right: 3px; - top: 3px; - } - } - &.expanded { - .mark, - .amount { - border-bottom: 0; - } - .amount .price { - .icon-font-symbol( - @_icon-font-content: @icon-up, - @_icon-font-position: after - ); - } - } - } - &-details { - border-bottom: @border-width__base solid @border-color__base; - display: none; - &.shown { - display: table-row; - } - } - } - .table-wrapper { - margin-bottom: 0; - } + // Summary block + &-summary { + &:extend(.abs-add-box-sizing all); + .css(background, @sidebar__background-color); + margin-bottom: 25px; + padding: 1px 0 25px; + > .title { + display: none; + .font-size(24); + font-weight: @font-weight__light; + margin: 12px 0; + } + + .block { + form:not(:last-of-type) { + .fieldset { + margin: 0 0 @indent__m; + } } - // Products table - &.table-wrapper { - .cart { - thead { - tr th.col { - border-bottom: @border-width__base solid @border-color__base; - padding-bottom: 15px; - padding-top: 24px; - } - } - tbody { - td { - border: 0; - } - } - > .item { - border-bottom: @border-width__base solid @border-color__base; - position: relative; - } - } - .col { - padding-top: 15px; - &.price, - &.subtotal, - &.msrp { - padding: @cart-item-cell-padding-top 11px @indent__s; - text-align: center; - &:extend(.abs-incl-excl-tax all); - } - &.qty { - padding: 20px 11px @indent__s; - text-align: center; - .label { - &:extend(.abs-visually-hidden all); - } - .input-text { - height: 36px; - margin-top: -7px; - text-align: center; - width: 45px; - } - } - > .price { - .css(color, @primary__color__lighter); - .font-size(18); - font-weight: @font-weight__bold; - } - } + .price { + font-weight: @font-weight__bold; + } - .item-actions { - td { - padding-bottom: 0; - padding-left: @mobile-cart-padding; - padding-right: @mobile-cart-padding; - white-space: normal; - } - } - .item { - .col.item { - display: block; - min-height: 75px; - padding: 15px @mobile-cart-padding @indent__s 90px; - position: relative; - } - } + .field { + margin: 0 0 16px; + &.note { + display: none; + } + } - .actions-toolbar { - &:extend(.abs-add-clearfix all); - min-height: 20px; - padding-bottom: 15px; - position: relative; - > .action-edit, - > .action-delete { - position: absolute; - right: 16px; - top: 0; - .icon-font( - @icon-edit, - @_icon-font-size: 18px, - @_icon-font-line-height: 20px, - @_icon-font-text-hide: true, - @_icon-font-color: @minicart-icons-color, - @_icon-font-color-hover: @primary__color, - @_icon-font-color-active: @minicart-icons-color - ); - } - > .action-delete { - right: 0; - .icon-font-symbol( - @_icon-font-content: @icon-trash - ); - } - } - .action { - margin-right: @indent__m; - &:last-child { - margin-right: 0; - } - &.help.map { - &:extend(.abs-action-button-as-link all); - font-weight: @font-weight__regular; - } + .actions-toolbar { + > .primary { + text-align: left; + .action.primary { + &:extend(.abs-revert-to-action-secondary all); + width: auto; } + } + } - .product { - &-item-photo { - display: block; - left: @mobile-cart-padding; - max-width: 65px; - padding: 0; - position: absolute; - top: 15px; - width: 100%; - } - &-item-name { - display: block; - .font-size(18); - margin: -3px 0 @indent__xs; - } - } - .gift-registry-name-label { - &:after { - content: ':'; - } + .fieldset.estimate { + > .legend, + > .legend + br { + &:extend(.abs-no-display all); + } + } + &:extend(.abs-cart-block all); + .title { + strong { + .font-size(14); + font-weight: @font-weight__semibold; + } + } + .item-options { + margin: 0 0 16px; + .field { + .radio { + float: left; + } + .radio { + + .label { + display: block; + margin: 0; + overflow: hidden; + } } + } + } + } - // Product options - .item-options { - margin-bottom: 0; - &:extend(.abs-product-options-list all); - &:extend(.abs-add-clearfix all); - } + .page-main & { + .block { + margin-bottom: 0; + } + } + + .checkout-methods-items { + &:extend(.abs-reset-list all); + margin: 20px 0 0; + padding: 0 @mobile-cart-padding; + text-align: center; + .action.primary.checkout { + &:extend(.abs-button-l all); + width: 100%; + } + .item { + margin-bottom: 25px; + &:last-child { + margin-bottom: 0; + } + } + } - .product-item-name + .item-options { - margin-top: @indent__base; - } + .message { + padding-left: 20px; + > *:first-child:before { + display: none; + } + } + &:extend(.abs-adjustment-incl-excl-tax all); + } - .cart-tax-total { - &:extend(.abs-tax-total all); - &-expanded { - &:extend(.abs-tax-total-expanded all); - } - } - .product-image-wrapper { - &:extend(.abs-reset-image-wrapper all); - } - .action.configure { - display: inline-block; - margin: @indent__s 0 0; - } - .item .message { - margin-top: @indent__base; - } + // Totals block + &-totals { + &:extend(.abs-sidebar-totals all); + tbody, + tfoot { + .mark { + text-align: left; } + } + } - // Discount - &-discount { + // Products table + &.table-wrapper { + .cart { + thead { + tr th.col { border-bottom: @border-width__base solid @border-color__base; - clear: left; - .block { - &:extend(.abs-cart-block all); - > .title { - strong { - color: @color-blue1; - font-weight: @font-weight__regular; - } - } - } - .fieldset > .field > .label { - display: none; - } - .actions-toolbar .primary { - .action { - &.primary, - &.cancel { - &:extend(.abs-revert-to-action-secondary all); - border-bottom-left-radius: 0; - border-top-left-radius: 0; - } - } - } - .action.check { - &:extend(.abs-action-button-as-link all); - font-weight: @font-weight__regular; - } - .fieldset { - display: table; - width: 100%; - } - .field { - display: table-cell; - } - .actions-toolbar { - display: table-cell; - vertical-align: top; - width: 1%; - .action { - &.primary, - &.cancel { - border-bottom-left-radius: 0; - border-top-left-radius: 0; - margin: 0 0 0 -1px; - white-space: nowrap; - width: auto; - } - } - .secondary { - bottom: 5px; - left: @mobile-cart-padding; - position: absolute; - } - } + padding-bottom: 15px; + padding-top: 24px; + } } - - // Empty cart - &-empty { - padding-left: @layout__width-xs-indent; - padding-right: @layout__width-xs-indent; + tbody { + td { + border: 0; + } + } + > .item { + border-bottom: @border-width__base solid @border-color__base; + position: relative; + } + } + .col { + padding-top: 15px; + &.price, + &.subtotal, + &.msrp { + padding: @cart-item-cell-padding-top 11px @indent__s; + text-align: center; + &:extend(.abs-incl-excl-tax all); + } + &.qty { + padding: 20px 11px @indent__s; + text-align: center; + .label { + &:extend(.abs-visually-hidden all); + } + .input-text { + height: 36px; + margin-top: -7px; + text-align: center; + width: 45px; + } + } + > .price { + .css(color, @primary__color__lighter); + .font-size(18); + font-weight: @font-weight__bold; + } + } + + .item-actions { + td { + padding-bottom: 0; + padding-left: @mobile-cart-padding; + padding-right: @mobile-cart-padding; + white-space: normal; + } + } + .item { + .col.item { + display: block; + min-height: 75px; + padding: 15px @mobile-cart-padding @indent__s 90px; + position: relative; + } + } + + .actions-toolbar { + &:extend(.abs-add-clearfix all); + min-height: 20px; + padding-bottom: 15px; + position: relative; + > .action-edit, + > .action-delete { + position: absolute; + right: 16px; + top: 0; + .icon-font( + @icon-edit, + @_icon-font-size: 18px, + @_icon-font-line-height: 20px, + @_icon-font-text-hide: true, + @_icon-font-color: @minicart-icons-color, + @_icon-font-color-hover: @primary__color, + @_icon-font-color-active: @minicart-icons-color + ); + } + > .action-delete { + right: 0; + .icon-font-symbol( + @_icon-font-content: @icon-trash + ); + } + } + .action { + margin-right: @indent__m; + &:last-child { + margin-right: 0; + } + &.help.map { + &:extend(.abs-action-button-as-link all); + font-weight: @font-weight__regular; + } + } + + .product { + &-item-photo { + display: block; + left: @mobile-cart-padding; + max-width: 65px; + padding: 0; + position: absolute; + top: 15px; + width: 100%; } + &-item-name { + display: block; + .font-size(18); + margin: -3px 0 @indent__xs; + } + } + .gift-registry-name-label { + &:after { + content: ':'; + } + } + + // Product options + .item-options { + margin-bottom: 0; + &:extend(.abs-product-options-list all); + &:extend(.abs-add-clearfix all); + } + + .product-item-name + .item-options { + margin-top: @indent__base; + } + + .cart-tax-total { + &:extend(.abs-tax-total all); + &-expanded { + &:extend(.abs-tax-total-expanded all); + } + } + .product-image-wrapper { + &:extend(.abs-reset-image-wrapper all); + } + .action.configure { + display: inline-block; + margin: @indent__s 0 0; + } + .item .message { + margin-top: @indent__base; + } + } - .cart-tax-info + .cart-tax-total { - display: block; + // Discount + &-discount { + border-bottom: @border-width__base solid @border-color__base; + clear: left; + .block { + &:extend(.abs-cart-block all); + > .title { + strong { + color: @color-blue1; + font-weight: @font-weight__regular; + } } + } + .fieldset > .field > .label { + display: none; + } + .actions-toolbar .primary { + .action { + &.primary, + &.cancel { + &:extend(.abs-revert-to-action-secondary all); + border-bottom-left-radius: 0; + border-top-left-radius: 0; + } + } + } + .action.check { + &:extend(.abs-action-button-as-link all); + font-weight: @font-weight__regular; + } + .fieldset { + display: table; + width: 100%; + } + .field { + display: table-cell; + } + .actions-toolbar { + display: table-cell; + vertical-align: top; + width: 1%; + .action { + &.primary, + &.cancel { + border-bottom-left-radius: 0; + border-top-left-radius: 0; + margin: 0 0 0 -1px; + white-space: nowrap; + width: auto; + } + } + .secondary { + bottom: 5px; + left: @mobile-cart-padding; + position: absolute; + } + } } + + // Empty cart + &-empty { + padding-left: @layout__width-xs-indent; + padding-right: @layout__width-xs-indent; + } + + .cart-tax-info + .cart-tax-total { + display: block; + } + } } // @@ -467,110 +380,97 @@ // _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { - .cart { - &-totals { - .table.totals { - th { - &:extend(.abs-col-no-prefix all); - display: table-cell; - } - td { - &:extend(.abs-col-no-prefix all); - display: table-cell; - } - tbody tr:not(:last-child) td { - &:extend(.abs-no-border-bottom-top all); - } - .amount { - text-align: right; - } - } - } - .table.items { - .col.item, - .item-actions td { - &:extend(.abs-col-no-prefix all); - } - .col.qty { - text-align: center; - } - tbody > tr > td:last-child { - &:extend(.abs-no-border-bottom-top all); - } - } + .cart { + &-totals { + .totals { + &:extend(.abs-sidebar-totals-mobile all); + } + } + .table.items { + .col.item, + .item-actions td { + &:extend(.abs-col-no-prefix all); + } + .col.qty { + text-align: center; + } + tbody > tr > td:last-child { + &:extend(.abs-no-border-bottom-top all); + } } + } } .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { - .cart { - // Cart container - &-container { - .form-cart { - .actions.main { - text-align: center; - } - } + .cart { + // Cart container + &-container { + .form-cart { + .actions.main { + text-align: center; } + } + } - &-discount { - border-bottom: @border-width__base solid @border-color__base; - } + &-discount { + border-bottom: @border-width__base solid @border-color__base; + } - &.table-wrapper { - border-top: @border-width__base solid @border-color__base; - thead { - .col { - &.item, - &.qty, - &.price, - &.subtotal, - &.msrp { - display: none; - } - } - } - .col { - &.qty, - &.price, - &.subtotal, - &.msrp { - box-sizing: border-box; - display: block; - float: left; - white-space: nowrap; - width: 33%; - &:before { - content: attr(data-th); - display: block; - font-weight: @font-weight__semibold; - padding-bottom: 10px; - } - } - &.msrp { - white-space: normal; - } - } - .item .col.item { - padding-bottom: 0; - } - tbody > tr > td:last-child { - border: 0; - } + &.table-wrapper { + border-top: @border-width__base solid @border-color__base; + thead { + .col { + &.item, + &.qty, + &.price, + &.subtotal, + &.msrp { + display: none; + } + } + } + .col { + &.qty, + &.price, + &.subtotal, + &.msrp { + box-sizing: border-box; + display: block; + float: left; + white-space: nowrap; + width: 33%; + &:before { + content: attr(data-th); + display: block; + font-weight: @font-weight__semibold; + padding-bottom: 10px; + } } + &.msrp { + white-space: normal; + } + } + .item .col.item { + padding-bottom: 0; + } + tbody > tr > td:last-child { + border: 0; + } + } - &-totals { - padding-left: @mobile-cart-padding; - padding-right: @mobile-cart-padding; - .table-wrapper { - border-top: 0; - } - .totals { - tbody > tr:not(:last-child) > td:last-child { - border: 0; - } - } + &-totals { + padding-left: @mobile-cart-padding; + padding-right: @mobile-cart-padding; + .table-wrapper { + border-top: 0; + } + .totals { + tbody > tr:not(:last-child) > td:last-child { + border: 0; } + } } + } } @@ -579,14 +479,14 @@ // _____________________________________________ & when (@media-common = true) { - // Cross sell - .block.crosssell { - margin-top: 70px; - .css(padding, 0 @mobile-cart-padding); - .product-item-info { - width: 200px; - } + // Cross sell + .block.crosssell { + margin-top: 70px; + .css(padding, 0 @mobile-cart-padding); + .product-item-info { + width: 200px; } + } } // @@ -594,150 +494,150 @@ // _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { - .checkout-cart-index { - .page-main { - padding-left: @layout__width-xs-indent; - padding-right: @layout__width-xs-indent; - } - .page-title-wrapper { - &:extend(.abs-revert-side-paddings all); - } + .checkout-cart-index { + .page-main { + padding-left: @layout__width-xs-indent; + padding-right: @layout__width-xs-indent; } - .cart { - // Cart container - &-container { - &:extend(.abs-add-clearfix-desktop all); - .form-cart { - &:extend(.abs-shopping-cart-items-desktop all); - .actions.main { - text-align: right; - } - } - .widget { - float: left; - } + .page-title-wrapper { + &:extend(.abs-revert-side-paddings all); + } + } + .cart { + // Cart container + &-container { + &:extend(.abs-add-clearfix-desktop all); + .form-cart { + &:extend(.abs-shopping-cart-items-desktop all); + .actions.main { + text-align: right; } + } + .widget { + float: left; + } + } - // Summary block - &-summary { - .layout-column(2, 2, @layout-column-checkout__width-left); - padding: 1px @indent__base @indent__m; - position: relative; - > .title { - display: block; - } - .fieldset .actions-toolbar { - margin-left: 0; - > .secondary { - float: none; - } - } - .block { - > .title { - padding-left: 0; - &:after { - right: 3px; - } - } - .content { - &:extend(.abs-revert-side-paddings all); - } - .fieldset { - .field { - .form-field-type-revert(@_type: block); - margin: 0 0 @indent__s; - } - } - } - .checkout-methods-items { - padding: 0; - } + // Summary block + &-summary { + .layout-column(2, 2, @layout-column-checkout__width-left); + padding: 1px @indent__base @indent__m; + position: relative; + > .title { + display: block; + } + .fieldset .actions-toolbar { + margin-left: 0; + > .secondary { + float: none; } + } + .block { + > .title { + padding-left: 0; + &:after { + right: 3px; + } + } + .content { + &:extend(.abs-revert-side-paddings all); + } + .fieldset { + .field { + .form-field-type-revert(@_type: block); + margin: 0 0 @indent__s; + } + } + } + .checkout-methods-items { + padding: 0; + } + } - // Products table - &.table-wrapper { - tbody td { - padding-top: @cart-item-cell-padding-top; - } - - .item { - .col.item { - padding: @cart-item-cell-padding-top 8px 20px 0; - } - } - - .item-actions td { - padding: 0; - } + // Products table + &.table-wrapper { + tbody td { + padding-top: @cart-item-cell-padding-top; + } - .product { - &-item-photo { - display: table-cell; - max-width: 100%; - padding-right: 20px; - position: static; - vertical-align: top; - width: 1%; - } - &-item-details { - padding-bottom: 35px; - } - &-item-details { - display: table-cell; - vertical-align: top; - white-space: normal; - width: 99%; - } - } + .item { + .col.item { + padding: @cart-item-cell-padding-top 8px 20px 0; } - - // Discount - &-discount { - border: 0; - .layout-column(2, 1, @layout-column-checkout__width-main); - &:extend(.abs-add-box-sizing-desktop all); - padding-right: 4%; - .block { - &:extend(.abs-blocks-2columns all); - width: 48%; - > .title { - border: 0; - cursor: default; - padding: 0 0 10px; - .column.main & strong { - .font-size(16); - } - &:after { - display: none; - } - } - .content { - display: block !important; // Need for overwriting collapsible widget - padding: 0; - } - } - .actions-toolbar { - .secondary { - bottom: -30px; - left: 0; - position: absolute; - } - } + } + + .item-actions td { + padding: 0; + } + + .product { + &-item-photo { + display: table-cell; + max-width: 100%; + padding-right: 20px; + position: static; + vertical-align: top; + width: 1%; } - - // Empty cart - &-empty { - &:extend(.abs-revert-side-paddings all); + &-item-details { + padding-bottom: 35px; } + &-item-details { + display: table-cell; + vertical-align: top; + white-space: normal; + width: 99%; + } + } } - // Cross sell - .block.crosssell { - .layout-column(2, 1, @layout-column-checkout__width-main); - &:extend(.abs-add-box-sizing-desktop all); - padding: 0 4% 0 0; - .products-grid .product-item { - width: 100%/4; + // Discount + &-discount { + border: 0; + .layout-column(2, 1, @layout-column-checkout__width-main); + &:extend(.abs-add-box-sizing-desktop all); + padding-right: 4%; + .block { + &:extend(.abs-blocks-2columns all); + width: 48%; + > .title { + border: 0; + cursor: default; + padding: 0 0 10px; + .column.main & strong { + .font-size(16); + } + &:after { + display: none; + } + } + .content { + display: block !important; // Need for overwriting collapsible widget + padding: 0; } + } + .actions-toolbar { + .secondary { + bottom: -30px; + left: 0; + position: absolute; + } + } + } + + // Empty cart + &-empty { + &:extend(.abs-revert-side-paddings all); + } + } + + // Cross sell + .block.crosssell { + .layout-column(2, 1, @layout-column-checkout__width-main); + &:extend(.abs-add-box-sizing-desktop all); + padding: 0 4% 0 0; + .products-grid .product-item { + width: 100%/4; } + } } diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less index ddeb77db7fdfda33523a0f4a167f393ece533d43..86564ca26cb6aa19691789f4b16a2917b8f84744 100644 --- a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/_minicart.less @@ -5,330 +5,332 @@ // // Variables -// --------------------------------------------- +// _____________________________________________ @minicart__border-color: @color-gray80; @minicart__padding-horizontal: @indent__base; // // Common -// --------------------------------------------- +// _____________________________________________ & when (@media-common = true) { -// -// Minicart -// --------------------------------------------- + // + // Minicart + // --------------------------------------------- -.block-minicart { - .items-total { - float: left; - margin: 0 @indent__s; - .count { - font-weight: @font-weight__bold; + .block-minicart { + .items-total { + float: left; + margin: 0 @indent__s; + .count { + font-weight: @font-weight__bold; + } } - } - .subtotal { - margin: 0 @indent__s; - text-align: right; - .label { - &:extend(.abs-colon all); + .subtotal { + margin: 0 @indent__s; + text-align: right; + .label { + &:extend(.abs-colon all); + } } - } - .amount { - .price-wrapper { - &:first-child { - .price { - font-size: @font-size__l; - font-weight: @font-weight__bold; + .amount { + .price-wrapper { + &:first-child { + .price { + font-size: @font-size__l; + font-weight: @font-weight__bold; + } } } } - } - .subtitle { - display: none; - } - .subtitle { - &.empty { - display: block; - padding: @indent__l 0 @indent__base; - text-align: center; - font-size: 14px; - } - } - .text { - &.empty { - text-align: center; + .subtitle { + display: none; + &.empty { + display: block; + padding: @indent__l 0 @indent__base; + text-align: center; + font-size: 14px; + } } - } - .block-content { - > .actions { - margin-top: 15px; - > .secondary { + .text { + &.empty { text-align: center; } - > .primary { - margin: 0 @indent__s 15px; - .action { - &.primary { - &:extend(.abs-button-l all); - display: block; - width: 100%; + } + .block-content { + > .actions { + margin-top: 15px; + > .secondary { + text-align: center; + } + > .primary { + margin: 0 @indent__s 15px; + .action { + &.primary { + &:extend(.abs-button-l all); + display: block; + width: 100%; + } } } - } - .paypal-logo { - margin-top: 15px; - text-align: center; + .paypal-logo { + margin-top: 15px; + text-align: center; + } } } + .block-category-link, + .block-product-link, + .block-cms-link, + .block-banners { + margin: 15px 0 0; + text-align: center; + } } - .block-category-link, - .block-product-link, - .block-cms-link, - .block-banners { - margin: 15px 0 0; - text-align: center; - } -} -.minicart-wrapper { - .dropdown( - @_toggle-selector: ~".action.showcart", - @_options-selector: ~".block-minicart", - @_dropdown-toggle-icon-content: @icon-cart, - @_dropdown-toggle-active-icon-content: @icon-cart, - @_dropdown-list-item-padding: false, - @_dropdown-list-item-hover: false, - @_icon-font-position: before, - @_icon-font-size: 22px, - @_icon-font-line-height: 28px, - @_icon-font-color: @minicart-icons-color, - @_icon-font-color-hover: @minicart-icons-color-hover, - @_icon-font-color-active: @minicart-icons-color - ); - float: right; - .block-minicart { - .css(padding, 25px @minicart__padding-horizontal); - right: 0; - width: 320px; - .block-title { - display: none; - } - &:after { - left: auto; - right: 25px; - } - &:before { - left: auto; - right: 26px; + .minicart-wrapper { + .dropdown( + @_toggle-selector: ~".action.showcart", + @_options-selector: ~".block-minicart", + @_dropdown-toggle-icon-content: @icon-cart, + @_dropdown-toggle-active-icon-content: @icon-cart, + @_dropdown-list-item-padding: false, + @_dropdown-list-item-hover: false, + @_icon-font-position: before, + @_icon-font-size: 22px, + @_icon-font-line-height: 28px, + @_icon-font-color: @minicart-icons-color, + @_icon-font-color-hover: @minicart-icons-color-hover, + @_icon-font-color-active: @minicart-icons-color + ); + float: right; + .block-minicart { + .css(padding, 25px @minicart__padding-horizontal); + right: 0; + width: 320px; + .block-title { + display: none; + } + &:after { + left: auto; + right: 25px; + } + &:before { + left: auto; + right: 26px; + } } - } - .product { - .actions { - float: right; - margin: -24px 0 0; - > .primary, - > .secondary { - display: inline; - &:not(:last-child) { - margin-right: 15px; + .product { + .actions { + float: right; + margin: -24px 0 0; + > .primary, + > .secondary { + display: inline; + &:not(:last-child) { + margin-right: 15px; + } } } } - } - .action { - &.close { - width: 40px; - height: 40px; - top: 0; - right: 0; - position: absolute; - .button-reset(); - .button-icon( - @icon-remove, - @_icon-font-color: @minicart-icons-color, - @_icon-font-size: 16px, - @_icon-font-line-height: 16px, - @_icon-font-text-hide: true - ); - } - &.showcart { - .text { - &:extend(.abs-visually-hidden all); + .action { + &.close { + width: 40px; + height: 40px; + top: 0; + right: 0; + position: absolute; + .button-reset(); + .button-icon( + @icon-remove, + @_icon-font-color: @minicart-icons-color, + @_icon-font-size: 16px, + @_icon-font-line-height: 16px, + @_icon-font-text-hide: true + ); } - white-space: nowrap; - .counter.qty { - &.empty { - display: none; + &.showcart { + .text { + &:extend(.abs-visually-hidden all); + } + white-space: nowrap; + .counter.qty { + &.empty { + display: none; + } + .css(background, @active__color); + border-radius: 2px; + .css(color, @page__background-color); + clip: none; + display: inline-block; + height: 24px; + line-height: 24px; + min-width: 18px; + margin: 3px 0 0; + padding: 0 3px; + overflow: hidden; + text-align: center; + white-space: normal; + } + .counter-label { + &:extend(.abs-visually-hidden all); } - .css(background, @active__color); - border-radius: 2px; - .css(color, @page__background-color); - clip: none; - display: inline-block; - height: 24px; - line-height: 24px; - min-width: 18px; - margin: 3px 0 0; - padding: 0 3px; - overflow: hidden; - text-align: center; - white-space: normal; - } - .counter-label { - &:extend(.abs-visually-hidden all); } } + .minicart-widgets { + margin-top: 15px; + } } - .minicart-widgets { - margin-top: 15px; - } -} -.minicart-items-wrapper { - .css(border, 1px solid @minicart__border-color); - .css(margin, 0 -@minicart__padding-horizontal); - border-left: 0; - border-right: 0; - overflow-x: auto; - padding: 15px; -} + .minicart-items-wrapper { + .css(border, 1px solid @minicart__border-color); + .css(margin, 0 -@minicart__padding-horizontal); + border-left: 0; + border-right: 0; + overflow-x: auto; + padding: 15px; + } -.minicart-items { - .list-reset-styles(0, 0); - .item { - &:not(:first-child) { - .css(border-top, 1px solid @minicart__border-color); - } - padding: @indent__base 0; - &:first-child { - padding-top: 0; - } - > .product { - &:extend(.abs-add-clearfix all); + .minicart-items { + .list-reset-styles(0, 0); + .product-item { + &:not(:first-child) { + .css(border-top, 1px solid @minicart__border-color); + } + padding: @indent__base 0; + &:first-child { + padding-top: 0; + } + > .product { + &:extend(.abs-add-clearfix all); + } } - } - .product-image-wrapper { - &:extend(.abs-reset-image-wrapper all); - } - .product-item-pricing { - .label { - display: inline-block; - width: 4.5rem; + .product-image-wrapper { + &:extend(.abs-reset-image-wrapper all); } - } - .price-minicart { - margin-bottom: @indent__xs; - } - .product-item-photo { - float: left; - } - .product-item-name { - font-weight: @font-weight__regular; - margin: 0 0 @indent__s; - a { - .css(color, @link__color); - } - } - .product-item-details { - padding-left: 88px; - .price { - font-weight: @font-weight__bold; + .product-item-pricing { + .label { + display: inline-block; + width: 4.5rem; + } } - .price-including-tax, - .price-excluding-tax { - margin: @indent__xs 0; + .price-minicart { + margin-bottom: @indent__xs; } - .weee[data-label] { - .font-size(11); - .label { - &:extend(.abs-no-display all); + .product-item-name { + font-weight: @font-weight__regular; + margin: 0 0 @indent__s; + a { + .css(color, @link__color); } } - .details-qty { - margin-top: @indent__s; + .product-item-details { + padding-left: 88px; + .price { + font-weight: @font-weight__bold; + } + .price-including-tax, + .price-excluding-tax { + margin: @indent__xs 0; + } + .weee[data-label] { + .font-size(11); + .label { + &:extend(.abs-no-display all); + } + } + .details-qty { + margin-top: @indent__s; + } } - } - .product { - .toggle { - &:extend(.abs-toggling-title all); - &:after { - position: static; - margin: 0 0 0 @indent__xs; - .css(color, @color-gray56); + .product { + > .product-item-photo, + > .product-image-container { + float: left; + } + .toggle { + &:extend(.abs-toggling-title all); + &:after { + position: static; + margin: 0 0 0 @indent__xs; + .css(color, @color-gray56); + } + border: 0; + padding: 0 @indent__xl @indent__xs 0; + } + .active { + > .toggle { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + &.pricing { + margin-top: 3px; + } + &.options { + .tooltip.toggle { + .icon-font( + @icon-down, + @_icon-font-size: 12px, + @_icon-font-line-height: 12px, + @_icon-font-text-hide: true, + @_icon-font-margin: -3px 0 0 7px, + @_icon-font-position: after + ); + } + .details { + display: none; + } } - border: 0; - padding: 0 @indent__xl @indent__xs 0; } - .active { - > .toggle { - .icon-font-symbol( - @_icon-font-content: @icon-up, - @_icon-font-position: after - ); + .details-qty, + .price-minicart { + .label { + &:extend(.abs-colon all); } } - &.pricing { - margin-top: 3px; + .item-qty { + width: 40px; + text-align: center; + margin-right: @indent__s; + } + .update-cart-item { + vertical-align: top; + .font-size(11); } - &.options { - .tooltip.toggle { + .action { + &.edit, + &.delete { .icon-font( - @icon-down, - @_icon-font-size: 12px, - @_icon-font-line-height: 12px, + @icon-edit, + @_icon-font-size: 18px, + @_icon-font-line-height: 20px, @_icon-font-text-hide: true, - @_icon-font-margin: -3px 0 0 7px, - @_icon-font-position: after + @_icon-font-color: @minicart-icons-color, + @_icon-font-color-hover: @primary__color, + @_icon-font-color-active: @minicart-icons-color ); } - .details { - display: none; + &.delete { + .icon-font-symbol( + @_icon-font-content: @icon-trash + ); } } - } - .details-qty, - .price-minicart { - .label { - &:extend(.abs-colon all); - } - } - .item-qty { - width: 40px; - text-align: center; - margin-right: @indent__s; - } - .update-cart-item { - vertical-align: top; - .font-size(11); - } - .action { - &.edit, - &.delete { - .icon-font( - @icon-edit, - @_icon-font-size: 18px, - @_icon-font-line-height: 20px, - @_icon-font-text-hide: true, - @_icon-font-color: @minicart-icons-color, - @_icon-font-color-hover: @primary__color, - @_icon-font-color-active: @minicart-icons-color - ); - } - &.delete { - .icon-font-symbol( - @_icon-font-content: @icon-trash - ); + .subtitle { + display: none; } } -} } // // Mobile -// --------------------------------------------- +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__xs) { .minicart-wrapper .block-minicart { @@ -345,7 +347,7 @@ // // Desktop -// --------------------------------------------- +// _____________________________________________ .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .minicart-wrapper { diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less new file mode 100644 index 0000000000000000000000000000000000000000..f8f2ee61ddae6ef52ea6ee2ca6a73c0b2c118cde --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_checkout.less @@ -0,0 +1,94 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-wrapper__margin: @indent__base; +@checkout-wrapper__columns: 16; + +@checkout-step-title__border: @border-width__base solid @color-gray80; +@checkout-step-title__font-size: 26px; +@checkout-step-title__font-weight: @font-weight__light; +@checkout-step-title__margin-bottom: 28px; +@checkout-step-title__padding: @indent__s; + +@checkout-step-title-mobile__font-size: 18px; +@checkout-step-title-mobile__margin-bottom: @indent__base; + +@checkout-step-content-mobile__background: @color-gray-light01; +@checkout-step-content-mobile__margin-s: 15px; +@checkout-step-content-mobile__margin: 0 -(@checkout-step-content-mobile__margin-s) @checkout-step-content-mobile__margin-s; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + .checkout-container { + &:extend(.abs-add-clearfix all); + .css(margin, 0 0 @checkout-wrapper__margin); + } + + .opc-wrapper { + .css(margin, 0 0 @checkout-wrapper__margin); + + .opc { + &:extend(.abs-reset-list all); + } + + .step-title { + &:extend(.abs-checkout-title all); + .css(border-bottom, @checkout-step-title__border); + .css(margin, 0 0 @checkout-step-title__margin-bottom); + } + + .step-content { + margin: 0 0 @indent__xl; + } + } + + .checkout-onepage-index { + .nav-sections, + .nav-toggle { + display: none; + } + .logo { + margin-left: 0; + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .opc-wrapper { + .step-title { + .css(font-size, @checkout-step-title-mobile__font-size); + .css(margin-bottom, @checkout-step-title-mobile__margin-bottom); + border-bottom: 0; + padding-bottom: 0; + } + .step-content { + .css(margin, 0 0 @checkout-step-content-mobile__margin-s); + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-wrapper { + &:extend(.abs-add-box-sizing-desktop-m all); + .layout-column(2, 1, @checkout-wrapper__columns); + padding-right: @indent__l; + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less new file mode 100644 index 0000000000000000000000000000000000000000..ccef519f1cbb1cbb51a1937d9a1ee524e74d621b --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_estimated-total.less @@ -0,0 +1,58 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Checkout Estimated Total + // --------------------------------------------- + + .opc-estimated-wrapper { + &:extend(.abs-no-display-desktop all); + &:extend(.abs-add-clearfix all); + .css(background, @checkout-step-content-mobile__background); + .css(border-bottom, @checkout-step-title__border); + .css(border-top, @checkout-step-title__border); + .css(margin, -21px -(@checkout-step-content-mobile__margin-s) @checkout-step-content-mobile__margin-s); + padding: 18px 15px; + + .estimated-block { + .css(font-size, @checkout-step-title-mobile__font-size); + float: left; + font-weight: @font-weight__bold; + + .estimated-label { + display: block; + margin: 0 0 @indent__xs; + } + } + + .minicart-wrapper { + button { + // todo ui: Change .action.showcart to .action-showcart + &.action.showcart { + .button-reset(); + &:before { + .css(color, @primary__color); + } + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { + .opc-estimated-wrapper { + display: none; + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less new file mode 100644 index 0000000000000000000000000000000000000000..7b2c5a55d6aa4e9000be31b548c098fa17adf33d --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_modals.less @@ -0,0 +1,90 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-modal-popup__width: 800px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + .checkout-onepage-index { + .modal-popup { + .field-tooltip { + .field-tooltip-content { + &:extend(.abs-checkout-tooltip-content-position-top all); + } + } + .fieldset { + .field { + .label { + font-weight: @font-weight__regular; + } + } + } + .modal-footer { + .action-hide-popup { + &:extend(.abs-action-button-as-link all); + margin-top: 8px; + } + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .checkout-onepage-index { + .modal-popup { + .modal-footer { + .action-save-address { + width: 100%; + } + .action-hide-popup { + margin-top: @indent__base; + } + } + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-onepage-index { + .modal-popup { + .form-shipping-address { + .css(max-width, @checkout-shipping-address__max-width); + } + .modal-footer { + .action-save-address { + float: right; + margin: 0 0 0 @indent__base; + } + } + } + } +} + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { + .checkout-onepage-index { + .modal-popup { + .modal-inner-wrap { + .css(margin-left, -(@checkout-modal-popup__width/2)); + .css(width, @checkout-modal-popup__width); + left: 50%; + } + } + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less new file mode 100644 index 0000000000000000000000000000000000000000..b77969dddddadfcd9985ed4fde68e3ef7aa9a5b6 --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_order-summary.less @@ -0,0 +1,188 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-summary__background-color: @color-white-smoke; +@checkout-summary__padding: 22px @indent__l; + +@checkout-summary-title__margin: @indent__s; +@checkout-summary-mark-value__color: @color-gray60; + +@checkout-summary-items__max-height: 370px; +@checkout-summary-items__padding: 15px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Order Summary + // --------------------------------------------- + + .opc-block-summary { + .css(background, @checkout-summary__background-color); + .css(margin, 0 0 @checkout-sidebar__margin); + .css(padding, @checkout-summary__padding); + &:extend(.abs-add-box-sizing all); + + > .title { + &:extend(.abs-checkout-title all); + display: block; + } + + // Totals table + .table-totals { + &:extend(.abs-sidebar-totals all); + } + + .mark { + .value { + .css(color, @checkout-summary-mark-value__color); + display: block; + } + } + + .grand.incl { + & + .grand.excl { + .mark, + .amount { + border-top: 0; + .font-size(14); + padding-top: 0; + strong { + font-weight: @font-weight__regular; + } + } + } + } + + .not-calculated { + font-style: italic; + } + + // + // Items list + // --------------------------------------------- + + // Block title + .items-in-cart { + > .title { + border-bottom: @border-width__base solid @border-color__base; + .css(padding, @indent__s @indent__xl @indent__s 0); + cursor: pointer; + .icon-font( + @icon-down, + @_icon-font-size: 12px, + @_icon-font-line-height: 12px, + @_icon-font-text-hide: true, + @_icon-font-margin: 3px 0 0, + @_icon-font-position: after, + @_icon-font-display: block + ); + margin-bottom: 0; + position: relative; + &:after { + position: absolute; + right: 0; + top: @indent__s; + } + strong { + .font-size(18); + font-weight: @font-weight__light; + margin: 0; + } + } + &.active { + > .title { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + .product { + position: relative; + } + } + + // Cart items + .minicart-items-wrapper { + .css(margin, 0 -(@checkout-summary-items__padding) 0 0); + .css(max-height, @checkout-summary-items__max-height); + .css(padding, @checkout-summary-items__padding @checkout-summary-items__padding 0 0); + border: 0; + } + .column.main & { + .product-item { + margin: 0; + padding-left: 0; + } + } + .product-item { + .product-item-inner { + display: table; + margin: 0 0 @indent__s; + width: 100%; + } + .product-item-name-block { + display: table-cell; + padding-right: @indent__xs; + text-align: left; + } + .subtotal { + display: table-cell; + text-align: right; + } + .price { + .font-size(16); + font-weight: @font-weight__regular; + } + .price-including-tax { + & + .price-excluding-tax { + .price { + .font-size(10); + } + } + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .opc-block-summary { + > .title { + border-bottom: 0; + .css(font-size, @checkout-step-title-mobile__font-size); + .css(margin-bottom, @checkout-step-title-mobile__margin-bottom); + padding-bottom: 0; + } + .totals { + &:extend(.abs-sidebar-totals-mobile all); + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .opc-summary-wrapper { + .modal-header { + .action-close { + display: none; + } + } + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less new file mode 100644 index 0000000000000000000000000000000000000000..13b59d044d72bef7d86ee8c84ee5979a3745407c --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_progress-bar.less @@ -0,0 +1,181 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-progress-bar__font-size: 18px; +@checkout-progress-bar__font-weight: @font-weight__light; +@checkout-progress-bar__margin: @indent__base; + +@checkout-progress-bar-item__background-color: @color-gray-middle1; +@checkout-progress-bar-item__border-radius: 6px; +@checkout-progress-bar-item__color: @primary__color; +@checkout-progress-bar-item__margin: @indent__s; +@checkout-progress-bar-item__transition: background .3s; +@checkout-progress-bar-item__width: 185px; + +@checkout-progress-bar-item__active__background-color: @color-orange-red1; +@checkout-progress-bar-item__complete__color: @link__color; +@checkout-progress-bar-item__hover__background-color: darken(@checkout-progress-bar-item__background-color, 5%); + +@checkout-progress-bar-item-element__height: @checkout-progress-bar-item-element__width; +@checkout-progress-bar-item-element__width: 38px; + +@checkout-progress-bar-item-element-inner__background-color: @page__background-color; +@checkout-progress-bar-item-element-inner__color: @checkout-progress-bar-item__color; +@checkout-progress-bar-item-element-inner__height: @checkout-progress-bar-item-element-inner__width; +@checkout-progress-bar-item-element-inner__width: @checkout-progress-bar-item-element__width - ( @checkout-progress-bar-item-element-outer-radius__width*2 ); +@checkout-progress-bar-item-element-inner__active__content: @icon-checkmark; + +@checkout-progress-bar-item-element-outer-radius__width: 6px; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + // + // Checkout Progress Bar + // --------------------------------------------- + + .opc-progress-bar { + &:extend(.abs-no-display-s all); + &:extend(.abs-reset-list all); + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__s) { + + .opc-progress-bar { + .css(margin, 0 0 @checkout-progress-bar__margin); + counter-reset: i; + font-size: 0; + } + + .opc-progress-bar-item { + .css(margin, 0 0 @checkout-progress-bar-item__margin); + .css(width, @checkout-progress-bar-item__width); + display: inline-block; + position: relative; + text-align: center; + vertical-align: top; + + &:before { // Horizontal line + .css(background, @checkout-progress-bar-item__background-color); + .css(top, @checkout-progress-bar-item-element__width/2); + .css(transition, @checkout-progress-bar-item__transition); + content: ''; + height: 7px; + left: 0; + position: absolute; + width: 100%; + } + + &:first-child { + &:before { + .css(border-radius, @checkout-progress-bar-item__border-radius 0 0 @checkout-progress-bar-item__border-radius); + } + } + + &:last-child { + &:before { + .css(border-radius, 0 @checkout-progress-bar-item__border-radius @checkout-progress-bar-item__border-radius 0); + } + } + + > span { + display: inline-block; + padding-top: 45px; + width: 100%; + word-wrap: break-word; + + .typography( + @_color: @checkout-progress-bar-item__background-color, + @_font-family: false, + @_font-size: @checkout-progress-bar__font-size, + @_font-style: false, + @_font-weight: @checkout-progress-bar__font-weight, + @_line-height: false + ); + + &:before, // Item element + &:after { + .css(background, @checkout-progress-bar-item__background-color); + .css(height, @checkout-progress-bar-item-element__height); + .css(margin-left, -(@checkout-progress-bar-item-element__width/2)); + .css(transition, @checkout-progress-bar-item__transition); + .css(width, @checkout-progress-bar-item-element__width); + border-radius: 50%; + content: ''; + left: 50%; + position: absolute; + top: 0; + } + + &:after { // Item element inner + .css(background, @checkout-progress-bar-item-element-inner__background-color); + .css(height, @checkout-progress-bar-item-element-inner__height); + .css(margin-left, -(@checkout-progress-bar-item-element-inner__width/2)); + .css(top, @checkout-progress-bar-item-element-outer-radius__width); + .css(width, @checkout-progress-bar-item-element-inner__width); + content: counter(i); + counter-increment: i; + .typography( + @_color: @checkout-progress-bar-item-element-inner__color, + @_font-family: false, + @_font-size: @checkout-progress-bar__font-size, + @_font-style: false, + @_font-weight: @font-weight__semibold, + @_line-height: false + ); + } + } + + &._complete { + cursor: pointer; + &:hover { + &:before { + .css(background, @checkout-progress-bar-item__hover__background-color); + } + > span { + &:before { + .css(background, @checkout-progress-bar-item__hover__background-color); + } + } + } + > span { + .css(color, @checkout-progress-bar-item__complete__color); + + &:after { + .css(font-family, @icons__font-name); + .css(content, @checkout-progress-bar-item-element-inner__active__content); + } + } + } + + &._active { + &:before { + background: @checkout-progress-bar-item__active__background-color; + } + > span { + .css(color, @checkout-progress-bar-item__color); + &:before { + .css(background, @checkout-progress-bar-item__active__background-color); + } + &:after { + .css(font-family, @icons__font-name); + .css(content, @checkout-progress-bar-item-element-inner__active__content); + } + } + } + } +} diff --git a/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less new file mode 100644 index 0000000000000000000000000000000000000000..fb2d200134402a5cc74cf30552da410b542dc21e --- /dev/null +++ b/app/design/frontend/Magento/luma/Magento_Checkout/web/css/source/module/checkout/_shipping.less @@ -0,0 +1,340 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Variables +// _____________________________________________ + +@checkout-shipping-address__max-width: 500px; + +@checkout-shipping-item-icon__background-color: @checkout-shipping-item__active__border-color; +@checkout-shipping-item-icon__color: @color-white; +@checkout-shipping-item-icon__content: @icon-checkmark; + +@checkout-shipping-item__border: 2px solid transparent; +@checkout-shipping-item__line-height: 30px; +@checkout-shipping-item__margin: 0 0 @indent__base; +@checkout-shipping-item__padding: @indent__base (@indent__l + 5px) @indent__base @indent__base; +@checkout-shipping-item__transition: .3s border-color; +@checkout-shipping-item__width: 100%/3; +@checkout-shipping-item-tablet__width: 100%/2; +@checkout-shipping-item-mobile__width: 100%; +@checkout-shipping-item__active__border-color: @color-orange-red1; + +@checkout-shipping-item-icon__selected__height: 27px; +@checkout-shipping-item-icon__selected__width: 29px; + +@checkout-shipping-item-mobile__padding: 0 0 15px; +@checkout-shipping-item-mobile__margin: @checkout-shipping-item-mobile__padding; +@checkout-shipping-item-mobile__active__padding: 15px (@indent__l + 5px) 15px 18px; + +@checkout-shipping-item-before__border-color: @color-gray80; +@checkout-shipping-item-before__height: calc(~"100% - 20px"); + +@checkout-shipping-method__border: @checkout-step-title__border; +@checkout-shipping-method__padding: @indent__base; + +// +// Common +// _____________________________________________ + +& when (@media-common = true) { + + .opc-wrapper { + + // + // Shipping Address + // --------------------------------------------- + + .form-login, + .form-shipping-address { + .css(margin-bottom, @checkout-step-title__margin-bottom); + .fieldset { + .field { + .label { + font-weight: @font-weight__regular; + } + } + .note { + font-size: @font-size__base; + margin-top: @indent__s; + } + } + } + + .shipping-address-items { + font-size: 0; + } + + .shipping-address-item { + &:extend(.abs-add-box-sizing all); + .css(border, @checkout-shipping-item__border); + .css(font-size, @font-size__base); + .css(line-height, @checkout-shipping-item__line-height); + .css(margin, @checkout-shipping-item__margin); + .css(padding, @checkout-shipping-item__padding); + .css(transition, @checkout-shipping-item__transition); + .css(width, @checkout-shipping-item-tablet__width); + display: inline-block; + position: relative; + vertical-align: top; + word-wrap: break-word; + + &.selected-item { + .css(border-color, @checkout-shipping-item__active__border-color); + + &:after { + .css(background, @checkout-shipping-item-icon__background-color); + .css(color, @checkout-shipping-item-icon__color); + .css(content, @checkout-shipping-item-icon__content); + .css(font-family, @icons__font-name); + .css(height, @checkout-shipping-item-icon__selected__height); + .css(width, @checkout-shipping-item-icon__selected__width); + font-size: 19px; + line-height: 21px; + padding-top: 2px; + position: absolute; + right: 0; + text-align: center; + top: 0; + } + + .action-select-shipping-item { + &:extend(.abs-no-display-s all); + visibility: hidden; + } + } + } + + .field { + &.addresses { + &:extend(.abs-add-clearfix all); + } + } + + .action-show-popup { + margin: 0 0 @indent__base; + > span { + &:before { + content: '+'; + padding-right: @indent__xs; + } + } + } + + .action-select-shipping-item { + float: right; + margin: @indent__base 0 0; + } + + .edit-address-link { + &:extend(.abs-action-button-as-link all); + display: block; + float: left; + margin: 26px 5px 0 0; + } + } + + // + // Shipping Methods + // --------------------------------------------- + + .checkout-shipping-method { + .step-title { + margin-bottom: 0; + } + .no-quotes-block { + margin: @indent__base 0; + } + } + + .methods-shipping { + .actions-toolbar { + .action { + &.primary { + &:extend(.abs-button-l all); + margin: @indent__base 0 0; + } + } + } + } + + .table-checkout-shipping-method { + thead { + th { + display: none; + } + } + tbody { + td { + .css(border-top, @checkout-shipping-method__border); + .css(padding-bottom, @checkout-shipping-method__padding); + .css(padding-top, @checkout-shipping-method__padding); + &:first-child { + padding-left: 0; + padding-right: 0; + width: 20px; + } + } + tr { + &:first-child { + td { + border-top: none; + } + } + } + .col-price { + font-weight: @font-weight__semibold; + } + .row-error { + td { + border-top: none; + padding-bottom: @indent__s; + padding-top: 0; + } + } + } + } +} + +// +// Mobile +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .opc-wrapper { + .form-login, + .form-shipping-address, + .methods-shipping { + .css(background, @checkout-step-content-mobile__background); + .css(margin, @checkout-step-content-mobile__margin); + .css(padding, @indent__base @checkout-step-content-mobile__margin-s); + } + + .form-login { + + .form-shipping-address { + .css(margin-top, -(@checkout-step-content-mobile__margin-s)); + } + } + + .shipping-address-item { + .css(border-bottom, 1px solid @checkout-shipping-item-before__border-color); + .css(margin, @checkout-shipping-item-mobile__margin); + .css(padding, @checkout-shipping-item-mobile__padding); + .css(width, @checkout-shipping-item-mobile__width); + &.selected-item { + .css(padding, @checkout-shipping-item-mobile__active__padding); + border-bottom-width: 2px; + + .edit-address-link { + .css(right, @checkout-shipping-item-icon__selected__width + @indent__s); + } + } + } + + .action-select-shipping-item { + float: none; + margin-top: @indent__s; + width: 100%; + } + + .action-show-popup { + width: 100%; + } + + .methods-shipping { + .css(border-bottom, @checkout-step-title__border); + padding-top: @indent__l; + } + + .edit-address-link { + .icon-font( + @icon-edit, + @_icon-font-size: 18px, + @_icon-font-line-height: 20px, + @_icon-font-text-hide: true, + @_icon-font-color: @minicart-icons-color, + @_icon-font-color-hover: @primary__color, + @_icon-font-color-active: @minicart-icons-color + ); + margin: 0; + position: absolute; + right: 0; + top: 5px; + } + } +} + +// +// Desktop +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .checkout-shipping-method { + .actions-toolbar { + > .primary { + float: right; + } + .action { + &.primary { + margin: 0; + } + } + } + } + .opc-wrapper { + .form-login, + .form-shipping-address { + .css(max-width, @checkout-shipping-address__max-width); + } + + .form-login { + .css(border-bottom, @checkout-step-title__border); + .css(padding-bottom, @checkout-step-title__margin-bottom); + } + } + .table-checkout-shipping-method { + width: auto; + } +} + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__l) { + .opc-wrapper { + .shipping-address-item { + .css(width, @checkout-shipping-item__width); + + &:before { + .css(background, @checkout-shipping-item-before__border-color); + .css(height, @checkout-shipping-item-before__height); + content: ''; + left: 0; + position: absolute; + top: 0; + width: 1px; + } + + &:nth-child(3n+1) { + &:before { + display: none; + } + } + + &.selected-item { + &:before { + display: none; + } + + + .shipping-address-item { + &:before { + display: none; + } + } + } + } + } + .table-checkout-shipping-method { + min-width: 500px; + } +} diff --git a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less index 0d3b4cd47ec03767fba0a2a1291fccd7235b6d4e..d10ebc66f56eaf506ac65e19b8f07dbb1ade7c37 100644 --- a/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less +++ b/app/design/frontend/Magento/luma/Magento_GiftMessage/web/css/source/_module.less @@ -274,13 +274,19 @@ } .gift-content { border-top: @border-width__base solid @color-gray-light5; - margin-left: -@mobile-cart-padding; margin-right: -@mobile-cart-padding; padding-left: @mobile-cart-padding; padding-right: @mobile-cart-padding; overflow: hidden; } } + + .gift-options-cart-item { + & + .action-towishlist { + left: 43px; + position: absolute; + } + } } // diff --git a/app/design/frontend/Magento/luma/web/css/source/_extends.less b/app/design/frontend/Magento/luma/web/css/source/_extends.less index cc4ab06b849cb5eec4233e701e915deedb4285ed..04018f6977c016c96c9444e206a8eb64ba787fff 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_extends.less +++ b/app/design/frontend/Magento/luma/web/css/source/_extends.less @@ -4,8 +4,9 @@ // */ // -// List default styles reset -//-------------------------------------- +// List default styles reset +// --------------------------------------------- + .abs-reset-list { .list-reset-styles(); > li { @@ -14,16 +15,18 @@ } // -// Primary button -//-------------------------------------- +// Primary button +// --------------------------------------------- + .action-primary { .button-primary(); .css(border-radius, @button__border-radius); } // -// Secondary button -//-------------------------------------- +// Secondary button +// --------------------------------------------- + .abs-revert-to-action-secondary { &:extend(.abs-revert-secondary-color all); .css(border-radius, @button__border-radius); @@ -36,8 +39,9 @@ } // -// Link as a button -//-------------------------------------- +// Link as a button +// --------------------------------------------- + .abs-action-link-button { .button(); .link-as-button(); @@ -46,7 +50,8 @@ // // Button as a link -//-------------------------------------- +// --------------------------------------------- + .abs-action-button-as-link { .button-as-link( @_margin: false @@ -61,28 +66,32 @@ // // Button revert secondary color -//-------------------------------------- +// --------------------------------------------- + .abs-revert-secondary-color { .button-revert-secondary-color(); } // // Button revert secondary size -//-------------------------------------- +// --------------------------------------------- + .abs-revert-secondary-size { .button-revert-secondary-size(); } // // Large button -//-------------------------------------- +// --------------------------------------------- + .abs-button-l { .button-l(); } // -// Product options list -//-------------------------------------- +// Product options list +// --------------------------------------------- + @abs-product-options-list: { dt { float: left; @@ -104,8 +113,9 @@ } // -// Desktop -//-------------------------------------- +// Desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-product-options-list-desktop { @abs-product-options-list(); @@ -113,8 +123,9 @@ } // -// Button reset width, floats, margins -//-------------------------------------- +// Button reset width, floats, margins +// --------------------------------------------- + .abs-button-responsive { .button-responsive(); } @@ -126,8 +137,9 @@ } // -// Blocks in 2 columns -//-------------------------------------- +// Blocks in 2 columns +// --------------------------------------------- + @abs-blocks-2columns: { width: 48%; &:nth-child(1) { @@ -155,8 +167,9 @@ } // -// Reset image alignment in container -//-------------------------------------- +// Reset image alignment in container +// --------------------------------------------- + .abs-reset-image-wrapper { height: auto; padding: 0!important; @@ -166,8 +179,9 @@ } // -// Adaptive images -//-------------------------------------- +// Adaptive images +// --------------------------------------------- + .abs-adaptive-images { display: block; height: auto; @@ -182,8 +196,9 @@ } // -// Title for login blocks -//-------------------------------------- +// Title for login blocks +// --------------------------------------------- + .abs-login-block-title { strong { font-weight: 500; @@ -195,8 +210,9 @@ } // -// Simple Dropdown -//-------------------------------------- +// Simple Dropdown +// --------------------------------------------- + .abs-dropdown-simple { .dropdown( @_dropdown-list-item-padding: 5px 5px 5px 23px, @@ -210,16 +226,18 @@ } // -// Input quantity -//-------------------------------------- +// Input quantity +// --------------------------------------------- + .abs-input-qty { width: 54px; text-align: center; } // -// Marging for blocks & widgets -//-------------------------------------- +// Marging for blocks & widgets +// --------------------------------------------- + .abs-margin-for-blocks-and-widgets { margin-bottom: @indent__xl; } @@ -231,8 +249,9 @@ } // -// Remove button for blocks -//-------------------------------------- +// Remove button for blocks +// --------------------------------------------- + .abs-remove-button-for-blocks { .icon-font( @icon-remove, @@ -246,8 +265,9 @@ } // -// Product link -//-------------------------------------- +// Product link +// --------------------------------------------- + .abs-product-link { font-weight: @font-weight__regular; > a { @@ -265,8 +285,9 @@ } // -// Link -//-------------------------------------- +// Link +// --------------------------------------------- + .abs-like-link { .link(); cursor: pointer; @@ -274,7 +295,8 @@ // // Reset left margin -//-------------------------------------- +// --------------------------------------------- + @abs-reset-left-margin: { margin-left: 0; }; @@ -296,8 +318,9 @@ } // -// Action with icon remove with text -//-------------------------------------- +// Action with icon remove with text +// --------------------------------------------- + .abs-action-remove { &:extend(.abs-action-button-as-link all); width: auto; @@ -308,8 +331,9 @@ } // -// Action with icon remove with text for desktop -//-------------------------------------- +// Action with icon remove with text for desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-action-remove-desktop { margin-left: 90%; @@ -317,8 +341,9 @@ } // -// Add Recipient -//-------------------------------------- +// Add Recipient +// --------------------------------------------- + .abs-add-fields { .fieldset { .field { @@ -360,8 +385,9 @@ } // -// Add Recipient for desktop -//-------------------------------------- +// Add Recipient for desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-add-fields-desktop { .fieldset { @@ -382,8 +408,9 @@ } // -// Margin for forms -//-------------------------------------- +// Margin for forms +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-margin-for-forms-desktop { .css(margin-left, @form-field-type-label-inline__width); @@ -391,8 +418,9 @@ } // -// Visibility hidden / show visibility hidden -//-------------------------------------- +// Visibility hidden / show visibility hidden +// --------------------------------------------- + @abs-hidden: { .visibility-hidden(); }; @@ -402,8 +430,9 @@ } // -// Visually hidden / show visually hidden -//-------------------------------------- +// Visually hidden / show visually hidden +// --------------------------------------------- + @abs-visually-hidden: { .visually-hidden(); }; @@ -437,8 +466,9 @@ } // -// Clearfix -//-------------------------------------- +// Clearfix +// --------------------------------------------- + @abs-add-clearfix: { .clearfix(); }; @@ -472,8 +502,9 @@ } // -// Box-sizing -//-------------------------------------- +// Box-sizing +// --------------------------------------------- + @abs-add-box-sizing: { box-sizing: border-box; }; @@ -494,9 +525,16 @@ } } +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + .abs-add-box-sizing-desktop-m { + @abs-add-box-sizing(); + } +} + // -// Revert field type -//-------------------------------------- +// Revert field type +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-revert-field-type-desktop { .fieldset { @@ -512,8 +550,9 @@ } // -// Settings icons -//-------------------------------------- +// Settings icons +// --------------------------------------------- + .abs-navigation-icon { .icon-font( @_icon-font-content: @icon-down, @@ -530,8 +569,9 @@ } // -// Split button -//-------------------------------------- +// Split button +// --------------------------------------------- + .abs-split-button { .dropdown-split( @_options-selector : ~".items", @@ -541,8 +581,9 @@ } // -// Field 2 column -//-------------------------------------- +// Field 2 column +// --------------------------------------------- + @abs-form-field-column-2: { .fieldset { .field { @@ -572,8 +613,9 @@ } // -// Field 1 column -//-------------------------------------- +// Field 1 column +// --------------------------------------------- + @abs-form-field-revert-column-1: { .form-field-column-number(@_column-number: 1); }; @@ -591,8 +633,9 @@ } // -// Checkout shipping methods title -//-------------------------------------- +// Checkout shipping methods title +// --------------------------------------------- + .abs-methods-shipping-title { .font-size(16); margin-bottom: 15px; @@ -600,8 +643,9 @@ } // -// Checkout order review -//-------------------------------------- +// Checkout order review +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-checkout-order-review { tbody > tr { @@ -642,8 +686,9 @@ } // -// Add to Actions -//-------------------------------------- +// Add to Actions +// --------------------------------------------- + .abs-actions-addto { .css(color, @addto-color); display: inline-block; @@ -664,15 +709,17 @@ } // -// Box-tocart block -//-------------------------------------- +// Box-tocart block +// --------------------------------------------- + .abs-box-tocart { margin: 0 0 @indent__l; } // -// General pages forms -//-------------------------------------- +// General pages forms +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-forms-general-desktop { max-width: 500px; @@ -686,8 +733,9 @@ } // -// Revert side paddings -//-------------------------------------- +// Revert side paddings +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-revert-side-paddings { padding-left: 0; @@ -696,8 +744,9 @@ } // -// Abstract toggle title block -//-------------------------------------- +// Abstract toggle title block +// --------------------------------------------- + @abs-toggling-title: { .css(border-top, @border-width__base solid @border-color__base); cursor: pointer; @@ -747,8 +796,9 @@ } // -// Cart discount block -//-------------------------------------- +// Cart discount block +// --------------------------------------------- + .abs-cart-block { margin: 0; > .title { @@ -780,8 +830,9 @@ } // -// Checkout order review price -//-------------------------------------- +// Checkout order review price +// --------------------------------------------- + .abs-checkout-cart-price { .css(color, @primary__color__lighter); .font-size(16); @@ -789,8 +840,9 @@ } // -// Checkout order product name -//-------------------------------------- +// Checkout order product name +// --------------------------------------------- + .abs-checkout-product-name { .font-size(18); font-weight: @font-weight__light; @@ -798,8 +850,9 @@ } // -// Mobile checkout order product name -//-------------------------------------- +// Mobile checkout order product name +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-product-items-summary { tbody { @@ -838,8 +891,9 @@ } // -// Account pages: title -//-------------------------------------- +// Account pages: title +// --------------------------------------------- + .abs-account-title { > strong, > span { @@ -852,8 +906,9 @@ } // -// Account pages: block font size -//-------------------------------------- +// Account pages: block font size +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-account-block-font-size { .font-size(16); @@ -861,15 +916,17 @@ } // -// Account pages: block line-height -//-------------------------------------- +// Account pages: block line-height +// --------------------------------------------- + .abs-account-block-line-height { line-height: 24px; } // -// Account pages: margin for table -//-------------------------------------- +// Account pages: margin for table +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-account-table-margin-mobile { .css(margin-top, -@indent__base); @@ -882,8 +939,9 @@ } // -// Account pages: table col actions -//-------------------------------------- +// Account pages: table col actions +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-col-no-prefix { &:before { @@ -893,8 +951,9 @@ } // -// Account pages: order table summary -//-------------------------------------- +// Account pages: order table summary +// --------------------------------------------- + .abs-account-summary { td { .css(background, @sidebar__background-color); @@ -902,8 +961,9 @@ } // -// Action print with icon -//-------------------------------------- +// Action print with icon +// --------------------------------------------- + @abs-action-print: { .icon-font( @icon-print, @@ -930,8 +990,9 @@ } // -// Excl/Incl tax -//-------------------------------------- +// Excl/Incl tax +// --------------------------------------------- + .abs-incl-excl-tax { .price-including-tax, .price-excluding-tax { @@ -965,8 +1026,9 @@ } // -// Cart tax total -//-------------------------------------- +// Cart tax total +// --------------------------------------------- + .abs-tax-total { cursor: pointer; position: relative; @@ -993,15 +1055,17 @@ } // -// Forms: margin-bottom for small forms -//-------------------------------------- +// Forms: margin-bottom for small forms +// --------------------------------------------- + .abs-forms-margin-small { .css(margin-bottom, @indent__base); } // -// Forms: margin-bottom for small forms -//-------------------------------------- +// Forms: margin-bottom for small forms +// --------------------------------------------- + .abs-rating-summary { .rating { &-summary { @@ -1022,8 +1086,9 @@ } // -// Account pages: actions -//-------------------------------------- +// Account pages: actions +// --------------------------------------------- + .abs-account-actions { &:after { content: ""; @@ -1041,8 +1106,9 @@ } // -// Account blocks -//-------------------------------------- +// Account blocks +// --------------------------------------------- + .abs-account-blocks { .block-title { &:extend(.abs-account-title all); @@ -1064,8 +1130,9 @@ } // -// Add colon -//-------------------------------------- +// Add colon +// --------------------------------------------- + .abs-colon { &:after { content: ": "; @@ -1073,8 +1140,9 @@ } // -// Icon - create add -//-------------------------------------- +// Icon - create add +// --------------------------------------------- + .abs-icon-add { .icon-font( @_icon-font-content: @icon-expand, @@ -1098,8 +1166,9 @@ } // -// Dropdown items - create new -//-------------------------------------- +// Dropdown items - create new +// --------------------------------------------- + .abs-dropdown-items-new { .items .item:last-child { &:hover { @@ -1116,8 +1185,9 @@ } // -// Abstract no display -//-------------------------------------- +// Abstract no display +// --------------------------------------------- + @abs-no-display: { display: none; }; @@ -1139,8 +1209,9 @@ } // -// Status -//-------------------------------------- +// Status +// --------------------------------------------- + .abs-status { .css(border, 2px solid @border-color__base); border-radius: 3px; @@ -1159,8 +1230,9 @@ } // -// Page title - orders pages -//-------------------------------------- +// Page title - orders pages +// --------------------------------------------- + .abs-title-orders { .page-main { .page-title-wrapper { @@ -1208,8 +1280,9 @@ } // -// Table striped -//-------------------------------------- +// Table striped +// --------------------------------------------- + .abs-table-striped { .table-striped( @_stripped-highlight: even @@ -1228,8 +1301,9 @@ } // -// Table bordered desktop -//-------------------------------------- +// Table bordered desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-table-bordered-desktop { .table-bordered( @@ -1240,8 +1314,9 @@ } // -// Pager toolbar for non-catalog pages desktop -//-------------------------------------- +// Pager toolbar for non-catalog pages desktop +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { .abs-pager-toolbar { position: relative; @@ -1263,8 +1338,9 @@ } // -// Items counter in blocks -//-------------------------------------- +// Items counter in blocks +// --------------------------------------------- + .abs-block-items-counter { .css(color, @primary__color__lighter); .font-size(12px); @@ -1272,8 +1348,9 @@ } // -// Sidebar and widget blocks title -//-------------------------------------- +// Sidebar and widget blocks title +// --------------------------------------------- + .abs-block-widget-title { strong { font-size: @font-size__l; @@ -1283,8 +1360,9 @@ } // -// Shopping cart items -//-------------------------------------- +// Shopping cart items +// --------------------------------------------- + .abs-shopping-cart-items { margin-bottom: @indent__base; .actions.main { @@ -1305,8 +1383,9 @@ } // -// Remove top border -//-------------------------------------- +// Remove top border +// --------------------------------------------- + .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-no-border-top { border-top: 0; @@ -1314,7 +1393,7 @@ } // -// Remove bottom border +// Remove bottom border //-------------------------------------- .media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { .abs-no-border-bottom { @@ -1323,8 +1402,9 @@ } // -// Form Field Date -//-------------------------------------- +// Form Field Date +// --------------------------------------------- + .abs-field-date { .control { position: relative; @@ -1336,9 +1416,207 @@ } // -// Form Field Date Input -//-------------------------------------- +// Form Field Date Input +// --------------------------------------------- + .abs-field-date-input { - margin-right: @indent__s; + .css(margin-right, @indent__s); width: calc(~"100% - (@{icon-calendar__font-size} + @{indent__s})"); } + +// +// Form Field Tooltip +// --------------------------------------------- + +.abs-field-tooltip { + &:extend(.abs-add-box-sizing all); + position: relative; + input { + .css(margin-right, @indent__s); + width: calc(~"100% - (@{checkout-tooltip-icon__font-size} + @{indent__s} + @{indent__xs})"); + &:focus { + + .field-tooltip { + .field-tooltip-action { + &:before { + .css(color, @checkout-tooltip-icon__hover__color); + } + } + .field-tooltip-content { + display: block; + } + } + } + } +} + +// +// Checkout Tooltip Content (position: top) +// --------------------------------------------- + +@abs-checkout-tooltip-content-position-top: { + .css(right, @checkout-tooltip-content-mobile__right); + .css(top, @checkout-tooltip-content-mobile__top); + left: auto; + + &:before, + &:after { + .arrow( + @_position: top, + @_size: @checkout-tooltip-icon-arrow__font-size, + @_color: @checkout-tooltip-content__background-color + ); + .css(margin-top, @checkout-tooltip-icon-arrow__left); + .css(right, @indent__s); + left: auto; + top: 0%; + } + &:before { + .css(border-bottom-color, @checkout-tooltip-content__active__border-color); + } + &:after { + .css(border-bottom-color, @checkout-tooltip-content__background-color); + top: 1px; + } +}; + +.abs-checkout-tooltip-content-position-top { + @abs-checkout-tooltip-content-position-top(); +} + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = (@screen__m + 1)) { + .abs-checkout-tooltip-content-position-top-mobile { + @abs-checkout-tooltip-content-position-top(); + } +} + +// +// Checkout title +// --------------------------------------------- + +.abs-checkout-title { + .css(padding-bottom, @checkout-step-title__padding); + .typography( + @_font-size: @checkout-step-title__font-size, + @_font-weight: @checkout-step-title__font-weight, + @_font-family: false, + @_font-style: false, + @_line-height: false + ); +} + +// +// Shopping cart sidebar and checkout sidebar totals +// --------------------------------------------- + +.abs-sidebar-totals { + border-top: 1px solid @border-color__base; + padding-top: 10px; + tbody, + tfoot { + .mark { + border: 0; + font-weight: @font-weight__regular; + padding: 6px 0; + } + .amount { + border: 0; + font-weight: @font-weight__regular; + padding: 6px 0 6px 14px; + text-align: right; + } + } + .table-caption { + &:extend(.abs-no-display all); + } + .grand { + th, + td { + padding: 11px 0; + } + strong { + display: inline-block; + font-weight: @font-weight__semibold; + padding: 3px 0 0; + } + .mark { + border-top: 1px solid @border-color__base; + .font-size(18); + padding-right: @indent__s; + } + .amount { + border-top: 1px solid @border-color__base; + .font-size(18); + } + } + .msrp { + margin-bottom: @indent__s; + } + tbody tr:last-child td { + padding-bottom: 19px; + } + .totals-tax { + &-summary { + .mark, + .amount { + border-top: @border-width__base solid @border-color__base; + border-bottom: @border-width__base solid @border-color__base; + cursor: pointer; + } + .amount .price { + position: relative; + padding-right: @indent__base; + .icon-font( + @icon-down, + @_icon-font-size: 12px, + @_icon-font-line-height: 12px, + @_icon-font-text-hide: true, + @_icon-font-position: after + ); + &:after { + position: absolute; + right: 3px; + top: 3px; + } + } + &.expanded { + .mark, + .amount { + border-bottom: 0; + } + .amount .price { + .icon-font-symbol( + @_icon-font-content: @icon-up, + @_icon-font-position: after + ); + } + } + } + &-details { + display: none; + border-bottom: @border-width__base solid @border-color__base; + &.shown { + display: table-row; + } + } + } + .table-wrapper { + margin-bottom: 0; + } +} + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__s) { + .abs-sidebar-totals-mobile { + th { + &:extend(.abs-col-no-prefix all); + } + td { + &:extend(.abs-col-no-prefix all); + } + tbody tr:not(:last-child) td { + &:extend(.abs-no-border-bottom-top all); + } + .amount { + text-align: right; + } + } +} diff --git a/app/design/frontend/Magento/luma/web/css/source/_theme.less b/app/design/frontend/Magento/luma/web/css/source/_theme.less index f293d18d117a1911f079065f25280984a9fd54a7..52914c1bd64117c7cba4af7e2086731a7ae19870 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_theme.less +++ b/app/design/frontend/Magento/luma/web/css/source/_theme.less @@ -248,3 +248,23 @@ @overlay__opacity-old: 70; @gallery-thumb-border-color-active: @active__color; + +// Modal popup +@modal-action-close__font-size: @font-size__base; + +// Checkout tooltip icon +@checkout-tooltip-icon__font-size: 21px; + +// Checkout Payment Option icon +@checkout-payment-option-title-icon__font-size: 14px; +@checkout-payment-option-title-icon__line-height: 16px; +@checkout-payment-option-title-icon__margin: 0 0 0 @indent__s; + +// Checkout Sidebar Shipping Information +@checkout-sidebar-shipping-information-edit-icon__content: @icon-edit; +@checkout-sidebar-shipping-information-edit-icon__font-size: 18px; +@checkout-sidebar-shipping-information-edit-icon__line-height: 20px; +@checkout-sidebar-shipping-information-edit-icon__top: @indent__s; + +// Checkout +@checkout-sidebar__columns: 8; diff --git a/app/design/frontend/Magento/luma/web/css/source/_variables.less b/app/design/frontend/Magento/luma/web/css/source/_variables.less index dbdbeb65ad660dccec8e724925392cf18b254c96..ee76525dd8cc68c2906c4bfa5aecdbaede9c7f32 100644 --- a/app/design/frontend/Magento/luma/web/css/source/_variables.less +++ b/app/design/frontend/Magento/luma/web/css/source/_variables.less @@ -26,7 +26,6 @@ @icon-success: '\e60e'; @icon-error: '\e61f'; @icon-edit: '\e601'; -@icon-help: '\e623'; @icon-print: '\e624'; @icon-star-empty: '\e625'; @icon-download: '\e626'; diff --git a/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg b/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg index 5e68e79f8e3e44488f98f45b6a4d1408f485d2ec..fa092836d03823258384bc553188cc92e412a02f 100644 --- a/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg +++ b/app/design/frontend/Magento/luma/web/fonts/Luma-Icons.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg"><defs><font id="Luma-Icons" horiz-adv-x="512"><font-face units-per-em="512" ascent="480" descent="-32"/><missing-glyph horiz-adv-x="512"/><glyph unicode=" " d="" horiz-adv-x="256"/><glyph unicode="" d="M436.608 435.568c-65.68 31.424-144.064 2.832-174.976-63.84-2.16-4.64-4.016-10.448-5.664-17.2-1.648 6.752-3.504 12.56-5.632 17.2-30.944 66.672-109.248 95.264-174.944 63.84-65.6-31.424-93.744-110.96-62.832-177.648 30.928-66.672 243.344-257.84 243.344-257.84s0.016 0.224 0.048 0.576c0.048-0.352 0.064-0.576 0.064-0.576s212.512 191.168 243.44 257.84c30.896 66.688 2.832 146.224-62.848 177.648z"/><glyph unicode="" d="M362.533 425.051c-49.81-49.792-20.809-20.772-20.809-20.772l96.402-96.384c0 0-31.067-31.049 20.772 20.773s-46.611 146.194-96.365 96.384zM320.147 383.671l-227.987-227.986 0.329-0.293-54.071-146.524 149.833 50.688 0.311-0.311 0.786 0.805v0.019l227.2 227.2-96.403 96.403zM179.036 104.375l-78.811-33.28 37.047 75.044 38.345 38.363 41.764-41.783-38.345-38.345z"/><glyph unicode="" d="M255.952 480l-255.952-448h512l-256.048 448zM287.12 353.808v-65.36l-16.688-128.544h-27.088l-18.032 128.544-0.992 65.36h62.8zM224.096 64.112v64.112h64.24v-64.112h-64.24z"/><glyph unicode="" d="M363.923 112.019c-29.805-28.764-68.663-43.502-108.013-43.538-35.145 0.036-70.199 11.757-99.347 35.932-37.029 30.829-56.046 74.971-56.1 119.661 0 7.442 0.549 14.829 1.591 22.18l-60.672-11.374c-0.164-3.602-0.292-7.186-0.292-10.807-0.036-61.495 26.459-122.899 77.549-165.285 40.009-33.335 88.887-49.683 137.252-49.683h0.128c56.211 0 112.164 22.217 153.746 64.914l39.844-39.772 0.311 124.745-131.803 0.348 45.805-47.324zM393.344 389.23c-40.046 33.335-88.923 49.664-137.271 49.664-55.808 0-111.397-21.833-152.923-63.945l-37.687 34.798-0.677-120.722 130.487-0.75-46.336 48.493c29.641 28.252 68.188 42.697 107.154 42.733 35.108-0.036 70.217-11.721 99.328-35.932 37.029-30.829 56.046-74.935 56.137-119.698 0-6.437-0.457-12.892-1.225-19.365l60.435 11.593c0.036 2.615 0.164 5.212 0.164 7.772-0.036 61.549-26.514 122.899-77.587 165.357z"/><glyph unicode="" d="M95.792-32h320.4v320.080h-320.4v-320.080zM318.336 228.512c0 9.904 8.032 17.904 17.952 17.904 9.904 0 17.936-8 17.936-17.904v-188.736c0-9.888-8.032-17.92-17.936-17.92-9.92 0-17.952 8.032-17.952 17.92v188.736zM238.048 228.512c0 9.904 8.032 17.904 17.92 17.904s17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92s-17.92 8.032-17.92 17.92v188.736zM157.6 228.512c0 9.904 8 17.904 17.92 17.904 9.888 0 17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92-9.92 0-17.92 8.032-17.92 17.92v188.736zM423.216 416.528h-71.232v10.896c0 29.040-19.76 52.576-48.8 52.576h-94.72c-29.008 0-48.48-23.536-48.48-52.576v-10.896h-71.232c-13.696 0-24.768-11.088-24.768-24.752v-71.984h384v71.984c0 13.664-11.040 24.752-24.768 24.752zM319.936 416.528h-128.192v14.704c0.032 9.248 7.488 16.736 16.72 16.768h94.72c9.216-0.032 16.704-7.52 16.752-16.768v-14.704z"/><glyph unicode="" d="M511.52 278.496c-1.312 4.096-5.152 6.88-9.44 6.88h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 6.992 3.6 11.088z"/><glyph unicode="" d="M473.015 200.375v49.371l-7.003 2.268-52.882 17.244-14.116 34.103 27.154 57.381-34.908 34.907-6.583-3.309-49.555-25.198-34.103 14.117-21.394 59.757h-49.371l-2.286-6.985-17.262-52.882-34.048-14.099-57.399 27.136-34.925-34.926 3.309-6.564 25.18-49.591-14.080-34.029-59.758-21.412v-49.39l6.949-2.249 52.901-17.28 14.099-34.067-27.118-57.38 34.925-34.925 6.528 3.328 49.591 25.197 34.066-14.116 21.394-59.757h49.371l2.286 6.985 17.28 52.882 34.029 14.116 57.399-27.136 34.944 34.908-3.346 6.546-25.197 49.572 14.116 34.067 59.813 21.413zM256 154.861c-38.199 0-69.156 30.957-69.156 69.139 0 38.217 30.958 69.156 69.156 69.156 38.163 0 69.156-30.94 69.156-69.156 0-38.18-31.012-69.139-69.156-69.139z"/><glyph unicode="" d="M31.008 351.36l224.992-239.984 225.040 239.984z"/><glyph unicode="" d="M383.415 226.596l-212.571 218.587-37.285-34.981 178.286-183.277-183.278-188.452 36.48-35.657 205.659 211.456-0.201 0.201z"/><glyph unicode="" d="M52.928 345.2h406.144c11.056 0 20 8.976 20 20.016 0 11.072-8.944 20.032-20 20.032h-406.144c-11.056 0-20.016-8.96-20.016-20.032 0-11.040 8.96-20.016 20.016-20.016zM459.072 244.016h-406.144c-11.056 0-20.016-8.944-20.016-20.016s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.016-20 20.016zM459.072 102.8h-406.144c-11.056 0-20.016-8.96-20.016-20.032s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.032-20 20.032z"/><glyph unicode="" d="M256.144 480c-89.12 0-161.344-72.24-161.344-161.376 0-89.104 161.344-350.624 161.344-350.624s161.376 261.52 161.376 350.624c0 89.136-72.192 161.376-161.376 161.376zM256.144 269.616c-27.056 0-49.024 21.952-49.024 49.008 0 27.072 21.984 49.024 49.024 49.024 27.104 0 49.088-21.952 49.088-49.024 0-27.056-21.984-49.008-49.088-49.008z"/><glyph unicode="" d="M0 256.144h224.032v223.808h-224.032v-223.808zM288.128 479.952v-95.728h224.176v95.728h-224.176zM0-32h224.032v223.808h-224.032v-223.808zM288.128 256.144h224.176v95.728h-224.176v-95.728zM288.128 96.080h224.176v95.728h-224.176v-95.728zM288.128-32h224.176v95.712h-224.176v-95.712z"/><glyph unicode="" d="M332.764 119.003c-9.216 0-45.495-56.027-65.243-56.027-5.284 0-7.863 4.644-7.863 9.216 0 10.569 7.241 27.044 11.154 36.937l47.397 128.384c23.772 63.891-6.546 81.024-34.871 81.024-38.217 0-72.448-19.091-98.779-44.124-8.576-8.576-37.523-36.206-37.523-48.091 0-3.932 3.931-8.576 8.576-8.576 11.813 0 43.447 57.308 67.803 57.308 5.285 0 11.191-5.924 6.583-17.755l-46.080-115.968c-4.644-11.154-27.044-65.171-27.044-96.786 0-25.015 16.476-36.188 40.192-36.188 66.523 0 143.543 81.645 143.543 100.755-0.019 5.925-4.589 9.892-7.844 9.892zM319.543 439.661c-28.947 0-54.016-23.68-54.016-52.663 0-27.008 17.792-44.8 44.837-44.8 29.55 0 54.62 22.4 54.62 52.7 0 27.008-19.072 44.764-45.44 44.764z"/><glyph unicode="" d="M0 351.552h128.464v128.448h-128.464v-128.448zM191.76 351.552h128.528v128.448h-128.528v-128.448zM383.568 480v-128.448h128.496v128.448h-128.496zM0 159.744h128.464v128.464h-128.464v-128.464zM191.76 159.744h128.528v128.464h-128.528v-128.464zM383.568 159.744h128.496v128.464h-128.496v-128.464zM0-32h128.464v128h-128.464v-128zM191.76-32h128.528v128h-128.528v-128zM383.568-32h128.496v128h-128.496v-128z"/><glyph unicode="" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM231.936 94.576l-125.936 128.032 32.208 25.936 72.864-57.088c29.76 35.424 96 106.032 187.312 161.984l7.696-17.792c-83.808-77.088-152.48-185.6-174.144-241.072z"/><glyph unicode="" d="M0 241.12h512v-34.064h-512v34.064z"/><glyph unicode="" d="M478.263 426.149c-142.555-87.388-245.98-197.632-292.48-252.947l-113.792 89.161-50.267-40.539 196.663-199.973c33.847 86.674 141.056 256.11 271.872 376.485l-11.995 27.813z"/><glyph unicode="" d="M220.576 83.248c-26.352 0-47.696-21.376-47.696-47.712s21.344-47.664 47.696-47.664c26.336 0 47.696 21.328 47.696 47.664s-21.36 47.712-47.696 47.712zM385.344 83.248c-26.4 0-47.76-21.376-47.76-47.712s21.344-47.664 47.76-47.664c26.288 0 47.632 21.328 47.632 47.664s-21.344 47.712-47.632 47.712zM459.856 350.32c-122.384 0-319.856 0-319.856 0s-19.152 52.608-37.392 84.864c-14.128 24.976-43.344 23.968-43.344 23.968-20.096 0-33.024-12.288-33.024-32.4 0-20.096 15.92-36.16 36.032-36.16l8.496-0.080 95.2-262.192 266.832-0.208c0 0 48.784 199.632 46.272 191.888 8.944 27.68-2.448 30.32-19.216 30.32zM166.528 257.344c-14 0-25.36 11.36-25.36 25.376s11.36 25.392 25.36 25.392c14.016 0 25.36-11.376 25.36-25.392s-11.344-25.376-25.36-25.376zM220.768 172.64c-14.016 0-25.376 11.376-25.376 25.392 0 13.984 11.36 25.36 25.376 25.36 14 0 25.36-11.376 25.36-25.36 0.016-14.016-11.36-25.392-25.36-25.392zM248.656 257.344c-14 0-25.376 11.36-25.376 25.376s11.36 25.392 25.376 25.392c14 0 25.36-11.376 25.36-25.392s-11.36-25.376-25.36-25.376zM302.896 172.64c-14 0-25.36 11.376-25.36 25.392 0 13.984 11.36 25.36 25.36 25.36 14.048 0 25.44-11.376 25.44-25.36 0-14.016-11.392-25.392-25.44-25.392zM330.848 257.344c-14 0-25.408 11.36-25.408 25.376s11.408 25.392 25.408 25.392c14 0 25.328-11.376 25.328-25.392s-11.328-25.376-25.328-25.376zM385.040 172.64c-13.984 0-25.328 11.376-25.328 25.392 0 13.984 11.36 25.36 25.328 25.36 14 0 25.408-11.376 25.408-25.36 0-14.016-11.408-25.392-25.408-25.392zM412.96 257.344c-14.016 0-25.36 11.36-25.36 25.376s11.344 25.392 25.36 25.392c14.048 0 25.376-11.376 25.376-25.392s-11.328-25.376-25.376-25.376z"/><glyph unicode="" d="M142.992 332.768c10.352 0 18.8 8.4 18.8 18.8v67.68c0 10.368-8.432 18.784-18.8 18.784-10.384 0-18.8-8.4-18.8-18.784v-67.68c0-10.4 8.416-18.8 18.8-18.8zM394.384 383.344v-0.32c7.776-6.944 12.72-17.008 12.72-28.288 0-20.816-16.88-37.712-37.744-37.712s-37.76 16.912-37.76 37.712c0 11.264 4.976 21.344 12.784 28.288v0.32h-176.416v-0.32c7.824-6.944 12.768-17.008 12.768-28.288 0-20.816-16.896-37.712-37.728-37.712-20.864 0-37.744 16.912-37.744 37.712 0 11.264 4.928 21.344 12.752 28.288v0.32h-85.536v-383.6h447.248v383.6h-85.344zM448.72 32.832h-383.152v254.72h383.152v-254.72zM369.36 332.768c10.384 0 18.784 8.4 18.784 18.8v67.68c0 10.368-8.4 18.784-18.784 18.784-10.352 0-18.816-8.4-18.816-18.784v-67.68c0-10.4 8.464-18.8 18.816-18.8zM349.216 184.128h-47.936v-47.872h47.952v47.872zM349.216 256.112h-47.936v-47.824h47.952v47.824zM349.216 114.112h-47.936v-47.872h47.952v47.872zM416.656 256.112h-47.92v-47.824h47.92v47.824zM416.656 184.128h-47.92v-47.872h47.92v47.872zM281.696 256.112h-47.872v-47.824h47.872v47.824zM146.8 184.128h-47.856v-47.872h47.856v47.872zM214.288 114.112h-47.888v-47.872h47.872v47.872zM146.8 114.112h-47.856v-47.872h47.856v47.872zM281.696 184.128h-47.872v-47.872h47.872v47.872zM281.696 114.112h-47.872v-47.872h47.872v47.872zM214.288 184.128h-47.888v-47.872h47.872v47.872zM214.288 256.112h-47.888v-47.824h47.872v47.824z"/><glyph unicode="" d="M256 444.727l-200.814-243.291h131.054v-198.144h139.575v198.144h131.017z"/><glyph unicode="" d="M325.779 246.583v198.144h-139.593v-198.144h-130.999l200.832-243.292 200.813 243.292z"/><glyph unicode="" d="M487.232 35.872c0 0-78.176 80.288-109.328 111.312-13.552 13.552-22.832 22.752-22.832 22.752 10.56 15.088 18.816 31.616 24.704 49.392 5.84 17.76 8.752 36.496 8.752 56.192 0 25.36-4.816 49.2-14.448 71.552-9.664 22.32-22.784 41.824-39.456 58.432-16.64 16.688-36.144 29.824-58.496 39.472-22.336 9.664-46.176 14.496-71.536 14.496-25.344 0-49.184-4.848-71.552-14.496-22.336-9.648-41.712-22.784-58.192-39.472-16.416-16.608-29.52-36.128-39.152-58.448-9.664-22.336-14.496-46.192-14.496-71.552 0-25.376 4.848-49.216 14.496-71.552 9.632-22.304 22.72-41.792 39.152-58.464 16.464-16.608 35.856-29.776 58.176-39.456 22.368-9.664 46.208-14.448 71.552-14.448 19.68 0 38.416 2.88 56.208 8.768 17.776 5.856 34.288 14.144 49.36 24.72 0 0 8.576-8.512 21.2-21.216 34.512-34.64 110.416-113.392 110.416-113.392 11.456-4.992 29.712 0.336 38.848 8.064 9.040 7.776 14.096 23.984 6.624 37.344zM327.792 223.28c-7.008-16.192-16.576-30.336-28.624-42.336-12.096-12.048-26.192-21.616-42.336-28.608-16.128-7.024-33.392-10.528-51.68-10.528-18.704 0-36.096 3.504-52.256 10.528-16.16 7.008-30.288 16.56-42.336 28.608-12.048 12.016-21.616 26.16-28.608 42.336-7.008 16.112-10.512 33.568-10.512 52.24 0 18.272 3.504 35.632 10.512 51.984 6.992 16.336 16.56 30.56 28.608 42.592 12.048 12.096 26.176 21.664 42.336 28.608 16.16 7.056 33.552 10.512 52.256 10.512 18.288 0 35.552-3.456 51.68-10.512 16.144-6.96 30.24-16.512 42.336-28.608 12.032-12.032 21.616-26.256 28.624-42.592 7.008-16.352 10.48-33.712 10.48-51.984 0.016-18.672-3.456-36.128-10.48-52.24z"/><glyph unicode="" d="M483.255 415.177l-36.023 35.968-191.25-191.268-191.25 191.268-35.986-35.968 191.268-191.269-191.123-191.14 35.968-35.932 191.14 191.104 191.123-191.104 35.932 35.932-191.104 191.123z"/><glyph unicode="" d="M200.21 226.889l178.213 183.315-37.248 34.981-212.608-218.588 218.459-223.78 36.389 35.657z"/><glyph unicode="" d="M256 335.168l-224.992-239.984h450.032z"/><glyph unicode="" d="M96.624 451.12v-454.24l312.928 227.12z"/><glyph unicode="" d="M102.992 224l312.912-227.12v454.24z"/><glyph unicode="" d="M0 0.464h63.984v479.536h-63.984v-479.536zM512.080 480h-415.824v-287.888h415.824l-138.208 142.032 138.208 145.856z"/><glyph unicode="" d="M512 241.12h-238.512v238.88h-34.016v-238.88h-239.472v-34.064h239.472v-239.056h34.016v239.056h238.512z"/><glyph unicode="" d="M255.968 228.064l221.488 155.84c-2.656 0.528-5.344 0.848-8.128 0.848h-426.656c-2.8 0-5.504-0.32-8.144-0.848l221.44-155.84zM256.928 168.496l-0.96 1.408-0.944-1.408-254.56 179.136c-0.176-1.6-0.464-3.2-0.464-4.816v-267.712c0-23.904 19.104-43.312 42.672-43.312h426.656c23.6 0 42.688 19.408 42.688 43.312v267.712c0 1.632-0.288 3.216-0.496 4.816l-254.592-179.136z"/><glyph unicode="" d="M127.584 31.776v127.632h-127.584v-127.632h127.584zM319.248 416.24h-126.928v-384.448h126.928v384.448zM511.584 287.472h-127.376v-255.68h127.376v255.68z"/><glyph unicode="" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM372.16 144.832l-37.104-37.104-79.088 79.056-79.056-79.040-37.12 37.136 79.024 79.024-79.136 79.12 37.136 37.136 79.12-79.136 79.184 79.184 37.152-37.152-79.2-79.168 79.088-79.056z"/><glyph unicode="" d="M262.748 418.688c-113.664 2.249-207.214-67.803-208.969-156.435-0.585-30.829 9.984-59.813 28.8-84.644l-4.919 4.955c32.384-41.618-31.104-153.308-31.104-153.308l142.281 70.345c22.51-7.095 44.16-11.923 69.724-12.452 113.664-2.231 205.111 78.355 206.848 167.004 1.755 88.631-88.96 162.304-202.661 164.535z"/><glyph unicode="" d="M259.163 285.422l201.837-196.224 38.546 41.070-240.713 234.021-246.363-240.476 39.26-40.101z"/><glyph unicode="" d="M252.819 162.579l-201.82 196.224-38.528-41.070 240.677-234.021 246.4 240.476-39.332 40.101z"/><glyph unicode="" d="M256-33.248c-141.408 0-256 114.624-256 256s114.592 256 256 256c141.376 0 256-114.624 256-256s-114.608-256-256-256zM256 447.76c-124.048 0-225.008-100.96-225.008-225.008s100.96-225.024 225.008-225.024 224.992 100.96 224.992 225.008-100.928 225.024-224.992 225.024zM320.24 219.152l-15.6-12.128c-8.496-6.624-14.128-14.32-16.912-23.152-1.776-5.6-3.008-12.256-3.168-24h-59.712c0.88 24.848 3.504 39.968 7.328 49.472 3.808 9.472 13.632 20.368 29.44 32.72l16.032 12.528c5.28 4 9.536 8.32 12.752 13.024 5.872 8.064 8.784 16.976 8.784 26.656 0 11.152-3.248 21.312-9.776 30.496-6.496 9.184-18.4 13.808-35.712 13.808-17.008 0-29.056-5.68-36.16-17.008s-10.592-21.664-10.592-33.84h-63.68c1.744 41.872 16.32 70.16 43.776 87.632 17.344 11.152 38.656 16.752 63.904 16.752 33.216 0 60.784-7.936 82.752-23.808 21.968-15.84 34.8-48.432 34.8-79.6 0-19.088-6.624-26.096-16.144-39.184-5.584-7.92-16.272-18.048-32.112-30.368zM287.728 64h-63.504v63.68h63.504v-63.68z"/><glyph unicode="" d="M416.656 128v135.696h-320.672v-135.696h-95.984v199.344c0 13.76 11.168 24.912 24.944 24.912h462.144c13.744 0 24.912-11.152 24.912-24.912v-199.344h-95.344zM464.304 324.624c-11.024 0-19.92-8.928-19.92-19.936s8.896-19.952 19.92-19.952c10.992 0 19.968 8.96 19.968 19.952 0 11.008-8.992 19.936-19.968 19.936zM127.728 480h256v-96.192h-256v96.192zM160.976 31.664h191.232v192.336h31.824v-224.080h-255.984v224.080h32.912v-192.336z"/><glyph unicode="" d="M502.080 285.376h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 7.008 3.6 11.088-1.312 4.096-5.168 6.88-9.44 6.88zM333.424 170.256l48.208-148.064-125.632 91.36-125.968-91.44 48.256 148.128-125.168 91.136h154.576l48.256 147.376 48.016-147.376h154.832l-125.376-91.12z"/><glyph unicode="" d="M319.376 223.824v127.76h-126.752v-127.76h-89.744l153.168-188.608 153.088 188.608zM256.016 480c-141.392 0-256-114.608-256-255.984 0-141.392 114.608-256.016 256-256.016 141.376 0 256 114.624 256 256.016 0 141.376-114.624 255.984-256 255.984zM256.016 0c-123.52 0-224 100.496-224 224.016 0 123.504 100.48 223.984 224 223.984s224-100.48 224-223.984c0-123.52-100.48-224.016-224-224.016z"/><glyph unicode="" d="M255.982 440.594c-119.607 0-216.576-96.969-216.576-216.594s96.969-216.595 216.576-216.595c119.625 0 216.595 96.969 216.595 216.595s-96.951 216.595-216.595 216.595zM255.982 419.913c108.051 0 195.913-87.881 195.913-195.913 0-45.184-15.507-86.711-41.325-119.899-3.108 1.134-6.217 2.195-9.197 3.456-19.748 8.265-41.709 17.957-61.421 26.094-5.632 1.536-11.264 3.072-16.896 4.608-6.692 4.589-13.33 19.986-16.914 27.666-3.548 0.512-7.149 1.005-10.752 1.481 0.531 11.868 7.881 12.544 10.752 21.541 2.541 7.954 0.293 18.341 4.279 25.728 2.779 5.12 9.125 5.12 12.233 9.545 2.853 3.95 4.772 10.917 5.668 15.799 1.609 8.905 3.017 21.12-1.207 29.988-2.432 5.065-3.968 5.577-4.644 11.739-0.823 7.516 2.212 31.891 2.341 37.175 0.293 13.678-0.055 14.793-3.346 28.123 0 0-4.005 12.087-10.295 15.726l-12.58 2.158-7.772 7.186c-31.305 19.273-64.877 5.76-82.834-1.499-25.911-8.43-42.295-33.792-30.867-87.955 1.957-9.289-5.065-13.421-4.608-18.468 1.042-11.045 1.207-37.614 11.648-44.124 0.969-0.603 8.375-2.469 8.339-1.938 1.006-10.752 2.048-21.522 3.054-32.238 2.615-7.149 8.869-7.954 10.679-18.048l-7.991-1.92c-3.602-7.68-10.185-23.077-16.896-27.666-5.65-1.517-11.282-3.053-16.915-4.589-19.731-8.119-41.655-17.829-61.422-26.094-1.079-0.439-2.213-0.786-3.291-1.207-24.759 32.786-39.625 73.454-39.625 117.632 0 108.032 87.881 195.913 195.895 195.913z"/><glyph unicode="" d="M94.8 322.592l-93.424 78.464-0.496-321.968 316.688 56.336-89.216 74.96c182.112 167.52 227.904-8.128 246.272-204.784 65.936 574.064-229.84 445.328-379.824 316.992z"/><glyph unicode="" d="M428.432 224h-20.080v96.176c0 43.36-16.448 83.104-43.632 112.144-27.056 29.056-65.632 47.712-108.16 47.68-42.544 0.032-81.12-18.624-108.192-47.68-27.184-29.040-43.632-68.784-43.648-112.144v-96.176h-20.816c-10.816 0-19.584-8.752-19.584-19.584v-216.8c0-10.848 8.768-19.616 19.584-19.616h344.528c10.8 0 19.584 8.768 19.584 19.632v216.8c0 10.816-8.784 19.568-19.584 19.568zM176.816 320.176c0 25.024 9.472 47.168 24.192 62.928 14.848 15.728 34.144 24.784 55.552 24.816 21.376-0.032 40.688-9.072 55.536-24.816 14.704-15.744 24.176-37.888 24.176-62.928v-96.176h-159.44v96.176z"/><glyph unicode="" d="M150.896 316.944h-112.192c-9.040 0-16.384-7.312-16.384-16.368v-80c0-9.056 7.344-16.368 16.384-16.368h112.192c9.056 0 16.432 7.312 16.432 16.368v80c0 9.056-7.376 16.368-16.432 16.368zM150.896 171.056h-79.376c-9.056 0-16.432-7.312-16.432-16.368v-170.32c-0.016-9.056 7.36-16.368 16.432-16.368h79.376c9.056 0 16.432 7.312 16.432 16.368v170.32c0 9.056-7.376 16.368-16.432 16.368zM473.328 316.944h-244.88c-9.056 0-16.368-7.312-16.368-16.368v-80c0-9.056 7.312-16.368 16.368-16.368h244.88c8.992 0 16.368 7.312 16.368 16.368v80c0 9.056-7.36 16.368-16.368 16.368zM439.52 169.376h-210.56c-9.056 0-16.368-7.344-16.368-16.4v-168.592c0-9.056 7.312-16.368 16.368-16.368h210.56c9.056 0 16.368 7.312 16.368 16.368v168.592c0 9.056-7.312 16.4-16.368 16.4zM251.952 335.68c19.12-3.504 37.568-5.536 54.816-5.536 86.688 0 133.68 46.592 133.936 90.464 0.128 28.256-20.752 58.88-68.368 59.376-63.808 0-103.312-45.056-123.872-78.496-20.944 33.312-60.624 77.472-124.56 77.472-46.256-0.464-67.2-31.088-67.008-59.328 0.176-43.888 47.248-90.512 133.936-90.512v0c18.752 0 38.88 2.128 59.872 6.336l1.248 0.224zM373.264 439.008c8-0.064 26.56-2 26.432-18.192-0.064-20.624-28.992-49.68-92.944-49.68-8.816 0-18 0.56-27.632 1.68 14.576 25.648 45.216 66.192 94.144 66.192zM190.832 370.128v0c-63.936 0-92.88 29.056-92.992 49.68-0.080 16.16 18.496 18.096 27.36 18.192 48.368 0 78.816-40.56 93.184-66.224-9.552-1.088-18.736-1.648-27.552-1.648z"/><glyph unicode="" d="M182.256 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.776c-9.216 0-16.72 7.472-16.72 16.72v59.872c0 9.216 7.504 16.72 16.72 16.72h9.776c9.184 0 16.688-7.504 16.688-16.72v-59.872zM373.072 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.744c-9.248 0-16.688 7.472-16.688 16.72v59.872c0 9.216 7.424 16.72 16.688 16.72h9.744c9.184 0 16.688-7.504 16.688-16.72v-59.872zM398.816 253.152l-33.936 27.664-133.68-163.872-71.312 56.688-25.28-31.728 105.184-83.648zM471.952 434h-62.432v-26.064c0-27.68-22.56-50.192-50.128-50.192h-9.808c-27.68 0-50.128 22.496-50.128 50.192v26.064h-85.504v-26.064c0-27.68-22.496-50.192-50.128-50.192h-9.76c-27.664 0-50.16 22.496-50.16 50.192v26.064h-63.808c-9.216 0-16.72-7.504-16.72-16.688v-432.592c0-9.216 7.504-16.72 16.72-16.72h431.84c9.184 0 16.688 7.504 16.688 16.72v432.592c0.016 9.184-7.488 16.688-16.672 16.688zM438.512 42.592c0-9.248-7.504-16.72-16.752-16.72h-331.504c-9.248 0-16.752 7.472-16.752 16.72v252.096c0 9.248 7.504 16.688 16.752 16.688h331.504c9.248 0 16.752-7.44 16.752-16.688v-252.096z"/></font></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg"><defs><font-face units-per-em="512" ascent="480" descent="-32" /><missing-glyph horiz-adv-x="512" /><glyph unicode=" " d="" horiz-adv-x="256" /><glyph unicode="" d="M436.608 435.568c-65.68 31.424-144.064 2.832-174.976-63.84-2.16-4.64-4.016-10.448-5.664-17.2-1.648 6.752-3.504 12.56-5.632 17.2-30.944 66.672-109.248 95.264-174.944 63.84-65.6-31.424-93.744-110.96-62.832-177.648 30.928-66.672 243.344-257.84 243.344-257.84s0.016 0.224 0.048 0.576c0.048-0.352 0.064-0.576 0.064-0.576s212.512 191.168 243.44 257.84c30.896 66.688 2.832 146.224-62.848 177.648z" /><glyph unicode="" d="M362.533 425.051c-49.81-49.792-20.809-20.772-20.809-20.772l96.402-96.384c0 0-31.067-31.049 20.772 20.773s-46.611 146.194-96.365 96.384zM320.147 383.671l-227.987-227.986 0.329-0.293-54.071-146.524 149.833 50.688 0.311-0.311 0.786 0.805v0.019l227.2 227.2-96.403 96.403zM179.036 104.375l-78.811-33.28 37.047 75.044 38.345 38.363 41.764-41.783-38.345-38.345z" /><glyph unicode="" d="M255.952 480l-255.952-448h512l-256.048 448zM287.12 353.808v-65.36l-16.688-128.544h-27.088l-18.032 128.544-0.992 65.36h62.8zM224.096 64.112v64.112h64.24v-64.112h-64.24z" /><glyph unicode="" d="M363.923 112.019c-29.805-28.764-68.663-43.502-108.013-43.538-35.145 0.036-70.199 11.757-99.347 35.932-37.029 30.829-56.046 74.971-56.1 119.661 0 7.442 0.549 14.829 1.591 22.18l-60.672-11.374c-0.164-3.602-0.292-7.186-0.292-10.807-0.036-61.495 26.459-122.899 77.549-165.285 40.009-33.335 88.887-49.683 137.252-49.683h0.128c56.211 0 112.164 22.217 153.746 64.914l39.844-39.772 0.311 124.745-131.803 0.348 45.805-47.324zM393.344 389.23c-40.046 33.335-88.923 49.664-137.271 49.664-55.808 0-111.397-21.833-152.923-63.945l-37.687 34.798-0.677-120.722 130.487-0.75-46.336 48.493c29.641 28.252 68.188 42.697 107.154 42.733 35.108-0.036 70.217-11.721 99.328-35.932 37.029-30.829 56.046-74.935 56.137-119.698 0-6.437-0.457-12.892-1.225-19.365l60.435 11.593c0.036 2.615 0.164 5.212 0.164 7.772-0.036 61.549-26.514 122.899-77.587 165.357z" /><glyph unicode="" d="M95.792-32h320.4v320.080h-320.4v-320.080zM318.336 228.512c0 9.904 8.032 17.904 17.952 17.904 9.904 0 17.936-8 17.936-17.904v-188.736c0-9.888-8.032-17.92-17.936-17.92-9.92 0-17.952 8.032-17.952 17.92v188.736zM238.048 228.512c0 9.904 8.032 17.904 17.92 17.904s17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92s-17.92 8.032-17.92 17.92v188.736zM157.6 228.512c0 9.904 8 17.904 17.92 17.904 9.888 0 17.92-8 17.92-17.904v-188.736c0-9.888-8.032-17.92-17.92-17.92-9.92 0-17.92 8.032-17.92 17.92v188.736zM423.216 416.528h-71.232v10.896c0 29.040-19.76 52.576-48.8 52.576h-94.72c-29.008 0-48.48-23.536-48.48-52.576v-10.896h-71.232c-13.696 0-24.768-11.088-24.768-24.752v-71.984h384v71.984c0 13.664-11.040 24.752-24.768 24.752zM319.936 416.528h-128.192v14.704c0.032 9.248 7.488 16.736 16.72 16.768h94.72c9.216-0.032 16.704-7.52 16.752-16.768v-14.704z" /><glyph unicode="" d="M511.52 278.496c-1.312 4.096-5.152 6.88-9.44 6.88h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 6.992 3.6 11.088z" /><glyph unicode="" d="M473.015 200.375v49.371l-7.003 2.268-52.882 17.244-14.116 34.103 27.154 57.381-34.908 34.907-6.583-3.309-49.555-25.198-34.103 14.117-21.394 59.757h-49.371l-2.286-6.985-17.262-52.882-34.048-14.099-57.399 27.136-34.925-34.926 3.309-6.564 25.18-49.591-14.080-34.029-59.758-21.412v-49.39l6.949-2.249 52.901-17.28 14.099-34.067-27.118-57.38 34.925-34.925 6.528 3.328 49.591 25.197 34.066-14.116 21.394-59.757h49.371l2.286 6.985 17.28 52.882 34.029 14.116 57.399-27.136 34.944 34.908-3.346 6.546-25.197 49.572 14.116 34.067 59.813 21.413zM256 154.861c-38.199 0-69.156 30.957-69.156 69.139 0 38.217 30.958 69.156 69.156 69.156 38.163 0 69.156-30.94 69.156-69.156 0-38.18-31.012-69.139-69.156-69.139z" /><glyph unicode="" d="M31.008 351.36l224.992-239.984 225.040 239.984z" /><glyph unicode="" d="M383.415 226.596l-212.571 218.587-37.285-34.981 178.286-183.277-183.278-188.452 36.48-35.657 205.659 211.456-0.201 0.201z" /><glyph unicode="" d="M52.928 345.2h406.144c11.056 0 20 8.976 20 20.016 0 11.072-8.944 20.032-20 20.032h-406.144c-11.056 0-20.016-8.96-20.016-20.032 0-11.040 8.96-20.016 20.016-20.016zM459.072 244.016h-406.144c-11.056 0-20.016-8.944-20.016-20.016s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.016-20 20.016zM459.072 102.8h-406.144c-11.056 0-20.016-8.96-20.016-20.032s8.96-20.016 20.016-20.016h406.144c11.056 0 20 8.944 20 20.016s-8.928 20.032-20 20.032z" /><glyph unicode="" d="M256.144 480c-89.12 0-161.344-72.24-161.344-161.376 0-89.104 161.344-350.624 161.344-350.624s161.376 261.52 161.376 350.624c0 89.136-72.192 161.376-161.376 161.376zM256.144 269.616c-27.056 0-49.024 21.952-49.024 49.008 0 27.072 21.984 49.024 49.024 49.024 27.104 0 49.088-21.952 49.088-49.024 0-27.056-21.984-49.008-49.088-49.008z" /><glyph unicode="" d="M0 256.144h224.032v223.808h-224.032v-223.808zM288.128 479.952v-95.728h224.176v95.728h-224.176zM0-32h224.032v223.808h-224.032v-223.808zM288.128 256.144h224.176v95.728h-224.176v-95.728zM288.128 96.080h224.176v95.728h-224.176v-95.728zM288.128-32h224.176v95.712h-224.176v-95.712z" /><glyph unicode="" d="M332.764 119.003c-9.216 0-45.495-56.027-65.243-56.027-5.284 0-7.863 4.644-7.863 9.216 0 10.569 7.241 27.044 11.154 36.937l47.397 128.384c23.772 63.891-6.546 81.024-34.871 81.024-38.217 0-72.448-19.091-98.779-44.124-8.576-8.576-37.523-36.206-37.523-48.091 0-3.932 3.931-8.576 8.576-8.576 11.813 0 43.447 57.308 67.803 57.308 5.285 0 11.191-5.924 6.583-17.755l-46.080-115.968c-4.644-11.154-27.044-65.171-27.044-96.786 0-25.015 16.476-36.188 40.192-36.188 66.523 0 143.543 81.645 143.543 100.755-0.019 5.925-4.589 9.892-7.844 9.892zM319.543 439.661c-28.947 0-54.016-23.68-54.016-52.663 0-27.008 17.792-44.8 44.837-44.8 29.55 0 54.62 22.4 54.62 52.7 0 27.008-19.072 44.764-45.44 44.764z" /><glyph unicode="" d="M0 351.552h128.464v128.448h-128.464v-128.448zM191.76 351.552h128.528v128.448h-128.528v-128.448zM383.568 480v-128.448h128.496v128.448h-128.496zM0 159.744h128.464v128.464h-128.464v-128.464zM191.76 159.744h128.528v128.464h-128.528v-128.464zM383.568 159.744h128.496v128.464h-128.496v-128.464zM0-32h128.464v128h-128.464v-128zM191.76-32h128.528v128h-128.528v-128zM383.568-32h128.496v128h-128.496v-128z" /><glyph unicode="" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM231.936 94.576l-125.936 128.032 32.208 25.936 72.864-57.088c29.76 35.424 96 106.032 187.312 161.984l7.696-17.792c-83.808-77.088-152.48-185.6-174.144-241.072z" /><glyph unicode="" d="M0 241.12h512v-34.064h-512v34.064z" /><glyph unicode="" d="M478.263 426.149c-142.555-87.388-245.98-197.632-292.48-252.947l-113.792 89.161-50.267-40.539 196.663-199.973c33.847 86.674 141.056 256.11 271.872 376.485l-11.995 27.813z" /><glyph unicode="" d="M220.576 83.248c-26.352 0-47.696-21.376-47.696-47.712s21.344-47.664 47.696-47.664c26.336 0 47.696 21.328 47.696 47.664s-21.36 47.712-47.696 47.712zM385.344 83.248c-26.4 0-47.76-21.376-47.76-47.712s21.344-47.664 47.76-47.664c26.288 0 47.632 21.328 47.632 47.664s-21.344 47.712-47.632 47.712zM459.856 350.32c-122.384 0-319.856 0-319.856 0s-19.152 52.608-37.392 84.864c-14.128 24.976-43.344 23.968-43.344 23.968-20.096 0-33.024-12.288-33.024-32.4 0-20.096 15.92-36.16 36.032-36.16l8.496-0.080 95.2-262.192 266.832-0.208c0 0 48.784 199.632 46.272 191.888 8.944 27.68-2.448 30.32-19.216 30.32zM166.528 257.344c-14 0-25.36 11.36-25.36 25.376s11.36 25.392 25.36 25.392c14.016 0 25.36-11.376 25.36-25.392s-11.344-25.376-25.36-25.376zM220.768 172.64c-14.016 0-25.376 11.376-25.376 25.392 0 13.984 11.36 25.36 25.376 25.36 14 0 25.36-11.376 25.36-25.36 0.016-14.016-11.36-25.392-25.36-25.392zM248.656 257.344c-14 0-25.376 11.36-25.376 25.376s11.36 25.392 25.376 25.392c14 0 25.36-11.376 25.36-25.392s-11.36-25.376-25.36-25.376zM302.896 172.64c-14 0-25.36 11.376-25.36 25.392 0 13.984 11.36 25.36 25.36 25.36 14.048 0 25.44-11.376 25.44-25.36 0-14.016-11.392-25.392-25.44-25.392zM330.848 257.344c-14 0-25.408 11.36-25.408 25.376s11.408 25.392 25.408 25.392c14 0 25.328-11.376 25.328-25.392s-11.328-25.376-25.328-25.376zM385.040 172.64c-13.984 0-25.328 11.376-25.328 25.392 0 13.984 11.36 25.36 25.328 25.36 14 0 25.408-11.376 25.408-25.36 0-14.016-11.408-25.392-25.408-25.392zM412.96 257.344c-14.016 0-25.36 11.36-25.36 25.376s11.344 25.392 25.36 25.392c14.048 0 25.376-11.376 25.376-25.392s-11.328-25.376-25.376-25.376z" /><glyph unicode="" d="M142.992 332.768c10.352 0 18.8 8.4 18.8 18.8v67.68c0 10.368-8.432 18.784-18.8 18.784-10.384 0-18.8-8.4-18.8-18.784v-67.68c0-10.4 8.416-18.8 18.8-18.8zM394.384 383.344v-0.32c7.776-6.944 12.72-17.008 12.72-28.288 0-20.816-16.88-37.712-37.744-37.712s-37.76 16.912-37.76 37.712c0 11.264 4.976 21.344 12.784 28.288v0.32h-176.416v-0.32c7.824-6.944 12.768-17.008 12.768-28.288 0-20.816-16.896-37.712-37.728-37.712-20.864 0-37.744 16.912-37.744 37.712 0 11.264 4.928 21.344 12.752 28.288v0.32h-85.536v-383.6h447.248v383.6h-85.344zM448.72 32.832h-383.152v254.72h383.152v-254.72zM369.36 332.768c10.384 0 18.784 8.4 18.784 18.8v67.68c0 10.368-8.4 18.784-18.784 18.784-10.352 0-18.816-8.4-18.816-18.784v-67.68c0-10.4 8.464-18.8 18.816-18.8zM349.216 184.128h-47.936v-47.872h47.952v47.872zM349.216 256.112h-47.936v-47.824h47.952v47.824zM349.216 114.112h-47.936v-47.872h47.952v47.872zM416.656 256.112h-47.92v-47.824h47.92v47.824zM416.656 184.128h-47.92v-47.872h47.92v47.872zM281.696 256.112h-47.872v-47.824h47.872v47.824zM146.8 184.128h-47.856v-47.872h47.856v47.872zM214.288 114.112h-47.888v-47.872h47.872v47.872zM146.8 114.112h-47.856v-47.872h47.856v47.872zM281.696 184.128h-47.872v-47.872h47.872v47.872zM281.696 114.112h-47.872v-47.872h47.872v47.872zM214.288 184.128h-47.888v-47.872h47.872v47.872zM214.288 256.112h-47.888v-47.824h47.872v47.824z" /><glyph unicode="" d="M256 444.727l-200.814-243.291h131.054v-198.144h139.575v198.144h131.017z" /><glyph unicode="" d="M325.779 246.583v198.144h-139.593v-198.144h-130.999l200.832-243.292 200.813 243.292z" /><glyph unicode="" d="M487.232 35.872c0 0-78.176 80.288-109.328 111.312-13.552 13.552-22.832 22.752-22.832 22.752 10.56 15.088 18.816 31.616 24.704 49.392 5.84 17.76 8.752 36.496 8.752 56.192 0 25.36-4.816 49.2-14.448 71.552-9.664 22.32-22.784 41.824-39.456 58.432-16.64 16.688-36.144 29.824-58.496 39.472-22.336 9.664-46.176 14.496-71.536 14.496-25.344 0-49.184-4.848-71.552-14.496-22.336-9.648-41.712-22.784-58.192-39.472-16.416-16.608-29.52-36.128-39.152-58.448-9.664-22.336-14.496-46.192-14.496-71.552 0-25.376 4.848-49.216 14.496-71.552 9.632-22.304 22.72-41.792 39.152-58.464 16.464-16.608 35.856-29.776 58.176-39.456 22.368-9.664 46.208-14.448 71.552-14.448 19.68 0 38.416 2.88 56.208 8.768 17.776 5.856 34.288 14.144 49.36 24.72 0 0 8.576-8.512 21.2-21.216 34.512-34.64 110.416-113.392 110.416-113.392 11.456-4.992 29.712 0.336 38.848 8.064 9.040 7.776 14.096 23.984 6.624 37.344zM327.792 223.28c-7.008-16.192-16.576-30.336-28.624-42.336-12.096-12.048-26.192-21.616-42.336-28.608-16.128-7.024-33.392-10.528-51.68-10.528-18.704 0-36.096 3.504-52.256 10.528-16.16 7.008-30.288 16.56-42.336 28.608-12.048 12.016-21.616 26.16-28.608 42.336-7.008 16.112-10.512 33.568-10.512 52.24 0 18.272 3.504 35.632 10.512 51.984 6.992 16.336 16.56 30.56 28.608 42.592 12.048 12.096 26.176 21.664 42.336 28.608 16.16 7.056 33.552 10.512 52.256 10.512 18.288 0 35.552-3.456 51.68-10.512 16.144-6.96 30.24-16.512 42.336-28.608 12.032-12.032 21.616-26.256 28.624-42.592 7.008-16.352 10.48-33.712 10.48-51.984 0.016-18.672-3.456-36.128-10.48-52.24z" /><glyph unicode="" d="M483.255 415.177l-36.023 35.968-191.25-191.268-191.25 191.268-35.986-35.968 191.268-191.269-191.123-191.14 35.968-35.932 191.14 191.104 191.123-191.104 35.932 35.932-191.104 191.123z" /><glyph unicode="" d="M200.21 226.889l178.213 183.315-37.248 34.981-212.608-218.588 218.459-223.78 36.389 35.657z" /><glyph unicode="" d="M256 335.168l-224.992-239.984h450.032z" /><glyph unicode="" d="M96.624 451.12v-454.24l312.928 227.12z" /><glyph unicode="" d="M102.992 224l312.912-227.12v454.24z" /><glyph unicode="" d="M0 0.464h63.984v479.536h-63.984v-479.536zM512.080 480h-415.824v-287.888h415.824l-138.208 142.032 138.208 145.856z" /><glyph unicode="" d="M512 241.12h-238.512v238.88h-34.016v-238.88h-239.472v-34.064h239.472v-239.056h34.016v239.056h238.512z" /><glyph unicode="" d="M255.968 228.064l221.488 155.84c-2.656 0.528-5.344 0.848-8.128 0.848h-426.656c-2.8 0-5.504-0.32-8.144-0.848l221.44-155.84zM256.928 168.496l-0.96 1.408-0.944-1.408-254.56 179.136c-0.176-1.6-0.464-3.2-0.464-4.816v-267.712c0-23.904 19.104-43.312 42.672-43.312h426.656c23.6 0 42.688 19.408 42.688 43.312v267.712c0 1.632-0.288 3.216-0.496 4.816l-254.592-179.136z" /><glyph unicode="" d="M127.584 31.776v127.632h-127.584v-127.632h127.584zM319.248 416.24h-126.928v-384.448h126.928v384.448zM511.584 287.472h-127.376v-255.68h127.376v255.68z" /><glyph unicode="" d="M255.296 450.464c-124.688 0-225.76-101.072-225.76-225.76 0-124.672 101.072-225.76 225.76-225.76 124.672 0 225.76 101.088 225.76 225.76 0 124.688-101.072 225.76-225.76 225.76zM372.16 144.832l-37.104-37.104-79.088 79.056-79.056-79.040-37.12 37.136 79.024 79.024-79.136 79.12 37.136 37.136 79.12-79.136 79.184 79.184 37.152-37.152-79.2-79.168 79.088-79.056z" /><glyph unicode="" d="M262.748 418.688c-113.664 2.249-207.214-67.803-208.969-156.435-0.585-30.829 9.984-59.813 28.8-84.644l-4.919 4.955c32.384-41.618-31.104-153.308-31.104-153.308l142.281 70.345c22.51-7.095 44.16-11.923 69.724-12.452 113.664-2.231 205.111 78.355 206.848 167.004 1.755 88.631-88.96 162.304-202.661 164.535z" /><glyph unicode="" d="M259.163 285.422l201.837-196.224 38.546 41.070-240.713 234.021-246.363-240.476 39.26-40.101z" /><glyph unicode="" d="M252.819 162.579l-201.82 196.224-38.528-41.070 240.677-234.021 246.4 240.476-39.332 40.101z" /><glyph unicode="" d="M256-33.248c-141.408 0-256 114.624-256 256s114.592 256 256 256c141.376 0 256-114.624 256-256s-114.608-256-256-256zM256 447.76c-124.048 0-225.008-100.96-225.008-225.008s100.96-225.024 225.008-225.024 224.992 100.96 224.992 225.008-100.928 225.024-224.992 225.024zM320.24 219.152l-15.6-12.128c-8.496-6.624-14.128-14.32-16.912-23.152-1.776-5.6-3.008-12.256-3.168-24h-59.712c0.88 24.848 3.504 39.968 7.328 49.472 3.808 9.472 13.632 20.368 29.44 32.72l16.032 12.528c5.28 4 9.536 8.32 12.752 13.024 5.872 8.064 8.784 16.976 8.784 26.656 0 11.152-3.248 21.312-9.776 30.496-6.496 9.184-18.4 13.808-35.712 13.808-17.008 0-29.056-5.68-36.16-17.008s-10.592-21.664-10.592-33.84h-63.68c1.744 41.872 16.32 70.16 43.776 87.632 17.344 11.152 38.656 16.752 63.904 16.752 33.216 0 60.784-7.936 82.752-23.808 21.968-15.84 34.8-48.432 34.8-79.6 0-19.088-6.624-26.096-16.144-39.184-5.584-7.92-16.272-18.048-32.112-30.368zM287.728 64h-63.504v63.68h63.504v-63.68z" /><glyph unicode="" d="M416.656 128v135.696h-320.672v-135.696h-95.984v199.344c0 13.76 11.168 24.912 24.944 24.912h462.144c13.744 0 24.912-11.152 24.912-24.912v-199.344h-95.344zM464.304 324.624c-11.024 0-19.92-8.928-19.92-19.936s8.896-19.952 19.92-19.952c10.992 0 19.968 8.96 19.968 19.952 0 11.008-8.992 19.936-19.968 19.936zM127.728 480h256v-96.192h-256v96.192zM160.976 31.664h191.232v192.336h31.824v-224.080h-255.984v224.080h32.912v-192.336z" /><glyph unicode="" d="M502.080 285.376h-180.704l-55.952 171.744c-1.344 4.096-5.136 6.88-9.44 6.88-4.272 0-8.096-2.784-9.44-6.88l-56.24-171.744h-180.384c-4.256 0-8.096-2.784-9.44-6.88-1.312-4.064 0.128-8.592 3.584-11.088l145.984-106.32-56.256-172.72c-1.328-4.096 0.128-8.592 3.616-11.12 3.456-2.496 8.208-2.496 11.664 0l146.896 106.624 146.64-106.624c1.792-1.28 3.76-1.936 5.808-1.936 2.096 0 4.144 0.656 5.856 1.936 3.568 2.528 4.96 7.008 3.6 11.12l-56.24 172.72 146.288 106.32c3.488 2.496 4.928 7.008 3.6 11.088-1.312 4.096-5.168 6.88-9.44 6.88zM333.424 170.256l48.208-148.064-125.632 91.36-125.968-91.44 48.256 148.128-125.168 91.136h154.576l48.256 147.376 48.016-147.376h154.832l-125.376-91.12z" /><glyph unicode="" d="M319.376 223.824v127.76h-126.752v-127.76h-89.744l153.168-188.608 153.088 188.608zM256.016 480c-141.392 0-256-114.608-256-255.984 0-141.392 114.608-256.016 256-256.016 141.376 0 256 114.624 256 256.016 0 141.376-114.624 255.984-256 255.984zM256.016 0c-123.52 0-224 100.496-224 224.016 0 123.504 100.48 223.984 224 223.984s224-100.48 224-223.984c0-123.52-100.48-224.016-224-224.016z" /><glyph unicode="" d="M255.982 440.594c-119.607 0-216.576-96.969-216.576-216.594s96.969-216.595 216.576-216.595c119.625 0 216.595 96.969 216.595 216.595s-96.951 216.595-216.595 216.595zM255.982 419.913c108.051 0 195.913-87.881 195.913-195.913 0-45.184-15.507-86.711-41.325-119.899-3.108 1.134-6.217 2.195-9.197 3.456-19.748 8.265-41.709 17.957-61.421 26.094-5.632 1.536-11.264 3.072-16.896 4.608-6.692 4.589-13.33 19.986-16.914 27.666-3.548 0.512-7.149 1.005-10.752 1.481 0.531 11.868 7.881 12.544 10.752 21.541 2.541 7.954 0.293 18.341 4.279 25.728 2.779 5.12 9.125 5.12 12.233 9.545 2.853 3.95 4.772 10.917 5.668 15.799 1.609 8.905 3.017 21.12-1.207 29.988-2.432 5.065-3.968 5.577-4.644 11.739-0.823 7.516 2.212 31.891 2.341 37.175 0.293 13.678-0.055 14.793-3.346 28.123 0 0-4.005 12.087-10.295 15.726l-12.58 2.158-7.772 7.186c-31.305 19.273-64.877 5.76-82.834-1.499-25.911-8.43-42.295-33.792-30.867-87.955 1.957-9.289-5.065-13.421-4.608-18.468 1.042-11.045 1.207-37.614 11.648-44.124 0.969-0.603 8.375-2.469 8.339-1.938 1.006-10.752 2.048-21.522 3.054-32.238 2.615-7.149 8.869-7.954 10.679-18.048l-7.991-1.92c-3.602-7.68-10.185-23.077-16.896-27.666-5.65-1.517-11.282-3.053-16.915-4.589-19.731-8.119-41.655-17.829-61.422-26.094-1.079-0.439-2.213-0.786-3.291-1.207-24.759 32.786-39.625 73.454-39.625 117.632 0 108.032 87.881 195.913 195.895 195.913z" /><glyph unicode="" d="M94.8 322.592l-93.424 78.464-0.496-321.968 316.688 56.336-89.216 74.96c182.112 167.52 227.904-8.128 246.272-204.784 65.936 574.064-229.84 445.328-379.824 316.992z" /><glyph unicode="" d="M428.432 224h-20.080v96.176c0 43.36-16.448 83.104-43.632 112.144-27.056 29.056-65.632 47.712-108.16 47.68-42.544 0.032-81.12-18.624-108.192-47.68-27.184-29.040-43.632-68.784-43.648-112.144v-96.176h-20.816c-10.816 0-19.584-8.752-19.584-19.584v-216.8c0-10.848 8.768-19.616 19.584-19.616h344.528c10.8 0 19.584 8.768 19.584 19.632v216.8c0 10.816-8.784 19.568-19.584 19.568zM176.816 320.176c0 25.024 9.472 47.168 24.192 62.928 14.848 15.728 34.144 24.784 55.552 24.816 21.376-0.032 40.688-9.072 55.536-24.816 14.704-15.744 24.176-37.888 24.176-62.928v-96.176h-159.44v96.176z" /><glyph unicode="" d="M150.896 316.944h-112.192c-9.040 0-16.384-7.312-16.384-16.368v-80c0-9.056 7.344-16.368 16.384-16.368h112.192c9.056 0 16.432 7.312 16.432 16.368v80c0 9.056-7.376 16.368-16.432 16.368zM150.896 171.056h-79.376c-9.056 0-16.432-7.312-16.432-16.368v-170.32c-0.016-9.056 7.36-16.368 16.432-16.368h79.376c9.056 0 16.432 7.312 16.432 16.368v170.32c0 9.056-7.376 16.368-16.432 16.368zM473.328 316.944h-244.88c-9.056 0-16.368-7.312-16.368-16.368v-80c0-9.056 7.312-16.368 16.368-16.368h244.88c8.992 0 16.368 7.312 16.368 16.368v80c0 9.056-7.36 16.368-16.368 16.368zM439.52 169.376h-210.56c-9.056 0-16.368-7.344-16.368-16.4v-168.592c0-9.056 7.312-16.368 16.368-16.368h210.56c9.056 0 16.368 7.312 16.368 16.368v168.592c0 9.056-7.312 16.4-16.368 16.4zM251.952 335.68c19.12-3.504 37.568-5.536 54.816-5.536 86.688 0 133.68 46.592 133.936 90.464 0.128 28.256-20.752 58.88-68.368 59.376-63.808 0-103.312-45.056-123.872-78.496-20.944 33.312-60.624 77.472-124.56 77.472-46.256-0.464-67.2-31.088-67.008-59.328 0.176-43.888 47.248-90.512 133.936-90.512v0c18.752 0 38.88 2.128 59.872 6.336l1.248 0.224zM373.264 439.008c8-0.064 26.56-2 26.432-18.192-0.064-20.624-28.992-49.68-92.944-49.68-8.816 0-18 0.56-27.632 1.68 14.576 25.648 45.216 66.192 94.144 66.192zM190.832 370.128v0c-63.936 0-92.88 29.056-92.992 49.68-0.080 16.16 18.496 18.096 27.36 18.192 48.368 0 78.816-40.56 93.184-66.224-9.552-1.088-18.736-1.648-27.552-1.648z" /><glyph unicode="" d="M182.256 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.776c-9.216 0-16.72 7.472-16.72 16.72v59.872c0 9.216 7.504 16.72 16.72 16.72h9.776c9.184 0 16.688-7.504 16.688-16.72v-59.872zM373.072 403.408c0-9.248-7.504-16.72-16.688-16.72h-9.744c-9.248 0-16.688 7.472-16.688 16.72v59.872c0 9.216 7.424 16.72 16.688 16.72h9.744c9.184 0 16.688-7.504 16.688-16.72v-59.872zM398.816 253.152l-33.936 27.664-133.68-163.872-71.312 56.688-25.28-31.728 105.184-83.648zM471.952 434h-62.432v-26.064c0-27.68-22.56-50.192-50.128-50.192h-9.808c-27.68 0-50.128 22.496-50.128 50.192v26.064h-85.504v-26.064c0-27.68-22.496-50.192-50.128-50.192h-9.76c-27.664 0-50.16 22.496-50.16 50.192v26.064h-63.808c-9.216 0-16.72-7.504-16.72-16.688v-432.592c0-9.216 7.504-16.72 16.72-16.72h431.84c9.184 0 16.688 7.504 16.688 16.72v432.592c0.016 9.184-7.488 16.688-16.672 16.688zM438.512 42.592c0-9.248-7.504-16.72-16.752-16.72h-331.504c-9.248 0-16.752 7.472-16.752 16.72v252.096c0 9.248 7.504 16.688 16.752 16.688h331.504c9.248 0 16.752-7.44 16.752-16.688v-252.096z" /></font></defs></svg> \ No newline at end of file diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php deleted file mode 100644 index 9081283ffa462a2520d277f2826c088e965061c6..0000000000000000000000000000000000000000 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/AddressDetailsManagementTest.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Copyright © 2015 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Quote\Api; - -class AddressDetailsManagementTest extends \Magento\TestFramework\TestCase\WebapiAbstract -{ - const SERVICE_VERSION = 'V1'; - const SERVICE_NAME = 'quoteAddressDetailsManagementV1'; - const RESOURCE_PATH = '/V1/carts/'; - - /** - * @var \Magento\TestFramework\ObjectManager - */ - protected $objectManager; - - protected function setUp() - { - $this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); - } - - /** - * @magentoApiDataFixture Magento/Checkout/_files/quote_with_address_saved.php - */ - public function testSaveAddresses() - { - /** @var \Magento\Quote\Model\Quote $quote */ - $quote = $this->objectManager->create('Magento\Quote\Model\Quote'); - $quote->load('test_order_1', 'reserved_order_id'); - - $serviceInfo = [ - 'rest' => [ - 'resourcePath' => self::RESOURCE_PATH . 'mine/addresses', - 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST, - ], - 'soap' => [ - 'service' => self::SERVICE_NAME, - 'serviceVersion' => self::SERVICE_VERSION, - 'operation' => self::SERVICE_NAME . 'SaveAddresses', - ], - ]; - - $addressData = [ - 'firstname' => 'John', - 'lastname' => 'Smith', - 'email' => 'cat@dog.com', - 'company' => 'eBay Inc', - 'street' => ['Typical Street', 'Tiny House 18'], - 'city' => 'Big City', - 'region_id' => 12, - 'region' => 'California', - 'region_code' => 'CA', - 'postcode' => '0985432', - 'country_id' => 'US', - 'telephone' => '88776655', - 'fax' => '44332255', - ]; - $requestData = [ - 'cart_id' => $quote->getId(), - 'billingAddress' => $addressData, - 'shippingAddress' => $addressData - ]; - - $response = $this->_webApiCall($serviceInfo, $requestData); - - $this->assertArrayHasKey('shipping_methods', $response); - $this->assertCount(1, $response['shipping_methods']); - $this->assertEquals('flatrate', $response['shipping_methods'][0]['method_code']); - - $this->assertArrayHasKey('payment_methods', $response); - $this->assertCount(2, $response['payment_methods']); - $this->assertEquals('checkmo', $response['payment_methods'][0]['code']); - } -} diff --git a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php index 1380a7251302f4d63ac9f61358ecb24a6bd8643c..bef10d5a5cfb5ab0114aab0bc7e4e60d5fc4e0cc 100644 --- a/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Quote/Api/CartTotalRepositoryTest.php @@ -77,6 +77,7 @@ class CartTotalRepositoryTest extends WebapiAbstract Totals::KEY_BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(), Totals::KEY_BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(), Totals::KEY_QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(), + Totals::KEY_ITEMS_QTY => $quote->getItemsQty(), Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)], ]; @@ -85,6 +86,10 @@ class CartTotalRepositoryTest extends WebapiAbstract $data = $this->formatTotalsData($data); $actual = $this->_webApiCall($this->getServiceInfoForTotalsService($cartId), $requestData); unset($actual['items'][0]['options']); + unset($actual['weee_tax_applied_amount']); + + /** TODO: cover total segments with separate test */ + unset($actual['total_segments']); if (array_key_exists('extension_attributes', $actual)) { unset($actual['extension_attributes']); } @@ -231,12 +236,17 @@ class CartTotalRepositoryTest extends WebapiAbstract Totals::KEY_BASE_SHIPPING_INCL_TAX => $shippingAddress->getBaseShippingInclTax(), Totals::KEY_BASE_CURRENCY_CODE => $quote->getBaseCurrencyCode(), Totals::KEY_QUOTE_CURRENCY_CODE => $quote->getQuoteCurrencyCode(), + Totals::KEY_ITEMS_QTY => $quote->getItemsQty(), Totals::KEY_ITEMS => [$this->getQuoteItemTotalsData($quote)], ]; $data = $this->formatTotalsData($data); $actual = $this->_webApiCall($serviceInfo); unset($actual['items'][0]['options']); + unset($actual['weee_tax_applied_amount']); + + /** TODO: cover total segments with separate test */ + unset($actual['total_segments']); if (array_key_exists('extension_attributes', $actual)) { unset($actual['extension_attributes']); } diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2869eb4f6c6a3148ae69e322a02353addd06ab4 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Directory/Model/Country/Postcode/ValidatorTest.php @@ -0,0 +1,160 @@ +<?php +/** + * Copyright © 2015 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Directory\Model\Country\Postcode; + +use Magento\TestFramework\Helper\Bootstrap; + +class ValidatorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Directory\Model\Country\Postcode\ValidatorInterface + */ + protected $validator; + + protected function setUp() + { + $objectManager = Bootstrap::getObjectManager(); + $this->validator = $objectManager->create('Magento\Directory\Model\Country\Postcode\ValidatorInterface'); + } + + /** + * @dataProvider getPostcodesDataProvider + */ + public function testPostCodes($countryId, $validPostcode) + { + try { + $this->assertTrue($this->validator->validate($validPostcode, $countryId)); + $this->assertFalse($this->validator->validate('INVALID-100', $countryId)); + } catch (\InvalidArgumentException $ex) { + //skip validation test for none existing countryId + } + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Provided countryId does not exist. + */ + public function testPostCodesThrowsExceptionIfCountryDoesNotExist() + { + $this->validator->validate('12345', 'INVALID-CODE'); + } + + /** + * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + public function getPostcodesDataProvider() + { + return [ + ['countryId' => 'DZ', 'postcode' => '12345'], + ['countryId' => 'AS', 'postcode' => '12345'], + ['countryId' => 'AR', 'postcode' => '1234'], + ['countryId' => 'AM', 'postcode' => '123456'], + ['countryId' => 'AU', 'postcode' => '1234'], + ['countryId' => 'AT', 'postcode' => '1234'], + ['countryId' => 'AZ', 'postcode' => '1234'], + ['countryId' => 'AZ', 'postcode' => '123456'], + ['countryId' => 'BD', 'postcode' => '1234'], + ['countryId' => 'BY', 'postcode' => '123456'], + ['countryId' => 'BE', 'postcode' => '1234'], + ['countryId' => 'BA', 'postcode' => '12345'], + ['countryId' => 'BR', 'postcode' => '12345'], + ['countryId' => 'BR', 'postcode' => '12345-678'], + ['countryId' => 'BN', 'postcode' => 'PS1234'], + ['countryId' => 'BG', 'postcode' => '1234'], + ['countryId' => 'CA', 'postcode' => 'P9M 3T6'], + ['countryId' => 'IC', 'postcode' => '12345'], + ['countryId' => 'CN', 'postcode' => '123456'], + ['countryId' => 'HR', 'postcode' => '12345'], + ['countryId' => 'CU', 'postcode' => '12345'], + ['countryId' => 'CY', 'postcode' => '1234'], + ['countryId' => 'CZ', 'postcode' => '123 45'], + ['countryId' => 'DK', 'postcode' => '1234'], + ['countryId' => 'EE', 'postcode' => '12345'], + ['countryId' => 'FI', 'postcode' => '12345'], + ['countryId' => 'FR', 'postcode' => '12345'], + ['countryId' => 'GF', 'postcode' => '12345'], + ['countryId' => 'GE', 'postcode' => '1234'], + ['countryId' => 'DE', 'postcode' => '12345'], + ['countryId' => 'GR', 'postcode' => '123 45'], + ['countryId' => 'GL', 'postcode' => '1234'], + ['countryId' => 'GP', 'postcode' => '12345'], + ['countryId' => 'GU', 'postcode' => '12345'], + ['countryId' => 'GG', 'postcode' => 'PL5 7TH'], + ['countryId' => 'HU', 'postcode' => '1234'], + ['countryId' => 'IS', 'postcode' => '123'], + ['countryId' => 'IN', 'postcode' => '123456'], + ['countryId' => 'ID', 'postcode' => '12345'], + ['countryId' => 'IL', 'postcode' => '12345'], + ['countryId' => 'IT', 'postcode' => '12345'], + ['countryId' => 'JP', 'postcode' => '123-4567'], + ['countryId' => 'JP', 'postcode' => '123'], + ['countryId' => 'JE', 'postcode' => 'TY8 9PL'], + ['countryId' => 'KZ', 'postcode' => '123456'], + ['countryId' => 'KE', 'postcode' => '12345'], + ['countryId' => 'KR', 'postcode' => '123-456'], + ['countryId' => 'KG', 'postcode' => '123456'], + ['countryId' => 'LV', 'postcode' => '1234'], + ['countryId' => 'LI', 'postcode' => '1234'], + ['countryId' => 'LT', 'postcode' => '12345'], + ['countryId' => 'LU', 'postcode' => '1234'], + ['countryId' => 'MK', 'postcode' => '1234'], + ['countryId' => 'MG', 'postcode' => '123'], + ['countryId' => 'MY', 'postcode' => '12345'], + ['countryId' => 'MV', 'postcode' => '12345'], + ['countryId' => 'MV', 'postcode' => '1234'], + ['countryId' => 'MT', 'postcode' => 'WRT 123'], + ['countryId' => 'MT', 'postcode' => 'WRT 45'], + ['countryId' => 'MH', 'postcode' => '12345'], + ['countryId' => 'MQ', 'postcode' => '12345'], + ['countryId' => 'MX', 'postcode' => '12345'], + ['countryId' => 'MD', 'postcode' => '1234'], + ['countryId' => 'MC', 'postcode' => '12345'], + ['countryId' => 'MN', 'postcode' => '123456'], + ['countryId' => 'MA', 'postcode' => '12345'], + ['countryId' => 'NL', 'postcode' => '1234 TR'], + ['countryId' => 'NO', 'postcode' => '1234'], + ['countryId' => 'PK', 'postcode' => '12345'], + ['countryId' => 'PH', 'postcode' => '1234'], + ['countryId' => 'PL', 'postcode' => '12-345'], + ['countryId' => 'PT', 'postcode' => '1234'], + ['countryId' => 'PT', 'postcode' => '1234-567'], + ['countryId' => 'PR', 'postcode' => '12345'], + ['countryId' => 'RE', 'postcode' => '12345'], + ['countryId' => 'RO', 'postcode' => '123456'], + ['countryId' => 'RU', 'postcode' => '123456'], + ['countryId' => 'MP', 'postcode' => '12345'], + ['countryId' => 'CS', 'postcode' => '12345'], + ['countryId' => 'SG', 'postcode' => '123456'], + ['countryId' => 'SK', 'postcode' => '123 45'], + ['countryId' => 'SI', 'postcode' => '1234'], + ['countryId' => 'ZA', 'postcode' => '1234'], + ['countryId' => 'ES', 'postcode' => '12345'], + ['countryId' => 'XY', 'postcode' => '12345'], + ['countryId' => 'SZ', 'postcode' => 'R123'], + ['countryId' => 'SE', 'postcode' => '123 45'], + ['countryId' => 'CH', 'postcode' => '1234'], + ['countryId' => 'TW', 'postcode' => '123'], + ['countryId' => 'TW', 'postcode' => '12345'], + ['countryId' => 'TJ', 'postcode' => '123456'], + ['countryId' => 'TH', 'postcode' => '12345'], + ['countryId' => 'TR', 'postcode' => '12345'], + ['countryId' => 'TM', 'postcode' => '123456'], + ['countryId' => 'UA', 'postcode' => '12345'], + ['countryId' => 'GB', 'postcode' => 'PL12 3RT'], + ['countryId' => 'GB', 'postcode' => 'P1L 2RT'], + ['countryId' => 'GB', 'postcode' => 'QW1 2RT'], + ['countryId' => 'GB', 'postcode' => 'QW1R 2TG'], + ['countryId' => 'GB', 'postcode' => 'L12 3PL'], + ['countryId' => 'GB', 'postcode' => 'Q1 2PL'], + ['countryId' => 'US', 'postcode' => '12345-6789'], + ['countryId' => 'US', 'postcode' => '12345'], + ['countryId' => 'UY', 'postcode' => '12345'], + ['countryId' => 'UZ', 'postcode' => '123456'], + ['countryId' => 'VI', 'postcode' => '12345'], + ]; + } +} diff --git a/dev/tests/performance/benchmark.jmx b/dev/tests/performance/benchmark.jmx index 6fda461b91e00c23daa17bf64a3f578f456c5ffc..92ac0e689898c76a1dd489ec125330ad1f4d3c61 100644 --- a/dev/tests/performance/benchmark.jmx +++ b/dev/tests/performance/benchmark.jmx @@ -892,19 +892,16 @@ <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp> </ConstantTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout billing/shipping addresses" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping information" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"shippingAddress":{"company":"","fax":"","city":"Culver City","firstname":"Name","lastname":"Lastname"
 -,"street":{"0":"10441 Jefferson Blvd, ste 200","1":""},"telephone":"1-310-945-0345","postcode":"90232"
 -,"region_id":"12","country_id":"US","region":"","save_in_address_book":"1","email":"test@example.com"
 -,"same_as_billing":1},"billingAddress":{"company":"","fax":"","city":"Culver City","firstname":"Name"
 -,"lastname":"Lastname","street":{"0":"10441 Jefferson Blvd, ste 200","1":""},"telephone":"1-310-945-0345"
 -,"postcode":"90232","region_id":"12","country_id":"US","region":"","save_in_address_book":"1","email"
 -:"test@example.com","same_as_billing":1},"additionalData":{"extensionAttributes":{}}}</stringProp> + <stringProp name="Argument.value">{"addressInformation":{"shipping_address":{"countryId":"US","regionId":"12","regionCode":"CA","region"
 +:"California","street":["10441 Jefferson Blvd","ste 200"],"company":"","telephone":"1-310-945-0345","fax"
 +:"","postcode":"90232","city":"Culver City","firstname":"Firstname","lastname":"Lastname","saveInAddressBook"
 +:true},"shipping_method_code":"flatrate","shipping_carrier_code":"flatrate"}}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -915,7 +912,7 @@ <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol">http</stringProp> <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/addresses</stringProp> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/shipping-information</stringProp> <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> @@ -948,7 +945,7 @@ <hashTree/> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="-768590464">{"shipping_methods":</stringProp> + <stringProp name="-1494218646">{"payment_methods":</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> @@ -960,15 +957,17 @@ <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp> </ConstantTimer> <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout shipping/payment method" enabled="true"> + <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout payment information" enabled="true"> <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> <collectionProp name="Arguments.arguments"> <elementProp name="" elementType="HTTPArgument"> <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value">{"cartId":"${cart_id}","paymentMethod":{"method":"checkmo","po_number":null,"cc_owner"
 -:null,"cc_number":null,"cc_type":null,"cc_exp_year":null,"cc_exp_month":null,"additional_data":null}
 -,"shippingCarrierCode":"flatrate","shippingMethodCode":"flatrate"}</stringProp> + <stringProp name="Argument.value">{"cartId":"${cart_id}","paymentMethod":{"method":"checkmo","po_number":null,"cc_owner":null,"cc_number":null
 +,"cc_type":null,"cc_exp_year":null,"cc_exp_month":null,"additional_data":null},"billingAddress":{"countryId"
 +:"US","regionId":"12","regionCode":"CA","region":"California","street":["10441 Jefferson Blvd","ste 200"
 +],"company":"","telephone":"1-310-945-0345","fax":"","postcode":"90232","city":"Culver City","firstname"
 +:"Firstname","lastname":"Lastname","saveInAddressBook":true}}</stringProp> <stringProp name="Argument.metadata">=</stringProp> </elementProp> </collectionProp> @@ -979,70 +978,8 @@ <stringProp name="HTTPSampler.response_timeout"></stringProp> <stringProp name="HTTPSampler.protocol">http</stringProp> <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/collect-totals</stringProp> - <stringProp name="HTTPSampler.method">PUT</stringProp> - <boolProp name="HTTPSampler.follow_redirects">true</boolProp> - <boolProp name="HTTPSampler.auto_redirects">false</boolProp> - <boolProp name="HTTPSampler.use_keepalive">true</boolProp> - <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp> - <boolProp name="HTTPSampler.monitor">false</boolProp> - <stringProp name="HTTPSampler.embedded_url_re"></stringProp> - </HTTPSamplerProxy> - <hashTree> - <HeaderManager guiclass="HeaderPanel" testclass="HeaderManager" testname="HTTP Header Manager" enabled="true"> - <collectionProp name="HeaderManager.headers"> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Referer</stringProp> - <stringProp name="Header.value">http://mage2.com/checkout/onepage/</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Content-Type</stringProp> - <stringProp name="Header.value">application/json; charset=UTF-8 </stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">Accept</stringProp> - <stringProp name="Header.value">application/json</stringProp> - </elementProp> - <elementProp name="" elementType="Header"> - <stringProp name="Header.name">X-Requested-With</stringProp> - <stringProp name="Header.value">XMLHttpRequest</stringProp> - </elementProp> - </collectionProp> - </HeaderManager> - <hashTree/> - <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Response Assertion" enabled="true"> - <collectionProp name="Asserion.test_strings"> - <stringProp name="629313218">{"grand_total":</stringProp> - </collectionProp> - <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> - <boolProp name="Assertion.assume_success">false</boolProp> - <intProp name="Assertion.test_type">2</intProp> - </ResponseAssertion> - <hashTree/> - </hashTree> - <ConstantTimer guiclass="ConstantTimerGui" testclass="ConstantTimer" testname="Constant Timer" enabled="true"> - <stringProp name="ConstantTimer.delay">${sleep_between_steps}</stringProp> - </ConstantTimer> - <hashTree/> - <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="Checkout place order" enabled="true"> - <boolProp name="HTTPSampler.postBodyRaw">true</boolProp> - <elementProp name="HTTPsampler.Arguments" elementType="Arguments"> - <collectionProp name="Arguments.arguments"> - <elementProp name="" elementType="HTTPArgument"> - <boolProp name="HTTPArgument.always_encode">false</boolProp> - <stringProp name="Argument.value"></stringProp> - <stringProp name="Argument.metadata">=</stringProp> - </elementProp> - </collectionProp> - </elementProp> - <stringProp name="HTTPSampler.domain"></stringProp> - <stringProp name="HTTPSampler.port"></stringProp> - <stringProp name="HTTPSampler.connect_timeout"></stringProp> - <stringProp name="HTTPSampler.response_timeout"></stringProp> - <stringProp name="HTTPSampler.protocol">http</stringProp> - <stringProp name="HTTPSampler.contentEncoding">UTF-8</stringProp> - <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/order</stringProp> - <stringProp name="HTTPSampler.method">PUT</stringProp> + <stringProp name="HTTPSampler.path">${base_path}rest/default/V1/carts/mine/payment-information</stringProp> + <stringProp name="HTTPSampler.method">POST</stringProp> <boolProp name="HTTPSampler.follow_redirects">true</boolProp> <boolProp name="HTTPSampler.auto_redirects">false</boolProp> <boolProp name="HTTPSampler.use_keepalive">true</boolProp> @@ -1143,7 +1080,7 @@ <hashTree> <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="Assert success" enabled="true"> <collectionProp name="Asserion.test_strings"> - <stringProp name="890055751">You are signed out.</stringProp> + <stringProp name="1723813687">You are signed out.</stringProp> </collectionProp> <stringProp name="Assertion.test_field">Assertion.response_data</stringProp> <boolProp name="Assertion.assume_success">false</boolProp> diff --git a/lib/web/css/source/components/_modals.less b/lib/web/css/source/components/_modals.less index df5c973eef2de55b58b941178d1acf677ee0a219..a57580c88722424f70b28214ed1500e94a4ed6c0 100644 --- a/lib/web/css/source/components/_modals.less +++ b/lib/web/css/source/components/_modals.less @@ -46,6 +46,7 @@ &._show { visibility: visible; .modal-inner-wrap { + -webkit-transform: translate(0, 0); transform: translate(0, 0); } } @@ -62,6 +63,7 @@ z-index: @modal-slide__z-index; &._show { .modal-inner-wrap { + -webkit-transform: translateX(0); transform: translateX(0); } } @@ -69,9 +71,11 @@ height: 100%; overflow-y: auto; position: static; + -webkit-transform: translateX(100%); transform: translateX(100%); transition-duration: .3s; transition-timing-function: ease-in-out; + -webkit-transition-property: -webkit-transform, visibility; transition-property: transform, visibility; width: auto; } @@ -83,18 +87,24 @@ z-index: @modal-popup__z-index; &._show { .modal-inner-wrap { + -webkit-transform: translateY(0); transform: translateY(0); } } .modal-inner-wrap { + box-sizing: border-box; .vendor-prefix-display(flex); .vendor-prefix-flex-direction(column); height: auto; - margin: @modal-popup__indent-vertical (100% - @modal-popup__width) / 2; + left: 0; + right: 0; + margin: @modal-popup__indent-vertical auto; position: absolute; + -webkit-transform: translateY(-200%); transform: translateY(-200%); transition-duration: .2s; transition-timing-function: ease; + -webkit-transition-property: -webkit-transform, visibility; transition-property: transform, visibility; width: @modal-popup__width; } @@ -102,10 +112,12 @@ // -._has-modal { - height: 100vh; - overflow: hidden; - width: 100vw; +body { + &._has-modal { + height: 100%; + overflow: hidden; + width: 100%; + } } // Modals overlay @@ -156,8 +168,16 @@ // If applied, switching outer popup scroll to inner &._inner-scroll { overflow-y: visible; + .ie10 &, + .ie9 & { + overflow-y: auto; + } .modal-inner-wrap { max-height: 90%; + .ie10 &, + .ie9 & { + max-height: none; + } } .modal-content { overflow-y: auto; diff --git a/lib/web/css/source/lib/_responsive.less b/lib/web/css/source/lib/_responsive.less index 42388a0be5b45753d628afbe2cd916ea13d99a99..105a06e6b5018a5886bc496c713bd3c484a00fc2 100644 --- a/lib/web/css/source/lib/_responsive.less +++ b/lib/web/css/source/lib/_responsive.less @@ -39,6 +39,10 @@ .media-width('max', @screen__m); } + @media only screen and (max-width: @screen__m) { + .media-width('max', (@screen__m + 1)); + } + @media all and (min-width: @screen__s) { .media-width('min', @screen__s); } @@ -56,6 +60,11 @@ .media-width('min', @screen__m); } + @media all and (min-width: (@screen__m + 1)), + print { + .media-width('min', (@screen__m + 1)); + } + @media all and (min-width: @screen__l), print { .media-width('min', @screen__l); diff --git a/lib/web/css/source/lib/variables/_icons.less b/lib/web/css/source/lib/variables/_icons.less index 999e9c2cf7922b5a9acb500e499ba271a116e992..ac6e0c0c9bd0c422c4c6f3fda7cb99f30b197858 100644 --- a/lib/web/css/source/lib/variables/_icons.less +++ b/lib/web/css/source/lib/variables/_icons.less @@ -75,10 +75,11 @@ @icon-comment: '\e620'; @icon-up: '\e621'; @icon-down: '\e622'; -@icon-arrow-up-thin: '\e623'; +@icon-help: '\e623'; @icon-arrow-right-thin: '\e624'; @icon-arrow-left-thin: '\e625'; @icon-arrow-down-thin: '\e626'; @icon-account: '\e627'; @icon-gift-registry: '\e628'; @icon-present: '\e629'; +@icon-arrow-up-thin: '\e633'; diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot index 9bc3197afaa63854e2a13d3f79f31488bf1fe4db..806461187aa48e9ad6e425d4308f8f93c61fe3f4 100644 Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.eot differ diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg index 85f6bf6ddeca82ba961382a061b92c7b6da011b7..37d511d157533ea09dca32f6568390647d2540e4 100644 --- a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg +++ b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg"><defs><font id="Blank-Theme-Icons" horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64"/><missing-glyph horiz-adv-x="1024"/><glyph unicode=" " d="" horiz-adv-x="512"/><glyph unicode="" d="M676.571 637.696c-59.867 28.197-131.255 2.523-159.415-57.307-1.975-4.133-3.657-9.362-5.157-15.397-1.499 6.034-3.182 11.264-5.157 15.397-28.197 59.831-99.547 85.504-159.415 57.307-59.831-28.197-85.504-99.547-57.271-159.378 28.197-59.867 221.806-231.424 221.806-231.424s0 0.219 0.037 0.585c0.037-0.366 0.037-0.585 0.037-0.585s193.646 171.557 221.806 231.424c28.233 59.831 2.597 131.182-57.271 159.378z"/><glyph unicode="" d="M676.571 637.696c-59.831 28.197-131.218 2.523-159.451-57.307-1.938-4.133-3.657-9.362-5.157-15.397-1.463 6.034-3.182 11.264-5.157 15.397-28.16 59.831-99.547 85.504-159.378 57.307s-85.467-99.547-57.271-159.378 221.806-231.424 221.806-231.424 0 0.219 0.037 0.585c0-0.402 0-0.622 0-0.622s193.646 171.557 221.842 231.424c28.233 59.867 2.597 131.218-57.271 159.415zM690.213 479.232c-25.417-43.776-174.007-184.722-174.007-184.722l-1.573 2.999c0 0-155.465 140.398-181.211 183.991-30.61 51.822-7.753 108.946 38.949 128.439 43.52 18.176 101.888-27.319 123.502-73.143 1.499-3.182 17.627-1.463 18.798-6.107 1.134 4.645 12.727 2.926 14.226 6.107 21.577 45.824 81.042 93.989 128 72.411 46.007-21.138 66.926-72.155 33.317-129.975z"/><glyph unicode="" d="M512 704.11l-296.85-512.256h593.701l-296.85 512.256zM544.219 254.135h-62.757v49.92h62.757v-49.92zM528.713 343.369h-31.269l-20.809 140.654-1.207 72.704h72.521v-72.704l-19.237-140.654z"/><glyph unicode="" d="M628.846 588.544c-34.085 28.343-75.63 42.24-116.773 42.24-47.47 0-94.757-18.578-130.085-54.382l-32.073 29.586-0.585-102.693 110.994-0.658-39.424 41.253c25.198 24.027 58.002 36.315 91.136 36.352 29.842-0.037 59.721-9.947 84.517-30.574 31.488-26.222 47.689-63.744 47.726-101.815 0-5.449-0.366-10.971-1.024-16.457l51.383 9.874c0.073 2.231 0.146 4.425 0.146 6.619 0.037 52.37-22.491 104.521-65.938 140.654zM603.794 352.768c-25.307-24.466-58.405-37.010-91.867-37.047-29.879 0.037-59.721 9.984-84.517 30.574-31.488 26.222-47.689 63.744-47.726 101.778 0 6.327 0.475 12.617 1.353 18.871l-51.602-9.691c-0.146-3.072-0.256-6.107-0.256-9.179-0.037-52.334 22.491-104.521 65.975-140.617 34.048-28.343 75.593-42.24 116.736-42.24h0.11c47.799 0 95.378 18.907 130.743 55.223l33.938-33.829 0.219 106.094-112.055 0.293 38.949-40.229z"/><glyph unicode="" d="M696.942 624.933l-19.273 6.107h-74.496v38.583l-12.544 21.029-22.711 13.495h-111.141l-23.333-13.495-12.581-21.029v-38.619h-73.765l-18.761-6.656-17.189-14.153v-88.869h19.017v-0.073h17.554v-329.435h36.571v0.293h255.415v-0.293h36.571v329.435h18.286v0.073h18.286v86.601l-15.909 17.006zM457.435 667.575h109.129v-36.571h-109.129v36.571zM639.707 228.718h-255.415v292.571h255.415v-292.571zM676.279 557.934h-328.558v36.498h328.558v-36.498zM457.435 483.511h-36.571v-218.587h36.571v218.587zM530.578 483.511h-36.571v-218.587h36.571v218.587zM603.721 483.511h-36.571v-218.587h36.571v218.587z"/><glyph unicode="" d="M804.645 515.401c-1.499 4.681-5.888 7.899-10.789 7.899h-206.958l-64.073 196.754c-1.536 4.645-5.888 7.826-10.825 7.826-4.901 0-9.289-3.182-10.825-7.863l-64.439-196.754h-206.592c-4.901 0-9.289-3.218-10.825-7.863-1.499-4.681 0.146-9.874 4.096-12.763l167.205-121.783-64.439-197.851c-1.536-4.681 0.146-9.838 4.133-12.727 3.95-2.889 9.399-2.889 13.349 0l168.338 122.185 167.936-122.149c2.011-1.463 4.315-2.231 6.693-2.231s4.681 0.768 6.693 2.231c4.023 2.889 5.669 8.009 4.133 12.727l-64.439 197.851 167.57 121.783c3.95 2.889 5.632 8.046 4.059 12.727z"/><glyph unicode="" d="M807.241 415.854v67.145l-9.509 3.145-71.936 23.442-19.2 46.373 36.937 78.080-47.506 47.506-8.923-4.498-67.438-34.304-46.373 19.2-29.111 81.298h-67.182l-26.624-81.445-46.336-19.163-78.043 36.901-47.506-47.506 4.498-8.96 34.267-67.438-19.2-46.336-81.298-29.074v-67.218l9.472-3.072 71.973-23.515 19.163-46.373-36.901-78.080 47.506-47.506 8.887 4.498 67.474 34.304 46.373-19.2 29.111-81.298h67.182l3.072 9.509 23.515 71.936 46.373 19.2 78.080-36.937 47.506 47.506-4.498 8.923-34.304 67.438 19.2 46.373 81.298 29.147zM512 353.938c-51.968 0-94.062 42.13-94.062 94.062 0 52.005 42.094 94.062 94.062 94.062 51.931 0 94.098-42.057 94.098-94.062-0.037-51.931-42.167-94.062-94.098-94.062z"/><glyph unicode="" d="M339.602 539.941l172.398-183.881 172.398 183.881z"/><glyph unicode="" d="M606.939 449.938l-158.391 162.853-27.794-26.075 132.827-136.558-136.521-140.361 27.173-26.587 153.198 157.55-0.146 0.146z"/><glyph unicode="" d="M127.634 740.571v-73.143h768.731v73.143h-768.731zM127.634 411.429h768.731v73.143h-768.731v-73.143zM127.634 155.429h768.731v73.143h-768.731v-73.143z"/><glyph unicode="" d="M512 742.217c-102.437 0-185.417-83.054-185.417-185.454 0-102.437 185.417-403.017 185.417-403.017s185.454 300.581 185.454 403.017c-0.037 102.437-83.017 185.454-185.454 185.454zM512 500.443c-31.122 0-56.357 25.198-56.357 56.357 0 31.086 25.234 56.357 56.357 56.357 31.159 0 56.393-25.271 56.393-56.357-0.037-31.159-25.271-56.357-56.393-56.357z"/><glyph unicode="" d="M219.429 485.595h255.927v254.793h-255.927v-254.793zM548.571 740.389v-109.349h256v109.349h-256zM219.429 156.453h255.927v254.793h-255.927v-254.793zM548.571 484.754h256v109.349h-256v-109.349zM548.571 301.897h256v109.349h-256v-109.349zM548.571 155.611h256v109.349h-256v-109.349z"/><glyph unicode="" d="M579.511 677.010c-30.793 0-57.381-25.161-57.381-55.954 0-28.635 18.907-47.579 47.579-47.579 31.415 0 58.002 23.771 58.002 55.991 0 28.709-20.224 47.543-48.201 47.543zM593.518 336.494c-9.801 0-48.311-59.502-69.266-59.502-5.595 0-8.375 4.937-8.375 9.801 0 11.227 7.68 28.709 11.849 39.205l50.322 136.375c25.198 67.84-6.985 86.016-37.047 86.016-40.558 0-76.946-20.297-104.887-46.848-9.106-9.070-39.863-38.437-39.863-51.054 0-4.133 4.169-9.070 9.106-9.070 12.544 0 46.153 60.855 72.009 60.855 5.595 0 11.886-6.29 6.985-18.871l-48.896-123.173c-4.937-11.849-28.709-69.23-28.709-102.802 0-26.587 17.518-38.437 42.679-38.437 70.656 0 152.43 86.711 152.43 107.008 0 6.29-4.864 10.496-8.338 10.496z"/><glyph unicode="" d="M219.063 593.92h147.017v147.017h-147.017v-147.017zM438.491 593.92h147.017v147.017h-147.017v-147.017zM657.92 740.937v-147.017h147.017v147.017h-147.017zM219.063 374.491h147.017v147.017h-147.017v-147.017zM438.491 374.491h147.017v147.017h-147.017v-147.017zM657.92 374.491h147.017v147.017h-147.017v-147.017zM219.063 155.063h147.017v147.017h-147.017v-147.017zM438.491 155.063h147.017v147.017h-147.017v-147.017zM657.92 155.063h147.017v147.017h-147.017v-147.017z"/><glyph unicode="" d="M711.607 401.591l-5.486-5.522c21.065 27.794 32.878 60.197 32.219 94.72-1.975 99.218-106.679 177.627-233.874 175.141-127.232-2.487-228.791-84.992-226.816-184.21 1.938-99.182 106.679-177.554 233.911-175.067 28.635 0.585 50.432-5.815 75.63 2.121l159.232-78.702c-0.037-0.037-71.058 124.965-34.816 171.52z"/><glyph unicode="" d="M236.946 466.286h550.107v-36.571h-550.107v36.571z"/><glyph unicode="" d="M749.129 663.698c-152.101-93.257-262.473-210.907-312.064-269.934l-121.417 95.159-53.65-43.264 209.847-213.394c36.096 92.489 150.491 273.298 290.158 401.737l-12.873 29.696z"/><glyph unicode="" d="M434.871 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.182 0 63.707 28.489 63.707 63.671 0 35.218-28.526 63.744-63.707 63.744zM654.848 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.145 0 63.707 28.489 63.707 63.671 0 35.218-28.562 63.744-63.707 63.744zM784.274 616.741c-163.511 0-427.227 0-427.227 0s-25.929 70.071-49.957 113.371c-24.027 43.227-57.893 32.037-57.893 32.037-26.843 0-39.314-16.055-39.314-42.971 0-26.843 16.457-48.64 43.337-48.64l16.603-14.848 121.929-330.533 356.425-0.256c0 0 65.17 261.705 61.806 251.355 11.959 36.974-3.255 40.485-25.71 40.485zM392.485 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM464.933 379.392c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM502.199 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM574.647 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.177 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM611.913 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902zM684.361 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.141 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM721.627 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902z"/><glyph unicode="" d="M642.487 578.304c11.959 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.691 21.65-21.65 21.65-11.922 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.728-21.65 21.65-21.65zM381.842 578.304c11.922 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.728 21.65-21.65 21.65-11.959 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.691-21.65 21.65-21.65zM671.269 636.562v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.483-43.447-23.991 0-43.447 19.456-43.447 43.447 0 12.946 5.705 24.576 14.702 32.549v0.402h-203.154v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.447-43.447-24.027 0-43.447 19.456-43.447 43.447 0 12.946 5.669 24.576 14.665 32.549v0.402h-96.841v-440.101h511.561v440.101h-96.512zM732.087 234.569h-437.76v291.694h437.76v-291.694zM619.301 407.113h-55.15v-55.113h55.15v55.113zM619.301 490.021h-55.15v-55.113h55.15v55.113zM619.301 326.51h-55.15v-55.15h55.15v55.15zM696.942 490.021h-55.15v-55.113h55.15v55.113zM696.942 407.113h-55.15v-55.113h55.15v55.113zM386.267 326.51h-55.113v-55.15h55.113v55.15zM463.982 326.51h-55.15v-55.15h55.15v55.15zM463.982 407.113h-55.15v-55.113h55.15v55.113zM386.267 407.113h-55.113v-55.113h55.113v55.113zM541.586 407.113h-55.113v-55.113h55.113v55.113zM541.586 490.021h-55.113v-55.113h55.113v55.113zM463.982 490.021h-55.15v-55.113h55.15v55.113zM541.586 326.51h-55.113v-55.15h55.113v55.15z"/><glyph unicode="" d="M512 677.742l-209.006-253.257h136.338v-206.19h145.298v206.19h136.375z"/><glyph unicode="" d="M584.631 471.515v206.226h-145.298v-206.226h-136.338l209.006-253.221 209.006 253.221z"/><glyph unicode="" d="M836.462 183.918c0 0-109.641 112.677-153.381 156.233-19.054 19.017-32.073 31.927-32.073 31.927 14.848 21.211 26.405 44.361 34.633 69.339s12.361 51.237 12.361 78.848c0 35.621-6.802 69.083-20.334 100.462-13.568 31.305-32 58.697-55.406 82.030-23.369 23.442-50.725 41.874-82.066 55.406-31.305 13.605-64.768 20.37-100.389 20.37-35.584 0-69.047-6.802-100.425-20.37-31.305-13.531-58.551-31.963-81.664-55.406-23.077-23.296-41.435-50.688-54.967-81.993-13.568-31.378-20.334-64.841-20.334-100.462s6.802-69.083 20.334-100.389c13.531-31.305 31.89-58.661 54.967-82.103 23.113-23.333 50.322-41.801 81.664-55.369 31.378-13.568 64.841-20.297 100.425-20.297 27.648 0 53.943 4.023 78.885 12.288s48.091 19.858 69.303 34.706c0 0 11.922-11.959 29.696-29.806 48.421-48.603 155.026-159.159 155.026-159.159 16.018-6.985 41.728 0.439 54.455 11.337s19.858 33.682 9.289 52.407zM612.718 447.013c-9.838-22.747-23.223-42.569-40.155-59.429-16.933-16.933-36.718-30.354-59.429-40.192-22.638-9.874-46.848-14.775-72.521-14.775-26.258 0-50.688 4.937-73.362 14.775s-42.496 23.259-59.429 40.192c-16.896 16.859-30.354 36.681-40.155 59.429-9.838 22.601-14.738 47.104-14.738 73.289 0 25.673 4.901 50.030 14.738 72.997 9.838 22.93 23.259 42.898 40.155 59.794 16.933 16.969 36.754 30.354 59.429 40.155 22.674 9.911 47.104 14.738 73.362 14.738 25.673 0 49.883-4.864 72.521-14.738 22.674-9.801 42.496-23.186 59.429-40.155 16.933-16.933 30.318-36.901 40.155-59.831 9.874-22.967 14.738-47.323 14.738-72.997 0-26.149-4.901-50.651-14.738-73.253z"/><glyph unicode="" d="M695.845 602.661l-29.147 29.111-154.697-154.734-154.734 154.734-29.111-29.111 154.734-154.734-154.624-154.624 29.111-29.074 154.624 154.587 154.661-154.587 29.038 29.074-154.587 154.624z"/><glyph unicode="" d="M470.418 450.158l132.791 136.558-27.794 26.075-158.354-162.853 9.618-9.033-0.11-0.146 153.234-157.55 27.136 26.587z"/><glyph unicode="" d="M512 539.941l-172.398-183.881h344.795z"/><glyph unicode="" d="M392.119 622.043v-348.087l239.726 174.043z"/><glyph unicode="" d="M392.119 448l239.726-174.043v348.087z"/><glyph unicode="" d="M237.714 191.159h73.728v513.682h-73.728v-513.682zM786.286 703.086h-440.283v-292.169h440.283l-148.078 144.128 148.078 148.041z"/><glyph unicode="" d="M787.054 466.359h-256.219v256.695h-36.571v-256.695h-257.317v-36.571h257.317v-256.841h36.571v256.841h256.219z"/><glyph unicode="" d="M769.134 594.286v36.571h-513.17v-25.271l-1.097-1.097 1.097-1.097v-9.106h0.622v-292.571h-0.622v-8.558l-1.097-1.097 1.097-1.097v-25.819h513.17v36.571h-0.585v292.571h0.585zM703.89 301.714h-387.657l119.881 119.881-25.856 25.856-117.138-117.138v236.361l220.014-217.088 25.856 25.856-1.39 1.353 194.377 194.341v-245.87l-122.149 122.149-25.856-25.856 119.918-119.845zM317.221 594.286h386.158l-191.781-191.781-194.377 191.781z"/><glyph unicode="" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM604.050 355.584v-145.225h109.202v145.225h-109.202zM457.399 210.359h109.202v475.319h-109.202v-475.319z"/><glyph unicode="" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM347.941 503.625h36.864v-256.768h-36.864v256.768zM604.050 355.584v-145.225h109.202v145.225h-109.202zM677.339 246.711h-36.827v71.863h36.827v-71.863zM457.399 210.359h109.202v475.319h-109.202v-475.319zM494.263 649.838h36.827v-402.834h-36.827v402.834z"/><glyph unicode="" d="M519.57 665.893c-127.232 2.487-231.936-75.922-233.911-175.141-0.695-34.487 11.154-66.926 32.219-94.72l-5.486 5.522c36.242-46.519-34.816-171.52-34.816-171.52l159.232 78.702c25.161-7.936 46.994-1.536 75.63-2.121 127.232-2.487 231.973 75.886 233.911 175.067 2.011 99.255-99.511 181.723-226.779 184.21z"/><glyph unicode="" d="M514.158 489.582l136.558-132.791 26.075 27.794-162.853 158.354-166.729-162.743 26.587-27.136z"/><glyph unicode="" d="M509.842 406.418l-136.558 132.791-26.075-27.794 162.853-158.354 166.729 162.743-26.587 27.136z"/><glyph unicode="" d="M938.824 426.028l-0.504 106.238-426.32 426.322-426.322-426.322-0.504-106.238 389.444 389.442v-880.006h74.764v880.006z"/><glyph unicode="" d="M1.994 518.75h748.928l-283.278 291.206h200.254l354.108-363.956-354.108-363.956h-200.254l283.278 291.174h-748.928v145.532z"/><glyph unicode="" d="M1022.006 375.25h-748.928l283.278-291.206h-200.254l-354.108 363.956 354.108 363.956h200.254l-283.278-291.174h748.928v-145.532z"/><glyph unicode="" d="M85.174 468.026l0.504-106.238 426.322-426.324 426.32 426.324 0.504 106.238-389.444-389.444 0.002 880.006h-74.764v-880.004z"/><glyph unicode="" d="M511.963 831.086c-211.529 0-383.049-171.52-383.049-383.086s171.483-383.086 383.049-383.086c211.602 0 383.086 171.483 383.086 383.086s-171.483 383.086-383.086 383.086zM511.963 794.514c191.086 0 346.514-155.429 346.514-346.514 0-79.909-27.429-153.344-73.070-212.041-5.486 1.975-11.008 3.84-16.274 6.107-34.926 14.629-73.801 31.781-108.654 46.153-9.911 2.706-19.931 5.413-29.842 8.155-11.849 8.155-23.589 35.365-29.915 48.933-6.29 0.914-12.654 1.792-19.017 2.633 0.914 20.992 13.934 22.126 19.017 38.071 4.498 14.080 0.512 32.439 7.57 45.495 4.937 9.070 16.128 9.070 21.65 16.933 5.083 6.985 8.411 19.273 9.984 27.941 2.853 15.799 5.339 37.339-2.158 53.029-4.279 8.96-6.985 9.874-8.229 20.736-1.426 13.275 3.913 56.43 4.133 65.755 0.512 24.21-0.073 26.149-5.925 49.737 0 0-7.058 21.358-18.213 27.831l-22.272 3.803-13.714 12.727c-55.369 34.085-114.761 10.167-146.505-2.67-45.824-14.885-74.789-59.758-54.565-155.538 3.474-16.421-8.96-23.698-8.155-32.658 1.829-19.566 2.158-66.487 20.59-78.080 1.719-1.061 14.811-4.352 14.738-3.438 1.792-19.017 3.621-38.071 5.376-57.015 4.608-12.654 15.689-14.080 18.907-31.927l-14.153-3.438c-6.363-13.568-17.993-40.777-29.879-48.933-9.947-2.706-19.931-5.413-29.879-8.155-34.889-14.373-73.691-31.488-108.654-46.153-1.902-0.768-3.877-1.39-5.815-2.158-43.776 58.112-70.071 130.011-70.071 208.165 0 191.086 155.429 346.514 346.478 346.514z"/><glyph unicode="" d="M427.703 653.019c0-10.569-8.558-19.090-19.090-19.090h-11.154c-10.533 0-19.090 8.521-19.090 19.090v68.462c0 10.533 8.594 19.090 19.090 19.090h11.154c10.533 0 19.090-8.558 19.090-19.090v-68.462zM645.778 653.019c0-10.569-8.521-19.090-19.054-19.090h-11.154c-10.533 0-19.054 8.521-19.054 19.090v68.462c-0.037 10.533 8.485 19.090 19.054 19.090h11.154c10.533 0 19.054-8.558 19.054-19.090v-68.462zM675.182 481.317l-38.729 31.598-152.795-187.282-81.518 64.805-28.891-36.242 120.21-95.634zM758.784 687.982h-71.351v-29.769c0-31.634-25.746-57.344-57.271-57.344h-11.227c-31.598 0-57.271 25.71-57.271 57.344v29.769h-97.682v-29.769c0-31.634-25.71-57.344-57.307-57.344h-11.154c-31.598 0-57.307 25.71-57.307 57.344v29.769h-72.96c-10.533 0-19.090-8.521-19.090-19.054v-494.373c-0.037-10.569 8.558-19.127 19.090-19.127h493.531c10.533 0 19.054 8.558 19.054 19.090v494.409c0 10.533-8.521 19.054-19.054 19.054zM720.567 240.677c0-10.569-8.558-19.090-19.090-19.090h-378.917c-10.569 0-19.090 8.521-19.090 19.090v288.11c0 10.569 8.521 19.054 19.090 19.054h378.88c10.533 0 19.090-8.485 19.090-19.054v-288.11z"/><glyph unicode="" d="M391.863 554.203h-128.219c-10.35 0-18.761-8.375-18.761-18.725v-91.429c0-10.35 8.375-18.725 18.761-18.725h128.219c10.35 0 18.761 8.375 18.761 18.725v91.429c0 10.386-8.375 18.725-18.761 18.725zM391.863 387.511h-90.734c-10.35 0-18.761-8.375-18.761-18.725v-194.633c0-10.35 8.411-18.725 18.761-18.725h90.734c10.35 0 18.761 8.375 18.761 18.725v194.633c0 10.35-8.375 18.725-18.761 18.725zM760.357 554.203h-279.845c-10.35 0-18.725-8.375-18.725-18.725v-91.429c0-10.35 8.375-18.725 18.725-18.725h279.845c10.313 0 18.725 8.375 18.725 18.725v91.429c-0.037 10.386-8.411 18.725-18.725 18.725zM721.701 385.573h-240.64c-10.313 0-18.725-8.375-18.725-18.761v-192.695c0-10.35 8.375-18.725 18.725-18.725h240.64c10.35 0 18.725 8.375 18.725 18.725v192.695c0 10.35-8.375 18.761-18.725 18.761zM507.355 575.634c21.87-3.986 42.971-6.327 62.647-6.327 99.072 0 152.832 53.248 153.088 103.387 0.183 32.293-23.698 67.291-78.117 67.84-72.923 0-118.089-51.493-141.605-89.71-23.918 38.107-69.266 88.576-142.373 88.576-52.882-0.549-76.763-35.547-76.581-67.84 0.256-50.139 54.016-103.424 153.088-103.424 0.037 0 0.037 0 0.037 0 21.394 0 44.398 2.414 68.425 7.241l1.39 0.256zM645.998 693.723c9.143-0.073 30.354-2.304 30.245-20.773-0.11-23.589-33.17-56.795-106.24-56.795-10.057 0-20.553 0.658-31.525 1.938 16.567 29.294 51.566 75.63 107.52 75.63zM437.504 614.985v0c-73.106 0-106.167 33.207-106.277 56.795-0.11 18.469 21.102 20.699 31.305 20.809 55.259 0 90.039-46.373 106.496-75.666-10.935-1.28-21.467-1.938-31.525-1.938z"/></font></defs></svg> +<svg xmlns="http://www.w3.org/2000/svg"><defs><font horiz-adv-x="1024"><font-face units-per-em="1024" ascent="960" descent="-64" /><missing-glyph horiz-adv-x="1024" /><glyph unicode=" " d="" horiz-adv-x="512" /><glyph unicode="" d="M676.571 637.696c-59.867 28.197-131.255 2.523-159.415-57.307-1.975-4.133-3.657-9.362-5.157-15.397-1.499 6.034-3.182 11.264-5.157 15.397-28.197 59.831-99.547 85.504-159.415 57.307-59.831-28.197-85.504-99.547-57.271-159.378 28.197-59.867 221.806-231.424 221.806-231.424s0 0.219 0.037 0.585c0.037-0.366 0.037-0.585 0.037-0.585s193.646 171.557 221.806 231.424c28.233 59.831 2.597 131.182-57.271 159.378z" /><glyph unicode="" d="M676.571 637.696c-59.831 28.197-131.218 2.523-159.451-57.307-1.938-4.133-3.657-9.362-5.157-15.397-1.463 6.034-3.182 11.264-5.157 15.397-28.16 59.831-99.547 85.504-159.378 57.307s-85.467-99.547-57.271-159.378 221.806-231.424 221.806-231.424 0 0.219 0.037 0.585c0-0.402 0-0.622 0-0.622s193.646 171.557 221.842 231.424c28.233 59.867 2.597 131.218-57.271 159.415zM690.213 479.232c-25.417-43.776-174.007-184.722-174.007-184.722l-1.573 2.999c0 0-155.465 140.398-181.211 183.991-30.61 51.822-7.753 108.946 38.949 128.439 43.52 18.176 101.888-27.319 123.502-73.143 1.499-3.182 17.627-1.463 18.798-6.107 1.134 4.645 12.727 2.926 14.226 6.107 21.577 45.824 81.042 93.989 128 72.411 46.007-21.138 66.926-72.155 33.317-129.975z" /><glyph unicode="" d="M512 704.11l-296.85-512.256h593.701l-296.85 512.256zM544.219 254.135h-62.757v49.92h62.757v-49.92zM528.713 343.369h-31.269l-20.809 140.654-1.207 72.704h72.521v-72.704l-19.237-140.654z" /><glyph unicode="" d="M628.846 588.544c-34.085 28.343-75.63 42.24-116.773 42.24-47.47 0-94.757-18.578-130.085-54.382l-32.073 29.586-0.585-102.693 110.994-0.658-39.424 41.253c25.198 24.027 58.002 36.315 91.136 36.352 29.842-0.037 59.721-9.947 84.517-30.574 31.488-26.222 47.689-63.744 47.726-101.815 0-5.449-0.366-10.971-1.024-16.457l51.383 9.874c0.073 2.231 0.146 4.425 0.146 6.619 0.037 52.37-22.491 104.521-65.938 140.654zM603.794 352.768c-25.307-24.466-58.405-37.010-91.867-37.047-29.879 0.037-59.721 9.984-84.517 30.574-31.488 26.222-47.689 63.744-47.726 101.778 0 6.327 0.475 12.617 1.353 18.871l-51.602-9.691c-0.146-3.072-0.256-6.107-0.256-9.179-0.037-52.334 22.491-104.521 65.975-140.617 34.048-28.343 75.593-42.24 116.736-42.24h0.11c47.799 0 95.378 18.907 130.743 55.223l33.938-33.829 0.219 106.094-112.055 0.293 38.949-40.229z" /><glyph unicode="" d="M696.942 624.933l-19.273 6.107h-74.496v38.583l-12.544 21.029-22.711 13.495h-111.141l-23.333-13.495-12.581-21.029v-38.619h-73.765l-18.761-6.656-17.189-14.153v-88.869h19.017v-0.073h17.554v-329.435h36.571v0.293h255.415v-0.293h36.571v329.435h18.286v0.073h18.286v86.601l-15.909 17.006zM457.435 667.575h109.129v-36.571h-109.129v36.571zM639.707 228.718h-255.415v292.571h255.415v-292.571zM676.279 557.934h-328.558v36.498h328.558v-36.498zM457.435 483.511h-36.571v-218.587h36.571v218.587zM530.578 483.511h-36.571v-218.587h36.571v218.587zM603.721 483.511h-36.571v-218.587h36.571v218.587z" /><glyph unicode="" d="M804.645 515.401c-1.499 4.681-5.888 7.899-10.789 7.899h-206.958l-64.073 196.754c-1.536 4.645-5.888 7.826-10.825 7.826-4.901 0-9.289-3.182-10.825-7.863l-64.439-196.754h-206.592c-4.901 0-9.289-3.218-10.825-7.863-1.499-4.681 0.146-9.874 4.096-12.763l167.205-121.783-64.439-197.851c-1.536-4.681 0.146-9.838 4.133-12.727 3.95-2.889 9.399-2.889 13.349 0l168.338 122.185 167.936-122.149c2.011-1.463 4.315-2.231 6.693-2.231s4.681 0.768 6.693 2.231c4.023 2.889 5.669 8.009 4.133 12.727l-64.439 197.851 167.57 121.783c3.95 2.889 5.632 8.046 4.059 12.727z" /><glyph unicode="" d="M807.241 415.854v67.145l-9.509 3.145-71.936 23.442-19.2 46.373 36.937 78.080-47.506 47.506-8.923-4.498-67.438-34.304-46.373 19.2-29.111 81.298h-67.182l-26.624-81.445-46.336-19.163-78.043 36.901-47.506-47.506 4.498-8.96 34.267-67.438-19.2-46.336-81.298-29.074v-67.218l9.472-3.072 71.973-23.515 19.163-46.373-36.901-78.080 47.506-47.506 8.887 4.498 67.474 34.304 46.373-19.2 29.111-81.298h67.182l3.072 9.509 23.515 71.936 46.373 19.2 78.080-36.937 47.506 47.506-4.498 8.923-34.304 67.438 19.2 46.373 81.298 29.147zM512 353.938c-51.968 0-94.062 42.13-94.062 94.062 0 52.005 42.094 94.062 94.062 94.062 51.931 0 94.098-42.057 94.098-94.062-0.037-51.931-42.167-94.062-94.098-94.062z" /><glyph unicode="" d="M339.602 539.941l172.398-183.881 172.398 183.881z" /><glyph unicode="" d="M606.939 449.938l-158.391 162.853-27.794-26.075 132.827-136.558-136.521-140.361 27.173-26.587 153.198 157.55-0.146 0.146z" /><glyph unicode="" d="M127.634 740.571v-73.143h768.731v73.143h-768.731zM127.634 411.429h768.731v73.143h-768.731v-73.143zM127.634 155.429h768.731v73.143h-768.731v-73.143z" /><glyph unicode="" d="M512 742.217c-102.437 0-185.417-83.054-185.417-185.454 0-102.437 185.417-403.017 185.417-403.017s185.454 300.581 185.454 403.017c-0.037 102.437-83.017 185.454-185.454 185.454zM512 500.443c-31.122 0-56.357 25.198-56.357 56.357 0 31.086 25.234 56.357 56.357 56.357 31.159 0 56.393-25.271 56.393-56.357-0.037-31.159-25.271-56.357-56.393-56.357z" /><glyph unicode="" d="M219.429 485.595h255.927v254.793h-255.927v-254.793zM548.571 740.389v-109.349h256v109.349h-256zM219.429 156.453h255.927v254.793h-255.927v-254.793zM548.571 484.754h256v109.349h-256v-109.349zM548.571 301.897h256v109.349h-256v-109.349zM548.571 155.611h256v109.349h-256v-109.349z" /><glyph unicode="" d="M579.511 677.010c-30.793 0-57.381-25.161-57.381-55.954 0-28.635 18.907-47.579 47.579-47.579 31.415 0 58.002 23.771 58.002 55.991 0 28.709-20.224 47.543-48.201 47.543zM593.518 336.494c-9.801 0-48.311-59.502-69.266-59.502-5.595 0-8.375 4.937-8.375 9.801 0 11.227 7.68 28.709 11.849 39.205l50.322 136.375c25.198 67.84-6.985 86.016-37.047 86.016-40.558 0-76.946-20.297-104.887-46.848-9.106-9.070-39.863-38.437-39.863-51.054 0-4.133 4.169-9.070 9.106-9.070 12.544 0 46.153 60.855 72.009 60.855 5.595 0 11.886-6.29 6.985-18.871l-48.896-123.173c-4.937-11.849-28.709-69.23-28.709-102.802 0-26.587 17.518-38.437 42.679-38.437 70.656 0 152.43 86.711 152.43 107.008 0 6.29-4.864 10.496-8.338 10.496z" /><glyph unicode="" d="M219.063 593.92h147.017v147.017h-147.017v-147.017zM438.491 593.92h147.017v147.017h-147.017v-147.017zM657.92 740.937v-147.017h147.017v147.017h-147.017zM219.063 374.491h147.017v147.017h-147.017v-147.017zM438.491 374.491h147.017v147.017h-147.017v-147.017zM657.92 374.491h147.017v147.017h-147.017v-147.017zM219.063 155.063h147.017v147.017h-147.017v-147.017zM438.491 155.063h147.017v147.017h-147.017v-147.017zM657.92 155.063h147.017v147.017h-147.017v-147.017z" /><glyph unicode="" d="M711.607 401.591l-5.486-5.522c21.065 27.794 32.878 60.197 32.219 94.72-1.975 99.218-106.679 177.627-233.874 175.141-127.232-2.487-228.791-84.992-226.816-184.21 1.938-99.182 106.679-177.554 233.911-175.067 28.635 0.585 50.432-5.815 75.63 2.121l159.232-78.702c-0.037-0.037-71.058 124.965-34.816 171.52z" /><glyph unicode="" d="M236.946 466.286h550.107v-36.571h-550.107v36.571z" /><glyph unicode="" d="M749.129 663.698c-152.101-93.257-262.473-210.907-312.064-269.934l-121.417 95.159-53.65-43.264 209.847-213.394c36.096 92.489 150.491 273.298 290.158 401.737l-12.873 29.696z" /><glyph unicode="" d="M434.871 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.182 0 63.707 28.489 63.707 63.671 0 35.218-28.526 63.744-63.707 63.744zM654.848 259.95c-35.218 0-63.707-28.526-63.707-63.744 0-35.182 28.489-63.671 63.707-63.671 35.145 0 63.707 28.489 63.707 63.671 0 35.218-28.562 63.744-63.707 63.744zM784.274 616.741c-163.511 0-427.227 0-427.227 0s-25.929 70.071-49.957 113.371c-24.027 43.227-57.893 32.037-57.893 32.037-26.843 0-39.314-16.055-39.314-42.971 0-26.843 16.457-48.64 43.337-48.64l16.603-14.848 121.929-330.533 356.425-0.256c0 0 65.17 261.705 61.806 251.355 11.959 36.974-3.255 40.485-25.71 40.485zM392.485 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM464.933 379.392c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM502.199 492.544c-18.725 0-33.902 15.177-33.902 33.902s15.177 33.902 33.902 33.902 33.902-15.177 33.902-33.902-15.177-33.902-33.902-33.902zM574.647 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.177 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM611.913 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902zM684.361 379.392c-18.725 0-33.865 15.177-33.865 33.902s15.141 33.902 33.865 33.902 33.938-15.177 33.938-33.902-15.214-33.902-33.938-33.902zM721.627 492.544c-18.725 0-33.938 15.177-33.938 33.902s15.214 33.902 33.938 33.902 33.865-15.177 33.865-33.902-15.141-33.902-33.865-33.902z" /><glyph unicode="" d="M642.487 578.304c11.959 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.691 21.65-21.65 21.65-11.922 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.728-21.65 21.65-21.65zM381.842 578.304c11.922 0 21.65 9.691 21.65 21.65v77.934c0 11.959-9.728 21.65-21.65 21.65-11.959 0-21.65-9.691-21.65-21.65v-77.934c0.037-11.959 9.691-21.65 21.65-21.65zM671.269 636.562v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.483-43.447-23.991 0-43.447 19.456-43.447 43.447 0 12.946 5.705 24.576 14.702 32.549v0.402h-203.154v-0.402c8.997-7.973 14.702-19.566 14.702-32.549 0-23.991-19.456-43.447-43.447-43.447-24.027 0-43.447 19.456-43.447 43.447 0 12.946 5.669 24.576 14.665 32.549v0.402h-96.841v-440.101h511.561v440.101h-96.512zM732.087 234.569h-437.76v291.694h437.76v-291.694zM619.301 407.113h-55.15v-55.113h55.15v55.113zM619.301 490.021h-55.15v-55.113h55.15v55.113zM619.301 326.51h-55.15v-55.15h55.15v55.15zM696.942 490.021h-55.15v-55.113h55.15v55.113zM696.942 407.113h-55.15v-55.113h55.15v55.113zM386.267 326.51h-55.113v-55.15h55.113v55.15zM463.982 326.51h-55.15v-55.15h55.15v55.15zM463.982 407.113h-55.15v-55.113h55.15v55.113zM386.267 407.113h-55.113v-55.113h55.113v55.113zM541.586 407.113h-55.113v-55.113h55.113v55.113zM541.586 490.021h-55.113v-55.113h55.113v55.113zM463.982 490.021h-55.15v-55.113h55.15v55.113zM541.586 326.51h-55.113v-55.15h55.113v55.15z" /><glyph unicode="" d="M512 677.742l-209.006-253.257h136.338v-206.19h145.298v206.19h136.375z" /><glyph unicode="" d="M584.631 471.515v206.226h-145.298v-206.226h-136.338l209.006-253.221 209.006 253.221z" /><glyph unicode="" d="M836.462 183.918c0 0-109.641 112.677-153.381 156.233-19.054 19.017-32.073 31.927-32.073 31.927 14.848 21.211 26.405 44.361 34.633 69.339s12.361 51.237 12.361 78.848c0 35.621-6.802 69.083-20.334 100.462-13.568 31.305-32 58.697-55.406 82.030-23.369 23.442-50.725 41.874-82.066 55.406-31.305 13.605-64.768 20.37-100.389 20.37-35.584 0-69.047-6.802-100.425-20.37-31.305-13.531-58.551-31.963-81.664-55.406-23.077-23.296-41.435-50.688-54.967-81.993-13.568-31.378-20.334-64.841-20.334-100.462s6.802-69.083 20.334-100.389c13.531-31.305 31.89-58.661 54.967-82.103 23.113-23.333 50.322-41.801 81.664-55.369 31.378-13.568 64.841-20.297 100.425-20.297 27.648 0 53.943 4.023 78.885 12.288s48.091 19.858 69.303 34.706c0 0 11.922-11.959 29.696-29.806 48.421-48.603 155.026-159.159 155.026-159.159 16.018-6.985 41.728 0.439 54.455 11.337s19.858 33.682 9.289 52.407zM612.718 447.013c-9.838-22.747-23.223-42.569-40.155-59.429-16.933-16.933-36.718-30.354-59.429-40.192-22.638-9.874-46.848-14.775-72.521-14.775-26.258 0-50.688 4.937-73.362 14.775s-42.496 23.259-59.429 40.192c-16.896 16.859-30.354 36.681-40.155 59.429-9.838 22.601-14.738 47.104-14.738 73.289 0 25.673 4.901 50.030 14.738 72.997 9.838 22.93 23.259 42.898 40.155 59.794 16.933 16.969 36.754 30.354 59.429 40.155 22.674 9.911 47.104 14.738 73.362 14.738 25.673 0 49.883-4.864 72.521-14.738 22.674-9.801 42.496-23.186 59.429-40.155 16.933-16.933 30.318-36.901 40.155-59.831 9.874-22.967 14.738-47.323 14.738-72.997 0-26.149-4.901-50.651-14.738-73.253z" /><glyph unicode="" d="M695.845 602.661l-29.147 29.111-154.697-154.734-154.734 154.734-29.111-29.111 154.734-154.734-154.624-154.624 29.111-29.074 154.624 154.587 154.661-154.587 29.038 29.074-154.587 154.624z" /><glyph unicode="" d="M470.418 450.158l132.791 136.558-27.794 26.075-158.354-162.853 9.618-9.033-0.11-0.146 153.234-157.55 27.136 26.587z" /><glyph unicode="" d="M512 539.941l-172.398-183.881h344.795z" /><glyph unicode="" d="M392.119 622.043v-348.087l239.726 174.043z" /><glyph unicode="" d="M392.119 448l239.726-174.043v348.087z" /><glyph unicode="" d="M237.714 191.159h73.728v513.682h-73.728v-513.682zM786.286 703.086h-440.283v-292.169h440.283l-148.078 144.128 148.078 148.041z" /><glyph unicode="" d="M787.054 466.359h-256.219v256.695h-36.571v-256.695h-257.317v-36.571h257.317v-256.841h36.571v256.841h256.219z" /><glyph unicode="" d="M769.134 594.286v36.571h-513.17v-25.271l-1.097-1.097 1.097-1.097v-9.106h0.622v-292.571h-0.622v-8.558l-1.097-1.097 1.097-1.097v-25.819h513.17v36.571h-0.585v292.571h0.585zM703.89 301.714h-387.657l119.881 119.881-25.856 25.856-117.138-117.138v236.361l220.014-217.088 25.856 25.856-1.39 1.353 194.377 194.341v-245.87l-122.149 122.149-25.856-25.856 119.918-119.845zM317.221 594.286h386.158l-191.781-191.781-194.377 191.781z" /><glyph unicode="" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM604.050 355.584v-145.225h109.202v145.225h-109.202zM457.399 210.359h109.202v475.319h-109.202v-475.319z" /><glyph unicode="" d="M310.747 210.359h109.166v328.485h-109.166v-328.485zM347.941 503.625h36.864v-256.768h-36.864v256.768zM604.050 355.584v-145.225h109.202v145.225h-109.202zM677.339 246.711h-36.827v71.863h36.827v-71.863zM457.399 210.359h109.202v475.319h-109.202v-475.319zM494.263 649.838h36.827v-402.834h-36.827v402.834z" /><glyph unicode="" d="M519.57 665.893c-127.232 2.487-231.936-75.922-233.911-175.141-0.695-34.487 11.154-66.926 32.219-94.72l-5.486 5.522c36.242-46.519-34.816-171.52-34.816-171.52l159.232 78.702c25.161-7.936 46.994-1.536 75.63-2.121 127.232-2.487 231.973 75.886 233.911 175.067 2.011 99.255-99.511 181.723-226.779 184.21z" /><glyph unicode="" d="M514.158 489.582l136.558-132.791 26.075 27.794-162.853 158.354-166.729-162.743 26.587-27.136z" /><glyph unicode="" d="M509.842 406.418l-136.558 132.791-26.075-27.794 162.853-158.354 166.729 162.743-26.587 27.136z" /><glyph unicode="" d="M512 52.005c-218.77 0-396.032 177.298-396.032 395.995s177.262 395.995 396.032 395.995c218.661 0 396.032-177.298 396.032-395.995s-177.371-395.995-396.032-395.995zM512 796.087c-191.89 0-348.087-156.197-348.087-348.087 0-191.927 156.197-348.087 348.087-348.087s348.050 156.16 348.050 348.087c-0.037 191.927-156.16 348.087-348.050 348.087zM611.328 442.441l-24.101-18.761c-13.166-10.24-21.87-22.126-26.185-35.84-2.743-8.558-4.681-18.907-4.901-37.12h-92.343c1.353 38.473 5.413 61.842 11.301 76.581 5.925 14.592 21.102 31.488 45.531 50.578l24.795 19.383c8.192 6.181 14.738 12.91 19.785 20.187 8.997 12.471 13.495 26.222 13.495 41.216 0 17.262-5.010 32.987-15.104 47.214-10.057 14.226-28.453 21.321-55.259 21.321-26.295 0-44.946-8.777-55.918-26.295s-16.384-33.463-16.384-52.37h-98.523c2.706 64.805 25.234 108.544 67.73 135.57 26.843 17.298 59.794 25.929 98.889 25.929 51.383 0 94.025-12.288 128-36.827 34.011-24.503 53.87-74.935 53.87-123.173 0-29.55-10.24-40.338-25.051-60.599-8.558-12.288-25.125-27.941-49.627-46.994zM561.042 202.423h-98.231v98.487h98.231v-98.487z" /><glyph unicode="" d="M1.994 518.75h748.928l-283.278 291.206h200.254l354.108-363.956-354.108-363.956h-200.254l283.278 291.174h-748.928v145.532z" /><glyph unicode="" d="M1022.006 375.25h-748.928l283.278-291.206h-200.254l-354.108 363.956 354.108 363.956h200.254l-283.278-291.174h748.928v-145.532z" /><glyph unicode="" d="M85.174 468.026l0.504-106.238 426.322-426.324 426.32 426.324 0.504 106.238-389.444-389.444 0.002 880.006h-74.764v-880.004z" /><glyph unicode="" d="M511.963 831.086c-211.529 0-383.049-171.52-383.049-383.086s171.483-383.086 383.049-383.086c211.602 0 383.086 171.483 383.086 383.086s-171.483 383.086-383.086 383.086zM511.963 794.514c191.086 0 346.514-155.429 346.514-346.514 0-79.909-27.429-153.344-73.070-212.041-5.486 1.975-11.008 3.84-16.274 6.107-34.926 14.629-73.801 31.781-108.654 46.153-9.911 2.706-19.931 5.413-29.842 8.155-11.849 8.155-23.589 35.365-29.915 48.933-6.29 0.914-12.654 1.792-19.017 2.633 0.914 20.992 13.934 22.126 19.017 38.071 4.498 14.080 0.512 32.439 7.57 45.495 4.937 9.070 16.128 9.070 21.65 16.933 5.083 6.985 8.411 19.273 9.984 27.941 2.853 15.799 5.339 37.339-2.158 53.029-4.279 8.96-6.985 9.874-8.229 20.736-1.426 13.275 3.913 56.43 4.133 65.755 0.512 24.21-0.073 26.149-5.925 49.737 0 0-7.058 21.358-18.213 27.831l-22.272 3.803-13.714 12.727c-55.369 34.085-114.761 10.167-146.505-2.67-45.824-14.885-74.789-59.758-54.565-155.538 3.474-16.421-8.96-23.698-8.155-32.658 1.829-19.566 2.158-66.487 20.59-78.080 1.719-1.061 14.811-4.352 14.738-3.438 1.792-19.017 3.621-38.071 5.376-57.015 4.608-12.654 15.689-14.080 18.907-31.927l-14.153-3.438c-6.363-13.568-17.993-40.777-29.879-48.933-9.947-2.706-19.931-5.413-29.879-8.155-34.889-14.373-73.691-31.488-108.654-46.153-1.902-0.768-3.877-1.39-5.815-2.158-43.776 58.112-70.071 130.011-70.071 208.165 0 191.086 155.429 346.514 346.478 346.514z" /><glyph unicode="" d="M427.703 653.019c0-10.569-8.558-19.090-19.090-19.090h-11.154c-10.533 0-19.090 8.521-19.090 19.090v68.462c0 10.533 8.594 19.090 19.090 19.090h11.154c10.533 0 19.090-8.558 19.090-19.090v-68.462zM645.778 653.019c0-10.569-8.521-19.090-19.054-19.090h-11.154c-10.533 0-19.054 8.521-19.054 19.090v68.462c-0.037 10.533 8.485 19.090 19.054 19.090h11.154c10.533 0 19.054-8.558 19.054-19.090v-68.462zM675.182 481.317l-38.729 31.598-152.795-187.282-81.518 64.805-28.891-36.242 120.21-95.634zM758.784 687.982h-71.351v-29.769c0-31.634-25.746-57.344-57.271-57.344h-11.227c-31.598 0-57.271 25.71-57.271 57.344v29.769h-97.682v-29.769c0-31.634-25.71-57.344-57.307-57.344h-11.154c-31.598 0-57.307 25.71-57.307 57.344v29.769h-72.96c-10.533 0-19.090-8.521-19.090-19.054v-494.373c-0.037-10.569 8.558-19.127 19.090-19.127h493.531c10.533 0 19.054 8.558 19.054 19.090v494.409c0 10.533-8.521 19.054-19.054 19.054zM720.567 240.677c0-10.569-8.558-19.090-19.090-19.090h-378.917c-10.569 0-19.090 8.521-19.090 19.090v288.11c0 10.569 8.521 19.054 19.090 19.054h378.88c10.533 0 19.090-8.485 19.090-19.054v-288.11z" /><glyph unicode="" d="M391.863 554.203h-128.219c-10.35 0-18.761-8.375-18.761-18.725v-91.429c0-10.35 8.375-18.725 18.761-18.725h128.219c10.35 0 18.761 8.375 18.761 18.725v91.429c0 10.386-8.375 18.725-18.761 18.725zM391.863 387.511h-90.734c-10.35 0-18.761-8.375-18.761-18.725v-194.633c0-10.35 8.411-18.725 18.761-18.725h90.734c10.35 0 18.761 8.375 18.761 18.725v194.633c0 10.35-8.375 18.725-18.761 18.725zM760.357 554.203h-279.845c-10.35 0-18.725-8.375-18.725-18.725v-91.429c0-10.35 8.375-18.725 18.725-18.725h279.845c10.313 0 18.725 8.375 18.725 18.725v91.429c-0.037 10.386-8.411 18.725-18.725 18.725zM721.701 385.573h-240.64c-10.313 0-18.725-8.375-18.725-18.761v-192.695c0-10.35 8.375-18.725 18.725-18.725h240.64c10.35 0 18.725 8.375 18.725 18.725v192.695c0 10.35-8.375 18.761-18.725 18.761zM507.355 575.634c21.87-3.986 42.971-6.327 62.647-6.327 99.072 0 152.832 53.248 153.088 103.387 0.183 32.293-23.698 67.291-78.117 67.84-72.923 0-118.089-51.493-141.605-89.71-23.918 38.107-69.266 88.576-142.373 88.576-52.882-0.549-76.763-35.547-76.581-67.84 0.256-50.139 54.016-103.424 153.088-103.424 0.037 0 0.037 0 0.037 0 21.394 0 44.398 2.414 68.425 7.241l1.39 0.256zM645.998 693.723c9.143-0.073 30.354-2.304 30.245-20.773-0.11-23.589-33.17-56.795-106.24-56.795-10.057 0-20.553 0.658-31.525 1.938 16.567 29.294 51.566 75.63 107.52 75.63zM437.504 614.985v0c-73.106 0-106.167 33.207-106.277 56.795-0.11 18.469 21.102 20.699 31.305 20.809 55.259 0 90.039-46.373 106.496-75.666-10.935-1.28-21.467-1.938-31.525-1.938z" /><glyph unicode="" d="M938.824 426.028l-0.504 106.238-426.32 426.322-426.322-426.322-0.504-106.238 389.444 389.442v-880.006h74.764v880.006z" /></font></defs></svg> \ No newline at end of file diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf index eaec02d1df42b6b0208db02f1da2a3fb3bcae7fd..6fabe5c3e89948ff20801ea1e43e18b15c9c4da1 100644 Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.ttf differ diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff index e9e8395b2574bc6cfbb3c2606213ca204179bf51..a8e688940c486205bcbc8bb9b787af33c1a8db86 100644 Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff differ diff --git a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 index 1d60f2f95c0facb689b7a0079cfb2b2312bcab17..e1fc31afbdaf56fd0fc3cfb09180f52be6f1b569 100644 Binary files a/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 and b/lib/web/fonts/Blank-Theme-Icons/Blank-Theme-Icons.woff2 differ diff --git a/lib/web/fonts/Blank-Theme-Icons/selection.json b/lib/web/fonts/Blank-Theme-Icons/selection.json index e3a71a30c6ae96426ed01b4041c20ae392e1e909..2e8beab777f8a696acbbbb6d6b4ce523f9d2f481 100644 --- a/lib/web/fonts/Blank-Theme-Icons/selection.json +++ b/lib/web/fonts/Blank-Theme-Icons/selection.json @@ -1,6 +1,34 @@ { "IcoMoonType": "selection", "icons": [ + { + "icon": { + "paths": [ + "M512 907.995c-218.77 0-396.032-177.298-396.032-395.995s177.262-395.995 396.032-395.995c218.661 0 396.032 177.298 396.032 395.995s-177.371 395.995-396.032 395.995zM512 163.913c-191.89 0-348.087 156.197-348.087 348.087 0 191.927 156.197 348.087 348.087 348.087s348.050-156.16 348.050-348.087c-0.037-191.927-156.16-348.087-348.050-348.087zM611.328 517.559l-24.101 18.761c-13.166 10.24-21.87 22.126-26.185 35.84-2.743 8.558-4.681 18.907-4.901 37.12h-92.343c1.353-38.473 5.413-61.842 11.301-76.581 5.925-14.592 21.102-31.488 45.531-50.578l24.795-19.383c8.192-6.181 14.738-12.91 19.785-20.187 8.997-12.471 13.495-26.222 13.495-41.216 0-17.262-5.010-32.987-15.104-47.214-10.057-14.226-28.453-21.321-55.259-21.321-26.295 0-44.946 8.777-55.918 26.295s-16.384 33.463-16.384 52.37h-98.523c2.706-64.805 25.234-108.544 67.73-135.57 26.843-17.298 59.794-25.929 98.889-25.929 51.383 0 94.025 12.288 128 36.827 34.011 24.503 53.87 74.935 53.87 123.173 0 29.55-10.24 40.338-25.051 60.599-8.558 12.288-25.125 27.941-49.627 46.994zM561.042 757.577h-98.231v-98.487h98.231v98.487z" + ], + "attrs": [ + {} + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "help" + ] + }, + "attrs": [ + {} + ], + "properties": { + "order": 44, + "id": 37, + "prevSize": 32, + "code": 58915, + "name": "help" + }, + "setIdx": 0, + "setId": 1, + "iconIdx": 0 + }, { "icon": { "paths": [ @@ -36,7 +64,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 0 + "iconIdx": 1 }, { "icon": { @@ -76,7 +104,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 1 + "iconIdx": 2 }, { "icon": { @@ -100,7 +128,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 2 + "iconIdx": 3 }, { "icon": { @@ -118,13 +146,13 @@ "order": 36, "id": 3, "prevSize": 32, - "code": 58915, + "code": 58931, "name": "arrow-up-thin", "ligatures": "" }, "setIdx": 0, "setId": 1, - "iconIdx": 3 + "iconIdx": 4 }, { "icon": { @@ -148,7 +176,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 4 + "iconIdx": 5 }, { "icon": { @@ -172,7 +200,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 5 + "iconIdx": 6 }, { "icon": { @@ -196,7 +224,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 6 + "iconIdx": 7 }, { "icon": { @@ -220,7 +248,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 7 + "iconIdx": 8 }, { "icon": { @@ -244,7 +272,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 8 + "iconIdx": 9 }, { "icon": { @@ -268,7 +296,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 9 + "iconIdx": 10 }, { "icon": { @@ -292,7 +320,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 10 + "iconIdx": 11 }, { "icon": { @@ -316,7 +344,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 11 + "iconIdx": 12 }, { "icon": { @@ -340,7 +368,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 12 + "iconIdx": 13 }, { "icon": { @@ -364,7 +392,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 13 + "iconIdx": 14 }, { "icon": { @@ -388,7 +416,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 14 + "iconIdx": 15 }, { "icon": { @@ -412,7 +440,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 15 + "iconIdx": 16 }, { "icon": { @@ -436,7 +464,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 16 + "iconIdx": 17 }, { "icon": { @@ -460,7 +488,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 17 + "iconIdx": 18 }, { "icon": { @@ -484,7 +512,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 18 + "iconIdx": 19 }, { "icon": { @@ -508,7 +536,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 19 + "iconIdx": 20 }, { "icon": { @@ -532,7 +560,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 20 + "iconIdx": 21 }, { "icon": { @@ -556,7 +584,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 21 + "iconIdx": 22 }, { "icon": { @@ -580,7 +608,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 22 + "iconIdx": 23 }, { "icon": { @@ -604,7 +632,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 23 + "iconIdx": 24 }, { "icon": { @@ -628,7 +656,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 24 + "iconIdx": 25 }, { "icon": { @@ -652,7 +680,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 25 + "iconIdx": 26 }, { "icon": { @@ -676,7 +704,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 26 + "iconIdx": 27 }, { "icon": { @@ -700,7 +728,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 27 + "iconIdx": 28 }, { "icon": { @@ -724,7 +752,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 28 + "iconIdx": 29 }, { "icon": { @@ -748,7 +776,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 29 + "iconIdx": 30 }, { "icon": { @@ -772,7 +800,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 30 + "iconIdx": 31 }, { "icon": { @@ -796,7 +824,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 31 + "iconIdx": 32 }, { "icon": { @@ -820,7 +848,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 32 + "iconIdx": 33 }, { "icon": { @@ -844,7 +872,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 33 + "iconIdx": 34 }, { "icon": { @@ -868,7 +896,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 34 + "iconIdx": 35 }, { "icon": { @@ -892,7 +920,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 35 + "iconIdx": 36 }, { "icon": { @@ -916,7 +944,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 36 + "iconIdx": 37 }, { "icon": { @@ -940,7 +968,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 37 + "iconIdx": 38 }, { "icon": { @@ -964,7 +992,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 38 + "iconIdx": 39 }, { "icon": { @@ -988,7 +1016,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 39 + "iconIdx": 40 }, { "icon": { @@ -1012,7 +1040,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 40 + "iconIdx": 41 }, { "icon": { @@ -1036,7 +1064,7 @@ }, "setIdx": 0, "setId": 1, - "iconIdx": 41 + "iconIdx": 42 } ], "height": 1024, diff --git a/lib/web/mage/dropdown.js b/lib/web/mage/dropdown.js index 61e44e1ee501264a5757973d94e7e6bade643118..dbf04d0da9387841fa28ab1050894fcf3b5fb236 100644 --- a/lib/web/mage/dropdown.js +++ b/lib/web/mage/dropdown.js @@ -36,6 +36,7 @@ define([ autoSize: false, draggable: false, resizable: false, + bodyClass: '', buttons: [ { 'class': "action close", @@ -111,6 +112,9 @@ define([ if(_self.options.parentClass) { $(_self.options.appendTo).addClass(_self.options.parentClass); } + if(_self.options.bodyClass) { + $('body').addClass(_self.options.bodyClass); + } if (_self.options.shadowHinter) { _self._setShadowHinterPosition(); @@ -132,6 +136,9 @@ define([ if(this.options.parentClass) { $(this.options.appendTo).removeClass(this.options.parentClass); } + if(this.options.bodyClass) { + $('body').removeClass(this.options.bodyClass); + } if(timer) { clearTimeout(timer); } diff --git a/lib/web/mage/loader.js b/lib/web/mage/loader.js index a4bfc58b7859edd2cff3c200bd37a67733fc32c7..455ba80c692df017ad30293b761036b0b54f9f56 100644 --- a/lib/web/mage/loader.js +++ b/lib/web/mage/loader.js @@ -194,18 +194,10 @@ define([ }, _onAjaxComplete: function (e, jqxhr, settings) { - var ariaSelected = $('[aria-selected="true"]'); - $(this.options.defaultContainer) .removeClass(this.options.loadingClass) .attr('aria-busy', false); - // ARIA support - if (ariaSelected.length) { - ariaSelected.first().focus(); - $(this.options.defaultContainer).addClass('_keyfocus'); - } - if (settings && settings.showLoader) { this._getJqueryObj(settings.loaderContext).trigger('processStop'); } diff --git a/lib/web/mage/storage.js b/lib/web/mage/storage.js index ea0b6b432ba9d0b8316b1f714c92c50e697f3d62..3c6bd89ca1ebf0de4d964a4533cf9ffd1ff8e20d 100644 --- a/lib/web/mage/storage.js +++ b/lib/web/mage/storage.js @@ -2,34 +2,83 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -/*global define*/ define(['jquery', 'mage/url'], function ($, urlBuilder) { - "use strict"; + 'use strict'; + return { - get: function (url, contentType) { + /** + * Perform asynchronous GET request to server. + * @param {String} url + * @param {Boolean} global + * @param {String} contentType + * @returns {Deferred} + */ + get: function (url, global, contentType) { + global = global === undefined ? true : global; contentType = contentType || 'application/json'; + return $.ajax({ url: urlBuilder.build(url), type: 'GET', - async: false, + global: global, contentType: contentType }); }, - post: function(url, data, contentType) { + /** + * Perform asynchronous POST request to server. + * @param {String} url + * @param {String} data + * @param {Boolean} global + * @param {String} contentType + * @returns {Deferred} + */ + post: function (url, data, global, contentType) { + global = global === undefined ? true : global; contentType = contentType || 'application/json'; + return $.ajax({ url: urlBuilder.build(url), type: 'POST', data: data, + global: global, contentType: contentType }); }, - put: function(url, data, contentType) { + /** + * Perform asynchronous PUT request to server. + * @param {String} url + * @param {String} data + * @param {Boolean} global + * @param {String} contentType + * @returns {Deferred} + */ + put: function(url, data, global, contentType) { + global = global === undefined ? true : global; contentType = contentType || 'application/json'; + return $.ajax({ url: urlBuilder.build(url), type: 'PUT', data: data, + global: global, + contentType: contentType + }); + }, + /** + * Perform asynchronous DELETE request to server. + * @param {String} url + * @param {Boolean} global + * @param {String} contentType + * @returns {Deferred} + */ + delete: function(url, global, contentType) { + global = global === undefined ? true : global; + contentType = contentType || 'application/json'; + + return $.ajax({ + url: urlBuilder.build(url), + type: 'DELETE', + global: global, contentType: contentType }); }