From 1e2e6bade49cbd262624989b5a129bb5d9b76b29 Mon Sep 17 00:00:00 2001 From: Lio Novelli Date: Mon, 2 May 2022 13:42:41 +0200 Subject: [PATCH] Add option to output reports. --- README.org | 5 +++ app/src/Commands/RprtCommand.php | 45 ++++++++++++++++--- app/src/Utils/CsvReport/ReportCsv.php | 2 +- app/src/Utils/PdfExport/PdfExportService.php | 2 +- .../TimeTrackingServices/YoutrackService.php | 42 ++++++++++++++++- 5 files changed, 87 insertions(+), 9 deletions(-) diff --git a/README.org b/README.org index 2aa6e9a..187d29b 100644 --- a/README.org +++ b/README.org @@ -50,6 +50,11 @@ *** ValueObjects +*** List my reports + +#+begin_example bash +curl 'https://drunomics.myjetbrains.com/youtrack/api/reports?$top=-1&fields=id,name,own,owner(login,name)&query=owner:+%7Bme%7D' -H "Authorization: Bearer $YTOKEN" -H 'Cache-Control: no-cache' | jq '.[] | select( .own == true )' +#+end_example ** Motivation - practice php diff --git a/app/src/Commands/RprtCommand.php b/app/src/Commands/RprtCommand.php index cb281f6..5fda1b6 100644 --- a/app/src/Commands/RprtCommand.php +++ b/app/src/Commands/RprtCommand.php @@ -75,7 +75,7 @@ class RprtCommand extends Command 'youtrack', 'y', InputOption::VALUE_NONE, - 'Use youtrack api to get a report. If this option is used --file does not have any effect.' + 'Use youtrack api to get a report. If this option is used --file does not have any effect..' ); $this->addOption( 'pdf', @@ -102,7 +102,7 @@ class RprtCommand extends Command 'Send pdf export via email to recipient.' ); $this->addOption( - 'send-to', + 'recipients', 'r', InputOption::VALUE_REQUIRED, 'Comma separated list of recipients that should get the exported pdf.' @@ -121,6 +121,19 @@ class RprtCommand extends Command 'Additional custom work untracked in format: name1=time1;name2=time2... Project to assign work items to has to be configured in app config. Leave empty for interactive output.', FALSE ); + $this->addOption( + 'list-reports', + 'l', + InputOption::VALUE_NONE, + 'List my reports' + ); + $this->addOption( + 'report', + 'g', + InputOption::VALUE_OPTIONAL, + 'Show time tracked for report.', + FALSE + ); } protected function execute(InputInterface $input, OutputInterface $output) : int @@ -129,15 +142,35 @@ class RprtCommand extends Command $test = $this->youtrack->testYoutrackapi(); $output->writeln($test); } + if ($input->getOption('list-reports')) { + $list = $this->youtrack->listReports(); + $output->writeln(var_export($list, TRUE)); + } + if ($input->hasParameterOption('--report') || $input->hasParameterOption('-g')) { + if ($report = $input->getOption('report')) { + $this->youtrack->setReportId($report); + } + else { + $reports = $this->youtrack->listReports(); + $count = 1; + foreach ($reports as $id => $name) { + $output->writeln("[{$count}] {$name} ({$id})"); + $count++; + } + $report = readline('Select id of the report: '); + // Asume people are literate. + $this->youtrack->setReportId($report); + } + } if ($youtrack = $input->getOption('youtrack')) { $report_id = $this->youtrack->getReportId(); $file = $this->youtrack->downloadReport($report_id); } - if ($input->hasParameterOption('expenses') || $input->hasParameterOption('-e')) { - $expenses = $this->getExpenses($input->getOption('expenses')); + if ($input->hasParameterOption('--expenses') || $input->hasParameterOption('-e')) { + $expenses = $this->getCustomWorkOrExpenses($input->getOption('expenses'), self::TYPE_EXPENSE); } - if ($input->hasParameterOption('custom') || $input->hasParameterOption('-c')) { - $custom = $this->getCustomWork($input->getOption('custom')); + if ($input->hasParameterOption('--custom') || $input->hasParameterOption('-c')) { + $custom = $this->getCustomWorkOrExpenses($input->getOption('custom'), self::TYPE_WORK); } if ($youtrack || $file = $input->getOption('file')) { // Youtrack can also provide a file name. diff --git a/app/src/Utils/CsvReport/ReportCsv.php b/app/src/Utils/CsvReport/ReportCsv.php index 35d2068..519f4a1 100644 --- a/app/src/Utils/CsvReport/ReportCsv.php +++ b/app/src/Utils/CsvReport/ReportCsv.php @@ -105,7 +105,7 @@ class ReportCsv implements ReportCsvInterface $hours = $config['time_format'] == 'm' ? $time/60 : $time; $price = $hours * (float) $config['price']; $row = [ - $config['label'] ?? $project, + $config['name'] ?? $project, number_format($hours, 2, ',', '.'), number_format($config['price'], 2, ',', '.'), number_format($price, 2, ',', '.'), diff --git a/app/src/Utils/PdfExport/PdfExportService.php b/app/src/Utils/PdfExport/PdfExportService.php index a9ff713..6ef2185 100644 --- a/app/src/Utils/PdfExport/PdfExportService.php +++ b/app/src/Utils/PdfExport/PdfExportService.php @@ -75,7 +75,7 @@ class PdfExportService implements PdfExportInterface { } if ($colspan) { $colspan += 1; - $cells[] = "{$cell}"; + $cells[] = "{$cell}"; $colspan = 0; } else { diff --git a/app/src/Utils/TimeTrackingServices/YoutrackService.php b/app/src/Utils/TimeTrackingServices/YoutrackService.php index c5cc765..393c06f 100644 --- a/app/src/Utils/TimeTrackingServices/YoutrackService.php +++ b/app/src/Utils/TimeTrackingServices/YoutrackService.php @@ -19,6 +19,8 @@ class YoutrackService implements YoutrackInterface protected $httpClient; + protected $report_id; + public function __construct(ConfigurationInterface $config, ClientInterface $http_client) { $this->config = $config; @@ -50,10 +52,26 @@ class YoutrackService implements YoutrackInterface return NULL; } + protected function requestYoutrackPath(string $path, array $query) { + $yt_url = $this->getYtUrl($path); + $yt_token = $this->getYtToken(); + $headers = [ + "Authorization" => "Bearer $yt_token", + 'Cache-Control' => 'no-cache', + ]; + return $this->httpClient->request('GET', $yt_url, [ + 'query' => $query, + 'headers' => $headers + ]); + } + public function getReportId(): ?string { // --report option value should take precedence. // @TODO error handling. + if (isset($this->report_id)) { + return $this->report_id; + } $yt_report_id = $this->config->get('tracking_service.youtrack.report_id'); if (!$yt_report_id) { $yt_report_id = readline('Enter the report id: '); @@ -61,10 +79,14 @@ class YoutrackService implements YoutrackInterface return $yt_report_id; } + public function setReportId(string $report_id) :void { + $this->report_id = $report_id; + } + public function downloadReport(string $report_id): ?string { $path = "youtrack/api/reports/$report_id/export/csv"; - $query = ['\$top' => -1]; + $query = ['$top' => -1]; $yt_token = $this->getYtToken(); $headers = [ 'Accept' => 'text/plain, */*', @@ -117,4 +139,22 @@ class YoutrackService implements YoutrackInterface public function setYtUrl(string $base_url) { $this->ytBaseUrl = $base_url; } + + public function listReports() { + // Now filter results by own = true; + $url = '/youtrack/api/reports'; + $query = [ + '$top' => -1, + 'fields' => 'id,name,own,owner(login,name)', + ]; + $response = $this->requestYoutrackPath($url, $query); + $body = (string) $response->getBody()->getContents(); + $body_json = (array) json_decode($body); + $my_reports = array_filter($body_json, fn($report) => $report->own); + $reports = array_combine( + array_map(fn($r) => $r->id, $my_reports), + array_map(fn ($r) => $r->name, $my_reports) + ); + return $reports; + } }