Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
### Added
- Cache report data in the browser (using ETag & If-None-Match) #535
- Warn about unsaved changes before leaving a report
- GitHub Community SLA data source
- Configure excluded authors, repositories, and SLA days via GitHub Community SLA options

### Changed
- Treat issues as triaged when the "0. Needs triage" label is removed or the issue is closed and evaluate open items against the current date in GitHub Community SLA data source
- Use GitHub GraphQL API for more efficient Community SLA queries
- Register GitHub Community SLA data source with ID 9
- Include counter column and use merge/close dates for PR SLA calculation in GitHub Community SLA data source

### Fixed
- Fix PHP 8.4 deprecation warnings #534 @[robertoschwald](https://github.com/robertoschwald)
Expand Down
61 changes: 39 additions & 22 deletions js/visualization.js
Original file line number Diff line number Diff line change
Expand Up @@ -1116,7 +1116,8 @@ OCA.Analytics.Visualization = {

const grouping = tg.grouping;
const mode = tg.mode || 'summation';
const valueIndex = data.data[0].length - 1;
const valueIndex1 = data.data[0].length - 2; // Second last column
const valueIndex2 = data.data[0].length - 1; // Last column

if (data.data.length === 0) {
return data;
Expand Down Expand Up @@ -1161,7 +1162,8 @@ OCA.Analytics.Visualization = {
return myMoment(date).format();
};

const sums = {};
const sums1 = {};
const sums2 = {};
const counts = {};

data.data.forEach(row => {
Expand All @@ -1182,22 +1184,26 @@ OCA.Analytics.Visualization = {
const newRow = row.slice();
newRow[dimension] = newTime;

const key = newRow.slice(0, valueIndex).join('\u0001');
const val = parseFloat(row[valueIndex]) || 0;
const key = newRow.slice(0, valueIndex1).join('\u0001');
const val1 = parseFloat(row[valueIndex1]) || 0;
const val2 = parseFloat(row[valueIndex2]) || 0;

if (!sums[key]) {
sums[key] = val;
if (!sums1[key]) {
sums1[key] = val1;
sums2[key] = val2;
counts[key] = 1;
} else {
sums[key] += val;
sums1[key] += val1;
sums2[key] += val2;
counts[key] += 1;
}
});

data.data = Object.keys(sums).map(key => {
data.data = Object.keys(sums1).map(key => {
const parts = key.split('\u0001');
const value = mode === 'average' ? sums[key] / counts[key] : sums[key];
return [...parts, value.toString()];
const value1 = mode === 'average' ? sums1[key] / counts[key] : sums1[key];
const value2 = mode === 'average' ? sums2[key] / counts[key] : sums2[key];
return [...parts, value1.toString(), value2.toString()];
});

return data;
Expand All @@ -1210,31 +1216,42 @@ OCA.Analytics.Visualization = {
* @returns {Array} Updated rows
*/
formatDates: function (data) {
let firstRow = data[0];
let now;
for (let i = 0; i < firstRow.length; i++) {
// loop columns and check for a valid date
if (!isNaN(new Date(firstRow[i]).valueOf()) && firstRow[i] !== null && firstRow[i].length >= 19) {
// column contains a valid date
// then loop all rows for this column and convert to local time
for (let i = 0; i < data[0].length; i++) {
// Find a valid date in the column
let validDateFound = false;
for (let j = 0; j < data.length; j++) {
if (!isNaN(new Date(data[j][i]).valueOf()) && data[j][i] !== null && data[j][i].length >= 19) {
validDateFound = true;
break;
}
}

// If a valid date is found, convert all dates in the column
if (validDateFound) {
for (let j = 0; j < data.length; j++) {
if (data[j][i].length === 19) {
// values are assumed to have a timezone or are used as UTC
data[j][i] = data[j][i] + 'Z';
}
now = new Date(data[j][i]);
data[j][i] = now.getFullYear()
+ "-" + (now.getMonth() < 9 ? '0' : '') + (now.getMonth() + 1) //getMonth will start with Jan = 0
+ "-" + (now.getDate() < 10 ? '0' : '') + now.getDate()
+ " " + (now.getHours() < 10 ? '0' : '') + now.getHours()
+ ":" + (now.getMinutes() < 10 ? '0' : '') + now.getMinutes()
+ ":" + (now.getSeconds() < 10 ? '0' : '') + now.getSeconds()
if (!isNaN(now.valueOf())) {
data[j][i] = now.getFullYear()
+ "-" + (now.getMonth() < 9 ? '0' : '') + (now.getMonth() + 1)
+ "-" + (now.getDate() < 10 ? '0' : '') + now.getDate()
+ " " + (now.getHours() < 10 ? '0' : '') + now.getHours()
+ ":" + (now.getMinutes() < 10 ? '0' : '') + now.getMinutes()
+ ":" + (now.getSeconds() < 10 ? '0' : '') + now.getSeconds();
} else {
data[j][i] = ''; // Set to empty string if date is invalid
}
}
}
}
return data;
},


/**
* Check a value against threshold rules and return a color style.
*
Expand Down
36 changes: 21 additions & 15 deletions lib/Controller/DatasourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use OCA\Analytics\Datasource\ExternalCsv;
use OCA\Analytics\Datasource\ExternalJson;
use OCA\Analytics\Datasource\Github;
use OCA\Analytics\Datasource\GithubCommunitySla;
use OCA\Analytics\Datasource\LocalCsv;
use OCA\Analytics\Datasource\LocalSpreadsheet;
use OCA\Analytics\Datasource\LocalJson;
Expand All @@ -27,6 +28,7 @@
class DatasourceController extends Controller {
private $logger;
private $GithubService;
private $GithubCommunitySlaService;
private $ExternalCsvService;
private $RegexService;
private $ExternalJsonService;
Expand All @@ -48,26 +50,29 @@ class DatasourceController extends Controller {
const DATASET_TYPE_EXTERNAL_JSON = 6;
const DATASET_TYPE_LOCAL_SPREADSHEET = 7;
const DATASET_TYPE_LOCAL_JSON = 8;
const DATASET_TYPE_GITHUB_COMMUNITY_SLA = 9;

public function __construct(
string $appName,
IRequest $request,
LoggerInterface $logger,
Github $GithubService,
LocalCsv $LocalCsvService,
Regex $RegexService,
ExternalJson $ExternalJsonService,
LocalJson $LocalJsonService,
ExternalCsv $ExternalCsvService,
LocalSpreadsheet $LocalSpreadsheetService,
IL10N $l10n,
IEventDispatcher $dispatcher,
IAppConfig $appConfig,
string $appName,
IRequest $request,
LoggerInterface $logger,
Github $GithubService,
GithubCommunitySla $GithubCommunitySlaService,
LocalCsv $LocalCsvService,
Regex $RegexService,
ExternalJson $ExternalJsonService,
LocalJson $LocalJsonService,
ExternalCsv $ExternalCsvService,
LocalSpreadsheet $LocalSpreadsheetService,
IL10N $l10n,
IEventDispatcher $dispatcher,
IAppConfig $appConfig,
) {
parent::__construct($appName, $request);
$this->logger = $logger;
$this->ExternalCsvService = $ExternalCsvService;
$this->GithubService = $GithubService;
$this->GithubCommunitySlaService = $GithubCommunitySlaService;
$this->RegexService = $RegexService;
$this->LocalCsvService = $LocalCsvService;
$this->ExternalJsonService = $ExternalJsonService;
Expand Down Expand Up @@ -129,7 +134,7 @@ public function getTemplates() {
}

/**
* Get the data from a data source;
* Get the data from a data source;
*
* @NoAdminRequired
* @param int $datasourceId
Expand Down Expand Up @@ -213,6 +218,7 @@ private function getOwnDatasources(?int $datasourceType = null) {
$dataSources = [];
$serviceMapping = [
self::DATASET_TYPE_GIT => $this->GithubService,
self::DATASET_TYPE_GITHUB_COMMUNITY_SLA => $this->GithubCommunitySlaService,
self::DATASET_TYPE_LOCAL_CSV => $this->LocalCsvService,
self::DATASET_TYPE_LOCAL_SPREADSHEET => $this->LocalSpreadsheetService,
self::DATASET_TYPE_EXTERNAL_CSV => $this->ExternalCsvService,
Expand Down Expand Up @@ -283,7 +289,7 @@ private function filterData($data, $filter) {
$filtered[] = $record;
} else if ($filterOption === 'IN') {
preg_match_all("/'(?:[^'\\\\]|\\\\.)*'|[^,;]+/", $filterValue, $matches);
$valuesArray = array_map(function($v) {
$valuesArray = array_map(function ($v) {
return trim($v, " '");
}, $matches[0]);

Expand Down
2 changes: 1 addition & 1 deletion lib/Controller/OutputController.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ private function returnDataWithCacheableHeader($reportMetadata) {
$response = new DataResponse($result, HTTP::STATUS_OK);

// only internal reports are cacheable
if ($reportMetadata['type'] === DatasourceController::DATASET_TYPE_INTERNAL_DB) {
if ($reportMetadata['type'] !== DatasourceController::DATASET_TYPE_INTERNAL_DB) {
$response->addHeader('ETag', '"' . $reportMetadata['version'] . '"');
$response->addHeader('X-Analytics-Cacheable', 'true');
} else {
Expand Down
Loading