Refactored back-office customer management

This commit is contained in:
Franck Allimant
2013-11-09 18:28:01 +01:00
parent 85ea937570
commit ac74c1d61d
17 changed files with 748 additions and 600 deletions

View File

@@ -83,9 +83,10 @@ class Customer extends BaseAction implements EventSubscriberInterface
public function delete(CustomerEvent $event) public function delete(CustomerEvent $event)
{ {
$customer = $event->getCustomer(); if (null !== $customer = $event->getCustomer()) {
$customer->delete(); $customer->delete();
}
} }
private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event) private function createOrUpdateCustomer(CustomerModel $customer, CustomerCreateOrUpdateEvent $event)

View File

@@ -109,19 +109,17 @@
<!-- Customer rule management --> <!-- Customer rule management -->
<route id="admin.customers" path="/admin/customers"> <route id="admin.customers" path="/admin/customers">
<default key="_controller">Thelia\Controller\Admin\CustomerController::indexAction</default> <default key="_controller">Thelia\Controller\Admin\CustomerController::defaultAction</default>
</route> </route>
<route id="admin.customer.update.view" path="/admin/customer/update/{customer_id}" methods="get"> <route id="admin.customer.update.view" path="/admin/customer/update">
<default key="_controller">Thelia\Controller\Admin\CustomerController::viewAction</default>
<requirement key="customer_id">\d+</requirement>
</route>
<route id="admin.customer.update.process" path="/admin/customer/update/{customer_id}" methods="post">
<default key="_controller">Thelia\Controller\Admin\CustomerController::updateAction</default> <default key="_controller">Thelia\Controller\Admin\CustomerController::updateAction</default>
<requirement key="customer_id">\d+</requirement>
</route> </route>
<route id="admin.customer.update.process" path="/admin/customer/save">
<default key="_controller">Thelia\Controller\Admin\CustomerController::processUpdateAction</default>
</route>
<route id="admin.customer.delete" path="/admin/customer/delete"> <route id="admin.customer.delete" path="/admin/customer/delete">
<default key="_controller">Thelia\Controller\Admin\CustomerController::deleteAction</default> <default key="_controller">Thelia\Controller\Admin\CustomerController::deleteAction</default>
</route> </route>
@@ -146,14 +144,12 @@
<default key="_controller">Thelia\Controller\Admin\AddressController::createAction</default> <default key="_controller">Thelia\Controller\Admin\AddressController::createAction</default>
</route> </route>
<route id="admin.address.update.view" path="/admin/address/update/{address_id}"> <route id="admin.address.update.view" path="/admin/address/update">
<default key="_controller">Thelia\Controller\Admin\AddressController::updateAction</default> <default key="_controller">Thelia\Controller\Admin\AddressController::updateAction</default>
<requirement key="address_id">\d+</requirement>
</route> </route>
<route id="admin.address.save" path="/admin/address/save/{address_id}"> <route id="admin.address.save" path="/admin/address/save">
<default key="_controller">Thelia\Controller\Admin\AddressController::processUpdateAction</default> <default key="_controller">Thelia\Controller\Admin\AddressController::processUpdateAction</default>
<requirement key="address_id">\d+</requirement>
</route> </route>
<!-- end address management --> <!-- end address management -->

View File

@@ -42,7 +42,7 @@ class AddressController extends AbstractCrudController
public function __construct() public function __construct()
{ {
parent::__construct( parent::__construct(
'address', 'registration_date',
null, null,
null, null,
@@ -50,10 +50,7 @@ class AddressController extends AbstractCrudController
TheliaEvents::ADDRESS_CREATE, TheliaEvents::ADDRESS_CREATE,
TheliaEvents::ADDRESS_UPDATE, TheliaEvents::ADDRESS_UPDATE,
TheliaEvents::ADDRESS_DELETE, TheliaEvents::ADDRESS_DELETE
null,
null
); );
} }
@@ -79,7 +76,7 @@ class AddressController extends AbstractCrudController
\Thelia\Log\Tlog::getInstance()->error(sprintf("error during address setting as default with message %s", $e->getMessage())); \Thelia\Log\Tlog::getInstance()->error(sprintf("error during address setting as default with message %s", $e->getMessage()));
} }
$this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId())); $this->redirectToEditionTemplate();
} }
/** /**
@@ -99,13 +96,14 @@ class AddressController extends AbstractCrudController
} }
/** /**
* Hydrate the update form for this object, before passing it to the update template * Fills in the form data array
* *
* @param \Thelia\Model\Address $object * @param unknown $object
* @return multitype:NULL
*/ */
protected function hydrateObjectForm($object) protected function createFormDataArray($object)
{ {
$data = array( return array(
"label" => $object->getLabel(), "label" => $object->getLabel(),
"title" => $object->getTitleId(), "title" => $object->getTitleId(),
"firstname" => $object->getFirstname(), "firstname" => $object->getFirstname(),
@@ -120,8 +118,16 @@ class AddressController extends AbstractCrudController
"phone" => $object->getPhone(), "phone" => $object->getPhone(),
"company" => $object->getCompany() "company" => $object->getCompany()
); );
}
return new AddressUpdateForm($this->getRequest(), "form", $data); /**
* Hydrate the update form for this object, before passing it to the update template
*
* @param \Thelia\Model\Address $object
*/
protected function hydrateObjectForm($object)
{
return new AddressUpdateForm($this->getRequest(), "form", $this->createFormDataArray($object));
} }
/** /**
@@ -240,7 +246,8 @@ class AddressController extends AbstractCrudController
*/ */
protected function renderListTemplate($currentOrder) protected function renderListTemplate($currentOrder)
{ {
// TODO: Implement renderListTemplate() method. // We render here the customer edit template.
return $this->renderEditionTemplate();
} }
/** /**
@@ -248,9 +255,10 @@ class AddressController extends AbstractCrudController
*/ */
protected function renderEditionTemplate() protected function renderEditionTemplate()
{ {
return $this->render('ajax/address-update-modal', array( return $this->render('customer-edit', array(
"address_id" => $this->getRequest()->get('address_id'), "address_id" => $this->getRequest()->get('address_id'),
"customer_id" => $this->getExistingObject()->getCustomerId() "page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
)); ));
} }
@@ -259,8 +267,11 @@ class AddressController extends AbstractCrudController
*/ */
protected function redirectToEditionTemplate() protected function redirectToEditionTemplate()
{ {
$address = $this->getExistingObject(); // We display here the custromer edition template
$this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId())); $this->redirectToRoute('admin.customer.update.view', array(
"page" => $this->getRequest()->get('page'),
"customer_id" => $this->getCustomerId()
));
} }
/** /**
@@ -279,8 +290,7 @@ class AddressController extends AbstractCrudController
*/ */
protected function performAdditionalDeleteAction($deleteEvent) protected function performAdditionalDeleteAction($deleteEvent)
{ {
$address = $deleteEvent->getAddress(); $this->redirectToEditionTemplate();
$this->redirectToRoute('admin.customer.update.view', array(), array('customer_id' => $address->getCustomerId()));
} }
/** /**
@@ -298,4 +308,11 @@ class AddressController extends AbstractCrudController
{ {
$this->redirectToEditionTemplate(); $this->redirectToEditionTemplate();
} }
protected function getCustomerId() {
if (null !== $address = $this->getExistingObject())
return $address->getCustomerId();
else
return $this->getRequest()->get('customer_id', 0);
}
} }

View File

@@ -35,171 +35,96 @@ use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\CustomerQuery; use Thelia\Model\CustomerQuery;
use Thelia\Core\Translation\Translator; use Thelia\Core\Translation\Translator;
use Thelia\Tools\Password; use Thelia\Tools\Password;
use Thelia\Model\AddressQuery;
use Thelia\Model\Address;
/** /**
* Class CustomerController * Class CustomerController
* @package Thelia\Controller\Admin * @package Thelia\Controller\Admin
* @author Manuel Raynaud <mraynaud@openstudio.fr> * @author Manuel Raynaud <mraynaud@openstudio.fr>
*/ */
class CustomerController extends BaseAdminController class CustomerController extends AbstractCrudController
{ {
public function indexAction() public function __construct()
{ {
if (null !== $response = $this->checkAuth(AdminResources::CUSTOMER, AccessManager::VIEW)) return $response; parent::__construct(
return $this->render("customers", array("display_customer" => 20)); 'customer',
'lastname',
'customer_order',
AdminResources::CUSTOMER,
TheliaEvents::CUSTOMER_CREATEACCOUNT,
TheliaEvents::CUSTOMER_UPDATEACCOUNT,
TheliaEvents::CUSTOMER_DELETEACCOUNT
);
} }
public function viewAction($customer_id) protected function getCreationForm()
{ {
if (null !== $response = $this->checkAuth(AdminResources::CUSTOMER, AccessManager::VIEW)) return $response; return new CustomerCreateForm($this->getRequest());
return $this->render("customer-edit", array(
"customer_id" => $customer_id
));
} }
/** protected function getUpdateForm()
* update customer action
*
* @param $customer_id
* @return mixed|\Thelia\Core\HttpFoundation\Response
*/
public function updateAction($customer_id)
{ {
if (null !== $response = $this->checkAuth(AdminResources::CUSTOMER, AccessManager::UPDATE)) return $response; return new CustomerUpdateForm($this->getRequest());
$message = false;
$customerUpdateForm = new CustomerUpdateForm($this->getRequest());
try {
$customer = CustomerQuery::create()->findPk($customer_id);
if (null === $customer) {
throw new \InvalidArgumentException(sprintf("%d customer id does not exist", $customer_id));
}
$form = $this->validateForm($customerUpdateForm);
$event = $this->createEventInstance($form->getData());
$event->setCustomer($customer);
$this->dispatch(TheliaEvents::CUSTOMER_UPDATEACCOUNT, $event);
$customerUpdated = $event->getCustomer();
$this->adminLogAppend(AdminResources::CUSTOMER, AccessManager::UPDATE, sprintf("Customer with Ref %s (ID %d) modified", $customerUpdated->getRef() , $customerUpdated->getId()));
if ($this->getRequest()->get("save_mode") == "close") {
$this->redirectToRoute("admin.customers");
} else {
$this->redirectSuccess($customerUpdateForm);
}
} catch (FormValidationException $e) {
$message = sprintf("Please check your input: %s", $e->getMessage());
} catch (PropelException $e) {
$message = $e->getMessage();
} catch (\Exception $e) {
$message = sprintf("Sorry, an error occured: %s", $e->getMessage()." ".$e->getFile());
}
if ($message !== false) {
\Thelia\Log\Tlog::getInstance()->error(sprintf("Error during customer update process : %s.", $message));
$customerUpdateForm->setErrorMessage($message);
$this->getParserContext()
->addForm($customerUpdateForm)
->setGeneralError($message)
;
}
return $this->render("customer-edit", array(
"customer_id" => $customer_id
));
} }
public function createAction() protected function getCreationEvent($formData)
{ {
if (null !== $response = $this->checkAuth(AdminResources::CUSTOMER, AccessManager::CREATE)) return $response; return $this->createEventInstance($formData);
$message = null;
$customerCreateForm = new CustomerCreateForm($this->getRequest());
try {
$form = $this->validateForm($customerCreateForm);
$data = $form->getData();
$data["password"] = Password::generateRandom();
$event = $this->createEventInstance($form->getData());
$this->dispatch(TheliaEvents::CUSTOMER_CREATEACCOUNT, $event);
$successUrl = $customerCreateForm->getSuccessUrl();
$successUrl = str_replace('_ID_', $event->getCustomer()->getId(), $successUrl);
$this->redirect($successUrl);
}catch (FormValidationException $e) {
$message = sprintf("Please check your input: %s", $e->getMessage());
} catch (PropelException $e) {
$message = $e->getMessage();
} catch (\Exception $e) {
$message = sprintf("Sorry, an error occured: %s", $e->getMessage()." ".$e->getFile());
}
if ($message !== false) {
\Thelia\Log\Tlog::getInstance()->error(sprintf("Error during customer creation process : %s.", $message));
$customerCreateForm->setErrorMessage($message);
$this->getParserContext()
->addForm($customerCreateForm)
->setGeneralError($message)
;
}
return $this->render("customers", array("display_customer" => 20));
} }
public function deleteAction() protected function getUpdateEvent($formData)
{ {
if (null !== $response = $this->checkAuth(AdminResources::CUSTOMER, AccessManager::DELETE)) return $response; $event = $this->createEventInstance($formData);
$message = null; $event->setCustomer($this->getExistingObject());
try { return $event;
$customer_id = $this->getRequest()->get("customer_id"); }
$customer = CustomerQuery::create()->findPk($customer_id);
if (null === $customer) { protected function getDeleteEvent()
throw new \InvalidArgumentException(Translator::getInstance("The customer you want to delete does not exist")); {
} return new CustomerEvent($this->getExistingObject());
}
$event = new CustomerEvent($customer); protected function eventContainsObject($event)
{
return $event->hasCustomer();
}
$this->dispatch(TheliaEvents::CUSTOMER_DELETEACCOUNT, $event); protected function hydrateObjectForm($object)
} catch (\Exception $e) { {
$message = $e->getMessage(); // Get default adress of the customer
} $address = $object->getDefaultAddress();
$params = array( // Prepare the data that will hydrate the form
"customer_page" => $this->getRequest()->get("customer_page", 1) $data = array(
'id' => $object->getId(),
'firstname' => $object->getFirstname(),
'lastname' => $object->getLastname(),
'email' => $object->getEmail(),
'title' => $object->getTitleId(),
'company' => $address->getCompany(),
'address1' => $address->getAddress1(),
'address2' => $address->getAddress2(),
'address3' => $address->getAddress3(),
'phone' => $address->getPhone(),
'cellphone' => $address->getCellphone(),
'zipcode' => $address->getZipcode(),
'city' => $address->getCity(),
'country' => $address->getCountryId(),
); );
if ($message) { // A loop is used in the template
$params["delete_error_message"] = $message; return new CustomerUpdateForm($this->getRequest(), 'form', $data);
} }
$this->redirectToRoute("admin.customers", $params);
protected function getObjectFromEvent($event)
{
return $event->hasCustomer() ? $event->getCustomer() : null;
} }
/** /**
@@ -209,26 +134,75 @@ class CustomerController extends BaseAdminController
private function createEventInstance($data) private function createEventInstance($data)
{ {
$customerCreateEvent = new CustomerCreateOrUpdateEvent( $customerCreateEvent = new CustomerCreateOrUpdateEvent(
$data["title"], $data["title"],
$data["firstname"], $data["firstname"],
$data["lastname"], $data["lastname"],
$data["address1"], $data["address1"],
$data["address2"], $data["address2"],
$data["address3"], $data["address3"],
$data["phone"], $data["phone"],
$data["cellphone"], $data["cellphone"],
$data["zipcode"], $data["zipcode"],
$data["city"], $data["city"],
$data["country"], $data["country"],
isset($data["email"])?$data["email"]:null, isset($data["email"])?$data["email"]:null,
isset($data["password"]) ? $data["password"]:null, isset($data["password"]) && ! empty($data["password"]) ? $data["password"]:null,
$this->getRequest()->getSession()->getLang()->getId(), $this->getRequest()->getSession()->getLang()->getId(),
isset($data["reseller"])?$data["reseller"]:null, isset($data["reseller"])?$data["reseller"]:null,
isset($data["sponsor"])?$data["sponsor"]:null, isset($data["sponsor"])?$data["sponsor"]:null,
isset($data["discount"])?$data["discount"]:null, isset($data["discount"])?$data["discount"]:null,
isset($data["company"])?$data["company"]:null isset($data["company"])?$data["company"]:null
); );
return $customerCreateEvent; return $customerCreateEvent;
} }
}
protected function getExistingObject()
{
return CustomerQuery::create()->findPk($this->getRequest()->get('customer_id', 0));
}
protected function getObjectLabel($object)
{
return $object->getRef() . "(".$object->getLastname()." ".$object->getFirstname().")";
}
protected function getObjectId($object)
{
return $object->getId();
}
protected function getEditionArguments()
{
return array(
'customer_id' => $this->getRequest()->get('customer_id', 0),
'page' => $this->getRequest()->get('page', 1)
);
}
protected function renderListTemplate($currentOrder)
{
return $this->render('customers', array(
'customer_order' => $currentOrder,
'display_customer' => 20,
'page' => $this->getRequest()->get('page', 1)
));
}
protected function redirectToListTemplate()
{
$this->redirectToRoute('admin.customers', array(
'page' => $this->getRequest()->get('page', 1))
);
}
protected function renderEditionTemplate()
{
return $this->render('customer-edit', $this->getEditionArguments());
}
protected function redirectToEditionTemplate()
{
$this->redirectToRoute("admin.customer.update.view", $this->getEditionArguments());
}
}

View File

@@ -1,19 +0,0 @@
<?php
namespace Thelia\Controller;
use Symfony\Component\HttpFoundation\Request;
/**
*
* @author Manuel Raynaud <mraynaud@openstudio.fr>
*/
interface NullControllerInterface
{
/**
* Nothing to do
*/
public function noAction(Request $request);
}

View File

@@ -31,7 +31,7 @@ use Thelia\Model\Customer;
* @package Thelia\Core\Event * @package Thelia\Core\Event
* @author Manuel Raynaud <mraynaud@openstudio.fr> * @author Manuel Raynaud <mraynaud@openstudio.fr>
*/ */
class CustomerCreateOrUpdateEvent extends ActionEvent class CustomerCreateOrUpdateEvent extends CustomerEvent
{ {
//base parameters for creating new customer //base parameters for creating new customer
protected $title; protected $title;
@@ -53,11 +53,6 @@ class CustomerCreateOrUpdateEvent extends ActionEvent
protected $discount; protected $discount;
protected $company; protected $company;
/**
* @var \Thelia\Model\Customer
*/
protected $customer;
/** /**
* @param int $title the title customer id * @param int $title the title customer id
* @param string $firstname * @param string $firstname
@@ -242,21 +237,4 @@ class CustomerCreateOrUpdateEvent extends ActionEvent
{ {
return $this->sponsor; return $this->sponsor;
} }
/**
* @param Customer $customer
*/
public function setCustomer(Customer $customer)
{
$this->customer = $customer;
}
/**
* @return Customer
*/
public function getCustomer()
{
return $this->customer;
}
} }

View File

@@ -28,13 +28,23 @@ use Thelia\Core\Event\ActionEvent;
class CustomerEvent extends ActionEvent class CustomerEvent extends ActionEvent
{ {
public $customer; public $customer = null;
public function __construct(Customer $customer) public function __construct(Customer $customer = null)
{ {
$this->customer = $customer; $this->customer = $customer;
} }
/**
* @param Customer $customer
*/
public function setCustomer(Customer $customer)
{
$this->customer = $customer;
return $this;
}
/** /**
* @return \Thelia\Model\Customer * @return \Thelia\Model\Customer
*/ */
@@ -43,4 +53,12 @@ class CustomerEvent extends ActionEvent
return $this->customer; return $this->customer;
} }
/**
* @return bool
*/
public function hasCustomer()
{
return $this->customer != null;
}
} }

View File

@@ -26,17 +26,7 @@ namespace Thelia\Core\Event\Customer;
use Thelia\Core\Event\ActionEvent; use Thelia\Core\Event\ActionEvent;
use Thelia\Model\Customer; use Thelia\Model\Customer;
class CustomerLoginEvent extends ActionEvent class CustomerLoginEvent extends CustomerEvent
{ {
protected $customer; // Nothing specific :)
public function __construct(Customer $customer)
{
$this->customer = $customer;
}
public function getCustomer()
{
return $this->customer;
}
} }

View File

@@ -22,7 +22,6 @@
/*************************************************************************************/ /*************************************************************************************/
namespace Thelia\Core\Template\Assets; namespace Thelia\Core\Template\Assets;
use Assetic\AssetManager; use Assetic\AssetManager;
use Assetic\FilterManager; use Assetic\FilterManager;
use Assetic\Filter; use Assetic\Filter;
@@ -59,7 +58,7 @@ class AsseticHelper
$am = new AssetManager(); $am = new AssetManager();
$fm = new FilterManager(); $fm = new FilterManager();
if (! empty($filters)) { if (!empty($filters)) {
$filter_list = explode(',', $filters); $filter_list = explode(',', $filters);
foreach ($filter_list as $filter_name) { foreach ($filter_list as $filter_name) {
@@ -67,36 +66,37 @@ class AsseticHelper
$filter_name = trim($filter_name); $filter_name = trim($filter_name);
switch ($filter_name) { switch ($filter_name) {
case 'less' : case 'less':
$fm->set('less', new Filter\LessphpFilter()); $fm->set('less', new Filter\LessphpFilter());
break; break;
case 'sass' : case 'sass':
$fm->set('sass', new Filter\Sass\SassFilter()); $fm->set('sass', new Filter\Sass\SassFilter());
break; break;
case 'cssembed' : case 'cssembed':
$fm->set('cssembed', new Filter\PhpCssEmbedFilter()); $fm->set('cssembed', new Filter\PhpCssEmbedFilter());
break; break;
case 'cssrewrite': case 'cssrewrite':
$fm->set('cssrewrite', new Filter\CssRewriteFilter()); $fm->set('cssrewrite', new Filter\CssRewriteFilter());
break; break;
case 'cssimport': case 'cssimport':
$fm->set('cssimport', new Filter\CssImportFilter()); $fm->set('cssimport', new Filter\CssImportFilter());
break; break;
case 'compass': case 'compass':
$fm->set('compass', new Filter\CompassFilter()); $fm->set('compass', new Filter\CompassFilter());
break; break;
default : default:
throw new \InvalidArgumentException("Unsupported Assetic filter: '$filter_name'"); throw new \InvalidArgumentException("Unsupported Assetic filter: '$filter_name'");
break; break;
} }
} }
} else { }
else {
$filter_list = array(); $filter_list = array();
} }
@@ -106,7 +106,7 @@ class AsseticHelper
$factory->setAssetManager($am); $factory->setAssetManager($am);
$factory->setFilterManager($fm); $factory->setFilterManager($fm);
$factory->setDefaultOutput('*'.(! empty($asset_type) ? '.' : '').$asset_type); $factory->setDefaultOutput('*' . (!empty($asset_type) ? '.' : '') . $asset_type);
$factory->setDebug($debug); $factory->setDebug($debug);
@@ -129,7 +129,7 @@ class AsseticHelper
// //
// before generating 3bc974a-ad3ef47.css, delete 3bc974a-* files. // before generating 3bc974a-ad3ef47.css, delete 3bc974a-* files.
// //
if ($dev_mode == true || ! file_exists($target_file)) { if ($dev_mode == true || !file_exists($target_file)) {
if (ConfigQuery::read('process_assets', true)) { if (ConfigQuery::read('process_assets', true)) {
@@ -144,7 +144,8 @@ class AsseticHelper
foreach ($filter_list as $filter) { foreach ($filter_list as $filter) {
if ('?' != $filter[0]) { if ('?' != $filter[0]) {
$asset->ensureFilter($fm->get($filter)); $asset->ensureFilter($fm->get($filter));
} elseif (!$debug) { }
elseif (!$debug) {
$asset->ensureFilter($fm->get(substr($filter, 1))); $asset->ensureFilter($fm->get(substr($filter, 1)));
} }
} }
@@ -155,6 +156,67 @@ class AsseticHelper
} }
} }
return rtrim($output_url, '/').'/'.$asset_target_path; return rtrim($output_url, '/') . '/' . $asset_target_path;
} }
}
// Create a hash of the current assets directory
public function getStamp($directory)
{
$stamp = '';
foreach (new \DirectoryIterator($directory) as $fileInfo) {
if ($fileInfo->isDot()) continue;
if ($fileInfo->isDir()) {
$stamp .= $this->getStamp($fileInfo->getPathName());
}
if ($fileInfo->isFile()) {
$stamp .= $fileInfo->getMTime();
}
}
return $stamp;
}
public function copyAssets($from_directory, $to_directory)
{
echo "copy $from_directory to $to_directory\n";
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($from_directory, \RecursiveDirectoryIterator::SKIP_DOTS),
\RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $item) {
if ($item->isDir()) {
$dest_dir = $to_directory . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
if (!is_dir($dest_dir)) {
if (file_exists($dest_dir)) {
@unlink($dest_dir);
}
if (!mkdir($dest_dir, 0777, true)) {
throw new \RuntimeException(
"Failed to create directory $dest_dir. Please check that your web server has the proper access rights");
}
}
}
else {
$dest_file = $to_directory . DIRECTORY_SEPARATOR . $iterator->getSubPathName();
if (file_exists($dest_file)) {
@unlink($dest_file);
}
if (!copy($item, $dest_file)) {
throw new \RuntimeException(
"Failed to copy $source_file to $dest_file. Please check that your web server has the proper access rights");
}
}
}
}
}

View File

@@ -36,6 +36,9 @@ use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Model\CustomerQuery; use Thelia\Model\CustomerQuery;
use Thelia\Type\TypeCollection; use Thelia\Type\TypeCollection;
use Thelia\Type; use Thelia\Type;
use Thelia\Model\OrderQuery;
use Thelia\Model\Map\OrderAddressTableMap;
use Thelia\Model\Map\OrderTableMap;
/** /**
* *
@@ -65,7 +68,22 @@ class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoop
) )
), ),
Argument::createBooleanTypeArgument('reseller'), Argument::createBooleanTypeArgument('reseller'),
Argument::createIntTypeArgument('sponsor') Argument::createIntTypeArgument('sponsor'),
new Argument(
'order',
new TypeCollection(
new Type\EnumListType(array(
'id', 'id_reverse',
'reference', 'reference_reverse',
'firstname', 'firstname_reverse',
'lastname', 'lastname_reverse',
'last_order', 'last_order_reverse',
'order_amount', 'order_amount_reverse',
'registration_date', 'registration_date_reverse'
))
),
'lastname'
)
); );
} }
@@ -151,6 +169,49 @@ class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoop
$search->filterBySponsor($sponsor, Criteria::EQUAL); $search->filterBySponsor($sponsor, Criteria::EQUAL);
} }
$orders = $this->getOrder();
foreach ($orders as $order) {
switch ($order) {
case 'id':
$search->orderById(Criteria::ASC);
break;
case 'id_reverse':
$search->orderById(Criteria::DESC);
break;
case 'reference':
$search->orderByRef(Criteria::ASC);
break;
case 'reference_reverse':
$search->orderByRef(Criteria::DESC);
break;
case 'lastname':
$search->orderByLastname(Criteria::ASC);
break;
case 'lastname_reverse':
$search->orderByLastname(Criteria::DESC);
break;
case 'firstname':
$search->orderByFirstname(Criteria::ASC);
break;
case 'firstname_reverse':
$search->orderByFirstname(Criteria::DESC);
break;
case 'registration_date':
$search->orderByCreatedAt(Criteria::ASC);
break;
case 'registration_date_reverse':
$search->orderByCreatedAt(Criteria::DESC);
break;
}
}
return $search; return $search;
} }
@@ -158,16 +219,24 @@ class Customer extends BaseLoop implements SearchLoopInterface, PropelSearchLoop
public function parseResults(LoopResult $loopResult) public function parseResults(LoopResult $loopResult)
{ {
foreach ($loopResult->getResultDataCollection() as $customer) { foreach ($loopResult->getResultDataCollection() as $customer) {
$loopResultRow = new LoopResultRow($customer); $loopResultRow = new LoopResultRow($customer);
$loopResultRow->set("ID", $customer->getId());
$loopResultRow->set("REF", $customer->getRef()); $loopResultRow
$loopResultRow->set("TITLE", $customer->getTitleId()); ->set("ID" , $customer->getId())
$loopResultRow->set("FIRSTNAME", $customer->getFirstname()); ->set("REF" , $customer->getRef())
$loopResultRow->set("LASTNAME", $customer->getLastname()); ->set("TITLE" , $customer->getTitleId())
$loopResultRow->set("EMAIL", $customer->getEmail()); ->set("FIRSTNAME" , $customer->getFirstname())
$loopResultRow->set("RESELLER", $customer->getReseller()); ->set("LASTNAME" , $customer->getLastname())
$loopResultRow->set("SPONSOR", $customer->getSponsor()); ->set("EMAIL" , $customer->getEmail())
$loopResultRow->set("DISCOUNT", $customer->getDiscount()); ->set("RESELLER" , $customer->getReseller())
->set("SPONSOR" , $customer->getSponsor())
->set("DISCOUNT" , $customer->getDiscount())
->set("LAST_ORDER_DATE" , $lastOrder != null ? $lastOrder->getCreatedAt() : '')
->set("LAST_ORDER_AMOUNT" , $lastOrder != null ? $lastOrder->getCreatedAt() : '')
->set("LAST_ORDER_CURRENCY" , $lastOrder != null ? $lastOrder->getCreatedAt() : '')
;
$loopResult->addRow($loopResultRow); $loopResult->addRow($loopResultRow);
} }

View File

@@ -82,6 +82,21 @@ class CustomerUpdateForm extends BaseForm
"for" => "lastname" "for" => "lastname"
) )
)) ))
->add("email", "email", array(
"constraints" => array(
new Constraints\NotBlank()
),
"label" => Translator::getInstance()->trans("Email address"),
"label_attr" => array(
"for" => "email"
)
))
->add("password", "text", array(
"label" => Translator::getInstance()->trans("Password"),
"label_attr" => array(
"for" => "email"
)
))
->add("address1", "text", array( ->add("address1", "text", array(
"constraints" => array( "constraints" => array(
new Constraints\NotBlank() new Constraints\NotBlank()
@@ -89,7 +104,7 @@ class CustomerUpdateForm extends BaseForm
"label_attr" => array( "label_attr" => array(
"for" => "address" "for" => "address"
), ),
"label" => Translator::getInstance()->trans("Street Address") "label" => Translator::getInstance()->trans("Street Address ")
)) ))
->add("address2", "text", array( ->add("address2", "text", array(
"label" => Translator::getInstance()->trans("Address Line 2"), "label" => Translator::getInstance()->trans("Address Line 2"),

View File

@@ -22,7 +22,7 @@
{block name="before-bootstrap-css"}{/block} {block name="before-bootstrap-css"}{/block}
{stylesheets file='assets/less/*' filters='less,cssembed'} {stylesheets file='assets/less/main.less' filters='less,cssembed'}
<link rel="stylesheet" href="{$asset_url}"> <link rel="stylesheet" href="{$asset_url}">
{/stylesheets} {/stylesheets}

View File

@@ -1,111 +0,0 @@
{* Update an Address *}
{form name="thelia.admin.address.update"}
{* Capture the dialog body, to pass it to the generic dialog *}
{capture "edit_address_dialog"}
{form_hidden_fields form=$form}
{form_field form=$form field='label'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label} }" placeholder="{intl l='Label'}">
</div>
{/form_field}
{form_field form=$form field='company'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Company'}">
</div>
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="title" name="title1"}
<option value="{$ID}" {if $value == $ID}selected{/if}>{$LONG}</option>
{/loop}
</select>
</div>
{/form_field}
{form_field form=$form field='firstname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Firstname'}">
</div>
{/form_field}
{form_field form=$form field='lastname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Lastname'}">
</div>
{/form_field}
{form_field form=$form field='address1'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Address'}">
</div>
<div class="form-group">
{form_field form=$form field='address2'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
<div class="form-group">
{form_field form=$form field='address3'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
{/form_field}
{form_field form=$form field='zipcode'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='Zip code'}">
</div>
{/form_field}
{form_field form=$form field='city'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{intl l={$label}}" placeholder="{intl l='City'}">
</div>
{/form_field}
{form_field form=$form field='country'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{intl l={$label}} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="country" name="country1"}
<option value="{$ID}" {if $value == $ID}selected{/if}>{$TITLE}</option>
{/loop}
</select>
</div>
{/form_field}
{/capture}
{include
file = "includes/generic-create-dialog.html"
dialog_id = "edit_address_dialog"
dialog_title = {intl l="Edit an address"}
dialog_body = {$smarty.capture.edit_address_dialog nofilter}
dialog_ok_label = {intl l="Edit this address"}
dialog_cancel_label = {intl l="Cancel"}
form_action = {url path="/admin/address/save/{$address_id}"}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
}
{/form}

View File

@@ -30,18 +30,21 @@
<div class="col-md-12"> <div class="col-md-12">
{form name="thelia.admin.customer.update"} {form name="thelia.admin.customer.update"}
<form method="POST" action="{url path="/admin/customer/update/{$ID}"}" {form_enctype form=$form} class="clearfix"> <form method="POST" action="{url path='/admin/customer/save'}" {form_enctype form=$form} class="clearfix">
<div class="row inner-toolbar clearfix"> {include
<div class="col-md-6 inner-actions pull-right"> file="includes/inner-form-toolbar.html"
<button type="submit" name="save_mode" value="stay" class="btn btn-default btn-primary" title="{intl l='Save'}">{intl l='Save'} <span class="glyphicon glyphicon-ok"></span></button> hide_flags = true
<button type="submit" name="save_mode" value="close" class="btn btn-default btn-info" title="{intl l='Save and close'}">{intl l='Save and close'} <span class="glyphicon glyphicon-remove"></span></button> close_url = {url path='/admin/customers'}
</div> }
</div>
{form_hidden_fields form=$form} {form_hidden_fields form=$form}
<input type="hidden" name="page" value="{$page}" />
<input type="hidden" name="customer_id" value="{$customer_id}" />
{form_field form=$form field='success_url'} {form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path="/admin/customer/update/{$ID}"}" /> <input type="hidden" name="{$name}" value="{url path='/admin/customers' page=$page}" />
{/form_field} {/form_field}
{if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if} {if $form_error}<div class="alert alert-danger">{$form_error_message}</div>{/if}
@@ -51,7 +54,7 @@
{form_field form=$form field='title'} {form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control"> <select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="title" name="title1" backend_context="1"} {loop type="title" name="title1" backend_context="1"}
@@ -63,15 +66,29 @@
{form_field form=$form field='firstname'} {form_field form=$form field='firstname'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$FIRSTNAME}" title="{$label}" placeholder="{intl l='Firstname'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Firstname'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='lastname'} {form_field form=$form field='lastname'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$LASTNAME}" title="{$label}" placeholder="{intl l='Lastname'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Lastname'}">
</div>
{/form_field}
{form_field form=$form field='email'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Lastname'}">
</div>
{/form_field}
{form_field form=$form field='password'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} (leave blank to keep current customer password) {if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Password'}">
</div> </div>
{/form_field} {/form_field}
@@ -81,50 +98,50 @@
{form_field form=$form field='company'} {form_field form=$form field='company'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$COMPANY}" title="{$label}" placeholder="{intl l='Company'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Company'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='address1'} {form_field form=$form field='address1'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$ADDRESS1}" title="{$label}" placeholder="{intl l='Address'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Address'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='address2'} {form_field form=$form field='address2'}
<div class="form-group"> <div class="form-group">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$ADDRESS2}" title="{$label}" placeholder="{intl l='Additional address'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='address3'} {form_field form=$form field='address3'}
<div class="form-group"> <div class="form-group">
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$ADDRESS3}" title="{$label}" placeholder="{intl l='Additional address'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='zipcode'} {form_field form=$form field='zipcode'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$ZIPCODE}" title="{$label}" placeholder="{intl l='Zip code'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Zip code'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='city'} {form_field form=$form field='city'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$CITY}" title="{$label}" placeholder="{intl l='City'}"> <input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='City'}">
</div> </div>
{/form_field} {/form_field}
{form_field form=$form field='country'} {form_field form=$form field='country'}
<div class="form-group {if $error}has-error{/if}"> <div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label> <label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control"> <select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="country" name="country1"} {loop type="country" name="country1"}
<option value="{$ID}" {if $ID == $COUNTRY}selected{/if}>{$TITLE}</option> <option value="{$ID}" {if {$value} == $ID}selected{/if}>{$TITLE}</option>
{/loop} {/loop}
</select> </select>
</div> </div>
@@ -149,13 +166,14 @@
<thead> <thead>
<tr> <tr>
<th>{intl l="Address"}</th> <th>{intl l="Address"}</th>
<th>{intl l="Actions"}</th> <th class="text-center">{intl l="Actions"}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{loop name="address" type="address" customer="$customer_id" backend_context="1" default="0"} {loop name="address" type="address" customer="$customer_id" backend_context="1" default="0"}
<tr> <tr>
<td> <td>
{$LABEL}
<address> <address>
<strong>{loop name="address.title" type="title" id=$TITLE}{$SHORT}{/loop} {$FIRSTNAME} {$LASTNAME}</strong><br> <strong>{loop name="address.title" type="title" id=$TITLE}{$SHORT}{/loop} {$FIRSTNAME} {$LASTNAME}</strong><br>
{$ADDRESS1} {$ADDRESS1}
@@ -166,21 +184,21 @@
<br>{$TITLE} <br>{$TITLE}
{/loop} {/loop}
{if $PHONE} {if $PHONE}
<br> <abbr title="{intl l="Phone"}">P:</abbr>{$PHONE} <br>{intl l="Phone"}: {$PHONE}
{/if} {/if}
{if $CELLPHONE} {if $CELLPHONE}
<br> <abbr title="{intl l="cell phone"}">P:</abbr>{$CELLPHONE} <br>{intl l="Cellular phone"}: {$CELLPHONE}
{/if} {/if}
</address> </address>
</td> </td>
<td> <td class="text-center">
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-default btn-xs customer-update-address" title="{intl l='Edit this address'}" href="#" data-id="{$ID}"> <a class="btn btn-default btn-xs customer-update-address" title="{intl l='Edit this address'}" href="{url path='/admin/address/update' address_id=$ID}">
<span class="glyphicon glyphicon-edit"></span> <span class="glyphicon glyphicon-edit"></span>
</a> </a>
<a class="btn btn-default btn-xs customer-address-use" title="{intl l='Use this address by default'}" href="#use_address_dialog" data-id="{$ID}" data-toggle="modal" rel="tooltip"> <a class="btn btn-default btn-xs customer-address-use" title="{intl l='Use this address by default'}" href="#use_address_dialog" data-toggle="modal" data-id="{$ID}" data-toggle="modal" rel="tooltip">
<span class="glyphicon glyphicon-pushpin"></span> <span class="glyphicon glyphicon-pushpin"></span>
</a> </a>
@@ -262,168 +280,117 @@
</div> </div>
</div> </div>
<div id="address-update-modal"></div> {* -- Add an Address -------------------------------------------------------- *}
{* Add an Address *}
{form name="thelia.admin.address.create"} {form name="thelia.admin.address.create"}
{* Capture the dialog body, to pass it to the generic dialog *} {* Capture the dialog body, to pass it to the generic dialog *}
{capture "address_creation_dialog"} {capture "address_creation_dialog"}
{form_hidden_fields form=$form} {include file='includes/customer_address_form_fields.html' customer_id=$customer_id page=$page}
<input type="hidden" name="customer_id" value="{$customer_id}">
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path="/admin/customer/update/{$customer_id}"}" />
{/form_field}
{form_field form=$form field='label'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Label'}">
</div>
{/form_field}
{form_field form=$form field='company'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Company'}">
</div>
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control" required>
{loop type="title" name="title1"}
<option value="{$ID}">{$LONG}</option>
{/loop}
</select>
</div>
{/form_field}
{form_field form=$form field='firstname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Firstname'}" required>
</div>
{/form_field}
{form_field form=$form field='lastname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Lastname'}" required>
</div>
{/form_field}
{form_field form=$form field='address1'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Address'}" required>
</div>
<div class="form-group">
{form_field form=$form field='address2'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
<div class="form-group">
{form_field form=$form field='address3'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
{/form_field}
{form_field form=$form field='zipcode'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Zip code'}" required>
</div>
{/form_field}
{form_field form=$form field='city'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='City'}" required>
</div>
{/form_field}
{form_field form=$form field='country'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control" required>
{loop type="country" name="country1"}
<option value="{$ID}">{$TITLE}</option>
{/loop}
</select>
</div>
{/form_field}
{/capture}
{include
file = "includes/generic-create-dialog.html"
dialog_id = "address_creation_dialog"
dialog_title = {intl l="Create an address"}
dialog_body = {$smarty.capture.address_creation_dialog nofilter}
dialog_ok_label = {intl l="Create this address"}
dialog_cancel_label = {intl l="Cancel"}
form_action = {url path='/admin/address/create'}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
}
{/form}
{* Default confirmation dialog *}
{capture "use_address_dialog"}
<input type="hidden" name="address_id" id="address_use_id" value="" />
{/capture} {/capture}
{include {include
file = "includes/generic-confirm-dialog.html" file = "includes/generic-create-dialog.html"
dialog_id = "use_address_dialog" dialog_id = "address_creation_dialog"
dialog_title = {intl l="Use address by default"} dialog_title = {intl l="Create a customer address"}
dialog_message = {intl l="Do you really want to use this address by default ?"} dialog_body = {$smarty.capture.address_creation_dialog nofilter}
form_action = {url path='/admin/address/use'} dialog_ok_label = {intl l="Create this address"}
form_content = {$smarty.capture.use_address_dialog nofilter} dialog_cancel_label = {intl l="Cancel"}
form_action = {url path='/admin/address/create'}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
} }
{* Delete confirmation dialog *} {/form}
{capture "delete_address_dialog"} {* -- Update an Address ----------------------------------------------------- *}
<input type="hidden" name="address_id" id="address_delete_id" value="" />
{/capture}
{include {if $address_id > 0}
file = "includes/generic-confirm-dialog.html" {form name="thelia.admin.address.update"}
dialog_id = "delete_address_dialog" {* Capture the dialog body, to pass it to the generic dialog *}
dialog_title = {intl l="Delete address"}
dialog_message = {intl l="Do you really want to delete this address ?"}
form_action = {url path='/admin/address/delete'} {capture "address_update_dialog"}
form_content = {$smarty.capture.delete_address_dialog nofilter} <input type="hidden" name="address_id" id="address_update_id" value="{$address_id}" />
}
{include file='includes/customer_address_form_fields.html' customer_id=$customer_id page=$page}
{/capture}
{include
file = "includes/generic-create-dialog.html"
dialog_id = "address_update_dialog"
dialog_title = {intl l="Edit a customer address"}
dialog_body = {$smarty.capture.address_update_dialog nofilter}
dialog_ok_label = {intl l="Save this address"}
dialog_cancel_label = {intl l="Cancel"}
form_action = {url path="/admin/address/save"}
form_enctype = {form_enctype form=$form}
form_error_message = $form_error_message
}
{/form}
{/if}
{* -- Confirm making an address the default --------------------------------- *}
{capture "use_address_dialog"}
<input type="hidden" name="address_id" id="address_use_id" value="" />
<input type="hidden" name="customer_id" value="{$customer_id}">
<input type="hidden" name="page" value="{$page}">
{/capture}
{include
file = "includes/generic-confirm-dialog.html"
dialog_id = "use_address_dialog"
dialog_title = {intl l="Use address by default"}
dialog_message = {intl l="Do you really want to use this address by default ?"}
form_action = {url path='/admin/address/use'}
form_content = {$smarty.capture.use_address_dialog nofilter}
}
{* -- Delete confirmation dialog -------------------------------------------- *}
{capture "delete_address_dialog"}
<input type="hidden" name="address_id" id="address_delete_id" value="" />
<input type="hidden" name="customer_id" value="{$customer_id}">
<input type="hidden" name="page" value="{$page}">
{/capture}
{include
file = "includes/generic-confirm-dialog.html"
dialog_id = "delete_address_dialog"
dialog_title = {intl l="Delete address"}
dialog_message = {intl l="Do you really want to delete this address ?"}
form_action = {url path='/admin/address/delete'}
form_content = {$smarty.capture.delete_address_dialog nofilter}
}
{/block} {/block}
{block name="javascript-initialization"} {block name="javascript-initialization"}
{javascripts file='assets/js/main.js'} {javascripts file='assets/js/main.js'}
<script src="{$asset_url}"></script> <script src="{$asset_url}"></script>
{/javascripts} {/javascripts}
<script> <script>
(function($) { $(function() {
$(document).ready(function(){
$("a.customer-address-delete").click(function(e){ $("a.customer-address-delete").click(function(e){
$("#address_delete_id").val($(this).data("id")); $("#address_delete_id").val($(this).data("id"));
}); });
@@ -432,23 +399,29 @@
$("#address_use_id").val($(this).data("id")); $("#address_use_id").val($(this).data("id"));
}); });
$("a.customer-update-address").click(function(e){ // JS stuff for creation form
var baseUrl = "{url path="/admin/address/update/"}"; {include
$('body').append('<div class="modal-backdrop fade in" id="loading-event"><div class="loading"></div></div>'); file = "includes/generic-js-dialog.html"
$.ajax({ dialog_id = "address_creation_dialog"
method: 'get', form_name = "thelia.admin.address.create"
url: baseUrl+$(this).data('id') }
}).done(function(data){
$("#loading-event").remove();
$("#address-update-modal").html(data);
$("#edit_address_dialog").modal("show");
});
});
$(document).on("hidden.bs.modal", "#edit_address_dialog", function(ev){ $(document).on("hidden.bs.modal", "#edit_address_dialog", function(ev){
$("#edit_address_dialog").remove(); $("#edit_address_dialog").remove();
}); });
// If $address_id is defined, show the edit dialog
{if $address_id > 0}
// JS stuff for update form
{include
file = "includes/generic-js-dialog.html"
dialog_id = "address_update_dialog"
form_name = "thelia.admin.address.update"
}
$('#address_update_dialog').modal();
{/if}
}); });
})(jQuery);
</script> </script>
{/block} {/block}

View File

@@ -7,9 +7,6 @@
{block name="check-access"}view{/block} {block name="check-access"}view{/block}
{block name="main-content"} {block name="main-content"}
{assign var=customer_page value={$smarty.get.page|default:1}}
<div class="customer"> <div class="customer">
<div id="wrapper" class="container"> <div id="wrapper" class="container">
@@ -41,27 +38,83 @@
<thead> <thead>
<tr> <tr>
<th class="object-title"> <th class="object-title">
{intl l="customer ref"} {admin_sortable_header
current_order=$customer_order
order='reference'
reverse_order='reference_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='Reference'}"
}
</th> </th>
{module_include location='category_list_header'} {module_include location='customer_list_header'}
<th> <th class="object-title">
{intl l="firstname & lastname"} {admin_sortable_header
current_order=$customer_order
order='lastname'
reverse_order='lastname_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='Last name'}"
}
</th> </th>
<th> <th class="object-title">
{intl l="last order"} {admin_sortable_header
current_order=$customer_order
order='firstname'
reverse_order='firstname_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='First name'}"
}
</th> </th>
<th>{intl l='order amount'}</th> <th class="object-title">
{admin_sortable_header
current_order=$customer_order
order='registration_date'
reverse_order='registration_date_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='Registration date'}"
}
</th>
<th class="object-title">{intl l='Date of last order'}</th>
<th class="object-title">{intl l='Last order amount'}</th>
{* TODO
<th class="object-title">
{admin_sortable_header
current_order=$customer_order
order='last_order'
reverse_order='last_order_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='Date of last order'}"
}
</th>
<th class="object-title">
{admin_sortable_header
current_order=$customer_order
order='order_amount'
reverse_order='order_amount_reverse'
path={url path='/admin/customers'}
request_parameter_name='customer_order'
label="{intl l='Last order amount'}"
}
</th>
*}
<th class="actions">{intl l='Actions'}</th> <th class="actions">{intl l='Actions'}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{loop name="customer_list" type="customer" current="false" visible="*" backend_context="1" page={$customer_page} limit={$display_customer}} {loop name="customer_list" type="customer" current="false" visible="*" order=$customer_order backend_context="1" page=$page limit=$display_customer}
{assign "lastOrderDate" ''} {assign "lastOrderDate" ''}
{assign "lastOrderAmount" ''} {assign "lastOrderAmount" ''}
{assign "lastOrderCurrency" ''} {assign "lastOrderCurrency" ''}
@@ -75,14 +128,23 @@
{/loop} {/loop}
<tr> <tr>
<td><a href="{url path="/admin/customer/update/{$ID}"}">{$REF}</a></td> <td><a href="{url path="/admin/customer/update" customer_id=$ID page=$page}">{$REF}</a></td>
<td class="object-title"> <td class="object-title">
{$FIRSTNAME} {$LASTNAME} {$LASTNAME}
</td> </td>
<td class="object-title">
{$FIRSTNAME}
</td>
{module_include location='customer_list_row'} {module_include location='customer_list_row'}
<td>
{format_date date=$CREATE_DATE}
</td>
<td> <td>
{$lastOrderDate} {$lastOrderDate}
</td> </td>
@@ -94,7 +156,7 @@
<div class="btn-group"> <div class="btn-group">
{loop type="auth" name="can_change" role="ADMIN" resource="admin.customer" access="UPDATE"} {loop type="auth" name="can_change" role="ADMIN" resource="admin.customer" access="UPDATE"}
<a class="btn btn-default btn-xs" title="{intl l='Edit this customer'}" href="{url path="/admin/customer/update/{$ID}" }"><i class="glyphicon glyphicon-edit"></i></a> <a class="btn btn-default btn-xs" title="{intl l='Edit this customer'}" href="{url path='/admin/customer/update' customer_id=$ID page=$page}"><i class="glyphicon glyphicon-edit"></i></a>
{/loop} {/loop}
{loop type="auth" name="can_send_mail" role="ADMIN" resource="admin.customer" access="VIEW"} {loop type="auth" name="can_send_mail" role="ADMIN" resource="admin.customer" access="VIEW"}
<a class="btn btn-default btn-xs" title="{intl l="Send a mail to this customer"}" href="mailto:{$EMAIL}"><span class="glyphicon glyphicon-envelope"></span></a> <a class="btn btn-default btn-xs" title="{intl l="Send a mail to this customer"}" href="mailto:{$EMAIL}"><span class="glyphicon glyphicon-envelope"></span></a>
@@ -111,10 +173,10 @@
<tfoot> <tfoot>
<tr> <tr>
<td colspan="6"> <td colspan="6">
<div class="text-center"> <div class="text-center">
<ul class="pagination pagination-centered"> <ul class="pagination pagination-centered">
{if $customer_page != 1} {if $page != 1}
<li><a href="{url path="/admin/customers" page="1"}">&laquo;</a></li> <li><a href="{url path="/admin/customers" page="1"}">&laquo;</a></li>
{else} {else}
<li class="disabled"><a href="#">&laquo;</a></li> <li class="disabled"><a href="#">&laquo;</a></li>
@@ -137,7 +199,7 @@
{/if} {/if}
</ul> </ul>
</div> </div>
</td> </td>
</tr> </tr>
</tfoot> </tfoot>
@@ -163,7 +225,7 @@
{form_field form=$form field='success_url'} {form_field form=$form field='success_url'}
{* on success, redirect to the edition page, _ID_ is replaced with the created object ID, see controller *} {* on success, redirect to the edition page, _ID_ is replaced with the created object ID, see controller *}
<input type="hidden" name="{$name}" value="{url path='/admin/customer/update/_ID_'}" /> <input type="hidden" name="{$name}" value="{url path='/admin/customer/update' customer_id='_ID_'}" />
{/form_field} {/form_field}
{form_field form=$form field="password"} {form_field form=$form field="password"}
@@ -283,7 +345,7 @@
{* Delete confirmation dialog *} {* Delete confirmation dialog *}
{capture "delete_customer_dialog"} {capture "delete_customer_dialog"}
<input type="hidden" name="customer_page" value="{$customer_page}"> <input type="hidden" name="page" value="{$page}">
<input type="hidden" name="customer_id" id="delete_customer_id"> <input type="hidden" name="customer_id" id="delete_customer_id">
{/capture} {/capture}

View File

@@ -0,0 +1,124 @@
{* Customer address creation / modification fields, used in the customer-edit.html template *}
{form_hidden_fields form=$form}
<input type="hidden" name="customer_id" value="{$customer_id}">
<input type="hidden" name="page" value="{$page}">
{form_field form=$form field='success_url'}
<input type="hidden" name="{$name}" value="{url path='/admin/customer/update'} customer_id=$customer_id page=$page" />
{/form_field}
{form_field form=$form field='label'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{$label}">
</div>
{/form_field}
{form_field form=$form field='company'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Company'}">
</div>
{/form_field}
{form_field form=$form field='title'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="title" name="title1"}
<option value="{$ID}" {if $value == $ID}selected{/if}>{$LONG}</option>
{/loop}
</select>
</div>
{/form_field}
<div class="row">
<div class="col-md-6">
{form_field form=$form field='firstname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Firstname'}">
</div>
{/form_field}
</div>
<div class="col-md-6">
{form_field form=$form field='lastname'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Lastname'}">
</div>
{/form_field}
</div>
</div>
{form_field form=$form field='address1'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Address'}">
</div>
<div class="form-group">
{form_field form=$form field='address2'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
<div class="form-group">
{form_field form=$form field='address3'}
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Additional address'}">
{/form_field}
</div>
{/form_field}
<div class="row">
<div class="col-md-3">
{form_field form=$form field='zipcode'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Zip code'}">
</div>
{/form_field}
</div>
<div class="col-md-9">
{form_field form=$form field='city'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='City'}">
</div>
{/form_field}
</div>
</div>
{form_field form=$form field='country'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<select name="{$name}" id="{$label_attr.for}" class="form-control">
{loop type="country" name="country1"}
<option value="{$ID}" {if $value == $ID}selected{/if}>{$TITLE}</option>
{/loop}
</select>
</div>
{/form_field}
<div class="row">
<div class="col-md-6">
{form_field form=$form field='phone'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Phone number'}">
</div>
{/form_field}
</div>
<div class="col-md-6">
{form_field form=$form field='cellphone'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for}" class="control-label">{$label}{if $required} <span class="required">*</span>{/if} : </label>
<input type="text" id="{$label_attr.for}" name="{$name}" class="form-control" value="{$value}" title="{$label}" placeholder="{intl l='Cellular phone number'}">
</div>
{/form_field}
</div>
</div>

View File

@@ -1,4 +1,3 @@
/* Bootstrap */ /* Bootstrap */
@import "bootstrap/bootstrap.less"; @import "bootstrap/bootstrap.less";