first commit
This commit is contained in:
7
modules/blockwishlist/.prettierrc.js
Normal file
7
modules/blockwishlist/.prettierrc.js
Normal file
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
htmlWhitespaceSensitivity: 'ignore',
|
||||
semi: true,
|
||||
singleQuote: true,
|
||||
vueIndentScriptAndStyle: true,
|
||||
trailingComma: 'none'
|
||||
};
|
||||
47
modules/blockwishlist/LICENSE.md
Normal file
47
modules/blockwishlist/LICENSE.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Academic Free License ("AFL") v. 3.0
|
||||
|
||||
This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work:
|
||||
|
||||
Licensed under the Academic Free License version 3.0
|
||||
|
||||
1) Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following:
|
||||
|
||||
a) to reproduce the Original Work in copies, either alone or as part of a collective work;
|
||||
|
||||
b) to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work;
|
||||
|
||||
c) to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License;
|
||||
|
||||
d) to perform the Original Work publicly; and
|
||||
|
||||
e) to display the Original Work publicly.
|
||||
|
||||
2) Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works.
|
||||
|
||||
3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work.
|
||||
|
||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license.
|
||||
|
||||
5) External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c).
|
||||
|
||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work.
|
||||
|
||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer.
|
||||
|
||||
8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation.
|
||||
|
||||
9) Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c).
|
||||
|
||||
10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware.
|
||||
|
||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License.
|
||||
|
||||
12) Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License.
|
||||
|
||||
13) Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable.
|
||||
|
||||
14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You.
|
||||
|
||||
16) Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under <insert your license name here>" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process.
|
||||
16
modules/blockwishlist/Makefile
Normal file
16
modules/blockwishlist/Makefile
Normal file
@@ -0,0 +1,16 @@
|
||||
help:
|
||||
@egrep "^#" Makefile
|
||||
|
||||
# target: docker-build|db - Setup/Build PHP & (node)JS dependencies
|
||||
db: docker-build
|
||||
docker-build: build-back build-front
|
||||
|
||||
build-back:
|
||||
docker-compose run --rm php sh -c "composer install"
|
||||
|
||||
build-back-prod:
|
||||
docker-compose run --rm php sh -c "composer install --no-dev -o"
|
||||
|
||||
build-front:
|
||||
docker-compose run --rm node sh -c "npm install"
|
||||
docker-compose run --rm node sh -c "npm run build"
|
||||
31
modules/blockwishlist/README.md
Normal file
31
modules/blockwishlist/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# BlockWishList
|
||||
|
||||
## About
|
||||
|
||||
Adds a block containing the customer's wishlists.
|
||||
|
||||
## Multistore compatibility
|
||||
|
||||
This module is compatible with the multistore :heavy_check_mark: <br/>
|
||||
It can be configured differently from one store to another.<br/>
|
||||
It can be configured quickly in the same way on all stores thanks to the all shops context or the group of shops.<br/>
|
||||
It can be activated on one store and deactivated on another
|
||||
|
||||
## Reporting issues
|
||||
|
||||
You can report issues with this module in the main PrestaShop repository. [Click here to report an issue][report-issue].
|
||||
|
||||
## Contributing
|
||||
|
||||
PrestaShop modules are open source extensions to the [PrestaShop e-commerce platform][prestashop]. Everyone is welcome and even encouraged to contribute with their own improvements!
|
||||
|
||||
Just make sure to follow our [contribution guidelines][contribution-guidelines].
|
||||
|
||||
## License
|
||||
|
||||
This module is released under the [Academic Free License 3.0][AFL-3.0]
|
||||
|
||||
[report-issue]: https://github.com/PrestaShop/PrestaShop/issues/new/choose
|
||||
[prestashop]: https://www.prestashop.com/
|
||||
[contribution-guidelines]: https://devdocs.prestashop.com/1.7/contribute/contribution-guidelines/project-modules/
|
||||
[AFL-3.0]: https://opensource.org/licenses/AFL-3.0
|
||||
78
modules/blockwishlist/_dev/back/js/backoffice.js
Normal file
78
modules/blockwishlist/_dev/back/js/backoffice.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import blockwishlistModule from 'blockwishlistModule';
|
||||
|
||||
const tabButtons = document.querySelectorAll('.btn-group button');
|
||||
const refreshButton = document.querySelector('.js-refresh');
|
||||
let isLoading = false;
|
||||
|
||||
tabButtons.forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
if (!button.classList.contains('active')) {
|
||||
tabButtons.forEach((elem) => {
|
||||
elem.classList.remove('active');
|
||||
});
|
||||
|
||||
button.classList.add('active');
|
||||
|
||||
const tabs = document.querySelectorAll('.wishlist-tab');
|
||||
|
||||
tabs.forEach((tab) => {
|
||||
if (
|
||||
tab.classList.contains('active')
|
||||
&& tab.dataset.tab !== button.dataset.tab
|
||||
) {
|
||||
tab.classList.remove('active');
|
||||
}
|
||||
|
||||
if (tab.dataset.tab === button.dataset.tab) {
|
||||
tab.classList.add('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
refreshButton.addEventListener('click', async () => {
|
||||
if (!isLoading) {
|
||||
isLoading = true;
|
||||
|
||||
const cacheButton = refreshButton.innerHTML;
|
||||
|
||||
refreshButton.innerHTML = '<i class="material-icons">hourglass_empty</i>';
|
||||
|
||||
const response = await fetch(`${blockwishlistModule.resetCacheUrl}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json, text/javascript, */*; q=0.01',
|
||||
},
|
||||
});
|
||||
|
||||
const {success} = await response.json();
|
||||
|
||||
if (success) {
|
||||
location.reload();
|
||||
} else {
|
||||
isLoading = false;
|
||||
refreshButton.innerHTML = cacheButton;
|
||||
}
|
||||
}
|
||||
});
|
||||
22
modules/blockwishlist/_dev/back/js/form.js
Normal file
22
modules/blockwishlist/_dev/back/js/form.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import TranslatableInput from '@PSJs/components/translatable-input';
|
||||
|
||||
new TranslatableInput();
|
||||
76
modules/blockwishlist/_dev/back/scss/_stats.scss
Normal file
76
modules/blockwishlist/_dev/back/scss/_stats.scss
Normal file
@@ -0,0 +1,76 @@
|
||||
.wishlist-stats {
|
||||
.card {
|
||||
&-text {
|
||||
width: 100%;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
}
|
||||
|
||||
& &-topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.btn-group {
|
||||
border: 1px solid #b7ced3;
|
||||
border-radius: 3px;
|
||||
|
||||
button {
|
||||
color: #363a41;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0;
|
||||
line-height: 19px;
|
||||
background: none;
|
||||
font-weight: 500;
|
||||
transition: 0.25s ease-out;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-right: 1px solid #b7ced3;
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: #25b9d7;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.refresh {
|
||||
color: #6c868e;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 19px;
|
||||
border: 1px solid #6c868e;
|
||||
border-radius: 4px;
|
||||
transition: 0.25s ease-out;
|
||||
background: none;
|
||||
|
||||
&:hover {
|
||||
background: #6c868e;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wishlist-tab {
|
||||
display: none;
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.column-image {
|
||||
img {
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
.column-conversionRate {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
58
modules/blockwishlist/_dev/back/scss/backoffice.css
Normal file
58
modules/blockwishlist/_dev/back/scss/backoffice.css
Normal file
@@ -0,0 +1,58 @@
|
||||
.wishlist-stats .card-text {
|
||||
width: 100%;
|
||||
padding: 10px 30px;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .btn-group {
|
||||
border: 1px solid #b7ced3;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .btn-group button {
|
||||
color: #363a41;
|
||||
font-size: 14px;
|
||||
letter-spacing: 0;
|
||||
line-height: 19px;
|
||||
background: none;
|
||||
font-weight: 500;
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .btn-group button:not(:last-child) {
|
||||
border-right: 1px solid #b7ced3;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .btn-group button:hover, .wishlist-stats .wishlist-stats-topbar .btn-group button.active {
|
||||
background-color: #25b9d7;
|
||||
color: #fff;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .refresh {
|
||||
color: #6c868e;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 19px;
|
||||
border: 1px solid #6c868e;
|
||||
border-radius: 4px;
|
||||
transition: 0.25s ease-out;
|
||||
background: none;
|
||||
}
|
||||
.wishlist-stats .wishlist-stats-topbar .refresh:hover {
|
||||
background: #6c868e;
|
||||
color: white;
|
||||
}
|
||||
.wishlist-stats .wishlist-tab {
|
||||
display: none;
|
||||
}
|
||||
.wishlist-stats .wishlist-tab.active {
|
||||
display: block;
|
||||
}
|
||||
.wishlist-stats .wishlist-tab .column-image img {
|
||||
max-width: 50px;
|
||||
}
|
||||
.wishlist-stats .wishlist-tab .column-conversionRate {
|
||||
font-weight: bold;
|
||||
}/*# sourceMappingURL=backoffice.css.map */
|
||||
1
modules/blockwishlist/_dev/back/scss/backoffice.css.map
Normal file
1
modules/blockwishlist/_dev/back/scss/backoffice.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["_stats.scss","backoffice.css"],"names":[],"mappings":"AAEI;EACE,WAAA;EACA,kBAAA;ACDN;ADKE;EACE,aAAA;EACA,8BAAA;EACA,mBAAA;EACA,eAAA;EACA,mBAAA;ACHJ;ADKI;EACE,yBAAA;EACA,kBAAA;ACHN;ADKM;EACE,cAAA;EACA,eAAA;EACA,iBAAA;EACA,iBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;ACHR;ADKQ;EACE,+BAAA;ACHV;ADMQ;EAEE,yBAAA;EACA,WAAA;ACLV;ADUI;EACE,cAAA;EACA,eAAA;EACA,iBAAA;EACA,iBAAA;EACA,iBAAA;EACA,yBAAA;EACA,kBAAA;EACA,0BAAA;EACA,gBAAA;ACRN;ADUM;EACE,mBAAA;EACA,YAAA;ACRR;ADaE;EACE,aAAA;ACXJ;ADaI;EACE,cAAA;ACXN;ADeM;EACE,eAAA;ACbR;ADiBI;EACE,iBAAA;ACfN","file":"backoffice.css"}
|
||||
1
modules/blockwishlist/_dev/back/scss/backoffice.scss
Normal file
1
modules/blockwishlist/_dev/back/scss/backoffice.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import '_stats';
|
||||
@@ -0,0 +1,126 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
import ChooseList from '../ChooseList/ChooseList';
|
||||
|
||||
export default {
|
||||
name: 'AddToWishlist',
|
||||
components: {
|
||||
ChooseList,
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '#',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
productAttributeId: 0,
|
||||
productId: 0,
|
||||
quantity: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Open and close the modal
|
||||
*/
|
||||
toggleModal(forceOpen) {
|
||||
if (forceOpen === true) {
|
||||
this.isHidden = false;
|
||||
} else {
|
||||
this.isHidden = !this.isHidden;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Dispatch an event to the Create component
|
||||
*/
|
||||
openNewWishlistModal() {
|
||||
this.toggleModal();
|
||||
|
||||
EventBus.$emit('showCreateWishlist');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event showAddToWishList so others component can open the modal of the current component
|
||||
*/
|
||||
EventBus.$on('showAddToWishList', (event) => {
|
||||
this.toggleModal(
|
||||
event.detail.forceOpen ? event.detail.forceOpen : null,
|
||||
);
|
||||
|
||||
if (event.detail.productId) {
|
||||
this.productId = event.detail.productId;
|
||||
}
|
||||
|
||||
if (typeof event.detail.productAttributeId === 'number') {
|
||||
this.productAttributeId = event.detail.productAttributeId;
|
||||
}
|
||||
|
||||
if (event.detail.quantity) {
|
||||
this.quantity = event.detail.quantity;
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-add-to-new {
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease-out;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1rem;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 0.3125rem;
|
||||
vertical-align: middle;
|
||||
color: $blue;
|
||||
margin-top: -0.125rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-add-to {
|
||||
.modal {
|
||||
&-body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-footer {
|
||||
text-align: left;
|
||||
padding: 0.75rem 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import AddToWishlist from './AddToWishlist';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(AddToWishlist, '.wishlist-add-to', props);
|
||||
233
modules/blockwishlist/_dev/front/js/components/Button/Button.vue
Normal file
233
modules/blockwishlist/_dev/front/js/components/Button/Button.vue
Normal file
@@ -0,0 +1,233 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<button
|
||||
class="wishlist-button-add"
|
||||
:class="{ 'wishlist-button-product': isProduct }"
|
||||
@click="addToWishlist"
|
||||
>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-if="isChecked"
|
||||
>favorite</i>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-else
|
||||
>favorite_border</i>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import removeFromList from '@graphqlFiles/mutations/removeFromList';
|
||||
import prestashop from 'prestashop';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
export default {
|
||||
name: 'Button',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '#',
|
||||
},
|
||||
productId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
productAttributeId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
isProduct: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isChecked: this.checked === 'true',
|
||||
idList: this.listId,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the heart on this component, basically if the heart is filled,
|
||||
* then this product is inside a wishlist, else it's not in a wishlist
|
||||
*/
|
||||
toggleCheck() {
|
||||
this.isChecked = !this.isChecked;
|
||||
},
|
||||
/**
|
||||
* If the product isn't in a wishlist, then open the "AddToWishlist" component modal,
|
||||
* if he's in a wishlist, then launch a removeFromList mutation to remote the product from a wishlist
|
||||
*/
|
||||
async addToWishlist(event) {
|
||||
event.preventDefault();
|
||||
const quantity = document.querySelector(
|
||||
'.product-quantity input#quantity_wanted',
|
||||
);
|
||||
|
||||
if (!prestashop.customer.is_logged) {
|
||||
EventBus.$emit('showLogin');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.isChecked) {
|
||||
EventBus.$emit('showAddToWishList', {
|
||||
detail: {
|
||||
productId: this.productId,
|
||||
productAttributeId: parseInt(this.productAttributeId, 10),
|
||||
forceOpen: true,
|
||||
quantity: quantity ? parseInt(quantity.value, 10) : 0,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const {data} = await this.$apollo.mutate({
|
||||
mutation: removeFromList,
|
||||
variables: {
|
||||
productId: this.productId,
|
||||
url: this.url,
|
||||
productAttributeId: this.productAttributeId,
|
||||
listId: this.idList ? this.idList : this.listId,
|
||||
},
|
||||
});
|
||||
|
||||
const {removeFromList: response} = data;
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: response.success ? 'success' : 'error',
|
||||
message: response.message,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.error) {
|
||||
this.toggleCheck();
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to event addedToWishlist to toggle the heart if the product has been added correctly
|
||||
*/
|
||||
EventBus.$on('addedToWishlist', (event) => {
|
||||
if (
|
||||
event.detail.productId === this.productId
|
||||
&& parseInt(event.detail.productAttributeId, 10) === this.productAttributeId
|
||||
) {
|
||||
this.isChecked = true;
|
||||
this.idList = event.detail.listId;
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line
|
||||
const items = productsAlreadyTagged.filter(
|
||||
(e) => parseInt(e.id_product, 10) === this.productId
|
||||
&& parseInt(e.id_product_attribute, 10) === this.productAttributeId,
|
||||
);
|
||||
|
||||
if (items.length > 0) {
|
||||
this.isChecked = true;
|
||||
this.idList = parseInt(items[0].id_wishlist, 10);
|
||||
}
|
||||
|
||||
if (this.isProduct) {
|
||||
prestashop.on('updateProduct', ({eventType}) => {
|
||||
if (eventType === 'updatedProductQuantity') {
|
||||
this.isChecked = false;
|
||||
}
|
||||
});
|
||||
|
||||
prestashop.on('updatedProduct', (args) => {
|
||||
const quantity = document.querySelector(
|
||||
'.product-quantity input#quantity_wanted',
|
||||
);
|
||||
|
||||
this.productAttributeId = parseInt(args.id_product_attribute, 10);
|
||||
|
||||
// eslint-disable-next-line
|
||||
const itemsFiltered = productsAlreadyTagged.filter(
|
||||
(e) => parseInt(e.id_product, 10) === this.productId
|
||||
&& e.quantity.toString() === quantity.value
|
||||
&& parseInt(e.id_product_attribute, 10) === this.productAttributeId,
|
||||
);
|
||||
|
||||
if (itemsFiltered.length > 0) {
|
||||
this.isChecked = true;
|
||||
this.idList = parseInt(itemsFiltered[0].id_wishlist, 10);
|
||||
} else {
|
||||
this.isChecked = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-button {
|
||||
&-product {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
|
||||
&-add {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
min-width: 2.5rem;
|
||||
padding-top: 0.1875rem;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0.125rem -0.125rem 0.25rem 0 rgba(0, 0, 0, 0.2);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease-out;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
i {
|
||||
color: #7a7a7a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Button from './Button';
|
||||
|
||||
const initButtons = () => {
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'checked',
|
||||
type: Boolean,
|
||||
},
|
||||
{
|
||||
name: 'productId',
|
||||
type: Number,
|
||||
},
|
||||
{
|
||||
name: 'productAttributeId',
|
||||
type: Number,
|
||||
},
|
||||
{
|
||||
name: 'isProduct',
|
||||
type: Boolean,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Button, '.wishlist-button', props);
|
||||
};
|
||||
|
||||
initButtons();
|
||||
|
||||
export default initButtons;
|
||||
@@ -0,0 +1,239 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div class="wishlist-chooselist">
|
||||
<ul class="wishlist-list">
|
||||
<li
|
||||
class="wishlist-list-item"
|
||||
v-for="list of lists"
|
||||
:key="list.id_wishlist"
|
||||
@click="select(list.id_wishlist)"
|
||||
>
|
||||
<p>
|
||||
{{ list.name }}
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ContentLoader
|
||||
v-if="$apollo.queries.lists.loading"
|
||||
class="wishlist-list-loader"
|
||||
height="105"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="12"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="36"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="60"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="84"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
</ContentLoader>
|
||||
|
||||
<p
|
||||
class="wishlist-list-empty"
|
||||
v-if="lists && lists.length <= 0 && !$apollo.queries.lists.loading"
|
||||
>
|
||||
{{ emptyText }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import getLists from '@graphqlFiles/queries/getlists';
|
||||
import addtolist from '@graphqlFiles/mutations/addtolist';
|
||||
import EventBus from '@components/EventBus';
|
||||
import {ContentLoader} from 'vue-content-loader';
|
||||
|
||||
/**
|
||||
* The role of this component is to render a list
|
||||
* and make the possibility to choose one for the selected product
|
||||
*/
|
||||
export default {
|
||||
name: 'ChooseList',
|
||||
components: {
|
||||
ContentLoader,
|
||||
},
|
||||
apollo: {
|
||||
lists: {
|
||||
query: getLists,
|
||||
variables() {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
props: {
|
||||
productId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
quantity: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
productAttributeId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: 0,
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'No list found',
|
||||
},
|
||||
addUrl: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Select a list and add the product to it
|
||||
*
|
||||
* @param {Int} listId The id of the list selected
|
||||
* @param {Int} userId The id of the user
|
||||
* @param {Int} productId The id of the product
|
||||
*/
|
||||
async select(listId) {
|
||||
const {data} = await this.$apollo.mutate({
|
||||
mutation: addtolist,
|
||||
variables: {
|
||||
listId,
|
||||
url: this.addUrl,
|
||||
productId: this.productId,
|
||||
quantity: this.quantity,
|
||||
productAttributeId: this.productAttributeId,
|
||||
},
|
||||
});
|
||||
|
||||
const {addToList: response} = data;
|
||||
|
||||
/**
|
||||
* Hide the modal inside the parent
|
||||
*/
|
||||
this.$emit('hide');
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: response.success ? 'success' : 'error',
|
||||
message: response.message,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Send an event to the Heart the user previously clicked on
|
||||
*/
|
||||
EventBus.$emit('addedToWishlist', {
|
||||
detail: {
|
||||
productId: this.productId,
|
||||
listId,
|
||||
productAttributeId: this.productAttributeId,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event refetchList so if an other component update it, this one can update his list
|
||||
*
|
||||
* @param {String} 'refetchList' The event I decided to create to communicate between VueJS Apps
|
||||
*/
|
||||
EventBus.$on('refetchList', () => {
|
||||
this.$apollo.queries.lists.refetch();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-list {
|
||||
max-height: 55vh;
|
||||
overflow-y: auto;
|
||||
border-top: 1px solid #e5e5e5;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
margin: 0;
|
||||
|
||||
&-empty {
|
||||
font-size: 30;
|
||||
text-align: center;
|
||||
padding: 30px;
|
||||
padding-bottom: 1.25rem;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
& .wishlist-list-item {
|
||||
padding: 0.875rem 0;
|
||||
transition: 0.25s ease-out;
|
||||
cursor: pointer;
|
||||
margin-bottom: 0;
|
||||
|
||||
&:hover {
|
||||
background: lighten($blue, 45%);
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
color: #232323;
|
||||
margin-bottom: 0;
|
||||
line-height: 1rem;
|
||||
padding: 0 2.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
159
modules/blockwishlist/_dev/front/js/components/Create/Create.vue
Normal file
159
modules/blockwishlist/_dev/front/js/components/Create/Create.vue
Normal file
@@ -0,0 +1,159 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import createList from '@graphqlFiles/mutations/createlist';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* This component display a modal where you can create a wishlist
|
||||
*/
|
||||
export default {
|
||||
name: 'Create',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '#',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'New wishlist',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Wishlist name',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Add name',
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Cancel',
|
||||
},
|
||||
lengthText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'List title is too short',
|
||||
},
|
||||
createText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Create',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the modal
|
||||
*/
|
||||
toggleModal() {
|
||||
this.isHidden = !this.isHidden;
|
||||
},
|
||||
/**
|
||||
* Launch a createList mutation to create a Wishlist
|
||||
*/
|
||||
async createWishlist() {
|
||||
const titleWithoutSpaces = this.value.replace(/ /g, '');
|
||||
|
||||
if (titleWithoutSpaces < 1) {
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: 'error',
|
||||
message: this.lengthText,
|
||||
},
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const {data: response} = await this.$apollo.mutate({
|
||||
mutation: createList,
|
||||
variables: {
|
||||
name: this.value,
|
||||
url: this.url,
|
||||
},
|
||||
});
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: response.createList.success ? 'success' : 'error',
|
||||
message: response.createList.message,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* As this is not a real SPA, we need to inform others VueJS apps that they need to refetch the list
|
||||
*/
|
||||
EventBus.$emit('refetchList');
|
||||
|
||||
/**
|
||||
* Finally hide the modal after creating the list
|
||||
* and reopen the wishlist modal
|
||||
*/
|
||||
this.toggleModal();
|
||||
EventBus.$emit('showAddToWishList', {
|
||||
detail: {
|
||||
forceOpen: true,
|
||||
},
|
||||
});
|
||||
|
||||
return true;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event showCreateWishlist so others components can toggle this modal
|
||||
*
|
||||
* @param {String} 'showCreateWishlist'
|
||||
*/
|
||||
EventBus.$on('showCreateWishlist', () => {
|
||||
this.value = '';
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-create {
|
||||
.wishlist-modal {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1053;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Create from './Create';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'productId',
|
||||
type: Number,
|
||||
},
|
||||
{
|
||||
name: 'placeholder',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'cancelText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'lengthText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'createText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Create, '.wishlist-create', props);
|
||||
177
modules/blockwishlist/_dev/front/js/components/Delete/Delete.vue
Normal file
177
modules/blockwishlist/_dev/front/js/components/Delete/Delete.vue
Normal file
@@ -0,0 +1,177 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import deleteList from '@graphqlFiles/mutations/deletelist';
|
||||
import removeFromList from '@graphqlFiles/mutations/removeFromList';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* This component display a modal where you can delete a wishlist
|
||||
*/
|
||||
export default {
|
||||
name: 'Delete',
|
||||
props: {
|
||||
deleteProductUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '#',
|
||||
},
|
||||
deleteListUrl: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '#',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Delete',
|
||||
},
|
||||
titleList: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Delete',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'This action is irreversible',
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Cancel',
|
||||
},
|
||||
deleteText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Delete',
|
||||
},
|
||||
deleteTextList: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Delete',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
listId: null,
|
||||
listName: '',
|
||||
productId: null,
|
||||
productAttributeId: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
confirmMessage() {
|
||||
return this.placeholder.replace('%nameofthewishlist%', this.listName);
|
||||
},
|
||||
modalTitle() {
|
||||
return this.productId ? this.title : this.titleList;
|
||||
},
|
||||
modalDeleteText() {
|
||||
return this.productId ? this.deleteText : this.deleteTextList;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the modal
|
||||
*/
|
||||
toggleModal() {
|
||||
this.isHidden = !this.isHidden;
|
||||
},
|
||||
/**
|
||||
* Launch a deleteList mutation to delete a Wishlist
|
||||
*/
|
||||
async deleteWishlist() {
|
||||
const {data} = await this.$apollo.mutate({
|
||||
mutation: this.productId ? removeFromList : deleteList,
|
||||
variables: {
|
||||
listId: this.listId,
|
||||
productId: parseInt(this.productId, 10),
|
||||
productAttributeId: parseInt(this.productAttributeId, 10),
|
||||
url: this.productId ? this.deleteProductUrl : this.deleteListUrl,
|
||||
},
|
||||
});
|
||||
|
||||
const response = data.deleteList
|
||||
? data.deleteList
|
||||
: data.removeFromList;
|
||||
|
||||
/**
|
||||
* As this is not a real SPA, we need to inform others VueJS apps that they need to refetch the list
|
||||
*/
|
||||
EventBus.$emit('refetchList');
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: response.success ? 'success' : 'error',
|
||||
message: response.message,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Finally hide the modal after deleting the list
|
||||
* and reopen the wishlist modal
|
||||
*/
|
||||
this.toggleModal();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event showCreateWishlist so others components can toggle this modal
|
||||
*
|
||||
* @param {String} 'showDeleteWishlist'
|
||||
*/
|
||||
EventBus.$on('showDeleteWishlist', (event) => {
|
||||
this.value = '';
|
||||
this.listId = event.detail.listId;
|
||||
this.listName = event.detail.listName;
|
||||
this.productId = null;
|
||||
this.productAttributeId = null;
|
||||
|
||||
if (event.detail.productId) {
|
||||
this.productId = event.detail.productId;
|
||||
this.productAttributeId = event.detail.productAttributeId;
|
||||
}
|
||||
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-delete {
|
||||
.wishlist-modal {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1053;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Delete from './Delete';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'deleteProductUrl',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'deleteListUrl',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'titleList',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'placeholder',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'cancelText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'deleteText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'deleteTextList',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Delete, '.wishlist-delete', props);
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import Vue from 'vue';
|
||||
import prestashop from 'prestashop';
|
||||
|
||||
const EventBus = new Vue();
|
||||
|
||||
window.WishlistEventBus = EventBus;
|
||||
|
||||
prestashop.emit('wishlistEventBusInit');
|
||||
|
||||
export default EventBus;
|
||||
351
modules/blockwishlist/_dev/front/js/components/List/List.vue
Normal file
351
modules/blockwishlist/_dev/front/js/components/List/List.vue
Normal file
@@ -0,0 +1,351 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div class="wishlist-list-container">
|
||||
<ul
|
||||
class="wishlist-list"
|
||||
v-if="items.length > 0 && items"
|
||||
v-click-outside="emptyPopups"
|
||||
>
|
||||
<li
|
||||
class="wishlist-list-item"
|
||||
:key="list.id_wishlist"
|
||||
v-for="list of items"
|
||||
:class="{ 'wishlist-list-item-default': list.default }"
|
||||
>
|
||||
<a
|
||||
class="wishlist-list-item-link"
|
||||
@click="redirectToList(list.listUrl)"
|
||||
>
|
||||
<p class="wishlist-list-item-title">
|
||||
{{ list.name }}
|
||||
<span v-if="list.nbProducts">({{ list.nbProducts }})</span>
|
||||
<span v-else>(0)</span>
|
||||
</p>
|
||||
|
||||
<div class="wishlist-list-item-right">
|
||||
<button
|
||||
class="wishlist-list-item-actions"
|
||||
@click.stop="togglePopup(list.id_wishlist)"
|
||||
v-if="!list.default"
|
||||
>
|
||||
<i class="material-icons">more_vert</i>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click.stop="toggleShare(list.id_wishlist, list.shareUrl)"
|
||||
v-if="list.default"
|
||||
>
|
||||
<i class="material-icons">share</i>
|
||||
</button>
|
||||
|
||||
<div
|
||||
class="dropdown-menu show"
|
||||
v-if="activeDropdowns.includes(list.id_wishlist)"
|
||||
>
|
||||
<button @click.stop="toggleRename(list.id_wishlist, list.name)">
|
||||
{{ renameText }}
|
||||
</button>
|
||||
<button
|
||||
@click.stop="toggleShare(list.id_wishlist, list.shareUrl)"
|
||||
>
|
||||
{{ shareText }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
@click.stop="toggleDelete(list.id_wishlist, list.name)"
|
||||
v-if="!list.default"
|
||||
>
|
||||
<i class="material-icons">delete</i>
|
||||
</button>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ContentLoader
|
||||
v-if="loading"
|
||||
class="wishlist-list-loader"
|
||||
height="105"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="12"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="36"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="60"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="84"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
</ContentLoader>
|
||||
<p
|
||||
class="wishlist-list-empty"
|
||||
v-if="items.length <= 0 && !loading"
|
||||
>
|
||||
{{ emptyText }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {ContentLoader} from 'vue-content-loader';
|
||||
import EventBus from '@components/EventBus';
|
||||
import wishlistUrl from 'wishlistUrl';
|
||||
import vClickOutside from 'v-click-outside';
|
||||
|
||||
/**
|
||||
* Dumb component to display the list of Wishlist on a page
|
||||
*/
|
||||
export default {
|
||||
name: 'List',
|
||||
components: {
|
||||
ContentLoader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeDropdowns: [],
|
||||
listUrl: wishlistUrl,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
items: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
renameText: {
|
||||
type: String,
|
||||
default: 'Rename',
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
shareText: {
|
||||
type: String,
|
||||
default: 'Share',
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle a dropdown with some actions
|
||||
*
|
||||
* @param {Int} id The ID of the list which contain this dropdown
|
||||
*/
|
||||
togglePopup(id) {
|
||||
if (this.activeDropdowns.includes(id)) {
|
||||
this.activeDropdowns = this.activeDropdowns.filter((e) => e !== id);
|
||||
} else {
|
||||
this.activeDropdowns = [];
|
||||
this.activeDropdowns.push(id);
|
||||
}
|
||||
},
|
||||
emptyPopups() {
|
||||
this.activeDropdowns = [];
|
||||
},
|
||||
/**
|
||||
* Toggle the popup to rename a list
|
||||
*
|
||||
* @param {Int} id The list ID so the rename popup know which list to rename
|
||||
* @param {String} The base title so the rename popup can autofill it
|
||||
*/
|
||||
toggleRename(id, title) {
|
||||
EventBus.$emit('showRenameWishlist', {
|
||||
detail: {listId: id, title},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Toggle the popup to rename a list
|
||||
*
|
||||
* @param {Int} id The list ID so the rename popup know which list to rename
|
||||
* @param {String} The base title so the rename popup can autofill it
|
||||
*/
|
||||
toggleShare(id, shareUrl) {
|
||||
EventBus.$emit('showShareWishlist', {
|
||||
detail: {listId: id, shareUrl},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Toggle the popup to rename a list
|
||||
*
|
||||
* @param {Int} id The list ID so the rename popup know which list to rename
|
||||
* @param {String} The base title so the rename popup can autofill it
|
||||
*/
|
||||
toggleDelete(id) {
|
||||
EventBus.$emit('showDeleteWishlist', {
|
||||
detail: {listId: id, userId: 1},
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Redirect to the list URI
|
||||
*
|
||||
* @param {String} listUrl The list url
|
||||
*/
|
||||
redirectToList(listUrl) {
|
||||
window.location.href = listUrl;
|
||||
},
|
||||
},
|
||||
directives: {
|
||||
clickOutside: vClickOutside.directive,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-list {
|
||||
margin-bottom: 0;
|
||||
|
||||
&-empty {
|
||||
font-size: 1.875rem;
|
||||
text-align: center;
|
||||
padding: 1.875rem;
|
||||
padding-bottom: 1.25rem;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&-loader {
|
||||
padding: 0 1.25rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-item {
|
||||
&-default {
|
||||
border-bottom: 1px solid #0000002e;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.wishlist-list-item-title {
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
&-link {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.5rem 1.25rem;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
right: 1.25rem;
|
||||
left: inherit;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-right {
|
||||
position: relative;
|
||||
|
||||
> button {
|
||||
transition: 0.25s ease-out;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
i {
|
||||
color: #7a7a7a;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 0.25rem;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0.125rem 0.125rem 0.625rem 0 rgba(0, 0, 0, 0.2);
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
|
||||
> button {
|
||||
padding: 0.625rem 1.25rem;
|
||||
transition: 0.2s ease-out;
|
||||
text-align: left;
|
||||
|
||||
&:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: #232323;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.375rem;
|
||||
margin-bottom: 0;
|
||||
|
||||
span {
|
||||
color: #7a7a7a;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.375rem;
|
||||
font-weight: normal;
|
||||
margin-left: 0.3125rem;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
background: none;
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,81 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
import prestashop from 'prestashop';
|
||||
|
||||
/**
|
||||
* This component display a modal where you can redirect to login page
|
||||
*/
|
||||
export default {
|
||||
name: 'Login',
|
||||
props: {
|
||||
cancelText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Cancel',
|
||||
},
|
||||
loginText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Login',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
listId: null,
|
||||
prestashop,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the modal
|
||||
*/
|
||||
toggleModal() {
|
||||
this.isHidden = !this.isHidden;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event showCreateWishlist so others components can toggle this modal
|
||||
*
|
||||
* @param {String} 'showDeleteWishlist'
|
||||
*/
|
||||
EventBus.$on('showLogin', () => {
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-login {
|
||||
.wishlist-modal {
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
z-index: 1053;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Login from './Login';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'loginText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'cancelText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Login, '.wishlist-login', props);
|
||||
@@ -0,0 +1,87 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* Dumb component to display the list of Wishlist on a page
|
||||
*/
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
data() {
|
||||
return {
|
||||
total: null,
|
||||
minShown: null,
|
||||
maxShown: null,
|
||||
pageNumber: 0,
|
||||
pages: [],
|
||||
currentPage: null,
|
||||
display: false,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
paginate(page) {
|
||||
EventBus.$emit('updatePagination', {
|
||||
page,
|
||||
});
|
||||
|
||||
this.currentPage = page;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
EventBus.$on('paginate', (payload) => {
|
||||
this.total = payload.detail.total;
|
||||
this.minShown = payload.detail.minShown;
|
||||
this.maxShown = payload.detail.maxShown;
|
||||
this.pageNumber = payload.detail.pageNumber;
|
||||
this.currentPage = payload.detail.currentPage;
|
||||
this.pages = payload.detail.pages;
|
||||
this.display = payload.detail.display;
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-pagination {
|
||||
.previous {
|
||||
margin-right: 1.875rem;
|
||||
}
|
||||
|
||||
.js-wishlist-search-link {
|
||||
cursor: pointer;
|
||||
|
||||
&:not([href]):not([tabindex]):hover {
|
||||
color: $blue;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
cursor: inherit;
|
||||
|
||||
&:hover {
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Pagination from './Pagination';
|
||||
|
||||
const props = [];
|
||||
|
||||
initApp(Pagination, '.wishlist-pagination', props);
|
||||
@@ -0,0 +1,608 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div class="wishlist-product">
|
||||
<a
|
||||
class="wishlist-product-link"
|
||||
:href="product.canonical_url"
|
||||
>
|
||||
<div class="wishlist-product-image">
|
||||
<img
|
||||
v-if="product.default_image"
|
||||
:src="product.default_image.large.url"
|
||||
:alt="product.default_image.legend"
|
||||
:title="product.default_image.legend"
|
||||
:class="{
|
||||
'wishlist-product-unavailable': !product.add_to_cart_url
|
||||
}"
|
||||
>
|
||||
<img
|
||||
v-else-if="product.cover"
|
||||
:src="product.cover.large.url"
|
||||
:alt="product.cover.legend"
|
||||
:title="product.cover.legend"
|
||||
:class="{
|
||||
'wishlist-product-unavailable': !product.add_to_cart_url
|
||||
}"
|
||||
>
|
||||
<img
|
||||
v-else
|
||||
:src="prestashop.urls.no_picture_image.bySize.home_default.url"
|
||||
>
|
||||
|
||||
<p
|
||||
class="wishlist-product-availability"
|
||||
v-if="product.show_availability"
|
||||
>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-if="product.availability === 'unavailable'"
|
||||
>
|
||||
block
|
||||
</i>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-if="product.availability === 'last_remaining_items'"
|
||||
>
|
||||
warning
|
||||
</i>
|
||||
{{ product.availability_message }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="wishlist-product-right">
|
||||
<p class="wishlist-product-title">{{ product.name }}</p>
|
||||
|
||||
<p class="wishlist-product-price">
|
||||
<span
|
||||
class="wishlist-product-price-promo"
|
||||
v-if="product.has_discount"
|
||||
>
|
||||
{{ product.regular_price }}
|
||||
</span>
|
||||
{{ product.price }}
|
||||
</p>
|
||||
|
||||
<div class="wishlist-product-combinations">
|
||||
<p class="wishlist-product-combinations-text">
|
||||
<template v-for="(attribute, key, index) of product.attributes">
|
||||
{{ attribute.group }} : {{ attribute.name }}
|
||||
<span
|
||||
:key="key"
|
||||
v-if="index <= Object.keys(product.attributes).length - 1"
|
||||
>
|
||||
-
|
||||
</span>
|
||||
|
||||
<span
|
||||
:key="key + 'end'"
|
||||
v-if="index == Object.keys(product.attributes).length - 1"
|
||||
>
|
||||
{{ quantityText }} : {{ product.wishlist_quantity }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<span v-if="Object.keys(product.attributes).length === 0">
|
||||
{{ quantityText }} : {{ product.wishlist_quantity }}
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<a
|
||||
:href="product.canonical_url"
|
||||
v-if="!isShare"
|
||||
>
|
||||
<i class="material-icons">create</i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<div class="wishlist-product-bottom">
|
||||
<button
|
||||
class="btn wishlist-product-addtocart"
|
||||
:class="{
|
||||
'btn-secondary': product.customizable === '1',
|
||||
'btn-primary': product.customizable === '0'
|
||||
}"
|
||||
:disabled="isDisabled || forceDisable"
|
||||
@click="
|
||||
product.add_to_cart_url || product.customizable === '1'
|
||||
? addToCartAction()
|
||||
: null
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="material-icons shopping-cart"
|
||||
v-if="product.customizable === '0'"
|
||||
>
|
||||
shopping_cart
|
||||
</i>
|
||||
{{ product.customizable === '1' ? customizeText : addToCart }}
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="wishlist-button-add"
|
||||
v-if="!isShare"
|
||||
@click="removeFromWishlist"
|
||||
>
|
||||
<i class="material-icons">delete</i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p
|
||||
class="wishlist-product-availability wishlist-product-availability-responsive"
|
||||
v-if="product.show_availability"
|
||||
>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-if="product.availability === 'unavailable'"
|
||||
>
|
||||
block
|
||||
</i>
|
||||
<i
|
||||
class="material-icons"
|
||||
v-if="product.availability === 'last_remaining_items'"
|
||||
>
|
||||
warning
|
||||
</i>
|
||||
{{ product.availability_message }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
import headers from '@constants/headers';
|
||||
import prestashop from 'prestashop';
|
||||
import wishlistAddProductToCartUrl from 'wishlistAddProductToCartUrl';
|
||||
|
||||
export default {
|
||||
name: 'Product',
|
||||
props: {
|
||||
product: {
|
||||
type: Object,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
listId: {
|
||||
type: Number,
|
||||
required: true,
|
||||
default: null,
|
||||
},
|
||||
listName: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
isShare: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
customizeText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Customize',
|
||||
},
|
||||
quantityText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Quantity',
|
||||
},
|
||||
addToCart: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
status: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
hasControls: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
prestashop,
|
||||
forceDisable: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isDisabled() {
|
||||
const wishlistQuantity = parseInt(this.product.wishlist_quantity, 10);
|
||||
const quantityAvailable = parseInt(this.product.quantity_available, 10);
|
||||
const cartQuantity = parseInt(this.product.cart_quantity, 10);
|
||||
|
||||
if (this.product.allow_oosp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.product.customizable === '1') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wishlistQuantity > quantityAvailable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cartQuantity >= quantityAvailable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cartQuantity
|
||||
&& cartQuantity + wishlistQuantity > quantityAvailable
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !this.product.add_to_cart_url;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Remove the product from the wishlist
|
||||
*/
|
||||
async removeFromWishlist() {
|
||||
EventBus.$emit('showDeleteWishlist', {
|
||||
detail: {
|
||||
listId: this.listId,
|
||||
listName: this.listName,
|
||||
productId: this.product.id,
|
||||
productAttributeId: this.product.id_product_attribute,
|
||||
},
|
||||
});
|
||||
},
|
||||
async addToCartAction() {
|
||||
if (this.product.add_to_cart_url && this.product.customizable !== '1') {
|
||||
try {
|
||||
this.forceDisable = true;
|
||||
const datas = new FormData();
|
||||
datas.append('qty', this.product.wishlist_quantity);
|
||||
datas.append('id_product', this.product.id_product);
|
||||
datas.append('id_customization', this.product.id_customization);
|
||||
|
||||
const response = await fetch(
|
||||
`${this.product.add_to_cart_url}&action=update`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: headers.addToCart,
|
||||
body: datas,
|
||||
},
|
||||
);
|
||||
|
||||
const resp = await response.json();
|
||||
|
||||
EventBus.$emit('refetchList');
|
||||
|
||||
prestashop.emit('updateCart', {
|
||||
reason: {
|
||||
idProduct: this.product.id_product,
|
||||
idProductAttribute: this.product.id_product_attribute,
|
||||
idCustomization: this.product.id_customization,
|
||||
linkAction: 'add-to-cart',
|
||||
},
|
||||
resp,
|
||||
});
|
||||
|
||||
$('body').on('hide.bs.modal', '#blockcart-modal', () => {
|
||||
this.forceDisable = false;
|
||||
});
|
||||
|
||||
/* eslint-disable */
|
||||
const statResponse = await fetch(
|
||||
`${wishlistAddProductToCartUrl}¶ms[idWishlist]=${this.listId}¶ms[id_product]=${this.product.id_product}¶ms[id_product_attribute]=${this.product.id_product_attribute}¶ms[quantity]=${this.product.wishlist_quantity}`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type':
|
||||
'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
Accept: 'application/json, text/javascript, */*; q=0.01'
|
||||
}
|
||||
}
|
||||
);
|
||||
/* eslint-enable */
|
||||
|
||||
await statResponse.json();
|
||||
} catch (error) {
|
||||
prestashop.emit('handleError', {
|
||||
eventType: 'addProductToCart',
|
||||
resp: error,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
window.location.href = this.product.canonical_url;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-products-item {
|
||||
margin: 1.5625rem;
|
||||
}
|
||||
|
||||
&-product {
|
||||
max-width: 15.625rem;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
&-unavailable {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&-availability {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 0;
|
||||
color: #232323;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.0625rem;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
bottom: 1.0625rem;
|
||||
z-index: 5;
|
||||
min-width: 80%;
|
||||
justify-content: center;
|
||||
|
||||
i {
|
||||
color: #ff4c4c;
|
||||
margin-right: 0.3125rem;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
&-responsive {
|
||||
display: none;
|
||||
position: inherit;
|
||||
transform: inherit;
|
||||
bottom: inherit;
|
||||
margin-top: 0.625rem;
|
||||
left: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&-link {
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
img {
|
||||
transform: translate(-50%, -50%) scale(1.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
margin-top: 0.625rem;
|
||||
margin-bottom: 0.315rem;
|
||||
color: #737373;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
|
||||
&-image {
|
||||
width: 15.625rem;
|
||||
height: 15.625rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
transition: 0.25s ease-out;
|
||||
}
|
||||
}
|
||||
|
||||
&-price {
|
||||
color: #232323;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.375rem;
|
||||
|
||||
&-promo {
|
||||
text-decoration: line-through;
|
||||
color: #737373;
|
||||
font-size: 0.875rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.1875rem;
|
||||
margin-right: 0.3125rem;
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin-top: -0.1875rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-combinations {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
color: #7a7a7a;
|
||||
|
||||
&:hover {
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
color: #7a7a7a;
|
||||
font-size: 0.8125rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.25rem;
|
||||
min-height: 3.125rem;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-addtocart {
|
||||
width: 100%;
|
||||
text-transform: inherit;
|
||||
padding-left: 0.625rem;
|
||||
|
||||
&.btn-secondary {
|
||||
background-color: #dddddd;
|
||||
|
||||
&:hover {
|
||||
background-color: #dddddd;
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
margin-top: -0.1875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-button {
|
||||
&-add {
|
||||
position: absolute;
|
||||
top: 0.625rem;
|
||||
right: 0.625rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 2.5rem;
|
||||
width: 2.5rem;
|
||||
min-width: 2.5rem;
|
||||
padding-top: 0.1875rem;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0.125rem 0.125rem 0.25rem 0 rgba(0, 0, 0, 0.2);
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease-out;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
i {
|
||||
color: #7a7a7a;
|
||||
margin-top: -0.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.wishlist {
|
||||
&-button-add {
|
||||
position: inherit;
|
||||
margin-left: 0.625rem;
|
||||
}
|
||||
|
||||
&-products-item {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
margin-bottom: 1.875rem;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 1.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-product {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
|
||||
&-link {
|
||||
&:hover {
|
||||
img {
|
||||
transform: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-right {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&-availability {
|
||||
display: none;
|
||||
|
||||
&-responsive {
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
&-image {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin-right: 1.25rem;
|
||||
position: inherit;
|
||||
|
||||
img {
|
||||
position: inherit;
|
||||
left: inherit;
|
||||
top: inherit;
|
||||
transform: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
&-link {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
&-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
133
modules/blockwishlist/_dev/front/js/components/Rename/Rename.vue
Normal file
133
modules/blockwishlist/_dev/front/js/components/Rename/Rename.vue
Normal file
@@ -0,0 +1,133 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import renameList from '@graphqlFiles/mutations/renamelist';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* A modal used to rename a list
|
||||
*/
|
||||
export default {
|
||||
name: 'Rename',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '#',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Rename wishlist',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Wishlist name',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Rename text',
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Cancel',
|
||||
},
|
||||
renameText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Rename',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
listId: 0,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the modal
|
||||
*/
|
||||
toggleModal() {
|
||||
this.isHidden = !this.isHidden;
|
||||
},
|
||||
/**
|
||||
* Launch a renameList mutation, then dispatch an event to everycomponent to refetch the list after renaming it
|
||||
*
|
||||
* @param {Int} listId Id of the list to be renamed
|
||||
*/
|
||||
async renameWishlist() {
|
||||
const {data} = await this.$apollo.mutate({
|
||||
mutation: renameList,
|
||||
variables: {
|
||||
name: this.value,
|
||||
url: this.url,
|
||||
listId: this.listId,
|
||||
},
|
||||
});
|
||||
|
||||
const {renameList: response} = data;
|
||||
|
||||
EventBus.$emit('refetchList');
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: response.success ? 'success' : 'error',
|
||||
message: response.message,
|
||||
},
|
||||
});
|
||||
|
||||
this.toggleModal();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the showRenameWishlist event so everycomponents can display this modal
|
||||
*/
|
||||
EventBus.$on('showRenameWishlist', (event) => {
|
||||
this.value = event.detail.title;
|
||||
this.listId = event.detail.listId;
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss" scoped>
|
||||
.wishlist {
|
||||
&-rename {
|
||||
.wishlist-modal {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1051;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Rename from './Rename';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'placeholder',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'cancelText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'renameText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Rename, '.wishlist-rename', props);
|
||||
132
modules/blockwishlist/_dev/front/js/components/Share/Share.vue
Normal file
132
modules/blockwishlist/_dev/front/js/components/Share/Share.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* This component display a modal where you can create a wishlist
|
||||
*/
|
||||
export default {
|
||||
name: 'Share',
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: '#',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Share wishlist',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Share link',
|
||||
},
|
||||
cancelText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Cancel',
|
||||
},
|
||||
copyText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Copy text',
|
||||
},
|
||||
copiedText: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: 'Copied',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: '',
|
||||
isHidden: true,
|
||||
actionText: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Toggle the modal
|
||||
*/
|
||||
toggleModal() {
|
||||
this.isHidden = !this.isHidden;
|
||||
},
|
||||
/**
|
||||
* Copy the link in the input value
|
||||
*/
|
||||
copyLink() {
|
||||
const shareInput = document.querySelector(
|
||||
'.wishlist-share .form-control',
|
||||
);
|
||||
|
||||
shareInput.select();
|
||||
shareInput.setSelectionRange(0, 99999);
|
||||
|
||||
document.execCommand('copy');
|
||||
|
||||
this.actionText = this.copiedText;
|
||||
|
||||
this.toggleModal();
|
||||
|
||||
EventBus.$emit('showToast', {
|
||||
detail: {
|
||||
type: 'success',
|
||||
message: 'copyText',
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.actionText = this.copyText;
|
||||
|
||||
/**
|
||||
* Register to the event showCreateWishlist so others components can toggle this modal
|
||||
*
|
||||
* @param {String} 'showCreateWishlist'
|
||||
*/
|
||||
EventBus.$on('showShareWishlist', async (event) => {
|
||||
this.actionText = this.copyText;
|
||||
this.value = event.detail.shareUrl;
|
||||
this.toggleModal();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-share {
|
||||
.wishlist-modal {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1053;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Share from './Share';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'label',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'copyText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'copiedText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'cancelText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Share, '.wishlist-share', props);
|
||||
151
modules/blockwishlist/_dev/front/js/components/Toast/Toast.vue
Normal file
151
modules/blockwishlist/_dev/front/js/components/Toast/Toast.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div
|
||||
class="wishlist-toast"
|
||||
:class="[{ isActive: active }, type]"
|
||||
>
|
||||
<p class="wishlist-toast-text">
|
||||
{{ text }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
export default {
|
||||
name: 'Button',
|
||||
props: {
|
||||
renameWishlistText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
addedWishlistText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
deleteWishlistText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
createWishlistText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
deleteProductText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
copyText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: '',
|
||||
active: false,
|
||||
timeout: null,
|
||||
type: 'basic',
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to an even so every components can show toast
|
||||
*/
|
||||
EventBus.$on('showToast', (event) => {
|
||||
if (event.detail.message) {
|
||||
if (this[event.detail.message]) {
|
||||
this.text = this[event.detail.message];
|
||||
} else {
|
||||
this.text = event.detail.message;
|
||||
}
|
||||
}
|
||||
|
||||
this.active = true;
|
||||
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
this.timeout = setTimeout(() => {
|
||||
this.active = false;
|
||||
this.timeout = null;
|
||||
}, 2500);
|
||||
|
||||
this.type = event.detail.type ? event.detail.type : 'basic';
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
.wishlist {
|
||||
&-toast {
|
||||
padding: 0.875rem 1.25rem;
|
||||
box-sizing: border-box;
|
||||
width: auto;
|
||||
border: 1px solid #e5e5e5;
|
||||
border-radius: 4px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: 0.125rem 0.125rem 0.625rem 0 rgba(0, 0, 0, 0.2);
|
||||
position: fixed;
|
||||
right: 1.25rem;
|
||||
z-index: 9999;
|
||||
top: 4.375rem;
|
||||
transition: 0.2s ease-out;
|
||||
transform: translateY(-10px);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
|
||||
&.success {
|
||||
background-color: #69b92d;
|
||||
border-color: #69b92d;
|
||||
|
||||
.wishlist-toast-text {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&.error {
|
||||
background-color: #b9312d;
|
||||
border-color: #b9312d;
|
||||
|
||||
.wishlist-toast-text {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&.isActive {
|
||||
transform: translateY(0);
|
||||
pointer-events: all;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&-text {
|
||||
color: #232323;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.1875rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import Toast from './Toast';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'renameWishlistText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'createWishlistText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'addedWishlistText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'shareText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'deleteWishlistText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'deleteProductText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'copyText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(Toast, '.wishlist-toast', props);
|
||||
64
modules/blockwishlist/_dev/front/js/components/init.js
Normal file
64
modules/blockwishlist/_dev/front/js/components/init.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import apolloClient from '@graphqlFiles/client';
|
||||
|
||||
/**
|
||||
* Init a VueJS application to keep monolith features such as hooks or event the use of twig/smarty
|
||||
*
|
||||
* @param {Vue} component The component to be init
|
||||
* @param {String} componentSelector A selector for querySelectorAll
|
||||
* @param {Array[Object]} props An array containing Object{name, type} to parse int
|
||||
*/
|
||||
export default function initApp(component, componentSelector, props) {
|
||||
Vue.use(VueApollo);
|
||||
|
||||
const apolloProvider = new VueApollo({
|
||||
defaultClient: apolloClient,
|
||||
});
|
||||
|
||||
const componentElements = document.querySelectorAll(componentSelector);
|
||||
const ComponentRoot = Vue.extend(component);
|
||||
|
||||
const propsData = {};
|
||||
|
||||
componentElements.forEach((e) => {
|
||||
/* eslint-disable */
|
||||
for (const prop of props) {
|
||||
if (e.dataset[prop.name]) {
|
||||
if (prop.type === Number) {
|
||||
propsData[prop.name] = parseInt(e.dataset[prop.name], 10);
|
||||
} else if (prop.type === Boolean) {
|
||||
propsData[prop.name] = e.dataset[prop.name] === 'true';
|
||||
} else {
|
||||
propsData[prop.name] = e.dataset[prop.name];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
new ComponentRoot({
|
||||
el: e,
|
||||
delimiters: ['((', '))'],
|
||||
apolloProvider,
|
||||
propsData,
|
||||
});
|
||||
});
|
||||
}
|
||||
11
modules/blockwishlist/_dev/front/js/constants/headers.js
Normal file
11
modules/blockwishlist/_dev/front/js/constants/headers.js
Normal file
@@ -0,0 +1,11 @@
|
||||
const headers = {
|
||||
addToCart: {
|
||||
Accept: 'application/json, text/javascript',
|
||||
},
|
||||
products: {
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json, text/javascript, */*; q=0.01',
|
||||
},
|
||||
};
|
||||
|
||||
export default headers;
|
||||
@@ -0,0 +1,366 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div class="wishlist-products-container">
|
||||
<div class="wishlist-products-container-header">
|
||||
<h1>
|
||||
{{ title }}
|
||||
|
||||
<span
|
||||
class="wishlist-products-count"
|
||||
v-if="products.datas && products.datas.products"
|
||||
>
|
||||
({{ products.datas.pagination.total_items }})
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
<div
|
||||
class="sort-by-row"
|
||||
v-if="products.datas"
|
||||
>
|
||||
<span class="col-sm-3 col-md-3 hidden-sm-down sort-by">{{ filter }}</span>
|
||||
<div class="col-sm-9 col-xs-8 col-md-9 products-sort-order dropdown">
|
||||
<button
|
||||
class="btn-unstyle select-title"
|
||||
rel="nofollow"
|
||||
data-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{{ currentSort }}
|
||||
<i class="material-icons float-xs-right">arrow_drop_down</i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a
|
||||
rel="nofollow"
|
||||
@click="changeSelectedSort(sort)"
|
||||
class="select-list"
|
||||
:key="key"
|
||||
v-for="(sort, key) in productList"
|
||||
>
|
||||
{{ sort.label }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section
|
||||
id="content"
|
||||
class="page-content card card-block"
|
||||
>
|
||||
<ul
|
||||
class="wishlist-products-list"
|
||||
v-if="products.datas && products.datas.products.length > 0"
|
||||
>
|
||||
<li
|
||||
class="wishlist-products-item"
|
||||
v-for="(product, key) in products.datas.products"
|
||||
:key="key"
|
||||
>
|
||||
<Product
|
||||
:product="product"
|
||||
:add-to-cart="addToCart"
|
||||
:customize-text="customizeText"
|
||||
:quantity-text="quantityText"
|
||||
:list-name="title"
|
||||
:list-id="
|
||||
listId ? listId : parseInt(currentWishlist.id_wishlist, 10)
|
||||
"
|
||||
:is-share="share"
|
||||
/>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ContentLoader
|
||||
v-if="!products.datas"
|
||||
class="wishlist-list-loader"
|
||||
height="105"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="12"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="36"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="60"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="84"
|
||||
rx="3"
|
||||
ry="0"
|
||||
width="100%"
|
||||
height="11"
|
||||
/>
|
||||
</ContentLoader>
|
||||
|
||||
<p
|
||||
class="wishlist-list-empty"
|
||||
v-if="products.datas && products.datas.products.length <= 0"
|
||||
>
|
||||
{{ noProductsMessage }}
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Product from '@components/Product/Product';
|
||||
import getProducts from '@graphqlFiles/queries/getproducts';
|
||||
import {ContentLoader} from 'vue-content-loader';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* This component act as a smart component wich will handle every actions of the list one
|
||||
*/
|
||||
export default {
|
||||
name: 'ProductsListContainer',
|
||||
components: {
|
||||
Product,
|
||||
ContentLoader,
|
||||
},
|
||||
apollo: {
|
||||
products: {
|
||||
query: getProducts,
|
||||
variables() {
|
||||
return {
|
||||
listId: this.listId,
|
||||
url: this.apiUrl,
|
||||
};
|
||||
},
|
||||
skip() {
|
||||
return true;
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
},
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '#',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
filter: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
noProductsMessage: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
listId: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 0,
|
||||
},
|
||||
addToCart: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
share: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
customizeText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
quantityText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
products: [],
|
||||
currentWishlist: {},
|
||||
apiUrl: window.location.href,
|
||||
selectedSort: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Sort by the select drop down
|
||||
* @param {String} value The value selected
|
||||
*/
|
||||
async changeSelectedSort(value) {
|
||||
this.selectedSort = value.label;
|
||||
this.apiUrl = value.url;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
productList() {
|
||||
const productList = this.products.datas.sort_orders.filter(
|
||||
(sort) => sort.label !== this.products.datas.sort_selected,
|
||||
);
|
||||
|
||||
return productList;
|
||||
},
|
||||
currentSort() {
|
||||
return this.selectedSort !== ''
|
||||
? this.selectedSort
|
||||
: this.products.datas.sort_selected;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
if (this.listId) {
|
||||
this.$apollo.queries.products.skip = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register to the event refetchProducts so if an other component update it, this one can update his list
|
||||
*
|
||||
* @param {String} 'refetchProduct' The event I decided to create to communicate between VueJS Apps
|
||||
*/
|
||||
EventBus.$on('refetchList', () => {
|
||||
this.$apollo.queries.products.refetch();
|
||||
});
|
||||
|
||||
EventBus.$on('updatePagination', (payload) => {
|
||||
this.products = false;
|
||||
this.apiUrl = payload.page.url;
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-list-loader {
|
||||
padding: 0 1.25rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-list-empty {
|
||||
font-size: 30;
|
||||
text-align: center;
|
||||
padding: 1.875rem;
|
||||
padding-bottom: 1.25rem;
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
&-products-container {
|
||||
.sort-by-row {
|
||||
min-width: 19.6875rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sort-by {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.products-sort-order {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
@at-root #main & .card.page-content {
|
||||
padding: 0;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-products {
|
||||
&-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: -1.5625rem;
|
||||
padding: 1.25rem 2.8125rem;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&-count {
|
||||
color: #7a7a7a;
|
||||
font-size: 1.375rem;
|
||||
font-weight: normal;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.wishlist {
|
||||
&-products-container {
|
||||
&-header {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.products-sort-order {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.filter-button {
|
||||
width: auto;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.sort-by-row {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.page-content.card {
|
||||
box-shadow: 0.125rem 0.125rem 0.5rem 0 rgba(0, 0, 0, 0.2);
|
||||
background-color: #fff;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
.wishlist-products-list {
|
||||
justify-content: center;
|
||||
margin: 0;
|
||||
padding: 0.9375rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import ProductsListContainer from './ProductsListContainer.vue';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'noProductsMessage',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'addToCart',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'customizeText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'wishlistProducts',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'wishlist',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'share',
|
||||
type: Boolean,
|
||||
},
|
||||
{
|
||||
name: 'quantityText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'filter',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'listId',
|
||||
type: Number,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(ProductsListContainer, '.wishlist-products-container', props);
|
||||
@@ -0,0 +1,172 @@
|
||||
<!--**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*-->
|
||||
<template>
|
||||
<div class="wishlist-container">
|
||||
<div class="wishlist-container-header">
|
||||
<h1>{{ title }}</h1>
|
||||
|
||||
<a
|
||||
@click="openNewWishlistModal"
|
||||
class="wishlist-add-to-new text-primary"
|
||||
>
|
||||
<i class="material-icons">add_circle_outline</i>
|
||||
{{ addText }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<section
|
||||
id="content"
|
||||
class="page-content card card-block"
|
||||
>
|
||||
<list
|
||||
:items="lists"
|
||||
:rename-text="renameText"
|
||||
:share-text="shareText"
|
||||
:empty-text="emptyText"
|
||||
:loading="$apollo.queries.lists.loading"
|
||||
/>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import List from '@components/List/List';
|
||||
import getLists from '@graphqlFiles/queries/getlists';
|
||||
import EventBus from '@components/EventBus';
|
||||
|
||||
/**
|
||||
* This component act as a smart component wich will handle every actions of the list one
|
||||
*/
|
||||
export default {
|
||||
name: 'WishlistContainer',
|
||||
components: {
|
||||
List,
|
||||
},
|
||||
apollo: {
|
||||
lists: {
|
||||
query: getLists,
|
||||
variables() {
|
||||
return {
|
||||
url: this.url,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
addText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
renameText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
emptyText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
shareText: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
lists: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Send an event to opoen the Create Wishlist Modal
|
||||
*/
|
||||
openNewWishlistModal() {
|
||||
EventBus.$emit('showCreateWishlist');
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
/**
|
||||
* Register to the event refetchList so if an other component update it, this one can update his list
|
||||
*
|
||||
* @param {String} 'refetchList' The event I decided to create to communicate between VueJS Apps
|
||||
*/
|
||||
EventBus.$on('refetchList', () => {
|
||||
this.$apollo.queries.lists.refetch();
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" type="text/scss">
|
||||
@import '@scss/_variables';
|
||||
|
||||
.wishlist {
|
||||
&-container {
|
||||
&-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
@at-root #main & .card.page-content {
|
||||
padding: 0;
|
||||
margin-bottom: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-add-to-new {
|
||||
cursor: pointer;
|
||||
transition: 0.2s ease-out;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1rem;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
i {
|
||||
margin-right: 0.3125rem;
|
||||
vertical-align: middle;
|
||||
margin-top: -0.125rem;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.wishlist {
|
||||
&-container {
|
||||
.page-content.card {
|
||||
box-shadow: 0.125rem 0.125rem 0.5rem 0 rgba(0, 0, 0, 0.2);
|
||||
background-color: #fff;
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
import initApp from '@components/init';
|
||||
import WishlistContainer from './WishlistContainer';
|
||||
|
||||
const props = [
|
||||
{
|
||||
name: 'url',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'title',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'addText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'renameText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'emptyText',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'homeLink',
|
||||
type: String,
|
||||
},
|
||||
{
|
||||
name: 'shareText',
|
||||
type: String,
|
||||
},
|
||||
];
|
||||
|
||||
initApp(WishlistContainer, '.wishlist-container', props);
|
||||
36
modules/blockwishlist/_dev/front/js/graphql/client.js
Normal file
36
modules/blockwishlist/_dev/front/js/graphql/client.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import {ApolloClient} from 'apollo-client';
|
||||
import {SchemaLink} from 'apollo-link-schema';
|
||||
import {InMemoryCache} from 'apollo-cache-inmemory';
|
||||
import link from './link';
|
||||
|
||||
/**
|
||||
* Enabling client side cache
|
||||
*/
|
||||
const cache = new InMemoryCache();
|
||||
|
||||
/**
|
||||
* Creating the ApolloClient managing cache and schemas
|
||||
*/
|
||||
export default new ApolloClient({
|
||||
link: new SchemaLink({schema: link}),
|
||||
cache,
|
||||
});
|
||||
31
modules/blockwishlist/_dev/front/js/graphql/link.js
Normal file
31
modules/blockwishlist/_dev/front/js/graphql/link.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import {makeExecutableSchema} from 'graphql-tools';
|
||||
import resolvers from './resolvers';
|
||||
import typeDefs from './types';
|
||||
|
||||
/**
|
||||
* Generate SchemaLink that ApolloClient needs to understand schemas
|
||||
* and link resolvers to schemas
|
||||
*/
|
||||
export default makeExecutableSchema({
|
||||
typeDefs,
|
||||
resolvers,
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation addToList($listId: Int!, $productId: Int!, $quantity: Int!, $productAttributeId: Int!, $url: String!) {
|
||||
addToList(
|
||||
listId: $listId
|
||||
productId: $productId
|
||||
quantity: $quantity
|
||||
productAttributeId: $productAttributeId
|
||||
url: $url
|
||||
) {
|
||||
success
|
||||
message
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation createList($name: String!, $url: String!) {
|
||||
createList(name: $name, url: $url) {
|
||||
message
|
||||
datas {
|
||||
name
|
||||
id_wishlist
|
||||
}
|
||||
success
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation deleteList($listId: Int!, $url: String!) {
|
||||
deleteList(listId: $listId, url: $url) {
|
||||
success
|
||||
message
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation removeFromList($listId: Int!, $productId: Int!, $productAttributeId: Int!, $url: String!) {
|
||||
removeFromList(listId: $listId, productId: $productId, productAttributeId: $productAttributeId, url: $url) {
|
||||
success
|
||||
message
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation renameList($name: String!, $url: String!, $listId: Int!) {
|
||||
renameList(name: $name, url: $url, listId: $listId) {
|
||||
message
|
||||
success
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
mutation shareList($listId: Int!, $userId: Int!) {
|
||||
shareList(listId: $listId, userId: $userId) {
|
||||
url
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
query lists($url: String!) {
|
||||
lists(url: $url) {
|
||||
id_wishlist
|
||||
name
|
||||
listUrl
|
||||
shareUrl
|
||||
nbProducts
|
||||
default
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export default gql`
|
||||
query getProducts($listId: Int!, $url: String!) {
|
||||
products(listId: $listId, url: $url) {
|
||||
datas
|
||||
}
|
||||
}
|
||||
`;
|
||||
197
modules/blockwishlist/_dev/front/js/graphql/resolvers.js
Normal file
197
modules/blockwishlist/_dev/front/js/graphql/resolvers.js
Normal file
@@ -0,0 +1,197 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import EventBus from '@components/EventBus';
|
||||
import headers from '@constants/headers';
|
||||
import GraphQLJSON, {GraphQLJSONObject} from 'graphql-type-json';
|
||||
|
||||
/**
|
||||
* Resolvers linked to schemas definitions
|
||||
*/
|
||||
export default {
|
||||
JSON: GraphQLJSON,
|
||||
JSONObject: GraphQLJSONObject,
|
||||
Query: {
|
||||
/**
|
||||
* Get product from a list
|
||||
*/
|
||||
products: async (root, {url}) => {
|
||||
const response = await fetch(`${url}&from-xhr`, {
|
||||
headers: headers.products,
|
||||
});
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
EventBus.$emit('paginate', {
|
||||
detail: {
|
||||
total: datas.pagination.total_items,
|
||||
minShown: datas.pagination.items_shown_from,
|
||||
maxShown: datas.pagination.items_shown_to,
|
||||
pageNumber: datas.pagination.pages_count,
|
||||
pages: datas.pagination.pages,
|
||||
display: datas.pagination.should_be_displayed,
|
||||
currentPage: datas.pagination.current_page,
|
||||
},
|
||||
});
|
||||
|
||||
window.history.pushState(datas, document.title, datas.current_url);
|
||||
window.scrollTo(0, 0);
|
||||
|
||||
return {
|
||||
datas: {
|
||||
products: datas.products,
|
||||
pagination: datas.pagination,
|
||||
current_url: datas.current_url,
|
||||
sort_orders: datas.sort_orders,
|
||||
sort_selected: datas.sort_selected,
|
||||
},
|
||||
};
|
||||
},
|
||||
/**
|
||||
* Get every lists from User
|
||||
*/
|
||||
lists: async (root, {url}) => {
|
||||
const response = await fetch(url);
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
return datas.wishlists;
|
||||
},
|
||||
},
|
||||
Mutation: {
|
||||
/**
|
||||
* Create a list based on a name and an userId
|
||||
*
|
||||
* @param {String} name The name of the list
|
||||
* @param {Int} userId The ID of the user you want to create a list on
|
||||
*/
|
||||
createList: async (root, {name, url}) => {
|
||||
const nameEncoded = encodeURIComponent(name);
|
||||
|
||||
const response = await fetch(`${url}¶ms[name]=${nameEncoded}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
return datas;
|
||||
},
|
||||
/**
|
||||
* Rename a list
|
||||
*
|
||||
* @param {String} {name New name of the list
|
||||
* @param {Int} userId Id of the user
|
||||
* @param {Int} listId} ID of the list to be renamed
|
||||
*/
|
||||
renameList: async (root, {name, listId, url}) => {
|
||||
const response = await fetch(`${url}¶ms[name]=${name}¶ms[idWishList]=${listId}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
return datas;
|
||||
},
|
||||
/**
|
||||
* Add a product to a list
|
||||
*
|
||||
* @param {Int} listId The list id
|
||||
* @param {Int} userId The user id
|
||||
* @param {Int} productId The product id to be added to the list id
|
||||
*
|
||||
* @returns {JSON} A success or failed response
|
||||
*/
|
||||
addToList: async (root, {
|
||||
listId, url, productId, quantity, productAttributeId,
|
||||
}) => {
|
||||
/* eslint-disable */
|
||||
const response = await fetch(
|
||||
`${url}¶ms[id_product]=${productId}¶ms[idWishList]=${listId}¶ms[quantity]=${quantity}¶ms[id_product_attribute]=${productAttributeId}`,
|
||||
{
|
||||
method: 'POST'
|
||||
}
|
||||
);
|
||||
/* eslint-enable */
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
if (datas.success) {
|
||||
// eslint-disable-next-line
|
||||
productsAlreadyTagged.push({
|
||||
id_product: productId.toString(),
|
||||
id_wishlist: listId.toString(),
|
||||
quantity: quantity.toString(),
|
||||
id_product_attribute: productAttributeId.toString(),
|
||||
});
|
||||
}
|
||||
|
||||
return datas;
|
||||
},
|
||||
/**
|
||||
* Remove a product from a list
|
||||
*
|
||||
* @param {Int} listId The list id
|
||||
* @param {Int} userId The user id
|
||||
* @param {Int} productId The product id to be removed from the list id
|
||||
*
|
||||
* @returns {JSON} A success or failed response
|
||||
*/
|
||||
removeFromList: async (root, {
|
||||
listId, productId, url, productAttributeId,
|
||||
}) => {
|
||||
/* eslint-disable */
|
||||
const response = await fetch(
|
||||
`${url}¶ms[id_product]=${productId}¶ms[idWishList]=${listId}¶ms[id_product_attribute]=${productAttributeId}`,
|
||||
{
|
||||
method: 'POST'
|
||||
}
|
||||
);
|
||||
/* eslint-enable */
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
if (datas.success) {
|
||||
// eslint-disable-next-line
|
||||
productsAlreadyTagged = productsAlreadyTagged.filter(
|
||||
(e) => e.id_product !== productId.toString()
|
||||
|| (e.id_product_attribute !== productAttributeId.toString() && e.id_product === productId.toString())
|
||||
|| e.id_wishlist !== listId.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
return datas;
|
||||
},
|
||||
/**
|
||||
* Remove a list
|
||||
*
|
||||
* @param {Int} {listId} The list id
|
||||
*
|
||||
* @returns {JSON} a JSON success or failed response
|
||||
*/
|
||||
deleteList: async (root, {listId, url}) => {
|
||||
const response = await fetch(`${url}¶ms[idWishList]=${listId}`, {
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
const datas = await response.json();
|
||||
|
||||
return datas;
|
||||
},
|
||||
},
|
||||
};
|
||||
64
modules/blockwishlist/_dev/front/js/graphql/types.js
Normal file
64
modules/blockwishlist/_dev/front/js/graphql/types.js
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
export default `
|
||||
scalar JSON
|
||||
scalar JSONObject
|
||||
|
||||
type List {
|
||||
id_wishlist: Int
|
||||
name: String
|
||||
listUrl: String
|
||||
shareUrl: String
|
||||
default: Int
|
||||
nbProducts: Int
|
||||
}
|
||||
|
||||
type ShareUrl {
|
||||
url: String
|
||||
}
|
||||
|
||||
type CreateResponse {
|
||||
datas: List
|
||||
success: Boolean!
|
||||
message: String!
|
||||
}
|
||||
|
||||
type ProductListResponse {
|
||||
datas: JSONObject
|
||||
}
|
||||
|
||||
type Response {
|
||||
success: Boolean!
|
||||
message: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
products(listId: Int!, url: String!): ProductListResponse
|
||||
lists(url: String!): [List]
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createList(name: String!, url: String!): CreateResponse
|
||||
shareList(listId: String!, userId: Int!): ShareUrl
|
||||
renameList(name: String!, url: String!, listId: Int!): Response
|
||||
addToList(listId: Int!, productId: Int!, quantity: Int!, productAttributeId: Int!, url: String!): Response
|
||||
removeFromList(listId: Int!, productId: Int!, productAttributeId: Int!, url: String!): Response
|
||||
deleteList(listId: Int!, url: String!): Response
|
||||
}
|
||||
`;
|
||||
54
modules/blockwishlist/_dev/front/js/pages/list/index.js
Normal file
54
modules/blockwishlist/_dev/front/js/pages/list/index.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
import initVueButtons from '@components/Button';
|
||||
import removeFromWishlistUrl from 'removeFromWishlistUrl';
|
||||
|
||||
const initButtons = () => {
|
||||
const products = document.querySelectorAll('.js-product-miniature');
|
||||
|
||||
products.forEach((product) => {
|
||||
const wishlistButton = document.createElement('div');
|
||||
|
||||
wishlistButton.classList.add('wishlist-button');
|
||||
wishlistButton.dataset.productId = product.dataset.idProduct;
|
||||
wishlistButton.dataset.url = removeFromWishlistUrl;
|
||||
wishlistButton.dataset.productAttributeId = product.dataset.idProductAttribute;
|
||||
wishlistButton.dataset.checked = false;
|
||||
|
||||
product.querySelector('.thumbnail-container').append(wishlistButton);
|
||||
});
|
||||
};
|
||||
|
||||
initButtons();
|
||||
initVueButtons();
|
||||
|
||||
const productList = document.querySelectorAll('#products, .featured-products');
|
||||
const config = {attributes: false, childList: true};
|
||||
|
||||
productList.forEach((e) => {
|
||||
const callback = function () {
|
||||
initButtons();
|
||||
initVueButtons();
|
||||
};
|
||||
|
||||
const observer = new MutationObserver(callback);
|
||||
|
||||
observer.observe(e, config);
|
||||
});
|
||||
23
modules/blockwishlist/_dev/front/scss/_footer-links.scss
Normal file
23
modules/blockwishlist/_dev/front/scss/_footer-links.scss
Normal file
@@ -0,0 +1,23 @@
|
||||
.wishlist {
|
||||
&-footer {
|
||||
&-links {
|
||||
margin-bottom: 3.125rem;
|
||||
|
||||
> a {
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.1875rem;
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 1.25rem;
|
||||
margin-right: 0.25rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
114
modules/blockwishlist/_dev/front/scss/_modal.scss
Normal file
114
modules/blockwishlist/_dev/front/scss/_modal.scss
Normal file
@@ -0,0 +1,114 @@
|
||||
.wishlist-modal {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
|
||||
&.show {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1051;
|
||||
|
||||
+ .modal-backdrop {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
|
||||
&.fade .modal-dialog {
|
||||
max-width: 34.375rem;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.close {
|
||||
font-weight: 400;
|
||||
color: #7a7a7a;
|
||||
opacity: 1;
|
||||
font-size: 2.25rem;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
&-header {
|
||||
padding: 0.625rem 1.875rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border: none;
|
||||
|
||||
h5 {
|
||||
color: #232323;
|
||||
font-size: 1.375rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
color: #232323;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
|
||||
&-body {
|
||||
padding: 0.9375 1.875rem;
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 0;
|
||||
|
||||
.form-control {
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
color: black;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-cancel {
|
||||
margin-right: 0.625rem;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
&-footer {
|
||||
padding: 0.75rem 1.875rem;
|
||||
border: none;
|
||||
padding-bottom: 1.875rem;
|
||||
|
||||
.btn {
|
||||
text-transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-backdrop {
|
||||
pointer-events: none;
|
||||
|
||||
&.in {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ .modal-backdrop {
|
||||
pointer-events: none;
|
||||
|
||||
&.in {
|
||||
pointer-events: all;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
modules/blockwishlist/_dev/front/scss/_product.scss
Normal file
12
modules/blockwishlist/_dev/front/scss/_product.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
.products {
|
||||
article {
|
||||
.wishlist {
|
||||
&-button-add {
|
||||
position: absolute;
|
||||
top: 0.635rem;
|
||||
right: 0.635rem;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
modules/blockwishlist/_dev/front/scss/_rtl.scss
Normal file
48
modules/blockwishlist/_dev/front/scss/_rtl.scss
Normal file
@@ -0,0 +1,48 @@
|
||||
.lang-rtl {
|
||||
|
||||
.products {
|
||||
|
||||
article {
|
||||
|
||||
.wishlist {
|
||||
|
||||
&-button-add {
|
||||
right: inherit;
|
||||
left: 0.635rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wishlist {
|
||||
|
||||
&-button {
|
||||
|
||||
&-product {
|
||||
margin-left: 0;
|
||||
margin-right: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
&-list {
|
||||
|
||||
&-item {
|
||||
|
||||
.dropdown-menu {
|
||||
right: inherit;
|
||||
left: 1.25rem;
|
||||
}
|
||||
|
||||
&-right {
|
||||
|
||||
.dropdown-menu {
|
||||
|
||||
> button {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
modules/blockwishlist/_dev/front/scss/_variables.scss
Normal file
1
modules/blockwishlist/_dev/front/scss/_variables.scss
Normal file
@@ -0,0 +1 @@
|
||||
$blue: #2fb5d2;
|
||||
131
modules/blockwishlist/_dev/front/scss/common.css
Normal file
131
modules/blockwishlist/_dev/front/scss/common.css
Normal file
@@ -0,0 +1,131 @@
|
||||
.wishlist-modal {
|
||||
display: none;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: 0;
|
||||
}
|
||||
.wishlist-modal.show {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
pointer-events: all;
|
||||
z-index: 1051;
|
||||
}
|
||||
.wishlist-modal.show + .modal-backdrop {
|
||||
pointer-events: all;
|
||||
}
|
||||
.wishlist-modal.fade .modal-dialog {
|
||||
max-width: 34.375rem;
|
||||
transform: translateY(0);
|
||||
}
|
||||
.wishlist-modal .close {
|
||||
font-weight: 400;
|
||||
color: #7a7a7a;
|
||||
opacity: 1;
|
||||
font-size: 2.25rem;
|
||||
}
|
||||
.wishlist-modal .close:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
.wishlist-modal .modal-header {
|
||||
padding: 0.625rem 1.875rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border: none;
|
||||
}
|
||||
.wishlist-modal .modal-header h5 {
|
||||
color: #232323;
|
||||
font-size: 1.375rem;
|
||||
font-weight: bold;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
.wishlist-modal .modal-header::after {
|
||||
content: none;
|
||||
}
|
||||
.wishlist-modal .modal-text {
|
||||
color: #232323;
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.875rem;
|
||||
}
|
||||
.wishlist-modal .modal-body {
|
||||
padding: 0.9375 1.875rem;
|
||||
}
|
||||
.wishlist-modal .modal-body .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.wishlist-modal .modal-body .form-group .form-control {
|
||||
border-radius: 0;
|
||||
background: none;
|
||||
color: black;
|
||||
}
|
||||
.wishlist-modal .modal-content {
|
||||
width: 100%;
|
||||
}
|
||||
.wishlist-modal .modal-cancel {
|
||||
margin-right: 0.625rem;
|
||||
}
|
||||
.wishlist-modal .modal-cancel:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.wishlist-modal .modal-footer {
|
||||
padding: 0.75rem 1.875rem;
|
||||
border: none;
|
||||
padding-bottom: 1.875rem;
|
||||
}
|
||||
.wishlist-modal .modal-footer .btn {
|
||||
text-transform: none;
|
||||
}
|
||||
.wishlist-modal .modal-backdrop {
|
||||
pointer-events: none;
|
||||
}
|
||||
.wishlist-modal .modal-backdrop.in {
|
||||
pointer-events: all;
|
||||
}
|
||||
.wishlist-modal + .modal-backdrop {
|
||||
pointer-events: none;
|
||||
}
|
||||
.wishlist-modal + .modal-backdrop.in {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.products article .wishlist-button-add {
|
||||
position: absolute;
|
||||
top: 0.635rem;
|
||||
right: 0.635rem;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.wishlist-footer-links {
|
||||
margin-bottom: 3.125rem;
|
||||
}
|
||||
.wishlist-footer-links > a {
|
||||
font-size: 0.875rem;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.1875rem;
|
||||
}
|
||||
.wishlist-footer-links > a:not(:first-child) {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
.wishlist-footer-links > a i {
|
||||
font-size: 1.25rem;
|
||||
margin-right: 0.25rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.lang-rtl .products article .wishlist-button-add {
|
||||
right: inherit;
|
||||
left: 0.635rem;
|
||||
}
|
||||
.lang-rtl .wishlist-button-product {
|
||||
margin-left: 0;
|
||||
margin-right: 1.25rem;
|
||||
}
|
||||
.lang-rtl .wishlist-list-item .dropdown-menu {
|
||||
right: inherit;
|
||||
left: 1.25rem;
|
||||
}
|
||||
.lang-rtl .wishlist-list-item-right .dropdown-menu > button {
|
||||
text-align: right;
|
||||
}/*# sourceMappingURL=common.css.map */
|
||||
1
modules/blockwishlist/_dev/front/scss/common.css.map
Normal file
1
modules/blockwishlist/_dev/front/scss/common.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["_modal.scss","common.css","_product.scss","_footer-links.scss","_rtl.scss"],"names":[],"mappings":"AAAA;EACE,aAAA;EACA,UAAA;EACA,oBAAA;EACA,UAAA;ACCF;ADCE;EACE,cAAA;EACA,UAAA;EACA,mBAAA;EACA,aAAA;ACCJ;ADCI;EACE,mBAAA;ACCN;ADGE;EACE,oBAAA;EACA,wBAAA;ACDJ;ADIE;EACE,gBAAA;EACA,cAAA;EACA,UAAA;EACA,kBAAA;ACFJ;ADII;EACE,YAAA;ACFN;ADOI;EACE,0BAAA;EACA,aAAA;EACA,mBAAA;EACA,8BAAA;EACA,YAAA;ACLN;ADOM;EACE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,iBAAA;EACA,qBAAA;ACLR;ADQM;EACE,aAAA;ACNR;ADUI;EACE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;ACRN;ADWI;EACE,wBAAA;ACTN;ADWM;EACE,gBAAA;ACTR;ADWQ;EACE,gBAAA;EACA,gBAAA;EACA,YAAA;ACTV;ADcI;EACE,WAAA;ACZN;ADeI;EACE,sBAAA;ACbN;ADeM;EACE,YAAA;ACbR;ADiBI;EACE,yBAAA;EACA,YAAA;EACA,wBAAA;ACfN;ADiBM;EACE,oBAAA;ACfR;ADmBI;EACE,oBAAA;ACjBN;ADmBM;EACE,mBAAA;ACjBR;ADsBE;EACE,oBAAA;ACpBJ;ADsBI;EACE,mBAAA;ACpBN;;ACvFM;EACE,kBAAA;EACA,aAAA;EACA,eAAA;EACA,WAAA;AD0FR;;AE/FI;EACE,uBAAA;AFkGN;AEhGM;EACE,mBAAA;EACA,iBAAA;EACA,sBAAA;AFkGR;AEhGQ;EACE,oBAAA;AFkGV;AE/FQ;EACE,kBAAA;EACA,qBAAA;EACA,sBAAA;AFiGV;;AG1GQ;EACE,cAAA;EACA,cAAA;AH6GV;AGnGM;EACE,cAAA;EACA,qBAAA;AHqGR;AG7FQ;EACE,cAAA;EACA,aAAA;AH+FV;AGxFY;EACE,iBAAA;AH0Fd","file":"common.css"}
|
||||
5
modules/blockwishlist/_dev/front/scss/common.scss
Normal file
5
modules/blockwishlist/_dev/front/scss/common.scss
Normal file
@@ -0,0 +1,5 @@
|
||||
@import '_variables';
|
||||
@import '_modal';
|
||||
@import '_product';
|
||||
@import '_footer-links';
|
||||
@import '_rtl';
|
||||
319
modules/blockwishlist/blockwishlist.php
Normal file
319
modules/blockwishlist/blockwishlist.php
Normal file
@@ -0,0 +1,319 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
use PrestaShop\Module\BlockWishList\Database\Install;
|
||||
use PrestaShop\Module\BlockWishList\Database\Uninstall;
|
||||
use PrestaShop\PrestaShop\Adapter\SymfonyContainer;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$autoloadPath = __DIR__ . '/vendor/autoload.php';
|
||||
if (file_exists($autoloadPath)) {
|
||||
require_once $autoloadPath;
|
||||
}
|
||||
|
||||
class BlockWishList extends Module
|
||||
{
|
||||
const HOOKS = [
|
||||
'actionAdminControllerSetMedia',
|
||||
'actionFrontControllerSetMedia',
|
||||
'actionAttributeDelete',
|
||||
'actionProductDelete',
|
||||
'actionProductAttributeDelete',
|
||||
'deleteProductAttribute',
|
||||
'displayProductActions',
|
||||
'displayCustomerAccount',
|
||||
'displayFooter',
|
||||
'displayAdminCustomers',
|
||||
'displayMyAccountBlock',
|
||||
];
|
||||
|
||||
const MODULE_ADMIN_CONTROLLERS = [
|
||||
[
|
||||
'class_name' => 'WishlistConfigurationAdminParentController',
|
||||
'visible' => false,
|
||||
'parent_class_name' => 'AdminParentModulesSf',
|
||||
'name' => 'Wishlist Module',
|
||||
],
|
||||
[
|
||||
'class_name' => 'WishlistConfigurationAdminController',
|
||||
'visible' => true,
|
||||
'parent_class_name' => 'WishlistConfigurationAdminParentController',
|
||||
'name' => 'Configuration',
|
||||
],
|
||||
[
|
||||
'class_name' => 'WishlistStatisticsAdminController',
|
||||
'visible' => true,
|
||||
'parent_class_name' => 'WishlistConfigurationAdminParentController',
|
||||
'name' => 'Statistics',
|
||||
],
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->name = 'blockwishlist';
|
||||
$this->tab = 'front_office_features';
|
||||
$this->version = '2.1.2';
|
||||
$this->author = 'PrestaShop';
|
||||
$this->need_instance = 0;
|
||||
|
||||
parent::__construct();
|
||||
|
||||
$this->displayName = $this->trans('Wishlist', [], 'Modules.Blockwishlist.Admin');
|
||||
$this->description = $this->trans('Allow customers to create wishlists to save their favorite products for later.', [], 'Modules.Blockwishlist.Admin');
|
||||
$this->ps_versions_compliancy = [
|
||||
'min' => '1.7.6.0',
|
||||
'max' => _PS_VERSION_,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function install()
|
||||
{
|
||||
if (false === (new Install($this->getTranslator()))->run()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parent::install()
|
||||
&& $this->registerHook(static::HOOKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function uninstall()
|
||||
{
|
||||
return (new Uninstall())->run()
|
||||
&& parent::uninstall();
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
Tools::redirectAdmin(
|
||||
SymfonyContainer::getInstance()->get('router')->generate('blockwishlist_configuration')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add asset for Administration
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function hookActionAdminControllerSetMedia(array $params)
|
||||
{
|
||||
$this->context->controller->addCss($this->getPathUri() . 'public/backoffice.css');
|
||||
|
||||
$this->context->controller->addJs($this->getPathUri() . 'public/vendors.js');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add asset for Shop Front Office
|
||||
*
|
||||
* @see https://devdocs.prestashop.com/1.7/themes/getting-started/asset-management/#without-a-front-controller-module
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function hookActionFrontControllerSetMedia(array $params)
|
||||
{
|
||||
$productsTagged = true === $this->context->customer->isLogged()
|
||||
? WishList::getAllProductByCustomer($this->context->customer->id, $this->context->shop->id)
|
||||
: false;
|
||||
|
||||
Media::addJsDef([
|
||||
'blockwishlistController' => $this->context->link->getModuleLink(
|
||||
$this->name,
|
||||
'action'
|
||||
),
|
||||
'removeFromWishlistUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'deleteProductFromWishlist']),
|
||||
'wishlistUrl' => $this->context->link->getModuleLink('blockwishlist', 'view'),
|
||||
'wishlistAddProductToCartUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'addProductToCart']),
|
||||
'productsAlreadyTagged' => $productsTagged ?: [],
|
||||
]);
|
||||
|
||||
$this->context->controller->registerStylesheet(
|
||||
'blockwishlistController',
|
||||
'modules/' . $this->name . '/public/wishlist.css',
|
||||
[
|
||||
'media' => 'all',
|
||||
'priority' => 100,
|
||||
]
|
||||
);
|
||||
|
||||
$this->context->controller->registerJavascript(
|
||||
'blockwishlistController',
|
||||
'modules/' . $this->name . '/public/product.bundle.js',
|
||||
[
|
||||
'priority' => 100,
|
||||
]
|
||||
);
|
||||
|
||||
$this->context->controller->registerJavascript(
|
||||
'blockwishlistGraphql',
|
||||
'modules/' . $this->name . '/public/graphql.js',
|
||||
[
|
||||
'priority' => 190,
|
||||
]
|
||||
);
|
||||
|
||||
$this->context->controller->registerJavascript(
|
||||
'blockwishlistVendors',
|
||||
'modules/' . $this->name . '/public/vendors.js',
|
||||
[
|
||||
'priority' => 190,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook allow additional action button, near the add to cart button on the product page
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hookDisplayProductActions(array $params)
|
||||
{
|
||||
$this->smarty->assign([
|
||||
'blockwishlist' => $this->displayName,
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'deleteProductFromWishlist']),
|
||||
]);
|
||||
|
||||
return $this->fetch('module:blockwishlist/views/templates/hook/product/add-button.tpl');
|
||||
}
|
||||
|
||||
public function hookActionProductDelete(array $params)
|
||||
{
|
||||
if (!isset($params['id_product'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
WishList::removeProductFromWishlist($params['id_product']);
|
||||
Statistics::removeProductFromStatistics($params['id_product']);
|
||||
}
|
||||
|
||||
public function hookActionProductAttributeDelete(array $params)
|
||||
{
|
||||
if (!isset($params['id_product']) || !isset($params['id_product_attribute'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove all attributes from a product
|
||||
if (!empty($params['deleteAllAttributes'])) {
|
||||
$this->hookActionProductDelete($params);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WishList::removeProductFromWishlist($params['id_product'], $params['id_product_attribute']);
|
||||
Statistics::removeProductFromStatistics($params['id_product'], $params['id_product_attribute']);
|
||||
}
|
||||
|
||||
public function hookActionAttributeDelete(array $params)
|
||||
{
|
||||
if (!isset($params['id_attribute'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
WishList::removeProductFromWishlist(null, $params['id_product_attribute']);
|
||||
Statistics::removeProductFromStatistics(null, $params['id_product_attribute']);
|
||||
}
|
||||
|
||||
public function hookDeleteProductAttribute(array $params)
|
||||
{
|
||||
$this->hookActionProductAttributeDelete($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook displays new elements on the customer account page
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hookDisplayCustomerAccount(array $params)
|
||||
{
|
||||
$this->smarty->assign([
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'lists'),
|
||||
'wishlistsTitlePage' => Configuration::get('blockwishlist_WishlistPageName', $this->context->language->id),
|
||||
]);
|
||||
|
||||
return $this->fetch('module:blockwishlist/views/templates/hook/displayCustomerAccount.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook displays a new block on the admin customer page
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hookDisplayAdminCustomers(array $params)
|
||||
{
|
||||
$this->smarty->assign([
|
||||
'blockwishlist' => $this->displayName,
|
||||
]);
|
||||
|
||||
return $this->fetch('module:blockwishlist/views/templates/hook/displayAdminCustomers.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display additional information inside the "my account" block
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hookDisplayMyAccountBlock(array $params)
|
||||
{
|
||||
$this->smarty->assign([
|
||||
'blockwishlist' => $this->displayName,
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'lists'),
|
||||
'wishlistsTitlePage' => Configuration::get('blockwishlist_WishlistPageName', $this->context->language->id),
|
||||
]);
|
||||
|
||||
return $this->fetch('module:blockwishlist/views/templates/hook/account/myaccount-block.tpl');
|
||||
}
|
||||
|
||||
/**
|
||||
* This hook adds additional elements in the footer section of your pages
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function hookDisplayFooter(array $params)
|
||||
{
|
||||
$this->smarty->assign([
|
||||
'context' => $this->context->controller->php_self,
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'getAllWishlist']),
|
||||
'deleteListUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'deleteWishlist']),
|
||||
'createUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'createNewWishlist']),
|
||||
'deleteProductUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'deleteProductFromWishlist']),
|
||||
'addUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'addProductToWishlist']),
|
||||
'newWishlistCTA' => Configuration::get('blockwishlist_CreateButtonLabel', $this->context->language->id),
|
||||
]);
|
||||
|
||||
return $this->fetch('module:blockwishlist/views/templates/hook/displayHeader.tpl');
|
||||
}
|
||||
}
|
||||
74
modules/blockwishlist/classes/Statistics.php
Normal file
74
modules/blockwishlist/classes/Statistics.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
class Statistics extends ObjectModel
|
||||
{
|
||||
/** @var int ID */
|
||||
public $id_statistics;
|
||||
|
||||
/** @var int id_product */
|
||||
public $id_product;
|
||||
|
||||
/** @var int id_product_attribute */
|
||||
public $id_product_attribute;
|
||||
|
||||
/** @var string date_add */
|
||||
public $date_add;
|
||||
|
||||
/** @var int|null date_add */
|
||||
public $id_cart;
|
||||
|
||||
/** @var int ID */
|
||||
public $id_shop;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'blockwishlist_statistics',
|
||||
'primary' => 'id_statistics',
|
||||
'fields' => [
|
||||
'id_cart' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => false],
|
||||
'id_product' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'id_product_attribute' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'required' => true],
|
||||
'id_shop' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* @param int|null $id_product
|
||||
* @param int|null $id_product_attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function removeProductFromStatistics($id_product = null, $id_product_attribute = null)
|
||||
{
|
||||
if ($id_product === null && $id_product_attribute === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Db::getInstance()->delete(
|
||||
'blockwishlist_statistics',
|
||||
($id_product ? 'id_product = ' . (int) $id_product : '')
|
||||
. ($id_product && $id_product_attribute ? ' AND ' : '')
|
||||
. ($id_product_attribute ? ' id_product_attribute = ' . (int) $id_product_attribute : '')
|
||||
);
|
||||
}
|
||||
}
|
||||
643
modules/blockwishlist/classes/WishList.php
Normal file
643
modules/blockwishlist/classes/WishList.php
Normal file
@@ -0,0 +1,643 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
class WishList extends ObjectModel
|
||||
{
|
||||
/** @var int Wishlist ID */
|
||||
public $id;
|
||||
|
||||
/** @var int Customer ID */
|
||||
public $id_customer;
|
||||
|
||||
/** @var int Token */
|
||||
public $token;
|
||||
|
||||
/** @var string Name */
|
||||
public $name;
|
||||
|
||||
/** @var string Object creation date */
|
||||
public $date_add;
|
||||
|
||||
/** @var string Object last modification date */
|
||||
public $date_upd;
|
||||
|
||||
/** @var int Object last modification date */
|
||||
public $id_shop;
|
||||
|
||||
/** @var int Object last modification date */
|
||||
public $id_shop_group;
|
||||
|
||||
/** @var int default */
|
||||
public $default;
|
||||
|
||||
/**
|
||||
* @see ObjectModel::$definition
|
||||
*/
|
||||
public static $definition = [
|
||||
'table' => 'wishlist',
|
||||
'primary' => 'id_wishlist',
|
||||
'fields' => [
|
||||
'id_customer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true],
|
||||
'token' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true],
|
||||
'name' => ['type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true],
|
||||
'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'date_upd' => ['type' => self::TYPE_DATE, 'validate' => 'isDate'],
|
||||
'id_shop' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'id_shop_group' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedId'],
|
||||
'default' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Get Customers having a wishlist
|
||||
*
|
||||
* @return array Results
|
||||
*/
|
||||
public static function getCustomers()
|
||||
{
|
||||
$cache_id = 'WishList::getCustomers';
|
||||
|
||||
if (false === Cache::isStored($cache_id)) {
|
||||
$result = Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT c.`id_customer`, c.`firstname`, c.`lastname`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist` w
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'customer` c ON c.`id_customer` = w.`id_customer`
|
||||
ORDER BY c.`firstname` ASC'
|
||||
);
|
||||
|
||||
Cache::store($cache_id, $result);
|
||||
}
|
||||
|
||||
return Cache::retrieve($cache_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if wishlist exists else false
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_customer
|
||||
*
|
||||
* @return bool exists
|
||||
*/
|
||||
public static function exists($id_wishlist, $id_customer)
|
||||
{
|
||||
$result = Db::getInstance()->getRow('
|
||||
SELECT 1
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist`
|
||||
WHERE `id_wishlist` = ' . (int) $id_wishlist . '
|
||||
AND `id_customer` = ' . (int) $id_customer . '
|
||||
AND `id_shop` = ' . (int) Context::getContext()->shop->id
|
||||
);
|
||||
|
||||
return (bool) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current WishList as default
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setDefault()
|
||||
{
|
||||
if ($default = $this->getDefault($this->id_customer)) {
|
||||
Db::getInstance()->update('wishlist', ['default' => '0'], 'id_wishlist = ' . (int) $default);
|
||||
}
|
||||
|
||||
return Db::getInstance()->update('wishlist', ['default' => '1'], 'id_wishlist = ' . (int) $this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if there is a default already set
|
||||
*
|
||||
* @param int $id_customer
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isDefault($id_customer)
|
||||
{
|
||||
return (bool) Db::getInstance()->getValue('SELECT 1 FROM `' . _DB_PREFIX_ . 'wishlist` WHERE `id_customer` = ' . (int) $id_customer . ' AND `default` = 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id_customer
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getDefault($id_customer)
|
||||
{
|
||||
return (int) Db::getInstance()->getValue('SELECT `id_wishlist` FROM `' . _DB_PREFIX_ . 'wishlist` WHERE `id_customer` = ' . (int) $id_customer . ' AND `default` = 1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add product to ID wishlist
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_customer
|
||||
* @param int $id_product
|
||||
* @param int $id_product_attribute
|
||||
* @param int $quantity
|
||||
*
|
||||
* @return bool succeed
|
||||
*/
|
||||
public static function addProduct($id_wishlist, $id_customer, $id_product, $id_product_attribute, $quantity)
|
||||
{
|
||||
$result = Db::getInstance()->getRow('
|
||||
SELECT wp.`quantity`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product` wp
|
||||
JOIN `' . _DB_PREFIX_ . 'wishlist` w ON (w.`id_wishlist` = wp.`id_wishlist`)
|
||||
WHERE wp.`id_wishlist` = ' . (int) $id_wishlist . '
|
||||
AND w.`id_customer` = ' . (int) $id_customer . '
|
||||
AND wp.`id_product` = ' . (int) $id_product . '
|
||||
AND wp.`id_product_attribute` = ' . (int) ($id_product_attribute)
|
||||
);
|
||||
|
||||
if (!empty($result)) {
|
||||
if ((int) $result['quantity'] + (int) $quantity <= 0) {
|
||||
return WishList::removeProduct($id_wishlist, $id_customer, $id_product, $id_product_attribute);
|
||||
}
|
||||
|
||||
// TODO: use a method for this like updateProduct ?
|
||||
return Db::getInstance()->update(
|
||||
'wishlist_product',
|
||||
[
|
||||
'quantity' => (int) $quantity + (int) $result['quantity'],
|
||||
],
|
||||
'`id_wishlist` = ' . (int) $id_wishlist . ' AND `id_product` = ' . (int) $id_product . ' AND `id_product_attribute` = ' . (int) $id_product_attribute
|
||||
);
|
||||
}
|
||||
|
||||
return Db::getInstance()->insert(
|
||||
'wishlist_product',
|
||||
[
|
||||
'id_wishlist' => (int) $id_wishlist,
|
||||
'id_product' => (int) $id_product,
|
||||
'id_product_attribute' => (int) $id_product_attribute,
|
||||
'quantity' => (int) $quantity,
|
||||
'priority' => 1,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove product from wishlist
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_customer
|
||||
* @param int $id_product
|
||||
* @param int $id_product_attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function removeProduct($id_wishlist, $id_customer, $id_product, $id_product_attribute)
|
||||
{
|
||||
$result = Db::getInstance()->getRow('
|
||||
SELECT w.`id_wishlist`, wp.`id_wishlist_product`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist` w
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'wishlist_product` wp ON (wp.`id_wishlist` = w.`id_wishlist`)
|
||||
WHERE `id_customer` = ' . (int) $id_customer . '
|
||||
AND w.`id_wishlist` = ' . (int) $id_wishlist
|
||||
);
|
||||
|
||||
if (empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Delete product in wishlist_product_cart
|
||||
Db::getInstance()->delete(
|
||||
'wishlist_product_cart',
|
||||
'id_wishlist_product = ' . (int) $result['id_wishlist_product']
|
||||
);
|
||||
|
||||
return Db::getInstance()->delete(
|
||||
'wishlist_product',
|
||||
'id_wishlist = ' . (int) $id_wishlist . ' AND id_product = ' . (int) $id_product . ' AND id_product_attribute = ' . (int) $id_product_attribute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $id_product
|
||||
* @param int|null $id_product_attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function removeProductFromWishlist($id_product = null, $id_product_attribute = null)
|
||||
{
|
||||
if ($id_product === null && $id_product_attribute === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Db::getInstance()->delete(
|
||||
'wishlist_product',
|
||||
($id_product ? 'id_product = ' . (int) $id_product : '')
|
||||
. ($id_product && $id_product_attribute ? ' AND ' : '')
|
||||
. ($id_product_attribute ? ' id_product_attribute = ' . (int) $id_product_attribute : '')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update product to wishlist
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_product
|
||||
* @param int $id_product_attribute
|
||||
* @param int $priority
|
||||
* @param int $quantity
|
||||
*
|
||||
* @return bool succeed
|
||||
*/
|
||||
public static function updateProduct($id_wishlist, $id_product, $id_product_attribute, $priority, $quantity)
|
||||
{
|
||||
if ($priority < 0 || $priority > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Db::getInstance()->update(
|
||||
'wishlist_product',
|
||||
[
|
||||
'priority' => (int) $priority,
|
||||
'quantity' => (int) $quantity,
|
||||
],
|
||||
'id_wishlist = ' . (int) $id_wishlist . 'id_product` = ' . (int) $id_product . 'id_product_attribute` = ' . (int) $id_product_attribute
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Wishlists by Customer ID
|
||||
*
|
||||
* @param int $id_customer
|
||||
*
|
||||
* @return array Results
|
||||
*/
|
||||
public static function getAllWishlistsByIdCustomer($id_customer)
|
||||
{
|
||||
$shop_restriction = '';
|
||||
|
||||
if (Shop::getContextShopID()) {
|
||||
$shop_restriction = 'AND w.id_shop = ' . (int) Shop::getContextShopID();
|
||||
} elseif (Shop::getContextShopGroupID()) {
|
||||
$shop_restriction = 'AND w.id_shop_group = ' . (int) Shop::getContextShopGroupID();
|
||||
}
|
||||
|
||||
$sql = sprintf(
|
||||
'SELECT w.`id_wishlist`, (
|
||||
SELECT COUNT(wp.id_wishlist_product)
|
||||
FROM `%1$swishlist_product` wp
|
||||
INNER JOIN `%1$sproduct` p ON p.`id_product` = wp.`id_product`
|
||||
%2$s
|
||||
WHERE wp.id_wishlist = w.id_wishlist
|
||||
) AS nbProducts, w.`name`, w.`default`, w.`token`
|
||||
FROM `%1$swishlist` w
|
||||
WHERE w.`id_customer` = %3$d %4$s
|
||||
ORDER BY w.`default` DESC, w.`name` ASC',
|
||||
_DB_PREFIX_,
|
||||
Shop::addSqlAssociation('product', 'p', true, 'product_shop.active = 1'),
|
||||
(int) $id_customer,
|
||||
$shop_restriction
|
||||
);
|
||||
|
||||
return Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->executeS($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get products by Wishlist
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
*
|
||||
* @return array|false Results
|
||||
*/
|
||||
public static function getProductsByWishlist($id_wishlist)
|
||||
{
|
||||
$wishlistProducts = Db::getInstance()->executeS('
|
||||
SELECT `id_product`, `id_product_attribute`, `quantity`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product`
|
||||
WHERE `id_wishlist` = ' . (int) $id_wishlist . '
|
||||
And quantity > 0'
|
||||
);
|
||||
|
||||
if (!empty($wishlistProducts)) {
|
||||
return $wishlistProducts;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Wishlist products by Customer ID
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_customer
|
||||
* @param int $id_lang
|
||||
* @param int|null $id_product
|
||||
* @param bool $quantity
|
||||
*
|
||||
* @return array Results
|
||||
*/
|
||||
public static function getProductByIdCustomer($id_wishlist, $id_customer, $id_lang, $id_product = null, $quantity = false)
|
||||
{
|
||||
$products = Db::getInstance()->executeS('
|
||||
SELECT wp.`id_product`, wp.`quantity` as wishlist_quantity, p.`quantity` AS product_quantity, pl.`name`, wp.`id_product_attribute`, wp.`priority`, pl.link_rewrite, cl.link_rewrite AS category_rewrite
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product` wp
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product` p ON p.`id_product` = wp.`id_product`
|
||||
' . Shop::addSqlAssociation('product', 'p') . '
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON pl.`id_product` = wp.`id_product`' . Shop::addSqlRestrictionOnLang('pl') . '
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'wishlist` w ON w.`id_wishlist` = wp.`id_wishlist`
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'category_lang` cl ON cl.`id_category` = product_shop.`id_category_default` AND cl.id_lang=' . (int) $id_lang . Shop::addSqlRestrictionOnLang('cl') . '
|
||||
WHERE w.`id_customer` = ' . (int) $id_customer . '
|
||||
AND pl.`id_lang` = ' . (int) $id_lang . '
|
||||
AND wp.`id_wishlist` = ' . (int) $id_wishlist .
|
||||
(empty($id_product) === false ? ' AND wp.`id_product` = ' . (int) $id_product : '') .
|
||||
($quantity == true ? ' AND wp.`quantity` != 0' : '') . '
|
||||
GROUP BY p.id_product, wp.id_product_attribute'
|
||||
);
|
||||
|
||||
if (empty($products)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
for ($i = 0; $i < sizeof($products); ++$i) {
|
||||
if (isset($products[$i]['id_product_attribute']) &&
|
||||
Validate::isUnsignedInt($products[$i]['id_product_attribute'])) {
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT al.`name` AS attribute_name, pa.`quantity` AS "attribute_quantity"
|
||||
FROM `' . _DB_PREFIX_ . 'product_attribute_combination` pac
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'attribute` a ON (a.`id_attribute` = pac.`id_attribute`)
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group` ag ON (ag.`id_attribute_group` = a.`id_attribute_group`)
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'attribute_lang` al ON (a.`id_attribute` = al.`id_attribute` AND al.`id_lang` = ' . (int) $id_lang . ')
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'attribute_group_lang` agl ON (ag.`id_attribute_group` = agl.`id_attribute_group` AND agl.`id_lang` = ' . (int) $id_lang . ')
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON (pac.`id_product_attribute` = pa.`id_product_attribute`)
|
||||
' . Shop::addSqlAssociation('product_attribute', 'pa') . '
|
||||
WHERE pac.`id_product_attribute` = ' . (int) ($products[$i]['id_product_attribute']));
|
||||
$products[$i]['attributes_small'] = '';
|
||||
if ($result) {
|
||||
foreach ($result as $k => $row) {
|
||||
$products[$i]['attributes_small'] .= $row['attribute_name'] . ', ';
|
||||
}
|
||||
}
|
||||
$products[$i]['attributes_small'] = rtrim($products[$i]['attributes_small'], ', ');
|
||||
if (isset($result[0])) {
|
||||
$products[$i]['attribute_quantity'] = $result[0]['attribute_quantity'];
|
||||
}
|
||||
} else {
|
||||
$products[$i]['attribute_quantity'] = $products[$i]['product_quantity'];
|
||||
}
|
||||
}
|
||||
|
||||
return $products;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add bought product
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
* @param int $id_product
|
||||
* @param int $id_product_attribute
|
||||
* @param int $id_cart
|
||||
* @param int $quantity
|
||||
*
|
||||
* @return bool succeed
|
||||
*/
|
||||
public static function addBoughtProduct($id_wishlist, $id_product, $id_product_attribute, $id_cart, $quantity)
|
||||
{
|
||||
$result = Db::getInstance()->getRow('
|
||||
SELECT `quantity`, `id_wishlist_product`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product` wp
|
||||
WHERE `id_wishlist` = ' . (int) $id_wishlist . '
|
||||
AND `id_product` = ' . (int) $id_product . '
|
||||
AND `id_product_attribute` = ' . (int) $id_product_attribute
|
||||
);
|
||||
|
||||
if (empty($result) ||
|
||||
($result['quantity'] - $quantity) < 0 ||
|
||||
$quantity > $result['quantity']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Db::getInstance()->executeS('
|
||||
SELECT *
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
WHERE `id_wishlist_product`=' . (int) $result['id_wishlist_product'] . ' AND `id_cart`=' . (int) $id_cart
|
||||
);
|
||||
|
||||
if (Db::getInstance()->NumRows() > 0) {
|
||||
$result2 = Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
SET `quantity`=`quantity` + ' . (int) $quantity . '
|
||||
WHERE `id_wishlist_product`=' . (int) $result['id_wishlist_product'] . ' AND `id_cart`=' . (int) $id_cart
|
||||
);
|
||||
} else {
|
||||
$result2 = Db::getInstance()->execute('
|
||||
INSERT INTO `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
(`id_wishlist_product`, `id_cart`, `quantity`, `date_add`) VALUES(
|
||||
' . (int) $result['id_wishlist_product'] . ',
|
||||
' . (int) $id_cart . ',
|
||||
' . (int) $quantity . ',
|
||||
\'' . pSQL(date('Y-m-d H:i:s')) . '\')');
|
||||
}
|
||||
|
||||
if ($result2 === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id_customer
|
||||
* @param int $idShop
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public static function getAllProductByCustomer($id_customer, $idShop)
|
||||
{
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT `id_product`, `id_product_attribute`, w.`id_wishlist`, wp.`quantity`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product` wp
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'wishlist` w ON (w.`id_wishlist` = wp.`id_wishlist`)
|
||||
WHERE w.`id_customer` = ' . (int) $id_customer . '
|
||||
AND w.id_shop = ' . (int) $idShop . '
|
||||
AND wp.`quantity` > 0 ');
|
||||
|
||||
if (empty($result)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ID wishlist by Token
|
||||
*
|
||||
* @param string $token
|
||||
*
|
||||
* @return array Results
|
||||
*
|
||||
* @throws PrestaShopException
|
||||
*/
|
||||
public static function getByToken($token)
|
||||
{
|
||||
if (empty($token) || false === Validate::isMessage($token)) {
|
||||
throw new PrestaShopException('Invalid token');
|
||||
}
|
||||
|
||||
return Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->getRow('
|
||||
SELECT w.`id_wishlist`, w.`name`, w.`id_customer`, c.`firstname`, c.`lastname`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist` w
|
||||
INNER JOIN `' . _DB_PREFIX_ . 'customer` c ON c.`id_customer` = w.`id_customer`
|
||||
WHERE `token` = \'' . pSQL($token) . '\''
|
||||
);
|
||||
}
|
||||
|
||||
public static function refreshWishList($id_wishlist)
|
||||
{
|
||||
$old_carts = Db::getInstance((bool) _PS_USE_SQL_SLAVE_)->executeS('
|
||||
SELECT wp.id_product, wp.id_product_attribute, wpc.id_cart, UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(wpc.date_add) AS timecart
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product_cart` wpc
|
||||
JOIN `' . _DB_PREFIX_ . 'wishlist_product` wp ON (wp.id_wishlist_product = wpc.id_wishlist_product)
|
||||
JOIN `' . _DB_PREFIX_ . 'cart` c ON (c.id_cart = wpc.id_cart)
|
||||
JOIN `' . _DB_PREFIX_ . 'cart_product` cp ON (wpc.id_cart = cp.id_cart)
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON (o.id_cart = c.id_cart)
|
||||
WHERE (wp.id_wishlist=' . (int) $id_wishlist . ' AND o.id_cart IS NULL)
|
||||
HAVING timecart >= 3600*6');
|
||||
|
||||
if (!empty($old_carts)) {
|
||||
foreach ($old_carts as $old_cart) {
|
||||
Db::getInstance()->execute('
|
||||
DELETE FROM `' . _DB_PREFIX_ . 'cart_product`
|
||||
WHERE id_cart=' . (int) $old_cart['id_cart'] . ' AND id_product=' . (int) $old_cart['id_product'] . ' AND id_product_attribute=' . (int) $old_cart['id_product_attribute']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$freshwish = Db::getInstance()->executeS('
|
||||
SELECT wpc.id_cart, wpc.id_wishlist_product
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product_cart` wpc
|
||||
JOIN `' . _DB_PREFIX_ . 'wishlist_product` wp ON (wpc.id_wishlist_product = wp.id_wishlist_product)
|
||||
JOIN `' . _DB_PREFIX_ . 'cart` c ON (c.id_cart = wpc.id_cart)
|
||||
LEFT JOIN `' . _DB_PREFIX_ . 'cart_product` cp ON (cp.id_cart = wpc.id_cart AND cp.id_product = wp.id_product AND cp.id_product_attribute = wp.id_product_attribute)
|
||||
WHERE (wp.id_wishlist = ' . (int) $id_wishlist . ' AND ((cp.id_product IS NULL AND cp.id_product_attribute IS NULL)))
|
||||
');
|
||||
$res = Db::getInstance()->executeS('
|
||||
SELECT wp.id_wishlist_product, cp.quantity AS cart_quantity, wpc.quantity AS wish_quantity, wpc.id_cart
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist_product_cart` wpc
|
||||
JOIN `' . _DB_PREFIX_ . 'wishlist_product` wp ON (wp.id_wishlist_product = wpc.id_wishlist_product)
|
||||
JOIN `' . _DB_PREFIX_ . 'cart` c ON (c.id_cart = wpc.id_cart)
|
||||
JOIN `' . _DB_PREFIX_ . 'cart_product` cp ON (cp.id_cart = wpc.id_cart AND cp.id_product = wp.id_product AND cp.id_product_attribute = wp.id_product_attribute)
|
||||
WHERE wp.id_wishlist=' . (int) $id_wishlist
|
||||
);
|
||||
|
||||
if (!empty($res)) {
|
||||
foreach ($res as $refresh) {
|
||||
if ($refresh['wish_quantity'] > $refresh['cart_quantity']) {
|
||||
Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'wishlist_product`
|
||||
SET `quantity`= `quantity` + ' . ((int) $refresh['wish_quantity'] - (int) $refresh['cart_quantity']) . '
|
||||
WHERE id_wishlist_product=' . (int) $refresh['id_wishlist_product']
|
||||
);
|
||||
Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
SET `quantity`=' . (int) $refresh['cart_quantity'] . '
|
||||
WHERE id_wishlist_product=' . (int) $refresh['id_wishlist_product'] . ' AND id_cart=' . (int) $refresh['id_cart']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!empty($freshwish)) {
|
||||
foreach ($freshwish as $prodcustomer) {
|
||||
Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'wishlist_product` SET `quantity`=`quantity` +
|
||||
(
|
||||
SELECT `quantity` FROM `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
WHERE `id_wishlist_product`=' . (int) $prodcustomer['id_wishlist_product'] . ' AND `id_cart`=' . (int) $prodcustomer['id_cart'] . '
|
||||
)
|
||||
WHERE `id_wishlist_product`=' . (int) $prodcustomer['id_wishlist_product'] . ' AND `id_wishlist`=' . (int) $id_wishlist
|
||||
);
|
||||
Db::getInstance()->execute('
|
||||
DELETE FROM `' . _DB_PREFIX_ . 'wishlist_product_cart`
|
||||
WHERE `id_wishlist_product`=' . (int) $prodcustomer['id_wishlist_product'] . ' AND `id_cart`=' . (int) $prodcustomer['id_cart']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment counter
|
||||
*
|
||||
* @param int $id_wishlist
|
||||
*
|
||||
* @return bool succeed
|
||||
*/
|
||||
public static function incCounter($id_wishlist)
|
||||
{
|
||||
$counter = WishList::getWishlistCounter((int) $id_wishlist);
|
||||
|
||||
++$counter;
|
||||
|
||||
return Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'wishlist` SET
|
||||
`counter` = ' . $counter . '
|
||||
WHERE `id_wishlist` = ' . (int) $id_wishlist
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id_wishlist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getWishlistCounter($id_wishlist)
|
||||
{
|
||||
return (int) Db::getInstance()->getValue('
|
||||
SELECT `counter`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist`
|
||||
WHERE `id_wishlist` = ' . (int) $id_wishlist
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Wishlists by Customer ID
|
||||
*
|
||||
* @param int $id_customer
|
||||
*
|
||||
* @return array Results
|
||||
*/
|
||||
public static function getByIdCustomer($id_customer)
|
||||
{
|
||||
$shop_restriction = '';
|
||||
|
||||
if (Shop::getContextShopID()) {
|
||||
$shop_restriction = 'AND id_shop = ' . (int) Shop::getContextShopID();
|
||||
} elseif (Shop::getContextShopGroupID()) {
|
||||
$shop_restriction = 'AND id_shop_group = ' . (int) Shop::getContextShopGroupID();
|
||||
}
|
||||
|
||||
$cache_id = 'WhishList::getByIdCustomer_' . (int) $id_customer . '-' . (int) Shop::getContextShopID() . '-' . (int) Shop::getContextShopGroupID();
|
||||
if (!Cache::isStored($cache_id)) {
|
||||
$result = Db::getInstance()->executeS('
|
||||
SELECT w.`id_wishlist`, w.`name`, w.`token`, w.`date_add`, w.`date_upd`, w.`counter`, w.`default`
|
||||
FROM `' . _DB_PREFIX_ . 'wishlist` w
|
||||
WHERE `id_customer` = ' . (int) $id_customer . '
|
||||
' . $shop_restriction . '
|
||||
ORDER BY w.`name` ASC'
|
||||
);
|
||||
Cache::store($cache_id, $result);
|
||||
}
|
||||
|
||||
return Cache::retrieve($cache_id);
|
||||
}
|
||||
}
|
||||
28
modules/blockwishlist/classes/index.php
Normal file
28
modules/blockwishlist/classes/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
header('Location: ../');
|
||||
exit;
|
||||
41
modules/blockwishlist/composer.json
Normal file
41
modules/blockwishlist/composer.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "prestashop/blockwishlist",
|
||||
"description": "PrestaShop module blockwishlist",
|
||||
"homepage": "https://github.com/PrestaShop/blockwishlist",
|
||||
"license": "AFL-3.0",
|
||||
"type": "prestashop-module",
|
||||
"authors": [
|
||||
{
|
||||
"name": "PrestaShop SA",
|
||||
"email": "contact@prestashop.com"
|
||||
}
|
||||
],
|
||||
"config": {
|
||||
"platform": {
|
||||
"php": "5.6.0"
|
||||
},
|
||||
"preferred-install": "dist",
|
||||
"classmap-authoritative": true,
|
||||
"optimize-autoloader": true,
|
||||
"sort-packages": true,
|
||||
"prepend-autoloader": false
|
||||
},
|
||||
"require-dev": {
|
||||
"prestashop/php-dev-tools": "~3.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PrestaShop\\Module\\BlockWishList\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"blockwishlist.php",
|
||||
"controllers",
|
||||
"classes"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"set-license-header": [
|
||||
"@php ./vendor/bin/header-stamp --license=\"assets/afl.txt\" --exclude=\".github,.webpack,node_modules,vendor\""
|
||||
]
|
||||
}
|
||||
}
|
||||
1351
modules/blockwishlist/composer.lock
generated
Normal file
1351
modules/blockwishlist/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
12
modules/blockwishlist/config.xml
Normal file
12
modules/blockwishlist/config.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<module>
|
||||
<name>blockwishlist</name>
|
||||
<displayName><![CDATA[Wishlist block]]></displayName>
|
||||
<version><![CDATA[2.1.2]]></version>
|
||||
<description><![CDATA[Adds a block containing the customer's wishlists.]]></description>
|
||||
<author><![CDATA[PrestaShop]]></author>
|
||||
<tab><![CDATA[front_office_features]]></tab>
|
||||
<is_configurable>1</is_configurable>
|
||||
<need_instance>0</need_instance>
|
||||
<limited_countries></limited_countries>
|
||||
</module>
|
||||
21
modules/blockwishlist/config/routes.yml
Normal file
21
modules/blockwishlist/config/routes.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
blockwishlist_configuration:
|
||||
path: blockwishlist/configuration
|
||||
methods: [GET, POST]
|
||||
defaults:
|
||||
_controller: PrestaShop\Module\BlockWishList\Controller\WishlistConfigurationAdminController::configurationAction
|
||||
_legacy_controller: 'WishlistConfigurationAdminController'
|
||||
_legacy_link: 'WishlistConfigurationAdminController'
|
||||
|
||||
blockwishlist_statistics:
|
||||
path: blockwishlist/statistics
|
||||
methods: [GET]
|
||||
defaults:
|
||||
_controller: PrestaShop\Module\BlockWishList\Controller\WishlistConfigurationAdminController::statisticsAction
|
||||
_legacy_controller: 'WishlistStatisticsAdminController'
|
||||
_legacy_link: 'WishlistStatisticsAdminController'
|
||||
|
||||
blockwishlist_statistics_reset:
|
||||
path: blockwishlist/statistics/reset
|
||||
methods: [POST]
|
||||
defaults:
|
||||
_controller: PrestaShop\Module\BlockWishList\Controller\WishlistConfigurationAdminController::resetStatisticsCacheAction
|
||||
103
modules/blockwishlist/config/services.yml
Normal file
103
modules/blockwishlist/config/services.yml
Normal file
@@ -0,0 +1,103 @@
|
||||
services:
|
||||
# Controller
|
||||
PrestaShop\Module\BlockWishList\Controller\WishlistConfigurationAdminController:
|
||||
public: true
|
||||
class: PrestaShop\Module\BlockWishList\Controller\WishlistConfigurationAdminController
|
||||
arguments:
|
||||
- '@doctrine.cache.provider'
|
||||
- '@=service("prestashop.adapter.shop.context").getContextShopID()'
|
||||
|
||||
# Calculator
|
||||
prestashop.module.blockwishlist.calculator.statistics_calculator:
|
||||
public: true
|
||||
class: PrestaShop\Module\BlockWishList\Calculator\StatisticsCalculator
|
||||
arguments:
|
||||
- '@prestashop.adapter.legacy.context' #used for product presenter
|
||||
- '@=service("prestashop.core.localization.locale.repository").getLocale(service("prestashop.adapter.legacy.context").getContext().language.getLocale())' # From PS 1.7.7: "@prestashop.core.localization.locale.context_locale"
|
||||
|
||||
# Grid Definition
|
||||
prestashop.module.blockwishlist.grid.all_time_statistics_grid_definition_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Definition\AllTimeStatisticsGridDefinitionFactory'
|
||||
parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_year_statistics_grid_definition_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Definition\CurrentYearStatisticsGridDefinitionFactory'
|
||||
parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_month_statistics_grid_definition_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Definition\CurrentMonthStatisticsGridDefinitionFactory'
|
||||
parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_day_statistics_grid_definition_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Definition\CurrentDayStatisticsGridDefinitionFactory'
|
||||
parent: 'prestashop.core.grid.definition.factory.abstract_grid_definition'
|
||||
|
||||
# Grid Data Factories
|
||||
prestashop.module.blockwishlist.grid.all_time_statistics_data_factory:
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Data\AllTimeStatisticsGridDataFactory'
|
||||
arguments:
|
||||
- '@doctrine.cache.provider'
|
||||
- '@prestashop.module.blockwishlist.calculator.statistics_calculator'
|
||||
- '@=service("prestashop.adapter.shop.context").getContextShopID()'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_year_statistics_data_factory:
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Data\CurrentYearStatisticsGridDataFactory'
|
||||
arguments:
|
||||
- '@doctrine.cache.provider'
|
||||
- '@prestashop.module.blockwishlist.calculator.statistics_calculator'
|
||||
- '@=service("prestashop.adapter.shop.context").getContextShopID()'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_month_statistics_data_factory:
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Data\CurrentMonthStatisticsGridDataFactory'
|
||||
arguments:
|
||||
- '@doctrine.cache.provider'
|
||||
- '@prestashop.module.blockwishlist.calculator.statistics_calculator'
|
||||
- '@=service("prestashop.adapter.shop.context").getContextShopID()'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_day_statistics_data_factory:
|
||||
class: 'PrestaShop\Module\BlockWishList\Grid\Data\CurrentDayStatisticsGridDataFactory'
|
||||
arguments:
|
||||
- '@doctrine.cache.provider'
|
||||
- '@prestashop.module.blockwishlist.calculator.statistics_calculator'
|
||||
- '@=service("prestashop.adapter.shop.context").getContextShopID()'
|
||||
|
||||
# Grid Factories
|
||||
prestashop.module.blockwishlist.grid.all_time_stastistics_grid_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory'
|
||||
arguments:
|
||||
- '@prestashop.module.blockwishlist.grid.all_time_statistics_grid_definition_factory'
|
||||
- '@prestashop.module.blockwishlist.grid.all_time_statistics_data_factory'
|
||||
- '@prestashop.core.grid.filter.form_factory'
|
||||
- '@prestashop.core.hook.dispatcher'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_year_stastistics_grid_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory'
|
||||
arguments:
|
||||
- '@prestashop.module.blockwishlist.grid.current_year_statistics_grid_definition_factory'
|
||||
- '@prestashop.module.blockwishlist.grid.current_year_statistics_data_factory'
|
||||
- '@prestashop.core.grid.filter.form_factory'
|
||||
- '@prestashop.core.hook.dispatcher'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_month_stastistics_grid_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory'
|
||||
arguments:
|
||||
- '@prestashop.module.blockwishlist.grid.current_month_statistics_grid_definition_factory'
|
||||
- '@prestashop.module.blockwishlist.grid.current_month_statistics_data_factory'
|
||||
- '@prestashop.core.grid.filter.form_factory'
|
||||
- '@prestashop.core.hook.dispatcher'
|
||||
|
||||
prestashop.module.blockwishlist.grid.current_day_stastistics_grid_factory:
|
||||
public: true
|
||||
class: 'PrestaShop\PrestaShop\Core\Grid\GridFactory'
|
||||
arguments:
|
||||
- '@prestashop.module.blockwishlist.grid.current_day_statistics_grid_definition_factory'
|
||||
- '@prestashop.module.blockwishlist.grid.current_day_statistics_data_factory'
|
||||
- '@prestashop.core.grid.filter.form_factory'
|
||||
- '@prestashop.core.hook.dispatcher'
|
||||
12
modules/blockwishlist/config_pl.xml
Normal file
12
modules/blockwishlist/config_pl.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<module>
|
||||
<name>blockwishlist</name>
|
||||
<displayName><![CDATA[Lista życzeń]]></displayName>
|
||||
<version><![CDATA[2.1.2]]></version>
|
||||
<description><![CDATA[Allow customers to create wishlists to save their favorite products for later.]]></description>
|
||||
<author><![CDATA[PrestaShop]]></author>
|
||||
<tab><![CDATA[front_office_features]]></tab>
|
||||
<is_configurable>1</is_configurable>
|
||||
<need_instance>0</need_instance>
|
||||
<limited_countries></limited_countries>
|
||||
</module>
|
||||
461
modules/blockwishlist/controllers/front/action.php
Normal file
461
modules/blockwishlist/controllers/front/action.php
Normal file
@@ -0,0 +1,461 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
use PrestaShop\Module\BlockWishList\Access\CustomerAccess;
|
||||
|
||||
class BlockWishListActionModuleFrontController extends ModuleFrontController
|
||||
{
|
||||
public function postProcess()
|
||||
{
|
||||
if (false === $this->context->customer->isLogged()) {
|
||||
$this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('You aren\'t logged in', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
$params = Tools::getValue('params');
|
||||
// Here we call all methods dynamically given by the path
|
||||
|
||||
if (method_exists($this, Tools::getValue('action') . 'Action')) {
|
||||
call_user_func([$this, Tools::getValue('action') . 'Action'], $params);
|
||||
exit;
|
||||
}
|
||||
|
||||
$this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Unknown action', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function addProductToWishListAction($params)
|
||||
{
|
||||
$id_product = (int) $params['id_product'];
|
||||
$product = new Product($id_product);
|
||||
if (!Validate::isLoadedObject($product)) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('There was an error adding the product', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
$idWishList = (int) $params['idWishList'];
|
||||
$id_product_attribute = (int) $params['id_product_attribute'];
|
||||
$quantity = (int) $params['quantity'];
|
||||
if (0 === $quantity) {
|
||||
$quantity = $product->minimal_quantity;
|
||||
}
|
||||
|
||||
if (false === $this->assertProductAttributeExists($id_product, $id_product_attribute) && $id_product_attribute !== 0) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('There was an error while adding the product attributes', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
$wishlist = new WishList($idWishList);
|
||||
// Exit if not owner of the wishlist
|
||||
$this->assertWriteAccess($wishlist);
|
||||
|
||||
$productIsAdded = $wishlist->addProduct(
|
||||
$idWishList,
|
||||
$this->context->customer->id,
|
||||
$id_product,
|
||||
$id_product_attribute,
|
||||
$quantity
|
||||
);
|
||||
|
||||
$newStat = new Statistics();
|
||||
$newStat->id_product = $id_product;
|
||||
$newStat->id_product_attribute = $id_product_attribute;
|
||||
$newStat->id_shop = $this->context->shop->id;
|
||||
$newStat->save();
|
||||
|
||||
if (false === $productIsAdded) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('There was an error adding the product', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
Hook::exec('actionWishlistAddProduct', [
|
||||
'idWishlist' => $idWishList,
|
||||
'customerId' => $this->context->customer->id,
|
||||
'idProduct' => $id_product,
|
||||
'idProductAttribute' => $id_product_attribute,
|
||||
]);
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('Product added', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
private function createNewWishListAction($params)
|
||||
{
|
||||
if (isset($params['name'])) {
|
||||
if (!Validate::isGenericName($params['name'])) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('The list name is invalid.', [], 'Modules.Blockwishlist.Shop'),
|
||||
'datas' => [
|
||||
'name' => $params['name'],
|
||||
],
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
$wishlist = new WishList();
|
||||
$wishlist->name = $params['name'];
|
||||
$wishlist->id_shop_group = $this->context->shop->id_shop_group;
|
||||
$wishlist->id_customer = $this->context->customer->id;
|
||||
$wishlist->id_shop = $this->context->shop->id;
|
||||
$wishlist->token = $this->generateWishListToken();
|
||||
|
||||
if (true === $wishlist->save()) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('The list has been properly created', [], 'Modules.Blockwishlist.Shop'),
|
||||
'datas' => [
|
||||
'name' => $wishlist->name,
|
||||
'id_wishlist' => $wishlist->id,
|
||||
],
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Error saving the new list', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
} else {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Missing name parameter', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function renameWishListAction($params)
|
||||
{
|
||||
if (isset($params['idWishList'], $params['name'])) {
|
||||
if (!Validate::isGenericName($params['name'])) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('The list name is invalid', [], 'Modules.Blockwishlist.Shop'),
|
||||
'datas' => [
|
||||
'name' => $params['name'],
|
||||
'id_whishlist' => $params['idWishList'],
|
||||
],
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
$wishlist = new WishList($params['idWishList']);
|
||||
// Exit if not owner of the wishlist
|
||||
$this->assertWriteAccess($wishlist);
|
||||
|
||||
$wishlist->name = $params['name'];
|
||||
|
||||
if (true === $wishlist->save()) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('List has been renamed', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('List could not be renamed', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRenderMissingParams();
|
||||
}
|
||||
|
||||
private function deleteWishListAction($params)
|
||||
{
|
||||
if (isset($params['idWishList'])) {
|
||||
$wishlist = new WishList($params['idWishList']);
|
||||
|
||||
// Exit if not owner of the wishlist
|
||||
$this->assertWriteAccess($wishlist);
|
||||
|
||||
if (true === (bool) $wishlist->delete()) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('List has been removed', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('List deletion was unsuccessful', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRenderMissingParams();
|
||||
}
|
||||
|
||||
private function deleteProductFromWishListAction($params)
|
||||
{
|
||||
if (
|
||||
isset($params['idWishList'])
|
||||
&& isset($params['id_product'])
|
||||
&& isset($params['id_product_attribute'])
|
||||
) {
|
||||
// Exit if not owner of the wishlist
|
||||
$this->assertWriteAccess(
|
||||
new WishList($params['idWishList'])
|
||||
);
|
||||
|
||||
$isDeleted = WishList::removeProduct(
|
||||
$params['idWishList'],
|
||||
$this->context->customer->id,
|
||||
$params['id_product'],
|
||||
$params['id_product_attribute']
|
||||
);
|
||||
|
||||
if (true === $isDeleted) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('Product successfully removed', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Unable to remove product from list', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRenderMissingParams();
|
||||
}
|
||||
|
||||
private function updateProductFromWishListAction($params)
|
||||
{
|
||||
if (isset(
|
||||
$params['idWishList'],
|
||||
$params['id_product'],
|
||||
$params['id_product_attribute'],
|
||||
$params['priority'],
|
||||
$params['quantity']
|
||||
)) {
|
||||
// Exit if not owner of the wishlist
|
||||
$this->assertWriteAccess(
|
||||
new WishList($params['idWishList'])
|
||||
);
|
||||
|
||||
$isDeleted = WishList::updateProduct(
|
||||
$params['idWishList'],
|
||||
$params['id_product'],
|
||||
$params['id_product_attribute'],
|
||||
$params['priority'],
|
||||
$params['quantity']
|
||||
);
|
||||
|
||||
if (true === $isDeleted) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('Product successfully updated', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Unable to update product from wishlist', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRenderMissingParams();
|
||||
}
|
||||
|
||||
private function getAllWishListAction()
|
||||
{
|
||||
$infos = WishList::getAllWishListsByIdCustomer($this->context->customer->id);
|
||||
if (empty($infos)) {
|
||||
$wishlist = new WishList();
|
||||
$wishlist->id_shop = $this->context->shop->id;
|
||||
$wishlist->id_shop_group = $this->context->shop->id_shop_group;
|
||||
$wishlist->id_customer = $this->context->customer->id;
|
||||
$wishlist->name = Configuration::get('blockwishlist_WishlistDefaultTitle', $this->context->language->id);
|
||||
$wishlist->token = $this->generateWishListToken();
|
||||
$wishlist->default = 1;
|
||||
$wishlist->add();
|
||||
|
||||
$infos = WishList::getAllWishListsByIdCustomer($this->context->customer->id);
|
||||
}
|
||||
|
||||
foreach ($infos as $key => $wishlist) {
|
||||
$infos[$key]['shareUrl'] = $this->context->link->getModuleLink('blockwishlist', 'view', ['token' => $wishlist['token']]);
|
||||
$infos[$key]['listUrl'] = $this->context->link->getModuleLink('blockwishlist', 'view', ['id_wishlist' => $wishlist['id_wishlist']]);
|
||||
}
|
||||
|
||||
if (false === empty($infos)) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'wishlists' => $infos,
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRenderMissingParams();
|
||||
}
|
||||
|
||||
private function generateWishListToken()
|
||||
{
|
||||
return strtoupper(substr(sha1(uniqid((string) rand(), true) . _COOKIE_KEY_ . $this->context->customer->id), 0, 16));
|
||||
}
|
||||
|
||||
private function ajaxRenderMissingParams()
|
||||
{
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Request is missing one or multiple parameters', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
private function addProductToCartAction($params)
|
||||
{
|
||||
$productAdd = WishList::addBoughtProduct(
|
||||
$params['idWishlist'],
|
||||
$params['id_product'],
|
||||
$params['id_product_attribute'],
|
||||
(int) $this->context->cart->id,
|
||||
$params['quantity']
|
||||
);
|
||||
|
||||
// Transform an add to favorite
|
||||
Db::getInstance()->execute('
|
||||
UPDATE `' . _DB_PREFIX_ . 'blockwishlist_statistics`
|
||||
SET `id_cart` = ' . (int) $this->context->cart->id . '
|
||||
WHERE `id_cart` = 0
|
||||
AND `id_product` = ' . (int) $params['id_product'] . '
|
||||
AND `id_product_attribute` = ' . (int) $params['id_product_attribute'] . '
|
||||
AND `id_shop`= ' . $this->context->shop->id
|
||||
);
|
||||
|
||||
if (true === $productAdd) {
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => true,
|
||||
'message' => $this->trans('Product added to cart', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('Error when adding product to cart', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
private function getUrlByIdWishListAction($params)
|
||||
{
|
||||
$wishlist = new WishList($params['idWishList']);
|
||||
|
||||
return $this->ajaxRender(
|
||||
json_encode([
|
||||
'status' => 'true',
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'view', ['token' => $wishlist->token]),
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the execution if the current customer isd not allowed to alter the wishlist
|
||||
*
|
||||
* @param WishList $wishlist
|
||||
*/
|
||||
private function assertWriteAccess(WishList $wishlist)
|
||||
{
|
||||
if ((new CustomerAccess($this->context->customer))->hasWriteAccessToWishlist($wishlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->ajaxRender(
|
||||
json_encode([
|
||||
'success' => false,
|
||||
'message' => $this->trans('You\'re not allowed to manage this list.', [], 'Modules.Blockwishlist.Shop'),
|
||||
])
|
||||
);
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if product attribute id is related to the product
|
||||
*
|
||||
* @param int $id_product
|
||||
* @param int $id_product_attribute
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function assertProductAttributeExists($id_product, $id_product_attribute)
|
||||
{
|
||||
return Db::getInstance()->getValue(
|
||||
'SELECT pas.`id_product_attribute` ' .
|
||||
'FROM `' . _DB_PREFIX_ . 'product_attribute` pa ' .
|
||||
'INNER JOIN `' . _DB_PREFIX_ . 'product_attribute_shop` pas ON (pas.id_product_attribute = pa.id_product_attribute) ' .
|
||||
'WHERE pas.id_shop =' . (int) $this->context->shop->id . ' AND pa.`id_product` = ' . (int) $id_product . ' ' .
|
||||
'AND pas.id_product_attribute = ' . (int) $id_product_attribute
|
||||
);
|
||||
}
|
||||
}
|
||||
65
modules/blockwishlist/controllers/front/lists.php
Normal file
65
modules/blockwishlist/controllers/front/lists.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
class BlockWishlistListsModuleFrontController extends ModuleFrontController
|
||||
{
|
||||
/**
|
||||
* @var bool If set to true, will be redirected to authentication page
|
||||
*/
|
||||
public $auth = true;
|
||||
|
||||
public function initContent()
|
||||
{
|
||||
parent::initContent();
|
||||
|
||||
$this->context->smarty->assign(
|
||||
[
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'getAllWishlist']),
|
||||
'renameUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'renameWishlist']),
|
||||
'shareUrl' => $this->context->link->getModuleLink('blockwishlist', 'action', ['action' => 'getUrlByIdWishlist']),
|
||||
'accountLink' => '#',
|
||||
'wishlistsTitlePage' => Configuration::get('blockwishlist_WishlistPageName', $this->context->language->id),
|
||||
'newWishlistCTA' => Configuration::get('blockwishlist_CreateButtonLabel', $this->context->language->id),
|
||||
]
|
||||
);
|
||||
|
||||
$this->context->controller->registerJavascript(
|
||||
'blockwishlistController',
|
||||
'modules/blockwishlist/public/wishlistcontainer.bundle.js',
|
||||
[
|
||||
'priority' => 200,
|
||||
]
|
||||
);
|
||||
|
||||
$this->setTemplate('module:blockwishlist/views/templates/pages/lists.tpl');
|
||||
}
|
||||
|
||||
public function getBreadcrumbLinks()
|
||||
{
|
||||
$breadcrumb = parent::getBreadcrumbLinks();
|
||||
|
||||
$breadcrumb['links'][] = $this->addMyAccountToBreadcrumb();
|
||||
$breadcrumb['links'][] = [
|
||||
'title' => Configuration::get('blockwishlist_WishlistPageName', $this->context->language->id),
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'lists'),
|
||||
];
|
||||
|
||||
return $breadcrumb;
|
||||
}
|
||||
}
|
||||
317
modules/blockwishlist/controllers/front/view.php
Normal file
317
modules/blockwishlist/controllers/front/view.php
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
use PrestaShop\Module\BlockWishList\Access\CustomerAccess;
|
||||
use PrestaShop\Module\BlockWishList\Search\WishListProductSearchProvider;
|
||||
use PrestaShop\PrestaShop\Core\Product\Search\ProductSearchQuery;
|
||||
use PrestaShop\PrestaShop\Core\Product\Search\SortOrder;
|
||||
use PrestaShop\PrestaShop\Core\Product\Search\SortOrderFactory;
|
||||
|
||||
/**
|
||||
* View the content of a personal wishlist
|
||||
*/
|
||||
class BlockWishlistViewModuleFrontController extends ProductListingFrontController
|
||||
{
|
||||
/**
|
||||
* Made public as the core considers this class as an ModuleFrontController
|
||||
* and other modules expects to find the $module property.
|
||||
*
|
||||
* @var BlockWishList
|
||||
*/
|
||||
public $module;
|
||||
|
||||
/**
|
||||
* @var WishList
|
||||
*/
|
||||
protected $wishlist;
|
||||
|
||||
/**
|
||||
* @var CustomerAccess
|
||||
*/
|
||||
private $customerAccess;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
/** @var BlockWishList $module */
|
||||
$module = Module::getInstanceByName('blockwishlist');
|
||||
$this->module = $module;
|
||||
|
||||
if (empty($this->module->active)) {
|
||||
Tools::redirect('index');
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
|
||||
$this->controller_type = 'modulefront';
|
||||
$this->customerAccess = new CustomerAccess($this->context->customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$id_wishlist = $this->getWishlistId();
|
||||
$this->wishlist = new WishList($id_wishlist);
|
||||
|
||||
if (false === Validate::isLoadedObject($this->wishlist)) {
|
||||
Tools::redirect('index.php?controller=404');
|
||||
}
|
||||
|
||||
parent::init();
|
||||
|
||||
if (false === $this->customerAccess->hasReadAccessToWishlist($this->wishlist)) {
|
||||
header('HTTP/1.1 403 Forbidden');
|
||||
header('Status: 403 Forbidden');
|
||||
$this->errors[] = $this->trans(
|
||||
'You do not have access to this wishlist.',
|
||||
[],
|
||||
'Modules.Blockwishlist.Shop'
|
||||
);
|
||||
$this->template = 'module:blockwishlist/views/templates/errors/forbidden.tpl';
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->smarty->assign(
|
||||
[
|
||||
'id' => $id_wishlist,
|
||||
'wishlistName' => $this->wishlist->name,
|
||||
'isGuest' => !$this->customerAccess->hasWriteAccessToWishlist($this->wishlist),
|
||||
'url' => Context::getContext()->link->getModuleLink('blockwishlist', 'view', $this->getAccessParams()),
|
||||
'wishlistsLink' => Context::getContext()->link->getModuleLink('blockwishlist', 'lists'),
|
||||
'deleteProductUrl' => Context::getContext()->link->getModuleLink('blockwishlist', 'action', ['action' => 'deleteProductFromWishlist']),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function initContent()
|
||||
{
|
||||
parent::initContent();
|
||||
|
||||
if (false === $this->customerAccess->hasReadAccessToWishlist($this->wishlist)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->context->controller->registerJavascript(
|
||||
'blockwishlistController',
|
||||
'modules/blockwishlist/public/productslist.bundle.js',
|
||||
[
|
||||
'priority' => 200,
|
||||
]
|
||||
);
|
||||
|
||||
$this->doProductSearch(
|
||||
'../../../modules/blockwishlist/views/templates/pages/products-list.tpl',
|
||||
[
|
||||
'entity' => 'wishlist_product',
|
||||
'id_wishlist' => $this->wishlist->id,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getListingLabel()
|
||||
{
|
||||
return $this->trans(
|
||||
'WishList: %wishlist_name%',
|
||||
['%wishlist_name%' => $this->wishlist->name],
|
||||
'Modules.Blockwishlist.Shop'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getProductSearchQuery()
|
||||
{
|
||||
$query = new ProductSearchQuery();
|
||||
$query->setSortOrder(
|
||||
new SortOrder(
|
||||
'product',
|
||||
Tools::getProductsOrder('by'),
|
||||
Tools::getProductsOrder('way')
|
||||
)
|
||||
);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getDefaultProductSearchProvider()
|
||||
{
|
||||
return new WishListProductSearchProvider(
|
||||
Db::getInstance(),
|
||||
$this->wishlist,
|
||||
new SortOrderFactory($this->getTranslator()),
|
||||
$this->getTranslator()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function getAjaxProductSearchVariables()
|
||||
{
|
||||
parent::getAjaxProductSearchVariables();
|
||||
$context = parent::getProductSearchContext();
|
||||
$query = $this->getProductSearchQuery();
|
||||
$provider = $this->getDefaultProductSearchProvider();
|
||||
|
||||
$resultsPerPage = (int) Tools::getValue('resultsPerPage');
|
||||
if ($resultsPerPage <= 0) {
|
||||
$resultsPerPage = Configuration::get('PS_PRODUCTS_PER_PAGE');
|
||||
}
|
||||
|
||||
// we need to set a few parameters from back-end preferences
|
||||
$query
|
||||
->setResultsPerPage($resultsPerPage)
|
||||
->setPage(max((int) Tools::getValue('page'), 1))
|
||||
;
|
||||
|
||||
// set the sort order if provided in the URL
|
||||
if (($encodedSortOrder = Tools::getValue('order'))) {
|
||||
$query->setSortOrder(SortOrder::newFromString($encodedSortOrder));
|
||||
}
|
||||
|
||||
// get the parameters containing the encoded facets from the URL
|
||||
$encodedFacets = Tools::getValue('q');
|
||||
$query->setEncodedFacets($encodedFacets);
|
||||
$result = $provider->runQuery($context, $query);
|
||||
|
||||
if (!$result->getCurrentSortOrder()) {
|
||||
$result->setCurrentSortOrder($query->getSortOrder());
|
||||
}
|
||||
|
||||
// prepare the products
|
||||
$products = $this->prepareMultipleProductsForTemplate($result->getProducts());
|
||||
|
||||
// render the facets with the core
|
||||
$rendered_facets = $this->renderFacets($result);
|
||||
$rendered_active_filters = $this->renderActiveFilters($result);
|
||||
$pagination = $this->getTemplateVarPagination($query, $result);
|
||||
|
||||
// prepare the sort orders
|
||||
// note that, again, the product controller is sort-orders agnostic
|
||||
// a module can easily add specific sort orders that it needs to support (e.g. sort by "energy efficiency")
|
||||
$sort_orders = $this->getTemplateVarSortOrders(
|
||||
$result->getAvailableSortOrders(),
|
||||
$query->getSortOrder()->toString()
|
||||
);
|
||||
|
||||
$sort_selected = false;
|
||||
$labelDefaultSort = '';
|
||||
if (!empty($sort_orders)) {
|
||||
foreach ($sort_orders as $order) {
|
||||
if ($order['field'] == 'id_wishlist_product') {
|
||||
$labelDefaultSort = $order['label'];
|
||||
}
|
||||
if (isset($order['current']) && true === $order['current']) {
|
||||
$sort_selected = $order['label'];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$searchVariables = [
|
||||
'result' => $result,
|
||||
'label' => $this->getListingLabel(),
|
||||
'products' => $products,
|
||||
'sort_orders' => $sort_orders,
|
||||
'sort_selected' => $sort_selected ? $sort_selected : $labelDefaultSort,
|
||||
'pagination' => $pagination,
|
||||
'rendered_facets' => $rendered_facets,
|
||||
'rendered_active_filters' => $rendered_active_filters,
|
||||
'js_enabled' => $this->ajax,
|
||||
'current_url' => $this->updateQueryString([
|
||||
'q' => $result->getEncodedFacets(),
|
||||
]),
|
||||
];
|
||||
|
||||
Hook::exec('filterProductSearch', ['searchVariables' => &$searchVariables]);
|
||||
Hook::exec('actionProductSearchAfter', $searchVariables);
|
||||
|
||||
return $searchVariables;
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the parameters sent, checks if the current visitor may reach the page
|
||||
*
|
||||
* @return int|false
|
||||
*/
|
||||
private function getWishlistId()
|
||||
{
|
||||
if (Tools::getIsset('id_wishlist')) {
|
||||
return (int) Tools::getValue('id_wishlist');
|
||||
}
|
||||
|
||||
if (Tools::getIsset('token')) {
|
||||
$wishlistData = WishList::getByToken(
|
||||
Tools::getValue('token')
|
||||
);
|
||||
|
||||
if (!empty($wishlistData['id_wishlist'])) {
|
||||
return $wishlistData['id_wishlist'];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getAccessParams()
|
||||
{
|
||||
if (Tools::getIsset('token')) {
|
||||
return ['token' => Tools::getValue('token')];
|
||||
}
|
||||
if (Tools::getIsset('id_wishlist')) {
|
||||
return ['id_wishlist' => Tools::getValue('id_wishlist')];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getBreadcrumbLinks()
|
||||
{
|
||||
$breadcrumb = parent::getBreadcrumbLinks();
|
||||
|
||||
$breadcrumb['links'][] = $this->addMyAccountToBreadcrumb();
|
||||
$breadcrumb['links'][] = [
|
||||
'title' => Configuration::get('blockwishlist_WishlistPageName', $this->context->language->id),
|
||||
'url' => $this->context->link->getModuleLink('blockwishlist', 'lists'),
|
||||
];
|
||||
$breadcrumb['links'][] = [
|
||||
'title' => $this->wishlist->name,
|
||||
'url' => Context::getContext()->link->getModuleLink('blockwishlist', 'view', $this->getAccessParams()),
|
||||
];
|
||||
|
||||
return $breadcrumb;
|
||||
}
|
||||
}
|
||||
28
modules/blockwishlist/controllers/index.php
Normal file
28
modules/blockwishlist/controllers/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
header('Location: ../');
|
||||
exit;
|
||||
18
modules/blockwishlist/docker-compose.yml
Normal file
18
modules/blockwishlist/docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
php:
|
||||
image: phpdockerio/php72-cli
|
||||
volumes:
|
||||
- ./:/var/www/html/modules/blockwishlist
|
||||
|
||||
working_dir: /var/www/html/modules/blockwishlist
|
||||
environment:
|
||||
_PS_ROOT_DIR_: /var/www/html
|
||||
node:
|
||||
image: node:10
|
||||
volumes:
|
||||
- ./:/var/www/html/modules/blockwishlist
|
||||
working_dir: /var/www/html/modules/blockwishlist
|
||||
environment:
|
||||
PATH: /var/www/html/_dev/node_modules/.bin/:$PATH
|
||||
28
modules/blockwishlist/index.php
Normal file
28
modules/blockwishlist/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
header('Location: ../');
|
||||
exit;
|
||||
BIN
modules/blockwishlist/logo.png
Normal file
BIN
modules/blockwishlist/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
11428
modules/blockwishlist/package-lock.json
generated
Normal file
11428
modules/blockwishlist/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
94
modules/blockwishlist/package.json
Normal file
94
modules/blockwishlist/package.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "blockwishlist",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"private": "true",
|
||||
"scripts": {
|
||||
"build": "webpack --progress --colors --mode=production",
|
||||
"dev": "webpack --progress --colors --debug --display-chunks --watch --mode=development",
|
||||
"watch": "npm run dev",
|
||||
"lint": "eslint -c .eslintrc.js --ext .js,.vue .",
|
||||
"lint-fix": "eslint -c .eslintrc.js --ext .js,.vue . --fix",
|
||||
"test": "mochapack --webpack-config .webpack/common.js --require tests/UI/setup.js tests/UI/**/*.spec.js"
|
||||
},
|
||||
"author": "PrestaShop",
|
||||
"license": "AFL-3.0",
|
||||
"dependencies": {
|
||||
"apollo-cache-inmemory": "^1.6.5",
|
||||
"apollo-client": "^2.6.8",
|
||||
"apollo-link": "^1.2.13",
|
||||
"apollo-link-http": "^1.5.16",
|
||||
"apollo-link-schema": "^1.2.4",
|
||||
"graphql": "^14.0.2",
|
||||
"graphql-tag": "^2.10.3",
|
||||
"graphql-tools": "^4.0.7",
|
||||
"graphql-type-json": "^0.3.1",
|
||||
"v-click-outside": "^3.0.1",
|
||||
"vue": "^2.6.11",
|
||||
"vue-apollo": "^3.0.3",
|
||||
"vue-content-loader": "^0.2.3",
|
||||
"vue-i18n": "^8.15.1",
|
||||
"vue-resource": "^1.5.1",
|
||||
"vue-router": "^2.8.1",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
"vuex": "^2.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.15.8",
|
||||
"@babel/eslint-parser": "^7.15.8",
|
||||
"@vue/test-utils": "^1.0.3",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-es2015": "^6.3.13",
|
||||
"babel-preset-stage-2": "^6.22.0",
|
||||
"babel-register": "^6.26.0",
|
||||
"chai": "^4.2.0",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"css-loader": "^3.4",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-config-airbnb-base": "^14.0.0",
|
||||
"eslint-config-prestashop": "0.1.1",
|
||||
"eslint-import-resolver-webpack": "^0.12.1",
|
||||
"eslint-plugin-html": "^6.0.0",
|
||||
"eslint-plugin-import": "^2.20.0",
|
||||
"eslint-plugin-vue": "^6.0.1",
|
||||
"expect": "^26.1.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"expose-loader": "^0.7.5",
|
||||
"file-loader": "^5.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"jsdom": "^16.2.2",
|
||||
"jsdom-global": "^3.0.2",
|
||||
"loader-utils": "^1.2.3",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"mocha": "^7.1.2",
|
||||
"mochapack": "^2.0.2",
|
||||
"node-sass": "^5.0.0",
|
||||
"path": "^0.12.7",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"sass-loader": "^10.1.1",
|
||||
"style-loader": "^1.1.3",
|
||||
"terser-webpack-plugin": "^3.0.6",
|
||||
"ts-loader": "^8.0.16",
|
||||
"ts-node": "^10.0.0",
|
||||
"typescript": "^4.1.4",
|
||||
"uglify-save-license": "^0.4.1",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"vue-loader": "^15",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"webpack": "^4.41",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-fix-style-only-entries": "^0.6.1",
|
||||
"webpack-merge": "^5.7.3"
|
||||
},
|
||||
"babel": {
|
||||
"presets": [
|
||||
"env"
|
||||
]
|
||||
}
|
||||
}
|
||||
26
modules/blockwishlist/postcss.config.js
Normal file
26
modules/blockwishlist/postcss.config.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'postcss-preset-env': {
|
||||
browsers: '> .5%, last 2 versions',
|
||||
},
|
||||
},
|
||||
};
|
||||
93
modules/blockwishlist/public/addtowishlist.bundle.js
Normal file
93
modules/blockwishlist/public/addtowishlist.bundle.js
Normal file
File diff suppressed because one or more lines are too long
19
modules/blockwishlist/public/backoffice.bundle.js
Normal file
19
modules/blockwishlist/public/backoffice.bundle.js
Normal file
File diff suppressed because one or more lines are too long
2
modules/blockwishlist/public/backoffice.css
Normal file
2
modules/blockwishlist/public/backoffice.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.wishlist-stats .card-text{width:100%;padding:10px 30px}.wishlist-stats .wishlist-stats-topbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:20px}.wishlist-stats .wishlist-stats-topbar .btn-group{border:1px solid #b7ced3;border-radius:3px}.wishlist-stats .wishlist-stats-topbar .btn-group button{color:#363a41;font-size:14px;letter-spacing:0;line-height:19px;background:none;font-weight:500;-webkit-transition:0.25s ease-out;transition:0.25s ease-out}.wishlist-stats .wishlist-stats-topbar .btn-group button:not(:last-child){border-right:1px solid #b7ced3}.wishlist-stats .wishlist-stats-topbar .btn-group button:hover,.wishlist-stats .wishlist-stats-topbar .btn-group button.active{background-color:#25b9d7;color:#fff}.wishlist-stats .wishlist-stats-topbar .refresh{color:#6c868e;font-size:14px;font-weight:bold;letter-spacing:0;line-height:19px;border:1px solid #6c868e;border-radius:4px;-webkit-transition:0.25s ease-out;transition:0.25s ease-out;background:none}.wishlist-stats .wishlist-stats-topbar .refresh:hover{background:#6c868e;color:white}.wishlist-stats .wishlist-tab{display:none}.wishlist-stats .wishlist-tab.active{display:block}.wishlist-stats .wishlist-tab .column-image img{max-width:50px}.wishlist-stats .wishlist-tab .column-conversionRate{font-weight:bold}
|
||||
|
||||
93
modules/blockwishlist/public/button.bundle.js
Normal file
93
modules/blockwishlist/public/button.bundle.js
Normal file
File diff suppressed because one or more lines are too long
93
modules/blockwishlist/public/create.bundle.js
Normal file
93
modules/blockwishlist/public/create.bundle.js
Normal file
File diff suppressed because one or more lines are too long
25
modules/blockwishlist/public/form.bundle.js
Normal file
25
modules/blockwishlist/public/form.bundle.js
Normal file
File diff suppressed because one or more lines are too long
2
modules/blockwishlist/public/form.css
Normal file
2
modules/blockwishlist/public/form.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.wishlist-stats .card-text{width:100%;padding:10px 30px}.wishlist-stats .wishlist-stats-topbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-bottom:20px}.wishlist-stats .wishlist-stats-topbar .btn-group{border:1px solid #b7ced3;border-radius:3px}.wishlist-stats .wishlist-stats-topbar .btn-group button{color:#363a41;font-size:14px;letter-spacing:0;line-height:19px;background:none;font-weight:500;-webkit-transition:0.25s ease-out;transition:0.25s ease-out}.wishlist-stats .wishlist-stats-topbar .btn-group button:not(:last-child){border-right:1px solid #b7ced3}.wishlist-stats .wishlist-stats-topbar .btn-group button:hover,.wishlist-stats .wishlist-stats-topbar .btn-group button.active{background-color:#25b9d7;color:#fff}.wishlist-stats .wishlist-stats-topbar .refresh{color:#6c868e;font-size:14px;font-weight:bold;letter-spacing:0;line-height:19px;border:1px solid #6c868e;border-radius:4px;-webkit-transition:0.25s ease-out;transition:0.25s ease-out;background:none}.wishlist-stats .wishlist-stats-topbar .refresh:hover{background:#6c868e;color:white}.wishlist-stats .wishlist-tab{display:none}.wishlist-stats .wishlist-tab.active{display:block}.wishlist-stats .wishlist-tab .column-image img{max-width:50px}.wishlist-stats .wishlist-tab .column-conversionRate{font-weight:bold}
|
||||
|
||||
1
modules/blockwishlist/public/graphql.js
Normal file
1
modules/blockwishlist/public/graphql.js
Normal file
File diff suppressed because one or more lines are too long
183
modules/blockwishlist/public/product.bundle.js
Normal file
183
modules/blockwishlist/public/product.bundle.js
Normal file
File diff suppressed because one or more lines are too long
147
modules/blockwishlist/public/productslist.bundle.js
Normal file
147
modules/blockwishlist/public/productslist.bundle.js
Normal file
File diff suppressed because one or more lines are too long
93
modules/blockwishlist/public/rename.bundle.js
Normal file
93
modules/blockwishlist/public/rename.bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
modules/blockwishlist/public/vendors.js
Normal file
1
modules/blockwishlist/public/vendors.js
Normal file
File diff suppressed because one or more lines are too long
2
modules/blockwishlist/public/wishlist.css
Normal file
2
modules/blockwishlist/public/wishlist.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.wishlist-modal{display:none;opacity:0;pointer-events:none;z-index:0}.wishlist-modal.show{display:block;opacity:1;pointer-events:all;z-index:1051}.wishlist-modal.show+.modal-backdrop{pointer-events:all}.wishlist-modal.fade .modal-dialog{max-width:34.375rem;-webkit-transform:translateY(0);transform:translateY(0)}.wishlist-modal .close{font-weight:400;color:#7a7a7a;opacity:1;font-size:2.25rem}.wishlist-modal .close:hover{opacity:0.6}.wishlist-modal .modal-header{padding:0.625rem 1.875rem;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;border:none}.wishlist-modal .modal-header h5{color:#232323;font-size:1.375rem;font-weight:bold;letter-spacing:0;line-height:1.875rem}.wishlist-modal .modal-header::after{content:none}.wishlist-modal .modal-text{color:#232323;font-size:0.875rem;letter-spacing:0;line-height:1.875rem}.wishlist-modal .modal-body{padding:0.9375 1.875rem}.wishlist-modal .modal-body .form-group{margin-bottom:0}.wishlist-modal .modal-body .form-group .form-control{border-radius:0;background:none;color:black}.wishlist-modal .modal-content{width:100%}.wishlist-modal .modal-cancel{margin-right:0.625rem}.wishlist-modal .modal-cancel:hover{opacity:0.7}.wishlist-modal .modal-footer{padding:0.75rem 1.875rem;border:none;padding-bottom:1.875rem}.wishlist-modal .modal-footer .btn{text-transform:none}.wishlist-modal .modal-backdrop{pointer-events:none}.wishlist-modal .modal-backdrop.in{pointer-events:all}.wishlist-modal+.modal-backdrop{pointer-events:none}.wishlist-modal+.modal-backdrop.in{pointer-events:all}.products article .wishlist-button-add{position:absolute;top:0.635rem;right:0.635rem;z-index:10}.wishlist-footer-links{margin-bottom:3.125rem}.wishlist-footer-links>a{font-size:0.875rem;letter-spacing:0;line-height:1.1875rem}.wishlist-footer-links>a:not(:first-child){margin-left:1.25rem}.wishlist-footer-links>a i{font-size:1.25rem;margin-right:0.25rem;vertical-align:middle}.lang-rtl .products article .wishlist-button-add{right:inherit;left:0.635rem}.lang-rtl .wishlist-button-product{margin-left:0;margin-right:1.25rem}.lang-rtl .wishlist-list-item .dropdown-menu{right:inherit;left:1.25rem}.lang-rtl .wishlist-list-item-right .dropdown-menu>button{text-align:right}
|
||||
|
||||
183
modules/blockwishlist/public/wishlistcontainer.bundle.js
Normal file
183
modules/blockwishlist/public/wishlistcontainer.bundle.js
Normal file
File diff suppressed because one or more lines are too long
64
modules/blockwishlist/src/Access/CustomerAccess.php
Normal file
64
modules/blockwishlist/src/Access/CustomerAccess.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Access;
|
||||
|
||||
use Customer;
|
||||
use Tools;
|
||||
use Validate;
|
||||
use WishList;
|
||||
|
||||
class CustomerAccess
|
||||
{
|
||||
/**
|
||||
* @var Customer
|
||||
*/
|
||||
private $customer;
|
||||
|
||||
public function __construct(Customer $customer)
|
||||
{
|
||||
$this->customer = $customer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasReadAccessToWishlist(WishList $wishlist)
|
||||
{
|
||||
// Wishlist is shared
|
||||
if (!empty($wishlist->token) && Tools::getIsset('token')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->hasWriteAccessToWishlist($wishlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function hasWriteAccessToWishlist(WishList $wishlist)
|
||||
{
|
||||
if (false === Validate::isLoadedObject($this->customer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((int) $wishlist->id_customer) === $this->customer->id;
|
||||
}
|
||||
}
|
||||
264
modules/blockwishlist/src/Calculator/StatisticsCalculator.php
Normal file
264
modules/blockwishlist/src/Calculator/StatisticsCalculator.php
Normal file
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Calculator;
|
||||
|
||||
use Customer;
|
||||
use DateTime;
|
||||
use Db;
|
||||
use DbQuery;
|
||||
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
|
||||
use PrestaShop\PrestaShop\Adapter\LegacyContext;
|
||||
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
|
||||
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
|
||||
use PrestaShop\PrestaShop\Core\Localization\Locale;
|
||||
use PrestaShop\PrestaShop\Core\Product\ProductPresenter;
|
||||
use ProductAssembler;
|
||||
use ProductPresenterFactory;
|
||||
|
||||
class StatisticsCalculator
|
||||
{
|
||||
const ARRAY_KEYS_STATS = [
|
||||
'allTime',
|
||||
'currentYear',
|
||||
'currentMonth',
|
||||
'currentDay',
|
||||
];
|
||||
|
||||
private $context;
|
||||
private $productAssembler;
|
||||
|
||||
/**
|
||||
* @var Locale
|
||||
*/
|
||||
private $locale;
|
||||
|
||||
public function __construct(LegacyContext $context, Locale $locale)
|
||||
{
|
||||
$this->context = $context->getContext();
|
||||
$this->context->customer = new Customer();
|
||||
$this->productAssembler = new ProductAssembler($this->context);
|
||||
$this->locale = $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeStatsFor
|
||||
*
|
||||
* @param string|null $statsRange
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function computeStatsFor($statsRange = null)
|
||||
{
|
||||
$query = new DbQuery();
|
||||
$query->select('id_product');
|
||||
$query->select('id_product_attribute');
|
||||
$query->select('date_add');
|
||||
$query->select('id_statistics');
|
||||
$query->from('blockwishlist_statistics');
|
||||
$query->where('id_shop = "' . (int) $this->context->shop->id . '"');
|
||||
|
||||
switch ($statsRange) {
|
||||
case 'currentYear':
|
||||
$dateStart = (new DateTime('now'))->modify('-1 year')->format('Y-m-d H:i:s');
|
||||
break;
|
||||
case 'currentMonth':
|
||||
$dateStart = (new DateTime('now'))->modify('-1 month')->format('Y-m-d H:i:s');
|
||||
break;
|
||||
case 'currentDay':
|
||||
$dateStart = (new DateTime('now'))->modify('-1 day')->format('Y-m-d H:i:s');
|
||||
break;
|
||||
case 'allTime':
|
||||
$dateStart = null;
|
||||
break;
|
||||
default:
|
||||
$dateStart = null;
|
||||
break;
|
||||
}
|
||||
|
||||
if (null !== $dateStart) {
|
||||
$query->where('date_add >= "' . $dateStart . '"');
|
||||
}
|
||||
|
||||
$results = Db::getInstance()->executeS($query);
|
||||
$stats = [];
|
||||
|
||||
foreach ($results as $result) {
|
||||
$productAttributeKey = $result['id_product'] . '.' . $result['id_product_attribute'];
|
||||
|
||||
if (isset($stats[$productAttributeKey])) {
|
||||
$stats[$productAttributeKey] = $stats[$productAttributeKey] + 1;
|
||||
} else {
|
||||
$stats[$productAttributeKey] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
arsort($stats);
|
||||
$stats = array_slice($stats, 0, 10);
|
||||
$this->computeConversionRate($stats, $dateStart);
|
||||
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeconversionRate
|
||||
*
|
||||
* @param array $stats
|
||||
* @param string|null $dateStart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function computeConversionRate(&$stats, $dateStart = null)
|
||||
{
|
||||
$position = 0;
|
||||
|
||||
foreach ($stats as $idProductAndAttribute => $count) {
|
||||
// first ID is product, second one is product_attribute
|
||||
$combination = '';
|
||||
$ids = explode('.', $idProductAndAttribute);
|
||||
$id_product = $ids[0];
|
||||
$id_product_attribute = $ids[1];
|
||||
$productDetails = $this->productAssembler->assembleProduct([
|
||||
'id_product' => $id_product,
|
||||
'id_product_attribute' => $id_product_attribute,
|
||||
]);
|
||||
|
||||
if (!empty($productDetails['attributes'])) {
|
||||
$combinationArr = [];
|
||||
foreach ($productDetails['attributes'] as $attribute) {
|
||||
$combinationArr[] = $attribute['group'] . ' : ' . $attribute['name'];
|
||||
}
|
||||
$combination = implode(',', $combinationArr);
|
||||
}
|
||||
|
||||
$imgDetails = $this->getProductImage($productDetails);
|
||||
$stats[$idProductAndAttribute] = [
|
||||
'position' => $position,
|
||||
'count' => $count,
|
||||
'id_product' => $id_product,
|
||||
'id_product_attribute' => $id_product_attribute,
|
||||
'name' => $productDetails['name'],
|
||||
'combination' => $combination,
|
||||
'category_name' => $productDetails['category_name'],
|
||||
'image_small_url' => $imgDetails['small']['url'],
|
||||
'link' => $productDetails['link'],
|
||||
'reference' => $productDetails['reference'],
|
||||
'price' => $this->locale->formatPrice($productDetails['price'], $this->context->currency->iso_code),
|
||||
'quantity' => $productDetails['quantity'],
|
||||
'conversionRate' => $this->computeConversionByProduct($id_product, $id_product_attribute, $dateStart) . '%',
|
||||
];
|
||||
|
||||
++$position;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* getProductImage
|
||||
*
|
||||
* @param array $productDetails
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getProductImage($productDetails)
|
||||
{
|
||||
$imgDetails = [];
|
||||
|
||||
$presenterFactory = new ProductPresenterFactory($this->context);
|
||||
$presentationSettings = $presenterFactory->getPresentationSettings();
|
||||
$imageRetriever = new ImageRetriever($this->context->link);
|
||||
$presenter = new ProductPresenter(
|
||||
$imageRetriever,
|
||||
$this->context->link,
|
||||
new PriceFormatter(),
|
||||
new ProductColorsRetriever(),
|
||||
$this->context->getTranslator()
|
||||
);
|
||||
|
||||
$presentedProduct = $presenter->present(
|
||||
$presentationSettings,
|
||||
$productDetails,
|
||||
$this->context->language
|
||||
);
|
||||
|
||||
foreach ($presentedProduct as $key => $value) {
|
||||
if ($key == 'embedded_attributes') {
|
||||
$imgDetails = $value['cover'];
|
||||
}
|
||||
}
|
||||
if (!$imgDetails) {
|
||||
$imgDetails = $imageRetriever->getNoPictureImage($this->context->language);
|
||||
}
|
||||
|
||||
return $imgDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
* computeConversionByProduct
|
||||
*
|
||||
* @param string $id_product
|
||||
* @param string $id_product_attribute
|
||||
* @param string $dateStart (Y-m-d H:i:s)
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function computeConversionByProduct($id_product, $id_product_attribute, $dateStart = null)
|
||||
{
|
||||
$nbOrderPaidAndShipped = [];
|
||||
$queryOrders = '
|
||||
SELECT count(distinct(o.id_order)) as nb
|
||||
FROM ' . _DB_PREFIX_ . 'orders o
|
||||
INNER JOIN ' . _DB_PREFIX_ . 'blockwishlist_statistics bws ON (o.id_cart = bws.id_cart )
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_history oh ON (o.`id_order` = oh.`id_order`)
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_state os ON (os.`id_order_state` = oh.`id_order_state` AND os.`paid` = 1 AND os.`shipped` = 1)
|
||||
LEFT JOIN ' . _DB_PREFIX_ . 'order_detail od ON (od.`id_order` = o.`id_order` AND od.`product_id` = bws.`id_product` AND od.`product_attribute_id` = bws.`id_product_attribute`)
|
||||
WHERE bws.`id_cart` <> 0 AND bws.`id_product` = ' . (int) $id_product . ' AND bws.`id_product_attribute` = ' . (int) $id_product_attribute . '
|
||||
AND bws.`id_shop` = ' . (int) $this->context->shop->id . '
|
||||
';
|
||||
|
||||
if (null != $dateStart) {
|
||||
$queryOrders .= 'AND bws.date_add >= "' . $dateStart . '"';
|
||||
}
|
||||
|
||||
$nbOrderPaidAndShipped = Db::getInstance()->getRow($queryOrders);
|
||||
|
||||
if (empty($nbOrderPaidAndShipped['nb'])) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$queryCountAll = new DbQuery();
|
||||
$queryCountAll->select('COUNT(id_statistics)');
|
||||
$queryCountAll->from('blockwishlist_statistics');
|
||||
$queryCountAll->where('id_product = ' . $id_product);
|
||||
$queryCountAll->where('id_product_attribute = ' . $id_product_attribute);
|
||||
$queryCountAll->where('id_shop = ' . (int) $this->context->shop->id);
|
||||
|
||||
if (null != $dateStart) {
|
||||
$queryCountAll->where('date_add >= "' . $dateStart . '"');
|
||||
}
|
||||
|
||||
$countAddedToWishlist = Db::getInstance()->getValue($queryCountAll);
|
||||
|
||||
if (0 != $countAddedToWishlist) {
|
||||
return round(($nbOrderPaidAndShipped['nb'] / $countAddedToWishlist) * 100, 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Controller;
|
||||
|
||||
use Configuration;
|
||||
use Doctrine\Common\Cache\CacheProvider;
|
||||
use Language;
|
||||
use PrestaShop\Module\BlockWishList\Grid\Data\BaseGridDataFactory;
|
||||
use PrestaShop\Module\BlockWishList\Type\ConfigurationType;
|
||||
use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteria;
|
||||
use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class WishlistConfigurationAdminController extends FrameworkBundleAdminController
|
||||
{
|
||||
/**
|
||||
* @var CacheProvider
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $shopId;
|
||||
|
||||
public function __construct(CacheProvider $cache, $shopId)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
$this->shopId = $shopId;
|
||||
}
|
||||
|
||||
public function configurationAction(Request $request)
|
||||
{
|
||||
$datas = $this->getWishlistConfigurationDatas();
|
||||
$configurationForm = $this->createForm(ConfigurationType::class, $datas);
|
||||
$configurationForm->handleRequest($request);
|
||||
$resultHandleForm = null;
|
||||
|
||||
if ($configurationForm->isSubmitted() && $configurationForm->isValid()) {
|
||||
$resultHandleForm = $this->handleForm($configurationForm->getData());
|
||||
if ($resultHandleForm) {
|
||||
return $this->redirectToRoute('blockwishlist_configuration');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('@Modules/blockwishlist/views/templates/admin/home.html.twig', [
|
||||
'configurationForm' => $configurationForm->createView(),
|
||||
'resultHandleForm' => $resultHandleForm,
|
||||
'enableSidebar' => true,
|
||||
'help_link' => $this->generateSidebarLink('WishlistConfigurationAdminController'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function statisticsAction()
|
||||
{
|
||||
$searchCriteria = new SearchCriteria();
|
||||
$allTimeStatsGridFactory = $this->get('prestashop.module.blockwishlist.grid.all_time_stastistics_grid_factory');
|
||||
$currentYearGridFactory = $this->get('prestashop.module.blockwishlist.grid.current_year_stastistics_grid_factory');
|
||||
$currentMonthGridFactory = $this->get('prestashop.module.blockwishlist.grid.current_month_stastistics_grid_factory');
|
||||
$currentDayGridFactory = $this->get('prestashop.module.blockwishlist.grid.current_day_stastistics_grid_factory');
|
||||
$allTimeStatisticsGrid = $allTimeStatsGridFactory->getGrid($searchCriteria);
|
||||
$currentYearGrid = $currentYearGridFactory->getGrid($searchCriteria);
|
||||
$currentMonthGrid = $currentMonthGridFactory->getGrid($searchCriteria);
|
||||
$currentDayGrid = $currentDayGridFactory->getGrid($searchCriteria);
|
||||
|
||||
return $this->render('@Modules/blockwishlist/views/templates/admin/statistics.html.twig', [
|
||||
'allTimeStatisticsGrid' => $this->presentGrid($allTimeStatisticsGrid),
|
||||
'currentYearStatisticsGrid' => $this->presentGrid($currentYearGrid),
|
||||
'currentMonthStatisticsGrid' => $this->presentGrid($currentMonthGrid),
|
||||
'currentDayStatisticsGrid' => $this->presentGrid($currentDayGrid),
|
||||
'shopId' => $this->shopId,
|
||||
'enableSidebar' => true,
|
||||
'help_link' => $this->generateSidebarLink('WishlistConfigurationAdminController'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function resetStatisticsCacheAction()
|
||||
{
|
||||
$result = $this->cache->delete(BaseGridDataFactory::CACHE_KEY_STATS_ALL_TIME . $this->shopId)
|
||||
&& $this->cache->delete(BaseGridDataFactory::CACHE_KEY_STATS_CURRENT_DAY . $this->shopId)
|
||||
&& $this->cache->delete(BaseGridDataFactory::CACHE_KEY_STATS_CURRENT_MONTH . $this->shopId)
|
||||
&& $this->cache->delete(BaseGridDataFactory::CACHE_KEY_STATS_CURRENT_YEAR . $this->shopId);
|
||||
|
||||
return new JsonResponse(['success' => $result]);
|
||||
}
|
||||
|
||||
/**
|
||||
* handleForm
|
||||
*
|
||||
* @param array $datas
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function handleForm($datas)
|
||||
{
|
||||
$result = true;
|
||||
$defaultLanguageId = (int) Configuration::get('PS_LANG_DEFAULT');
|
||||
|
||||
if (isset($datas['WishlistPageName'])) {
|
||||
foreach ($datas['WishlistPageName'] as $langID => $value) {
|
||||
if (empty($value) && $langID != $defaultLanguageId) {
|
||||
$value = $datas['WishlistPageName'][$defaultLanguageId];
|
||||
}
|
||||
$result = $result && Configuration::updateValue('blockwishlist_WishlistPageName', [$langID => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($datas['WishlistDefaultTitle'])) {
|
||||
foreach ($datas['WishlistDefaultTitle'] as $langID => $value) {
|
||||
if (empty($value) && $langID != $defaultLanguageId) {
|
||||
$value = $datas['WishlistDefaultTitle'][$defaultLanguageId];
|
||||
}
|
||||
$result = $result && Configuration::updateValue('blockwishlist_WishlistDefaultTitle', [$langID => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($datas['CreateButtonLabel'])) {
|
||||
foreach ($datas['CreateButtonLabel'] as $langID => $value) {
|
||||
if (empty($value) && $langID != $defaultLanguageId) {
|
||||
$value = $datas['CreateButtonLabel'][$defaultLanguageId];
|
||||
}
|
||||
$result = $result && Configuration::updateValue('blockwishlist_CreateButtonLabel', [$langID => $value]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($result === true) {
|
||||
$this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success'));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* getWishlistConfigurationDatas
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getWishlistConfigurationDatas()
|
||||
{
|
||||
$languages = Language::getLanguages(true);
|
||||
$wishlistNames = $wishlistDefaultTitles = $wishlistCreateNewButtonsLabel = [];
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
$wishlistNames[$lang['id_lang']] = Configuration::get('blockwishlist_WishlistPageName', $lang['id_lang']);
|
||||
$wishlistDefaultTitles[$lang['id_lang']] = Configuration::get('blockwishlist_WishlistDefaultTitle', $lang['id_lang']);
|
||||
$wishlistCreateNewButtonsLabel[$lang['id_lang']] = Configuration::get('blockwishlist_CreateButtonLabel', $lang['id_lang']);
|
||||
}
|
||||
|
||||
$datas = [
|
||||
'WishlistPageName' => $wishlistNames,
|
||||
'WishlistDefaultTitle' => $wishlistDefaultTitles,
|
||||
'CreateButtonLabel' => $wishlistCreateNewButtonsLabel,
|
||||
];
|
||||
|
||||
return $datas;
|
||||
}
|
||||
}
|
||||
140
modules/blockwishlist/src/Database/Install.php
Normal file
140
modules/blockwishlist/src/Database/Install.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Database;
|
||||
|
||||
use BlockWishList;
|
||||
use Configuration;
|
||||
use Db;
|
||||
use Language;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
use Tab;
|
||||
|
||||
class Install
|
||||
{
|
||||
/**
|
||||
* @var TranslatorInterface
|
||||
*/
|
||||
protected $translator;
|
||||
|
||||
public function __construct(TranslatorInterface $translator)
|
||||
{
|
||||
$this->translator = $translator;
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
return $this->installTables()
|
||||
&& $this->installConfiguration()
|
||||
&& $this->installTabs();
|
||||
}
|
||||
|
||||
public function installTables()
|
||||
{
|
||||
$sql = [];
|
||||
|
||||
$sql[] = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'wishlist` (
|
||||
`id_wishlist` int(10) unsigned NOT NULL auto_increment,
|
||||
`id_customer` int(10) unsigned NOT NULL,
|
||||
`id_shop` int(10) unsigned default 1,
|
||||
`id_shop_group` int(10) unsigned default 1,
|
||||
`token` varchar(64) NOT NULL,
|
||||
`name` varchar(64) NOT NULL,
|
||||
`counter` int(10) unsigned NULL,
|
||||
`date_add` datetime NOT NULL,
|
||||
`date_upd` datetime NOT NULL,
|
||||
`default` int(10) unsigned default 0,
|
||||
PRIMARY KEY (`id_wishlist`)
|
||||
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[] = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'wishlist_product` (
|
||||
`id_wishlist_product` int(10) NOT NULL auto_increment,
|
||||
`id_wishlist` int(10) unsigned NOT NULL,
|
||||
`id_product` int(10) unsigned NOT NULL,
|
||||
`id_product_attribute` int(10) unsigned NOT NULL,
|
||||
`quantity` int(10) unsigned NOT NULL,
|
||||
`priority` int(10) unsigned NOT NULL,
|
||||
PRIMARY KEY (`id_wishlist_product`)
|
||||
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[] = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'wishlist_product_cart` (
|
||||
`id_wishlist_product` int(10) unsigned NOT NULL,
|
||||
`id_cart` int(10) unsigned NOT NULL,
|
||||
`quantity` int(10) unsigned NOT NULL,
|
||||
`date_add` datetime NOT NULL
|
||||
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$sql[] = 'CREATE TABLE IF NOT EXISTS `' . _DB_PREFIX_ . 'blockwishlist_statistics` (
|
||||
`id_statistics` int(10) unsigned NOT NULL auto_increment,
|
||||
`id_cart` int(10) unsigned default NULL,
|
||||
`id_product` int(10) unsigned NOT NULL,
|
||||
`id_product_attribute` int(10) unsigned NOT NULL,
|
||||
`date_add` datetime NOT NULL,
|
||||
`id_shop` int(10) unsigned default 1,
|
||||
PRIMARY KEY (`id_statistics`)
|
||||
) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;';
|
||||
|
||||
$result = true;
|
||||
|
||||
foreach ($sql as $query) {
|
||||
$result = $result && Db::getInstance()->execute($query);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function installConfiguration()
|
||||
{
|
||||
$pageName = $defaultName = $createButtonLabel = [];
|
||||
|
||||
foreach (Language::getLanguages() as $lang) {
|
||||
$pageName[$lang['id_lang']] = $this->translator->trans('My wishlists', [], 'Modules.Blockwishlist.Admin', $lang['locale']);
|
||||
$defaultName[$lang['id_lang']] = $this->translator->trans('My wishlist', [], 'Modules.Blockwishlist.Admin', $lang['locale']);
|
||||
$createButtonLabel[$lang['id_lang']] = $this->translator->trans('Create new list', [], 'Modules.Blockwishlist.Admin', $lang['locale']);
|
||||
}
|
||||
|
||||
return Configuration::updateValue('blockwishlist_WishlistPageName', $pageName)
|
||||
&& Configuration::updateValue('blockwishlist_WishlistDefaultTitle', $defaultName)
|
||||
&& Configuration::updateValue('blockwishlist_CreateButtonLabel', $createButtonLabel);
|
||||
}
|
||||
|
||||
public function installTabs()
|
||||
{
|
||||
$installTabCompleted = true;
|
||||
|
||||
foreach (BlockWishList::MODULE_ADMIN_CONTROLLERS as $controller) {
|
||||
if (Tab::getIdFromClassName($controller['class_name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tab = new Tab();
|
||||
$tab->class_name = $controller['class_name'];
|
||||
$tab->active = $controller['visible'];
|
||||
foreach (Language::getLanguages() as $lang) {
|
||||
$tab->name[$lang['id_lang']] = $this->translator->trans($controller['name'], [], 'Modules.BlockWishList.Admin', $lang['locale']);
|
||||
}
|
||||
$tab->id_parent = Tab::getIdFromClassName($controller['parent_class_name']);
|
||||
$tab->module = 'blockwishlist';
|
||||
$installTabCompleted = $installTabCompleted && $tab->add();
|
||||
}
|
||||
|
||||
return $installTabCompleted;
|
||||
}
|
||||
}
|
||||
64
modules/blockwishlist/src/Database/Uninstall.php
Normal file
64
modules/blockwishlist/src/Database/Uninstall.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Database;
|
||||
|
||||
use BlockWishList;
|
||||
use Db;
|
||||
use Tab;
|
||||
use Validate;
|
||||
|
||||
class Uninstall
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
return $this->dropTables() && $this->uninstallTabs();
|
||||
}
|
||||
|
||||
private function dropTables()
|
||||
{
|
||||
$sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'wishlist`';
|
||||
$sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'wishlist_product`';
|
||||
$sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'wishlist_product_cart`';
|
||||
$sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'blockwishlist_statistics`';
|
||||
|
||||
$result = true;
|
||||
foreach ($sql as $query) {
|
||||
$result = $result && Db::getInstance()->execute($query);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function uninstallTabs()
|
||||
{
|
||||
$uninstallTabCompleted = true;
|
||||
|
||||
foreach (BlockWishList::MODULE_ADMIN_CONTROLLERS as $controller) {
|
||||
$id_tab = (int) Tab::getIdFromClassName($controller['class_name']);
|
||||
$tab = new Tab($id_tab);
|
||||
if (Validate::isLoadedObject($tab)) {
|
||||
$uninstallTabCompleted = $uninstallTabCompleted && $tab->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return $uninstallTabCompleted;
|
||||
}
|
||||
}
|
||||
28
modules/blockwishlist/src/Database/index.php
Normal file
28
modules/blockwishlist/src/Database/index.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* 2007-2020 PrestaShop and Contributors
|
||||
*
|
||||
* NOTICE OF LICENSE
|
||||
*
|
||||
* This source file is subject to the Academic Free License 3.0 (AFL-3.0)
|
||||
* that is bundled with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* https://opensource.org/licenses/AFL-3.0
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@prestashop.com so we can send you a copy immediately.
|
||||
*
|
||||
* @author PrestaShop SA <contact@prestashop.com>
|
||||
* @copyright 2007-2020 PrestaShop SA and Contributors
|
||||
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License 3.0 (AFL-3.0)
|
||||
* International Registered Trademark & Property of PrestaShop SA
|
||||
*/
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
|
||||
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
header('Location: ../');
|
||||
exit;
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace PrestaShop\Module\BlockWishList\Grid\Data;
|
||||
|
||||
use PrestaShop\PrestaShop\Core\Grid\Data\Factory\GridDataFactoryInterface;
|
||||
use PrestaShop\PrestaShop\Core\Grid\Data\GridData;
|
||||
use PrestaShop\PrestaShop\Core\Grid\Record\RecordCollection;
|
||||
use PrestaShop\PrestaShop\Core\Grid\Search\SearchCriteriaInterface;
|
||||
|
||||
class AllTimeStatisticsGridDataFactory extends BaseGridDataFactory implements GridDataFactoryInterface
|
||||
{
|
||||
// 1 month
|
||||
const CACHE_LIFETIME_SECONDS = 2629746;
|
||||
|
||||
public function getData(SearchCriteriaInterface $searchCriteria)
|
||||
{
|
||||
if ($this->cache->contains(self::CACHE_KEY_STATS_ALL_TIME . $this->shopId)) {
|
||||
$results = $this->cache->fetch(self::CACHE_KEY_STATS_ALL_TIME . $this->shopId);
|
||||
} else {
|
||||
$results = $this->calculator->computeStatsFor('allTime');
|
||||
$this->cache->save(self::CACHE_KEY_STATS_ALL_TIME . $this->shopId, $results, self::CACHE_LIFETIME_SECONDS);
|
||||
}
|
||||
|
||||
return new GridData(new RecordCollection($results), count($results));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user