diff --git a/root/app/www/public/ajax/code.php b/root/app/www/public/ajax/code.php index 273a3b3..4f26adb 100644 --- a/root/app/www/public/ajax/code.php +++ b/root/app/www/public/ajax/code.php @@ -14,6 +14,9 @@ $labels = $dataFiles = $dataLines = $colors = ''; $usedColors = []; + array_sort_by_key($fileTypes, 'lines', 'desc'); + $fileTypes = array_slice($fileTypes, 0, ($settings['pages']['code']['limit'] ? $settings['pages']['code']['limit'] : 20)); + foreach ($fileTypes as $fileType => $fileTypeData) { $randomColor = randomColor($usedColors); $usedColors[] = $randomColor; diff --git a/root/app/www/public/ajax/contributors.php b/root/app/www/public/ajax/contributors.php index ab6f625..14f1817 100644 --- a/root/app/www/public/ajax/contributors.php +++ b/root/app/www/public/ajax/contributors.php @@ -13,6 +13,7 @@ ?>

Contributors


$graphPointCount) { - $labels .= ($labels ? ', ' : '') . '"' . $graphPointDate . '"'; - $data .= ($data ? ', ' : '') . intval($graphPointCount); + $label = date('M. y', strtotime($graphPointDate . '-1 12:00:00')); + + $labels .= ($labels ? ', ' : '') . '"' . $label . '"'; + $data .= ($data ? ', ' : '') . intval($graphPointCount); } ?>

-
-
-
-
- Commits: /
- - Newest:
- - - Oldest:
- - Files changed:
- Lines added:
- Lines removed:
+
+
+
+
+
+ Commits: /
+ + Newest:
+ + + Oldest:
+ + Files changed:
+ Lines added:
+ Lines removed:
+
-
-
-
-
- +
+
+ + Commit:
+ Date:
+
  • ', array_slice($newestCommit, 3)) ?>
+ No commit information found. - Commit:
- Date:
-
  • ', array_slice($newestCommit, 3)) ?>
- No commit information found. +
-
-
-
-
- +
+
+
+ +
@@ -163,5 +172,4 @@
($newest + $oldest)) { + $newestCommits = $oldestCommits = []; + $hidden = count($commits) - ($newest + $oldest); + $newestCommits = array_slice($commits, 0, $newest); + $oldestCommits = array_slice($commits, ($oldest * -1)); + + $commits = []; + foreach ($newestCommits as $newestCommit) { + $commits[] = $newestCommit; + } + foreach ($oldestCommits as $oldestCommit) { + $commits[] = $oldestCommit; + } + } + $display = ''; - foreach ($overview['shell'] as $line) { - list($tree, $stuff) = explode('{', $line); + foreach ($commits as $commitIndex => $commit) { + list($tree, $stuff) = explode('{', $commit); $display .= '' . str_pad($tree, $treeSpacing, ' ', STR_PAD_RIGHT) . ''; - $details = str_replace($tree, '', $line); + $details = str_replace($tree, '', $commit); $details = preg_match($regex, $details, $matches); $hash = str_replace('hash:', '', $matches['hash']); $date = str_replace('date:', '', $matches['date']); @@ -76,6 +96,22 @@ $display .= str_pad($email, ($emailSpacing - strlen($author)), ' ', STR_PAD_RIGHT); $display .= ' ' . trim($branch) . ' ' . str_replace('note:', '', $matches['note']); $display .= '
'; + + if ($hidden > 0 && ($commitIndex + 1) == $newest) { + $hiddenLine = '~~~~~~~~~~~~~~~[ Truncated commits: ' . $hidden . ' ]~~~~~~~~~~~~~~~'; + + $display .= '
'; + for ($x = 0; $x < strlen($hiddenLine) + 2; $x++) { + $display .= '~'; + } + + $display .= '
' . $hiddenLine . '
'; + + for ($x = 0; $x < strlen($hiddenLine) + 2; $x++) { + $display .= '~'; + } + $display .= '

'; + } } ?> @@ -96,7 +132,7 @@
Objects
-

+

Size
diff --git a/root/app/www/public/ajax/settings.php b/root/app/www/public/ajax/settings.php index f574695..f020914 100644 --- a/root/app/www/public/ajax/settings.php +++ b/root/app/www/public/ajax/settings.php @@ -15,7 +15,6 @@ ?> - @@ -23,11 +22,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -44,11 +71,13 @@ $field = $key; if (str_contains($field, '-')) { - list($cat, $field) = explode('-', $key); + $keyParts = explode('-', $key); } - if ($cat) { - $settings[$cat][$field] = $val; + if (count($keyParts) == 3) { + $settings[$keyParts[0]][$keyParts[1]][$keyParts[2]] = $val; + } elseif (count($keyParts) == 2) { + $settings[$keyParts[0]][$keyParts[1]] = $val; } else { $settings[$field] = $val; } diff --git a/root/app/www/public/ajax/shared.php b/root/app/www/public/ajax/shared.php index 813bc10..b99fd7c 100644 --- a/root/app/www/public/ajax/shared.php +++ b/root/app/www/public/ajax/shared.php @@ -18,35 +18,45 @@ } require ABSOLUTE_PATH . 'loader.php'; -$repository = $_POST['repository']; -$git = new Git($repository); -$repoSize = $git->size(); -$overview = $git->log(); -$branches = $git->branches(); -$contributors = $git->contributors(); -$totalFiles = $git->totalFiles(); -$totalCommits = $git->totalCommits(); -$totalLines = $git->totalLines(); -$branchHeads = $git->branchHeads(); -$linesOfCode = 0; -$fileTypes = []; +$repository = $_POST['repository']; +$git = new Git($repository); -list($objects, $size) = explode(',', $repoSize['shell'][0]); -$repoObjects = preg_replace("/[^0-9]/", '', $objects); -$repoSize = trim($size); +if ($_POST['page'] != 'settings') { + $repoObjects = $git->size(); + $overview = $git->log(); + $branches = $git->branches(); + $contributors = $git->contributors(); + $totalFiles = $git->totalFiles(); + $totalCommits = $git->totalCommits(); + $totalLines = $git->totalLines(); + $branchHeads = $git->branchHeads(); + $linesOfCode = 0; + $fileTypes = []; -foreach ($totalLines['shell'] as $file) { - $fileParts = array_filter(explode(' ', $file)); - sort($fileParts, SORT_NUMERIC); - $linesOfCode += intval($fileParts[1]); - - if (str_contains($fileParts[0], '.') && $fileParts[0][0] != '.' && !is_dir(ABSOLUTE_PATH . $repository . '.' . $fileParts[0][0])) { - $filePathParts = explode('.', $fileParts[0]); - $extension = trim(end($filePathParts)); + foreach ($repoObjects['shell'] as $repoSizeObject) { + if (str_contains($repoSizeObject, 'count') || str_contains($repoSizeObject, 'in-pack')) { + $repoObjectCount += preg_replace("/[^0-9]/", '', $repoSizeObject); + } + if (str_contains($repoSizeObject, 'size') || str_contains($repoSizeObject, 'size-pack')) { + $repoSizeTotal += preg_replace("/[^0-9]/", '', $repoSizeObject); + } + } + $repoObjects = number_format(intval($repoObjectCount)); + $repoSize = byteConversion(intval($repoSizeTotal) * 1000); - if (!str_contains($extension, '/') && $extension) { - $fileTypes[$extension]['files']++; - $fileTypes[$extension]['lines'] += intval($fileParts[1]); + foreach ($totalLines['shell'] as $file) { + $fileParts = array_filter(explode(' ', $file)); + sort($fileParts, SORT_NUMERIC); + $linesOfCode += intval($fileParts[1]); + + if (str_contains($fileParts[0], '.') && $fileParts[0][0] != '.' && !is_dir(ABSOLUTE_PATH . $repository . '.' . $fileParts[0][0])) { + $filePathParts = explode('.', $fileParts[0]); + $extension = trim(end($filePathParts)); + + if (!in_array($extension, $ignoreCodePageExtensions) && !str_contains($extension, '/') && $extension) { + $fileTypes[$extension]['files']++; + $fileTypes[$extension]['lines'] += intval($fileParts[1]); + } } } } diff --git a/root/app/www/public/assets/js/misc.js b/root/app/www/public/assets/js/misc.js new file mode 100644 index 0000000..ae8e4e8 --- /dev/null +++ b/root/app/www/public/assets/js/misc.js @@ -0,0 +1,110 @@ +(function($) { + 'use strict'; + $(function() { + var body = $('body'); + var contentWrapper = $('.content-wrapper'); + var scroller = $('.container-scroller'); + var footer = $('.footer'); + var sidebar = $('.sidebar'); + + //Add active class to nav-link based on url dynamically + //Active class can be hard coded directly in html file also as required + + function addActiveClass(element) { + if (current === "") { + //for root url + if (element.attr('href').indexOf("index.html") !== -1) { + element.parents('.nav-item').last().addClass('active'); + if (element.parents('.sub-menu').length) { + element.closest('.collapse').addClass('show'); + element.addClass('active'); + } + } + } else { + //for other url + if (element.attr('href').indexOf(current) !== -1) { + element.parents('.nav-item').last().addClass('active'); + if (element.parents('.sub-menu').length) { + element.closest('.collapse').addClass('show'); + element.addClass('active'); + } + if (element.parents('.submenu-item').length) { + element.addClass('active'); + } + } + } + } + + var current = location.pathname.split("/").slice(-1)[0].replace(/^\/|\/$/g, ''); + $('.nav li a', sidebar).each(function() { + var $this = $(this); + addActiveClass($this); + }) + + $('.horizontal-menu .nav li a').each(function() { + var $this = $(this); + addActiveClass($this); + }) + + //Close other submenu in sidebar on opening any + + sidebar.on('show.bs.collapse', '.collapse', function() { + sidebar.find('.collapse.show').collapse('hide'); + }); + + + //Change sidebar and content-wrapper height + applyStyles(); + + function applyStyles() { + //Applying perfect scrollbar + if (!body.hasClass("rtl")) { + if ($('.settings-panel .tab-content .tab-pane.scroll-wrapper').length) { + const settingsPanelScroll = new PerfectScrollbar('.settings-panel .tab-content .tab-pane.scroll-wrapper'); + } + if ($('.chats').length) { + const chatsScroll = new PerfectScrollbar('.chats'); + } + if (body.hasClass("sidebar-fixed")) { + var fixedSidebarScroll = new PerfectScrollbar('#sidebar .nav'); + } + } + } + + $('[data-toggle="minimize"]').on("click", function() { + if ((body.hasClass('sidebar-toggle-display')) || (body.hasClass('sidebar-absolute'))) { + body.toggleClass('sidebar-hidden'); + } else { + body.toggleClass('sidebar-icon-only'); + } + }); + + //checkbox and radios + $(".form-check label,.form-radio label").append(''); + + //fullscreen + $("#fullscreen-button").on("click", function toggleFullScreen() { + if ((document.fullScreenElement !== undefined && document.fullScreenElement === null) || (document.msFullscreenElement !== undefined && document.msFullscreenElement === null) || (document.mozFullScreen !== undefined && !document.mozFullScreen) || (document.webkitIsFullScreen !== undefined && !document.webkitIsFullScreen)) { + if (document.documentElement.requestFullScreen) { + document.documentElement.requestFullScreen(); + } else if (document.documentElement.mozRequestFullScreen) { + document.documentElement.mozRequestFullScreen(); + } else if (document.documentElement.webkitRequestFullScreen) { + document.documentElement.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (document.documentElement.msRequestFullscreen) { + document.documentElement.msRequestFullscreen(); + } + } else { + if (document.cancelFullScreen) { + document.cancelFullScreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitCancelFullScreen) { + document.webkitCancelFullScreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } + } + }) + }); +})(jQuery); \ No newline at end of file diff --git a/root/app/www/public/classes/Git.php b/root/app/www/public/classes/Git.php index 5ed00d9..93aae20 100644 --- a/root/app/www/public/classes/Git.php +++ b/root/app/www/public/classes/Git.php @@ -26,11 +26,15 @@ class Git public $cd; public $repository; + public $ignoreDirectories; public function __construct($repository) { - $this->repository = $repository; - $this->cd = 'cd ' . $this->repository .' && '; + global $ignoreDirectories; + + $this->repository = $repository; + $this->cd = 'cd ' . $this->repository .' && '; + $this->ignoreDirectories = $ignoreDirectories; } public function __toString() @@ -64,9 +68,9 @@ public function clone($repository, $folder) public function size() { - $cmd = $this->cd . 'git count-objects -H'; + $cmd = $this->cd . 'git count-objects -vH'; $shell = explode("\n", shell_exec($cmd)); - + return ['cmd' => $cmd, 'shell' => array_filter($shell)]; } } diff --git a/root/app/www/public/classes/traits/Git/Files.php b/root/app/www/public/classes/traits/Git/Files.php index 953953d..3004335 100644 --- a/root/app/www/public/classes/traits/Git/Files.php +++ b/root/app/www/public/classes/traits/Git/Files.php @@ -11,15 +11,33 @@ trait Files { public function totalFiles() { - $cmd = $this->cd . 'git ls-files | wc -l'; + $grepExcludeDirectories = ''; + if ($this->ignoreDirectories) { + foreach ($this->ignoreDirectories as $directory) { + $grepExcludeDirectories .= ($grepExcludeDirectories ? '|' : '') . $directory . '/*'; + } + + $grepExcludeDirectories = '| grep -v -E "' . $grepExcludeDirectories . '" '; + } + + $cmd = $this->cd . 'git ls-files ' . $grepExcludeDirectories . '| wc -l'; $shell = shell_exec($cmd); return ['cmd' => $cmd, 'shell' => $shell]; } - + public function totalLines() { - $cmd = $this->cd . 'git ls-files | xargs wc -l'; + $grepExcludeDirectories = ''; + if ($this->ignoreDirectories) { + foreach ($this->ignoreDirectories as $directory) { + $grepExcludeDirectories .= ($grepExcludeDirectories ? '|' : '') . $directory . '/*'; + } + + $grepExcludeDirectories = '| grep -v -E "' . $grepExcludeDirectories . '" '; + } + + $cmd = $this->cd . 'git ls-files ' . $grepExcludeDirectories . '| xargs wc -l'; $shell = explode("\n", shell_exec($cmd)); return ['cmd' => $cmd, 'shell' => $shell]; diff --git a/root/app/www/public/functions/common.php b/root/app/www/public/functions/common.php index 807ecfd..f89cd0a 100644 --- a/root/app/www/public/functions/common.php +++ b/root/app/www/public/functions/common.php @@ -86,3 +86,18 @@ function byteConversion($bytes, $measurement = false, $dec = 2) return round($bytes / pow(1024, 4), $dec); } } + +function array_sort_by_key(&$array, $field, $direction = 'asc') +{ + if (!is_array($array)) { + return $array; + } + + uasort($array, function ($a, $b) use ($field, $direction) { + if ($direction == 'asc') { + return $a[$field] <=> $b[$field]; + } else { + return $b[$field] <=> $a[$field]; + } + }); +} diff --git a/root/app/www/public/includes/constants.php b/root/app/www/public/includes/constants.php index d818a70..cec984d 100644 --- a/root/app/www/public/includes/constants.php +++ b/root/app/www/public/includes/constants.php @@ -9,3 +9,6 @@ define('APP_DATA_PATH', '/config/'); define('SETTINGS_FILE', APP_DATA_PATH . 'settings.json'); + +$ignoreCodePageExtensions = ['txt', 'json', 'yml', 'tgz', 'zip', 'sql']; +$ignoreDirectories = ['assets', 'vendor', 'libraries', 'node_modules']; diff --git a/root/app/www/public/includes/footer.php b/root/app/www/public/includes/footer.php index 5adecb2..5775f89 100644 --- a/root/app/www/public/includes/footer.php +++ b/root/app/www/public/includes/footer.php @@ -37,6 +37,7 @@ + diff --git a/root/app/www/public/js/common.js b/root/app/www/public/js/common.js index 7bd5b79..2291af1 100644 --- a/root/app/www/public/js/common.js +++ b/root/app/www/public/js/common.js @@ -15,7 +15,7 @@ function loadPage(page) $.ajax({ type: 'POST', url: 'ajax/' + page + '.php', - data: '&m=init&repository=' + repository, + data: '&m=init&repository=' + repository + '&page=' + page, success: function (resultData) { $('#page-content').html(resultData); } @@ -108,6 +108,7 @@ function checkoutBranch() function loadRepositoryBranches() { const repository = $('#active-repository').val(); + $('#page-content').html(' Gathering all the data, crunching all the numbers...'); $.ajax({ type: 'POST', diff --git a/root/app/www/public/loader.php b/root/app/www/public/loader.php index 98bcd98..4f30a13 100644 --- a/root/app/www/public/loader.php +++ b/root/app/www/public/loader.php @@ -33,6 +33,8 @@ } } define('REPOSITORY_PATH', ($settings['global']['repositoryPath'] ? $settings['global']['repositoryPath'] : '/config/repositories/')); +$ignoreCodePageExtensions = $settings['pages']['code']['ignoreExtension'] ? explode(',', str_replace(' ', '', $settings['pages']['code']['ignoreExtension'])) : $ignoreCodePageExtensions; +$ignoreDirectories = $settings['global']['ignoreDirectories'] ? explode(',', str_replace(' ', '', $settings['global']['ignoreDirectories'])) : $ignoreDirectories; //-- INCLUDE FUNCTIONS $dir = ABSOLUTE_PATH . 'functions';
Global
Setting Value
Global
Repository location This is the location of all git repositories to load and use
IgnoreIgnore these directories for all calculations
Page: Overview
Display newestAmount of commits (newest) to show
Display oldestAmount of commits (oldest) to show
Page: Code
LimitHow many different file types to show
IgnoreIgnore these file types when generating the graphs