Browse Source

[Administration] Tableau de bord administrateur

feature/souke
Guillaume Bourgeois 10 months ago
parent
commit
9fb5952ccf
10 changed files with 372 additions and 27 deletions
  1. +85
    -0
      backend/controllers/DashboardAdminController.php
  2. +166
    -0
      backend/views/dashboard-admin/index.php
  3. +6
    -0
      backend/views/layouts/left.php
  4. +37
    -22
      backend/web/css/screen.css
  5. +11
    -1
      backend/web/js/backend.js
  6. +18
    -0
      backend/web/sass/_adminlte.scss
  7. +4
    -0
      backend/web/sass/dashboard-admin/_index.scss
  8. +1
    -0
      backend/web/sass/screen.scss
  9. +39
    -4
      domain/Producer/Producer/DolibarrProducerUtils.php
  10. +5
    -0
      domain/User/User/UserRepository.php

+ 85
- 0
backend/controllers/DashboardAdminController.php View File

@@ -0,0 +1,85 @@
<?php

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace backend\controllers;

use common\helpers\Price;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;

class DashboardAdminController extends BackendController
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return $this->getUserModule()
->getAuthorizationChecker()
->isGrantedAsAdministrator($this->getUserCurrent());
}
],
],
],
];
}


public function actionIndex()
{
return $this->render('index', [
'countUsersOnline' => $this->getUserModule()->getRepository()->countUsersOnline(),
'countTicketsAdminOpen' => $this->getTicketModule()->getRepository()->countTicketsAdminStatusOpen(),
'countTicketsAdminUnread' => $this->getTicketModule()->getRepository()->countTicketsAdminUnreadByUser($this->getUserCurrent()),
'amountProducerUnpaidInvoices' => '--',
]);
}

public function actionAjaxAmountProducerInvoicesUnpaid()
{
return Price::format($this->getProducerModule()->getDolibarrUtils()->getAmountProducerInvoicesUnpaid());
}
}

+ 166
- 0
backend/views/dashboard-admin/index.php View File

@@ -0,0 +1,166 @@
<?php

$this->setTitle('Tableau de bord');

?>

<div class="dashboard-admin-index">
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-aqua">
<div class="inner">
<h3><?= $countUsersOnline ?></h3>
<p>En ligne</p>
</div>
<div class="icon">
<i class="fa fa-wifi"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('online-admin/index') ?>" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-green">
<div class="inner">
<h3><?= 'Oui' ?></h3>
<p>Support activé</p>
</div>
<div class="icon">
<i class="fa fa-phone"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('support-admin/index') ?>" class="small-box-footer">
Désactiver <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-<?= $countTicketsAdminUnread ? 'green' : 'blue' ?>">
<div class="inner">
<h3><?= $countTicketsAdminOpen ?></h3>
<p>Tickets</p>
</div>
<div class="icon">
<i class="fa fa-comments"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('support-admin/index') ?>" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-green">
<div class="inner">
<h3><?= '1230 €' ?></h3>
<p>Total factures producteurs mois en cours</p>
</div>
<div class="icon">
<i class="fa fa-euro"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('producer-admin/index') ?>" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-red">
<div class="inner">
<h3 id="amount-producer-invoices-unpaid"><?= $amountProducerUnpaidInvoices ?></h3>
<p>Montant factures impayées</p>
</div>
<div class="icon">
<i class="fa fa-euro"></i>
</div>
<a target="_blank" href="<?= Yii::$app->parameterBag->get('dolibarrUrl') ?>compta/facture/list.php?leftmenu=customers_bills_notpaid&search_status=1" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-yellow">
<div class="inner">
<h3><?= '127 000 €' ?></h3>
<p>CA producteurs 30 derniers jours</p>
</div>
<div class="icon">
<i class="fa fa-line-chart"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('stats-admin/turnover') ?>" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-yellow">
<div class="inner">
<h3><?= '141' ?></h3>
<p>Commandes clients / jour</p>
</div>
<div class="icon">
<i class="fa fa-line-chart"></i>
</div>
<a href="<?= Yii::$app->urlManager->createUrl('stats-admin/turnover') ?>" class="small-box-footer">
Voir <i class="fa fa-arrow-circle-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-aqua">
<div class="inner">
<h3>43</h3>
<p>Producteurs actifs sur les 3 derniers mois</p>
</div>
<div class="icon">
<i class="fa fa-th-list"></i>
</div>
<div class="small-box-footer">&nbsp;</div>
</div>
</div>
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-aqua">
<div class="inner">
<h3>357</h3>
<p>Points de vente actifs sur les 3 derniers mois</p>
</div>
<div class="icon">
<i class="fa fa-map-marker"></i>
</div>
<div class="small-box-footer">&nbsp;</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-aqua">
<div class="inner">
<h3>3 865</h3>
<p>Clients actifs sur les 3 derniers mois</p>
</div>
<div class="icon">
<i class="fa fa-users"></i>
</div>
<div class="small-box-footer">&nbsp;</div>
</div>
</div>
<div class="col-lg-6 col-xs-6">
<div class="small-box bg-aqua">
<div class="inner">
<h3>32</h3>
<p>Inscriptions utilisateurs des 7 derniers jours</p>
</div>
<div class="icon">
<i class="fa fa-user-plus"></i>
</div>
<div class="small-box-footer">&nbsp;</div>
</div>
</div>
</div>
</div>

+ 6
- 0
backend/views/layouts/left.php View File

@@ -120,6 +120,12 @@ $isUserCurrentGrantedAsProducer = $userModule->getAuthorizationChecker()->isGran

// Administration
['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => $isUserCurrentGrantedAsAdministrator],
[
'label' => 'Tableau de bord',
'icon' => 'dashboard',
'url' => ['dashboard-admin/index'],
'visible' => $isUserCurrentGrantedAsAdministrator,
],
[
'label' => 'En ligne',
'icon' => 'wifi',

+ 37
- 22
backend/web/css/screen.css View File

@@ -1829,50 +1829,65 @@ body.skin-black .content-wrapper .alert .close:hover {
opacity: 1;
}
/* line 301, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .small-box h3 {
font-size: 28px;
font-family: 'Source Sans Pro',sans-serif;
}
/* line 306, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .small-box .icon {
top: -2px;
}
/* line 310, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .small-box .small-box-footer {
color: white;
padding-top: 6px;
padding-bottom: 2px;
}
/* line 319, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .callout h4 .fa {
margin-right: 7px;
}
/* line 304, ../sass/_adminlte.scss */
/* line 322, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .callout a {
color: white;
}
/* line 307, ../sass/_adminlte.scss */
/* line 325, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .callout .btn {
color: #333;
text-decoration: none;
}
/* line 314, ../sass/_adminlte.scss */
/* line 332, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .table th {
font-size: 13px;
}
/* line 317, ../sass/_adminlte.scss */
/* line 335, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .table th.column-actions, body.skin-black .content-wrapper .table td.column-actions {
width: 172px;
text-align: right;
}
/* line 321, ../sass/_adminlte.scss */
/* line 339, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .table td.text-small, body.skin-black .content-wrapper .table th.text-small {
font-size: 12px;
}
/* line 326, ../sass/_adminlte.scss */
/* line 344, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .pagination > .active > a, body.skin-black .content-wrapper .pagination > .active > span, body.skin-black .content-wrapper .pagination > .active > a:hover, body.skin-black .content-wrapper .pagination > .active > span:hover, body.skin-black .content-wrapper .pagination > .active > a:focus, body.skin-black .content-wrapper .pagination > .active > span:focus {
background-color: #F39C12;
border: solid 1px #F39C12;
color: white;
}
/* line 332, ../sass/_adminlte.scss */
/* line 350, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .pagination > li > a, body.skin-black .content-wrapper .pagination > li > span {
color: #F39C12;
}
/* line 334, ../sass/_adminlte.scss */
/* line 352, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .pagination > li > a:hover, body.skin-black .content-wrapper .pagination > li > span:hover {
color: #c87f0a;
}
/* line 339, ../sass/_adminlte.scss */
/* line 357, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .submenu {
margin-bottom: 25px;
}
/* line 343, ../sass/_adminlte.scss */
/* line 361, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .form-actions {
position: fixed;
bottom: 0;
@@ -1886,59 +1901,59 @@ body.skin-black .content-wrapper .form-actions {
z-index: 10;
border-top: solid 1px #e0e0e0;
}
/* line 356, ../sass/_adminlte.scss */
/* line 374, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .form-actions a, body.skin-black .content-wrapper .form-actions button {
margin-left: 10px;
}
/* line 361, ../sass/_adminlte.scss */
/* line 379, ../sass/_adminlte.scss */
body.skin-black .content-wrapper .form-buttons {
margin-top: 25px;
text-align: right;
}
/* line 368, ../sass/_adminlte.scss */
/* line 386, ../sass/_adminlte.scss */
body.skin-black .main-footer a {
color: #F39C12;
}
/* line 373, ../sass/_adminlte.scss */
/* line 391, ../sass/_adminlte.scss */
body.skin-black .gridview-pagesize {
float: right;
margin-bottom: 8px;
}
/* line 378, ../sass/_adminlte.scss */
/* line 396, ../sass/_adminlte.scss */
body.skin-black #yii-debug-toolbar {
bottom: 64px;
}

/* line 383, ../sass/_adminlte.scss */
/* line 401, ../sass/_adminlte.scss */
body.login-page {
background: none;
background-color: white;
}
/* line 387, ../sass/_adminlte.scss */
/* line 405, ../sass/_adminlte.scss */
body.login-page .login-box .login-logo {
text-align: center;
font-family: 'highvoltageregular';
}
/* line 391, ../sass/_adminlte.scss */
/* line 409, ../sass/_adminlte.scss */
body.login-page .login-box .login-logo img {
width: 50px;
}
/* line 396, ../sass/_adminlte.scss */
/* line 414, ../sass/_adminlte.scss */
body.login-page .login-box .login-box-body .btn-primary {
background-color: #F39C12;
border-color: #F39C12;
padding: 5px 10px;
}
/* line 401, ../sass/_adminlte.scss */
/* line 419, ../sass/_adminlte.scss */
body.login-page .login-box .login-box-body .btn-primary:active {
background-color: #f4a62a;
border-color: #F39C12;
}
/* line 407, ../sass/_adminlte.scss */
/* line 425, ../sass/_adminlte.scss */
body.login-page .login-box .login-box-body a {
color: #F39C12;
}
/* line 409, ../sass/_adminlte.scss */
/* line 427, ../sass/_adminlte.scss */
body.login-page .login-box .login-box-body a:hover {
color: #f4a62a;
}

+ 11
- 1
backend/web/js/backend.js View File

@@ -57,18 +57,28 @@ $(document).ready(function () {
opendistrib_features_index();
opendistrib_point_sale_form();
opendistrib_check_all_checkboxes();
opendistrib_dashboard_admin_invoices_unpaid();
});

var UrlManager = {
getBaseUrl: function () {
return $('meta[name=baseurl]').attr('content') + '/';

},
getBaseUrlAbsolute: function () {
return $('meta[name=baseurl-absolute]').attr('content') + '/';
}
};

function opendistrib_dashboard_admin_invoices_unpaid() {
var selector = '#amount-producer-invoices-unpaid';
$(selector).click(function() {
$(this).html('<i class="fa fa-spinner"></i>');
$.get(UrlManager.getBaseUrl() + 'dashboard-admin/ajax-amount-producer-invoices-unpaid', {}, function(result) {
$(selector).html(result);
});
});
}

function opendistrib_check_all_checkboxes() {
$('.check-all-checkboxes').change(function() {
var selector = $(this).data('selector');

+ 18
- 0
backend/web/sass/_adminlte.scss View File

@@ -296,6 +296,24 @@ body.skin-black {
}
}
}

.small-box {
h3 {
font-size: 28px;
font-family: 'Source Sans Pro',sans-serif;
}

.icon {
top: -2px;
}

.small-box-footer {
color: white;
padding-top: 6px;
padding-bottom: 2px;

}
}
.callout {
h4 .fa {

+ 4
- 0
backend/web/sass/dashboard-admin/_index.scss View File

@@ -0,0 +1,4 @@

.dashboard-admin-index {

}

+ 1
- 0
backend/web/sass/screen.scss View File

@@ -1553,4 +1553,5 @@ a.btn, button.btn {
@import "online-admin/_index.scss";
@import "feature-admin/_index.scss";
@import "setting/_form.scss";
@import "dashboard-admin/_index.scss" ;
@import "_responsive.scss" ;

+ 39
- 4
domain/Producer/Producer/DolibarrProducerUtils.php View File

@@ -30,17 +30,52 @@ class DolibarrProducerUtils extends AbstractManager
return $invoicesArray;
}

public function countDolibarrProducerInvoicesUnpaid(Producer $producer): int
public function getDolibarrProducerInvoicesUnpaid(Producer $producer): array
{
$count = 0;
$unpaidInvoicesArray = [];
$invoicesArray = $this->getDolibarrProducerInvoices($producer);

foreach($invoicesArray as $invoice) {
if($invoice['remaintopay'] > 0) {
$count ++;
$unpaidInvoicesArray[] = $invoice;
}
}

return $count;
return $unpaidInvoicesArray;
}

public function countDolibarrProducerInvoicesUnpaid(Producer $producer): int
{
return count($this->getDolibarrProducerInvoicesUnpaid($producer));
}

public function getDolibarrInvoicesUnpaid()
{
$unpaidInvoicesArray = [];
$producersArray = $this->producerRepository->findProducersActive();

foreach($producersArray as $producer) {
$unpaidInvoicesArray = array_merge(
$unpaidInvoicesArray,
$this->getDolibarrProducerInvoicesUnpaid($producer)
);
}

//die('test : '.count($unpaidInvoicesArray));

return $unpaidInvoicesArray;
}

public function getAmountProducerInvoicesUnpaid()
{
$amount = 0;
$unpaidInvoicesArray = $this->getDolibarrInvoicesUnpaid();

foreach($unpaidInvoicesArray as $unpaidInvoice) {
$amount += $unpaidInvoice['remaintopay'];
}

return $amount;
}

public function generateDolibarrProducerInvoice(Producer $producer)

+ 5
- 0
domain/User/User/UserRepository.php View File

@@ -291,4 +291,9 @@ class UserRepository extends AbstractRepository
{
return count($this->findUsersWithStatusUserAndOnline());
}

public function countUsersOnline(): int
{
return $this->countUsersStatusUserOnline() + $this->countUsersStatusProducerOnline();
}
}

Loading…
Cancel
Save