diff --git a/CHANGELOG.md b/CHANGELOG.md index d00b2a1b..4e2f5a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - Cache report data in the browser (using ETag & If-None-Match) #535 - Warn about unsaved changes before leaving a report +- OCS endpoint to create reports from CSV files via files clients ### Fixed - Fix PHP 8.4 deprecation warnings #534 @[robertoschwald](https://github.com/robertoschwald) diff --git a/appinfo/routes.php b/appinfo/routes.php index 369aba94..82de7506 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -25,7 +25,7 @@ ['name' => 'report#update', 'url' => '/report/{reportId}', 'verb' => 'PUT'], ['name' => 'report#rename', 'url' => '/report/{reportId}/rename', 'verb' => 'PUT'], ['name' => 'report#createCopy', 'url' => '/report/copy', 'verb' => 'POST'], - ['name' => 'report#createFromDataFile', 'url' => '/report/file', 'verb' => 'POST'], + //['name' => 'report#createFromDataFile', 'url' => '/report/file/{fileId}', 'verb' => 'POST'], ['name' => 'report#updateOptions', 'url' => '/report/{reportId}/options', 'verb' => 'POST'], ['name' => 'report#updateRefresh', 'url' => '/report/{reportId}/refresh', 'verb' => 'POST'], ['name' => 'report#updateGroup', 'url' => '/report/{reportId}/group', 'verb' => 'POST'], @@ -147,4 +147,4 @@ ['name' => 'whatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'], ['name' => 'whatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'], ] -]; +]; \ No newline at end of file diff --git a/js/sidebar.js b/js/sidebar.js index 5112697b..a190e37e 100644 --- a/js/sidebar.js +++ b/js/sidebar.js @@ -608,6 +608,7 @@ OCA.Analytics.Sidebar.Report = { }); }, + // not used; rework to be done as the fileId is expected now createFromDataFile: function (file = '') { let requestUrl = OC.generateUrl('apps/analytics/report/file'); fetch(requestUrl, { diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index bb696157..34097070 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -17,6 +17,7 @@ use OCA\Analytics\Search\SearchProvider; use OCA\Analytics\Listener\ReferenceListener; use OCA\Analytics\Reference\ReferenceProvider; +use OCA\Analytics\Capabilities; use OCA\ShareReview\Sources\SourceEvent; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; @@ -41,6 +42,8 @@ public function register(IRegistrationContext $context): void { $context->registerSearchProvider(SearchProvider::class); + $context->registerCapability(Capabilities::class); + // file actions are not working at the moment // $context->registerEventListener(LoadAdditionalScriptsEvent::class, LoadAdditionalScripts::class); $context->registerEventListener(UserDeletedEvent::class, UserDeletedListener::class); diff --git a/lib/Capabilities.php b/lib/Capabilities.php new file mode 100644 index 00000000..79d4cbb2 --- /dev/null +++ b/lib/Capabilities.php @@ -0,0 +1,42 @@ +l10n = $l10n; + } + + /** + * Expose the endpoint to create a report from a csv file + */ + public function getCapabilities() { + return [ + 'declarativeui' => [ + Application::APP_ID => [ + 'context-menu' => [ + [ + 'name' => $this->l10n->t('Visualize data in Analytics'), + 'url' => '/ocs/v2.php/apps/analytics/createFromDataFile?fileId={fileId}', + 'method' => 'POST', + 'mimetype_filters' => 'text/csv', + 'bodyParams' => [], + 'icon' => '/apps/analytics/img/app.svg' + ], + ], + ], + ], + ]; + } +} \ No newline at end of file diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php new file mode 100644 index 00000000..b7dffbcf --- /dev/null +++ b/lib/Controller/ApiController.php @@ -0,0 +1,59 @@ +reportService = $reportService; + } + + /** + * Create an analytics report from an existing data file. + * + * @param int $fileId ID of the file to import + * + * @return JSONResponse HTTP 200 with a link to the created report + * + */ + #[NoAdminRequired] + #[NoCSRFRequired] + #[ApiRoute(verb: 'POST', url: '/createFromDataFile')] + public function createFromDataFile(int $fileId): JSONResponse { + $reportId = $this->reportService->createFromDataFile($fileId); + $url = '/apps/analytics/r/' . $reportId; + return new JSONResponse([ + 'version' => 0.1, + 'root' => [ + 'orientation' => 'vertical', + 'rows' => [ + [ + 'children' => [ + [ + 'element' => 'URL', + 'text' => 'Analytics report created', + 'url' => $url, + ], + ], + ], + ], + ], + ]); + } +} diff --git a/lib/Service/ReportService.php b/lib/Service/ReportService.php index 9ddb8019..e4f31749 100644 --- a/lib/Service/ReportService.php +++ b/lib/Service/ReportService.php @@ -234,22 +234,39 @@ public function createCopy(int $reportId, $chartoptions, $dataoptions, $filterop * @param string $file * @return int */ - public function createFromDataFile($file = '') { - $this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_ADD); - - if ($file !== '') { - $name = explode('.', end(explode('/', $file)))[0]; - $subheader = $file; - $parent = 0; - $dataset = 0; - $type = DatasourceController::DATASET_TYPE_LOCAL_CSV; - $link = $file; - $visualization = 'table'; - $chart = 'line'; - $reportId = $this->ReportMapper->create($name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, '', '', ''); - } - return $reportId; - } + /** + * Create a report based on a data file. + * + * @param int|string $file Path to the file or the numeric file ID + * + * @return int ID of the newly created report + */ + public function createFromDataFile($file = '') { + $this->ActivityManager->triggerEvent(0, ActivityManager::OBJECT_REPORT, ActivityManager::SUBJECT_REPORT_ADD); + + $reportId = 0; + + if ($file !== '') { + if (is_numeric($file)) { + $userFolder = $this->rootFolder->getUserFolder($this->userId); + $nodes = $userFolder->getById((int)$file); + if (isset($nodes[0])) { + $file = $userFolder->getRelativePath($nodes[0]->getPath()); + } + } + + $name = explode('.', end(explode('/', $file)))[0]; + $subheader = $file; + $parent = 0; + $dataset = 0; + $type = DatasourceController::DATASET_TYPE_LOCAL_CSV; + $link = $file; + $visualization = 'table'; + $chart = 'line'; + $reportId = $this->ReportMapper->create($name, $subheader, $parent, $type, $dataset, $link, $visualization, $chart, '', '', ''); + } + return $reportId; + } /** * update report details diff --git a/openapi.json b/openapi.json new file mode 100644 index 00000000..479f6251 --- /dev/null +++ b/openapi.json @@ -0,0 +1,59 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Analytics OCS API", + "version": "1.0.0" + }, + "paths": { + "/ocs/v2.php/apps/analytics/createFromDataFile": { + "post": { + "summary": "Create analytics report from a data file", + "operationId": "createFromDataFile", + "tags": ["analytics"], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "fileId": { + "type": "integer", + "description": "ID of the file to import" + } + }, + "required": ["fileId"] + } + } + } + }, + "responses": { + "200": { + "description": "Report created", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "version": {"type": "number"}, + "root": { + "type": "object", + "properties": { + "orientation": {"type": "string"}, + "rows": { + "type": "array", + "items": {"type": "object"} + } + } + } + } + } + } + } + }, + "404": {"description": "File not found"} + } + } + } + } +}