Inital commit
This commit is contained in:
35
local/modules/HookAdminHome/Config/config.xml
Normal file
35
local/modules/HookAdminHome/Config/config.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<hooks>
|
||||
<hook id="hookadminhome.hook.css">
|
||||
<tag name="hook.event_listener" event="main.head-css" type="back" templates="css:assets/css/home.css" />
|
||||
</hook>
|
||||
|
||||
<hook id="hookadminhome.hook.block_information">
|
||||
<tag name="hook.event_listener" event="home.top" type="back" templates="render:block-information.html" />
|
||||
</hook>
|
||||
|
||||
<hook id="hookadminhome.hook.block_statistics" class="HookAdminHome\Hook\AdminHook">
|
||||
<tag name="hook.event_listener" event="home.top" type="back" method="blockStatistics" />
|
||||
<tag name="hook.event_listener" event="home.js" type="back" method="blockStatisticsJs" />
|
||||
</hook>
|
||||
|
||||
<hook id="hookadminhome.hook.block_sales_statistics" class="HookAdminHome\Hook\AdminHook">
|
||||
<tag name="hook.event_listener" event="home.block" type="back" method="blockSalesStatistics" />
|
||||
</hook>
|
||||
|
||||
<hook id="hookadminhome.hook.block_news" class="HookAdminHome\Hook\AdminHook">
|
||||
<tag name="hook.event_listener" event="home.block" type="back" method="blockNews" />
|
||||
<tag name="hook.event_listener" event="home.js" type="back" templates="render:block-news-js.html" />
|
||||
</hook>
|
||||
|
||||
<hook id="hookadminhome.hook.block_thelia_informations" class="HookAdminHome\Hook\AdminHook">
|
||||
<tag name="hook.event_listener" event="home.block" type="back" method="blockTheliaInformation" />
|
||||
</hook>
|
||||
</hooks>
|
||||
|
||||
</config>
|
||||
32
local/modules/HookAdminHome/Config/module.xml
Normal file
32
local/modules/HookAdminHome/Config/module.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module xmlns="http://thelia.net/schema/dic/module"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/module http://thelia.net/schema/dic/module/module-2_2.xsd">
|
||||
<fullnamespace>HookAdminHome\HookAdminHome</fullnamespace>
|
||||
<descriptive locale="en_US">
|
||||
<title>Displays the default blocks on the homepage of the administration</title>
|
||||
</descriptive>
|
||||
<descriptive locale="fr_FR">
|
||||
<title>Affiche les blocs par défaut sur la page d'accueil de l'administration</title>
|
||||
</descriptive>
|
||||
<languages>
|
||||
<language>en_US</language>
|
||||
<language>fr_FR</language>
|
||||
</languages>
|
||||
<version>2.3.5</version>
|
||||
<authors>
|
||||
<author>
|
||||
<name>Gilles Bourgeat</name>
|
||||
<email>gilles@thelia.net</email>
|
||||
</author>
|
||||
<author>
|
||||
<name>Franck Allimant</name>
|
||||
<company>CQFDev</company>
|
||||
<email>franck@cqfdev.fr</email>
|
||||
<website>www.cqfdev.fr</website>
|
||||
</author>
|
||||
</authors>
|
||||
<type>classic</type>
|
||||
<thelia>2.2.0</thelia>
|
||||
<stability>prod</stability>
|
||||
</module>
|
||||
23
local/modules/HookAdminHome/Config/routing.xml
Normal file
23
local/modules/HookAdminHome/Config/routing.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="admin.home.stats" path="/admin/home/stats">
|
||||
<default key="_controller">HookAdminHome\Controller\HomeController::loadStatsAjaxAction</default>
|
||||
</route>
|
||||
|
||||
<route id="admin.home.month.sales.block" path="/admin/home/month-sales-block/{month}/{year}">
|
||||
<default key="_controller">HookAdminHome\Controller\HomeController::blockMonthSalesStatistics</default>
|
||||
<requirement key="month">\d+</requirement>
|
||||
<requirement key="year">\d+</requirement>
|
||||
</route>
|
||||
|
||||
<route id="admin.news-feed" path="/admin/ajax/thelia_news_feed">
|
||||
<default key="_controller">HookAdminHome\Controller\HomeController::processTemplateAction</default>
|
||||
<default key="template">ajax/thelia_news_feed</default>
|
||||
<default key="not-logged">1</default>
|
||||
</route>
|
||||
|
||||
</routes>
|
||||
154
local/modules/HookAdminHome/Controller/HomeController.php
Normal file
154
local/modules/HookAdminHome/Controller/HomeController.php
Normal file
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace HookAdminHome\Controller;
|
||||
|
||||
use HookAdminHome\HookAdminHome;
|
||||
use Symfony\Component\Cache\Adapter\AdapterInterface;
|
||||
use Thelia\Controller\Admin\BaseAdminController;
|
||||
use Thelia\Core\Security\AccessManager;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Currency;
|
||||
use Thelia\Model\CustomerQuery;
|
||||
use Thelia\Model\OrderQuery;
|
||||
|
||||
/**
|
||||
* Class HomeController
|
||||
* @package HookAdminHome\Controller
|
||||
* @author Gilles Bourgeat <gilles@thelia.net>
|
||||
*/
|
||||
class HomeController extends BaseAdminController
|
||||
{
|
||||
/**
|
||||
* Key prefix for stats cache
|
||||
*/
|
||||
const STATS_CACHE_KEY = "stats";
|
||||
|
||||
const RESOURCE_CODE = "admin.home";
|
||||
|
||||
public function loadStatsAjaxAction()
|
||||
{
|
||||
if (null !== $response = $this->checkAuth(self::RESOURCE_CODE, array(), AccessManager::VIEW)) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$cacheExpire = ConfigQuery::getAdminCacheHomeStatsTTL();
|
||||
|
||||
/** @var AdapterInterface $cacheAdapter */
|
||||
$cacheAdapter = $this->container->get('thelia.cache');
|
||||
|
||||
$month = (int) $this->getRequest()->query->get('month', date('m'));
|
||||
$year = (int) $this->getRequest()->query->get('year', date('Y'));
|
||||
|
||||
$cacheKey = self::STATS_CACHE_KEY . "_" . $month . "_" . $year;
|
||||
|
||||
$cacheItem = $cacheAdapter->getItem($cacheKey);
|
||||
|
||||
// force flush
|
||||
if ($this->getRequest()->query->get('flush', "0")) {
|
||||
$cacheAdapter->deleteItem($cacheItem);
|
||||
}
|
||||
|
||||
if (!$cacheItem->isHit()) {
|
||||
$data = $this->getStatus($month, $year);
|
||||
|
||||
$cacheItem->set(json_encode($data));
|
||||
$cacheItem->expiresAfter($cacheExpire);
|
||||
|
||||
if ($cacheExpire) {
|
||||
$cacheAdapter->save($cacheItem);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->jsonResponse($cacheItem->get());
|
||||
}
|
||||
|
||||
public function blockMonthSalesStatistics($month, $year)
|
||||
{
|
||||
$baseDate = sprintf("%04d-%02d", $year, $month);
|
||||
|
||||
$startDate = "$baseDate-01";
|
||||
$endDate = date("Y-m-t", strtotime($startDate));
|
||||
|
||||
$prevMonthStartDate = date('Y-m-01', strtotime("$baseDate -1 month"));
|
||||
$prevMonthEndDate = date("Y-m-t", strtotime($prevMonthStartDate));
|
||||
|
||||
return $this->render('block-month-sales-statistics', [
|
||||
'startDate' => $startDate,
|
||||
'endDate' => $endDate,
|
||||
'prevMonthStartDate' => $prevMonthStartDate,
|
||||
'prevMonthEndDate' => $prevMonthEndDate,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $month
|
||||
* @param int $year
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function getStatus($month, $year)
|
||||
{
|
||||
$data = new \stdClass();
|
||||
|
||||
$data->title = $this->getTranslator()->trans(
|
||||
"Stats on %month/%year",
|
||||
['%month' => $month, '%year' => $year],
|
||||
HookAdminHome::DOMAIN_NAME
|
||||
);
|
||||
|
||||
$data->series = [];
|
||||
|
||||
/* sales */
|
||||
$data->series[] = $saleSeries = new \stdClass();
|
||||
$saleSeries->color = self::testHexColor('sales_color', '#adadad');
|
||||
$saleSeries->data = OrderQuery::getMonthlySaleStats($month, $year);
|
||||
$saleSeries->valueFormat = "%1.2f " . Currency::getDefaultCurrency()->getSymbol();
|
||||
|
||||
/* new customers */
|
||||
$data->series[] = $newCustomerSeries = new \stdClass();
|
||||
$newCustomerSeries->color = self::testHexColor('customers_color', '#f39922');
|
||||
$newCustomerSeries->data = CustomerQuery::getMonthlyNewCustomersStats($month, $year);
|
||||
$newCustomerSeries->valueFormat = "%d";
|
||||
|
||||
/* orders */
|
||||
$data->series[] = $orderSeries = new \stdClass();
|
||||
$orderSeries->color = self::testHexColor('orders_color', '#5cb85c');
|
||||
$orderSeries->data = OrderQuery::getMonthlyOrdersStats($month, $year);
|
||||
$orderSeries->valueFormat = "%d";
|
||||
|
||||
/* first order */
|
||||
$data->series[] = $firstOrderSeries = new \stdClass();
|
||||
$firstOrderSeries->color = self::testHexColor('first_orders_color', '#5bc0de');
|
||||
$firstOrderSeries->data = OrderQuery::getFirstOrdersStats($month, $year);
|
||||
$firstOrderSeries->valueFormat = "%d";
|
||||
|
||||
/* cancelled orders */
|
||||
$data->series[] = $cancelledOrderSeries = new \stdClass();
|
||||
$cancelledOrderSeries->color = self::testHexColor('cancelled_orders_color', '#d9534f');
|
||||
$cancelledOrderSeries->data = OrderQuery::getMonthlyOrdersStats($month, $year, array(5));
|
||||
$cancelledOrderSeries->valueFormat = "%d";
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $default
|
||||
* @return string hexadecimal color or default argument
|
||||
*/
|
||||
protected function testHexColor($key, $default)
|
||||
{
|
||||
$hexColor = $this->getRequest()->query->get($key, $default);
|
||||
|
||||
return preg_match('/^#[a-f0-9]{6}$/i', $hexColor) ? $hexColor : $default;
|
||||
}
|
||||
}
|
||||
71
local/modules/HookAdminHome/Hook/AdminHook.php
Normal file
71
local/modules/HookAdminHome/Hook/AdminHook.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace HookAdminHome\Hook;
|
||||
|
||||
use HookAdminHome\HookAdminHome;
|
||||
use Thelia\Core\Event\Hook\HookRenderBlockEvent;
|
||||
use Thelia\Core\Event\Hook\HookRenderEvent;
|
||||
use Thelia\Core\Hook\BaseHook;
|
||||
|
||||
/**
|
||||
* Class AdminHook
|
||||
* @package HookAdminHome\Hook
|
||||
* @author Gilles Bourgeat <gilles@thelia.net>
|
||||
*/
|
||||
class AdminHook extends BaseHook
|
||||
{
|
||||
public function blockStatistics(HookRenderEvent $event)
|
||||
{
|
||||
$event->add($this->render('block-statistics.html'));
|
||||
}
|
||||
|
||||
public function blockStatisticsJs(HookRenderEvent $event)
|
||||
{
|
||||
$event->add($this->render('block-statistics-js.html'));
|
||||
}
|
||||
|
||||
public function blockSalesStatistics(HookRenderBlockEvent $event)
|
||||
{
|
||||
$content = trim($this->render("block-sales-statistics.html"));
|
||||
if (!empty($content)) {
|
||||
$event->add([
|
||||
"id" => "block-sales-statistics",
|
||||
"title" => $this->trans("Sales statistics", [], HookAdminHome::DOMAIN_NAME),
|
||||
"content" => $content
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function blockNews(HookRenderBlockEvent $event)
|
||||
{
|
||||
$content = trim($this->render("block-news.html"));
|
||||
if (!empty($content)) {
|
||||
$event->add([
|
||||
"id" => "block-news",
|
||||
"content" => $content
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function blockTheliaInformation(HookRenderBlockEvent $event)
|
||||
{
|
||||
$content = trim($this->render("block-thelia-information.html"));
|
||||
if (!empty($content)) {
|
||||
$event->add([
|
||||
"id" => "block-thelia-information",
|
||||
"title" => $this->trans("Thelia informations", [], HookAdminHome::DOMAIN_NAME),
|
||||
"content" => $content
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
21
local/modules/HookAdminHome/HookAdminHome.php
Normal file
21
local/modules/HookAdminHome/HookAdminHome.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/*************************************************************************************/
|
||||
/* This file is part of the Thelia package. */
|
||||
/* */
|
||||
/* Copyright (c) OpenStudio */
|
||||
/* email : dev@thelia.net */
|
||||
/* web : http://www.thelia.net */
|
||||
/* */
|
||||
/* For the full copyright and license information, please view the LICENSE.txt */
|
||||
/* file that was distributed with this source code. */
|
||||
/*************************************************************************************/
|
||||
|
||||
namespace HookAdminHome;
|
||||
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
class HookAdminHome extends BaseModule
|
||||
{
|
||||
/** @var string */
|
||||
const DOMAIN_NAME = 'hookadminhome';
|
||||
}
|
||||
5
local/modules/HookAdminHome/I18n/ar_SA.php
Normal file
5
local/modules/HookAdminHome/I18n/ar_SA.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Stats on %month/%year' => 'إحصائيات عن الشهر و السنة %month/%year',
|
||||
];
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'تم إحباط الطلبات',
|
||||
'Average cart' => 'متوسط العربة',
|
||||
'Categories' => 'الفئات',
|
||||
'Click here' => 'انقر هنا',
|
||||
'Current version' => 'النسخة الحالية',
|
||||
'Customers' => 'العملاء',
|
||||
'Dashboard' => 'لوحة المعلومات',
|
||||
];
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Aborted orders',
|
||||
'Average cart' => 'Average cart',
|
||||
'Categories' => 'Categories',
|
||||
'Click here' => 'Click here',
|
||||
'Current version' => 'Current version',
|
||||
'Customers' => 'Customers',
|
||||
'Dashboard' => 'Dashboard',
|
||||
'First orders' => 'First orders',
|
||||
'Latest version available' => 'Latest version available',
|
||||
'Lire la suite' => 'Lire la suite',
|
||||
'Loading Thelia lastest news...' => 'Loading Thelia lastest news...',
|
||||
'Loading...' => 'Loading...',
|
||||
'New customers' => 'New customers',
|
||||
'News' => 'News',
|
||||
'Offline products' => 'Offline products',
|
||||
'Online products' => 'Online products',
|
||||
'Orders' => 'Orders',
|
||||
'Overall sales' => 'Overall sales',
|
||||
'Previous month sales' => 'Previous month sales',
|
||||
'Previous year sales' => 'Previous year sales',
|
||||
'Products' => 'Products',
|
||||
'Sales' => 'Sales',
|
||||
'Sales excluding shipping' => 'Sales excluding shipping',
|
||||
'This month' => 'This month',
|
||||
'This year' => 'This year',
|
||||
'Today' => 'Today',
|
||||
'Yesterday sales' => 'Yesterday sales',
|
||||
];
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Abgebrochene Bestellungen',
|
||||
'Average cart' => 'Durchschnittlichen Warenkorb',
|
||||
'Categories' => 'Kategorien',
|
||||
'Click here' => 'Hier Klicken',
|
||||
'Current version' => 'Aktuelle Version',
|
||||
'Customers' => 'Kunden',
|
||||
'Dashboard' => 'Dashboard',
|
||||
'First orders' => 'Erste Bestellungen',
|
||||
'Latest version available' => 'Neueste Version verfügbar',
|
||||
'Lire la suite' => 'Weiterlesen',
|
||||
'Loading Thelia lastest news...' => 'THELIAs neuesten Nachrichten Laden ...',
|
||||
'Loading...' => 'Laden...',
|
||||
'New customers' => 'Neue Kunde',
|
||||
'Offline products' => 'Offline Produkte',
|
||||
'Online products' => 'Online Produkte',
|
||||
'Orders' => 'Bestellungen',
|
||||
'Overall sales' => 'Gesamtverkäufe',
|
||||
'Previous month sales' => 'Vorheriger Monat Verkäufe',
|
||||
'Previous year sales' => 'Vorheriges Jahr Verkäufe',
|
||||
'Products' => 'Produkte',
|
||||
'Sales' => 'Verkäufe',
|
||||
'Sales excluding shipping' => 'Verkäufe ohne Lieferung',
|
||||
'This month' => 'Diesen Monat',
|
||||
'This year' => 'Dieses Jahr',
|
||||
'Today' => 'Heute',
|
||||
'Yesterday sales' => 'Verkäufe von Gestern',
|
||||
];
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Aborted orders' => 'Aborted orders',
|
||||
'An error occurred while reading from JSON file' => 'An error occurred while reading from JSON file',
|
||||
'Average cart' => 'Average cart',
|
||||
'Categories' => 'Categories',
|
||||
'Click here' => 'Click here',
|
||||
'Current version' => 'Current version',
|
||||
'Customers' => 'Customers',
|
||||
'Dashboard' => 'Dashboard',
|
||||
'First orders' => 'First orders',
|
||||
'Latest version available' => 'Latest version available',
|
||||
'Loading Thelia lastest news...' => 'Loading Thelia lastest news...',
|
||||
'Loading...' => 'Loading...',
|
||||
'New customers' => 'New customers',
|
||||
'News' => 'News',
|
||||
'Offline products' => 'Offline products',
|
||||
'Online products' => 'Online products',
|
||||
'Orders' => 'Orders',
|
||||
'Overall sales' => 'Overall sales',
|
||||
'Previous month sales' => 'Previous month sales',
|
||||
'Previous year sales' => 'Previous year sales',
|
||||
'Products' => 'Products',
|
||||
'Read more' => 'Read more',
|
||||
'Sales' => 'Sales',
|
||||
'Sales excluding shipping' => 'Sales excluding shipping',
|
||||
'This month' => 'This month',
|
||||
'This year' => 'This year',
|
||||
'Today' => 'Today',
|
||||
'YYYY-MM' => 'YYYY-MM',
|
||||
'Yesterday sales' => 'Yesterday sales',
|
||||
);
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Pedidos abandonados',
|
||||
'Average cart' => 'Carrito medio',
|
||||
'Categories' => 'Categorías',
|
||||
'Click here' => 'Haz clic aquí',
|
||||
'Current version' => 'Versión actual',
|
||||
'Customers' => 'Clientes',
|
||||
'Dashboard' => 'Panel de Control',
|
||||
'First orders' => 'Primeros pedidos',
|
||||
'Latest version available' => 'Última versión disponible',
|
||||
'Lire la suite' => 'Leer más',
|
||||
'Loading Thelia lastest news...' => 'Carregant Thelia últimes notícies ...',
|
||||
'Loading...' => 'Carregant ...',
|
||||
'New customers' => 'Nuevos clientes',
|
||||
'News' => 'Noticias',
|
||||
'Offline products' => 'Productos fuera de línea',
|
||||
'Online products' => 'Productos en línea',
|
||||
'Orders' => 'Pedidos',
|
||||
'Overall sales' => 'Ventas totales',
|
||||
'Previous month sales' => 'Ventas del mes anterior',
|
||||
'Previous year sales' => 'Ventas del año anterior',
|
||||
'Products' => 'Productos',
|
||||
'Sales' => 'Ventas',
|
||||
'Sales excluding shipping' => 'Ventas sin el envio',
|
||||
'This month' => 'Este mes',
|
||||
'This year' => 'Este año',
|
||||
'Today' => 'Hoy',
|
||||
'Yesterday sales' => 'Ventas de ayer',
|
||||
];
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Aborted orders' => 'Paniers abandonnés',
|
||||
'An error occurred while reading from JSON file' => 'Désolé, une erreur s\'est produite pendant la récupération des données.',
|
||||
'Average cart' => 'Panier moyen',
|
||||
'Categories' => 'Rubriques',
|
||||
'Click here' => 'Cliquez ici',
|
||||
'Current version' => 'Version en cours',
|
||||
'Customers' => 'Clients',
|
||||
'Dashboard' => 'Tableau de bord',
|
||||
'First orders' => 'Premières commandes',
|
||||
'Latest version available' => 'Dernière version disponible',
|
||||
'Loading Thelia lastest news...' => 'Chargement des dernières information Thelia...',
|
||||
'Loading...' => 'Chargement...',
|
||||
'New customers' => 'Nouveaux clients',
|
||||
'News' => 'Actualités',
|
||||
'Offline products' => 'Produits hors ligne',
|
||||
'Online products' => 'Produits en ligne',
|
||||
'Orders' => 'Commandes',
|
||||
'Overall sales' => 'Total des ventes',
|
||||
'Previous month sales' => 'Ventes du mois précédent',
|
||||
'Previous year sales' => 'Ventes de l\'année précédente',
|
||||
'Products' => 'Produits',
|
||||
'Read more' => 'Lire la suite',
|
||||
'Sales' => 'Ventes',
|
||||
'Sales excluding shipping' => 'Ventes hors frais de port',
|
||||
'This month' => 'Ce mois',
|
||||
'This year' => 'Cette année',
|
||||
'Today' => 'Aujourd\'hui',
|
||||
'YYYY-MM' => 'MM/YYYY',
|
||||
'Yesterday sales' => 'Ventes de la veille',
|
||||
);
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Ordini annullati',
|
||||
'Average cart' => 'Carrello medio',
|
||||
'Categories' => 'Categorie',
|
||||
'Click here' => 'Clicca qui',
|
||||
'Current version' => 'Versione attuale',
|
||||
'Customers' => 'Clienti',
|
||||
'Dashboard' => 'Dashboard',
|
||||
'First orders' => 'Primi ordini',
|
||||
'Latest version available' => 'Ultima versione disponibile',
|
||||
'Lire la suite' => 'Per saperne di più',
|
||||
'Loading Thelia lastest news...' => 'Caricamento delle ultime notizie su Thelia...',
|
||||
'Loading...' => 'Caricamento...',
|
||||
'New customers' => 'Nuovi clienti',
|
||||
'News' => 'Notizie',
|
||||
'Offline products' => 'Prodotti non in linea',
|
||||
'Online products' => 'Prodotti online',
|
||||
'Orders' => 'Ordini',
|
||||
'Overall sales' => 'Vendite complessive',
|
||||
'Previous month sales' => 'Vendite del mese precedente',
|
||||
'Previous year sales' => 'Vendite dell\'anno precedente',
|
||||
'Products' => 'Prodotti',
|
||||
'Read more' => 'Per saperne di più',
|
||||
'Sales' => 'Vendite',
|
||||
'Sales excluding shipping' => 'Vendite escluse spese di spedizione',
|
||||
'This month' => 'Questo mese',
|
||||
'This year' => 'Quest\'anno',
|
||||
'Today' => 'Oggi',
|
||||
'Yesterday sales' => 'Vendite di ieri',
|
||||
];
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Ordens abortadas',
|
||||
'Click here' => 'Clique aqui',
|
||||
];
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'Aborted orders',
|
||||
'Average cart' => 'Average cart',
|
||||
'Categories' => 'Categories',
|
||||
'Click here' => 'Click here',
|
||||
'Current version' => 'Current version',
|
||||
'Customers' => 'Customers',
|
||||
'Dashboard' => 'Dashboard',
|
||||
'First orders' => 'First orders',
|
||||
'Latest version available' => 'Latest version available',
|
||||
'Lire la suite' => 'Lire la suite',
|
||||
'Loading Thelia lastest news...' => 'Loading Thelia lastest news...',
|
||||
'Loading...' => 'Loading...',
|
||||
'New customers' => 'New customers',
|
||||
'News' => 'News',
|
||||
'Offline products' => 'Offline products',
|
||||
'Online products' => 'Online products',
|
||||
'Orders' => 'Orders',
|
||||
'Overall sales' => 'Overall sales',
|
||||
'Previous month sales' => 'Previous month sales',
|
||||
'Previous year sales' => 'Previous year sales',
|
||||
'Products' => 'Products',
|
||||
'Sales' => 'Sales',
|
||||
'Sales excluding shipping' => 'Sales excluding shipping',
|
||||
'This month' => 'This month',
|
||||
'This year' => 'This year',
|
||||
'Today' => 'Today',
|
||||
'Yesterday sales' => 'Yesterday sales',
|
||||
];
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Aborted orders' => 'İptal edilen siparişler',
|
||||
'Average cart' => 'Sepet Ortalaması',
|
||||
'Categories' => 'Katogoriler',
|
||||
'Click here' => 'Buraya tıklayın',
|
||||
'Current version' => 'Güncel Sürüm',
|
||||
'Customers' => 'müşteriler',
|
||||
'Dashboard' => 'Kontrol paneli',
|
||||
'First orders' => 'İlk emir',
|
||||
'Latest version available' => 'En son yorum elde edilebilir',
|
||||
'Lire la suite' => 'Devamını okuyun',
|
||||
'Loading Thelia lastest news...' => 'Thelia yükleme son haberler...',
|
||||
'Loading...' => 'Yükleneniyor…...',
|
||||
'New customers' => 'Yeni Müşteriler',
|
||||
'News' => 'Yeni Haberler',
|
||||
'Offline products' => 'Çevrimdışı ürünler',
|
||||
'Online products' => 'Online Ürünler',
|
||||
'Orders' => 'siparişler',
|
||||
'Overall sales' => 'Genel satış',
|
||||
'Previous month sales' => 'Önceki ay satış',
|
||||
'Previous year sales' => 'Önceki yılın satış',
|
||||
'Products' => 'ürün',
|
||||
'Sales' => 'Satış',
|
||||
'Sales excluding shipping' => 'Nakliye hariç satış',
|
||||
'This month' => 'Bu Ay',
|
||||
'This year' => 'Bu yıl',
|
||||
'Today' => 'bugün',
|
||||
'Yesterday sales' => 'Dün satış',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/cs_CZ.php
Normal file
7
local/modules/HookAdminHome/I18n/cs_CZ.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Sales statistics',
|
||||
'Stats on %month/%year' => 'Stats on %month/%year',
|
||||
'Thelia informations' => 'Thelia information',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/de_DE.php
Normal file
7
local/modules/HookAdminHome/I18n/de_DE.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Verkaufsstatistiken',
|
||||
'Stats on %month/%year' => 'Statistiken für %month/%year',
|
||||
'Thelia informations' => 'Thelias Informationen',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/en_US.php
Normal file
7
local/modules/HookAdminHome/I18n/en_US.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
'Stats on %month/%year' => 'Stats on %month/%year',
|
||||
'Thelia informations' => 'Thelia information',
|
||||
'Sales statistics' => 'Sales statistics',
|
||||
);
|
||||
6
local/modules/HookAdminHome/I18n/es_ES.php
Normal file
6
local/modules/HookAdminHome/I18n/es_ES.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Estadísticas de ventas',
|
||||
'Thelia informations' => 'información sobre Thelia',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/fr_FR.php
Normal file
7
local/modules/HookAdminHome/I18n/fr_FR.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Statistiques de vente',
|
||||
'Stats on %month/%year' => 'Statistiques pour %month/%year',
|
||||
'Thelia informations' => 'Informations Thelia',
|
||||
];
|
||||
5
local/modules/HookAdminHome/I18n/id_ID.php
Normal file
5
local/modules/HookAdminHome/I18n/id_ID.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Stats on %month/%year' => 'Stats on %month/%year',
|
||||
];
|
||||
6
local/modules/HookAdminHome/I18n/it_IT.php
Normal file
6
local/modules/HookAdminHome/I18n/it_IT.php
Normal file
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Statistiche di vendita',
|
||||
'Thelia informations' => 'Thelia informazioni',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/ru_RU.php
Normal file
7
local/modules/HookAdminHome/I18n/ru_RU.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Sales statistics',
|
||||
'Stats on %month/%year' => 'Stats on %month/%year',
|
||||
'Thelia informations' => 'Thelia information',
|
||||
];
|
||||
7
local/modules/HookAdminHome/I18n/tr_TR.php
Normal file
7
local/modules/HookAdminHome/I18n/tr_TR.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'Sales statistics' => 'Satış istatistikleri',
|
||||
'Stats on %month/%year' => '%month/%year istatistikleri',
|
||||
'Thelia informations' => 'Thelia bilgi',
|
||||
];
|
||||
165
local/modules/HookAdminHome/LICENSE.txt
Normal file
165
local/modules/HookAdminHome/LICENSE.txt
Normal file
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
11
local/modules/HookAdminHome/composer.json
Normal file
11
local/modules/HookAdminHome/composer.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "thelia/hook-admin-home-module",
|
||||
"license": "LGPL-3.0+",
|
||||
"type": "thelia-module",
|
||||
"require": {
|
||||
"thelia/installer": "~1.1"
|
||||
},
|
||||
"extra": {
|
||||
"installer-name": "HookAdminHome"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{* this template is loaded via Ajax in the login page, to prevent login page slowdown *}
|
||||
|
||||
{* Set the default translation domain, that will be used by intl when the 'd' parameter is not set *}
|
||||
{default_translation_domain domain='hookadminhome.bo.default'}
|
||||
|
||||
<div class="panel-group" id="accordion">
|
||||
{loop type="feed" name="thelia_feeds" url="http://thelia.net/feeds/?lang={$lang_code}" limit="3"}
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">
|
||||
<a class="accordion-toggle" data-toggle="collapse" data-parent="#accordion" href="#collapse-{$LOOP_COUNT}">
|
||||
{$TITLE|strip_tags nofilter} - {format_date timestamp=$DATE output='date'}
|
||||
</a>
|
||||
</h3>
|
||||
</div>
|
||||
<div id="collapse-{$LOOP_COUNT}" class="panel-collapse collapse {if $LOOP_COUNT == 1}in{/if}">
|
||||
<div class="panel-body">
|
||||
{* we use unescape:"htmlall" to unescape var before truncate, to prevent a cut in the middel of an HTML entity, eg &ea... *}
|
||||
<p>{$DESCRIPTION|strip_tags|unescape:"htmlall"|truncate:250:"...":true nofilter}</p>
|
||||
</div>
|
||||
<div class="panel-footer">
|
||||
<a href="{$URL nofilter}" target="_blank" class="btn btn-defaut btn-primary"><span class="glyphicon glyphicon-book"></span> {intl l='Read more'}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/loop}
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
#block-information a{color:#8A8A8A}.stats{border-right:1px solid #f0f0f0;text-align:center}.stats:last-child{border-right:none}.stats h2{margin-top:0;margin-bottom:5px;font-size:30px}.stats p{margin-top:0;text-transform:uppercase;font-size:12px}@media (max-width:991px){.stats{margin-bottom:10px}.stats:nth-child(3){border-right:none}}.homepage #date-picker{text-align:center;}
|
||||
@@ -0,0 +1,45 @@
|
||||
@import "../../../../../../../../templates/backOffice/default/assets/less/bootstrap/variables.less";
|
||||
@import "../../../../../../../../templates/backOffice/default/assets/less/thelia/variables.less";
|
||||
|
||||
#block-information {
|
||||
a {
|
||||
color: #8A8A8A;
|
||||
}
|
||||
}
|
||||
|
||||
.stats {
|
||||
border-right: 1px solid @table-border-color;
|
||||
text-align: center;
|
||||
|
||||
&:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 5px;
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: @font-size-base - 1; // 12px
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: @screen-sm-max) {
|
||||
.stats {
|
||||
margin-bottom: 10px;
|
||||
|
||||
&:nth-child(3) {
|
||||
border-right: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.homepage {
|
||||
#date-picker {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
{* Do not display shop information block if user none of the required authorizations *}
|
||||
|
||||
{capture name="shop_information_block_content"}
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.customer" access="VIEW"}
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/customers'}">
|
||||
<h2>{count type="customer" current="false" backend_context="1"}</h2>
|
||||
<p>{intl l="Customers" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.category" access="VIEW"}
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/catalog'}">
|
||||
<h2>{count type="category" visible="*" backend_context="1"}</h2>
|
||||
<p>{intl l="Categories" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.product" access="VIEW"}
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/catalog'}">
|
||||
<h2>{count type="product" visible="*" backend_context="1"}</h2>
|
||||
<p>{intl l="Products" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/catalog'}">
|
||||
<h2>{count type="product" visible="true" backend_context="1"}</h2>
|
||||
<p>{intl l="Online products" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/catalog'}">
|
||||
<h2>{count type="product" visible="false" backend_context="1"}</h2>
|
||||
<p>{intl l="Offline products" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
{/loop}
|
||||
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"}
|
||||
<div class="stats col-md-2 col-xs-4">
|
||||
<a href="{url path='/admin/orders'}">
|
||||
<h2>{count type="order" status="*" customer="*" backend_context="1"}</h2>
|
||||
<p>{intl l="Orders" d='hookadminhome.bo.default'}</p>
|
||||
</a>
|
||||
</div>
|
||||
{/loop}
|
||||
{/capture}
|
||||
|
||||
{if trim($smarty.capture.shop_information_block_content) ne ""}
|
||||
<div class="general-block-decorator" id="block-information">
|
||||
<div class="row">
|
||||
{$smarty.capture.shop_information_block_content nofilter}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -0,0 +1,48 @@
|
||||
{loop type="currency" name="default-currency" default_only="1"}
|
||||
{$defaultCurrency = $SYMBOL}
|
||||
{/loop}
|
||||
|
||||
{if empty($startDate)}{$startDate = 'this_month'}{/if}
|
||||
{if empty($startDate)}{$startDate = 'this_month'}{/if}
|
||||
|
||||
{if empty($prevMonthStartDate)}{$prevMonthStartDate = 'last_month'}{/if}
|
||||
{if empty($prevMonthEndDate)}{$prevMonthEndDate = 'last_month'}{/if}
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{intl l="Overall sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate=$startDate endDate=$endDate} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Sales excluding shipping" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$salesNoShipping = {stats key="sales" startDate=$startDate endDate=$endDate includeShipping="false"}}
|
||||
{format_money number=$salesNoShipping symbol=$defaultCurrency}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Previous month sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate=$prevMonthStartDate endDate=$prevMonthEndDate} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Orders" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$orderCount = {stats key="orders" startDate=$startDate endDate=$endDate}}
|
||||
{$orderCount}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Average cart" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{if $orderCount == 0}
|
||||
{format_money number=0 symbol=$defaultCurrency}
|
||||
{else}
|
||||
{format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency}
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -0,0 +1,7 @@
|
||||
{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"}
|
||||
<script>
|
||||
(function ($) {
|
||||
$(".feed-list").load("{admin_viewurl view='ajax/thelia_news_feed'}");
|
||||
}(jQuery));
|
||||
</script>
|
||||
{/loop}
|
||||
@@ -0,0 +1,5 @@
|
||||
{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"}
|
||||
<div class="feed-list">
|
||||
<div class="alert alert-info">{intl l="Loading Thelia lastest news..." d='hookadminhome.bo.default'}</div>
|
||||
</div>
|
||||
{/loop}
|
||||
@@ -0,0 +1,100 @@
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"}
|
||||
<ul class="nav nav-tabs nav-justified">
|
||||
<li class="active"><a href="#statjour" id="statjour_label"
|
||||
data-toggle="tab">{intl l="Today" d='hookadminhome.bo.default'}</a></li>
|
||||
<li><a href="#statmois" id="statmois_label"
|
||||
data-toggle="tab">{intl l="This month" d='hookadminhome.bo.default'}</a></li>
|
||||
<li><a href="#statannee" id="statannee_label"
|
||||
data-toggle="tab">{intl l="This year" d='hookadminhome.bo.default'}</a></li>
|
||||
</ul>
|
||||
{loop type="currency" name="default-currency" default_only="1"}
|
||||
{$defaultCurrency = $SYMBOL}
|
||||
{/loop}
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade active in" id="statjour">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{intl l="Overall sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate="today" endDate="today"} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Sales excluding shipping" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$salesNoShipping = {stats key="sales" startDate="today" endDate="today" includeShipping="false"}}
|
||||
{format_money number=$salesNoShipping symbol=$defaultCurrency}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Yesterday sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate="yesterday" endDate="yesterday"} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Orders" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$orderCount = {stats key="orders" startDate="today" endDate="today"}}
|
||||
{$orderCount}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Average cart" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{if $orderCount == 0}
|
||||
{format_money number=0 symbol=$defaultCurrency}
|
||||
{else}
|
||||
{format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency}
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="statmois">
|
||||
{include file="block-month-sales-statistics.html"}
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="statannee">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{intl l="Overall sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate="this_year" endDate="this_year"} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Sales excluding shipping" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$salesNoShipping = {stats key="sales" startDate="this_year" endDate="this_year" includeShipping="false"}}
|
||||
{format_money number=$salesNoShipping symbol=$defaultCurrency}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Previous year sales" d='hookadminhome.bo.default'}</th>
|
||||
<td>{format_money number={stats key="sales" startDate="last_year" endDate="last_year"} symbol=$defaultCurrency}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Orders" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{$orderCount = {stats key="orders" startDate="this_year" endDate="this_year"}}
|
||||
{$orderCount}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Average cart" d='hookadminhome.bo.default'}</th>
|
||||
<td>
|
||||
{if $orderCount == 0}
|
||||
{format_money number=0 symbol=$defaultCurrency}
|
||||
{else}
|
||||
{format_money number={($salesNoShipping/$orderCount)|round:"2"} symbol=$defaultCurrency}
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/loop}
|
||||
@@ -0,0 +1,207 @@
|
||||
<script src="{javascript file='assets/js/jqplot/jquery.jqplot.min.js'}"></script>
|
||||
<script src="{javascript file='assets/js/jqplot/plugins/jqplot.highlighter.min.js'}"></script>
|
||||
<script src="{javascript file='assets/js/jqplot/plugins/jqplot.pointLabels.min.js'}"></script>
|
||||
<script src="{javascript file='assets/js/moment-with-locales.min.js'}"></script>
|
||||
<script src="{javascript file='assets/js/bootstrap-datetimepicker/bootstrap-datetimepicker.min.js'}"></script>
|
||||
|
||||
<script>
|
||||
jQuery(function ($) {
|
||||
{$langcode = {lang attr="code"}|substr:0:2}
|
||||
|
||||
var jQplotDate = moment();
|
||||
var $datePicker = $('#date-picker');
|
||||
var displayDateFormat = '{intl l='YYYY-MM' d='hookadminhome.bo.default'}';
|
||||
|
||||
$datePicker.val(moment().format(displayDateFormat));
|
||||
|
||||
$datePicker.datetimepicker({
|
||||
locale: "{$langcode}",
|
||||
viewMode: 'months',
|
||||
format: displayDateFormat
|
||||
}).on('dp.change', function (e) {
|
||||
// Load month statistics block
|
||||
$('#statmois_label').html(e.date.format(displayDateFormat)).click();
|
||||
$('#statmois').load('{url path="/admin/home/month-sales-block/"}' + (e.date.month() + 1) + '/' + e.date.year());
|
||||
|
||||
// e.date is a moment.js date
|
||||
jQplotDate = e.date;
|
||||
|
||||
statInputActive(true);
|
||||
|
||||
retrieveJQPlotJson(
|
||||
jQplotDate,
|
||||
function () {
|
||||
statInputActive(false);
|
||||
},
|
||||
0
|
||||
);
|
||||
});
|
||||
|
||||
$("#span-calendar").click(function (e) {
|
||||
$('#date-picker').focus();
|
||||
});
|
||||
|
||||
function statInputActive(type) {
|
||||
$('#date-picker').attr('readonly', type);
|
||||
$('.js-stats-refresh').attr('disabled', type)
|
||||
}
|
||||
|
||||
var url = "{url path='/admin/home/stats'}";
|
||||
var jQplotData; // json data
|
||||
var jQPlotInstance; // global instance
|
||||
var valueFormats; // sprintf format of tooltip text
|
||||
|
||||
var jQPlotsOptions = {
|
||||
animate: false,
|
||||
axesDefaults: {
|
||||
tickOptions: {
|
||||
showMark: true,
|
||||
showGridline: true
|
||||
}
|
||||
},
|
||||
axes: {
|
||||
xaxis: {
|
||||
borderColor: '#ccc',
|
||||
ticks: [],
|
||||
tickOptions: {
|
||||
showGridline: false
|
||||
}
|
||||
},
|
||||
yaxis: {
|
||||
min: 0,
|
||||
tickOptions: {
|
||||
showGridline: true,
|
||||
showMark: false,
|
||||
showLabel: true,
|
||||
shadow: false
|
||||
}
|
||||
}
|
||||
},
|
||||
seriesDefaults: {
|
||||
lineWidth: 3,
|
||||
shadow: false,
|
||||
markerOptions: {
|
||||
shadow: false,
|
||||
style: 'filledCircle',
|
||||
size: 12
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
background: '#FFF',
|
||||
shadow: false,
|
||||
borderColor: '#FFF'
|
||||
},
|
||||
highlighter: {
|
||||
show: true,
|
||||
sizeAdjust: 7,
|
||||
tooltipLocation: 'n',
|
||||
tooltipContentEditor: function (str, seriesIndex, pointIndex, plot) {
|
||||
return $.jqplot.sprintf(
|
||||
valueFormats[seriesIndex],
|
||||
plot.data[seriesIndex][pointIndex][1]
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Get initial data Json
|
||||
retrieveJQPlotJson(jQplotDate);
|
||||
|
||||
$('[data-toggle="jqplot"]').click(function () {
|
||||
$(this).toggleClass('active');
|
||||
jsonSuccessLoad();
|
||||
});
|
||||
|
||||
$('.js-stats-refresh').click(function (e) {
|
||||
statInputActive(true);
|
||||
|
||||
retrieveJQPlotJson(
|
||||
jQplotDate,
|
||||
function () {
|
||||
statInputActive(false);
|
||||
},
|
||||
1
|
||||
);
|
||||
});
|
||||
|
||||
function retrieveJQPlotJson(moment, callback, flush) {
|
||||
|
||||
if (typeof flush === "undefined") {
|
||||
flush = 0;
|
||||
}
|
||||
|
||||
// JS month range is [0..11], the url requires a PHP month range [1..12]
|
||||
$.getJSON(url, {
|
||||
month : moment.month() + 1,
|
||||
year : moment.year(),
|
||||
flush : flush
|
||||
}).done(function (data) {
|
||||
jQplotData = data;
|
||||
jsonSuccessLoad();
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}).fail(jsonFailLoad);
|
||||
}
|
||||
|
||||
function initJqplotData(json) {
|
||||
var series = [];
|
||||
var seriesColors = [];
|
||||
|
||||
// Used globally !
|
||||
valueFormats = [];
|
||||
|
||||
$('[data-toggle="jqplot"].active').each(function (i) {
|
||||
var position = $(this).index();
|
||||
var serie = json.series[position];
|
||||
|
||||
series.push(serie.data);
|
||||
seriesColors.push(serie.color);
|
||||
valueFormats.push(serie.valueFormat);
|
||||
});
|
||||
|
||||
// Number of days to display ( = data.length in one serie)
|
||||
var days = json.series[0].data.length;
|
||||
|
||||
// Add days to xaxis
|
||||
var ticks = [];
|
||||
for (var i = 1; i < (days + 1); i++) {
|
||||
ticks.push([i - 1, i]);
|
||||
}
|
||||
|
||||
jQPlotsOptions.axes.xaxis.ticks = ticks;
|
||||
|
||||
// Graph title
|
||||
jQPlotsOptions.title = json.title;
|
||||
|
||||
// Graph series colors
|
||||
jQPlotsOptions.seriesColors = seriesColors;
|
||||
|
||||
return series;
|
||||
}
|
||||
|
||||
function jsonFailLoad(data) {
|
||||
$('#jqplot').html(
|
||||
'<div class="alert alert-danger">{intl l='An error occurred while reading from JSON file' js=1 d='hookadminhome.bo.default'}</div>'
|
||||
);
|
||||
}
|
||||
|
||||
function jsonSuccessLoad() {
|
||||
// Init jQPlot
|
||||
var series = initJqplotData(jQplotData);
|
||||
|
||||
// Start jQPlot
|
||||
if (jQPlotInstance) {
|
||||
jQPlotInstance.destroy();
|
||||
}
|
||||
|
||||
jQPlotInstance = $.jqplot("jqplot", series, jQPlotsOptions);
|
||||
|
||||
$(window).bind('resize', function (event, ui) {
|
||||
jQPlotInstance.replot({
|
||||
resetAxes: true
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,34 @@
|
||||
{loop type="auth" name="can_view" role="ADMIN" resource="admin.order" access="VIEW"}
|
||||
<div class="general-block-decorator dashboard">
|
||||
|
||||
<div class="title title-without-tabs clearfix">
|
||||
{intl l='Dashboard' d='hookadminhome.bo.default'}
|
||||
<div class="col-sm-2 input-group pull-right">
|
||||
<span id="span-calendar" class="input-group-addon">
|
||||
<span class="glyphicon glyphicon-calendar"></span>
|
||||
</span>
|
||||
<input type="text" class="form-control" id="date-picker">
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="form-control btn btn-default js-stats-refresh" data-month-offset="0"><span class="glyphicon glyphicon-refresh"></span></button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center clearfix">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-default active" data-toggle="jqplot" data-target="sales"><span class="glyphicon glyphicon-euro"></span> {intl l="Sales" d='hookadminhome.bo.default'}</button>
|
||||
<button type="button" class="btn btn-primary" data-toggle="jqplot" data-target="registration"><span class="glyphicon glyphicon-user"></span> {intl l="New customers" d='hookadminhome.bo.default'}</button>
|
||||
<button type="button" class="btn btn-success" data-toggle="jqplot" data-target="orders"><span class="glyphicon glyphicon-shopping-cart"></span> {intl l="Orders" d='hookadminhome.bo.default'}</button>
|
||||
<button type="button" class="btn btn-info" data-toggle="jqplot" data-target="first-orders"><span class="glyphicon glyphicon-thumbs-up"></span> {intl l="First orders" d='hookadminhome.bo.default'}</button>
|
||||
<button type="button" class="btn btn-danger" data-toggle="jqplot" data-target="aborted-orders"><span class="glyphicon glyphicon-thumbs-down"></span> {intl l="Aborted orders" d='hookadminhome.bo.default'}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="jqplot-content">
|
||||
<div id="jqplot"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{/loop}
|
||||
@@ -0,0 +1,20 @@
|
||||
{loop type="auth" name="can_view" role="ADMIN" module="HookAdminHome" access="VIEW"}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{intl l="Current version" d='hookadminhome.bo.default'}</th>
|
||||
<td>{$THELIA_VERSION}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="Latest version available"}</th>
|
||||
<td><a href="http://thelia.net/#download" id="latest-thelia-version">{intl l="Loading..." d='hookadminhome.bo.default'}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{intl l="News"}</th>
|
||||
<td><a href="http://thelia.net/blog" target="_blank">{intl l="Click here" d='hookadminhome.bo.default'}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/loop}
|
||||
Reference in New Issue
Block a user