<?php /* ###################################################################### IML DEPLOYMENT class projectlist to render overview page --------------------------------------------------------------------- Axel <axel.hahn@unibe.ch> 2013-11-08 Axel 2024-08-29 Axel php8 only; added variable types; short array syntax ###################################################################### */ require_once 'base.class.php'; require_once 'project_gui.class.php'; require_once("actionlog.class.php"); /** * class for project overview */ class projectlist extends base { // ---------------------------------------------------------------------- // CONFIG // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // constructor // ---------------------------------------------------------------------- /** * constructor2 called from constructor of base class */ public function __construct() { $this->oUser = new user(); } // ---------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // GETTER // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // SETTER // ---------------------------------------------------------------------- // ---------------------------------------------------------------------- // ACTIONS // ---------------------------------------------------------------------- /** * render html for overview table * @return string */ public function renderOverview(): string { global $renderAdminLTE; $sOut = ''; // table $oPrj = false; $sTrClass = "trproject"; $sColClass = "tdphase"; $sNone = 'none'; $oPrj1 = new projectgui(); $oHtml = new htmlguielements(); // TODO :: TIMEFILTER // $oLog = new actionlog(); $sPrjFilter = ''; $sPrjGroupFilter = ''; $sPhaseFilter = ''; $sPrjFilter .= '<option value="">' . t("all") . '</option>'; $sPrjGroupFilter .= '<option value="">' . t("all") . '</option>'; $sPhaseFilter .= '<option value="' . $sColClass . '">' . t("all") . '</option>'; $iInprogress = 0; $iHasqueue = 0; $aPrjGroups = []; $sDivInprogress = '<div class="progressinprogress" title="' . t("progress-inprogress") . '">' . $oHtml->getIcon('refresh') . t("progress-inprogress") . '</div>'; $sDivHasqueue = '<div class="progresshasqueue" title="' . t("progress-hasqueue") . '">' . $oHtml->getIcon('waiting') . t("progress-hasqueue") . '</div>'; $sErrors = ''; // foreach (array_keys($this->_aPhases) as $sPhase) { foreach (array_keys($oPrj1->getPhases()) as $sPhase) { $sPhaseFilter .= '<option value="' . $sPhase . '" >' . $sPhase . '</option>'; } // #6611 Übersichtsseite nach Project Name sortieren // foreach ($oPrj1->getProjects() as $sPrj) { $oPrj = new projectgui(); $aProjectByLabel = $oPrj->getProjects("label"); foreach ($aProjectByLabel as $aProject) { $sPrj = $aProject['id']; $oPrj = new projectgui($sPrj); $sPrjFilter .= '<option value="' . $sPrj . '">' . $aProject['label'] . '</option>'; $sOutPhases = ''; $sOutPhases2 = ''; $sProgress = ''; // loop over phases ... foreach (array_keys($oPrj->getPhases()) as $sPhase) { $sOutPhases .= $oPrj->renderAllPhaseDetails($sPhase, true, false); if ($oPrj->canAcceptPhase($sPhase)) { // $sOutPhases2.=' <span class="'.$sPhase.'" style="padding: 1em 0.5em 0.5em;">'.$oPrj->renderLink("accept", $sPhase).'</span>'; $sOutPhases2 .= ' ' . $oPrj->renderLink("accept", $sPhase); } } $aProgress = $oPrj->getProgress(); $sPrjGroup = $oPrj->getProjectGroup(); $sPrjGroup = $sPrjGroup ? $sPrjGroup : $sNone; $sClasses = $sPrj . ' ' . $sTrClass . ' trprogress' . ($aProgress['inprogress'] ? ' progressinprogress' : '') . ($aProgress['hasQueue'] ? ' progresshasqueue' : '') . (!($aProgress['hasQueue'] || $aProgress['inprogress']) ? ' nochange' : '') . ' group-' . $sPrjGroup; /* TODO :: TIMEFILTER $aLastaction=$oLog->getLastProjectAction($sPrj); $TimeLastAction=isset($aLastaction[0]['time']) ? date('U', strtotime((string)$aLastaction[0]['time'])) : false; if($TimeLastAction){ $iAge = (time() - $TimeLastAction) / 60 / 60 / 24; if($iAge < 7){ $sClasses .= ' time-week'; } if($iAge < 1){ $sClasses .= ' time-today'; } } */ if ($aProgress['inprogress']) { $iInprogress++; $sProgress .= $sDivInprogress; } if ($aProgress['hasQueue']) { $iHasqueue++; $sProgress .= $sDivHasqueue; } if ($sPrjGroup) { $sPrjLabel = $oPrj->getProjectGroupLabel(); $sPrjLabel = $sPrjLabel ? $sPrjLabel : $sNone; if (!isset($aPrjGroups[$sPrjLabel])) { $aPrjGroups[$sPrjLabel] = [ 'id' => $sPrjGroup, 'count' => 1 ]; } else { $aPrjGroups[$sPrjLabel]['count']++; } } $sErrors .= $oPrj->renderErrorBoxes(); // render output $sOut .= ' <tr class="' . $sClasses . '" ' . 'ondblclick="location.href=\'/deployment/' . $sPrj . '/\'" ' . 'title="' . sprintf(t("overview-hint-dblclick"), $sPrj) . '"> <td class="prj"> <span class="float-right"><i class="fa-solid fa-tag"></i> ' . $sPrjGroup . '</span> <strong>' . $oHtml->getLink([ 'href' => '/deployment/' . $sPrj . '/', // 'title' => $oPrj->getDescription(), 'icon' => 'project', 'label' => $oPrj->getLabel() ]) . '</strong>' . '<div class="descr">' . $oPrj->getDescription() . '</div>' . ($sProgress ? '<div class="deployprogress">' . $sProgress . '</div>' : '') // . ' <br>' . '</td>' . '<td class="prj">' . $oHtml->getLinkButton([ 'href' => '#', 'onclick' => 'setProjectFilter(\'' . $sPrj . '\'); return false;', 'style' => 'float: right', 'title' => t("overview-filter-hint"), 'icon' => 'filter', 'label' => t("overview-filter"), ]) . '</td>' . '<td class="prj">'; if ($oPrj->canAcceptPhase()) { $sOut .= $oPrj->renderLink("build"); } $sOut .= '</td> ' . $sOutPhases . ' </tr>'; } if ($sOut) { $sRowHead1 = ''; $sRowHead2 = ''; $aGrouplist = array_keys($aPrjGroups); sort($aGrouplist); $iNone = isset($aPrjGroups[$sNone]['count']) && $aPrjGroups[$sNone]['count'] ? $aPrjGroups[$sNone]['count'] : 0; $sPrjGroupFilter .= ($iNone ? '<option value="none">' . t("none") . ' (' . $iNone . ')</option>' : '') . '<option value="">-----</option>'; foreach ($aGrouplist as $sLabel) { $sId = $aPrjGroups[$sLabel]['id']; $iCount = $aPrjGroups[$sLabel]['count']; $sPrjGroupFilter .= ($sLabel != $sNone) ? '<option value="' . $sId . '">' . $sLabel . ' (' . $iCount . ')</option>' : ''; } foreach (array_keys($oPrj1->getPhases()) as $sPhase) { // Anzahl colspan ist hartcodiert :-/ $sRowHead1 .= '<th class="' . $sPhase . ' ' . $sColClass . '" colspan="3">' . $oHtml->getIcon('phase') . $sPhase . '</th>'; $sRowHead2 .= $oPrj->renderPlacesAsTd($sPhase); } $sOutTop = ' <div id="counter">...</div><br> <div class="filterbar"> <form class="form-inline"> <label for="efilter"> ' . $oHtml->getIcon('filter') . ' ' . t("overview-textsearch") . ': </label> <input type="text" id="efilter" name="efilter" class="form-control" style="width: 200px;" onchange="filterTableByTyping();" onKeypress="filterTableByTyping(); " onKeyup="filterTableByTyping(); " title="' . t("overview-textsearch-hint") . '" > <button class="btn btn-default" onclick="$(\'#efilter\').val(\'' . $this->oUser->getUsername() . '\'); filterTableByTyping(); return false;"> ' . $oHtml->getIcon('user') . $this->oUser->getUsername() . ' </button> <button id="btnresetefilter" class="btn btn-default" onclick="$(\'#efilter\').val(\'\'); filterTableByTyping(); return false;"> ' . $oHtml->getIcon('close') . ' </button> <span style="display: none;"> <label for="progressfilter"> ' . t("overview-filterprogress") . ': </label> <select id="progressfilter" class="form-control" onchange="setprogress(); return false;"> <option value="">' . t("all") . '</option> <option value="inprogress">' . t("progress-inprogress") . '</option> <option value="hasqueue">' . t("progress-hasqueue") . '</option> </select> </span> <div class="btn-group"> <button id="btnProgress" class="btn btn-default prjprogress" onclick="$(\'#progressfilter\').val(\'\'); return setprogress();" >' . t("overview-projectcount") . '<br><span>' . count($oPrj1->getProjects()) . '</span></button> <button id="btnProgressinprogress" class="btn btn-default prjprogress" onclick="$(\'#progressfilter\').val(\'inprogress\'); return setprogress();" >' . $sDivInprogress . '<span>' . $iInprogress . '</span></button> <button id="btnProgresshasqueue" class="btn btn-default prjprogress" onclick="$(\'#progressfilter\').val(\'hasqueue\'); return setprogress();" >' . $sDivHasqueue . '<span>' . $iHasqueue . '</span></button> </div> <!-- TODO :: TIMEFILTER - set buttons - extend js code for filtering public_html/deployment/js/functions_overview.js - lang texts <div class="btn-group"> <button id="btnTimeAll" class="btn btn-default prjtime" onclick="$(\'#progressfilter\').val(\'\'); return setprogress();" >' . t("overview-time-all") . '</button> <button id="btnTimeAll" class="btn btn-default prjtime" onclick="$(\'#progressfilter\').val(\'\'); return setprogress();" >' . t("overview-time-week") . '</button> <button id="btnTimeAll" class="btn btn-default prjtime" onclick="$(\'#progressfilter\').val(\'\'); return setprogress();" >' . t("overview-time-today") . '</button> </div> --> <label for="prjgroupfilter"> ' . t("projectgroup") . ': </label> <select id="prjgroupfilter" class="selectpicker" data-live-search="true" onchange="filterOverviewTable(); return false;"> ' . $sPrjGroupFilter . ' </select> <span style="display: none;"> <span class="view viewextended"> <label for="prjfilter"> ' . t("overview-filterprj") . ': </label> <select id="prjfilter" class="form-control" onchange="filterOverviewTable(); return false;"> ' . $sPrjFilter . ' </select> <span style="display: none;"> <label for="phasefilter">Phasen:</label> <select id="phasefilter" class="form-control" onchange="filterOverviewTable(); return false;"> ' . $sPhaseFilter . ' </select> </span> </span> </span> <input type="hidden" id="rolefilter" value="" /> <!-- <label for="rolefilter"> ' . t("overview-filterrole") . ': </label> <select id="rolefilter" class="form-control" onchange="setrole(); return false;"> <option value="">' . t("all") . '</option> <option value="developer">' . t("developer") . '</option> <option value="pl">' . t("projectmanager") . '</option> </select> --> <a href="#" class="btn btn-danger" id="btnresetfilter" title="' . t("overview-filterreset-hint") . '" onclick="resetFilter();">' . $oHtml->getIcon('close') . t("overview-filterreset") . '</a> </form> <div style="clear: both; margin-bottom: 1em"></div> </div>'; $sOut = $sErrors . ' <table class="table view viewextended" id="tbloverview"> <thead> <tr> <th class="prj" rowspan="2">' . t("project") . '<br><br></th> <th class="prj" rowspan="2"></th> <th class="prj" rowspan="2"></th> ' . $sRowHead1 . ' </tr> <tr> ' . $sRowHead2 . ' </tr> </thead> <tbody> ' . $sOut . '</tbody></table>' ; } else { $sOut = t("class-pl-error-no-project") . '<br><br>' . $oPrj1->renderLink("new"); } $sOut = '' . $renderAdminLTE->addRow( $renderAdminLTE->addCol($sOutTop, 12) ) . $renderAdminLTE->addRow( $renderAdminLTE->addCol( $renderAdminLTE->getCard([ 'type' => '', 'variant' => 'outline', 'text' => $sOut, ]), 12 ) ); return $sOut; } }