Add progress bar for task list and visual status badges

This commit is contained in:
ATM john 2019-08-10 15:41:21 +02:00
parent 22575bb6e7
commit 3f0f7e2ad5
5 changed files with 352 additions and 4 deletions

View File

@ -457,6 +457,9 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
$taskstatic->progress = $lines[$i]->progress;
$taskstatic->fk_statut = $lines[$i]->status;
$taskstatic->datee = $lines[$i]->date_end;
$taskstatic->planned_workload= $lines[$i]->planned_workload;
$taskstatic->duration_effective= $lines[$i]->duration;
if ($showproject)
{
@ -556,10 +559,15 @@ function projectLinesa(&$inc, $parent, &$lines, &$level, $var, $showproject, &$t
print '<td class="right">';
if ($lines[$i]->progress != '')
{
print $lines[$i]->progress.' %';
print getTaskProgressBadge($taskstatic);
}
print '</td>';
// resume
print '<td class="right">';
print getTaskProgressView($taskstatic, false, false);
print '</td>';
if ($showbilltime)
{
// Time not billed
@ -1943,3 +1951,141 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks
print '</table></form>';
}
}
/**
* @param $task Task
* @param $label string|bool true = auto, false = dont display, string = replace output
* @param $progressNumber string|bool true = auto, false = dont display, string = replace output
* @return string
*/
function getTaskProgressView($task, $label = true, $progressNumber = true)
{
global $langs, $conf;
$out = '';
$plannedworkloadoutputformat='allhourmin';
$timespentoutputformat='allhourmin';
if (! empty($conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT)) $plannedworkloadoutputformat=$conf->global->PROJECT_PLANNED_WORKLOAD_FORMAT;
if (! empty($conf->global->PROJECT_TIMES_SPENT_FORMAT)) $timespentoutputformat=$conf->global->PROJECT_TIME_SPENT_FORMAT;
if ($task->progress != '')
{
// define progress color according to time spend vs workload
$progressBarClass = 'progress-bar-info';
if ($task->planned_workload){
$progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2);
// this conf is actually hidden, by default we use 1% for "be carefull or warning"
$warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.01;
if($progressCalculated > doubleval($task->progress)){
$progressBarClass = 'progress-bar-danger';
}
elseif($progressCalculated * $warningRatio >= doubleval($task->progress)){ // warning if close at 1%
$progressBarClass = 'progress-bar-warning';
}
else{
$progressBarClass = 'progress-bar-success';
}
}
$out.= '<div class="progress-group">';
if($label !== false)
{
$out.= ' <span class="progress-text">';
if ($task->hasDelay()) $out.= img_warning($langs->trans("Late")).' ';
if($label!==true){
$out.= $label; // replace label by param
}
else{
$out.= $task->label;
}
$out.= ' </span>';
}
if($progressNumber !== false)
{
$out.= ' <span class="progress-number">';
if($progressNumber!==true){
$out.= $progressNumber; // replace label by param
}
else{
$out.= '<b title="'.$langs->trans('TimeSpent').'" >';
if ($task->duration_effective) $out.= convertSecondToTime($task->duration_effective, $timespentoutputformat);
else $out.= '--:--';
$out.= '</b>';
$out.= '/';
$out.= '<span title="'.$langs->trans('PlannedWorkload').'" >';
if ($task->planned_workload) $out.= convertSecondToTime($task->planned_workload, $plannedworkloadoutputformat);
else $out.= '--:--';
}
$out.= ' </span>';
}
$out.= '</span>';
$out.= ' <div class="progress sm">';
$out.= ' <div title="'.price($task->progress).'%" class="progress-bar '.$progressBarClass.'" style="width: '.doubleval($task->progress).'%"></div>';
$out.= ' </div>';
$out.= '</div>';
}
return $out;
}
/**
* @param $task Task
* @param $label string empty = auto (progress), string = replace output
* @param $tooltip string empty = auto , string = replace output
* @return string
*/
function getTaskProgressBadge($task, $label = '', $tooltip = '')
{
global $conf;
$out = '';
$badgeColorClass = '';
if ($task->progress != '')
{
// define color according to time spend vs workload
$badgeColorClass = 'badge ';
if ($task->planned_workload){
$progressCalculated = round(100 * doubleval($task->duration_effective) / doubleval($task->planned_workload), 2);
// this conf is actually hidden, by default we use 1% for "be carefull or warning"
$warningRatio = !empty($conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT) ? (1 + $conf->global->PROJECT_TIME_SPEND_WARNING_PERCENT / 100) : 1.01;
if($progressCalculated > doubleval($task->progress)){
$badgeColorClass.= 'badge-danger';
}
elseif($progressCalculated * $warningRatio >= doubleval($task->progress)){ // warning if close at 1%
$badgeColorClass.= 'badge-warning';
}
else{
$badgeColorClass.= 'badge-success';
}
}
}
if(empty($label)){
$label = $task->progress.' %';
}
if(!empty($label)){
$out = '<span class="'.$badgeColorClass.'" >'.$label.'</span>';
}
return $out;
}

View File

@ -76,6 +76,7 @@ MyProjects=My projects
MyProjectsArea=My projects Area
DurationEffective=Effective duration
ProgressDeclared=Declared progress
TaskProgressSummary=Task progress
ProgressCalculated=Calculated progress
Time=Time
ListOfTasks=List of tasks

View File

@ -746,9 +746,12 @@ elseif ($id > 0 || ! empty($ref))
print '<input class="flat" type="text" size="4" name="search_progresscalc" value="'.$search_progresscalc.'">';
print '</td>';
print '<td class="liste_titre right">';
print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
print '</td>';
print '<td class="liste_titre right">';
print '<input class="flat" type="text" size="4" name="search_progressdeclare" value="'.$search_progressdeclare.'">';
print '</td>';
// progress resume not searchable
print '<td class="liste_titre right"></td>';
if ($object->bill_time)
{
@ -778,6 +781,7 @@ elseif ($id > 0 || ! empty($ref))
print_liste_field_titre("TimeSpent", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("ProgressCalculated", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("ProgressDeclared", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
print_liste_field_titre("TaskProgressSummary", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');
if ($object->bill_time)
{
print_liste_field_titre("TimeToBill", $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'right ');

View File

@ -405,6 +405,16 @@ textarea.centpercent {
.small, small {
font-size: 85%;
}
.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, h1 .small, h1 small, h2 .small, h2 small, h3 .small, h3 small {
font-size: 65%;
}
.h1 .small, .h1 small, .h2 .small, .h2 small, .h3 .small, .h3 small, .h4 .small, .h4 small, .h5 .small, .h5 small, .h6 .small, .h6 small, h1 .small, h1 small, h2 .small, h2 small, h3 .small, h3 small, h4 .small, h4 small, h5 .small, h5 small, h6 .small, h6 small {
font-weight: 400;
line-height: 1;
color: #777;
}
.center {
text-align: center;
margin: 0px auto;
@ -5750,3 +5760,5 @@ div.tabsElem a.tab {
<?php
include dol_buildpath($path.'/theme/'.$theme.'/dropdown.inc.php', 0);
include dol_buildpath($path.'/theme/'.$theme.'/progress.inc.php', 0);

View File

@ -0,0 +1,185 @@
<?php
if (! defined('ISLOADEDBYSTEELSHEET')) die('Must be call by steelsheet'); ?>
/* <style type="text/css" > */
/*
progress style is based on boostrap and admin lte framework
*/
/*
* Component: Progress Bar
* -----------------------
*/
.progress * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.progress {
height: 20px;
overflow: hidden;
background-color: #f5f5f5;
background-color: rgba(0,0,0,0.1);
border-radius: 4px;
-webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
}
.progress.spaced{
margin-bottom: 20px;
}
.progress-bar {
float: left;
width: 0;
height: 100%;
font-size: 12px;
line-height: 20px;
color: #fff;
text-align: center;
background-color: #337ab7;
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
-webkit-transition: width .6s ease;
-o-transition: width .6s ease;
transition: width .6s ease;
}
.progress-group > .progress{
clear: both;
}
.progress,
.progress > .progress-bar {
-webkit-box-shadow: none;
box-shadow: none;
}
.progress,
.progress > .progress-bar,
.progress .progress-bar,
.progress > .progress-bar .progress-bar {
border-radius: 1px;
}
/* size variation */
.progress.sm,
.progress-sm {
height: 10px;
}
.progress.sm,
.progress-sm,
.progress.sm .progress-bar,
.progress-sm .progress-bar {
border-radius: 1px;
}
.progress.xs,
.progress-xs {
height: 7px;
}
.progress.xs,
.progress-xs,
.progress.xs .progress-bar,
.progress-xs .progress-bar {
border-radius: 1px;
}
.progress.xxs,
.progress-xxs {
height: 3px;
}
.progress.xxs,
.progress-xxs,
.progress.xxs .progress-bar,
.progress-xxs .progress-bar {
border-radius: 1px;
}
/* Vertical bars */
.progress.vertical {
position: relative;
width: 30px;
height: 200px;
display: inline-block;
margin-right: 10px;
}
.progress.vertical > .progress-bar {
width: 100%;
position: absolute;
bottom: 0;
}
.progress.vertical.sm,
.progress.vertical.progress-sm {
width: 20px;
}
.progress.vertical.xs,
.progress.vertical.progress-xs {
width: 10px;
}
.progress.vertical.xxs,
.progress.vertical.progress-xxs {
width: 3px;
}
.progress-group .progress-text {
font-weight: 600;
}
.progress-group .progress-number {
float: right;
}
/* Remove margins from progress bars when put in a table */
.table tr > td .progress {
margin: 0;
}
.progress-bar-light-blue,
.progress-bar-primary {
background-color: #3c8dbc;
}
.progress-striped .progress-bar-light-blue,
.progress-striped .progress-bar-primary {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-bar-green,
.progress-bar-success {
background-color: #00a65a;
}
.progress-striped .progress-bar-green,
.progress-striped .progress-bar-success {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-bar-aqua,
.progress-bar-info {
background-color: #00c0ef;
}
.progress-striped .progress-bar-aqua,
.progress-striped .progress-bar-info {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-bar-yellow,
.progress-bar-warning {
background-color: #f39c12;
}
.progress-striped .progress-bar-yellow,
.progress-striped .progress-bar-warning {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}
.progress-bar-red,
.progress-bar-danger {
background-color: #dd4b39;
}
.progress-striped .progress-bar-red,
.progress-striped .progress-bar-danger {
background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
}