Jump to content
thirty bees forum

ssimard

Members
  • Posts

    162
  • Joined

  • Last visited

  • Days Won

    1

Everything posted by ssimard

  1. Any updates on this ? I am having the exact same issue as op. I've just activated the Mailchimp 1.5.0 module and subscribers with active = 0 in the newsletter table are still subscribed to the Mailchimp list, even thou they did not click the confirmation link sent by email.
  2. Thanks Lesley, I understand the reason behind updating things but sometimes I just can't do it blindly. Btw, the modules controllers can't be override (or maybe I just never understood how to properly do it), you can just override the root php file if I remember well. In some cases, I had to do some fixes in classes directly in the modules folder.
  3. Hi everyone, I am now using TB on a production site and would like to keep it as-is, without updating the modules since I have a lot of overrides. Is there a way to turn the module update warnings OFF ? Especially for the non-admin employees. Right-now I have permissions restricted for a few people but they should be able to update some modules configs and therefore, they are seing the modules lists. I don't want them to click on update buttons thou ! Any ideas ? Thanks. Sylvain
  4. Awesome, not going to update my shop yet as I will upgrade my server to PHP 7.1 first but will definitely do it when I get a chance. Thank you !
  5. Well the iPhone X and the Plus variants (6 Plus, 7 Plus and 8 Plus) are all using a retina 3x display (but TB does not create them). I don't know anything with a 4x display, does not mean there are none thou.
  6. @mockob you don't have to overwrite anything if you are only uploading your images via the backend, it will work. The only thing you have to change is in the template itself, in the Smarty files. @mdekker was supposed to fix it in the core for the CSV and Webservice upload.
  7. Take a look at my replies in this particular thread: https://forum.thirtybees.com/topic/40/retina-images-please-help Also be aware that the 2x images are not created if you use the csv import and neither are they if you are using the API. You will have to edit the template yourself and for the csv and API import there are fixes I will dig my old thread for you .. Here: https://forum.thirtybees.com/topic/798/retina-images-are-not-created-when-uploading-through-the-webservice This was supposed to be added to the core so i don't know if it has been yet.
  8. Yeah, our tech support staff wanted a few things added before using it. I'll see what else is missing, we are also adding an option to simply send a message to multiple persons without reassigning it to anybody. Sometimes, our tech support staff are sending me and other colleagues questions that they don't know how to answer. They have to be able to send it to multiple persons at once and also, I don't want it to be 'reassigned' to me in the backend. So basically just a 'forward' option. We are almost done on that too.
  9. Well I finally did it myself. I posted it in the tips and tricks section. Here: https://forum.thirtybees.com/topic/1626/customer-service-add-predefined-messages Cheers !
  10. Hi all, well I went ahead and did it myself. Here are the steps in order to add predefined messages in the customer service section. I hope that it will be useful for someone. ** Sorry about the french screenshots and strings, I am running a french site so it is what it is :grinning: ** You will have to duplicate the 2 database tables used by the orders predefined messages option. They are "xxordermessage" and "xxordermessagelang". Duplicate the structure only and rename them to "xxclientmessage" and "xxclientmessagelang". In both new tables, change the first column name to "idclientmessage". In the override section, create AdminClientMessageController.php and add the following code. ``` <?php /** * 2007-2016 PrestaShop * * Thirty Bees is an extension to the PrestaShop e-commerce software developed by PrestaShop SA * Copyright (C) 2017 Thirty Bees * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 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: * http://opensource.org/licenses/osl-3.0.php * 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@thirtybees.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://www.thirtybees.com for more information. * * @author Thirty Bees contact@thirtybees.com * @author PrestaShop SA contact@prestashop.com * @copyright 2017 Thirty Bees * @copyright 2007-2016 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * PrestaShop is an internationally registered trademark & property of PrestaShop SA */ /** * Class AdminClientMessageControllerCore * * @since 1.0.0 */ class AdminClientMessageControllerCore extends AdminController { /** * AdminClintMessageControllerCore constructor. * * @since 1.0.0 */ public function __construct() { $this->bootstrap = true; $this->table = 'client_message'; $this->className = 'ClientMessage'; $this->lang = true; $this->addRowAction('edit'); $this->addRowAction('delete'); $this->context = Context::getContext(); if (!Tools::getValue('realedit')) { $this->deleted = false; } $this->bulk_actions = [ 'delete' => [ 'text' => $this->l('Delete selected'), 'confirm' => $this->l('Delete selected items?'), 'icon' => 'icon-trash', ], ]; $this->fields_list = [ 'id_client_message' => [ 'title' => $this->l('ID'), 'align' => 'center', ], 'name' => [ 'title' => $this->l('Name'), ], 'message' => [ 'title' => $this->l('Message'), 'maxlength' => 300, ], ]; $this->fields_form = [ 'legend' => [ 'title' => $this->l('Client messages'), 'icon' => 'icon-mail', ], 'input' => [ [ 'type' => 'text', 'lang' => true, 'label' => $this->l('Name'), 'name' => 'name', 'size' => 53, 'required' => true, ], [ 'type' => 'textarea', 'lang' => true, 'label' => $this->l('Message'), 'name' => 'message', 'required' => true, ], ], 'submit' => [ 'title' => $this->l('Save'), ], ]; parent::__construct(); } /** * Initialize page header toolbar * * @return void * * @since 1.0.0 */ public function initPageHeaderToolbar() { if (empty($this->display)) { $this->page_header_toolbar_btn['new_client_message'] = [ 'href' => static::$currentIndex.'&addclient_message&token='.$this->token, 'desc' => $this->l('Ajouter un nouveau message client'), 'icon' => 'process-icon-new', ]; } parent::initPageHeaderToolbar(); } } ``` 3. In override, create ClientMessage.php and paste the following code inside. ```<?php /** * 2007-2016 PrestaShop * * Thirty Bees is an extension to the PrestaShop e-commerce software developed by PrestaShop SA * Copyright (C) 2017 Thirty Bees * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 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: * http://opensource.org/licenses/osl-3.0.php * 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@thirtybees.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://www.thirtybees.com for more information. * * @author Thirty Bees contact@thirtybees.com * @author PrestaShop SA contact@prestashop.com * @copyright 2017 Thirty Bees * @copyright 2007-2016 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * PrestaShop is an internationally registered trademark & property of PrestaShop SA */ /** * Class ClientMessageCore * * @since 1.0.0 */ class ClientMessageCore extends ObjectModel { // @codingStandardsIgnoreStart /** @var string name name */ public $name; /** @var string message content */ public $message; /** @var string Object creation date */ public $date_add; // @codingStandardsIgnoreEnd /** * @see ObjectModel::$definition */ public static $definition = [ 'table' => 'client_message', 'primary' => 'id_client_message', 'multilang' => true, 'fields' => [ 'date_add' => ['type' => self::TYPE_DATE, 'validate' => 'isDate' ], 'name' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128 ], 'message' => ['type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isMessage', 'required' => true, 'size' => 1200], ], ]; protected $webserviceParameters = [ 'fields' => [ 'id' => ['sqlId' => 'id_discount_type', 'xlink_resource' => 'client_message_lang'], 'date_add' => ['sqlId' => 'date_add'], ], ]; /** * @param $idLang * * @return array|false|mysqli_result|null|PDOStatement|resource * * @since 1.0.0 * @version 1.0.0 Initial version */ public static function getClientMessages($idLang) { return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(' SELECT om.id_client_message, oml.name, oml.message FROM '._DB_PREFIX_.'client_message om LEFT JOIN '._DB_PREFIX_.'client_message_lang oml ON (oml.id_client_message = om.id_client_message) WHERE oml.id_lang = '.(int) $idLang.' ORDER BY name ASC'); } } ``` Next you will have to override AdminCustomerThreadsController.php in order to add the messages list to the template. Do it and add the following code into it. ``` <?php /** * 2007-2016 PrestaShop * * Thirty Bees is an extension to the PrestaShop e-commerce software developed by PrestaShop SA * Copyright (C) 2017 Thirty Bees * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 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: * http://opensource.org/licenses/osl-3.0.php * 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@thirtybees.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://www.thirtybees.com for more information. * * @author Thirty Bees contact@thirtybees.com * @author PrestaShop SA contact@prestashop.com * @copyright 2017 Thirty Bees * @copyright 2007-2016 PrestaShop SA * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * PrestaShop is an internationally registered trademark & property of PrestaShop SA */ /** * Class AdminCustomerThreadsControllerCore * * @since 1.0.0 */ class AdminCustomerThreadsController extends AdminCustomerThreadsControllerCore { /** * Render view * * @return string * * @since 1.0.0 */ public function renderView() { if (!$idCustomerThread = (int) Tools::getValue('id_customer_thread')) { return ''; } $this->context = Context::getContext(); if (!($thread = $this->loadObject())) { return ''; } $this->context->cookie->{'customer_threadFilter_cl!id_contact'} = $thread->id_contact; $employees = Employee::getEmployees(); $messages = CustomerThread::getMessageCustomerThreads($idCustomerThread); foreach ($messages as $key => $mess) { if ($mess['id_employee']) { $employee = new Employee($mess['id_employee']); $messages[$key]['employee_image'] = $employee->getImage(); } if (isset($mess['file_name']) && $mess['file_name'] != '') { $messages[$key]['file_name'] = _THEME_PROD_PIC_DIR_.$mess['file_name']; } else { unset($messages[$key]['file_name']); } if ($mess['id_product']) { $product = new Product((int) $mess['id_product'], false, $this->context->language->id); if (Validate::isLoadedObject($product)) { $messages[$key]['product_name'] = $product->name; $messages[$key]['product_link'] = $this->context->link->getAdminLink('AdminProducts').'&updateproduct&id_product='.(int) $product->id; } } } $nextThread = CustomerThread::getNextThread((int) $thread->id); $contacts = Contact::getContacts($this->context->language->id); $actions = []; if ($nextThread) { $nextThread = [ 'href' => static::$currentIndex.'&id_customer_thread='.(int) $nextThread.'&viewcustomer_thread&token='.$this->token, 'name' => $this->l('Reply to the next unanswered message in this thread'), ]; } if ($thread->status != 'closed') { $actions['closed'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=2&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "handled"'), 'name' => 'setstatus', 'value' => 2, ]; } else { $actions['open'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Re-open'), 'name' => 'setstatus', 'value' => 1, ]; } if ($thread->status != 'pending1') { $actions['pending1'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=3&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "pending 1" (will be answered later)'), 'name' => 'setstatus', 'value' => 3, ]; } else { $actions['pending1'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Disable pending status'), 'name' => 'setstatus', 'value' => 1, ]; } if ($thread->status != 'pending2') { $actions['pending2'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=4&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "pending 2" (will be answered later)'), 'name' => 'setstatus', 'value' => 4, ]; } else { $actions['pending2'] = [ 'href' => static::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int) Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Disable pending status'), 'name' => 'setstatus', 'value' => 1, ]; } if ($thread->id_customer) { $customer = new Customer($thread->id_customer); $orders = Order::getCustomerOrders($customer->id); if ($orders && count($orders)) { $totalOk = 0; $ordersOk = []; foreach ($orders as $key => $order) { if ($order['valid']) { $ordersOk[] = $order; $totalOk += $order['total_paid_real'] / $order['conversion_rate']; } $orders[$key]['date_add'] = Tools::displayDate($order['date_add']); $orders[$key]['total_paid_real'] = Tools::displayPrice($order['total_paid_real'], new Currency((int) $order['id_currency'])); } } $products = $customer->getBoughtProducts(); if ($products && count($products)) { foreach ($products as $key => $product) { $products[$key]['date_add'] = Tools::displayDate($product['date_add'], null, true); } } } $timelineItems = $this->getTimeline($messages, $thread->id_order); $firstMessage = $messages[0]; if (!$messages[0]['id_employee']) { unset($messages[0]); } $contact = ''; foreach ($contacts as $c) { if ($c['id_contact'] == $thread->id_contact) { $contact = $c['name']; } } $this->tpl_view_vars = [ 'id_customer_thread' => $idCustomerThread, 'thread' => $thread, 'actions' => $actions, 'employees' => $employees, 'current_employee' => $this->context->employee, 'messages' => $messages, 'first_message' => $firstMessage, 'contact' => $contact, 'next_thread' => $nextThread, 'orders' => isset($orders) ? $orders : false, 'customer' => isset($customer) ? $customer : false, 'products' => isset($products) ? $products : false, 'total_ok' => isset($totalOk) ? Tools::displayPrice($totalOk, $this->context->currency) : false, 'orders_ok' => isset($ordersOk) ? $ordersOk : false, 'count_ok' => isset($ordersOk) ? count($ordersOk) : false, 'PS_CUSTOMER_SERVICE_SIGNATURE' => str_replace('\r\n', "\n", Configuration::get('PS_CUSTOMER_SERVICE_SIGNATURE', (int) $thread->id_lang)), 'timeline_items' => $timelineItems, 'clientMessages' => ClientMessage::getClientMessages($thread->id_lang), ]; if ($nextThread) { $this->tpl_view_vars['next_thread'] = $nextThread; } return AdminController::renderView(); } } ``` 5. And finally, you will have to override the helper view.tpl with the following code. ``` {* * 2007-2016 PrestaShop * * NOTICE OF LICENSE * * This source file is subject to the Academic Free License (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: * http://opensource.org/licenses/afl-3.0.php * 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. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to http://www.prestashop.com for more information. * * @author PrestaShop SA contact@prestashop.com * @copyright 2007-2016 PrestaShop SA * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) * International Registered Trademark & Property of PrestaShop SA *} {extends file="helpers/view/view.tpl"} {block name="overridetpl"} {include file="controllers/customerthreads/helpers/view/modal.tpl" } {l s="Thread"}: #{$id_customer_thread|intval} {if isset($next_thread) && $next_thread} {$next_thread.name} {/if} {foreach $actions as $action} {if isset($action.icon)}{/if}{$action.label} {/foreach} {l s="Forward this discussion to another employee"} {if isset($customer->firstname)} {$customer->firstname|escape:'html':'UTF-8'} {$customer->lastname|escape:'html':'UTF-8'} ({$customer->email|escape:'html':'UTF-8'}) {else} {$thread->email|escape:'html':'UTF-8'} {/if} {if isset($contact) && trim($contact) != ''} {l s="To:"} {$contact|escape:'html':'UTF-8'} {/if} {if isset($customer->firstname)} {if $count_ok} {l s='[1]%1$d[/1] order(s) validated for a total amount of [2]%2$s[/2]' sprintf=[$count_ok, $total_ok] tags=['', '']} {else} {l s="No orders validated for the moment"} {/if} {l s="Customer since: %s" sprintf=[{dateFormat date=$customer->date_add full=0}]} {/if} {if !$first_message.id_employee} {include file="controllers/customer_threads/helpers/view/message.tpl" message=$first_message initial=true} {/if} </div> <div class="row"> {foreach $messages as $message} {include file="controllers/customer_threads/helpers/view/message.tpl" message=$message initial=false} {/foreach} </div> {l s="Your answer to"} {if isset($customer->firstname)}{$customer->firstname|escape:'html':'UTF-8'} {$customer->lastname|escape:'html':'UTF-8'} {else} {$thread->email}{/if} {if isset($current_employee->firstname)}{/if} {$PS_CUSTOMER_SERVICE_SIGNATURE|escape:'html':'UTF-8'} {l s='Messages prédéfinis'} - {foreach from=$clientMessages item=clientMessage} {$clientMessage['name']} {/foreach} {l s='Configurer les messages prédéfinis'} <div class="panel-footer"> <!-- <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <i class="icon-magic icon-2x"></i><br> {l s="Choose a template"} </button> --> <button class="btn btn-default pull-right" name="submitReply"><i class="process-icon-mail-reply"></i> {l s="Send"}</button> <input type="hidden" name="id_customer_thread" value="{$thread->id|intval}" /> <input type="hidden" name="msg_email" value="{$thread->email}" /> </div> </form> {if count($timeline_items)} {l s="Orders and messages timeline"} {foreach $timeline_items as $dates} {foreach from=$dates key=date item=timeline_item} {include file="controllers/customer_threads/helpers/view/timeline_item.tpl" timeline_item=$timeline_item} {/foreach} {/foreach} {/if} {/block} ``` @@@@@ Code is complete, don't forget to delete class_index.php in your cache folder before running it. Your customer service reply page should now look like this: To add the management link to the clients menu, just go to administration-menus and add an item like this: ----> One last important thing, you may notice that the drop-down length is fine at first but does not scale if you resize your window. There is a bug in the chosen implementation (you will notice the same problem in the orders section). To fix it, you will have to edit js/admin.js and add the width parameter and set it to 100%. You should now be able to add as many predefined replies as you wish. Hopefully I did not forget anything but feel free to post if you have problems and I will do my best to help you out. Cheers !
  11. Not really what I am looking for but thanks ;-) Our customer support staff are already using predefined messages in gmail in order to quickly reply to the most common issues but I don't want them to copy/paste an answer in the back office module. I would really like them to use it thou... I might have to do it myself if it doesn't exist..
  12. Is there a way to create predefined messages for the most popular tech support emails ? I found a way to do it in the orders section but not in the customer service.. which would really help. Thanks.
  13. I can confirm that's it's a lot of work to do. Not sure if you would be better starting from another theme or not, I pretty much jumped in TB at the first public release so the version of the theme I used was a bit older than what you have now. For me the hardest has been to hack the suppliers into authors. Also selling PDF and ePubs of my book as variations was a nice puzzle. If you like retina images, be aware that the default theme does not support them (or at least did not at first). You can search the forum for my threads on retina images, good advices and code examples for you to fix it.
  14. @hubbobubbo said in My site has finally launched !: Nice shop, well done. Which theme did you use as base? Thanks, started with the default theme.
  15. I don't think I can move it myself, or can I ?
  16. I'm glad that you find it useful, it definitely makes life easier for me since I am tagging books on multiple pre-defined keywords.
  17. If you had an overriden product.php already then you should just add the function into it..
  18. I'm not sure why it's not working, I haven't posted the full override code for product.php but I assume that you've done it properly ? ``` class Product extends ProductCore{ public function getAllTags($idlang = 0, $qty = 10){ if(!$idlang){ $context = Context::getContext(); $id_lang = $context->language->id; } return Tag::getTags($id_lang, $qty); } } ``` I'm really sorry, I fail to see why it is not working on your end :-/
  19. You have to override the Tag class for this to work. Look in my accepted answer. Basically, it is just an SQL request that retrieves entries in the tag database. It is called by the getAllTags function that you have to add to product.php class as well. Make sure that you have datas in that table. I can't read German, what does the full error means ?
  20. @zimmer-media You should be good if you modify the 3 files I pointed out in my previous post. You can do a quick test and just pass a manual list of keywords to the autocomplete function in Informations.tpl. -> /override/controllers/admin/templates/products/informations.tpl Find the code in the original file(between line 438 and 448) and replace it with this: ``` {literal} {/literal} ```
  21. I forgot to mention that you have to override product.php, of course, and delete the cache file.. (class_index.php). -> /override/controllers/admin/templates/products/informations.tpl -> /override/classes/Tag.php -> /override/classes/Product.php
  22. @lathaneo said in Keywords autocomplete in the products page: Hi, Tagify doesn't work with jquery autocomplete. Tagify use only the widget factory of JqueryUI. Regards. I only wanted to make it easier to choose keywords while typing. I have several keywords that are the same for several books (kinda like bisac codes if you're familiar). It is working now with JQuery autocomplete (see the code I posted). The only downside is that you have to click once to select it then ENTER in order to confirm.
  23. There was a conflict between JQueryUI and standard JQuery it seems.. here's what I did in the end using standard JQuery autocomplete: Informations.tpl ``` {literal} {/literal} ``` Tag.php class Tag extends TagCore { public static function getTags($id_lang, $nb = 10) { return Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT t.`name` FROM `'._DB_PREFIX_.'tag` t WHERE t.`id_lang` = '.(int)$id_lang.' ORDER BY t.`name` ASC'); //I commented this out since I need them all and not only the first 10. Could be useful to someone, I don't know. //LIMIT 0, '.(int)$nb); } } Product.php, added this function: ``` class Product extends ProductCore{ public function getAllTags($idlang = 0, $qty = 10){ if(!$idlang){ $context = Context::getContext(); $id_lang = $context->language->id; } return Tag::getTags($id_lang, $qty); } } ```
×
×
  • Create New...