├── Block └── Attributes │ └── Avatar.php ├── Controller └── Avatar │ └── View.php ├── Model ├── Attribute │ └── Backend │ │ └── Avatar.php └── Source │ └── Validation │ └── Image.php ├── Plugin ├── CustomerData │ └── Customer.php └── Metadata │ └── Form │ └── Image.php ├── README.md ├── Setup ├── InstallData.php └── Uninstall.php ├── Snapshot ├── avatar-in-customer-grid.png ├── customer-review.png ├── header-avatar.png ├── image-is-invalid.png ├── upload-delete-an-avatar.png ├── upload-new-avatar.png └── validate-by-js.png ├── Ui └── Component │ └── Listing │ └── Columns │ └── Avatar.php ├── composer.json ├── etc ├── di.xml ├── frontend │ ├── routes.xml │ └── sections.xml └── module.xml ├── registration.php └── view ├── adminhtml ├── ui_component │ └── customer_listing.xml └── web │ └── images │ └── no-profile-photo.jpg └── frontend ├── layout ├── customer_account_edit.xml ├── default.xml └── review_product_listajax.xml ├── templates ├── account │ └── customer.phtml ├── form │ └── edit.phtml └── review │ └── product │ └── view │ └── list.phtml └── web ├── css ├── avatar.css ├── global-avatar.css └── review-item.css ├── images └── no-profile-photo.jpg └── js └── avatar-validation.js /Block/Attributes/Avatar.php: -------------------------------------------------------------------------------- 1 | objectManager = $objectManager; 49 | $this->viewFileUrl = $viewFileUrl; 50 | $this->customer = $customer; 51 | parent::__construct($context); 52 | } 53 | 54 | /** 55 | * Check the file is already exist in the path. 56 | * @return boolean 57 | */ 58 | public function checkImageFile($file) 59 | { 60 | $file = base64_decode($file); 61 | $filesystem = $this->objectManager->get('Magento\Framework\Filesystem'); 62 | $directory = $filesystem->getDirectoryRead(DirectoryList::MEDIA); 63 | $fileName = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($file, '/'); 64 | $path = $directory->getAbsolutePath($fileName); 65 | if (!$directory->isFile($fileName) 66 | && !$this->objectManager->get('Magento\MediaStorage\Helper\File\Storage')->processStorageFile($path) 67 | ) { 68 | return false; 69 | } 70 | return true; 71 | } 72 | 73 | /** 74 | * Get the avatar of the customer is already logged in 75 | * @return string 76 | */ 77 | public function getAvatarCurrentCustomer($file) 78 | { 79 | if ($this->checkImageFile(base64_encode($file)) === true) { 80 | return $this->getUrl('viewfile/avatar/view/', ['image' => base64_encode($file)]); 81 | } 82 | return $this->viewFileUrl->getUrl('PHPCuong_CustomerProfilePicture::images/no-profile-photo.jpg'); 83 | } 84 | 85 | /** 86 | * Get the avatar of the customer by the customer id 87 | * @return string 88 | */ 89 | public function getCustomerAvatarById($customer_id = false) 90 | { 91 | if ($customer_id) { 92 | $customerDetail = $this->customer->load($customer_id); 93 | if ($customerDetail && !empty($customerDetail->getProfilePicture())) { 94 | if ($this->checkImageFile(base64_encode($customerDetail->getProfilePicture())) === true) { 95 | return $this->getUrl('viewfile/avatar/view/', ['image' => base64_encode($customerDetail->getProfilePicture())]); 96 | } 97 | } 98 | } 99 | return $this->viewFileUrl->getUrl('PHPCuong_CustomerProfilePicture::images/no-profile-photo.jpg'); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Controller/Avatar/View.php: -------------------------------------------------------------------------------- 1 | resultRawFactory = $resultRawFactory; 47 | $this->urlDecoder = $urlDecoder; 48 | $this->fileFactory = $fileFactory; 49 | return parent::__construct($context); 50 | } 51 | 52 | /** 53 | * View action 54 | * 55 | * @return \Magento\Framework\View\Result\PageFactory 56 | * @SuppressWarnings(PHPMD.NPathComplexity) 57 | */ 58 | public function execute() 59 | { 60 | $file = null; 61 | $plain = false; 62 | if ($this->getRequest()->getParam('file')) { 63 | // download file 64 | $file = $this->urlDecoder->decode( 65 | $this->getRequest()->getParam('file') 66 | ); 67 | } elseif ($this->getRequest()->getParam('image')) { 68 | // show plain image 69 | $file = $this->urlDecoder->decode( 70 | $this->getRequest()->getParam('image') 71 | ); 72 | $plain = true; 73 | } else { 74 | throw new NotFoundException(__('Page not found.')); 75 | } 76 | 77 | /** @var \Magento\Framework\Filesystem $filesystem */ 78 | $filesystem = $this->_objectManager->get('Magento\Framework\Filesystem'); 79 | $directory = $filesystem->getDirectoryRead(DirectoryList::MEDIA); 80 | $fileName = CustomerMetadataInterface::ENTITY_TYPE_CUSTOMER . '/' . ltrim($file, '/'); 81 | $path = $directory->getAbsolutePath($fileName); 82 | 83 | if (!$directory->isFile($fileName) 84 | && !$this->_objectManager->get('Magento\MediaStorage\Helper\File\Storage')->processStorageFile($path) 85 | ) { 86 | throw new NotFoundException(__('Page not found.')); 87 | } 88 | 89 | if ($plain) { 90 | $extension = pathinfo($path, PATHINFO_EXTENSION); 91 | switch (strtolower($extension)) { 92 | case 'gif': 93 | $contentType = 'image/gif'; 94 | break; 95 | case 'jpg': 96 | $contentType = 'image/jpeg'; 97 | break; 98 | case 'png': 99 | $contentType = 'image/png'; 100 | break; 101 | default: 102 | $contentType = 'application/octet-stream'; 103 | break; 104 | } 105 | $stat = $directory->stat($fileName); 106 | $contentLength = $stat['size']; 107 | $contentModify = $stat['mtime']; 108 | 109 | /** @var \Magento\Framework\Controller\Result\Raw $resultRaw */ 110 | $resultRaw = $this->resultRawFactory->create(); 111 | $resultRaw->setHttpResponseCode(200) 112 | ->setHeader('Pragma', 'public', true) 113 | ->setHeader('Content-type', $contentType, true) 114 | ->setHeader('Content-Length', $contentLength) 115 | ->setHeader('Last-Modified', date('r', $contentModify)); 116 | $resultRaw->setContents($directory->readFile($fileName)); 117 | return $resultRaw; 118 | } else { 119 | $name = pathinfo($path, PATHINFO_BASENAME); 120 | $this->fileFactory->create( 121 | $name, 122 | ['type' => 'filename', 'value' => $fileName], 123 | DirectoryList::MEDIA 124 | ); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Model/Attribute/Backend/Avatar.php: -------------------------------------------------------------------------------- 1 | getAttribute()->getAttributeCode(); 26 | if ($attrCode == 'profile_picture') { 27 | if ($validation->isImageValid('tmpp_name', $attrCode) === false) { 28 | throw new \Magento\Framework\Exception\LocalizedException( 29 | __('The profile picture is not a valid image.') 30 | ); 31 | } 32 | } 33 | 34 | return parent::beforeSave($object); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Model/Source/Validation/Image.php: -------------------------------------------------------------------------------- 1 | currentCustomer = $currentCustomer; 46 | $this->customerViewHelper = $customerViewHelper; 47 | $this->customerAvatar = $customerAvatar; 48 | } 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function afterGetSectionData() 54 | { 55 | if (!$this->currentCustomer->getCustomerId()) { 56 | return []; 57 | } 58 | $customer = $this->currentCustomer->getCustomer(); 59 | if (!empty($customer->getCustomAttribute('profile_picture'))) { 60 | $file = $customer->getCustomAttribute('profile_picture')->getValue(); 61 | } else { 62 | $file = ''; 63 | } 64 | return [ 65 | 'fullname' => $this->customerViewHelper->getCustomerName($customer), 66 | 'firstname' => $customer->getFirstname(), 67 | 'avatar' => $this->customerAvatar->getAvatarCurrentCustomer($file) 68 | ]; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /Plugin/Metadata/Form/Image.php: -------------------------------------------------------------------------------- 1 | validImage = $validImage; 21 | } 22 | 23 | /** 24 | * {@inheritdoc} 25 | * 26 | * @return ImageContentInterface|array|string|null 27 | */ 28 | public function beforeExtractValue(\Magento\Customer\Model\Metadata\Form\Image $subject, $value) 29 | { 30 | $attrCode = $subject->getAttribute()->getAttributeCode(); 31 | 32 | if ($this->validImage->isImageValid('tmp_name', $attrCode) === false) { 33 | $_FILES[$attrCode]['tmpp_name'] = $_FILES[$attrCode]['tmp_name']; 34 | unset($_FILES[$attrCode]['tmp_name']); 35 | } 36 | 37 | return []; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # You can get the professional version of this extension here (No issues and is supported free) 2 | https://www.giaphugroup.com/magento-2-customer-avatar-extension.html 3 | 4 | # How to add the profile picture for a customer in Magento 2 5 | This is an awesome module, it allows the customers the opportunity to personalize their account by uploading an avatar. 6 | 7 | Please donate if you enjoy my extension. 8 | 9 | [![](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CR756BABGNDC4) 10 | 11 | ## See the video How this extension can work here 12 | https://www.youtube.com/watch?v=3Tt82EvXLLA&list=PL98CDCbI3TNvPczWSOnpaMoyxVISLVzYQ&index=96 13 | 14 | ## The features of this extension: 15 | ### Frontend: 16 | - The customer can upload a new avatar. 17 | - The avatar can be displayed in the header of the website. 18 | - The avatar can be displayed in the reviews list. 19 | 20 | ### Backend: 21 | - Display the avatar of the customer in the customer's grid of Magento Admin. 22 | - Upload a new avatar or delete an avatar of the customer. 23 | 24 | ## Introduction installation: 25 | 26 | ### 1 - Using Composer 27 | 28 | ``` 29 | composer require php-cuong/magento2-customer-avatar:dev-master 30 | 31 | ``` 32 | 33 | ### 2- Enable the Customer Avatar extension 34 | * php bin/magento setup:upgrade 35 | * php bin/magento setup:static-content:deploy 36 | * php bin/magento indexer:reindex 37 | * php bin/magento cache:flush 38 | 39 | ### 3 - See results 40 | #### Frontend 41 | Log into your customer account, go to Edit Account Information 42 | 43 | ##### The avatar in the header 44 | 45 | ![ScreenShot](https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/master/Snapshot/header-avatar.png) 46 | 47 | ##### The avatar in the edit account information 48 | 49 | ![ScreenShot](https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/master/Snapshot/upload-new-avatar.png) 50 | 51 | ##### The avatar in the reviews list 52 | 53 | ![ScreenShot](https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/master/Snapshot/customer-review.png) 54 | 55 | #### Backend 56 | Log into your Magento admin, go to Customers -> All Customers 57 | 58 | ##### The avatar in the customer's grid of Magento Admin 59 | 60 | ![ScreenShot](https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/master/Snapshot/avatar-in-customer-grid.png) 61 | 62 | ##### Upload a new avatar or delete an avatar of the customer 63 | 64 | ![ScreenShot](https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/master/Snapshot/upload-delete-an-avatar.png) 65 | 66 | ## Donations 67 | Please donate if you enjoy my extension. 68 | 69 | [![](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=CR756BABGNDC4) 70 | 71 | 72 | -------------------------------------------------------------------------------- /Setup/InstallData.php: -------------------------------------------------------------------------------- 1 | customerSetupFactory = $customerSetupFactory; 46 | $this->attributeSetFactory = $attributeSetFactory; 47 | } 48 | 49 | 50 | /** 51 | * {@inheritdoc} 52 | */ 53 | public function install(ModuleDataSetupInterface $setup, ModuleContextInterface $context) 54 | { 55 | 56 | /** @var CustomerSetup $customerSetup */ 57 | $customerSetup = $this->customerSetupFactory->create(['setup' => $setup]); 58 | 59 | $customerEntity = $customerSetup->getEavConfig()->getEntityType('customer'); 60 | $attributeSetId = $customerEntity->getDefaultAttributeSetId(); 61 | 62 | /** @var $attributeSet AttributeSet */ 63 | $attributeSet = $this->attributeSetFactory->create(); 64 | $attributeGroupId = $attributeSet->getDefaultGroupId($attributeSetId); 65 | 66 | $customerSetup->addAttribute(Customer::ENTITY, 'profile_picture', [ 67 | 'type' => 'varchar', 68 | 'label' => 'Profile Picture', 69 | 'input' => 'image', 70 | 'backend' => 'PHPCuong\CustomerProfilePicture\Model\Attribute\Backend\Avatar', 71 | 'required' => false, 72 | 'visible' => true, 73 | 'user_defined' => true, 74 | 'sort_order' => 10, 75 | 'position' => 10, 76 | 'system' => 0, 77 | 'is_used_in_grid' => true, 78 | 'is_visible_in_grid' => true, 79 | 'is_html_allowed_on_front' => true, 80 | 'visible_on_front' => true 81 | ]); 82 | 83 | $attribute = $customerSetup->getEavConfig()->getAttribute(Customer::ENTITY, 'profile_picture') 84 | ->addData([ 85 | 'attribute_set_id' => $attributeSetId, 86 | 'attribute_group_id' => $attributeGroupId, 87 | 'used_in_forms' => ['adminhtml_customer', 'customer_account_edit'], 88 | ]); 89 | 90 | $attribute->save(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /Setup/Uninstall.php: -------------------------------------------------------------------------------- 1 | eavSetupFactory = $eavSetupFactory; 32 | } 33 | 34 | /** 35 | * {@inheritdoc} 36 | * @SuppressWarnings(PHPMD.CyclomaticComplexity) 37 | * @SuppressWarnings(PHPMD.ExcessiveMethodLength) 38 | * @SuppressWarnings(PHPMD.NPathComplexity) 39 | */ 40 | public function uninstall(SchemaSetupInterface $setup, ModuleContextInterface $context) 41 | { 42 | $setup->startSetup(); 43 | $eavSetup = $this->eavSetupFactory->create(); 44 | $eavSetup->removeAttribute( 45 | \Magento\Customer\Model\Customer::ENTITY, 46 | 'profile_picture' 47 | ); 48 | $setup->endSetup(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Snapshot/avatar-in-customer-grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/avatar-in-customer-grid.png -------------------------------------------------------------------------------- /Snapshot/customer-review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/customer-review.png -------------------------------------------------------------------------------- /Snapshot/header-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/header-avatar.png -------------------------------------------------------------------------------- /Snapshot/image-is-invalid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/image-is-invalid.png -------------------------------------------------------------------------------- /Snapshot/upload-delete-an-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/upload-delete-an-avatar.png -------------------------------------------------------------------------------- /Snapshot/upload-new-avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/upload-new-avatar.png -------------------------------------------------------------------------------- /Snapshot/validate-by-js.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/Snapshot/validate-by-js.png -------------------------------------------------------------------------------- /Ui/Component/Listing/Columns/Avatar.php: -------------------------------------------------------------------------------- 1 | urlBuilder = $urlBuilder; 41 | $this->viewFileUrl = $viewFileUrl; 42 | } 43 | 44 | /** 45 | * Prepare Data Source 46 | * 47 | * @param array $dataSource 48 | * @return array 49 | */ 50 | public function prepareDataSource(array $dataSource) 51 | { 52 | if (isset($dataSource['data']['items'])) { 53 | $fieldName = $this->getData('name'); 54 | foreach ($dataSource['data']['items'] as & $item) { 55 | $customer = new \Magento\Framework\DataObject($item); 56 | $picture_url = !empty($customer["profile_picture"]) ? $this->urlBuilder->getUrl( 57 | 'customer/index/viewfile/image/'.base64_encode($customer["profile_picture"])) : $this->viewFileUrl->getUrl('PHPCuong_CustomerProfilePicture::images/no-profile-photo.jpg'); 58 | $item[$fieldName . '_src'] = $picture_url; 59 | $item[$fieldName . '_orig_src'] = $picture_url; 60 | $item[$fieldName . '_alt'] = 'The profile picture'; 61 | } 62 | } 63 | 64 | return $dataSource; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "php-cuong/magento2-customer-avatar", 3 | "description":"Magento 2 Customer Avatar", 4 | "keywords": [ 5 | "magento 2", 6 | "Avatar", 7 | "Profile picture", 8 | "Customer Avatar", 9 | "Customer Profile Picture", 10 | "Magento 2 Customer Avatar", 11 | "Magento 2 Customer Profile Picture" 12 | ], 13 | "require": { 14 | "php": "~5.6.0|7.0.2|~7.0.6", 15 | "magento/module-backend": "100.0.*|100.1.*", 16 | "magento/framework": "100.0.*|100.1.*" 17 | }, 18 | "type": "magento2-module", 19 | "version": "2.1.0", 20 | "license": [ 21 | "OSL-3.0", 22 | "AFL-3.0" 23 | ], 24 | "authors": [ 25 | { 26 | "name": "Cuong NQ", 27 | "email": "bestearnmoney87@gmail.com", 28 | "role": "Developer" 29 | } 30 | ], 31 | "autoload": { 32 | "files": [ 33 | "registration.php" 34 | ], 35 | "psr-4": { 36 | "PHPCuong\\CustomerProfilePicture\\": "" 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /etc/di.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /etc/frontend/routes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /etc/frontend/sections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | -------------------------------------------------------------------------------- /etc/module.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /registration.php: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | Magento_Ui/js/grid/columns/thumbnail 14 | false 15 | 1 16 | Avatar 17 | 1 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /view/adminhtml/web/images/no-profile-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/view/adminhtml/web/images/no-profile-photo.jpg -------------------------------------------------------------------------------- /view/frontend/layout/customer_account_edit.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 34 | getChildHtml()):?> 35 |
36 | getChildHtml();?> 37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /view/frontend/templates/form/edit.phtml: -------------------------------------------------------------------------------- 1 | 11 | 104 | 134 | 145 | -------------------------------------------------------------------------------- /view/frontend/templates/review/product/view/list.phtml: -------------------------------------------------------------------------------- 1 | 10 | 16 | getReviewsCollection()->getItems(); 18 | $format = $block->getDateFormat() ?: \IntlDateFormatter::SHORT; 19 | ?> 20 | 21 |
22 |
23 | 24 |
25 |
26 |
27 | getChildHtml('toolbar') ?> 28 |
29 |
    30 | 31 |
  1. 32 |
    33 | avatar 34 |
    35 |
    36 |
    escapeHtml($_review->getTitle()) ?>
    37 |
    38 | getRatingVotes())): ?> 39 |
    40 | getRatingVotes() as $_vote): ?> 41 |
    42 | escapeHtml($_vote->getRatingCode()) ?> 43 |
    44 | 45 | 46 | 47 | getPercent() ?>% 48 | 49 |
    50 |
    51 | 52 |
    53 | 54 |

    55 | 56 | 57 |

    58 |

    59 | 60 | 61 |

    62 |
    63 |
    64 |
    65 | escapeHtml($_review->getDetail())) ?> 66 |
    67 |
  2. 68 | 69 |
70 |
71 | getChildHtml('toolbar') ?> 72 |
73 |
74 |
75 | 76 | -------------------------------------------------------------------------------- /view/frontend/web/css/avatar.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Ngo Quang Cuong 3 | * @Date: 2017-07-02 15:04:26 4 | * @Last Modified by: nquangcuong 5 | * @Last Modified time: 2017-07-03 14:51:49 6 | */ 7 | .avatar { 8 | opacity: 0; 9 | } 10 | .avatar-title { 11 | display: block; 12 | margin-bottom: 8px; 13 | } 14 | .avatar-file-upload { 15 | border: 1px solid #ccc; 16 | display: inline-block; 17 | padding: 6px 12px; 18 | cursor: pointer; 19 | } 20 | .field-name-avatar img { 21 | cursor: pointer; 22 | } 23 | -------------------------------------------------------------------------------- /view/frontend/web/css/global-avatar.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Ngo Quang Cuong 3 | * @Date: 2017-07-03 16:29:29 4 | * @Last Modified by: nquangcuong 5 | * @Last Modified time: 2017-07-03 18:40:05 6 | */ 7 | @media(min-width: 768px) { 8 | .customer-welcome .customer-name { 9 | display: block; 10 | height: 25px; 11 | } 12 | .customer-welcome ul.header.links:before { 13 | right: 5px; 14 | } 15 | .customer-welcome ul.header.links:after { 16 | right: 4px; 17 | } 18 | } 19 | .customer-welcome .customer-name .avatar-header-links { 20 | border-radius: 50%; 21 | height: 25px; 22 | width: 25px; 23 | } 24 | -------------------------------------------------------------------------------- /view/frontend/web/css/review-item.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Ngo Quang Cuong 3 | * @Date: 2017-07-04 11:02:13 4 | * @Last Modified by: nquangcuong 5 | * @Last Modified time: 2017-07-04 11:22:24 6 | */ 7 | .review-item .review-image { 8 | width: 70px; 9 | padding: 0px 10px 5px 0px; 10 | float: left; 11 | } 12 | .review-item .review-image img { 13 | border-radius: 50%; 14 | width: 70px; 15 | height: 70px; 16 | } 17 | .review-item .review-infor { 18 | display: inline-block; 19 | } 20 | .review-item .review-infor .review-title { 21 | padding: 0px; 22 | margin: 0px; 23 | line-height: inherit; 24 | padding-bottom: 0px; 25 | } 26 | .review-item .review-infor .review-details { 27 | color: gray; 28 | padding-bottom: 10px; 29 | font-size: 13px; 30 | } 31 | .review-item .review-infor .review-details .review-ratings { 32 | float: inherit; 33 | padding-bottom: 5px; 34 | margin: 0px; 35 | } 36 | .review-item .review-infor .review-details .review-ratings .rating-label { 37 | display: none; 38 | } 39 | .review-item .review-content { 40 | margin-bottom: 20px; 41 | float: left; 42 | width: 100%; 43 | } 44 | @media(max-width: 767px) { 45 | .review-item .review-image { 46 | width: 60px; 47 | padding: 0px 10px 5px 0px; 48 | float: left; 49 | } 50 | .review-item .review-image img { 51 | border-radius: 50%; 52 | width: 60px; 53 | height: 60px; 54 | } 55 | .review-item .review-infor .review-title { 56 | font-size: 13px; 57 | } 58 | .review-item .review-infor .review-details { 59 | color: gray; 60 | padding-bottom: 10px; 61 | font-size: 12px; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /view/frontend/web/images/no-profile-photo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php-cuong/magento2-customer-avatar/3f467418f9206efc00690e95c19ab4a3d37f3320/view/frontend/web/images/no-profile-photo.jpg -------------------------------------------------------------------------------- /view/frontend/web/js/avatar-validation.js: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: Ngo Quang Cuong 3 | * @Date: 2017-07-02 16:47:45 4 | * @Last Modified by: nquangcuong 5 | * @Last Modified time: 2017-07-03 16:00:03 6 | */ 7 | 8 | require([ 9 | 'jquery', 10 | 'jquery/ui', 11 | 'jquery/validate', 12 | 'mage/translate' 13 | ], function ($) { 14 | //Validate Image FileSize 15 | $('.avatar.validate-image').on('change', function() { 16 | $('.profile-image, .avatar-file-upload').css({'opacity':'0.5'}); 17 | }); 18 | $.validator.addMethod( 19 | 'validate-image', function (v, elm) { 20 | if (elm.value != '') { 21 | var ext = elm.value.split('.').pop().toLowerCase(); 22 | if ($.inArray(ext, ['gif', 'png', 'jpg', 'jpeg']) == -1) { 23 | return false; 24 | } 25 | } 26 | return true; 27 | }, $.mage.__('Image invalid (Accepting format .gif .png .jpg .jpeg)') 28 | ); 29 | }); 30 | --------------------------------------------------------------------------------