mirror of
https://github.com/Piwigo/Piwigo.git
synced 2026-03-28 17:42:57 +01:00
Issue #1190: Redesign of intro page
* Add an Activity graph for activity peaks * Add a storage graph for storage repartition * Redesign intro page for those charts
This commit is contained in:
193
admin/intro.php
193
admin/intro.php
@@ -187,6 +187,199 @@ SELECT MIN(date_available)
|
||||
|
||||
trigger_notify('loc_end_intro');
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | get activity data |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
$number_week = 4;
|
||||
$date = new DateTime();
|
||||
//Array for the JS tooltip
|
||||
$activity_last_weeks = array();
|
||||
//Count mondays
|
||||
$mondays = 0;
|
||||
//Get mondays date (day + month) for the chart legend
|
||||
$mondays_date = array();
|
||||
//Array for sorting days in circle size
|
||||
$temp_data = array();
|
||||
|
||||
//Get data from $number_week last weeks
|
||||
while ($mondays < $number_week)
|
||||
{
|
||||
$date_string = $date->format('Y-m-d');
|
||||
$query = '
|
||||
SELECT *
|
||||
FROM `'.ACTIVITY_TABLE.'`
|
||||
WHERE occured_on LIKE "'.$date_string.'%"
|
||||
;';
|
||||
|
||||
$result = query2array($query, null);
|
||||
|
||||
$this_day = array('number' => 0);
|
||||
foreach ($result as $act) {
|
||||
if(isset($this_day['details'][ucfirst($act['object'])][ucfirst($act['action'])]))
|
||||
{
|
||||
$this_day['details'][ucfirst($act['object'])][ucfirst($act['action'])] += 1;
|
||||
} else {
|
||||
$this_day['details'][ucfirst($act['object'])][ucfirst($act['action'])] = 1;
|
||||
}
|
||||
$this_day['number'] += 1;
|
||||
}
|
||||
|
||||
if ($this_day['number'] > 0)
|
||||
{
|
||||
$temp_data[] = array('x' => $this_day['number'], 'd'=>$date->format('N'), 'w'=>$mondays);
|
||||
}
|
||||
|
||||
|
||||
$activity_last_weeks[$mondays][intval($date->format('N'))] = $this_day;
|
||||
|
||||
if ($date->format('D') == 'Mon') {
|
||||
$mondays_date[$mondays]['m'] = $date->format('m');
|
||||
$mondays_date[$mondays]['d'] = $date->format('d');
|
||||
$mondays += 1;
|
||||
}
|
||||
$date->sub(new DateInterval('P1D'));
|
||||
}
|
||||
|
||||
// Algorithm to sort days in circle size :
|
||||
// * Get the difference between sorted numbers of activity per day (only not null numbers)
|
||||
// * Split days max $circle_sizes time on the biggest difference (but not below 120%)
|
||||
// * Set the sizes according to the groups created
|
||||
|
||||
//Function to sort days by number of activity
|
||||
function cmp_day($a, $b)
|
||||
{
|
||||
if ($a['x'] == $b['x']) {
|
||||
return 0;
|
||||
}
|
||||
return ($a['x'] < $b['x']) ? -1 : 1;
|
||||
}
|
||||
|
||||
usort($temp_data, 'cmp_day');
|
||||
|
||||
//Get the percent difference
|
||||
$diff_x = array();
|
||||
|
||||
for ($i=1; $i < count($temp_data); $i++)
|
||||
{
|
||||
$diff_x[] = $temp_data[$i]['x']/$temp_data[$i-1]['x']*100;
|
||||
}
|
||||
|
||||
$split = 0;
|
||||
//Split (split represented by -1)
|
||||
while (max($diff_x) > 120) {
|
||||
$diff_x[array_search(max($diff_x), $diff_x)] = -1;
|
||||
$split++;
|
||||
}
|
||||
|
||||
//Fill empty chart data for the template
|
||||
$chart_data = array();
|
||||
for ($i=0; $i < $number_week; $i++) {
|
||||
for ($j=1; $j <= 7; $j++) {
|
||||
$chart_data[$i][$j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
$size = 1;
|
||||
$chart_data[$temp_data[0]['w']][$temp_data[0]['d']] = $size;
|
||||
//Set sizes in chart data
|
||||
for ($i=1; $i < count($temp_data); $i++) {
|
||||
if ($diff_x[$i-1] == -1) {$size++;}
|
||||
$chart_data[$temp_data[$i]['w']][$temp_data[$i]['d']] = $size;
|
||||
}
|
||||
|
||||
//Assign data for the template
|
||||
$template->assign('ACTIVITY_MONDAYS_DATE',array_reverse($mondays_date));
|
||||
$template->assign('ACTIVITY_LAST_WEEKS', array_reverse($activity_last_weeks));
|
||||
$template->assign('ACTIVITY_CHART_DATA',array_reverse($chart_data));
|
||||
$template->assign('ACTIVITY_CHART_NUMBER_SIZES',$size);
|
||||
|
||||
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | get storage data |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
$video_format = array('webm','webmv','ogg','ogv','mp4','m4v');
|
||||
$data_storage = array();
|
||||
|
||||
//Select files in Image_Table
|
||||
$query = '
|
||||
SELECT file, filesize
|
||||
FROM `'.IMAGES_TABLE.'`
|
||||
;';
|
||||
|
||||
$result = query2array($query, null);
|
||||
|
||||
foreach ($result as $file)
|
||||
{
|
||||
$tabString = explode('.',$file['file']);
|
||||
$ext = $tabString[count($tabString) -1];
|
||||
$size = $file['filesize'];
|
||||
if (in_array($ext, $conf['picture_ext']))
|
||||
{
|
||||
if (isset($data_storage['Photos']))
|
||||
{
|
||||
$data_storage['Photos'] += $size;
|
||||
} else {
|
||||
$data_storage['Photos'] = $size;
|
||||
}
|
||||
} elseif (in_array($ext, $video_format)) {
|
||||
if (isset($data_storage['Videos']))
|
||||
{
|
||||
$data_storage['Videos'] += $size;
|
||||
} else {
|
||||
$data_storage['Videos'] = $size;
|
||||
}
|
||||
} else {
|
||||
if (isset($data_storage['Others']))
|
||||
{
|
||||
$data_storage['Others'] += $size;
|
||||
} else {
|
||||
$data_storage['Others'] = $size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Select files from format table
|
||||
$query = '
|
||||
SELECT SUM(filesize)
|
||||
FROM `'.IMAGE_FORMAT_TABLE.'`
|
||||
;';
|
||||
|
||||
$result = query2array($query);
|
||||
|
||||
if (isset($result[0]['SUM(filesize)']))
|
||||
{
|
||||
$data_storage['Format'] = $result[0]['SUM(filesize)'];
|
||||
}
|
||||
|
||||
//If the host is not windows, get the cache size
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
|
||||
{
|
||||
$f = './_data';
|
||||
$io = popen ( '/usr/bin/du -sk ' . $f, 'r' );
|
||||
$size = fgets ($io, 4096);
|
||||
$size = substr ( $size, 0, strpos ( $size, "\t" ) );
|
||||
pclose ( $io );
|
||||
$data_storage['Cache'] = $size;
|
||||
}
|
||||
|
||||
//Calculate total storage
|
||||
$total_storage = 0;
|
||||
foreach ($data_storage as $value)
|
||||
{
|
||||
$total_storage += $value;
|
||||
}
|
||||
|
||||
//Get percentage of the total storage
|
||||
foreach ($data_storage as $key=>$value)
|
||||
{
|
||||
$data_storage[$key] = $value/$total_storage*100;
|
||||
}
|
||||
|
||||
//Pass data to HTML
|
||||
$template->assign('STORAGE_TOTAL',$total_storage/1000);
|
||||
$template->assign('STORAGE_CHART_DATA',$data_storage);
|
||||
// +-----------------------------------------------------------------------+
|
||||
// | sending html code |
|
||||
// +-----------------------------------------------------------------------+
|
||||
|
||||
@@ -7,7 +7,7 @@ var piwigo_need_update_msg = '<a href="admin.php?page=updates">{'A new version o
|
||||
var ext_need_update_msg = '<a href="admin.php?page=updates&tab=ext">{'Some upgrades are available for extensions.'|@translate|@escape:"javascript"} <i class="icon-right"></i></a>';
|
||||
|
||||
{literal}
|
||||
jQuery().ready(function(){
|
||||
jQuery().ready(function(){
|
||||
jQuery('.cluetip').cluetip({
|
||||
width: 300,
|
||||
splitTitle: '|',
|
||||
@@ -61,6 +61,7 @@ jQuery().ready(function(){
|
||||
|
||||
<h2>{'Piwigo Administration'|@translate}</h2>
|
||||
|
||||
<div class="intro-page-container">
|
||||
<div class="stat-boxes">
|
||||
|
||||
{if $NB_PHOTOS > 1}
|
||||
@@ -140,6 +141,52 @@ jQuery().ready(function(){
|
||||
|
||||
</div> {* .stat-boxes *}
|
||||
|
||||
<div class="intro-charts">
|
||||
|
||||
<div class="chart-title"> {"Activity peak in the last weeks"|@translate}</div>
|
||||
<div class="activity-chart" style="grid-template-rows: repeat({count($ACTIVITY_CHART_DATA) + 1}, 6vw);">
|
||||
{foreach from=$ACTIVITY_CHART_DATA item=WEEK_ACTIVITY key=WEEK_NUMBER}
|
||||
<div id="week-{$WEEK_NUMBER}-legend" class="row-legend"><div>{"Week of %s/%s"|@translate:$ACTIVITY_MONDAYS_DATE[$WEEK_NUMBER]['d']:$ACTIVITY_MONDAYS_DATE[$WEEK_NUMBER]['m']}</div></div>
|
||||
{foreach from=$WEEK_ACTIVITY item=SIZE key=DAY_NUMBER}
|
||||
<span>
|
||||
{if $SIZE != 0}
|
||||
<div id="day{$WEEK_NUMBER}-{$DAY_NUMBER}" style="height:{$SIZE/$ACTIVITY_CHART_NUMBER_SIZES * 7 + 1}vw;width:{$SIZE/$ACTIVITY_CHART_NUMBER_SIZES * 7 + 1}vw;opacity:{$SIZE/$ACTIVITY_CHART_NUMBER_SIZES * 0.7 + 0.1}"></div>
|
||||
{if $ACTIVITY_LAST_WEEKS[$WEEK_NUMBER][$DAY_NUMBER]["number"] != 0}
|
||||
<p style="transform: translate(-50%, 50%) translate(0, {if $SIZE/2 >= 1}{$SIZE/2}{else}2{/if}vw)">
|
||||
<b>{"%s Activities"|@translate:$ACTIVITY_LAST_WEEKS[$WEEK_NUMBER][$DAY_NUMBER]["number"]}</b>
|
||||
{foreach from=$ACTIVITY_LAST_WEEKS[$WEEK_NUMBER][$DAY_NUMBER]["details"] item=actions key=cat}
|
||||
<br> {$cat} : {foreach from=$actions item=number key=action} ({$action}) {$number} {/foreach}
|
||||
{/foreach}
|
||||
</p>
|
||||
{/if}
|
||||
{/if}
|
||||
</span>
|
||||
{/foreach}
|
||||
{/foreach}
|
||||
<div></div>
|
||||
{foreach from=array('Mon'|translate, 'Tue'|translate, 'Wed'|translate, 'Thu'|translate, 'Fri'|translate, 'Sat'|translate, 'Sun'|translate) item=day}
|
||||
<div class="col-legend">{$day} <div class="line-vertical" style="height: {count($ACTIVITY_CHART_DATA)*100 - 50}%;"></div></div>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<div class="chart-title"> {"Storage"|@translate} <span class="chart-title-infos"> {'%s MB used'|translate:$STORAGE_TOTAL} </span></div>
|
||||
|
||||
<div class="storage-chart">
|
||||
{foreach from=$STORAGE_CHART_DATA item=value}
|
||||
<span style="width:{$value}%"> <p>{round($value)}%</p> </span>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<div class="storage-chart-legend">
|
||||
{foreach from=$STORAGE_CHART_DATA item=i key=type}
|
||||
<div><span></span> <p>{$type|translate}</p></div>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
</div> {* .intro-chart *}
|
||||
|
||||
</div> {* .intro-page-container *}
|
||||
|
||||
<p class="showCreateAlbum">
|
||||
{if $ENABLE_SYNCHRONIZATION}
|
||||
<a href="{$U_QUICK_SYNC}" class="icon-exchange">{'Quick Local Synchronization'|translate}</a>
|
||||
@@ -149,4 +196,4 @@ jQuery().ready(function(){
|
||||
{if isset($SUBSCRIBE_BASE_URL)}
|
||||
<br><span class="newsletter-subscription"><a href="{$SUBSCRIBE_BASE_URL}{$EMAIL}" id="newsletterSubscribe" class="externalLink cluetip icon-mail-alt" title="{'Piwigo Announcements Newsletter'|@translate}|{'Keep in touch with Piwigo project, subscribe to Piwigo Announcement Newsletter. You will receive emails when a new release is available (sometimes including a security bug fix, it\'s important to know and upgrade) and when major events happen to the project. Only a few emails a year.'|@translate|@htmlspecialchars|@nl2br}">{'Subscribe %s to Piwigo Announcements Newsletter'|@translate:$EMAIL}</a> <a href="#" class="newsletter-hide">{'... or hide this link'|translate}</a></span>
|
||||
{/if}
|
||||
</p>
|
||||
</p>
|
||||
@@ -545,14 +545,18 @@ FORM.properties SPAN.property {
|
||||
}
|
||||
|
||||
/* Dashboard */
|
||||
.intro-page-container {
|
||||
display: grid;
|
||||
grid-template-columns: 41% 44%;
|
||||
}
|
||||
|
||||
.stat-boxes {
|
||||
text-align:left;
|
||||
margin:40px 10px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.stat-box {
|
||||
display:inline-block;
|
||||
width:200px;
|
||||
width:150px;
|
||||
margin:10px 10px 40px 10px;
|
||||
color:#3b3b3b;
|
||||
text-align: center;
|
||||
@@ -565,7 +569,7 @@ div.stat-box {
|
||||
.stat-box i {
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
font-size: 37px;
|
||||
font-size: 30px;
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@@ -586,6 +590,212 @@ a.stat-box:hover {
|
||||
color:#777;
|
||||
}
|
||||
|
||||
.intro-charts {
|
||||
width: 48vw;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
font-size: 18px;
|
||||
text-align: left;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
color: #3b3b3b;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.chart-title-infos {
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.activity-chart {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(8, 6vw) ;
|
||||
grid-template-rows: repeat(4, 6vw);
|
||||
}
|
||||
|
||||
.activity-chart .row-legend,.activity-chart .col-legend {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.activity-chart .row-legend {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.activity-chart .row-legend div{
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.activity-chart .col-legend {
|
||||
line-height: 6vw;
|
||||
}
|
||||
|
||||
.activity-chart .row-legend:after {
|
||||
content: "";
|
||||
border-top: 2px solid black;
|
||||
opacity: 0.05;
|
||||
position: absolute;
|
||||
width: 700%;
|
||||
transform: translate(6vw,3vw);
|
||||
}
|
||||
|
||||
.activity-chart .col-legend .line-vertical {
|
||||
border-left: 2px solid black;
|
||||
opacity: 0.05;
|
||||
position: absolute;
|
||||
height: 250%;
|
||||
left: 50%;
|
||||
bottom: 100%;
|
||||
}
|
||||
|
||||
.activity-chart span {
|
||||
display: flex;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.activity-chart span div{
|
||||
height: 0px;
|
||||
width: 0px;
|
||||
background-color: #ff5252;
|
||||
opacity: 0.8;
|
||||
display: block;
|
||||
border-radius: 100%;
|
||||
z-index: 100;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.activity-chart span p {
|
||||
position: absolute;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
z-index: 102;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
background-color: white;
|
||||
padding: 5px;
|
||||
width: 150px;
|
||||
box-shadow: 0px 0px 5px #acacac;
|
||||
border-radius: 5px;
|
||||
transform : translate(-50%, 5vw);
|
||||
transition: ease 0.2s;
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.activity-chart span p::after {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
bottom: 100%; /* At the bottom of the tooltip */
|
||||
left: 51%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent white transparent;
|
||||
}
|
||||
|
||||
.activity-chart span div:hover{
|
||||
padding: 0.5vw;
|
||||
}
|
||||
|
||||
.activity-chart span div:hover + p{
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.activity-chart #week-1-legend ~ span div {
|
||||
background-color: #2883c3;
|
||||
}
|
||||
|
||||
.activity-chart #week-2-legend ~ span div {
|
||||
background-color: #896af3 ;
|
||||
}
|
||||
|
||||
.activity-chart #week-3-legend ~ span div {
|
||||
background-color: #6ece5e ;
|
||||
}
|
||||
|
||||
.activity-chart #week-4-legend ~ span div {
|
||||
background-color: #ffa744 ;
|
||||
}
|
||||
|
||||
.storage-chart {
|
||||
border-radius: 5px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
height: 30px;
|
||||
display: flex;
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
|
||||
.storage-chart span{
|
||||
opacity: 0.7;
|
||||
transition: ease 0.2s;
|
||||
}
|
||||
|
||||
.storage-chart span p{
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
color: black;
|
||||
opacity: 0;
|
||||
line-height: 0;
|
||||
transition: ease 0.2s;
|
||||
}
|
||||
|
||||
.storage-chart span:hover{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.storage-chart span:hover p{
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.storage-chart-legend {
|
||||
display: flex
|
||||
}
|
||||
|
||||
.storage-chart-legend div{
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.storage-chart-legend div span{
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
display: block;
|
||||
margin: 5px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.storage-chart span:nth-child(1), .storage-chart-legend div:nth-child(1) span{
|
||||
background-color:#ffa744;
|
||||
}
|
||||
|
||||
.storage-chart span:nth-child(2), .storage-chart-legend div:nth-child(2) span{
|
||||
background-color:#6ece5e;
|
||||
}
|
||||
|
||||
.storage-chart span:nth-child(3), .storage-chart-legend div:nth-child(3) span{
|
||||
background-color:#896af3;
|
||||
}
|
||||
|
||||
.storage-chart span:nth-child(4), .storage-chart-legend div:nth-child(4) span{
|
||||
background-color:#2883c3;
|
||||
}
|
||||
|
||||
.storage-chart span:nth-child(5), .storage-chart-legend div:nth-child(5) span{
|
||||
background-color:#ff5252;
|
||||
}
|
||||
|
||||
#configContent fieldset {
|
||||
border:none;
|
||||
padding-left:20px;
|
||||
|
||||
@@ -232,6 +232,19 @@ a.stat-box:hover {
|
||||
background-color: #555
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.activity-chart span p {
|
||||
background-color: #333333;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.activity-chart span p::after {
|
||||
border-color: transparent transparent #333333 transparent;
|
||||
}
|
||||
|
||||
/* hacks */
|
||||
* html[lang="en"] body .content h2 , *+html[lang="en"] body .content h2 { text-transform:capitalize; } /* IE */
|
||||
*+html .bigtext { left: 70px; }
|
||||
@@ -876,4 +889,4 @@ li.plupload_delete a:hover {background: url("images/cancelhover.svg")!important;
|
||||
.icon-green {
|
||||
background-color: #4ac641;
|
||||
color: #014400;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user