From acaa2cd3abdeb647bbd69efea86355652637fb65 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Mon, 29 Apr 2024 14:47:24 +0300 Subject: [PATCH 01/14] feat: file actions redirect, v2 api version Signed-off-by: Andrey Borysenko --- CHANGELOG.md | 1 + appinfo/info.xml | 2 +- appinfo/routes.php | 1 + docs/tech_details/api/fileactionsmenu.rst | 41 +++++++++- lib/Controller/OCSUiController.php | 23 +++++- lib/Db/UI/FilesActionsMenu.php | 8 ++ .../Version2206Date20240502145029.php | 37 +++++++++ lib/Service/UI/FilesActionsMenuService.php | 4 +- src/filesplugin28.js | 82 +++++++++++++------ 9 files changed, 167 insertions(+), 32 deletions(-) create mode 100644 lib/Migration/Version2206Date20240502145029.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 00a8c768..1a4c0d28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Test deploy button in Admin settings for each Daemon configuration. #279 +- File Actions option to redirect to the ExApp Top Menu (UI) page with the selected file context. #280 ## [2.5.0 - 2024-04-23] diff --git a/appinfo/info.xml b/appinfo/info.xml index 236f15ad..d17f5921 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -43,7 +43,7 @@ to join us in shaping a more versatile, stable, and secure app landscape. *Your insights, suggestions, and contributions are invaluable to us.* ]]> - 2.5.1 + 2.6.0 agpl Andrey Borysenko Alexander Piskun diff --git a/appinfo/routes.php b/appinfo/routes.php index bac06c48..9e08a6e2 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -99,6 +99,7 @@ // --- UI --- // File Actions Menu ['name' => 'OCSUi#registerFileActionMenu', 'url' => '/api/v1/ui/files-actions-menu', 'verb' => 'POST'], + ['name' => 'OCSUi#registerFileActionMenuV2', 'url' => '/api/v2/ui/files-actions-menu', 'verb' => 'POST'], ['name' => 'OCSUi#unregisterFileActionMenu', 'url' => '/api/v1/ui/files-actions-menu', 'verb' => 'DELETE'], ['name' => 'OCSUi#getFileActionMenu', 'url' => '/api/v1/ui/files-actions-menu', 'verb' => 'GET'], diff --git a/docs/tech_details/api/fileactionsmenu.rst b/docs/tech_details/api/fileactionsmenu.rst index a3a70a51..0b7e1c46 100644 --- a/docs/tech_details/api/fileactionsmenu.rst +++ b/docs/tech_details/api/fileactionsmenu.rst @@ -25,12 +25,13 @@ Complete list of params (including optional): { "name": "unique_name_of_file_actions_menu", - "displayName": "Display name (for UI listing)", - "actionHandler": "/action_handler_route" + "display_name": "Display name (for UI listing)", + "action_handler": "/action_handler_route" "mime": "mime of files where to display action menu", "icon": "img/icon.svg", "permissions": "permissions", "order": "order_in_file_actions_menu", + "version": "1.0" } .. note:: Urls ``icon`` and ``actionHandler`` are relative to the ExApp root, starting slash is not required. @@ -90,6 +91,38 @@ The following data is sent to ExApp FileActionsMenu handler from the context of "instanceId": "string", } +Redirect to ExApp UI page (top menu) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: + Supported in Nextcloud 28+. + +If you want to open some file in ExApp UI, you need to set ``version`` to ``2.0``` in the FileActionsMenu registration. + +.. code-block:: json + + { + "name": "unique_name_of_file_actions_menu", + "display_name": "Display name (for UI listing)", + "action_handler": "/action_handler_route" + "mime": "mime of files where to display action menu", + "icon": "img/icon.svg", + "permissions": "permissions", + "order": "order_in_file_actions_menu", + "version": "2.0" + } + +After that, AppAPI will expect in the JSON response of the ExApp ``action_handler`` +the ``redirect_handler`` - a relative path on the ExApp Top Menu page, +to which AppAPI will attach a ``fileIds`` query parameter with the selected file ids, for example: + +``/index.php/apps/app_api/embedded/ui_example/first_menu/second_page?fileIds=123,124,125``, + +where the ``first_menu`` is the name of the Top Menu ExApp UI page, +and the ``second_page`` relative route handled on the frontend routing of the ExApp, +the ``fileIds`` query parameter contains the selected file ids separated by commas. +After that you can get the files info via webdav search request, see `ui_example `_. + Request flow ^^^^^^^^^^^^ @@ -126,5 +159,5 @@ Examples Here is a list of simple example ExApps based on FileActionsMenu: -* `video_to_gif `_ - ExApp based on FileActionsMenu to convert videos to gif in place -* `upscaler_demo `_ - ExApp based on FileActionsMenu to upscale image in place +* `to_gif `_ - ExApp based on FileActionsMenu to convert videos to gif in place +* `upscaler_example `_ - ExApp based on FileActionsMenu to upscale image in place diff --git a/lib/Controller/OCSUiController.php b/lib/Controller/OCSUiController.php index 56a52c5b..8601938d 100644 --- a/lib/Controller/OCSUiController.php +++ b/lib/Controller/OCSUiController.php @@ -38,15 +38,34 @@ public function __construct( /** * @throws OCSBadRequestException + * + * @depreacted since AppAPI 2.6.0, use registerFileActionMenuV2 instead */ #[AppAPIAuth] #[PublicPage] #[NoCSRFRequired] public function registerFileActionMenu(string $name, string $displayName, string $actionHandler, string $icon = "", string $mime = "file", int $permissions = 31, - int $order = 0): DataResponse { + int $order = 0, string $version = '1.0'): DataResponse { $result = $this->filesActionsMenuService->registerFileActionMenu( - $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order); + $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, $version); + if (!$result) { + throw new OCSBadRequestException("File Action Menu entry could not be registered"); + } + return new DataResponse(); + } + + /** + * @throws OCSBadRequestException + */ + #[AppAPIAuth] + #[PublicPage] + #[NoCSRFRequired] + public function registerFileActionMenuV2(string $name, string $displayName, string $actionHandler, + string $icon = "", string $mime = "file", int $permissions = 31, + int $order = 0, string $version = '2.0'): DataResponse { + $result = $this->filesActionsMenuService->registerFileActionMenu( + $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, $version); if (!$result) { throw new OCSBadRequestException("File Action Menu entry could not be registered"); } diff --git a/lib/Db/UI/FilesActionsMenu.php b/lib/Db/UI/FilesActionsMenu.php index 17d058aa..124c4a12 100644 --- a/lib/Db/UI/FilesActionsMenu.php +++ b/lib/Db/UI/FilesActionsMenu.php @@ -20,6 +20,7 @@ * @method int getOrder() * @method string getIcon() * @method string getActionHandler() + * @method string getVersion() * @method void setAppid(string $appid) * @method void setName(string $name) * @method void setDisplayName(string $displayName) @@ -28,6 +29,7 @@ * @method void setOrder(int $order) * @method void setIcon(string $icon) * @method void setActionHandler(string $actionHandler) + * @method void setVersion(string $version) */ class FilesActionsMenu extends Entity implements JsonSerializable { protected $appid; @@ -38,6 +40,7 @@ class FilesActionsMenu extends Entity implements JsonSerializable { protected $order; protected $icon; protected $actionHandler; + protected $version; /** * @param array $params @@ -51,6 +54,7 @@ public function __construct(array $params = []) { $this->addType('order', 'int'); $this->addType('icon', 'string'); $this->addType('actionHandler', 'string'); + $this->addType('version', 'string'); if (isset($params['id'])) { $this->setId($params['id']); @@ -79,6 +83,9 @@ public function __construct(array $params = []) { if (isset($params['action_handler'])) { $this->setActionHandler($params['action_handler']); } + if (isset($params['version'])) { + $this->setVersion($params['version']); + } } public function jsonSerialize(): array { @@ -92,6 +99,7 @@ public function jsonSerialize(): array { 'order' => $this->getOrder(), 'icon' => $this->getIcon(), 'action_handler' => $this->getActionHandler(), + 'version' => $this->getVersion(), ]; } } diff --git a/lib/Migration/Version2206Date20240502145029.php b/lib/Migration/Version2206Date20240502145029.php new file mode 100644 index 00000000..fe8b948a --- /dev/null +++ b/lib/Migration/Version2206Date20240502145029.php @@ -0,0 +1,37 @@ +hasTable('ex_ui_files_actions')) { + $table = $schema->getTable('ex_ui_files_actions'); + + $table->addColumn('version', Types::STRING, [ + 'notnull' => true, + 'length' => 64, + 'default' => '1.0', + ]); + } + + return $schema; + } +} diff --git a/lib/Service/UI/FilesActionsMenuService.php b/lib/Service/UI/FilesActionsMenuService.php index 5e6eacdb..693f1f2a 100644 --- a/lib/Service/UI/FilesActionsMenuService.php +++ b/lib/Service/UI/FilesActionsMenuService.php @@ -36,10 +36,11 @@ public function __construct( * @param string $mime * @param int $permissions * @param int $order + * @param string $version * @return FilesActionsMenu|null */ public function registerFileActionMenu(string $appId, string $name, string $displayName, string $actionHandler, - string $icon, string $mime, int $permissions, int $order): ?FilesActionsMenu { + string $icon, string $mime, int $permissions, int $order, string $version): ?FilesActionsMenu { try { $fileActionMenu = $this->mapper->findByAppidName($appId, $name); } catch (DoesNotExistException|MultipleObjectsReturnedException|Exception) { @@ -55,6 +56,7 @@ public function registerFileActionMenu(string $appId, string $name, string $disp 'mime' => $mime, 'permissions' => $permissions, 'order' => $order, + 'version' => $version, ]); if ($fileActionMenu !== null) { $newFileActionMenu->setId($fileActionMenu->getId()); diff --git a/src/filesplugin28.js b/src/filesplugin28.js index 7832f656..72a0d66f 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -6,6 +6,7 @@ import { getCurrentUser } from '@nextcloud/auth' import { translate as t } from '@nextcloud/l10n' const state = loadState('app_api', 'ex_files_actions_menu') +console.debug('ex_files_actions_menu', state) function loadStaticAppAPIInlineSvgIcon() { return '' @@ -29,6 +30,10 @@ function generateAppAPIProxyUrl(appId, route) { return generateUrl(`/apps/app_api/proxy/${appId}/${route}`) } +function generateExAppUIPageUrl(appId, route) { + return generateUrl(`/apps/app_api/embedded/${appId}/${route}`) +} + function registerFileAction28(fileAction, inlineSvgIcon) { const action = new FileAction({ id: fileAction.name, @@ -61,32 +66,39 @@ function registerFileAction28(fileAction, inlineSvgIcon) { }, async exec(node, view, dir) { const exAppFileActionHandler = generateAppAPIProxyUrl(fileAction.appid, fileAction.action_handler) - return axios.post(exAppFileActionHandler, { - fileId: node.fileid, - name: node.basename, - directory: node.dirname, - etag: node.attributes.etag, - mime: node.mime, - favorite: Boolean(node.attributes.favorite).toString(), - permissions: node.permissions, - fileType: node.type, - size: Number(node.size), - mtime: new Date(node.mtime).getTime() / 1000, // convert ms to s - shareTypes: node.attributes.shareTypes || null, - shareAttributes: node.attributes.shareAttributes || null, - sharePermissions: node.attributes.sharePermissions || null, - shareOwner: node.attributes.ownerDisplayName || null, - shareOwnerId: node.attributes.ownerId || null, - userId: getCurrentUser().uid, - instanceId: state.instanceId, - }).then((response) => { - return true - }).catch((error) => { - console.error('Failed to send FileAction request to ExApp', error) - return false - }) + return axios.post(exAppFileActionHandler, buildNodeInfo(node)) + .then((response) => { + if ('redirect_handler' in response.data) { + const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) + window.location.assign(`${redirectPage}?fileIds=${fileIds}`) + return true + } + return true + }).catch((error) => { + console.error('Failed to send FileAction request to ExApp', error) + return false + }) }, async execBatch(nodes, view, dir) { + if ('version' in fileAction && fileAction.version === '2.0') { + const exAppFileActionHandler = generateAppAPIProxyUrl(fileAction.appid, fileAction.action_handler) + const nodesDataList = nodes.map(buildNodeInfo) + return axios.post(exAppFileActionHandler, { files: nodesDataList }) + .then((response) => { + if ('redirect_handler' in response.data) { + const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) + const fileIds = nodes.map((node) => node.fileid).join(',') + window.location.assign(`${redirectPage}?fileIds=${fileIds}`) + return true + } + return true + }) + .catch((error) => { + console.error('Failed to send FileAction request to ExApp', error) + return false + }) + } + // for version 1.0 behavior is not changed return Promise.all(nodes.map((node) => { return this.exec(node, view, dir) })) @@ -95,6 +107,28 @@ function registerFileAction28(fileAction, inlineSvgIcon) { registerFileAction(action) } +function buildNodeInfo(node) { + return { + fileId: node.fileid, + name: node.basename, + directory: node.dirname, + etag: node.attributes.etag, + mime: node.mime, + favorite: Boolean(node.attributes.favorite).toString(), + permissions: node.permissions, + fileType: node.type, + size: Number(node.size), + mtime: new Date(node.mtime).getTime() / 1000, // convert ms to s + shareTypes: node.attributes.shareTypes || null, + shareAttributes: node.attributes.shareAttributes || null, + sharePermissions: node.attributes.sharePermissions || null, + shareOwner: node.attributes.ownerDisplayName || null, + shareOwnerId: node.attributes.ownerId || null, + userId: getCurrentUser().uid, + instanceId: state.instanceId, + } +} + document.addEventListener('DOMContentLoaded', () => { state.fileActions.forEach(fileAction => { if (fileAction.icon === '') { From 4d874026f5a65a6afad96f6361058549fb5ac27e Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 09:27:23 +0300 Subject: [PATCH 02/14] remove debug log Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index 72a0d66f..bb5715ec 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -6,7 +6,6 @@ import { getCurrentUser } from '@nextcloud/auth' import { translate as t } from '@nextcloud/l10n' const state = loadState('app_api', 'ex_files_actions_menu') -console.debug('ex_files_actions_menu', state) function loadStaticAppAPIInlineSvgIcon() { return '' From ff70ebd95b31038c0edbf24bbfcbaeef474d3045 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 09:27:52 +0300 Subject: [PATCH 03/14] update changelog Signed-off-by: Andrey Borysenko --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a4c0d28..040ec458 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2.6.0 - 2024-05-xx] + +### Added + +- Added File Actions v2 version with redirect to the ExApp UI. #284 + ## [2.5.1 - 2024-05-02] ### Added From 687bcf4ad74039c0b6bbe0f3a8d70f066c83321b Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 09:32:14 +0300 Subject: [PATCH 04/14] fix undefined variable Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index bb5715ec..d35df3e2 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -69,7 +69,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { .then((response) => { if ('redirect_handler' in response.data) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) - window.location.assign(`${redirectPage}?fileIds=${fileIds}`) + window.location.assign(`${redirectPage}?fileIds=${node.fileid}`) return true } return true From d39366e4d715eb35e9d9e1619c19364125057aa8 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 09:53:42 +0300 Subject: [PATCH 05/14] correct endpoint params, update docs Signed-off-by: Andrey Borysenko --- docs/tech_details/api/fileactionsmenu.rst | 26 ++++++++--------------- lib/Controller/OCSUiController.php | 8 +++---- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/docs/tech_details/api/fileactionsmenu.rst b/docs/tech_details/api/fileactionsmenu.rst index 0b7e1c46..837e6aca 100644 --- a/docs/tech_details/api/fileactionsmenu.rst +++ b/docs/tech_details/api/fileactionsmenu.rst @@ -14,8 +14,15 @@ AppAPI takes responsibility to register FileActionsMenu, ExApps needs only to re Register ^^^^^^^^ +.. note:: + + With AppAPI 2.6.0 there is a new v2 OCS endpoint with redirect to ExApp UI support: + OCS endpoint: ``POST /apps/app_api/api/v2/ui/files-actions-menu``. + Old v1 is marked as deprecated. + OCS endpoint: ``POST /apps/app_api/api/v1/ui/files-actions-menu`` + Params ****** @@ -31,12 +38,10 @@ Complete list of params (including optional): "icon": "img/icon.svg", "permissions": "permissions", "order": "order_in_file_actions_menu", - "version": "1.0" } .. note:: Urls ``icon`` and ``actionHandler`` are relative to the ExApp root, starting slash is not required. - Optional params *************** @@ -95,22 +100,9 @@ Redirect to ExApp UI page (top menu) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. note:: - Supported in Nextcloud 28+. - -If you want to open some file in ExApp UI, you need to set ``version`` to ``2.0``` in the FileActionsMenu registration. - -.. code-block:: json + Supported only for Nextcloud 28+. - { - "name": "unique_name_of_file_actions_menu", - "display_name": "Display name (for UI listing)", - "action_handler": "/action_handler_route" - "mime": "mime of files where to display action menu", - "icon": "img/icon.svg", - "permissions": "permissions", - "order": "order_in_file_actions_menu", - "version": "2.0" - } +If you want to open some files in ExApp UI, your FileActionsMenu have to be registered using OCS v2 version (``/apps/app_api/api/v2/ui/files-actions-menu``). After that, AppAPI will expect in the JSON response of the ExApp ``action_handler`` the ``redirect_handler`` - a relative path on the ExApp Top Menu page, diff --git a/lib/Controller/OCSUiController.php b/lib/Controller/OCSUiController.php index 8601938d..ea564355 100644 --- a/lib/Controller/OCSUiController.php +++ b/lib/Controller/OCSUiController.php @@ -46,9 +46,9 @@ public function __construct( #[NoCSRFRequired] public function registerFileActionMenu(string $name, string $displayName, string $actionHandler, string $icon = "", string $mime = "file", int $permissions = 31, - int $order = 0, string $version = '1.0'): DataResponse { + int $order = 0): DataResponse { $result = $this->filesActionsMenuService->registerFileActionMenu( - $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, $version); + $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, '1.0'); if (!$result) { throw new OCSBadRequestException("File Action Menu entry could not be registered"); } @@ -63,9 +63,9 @@ public function registerFileActionMenu(string $name, string $displayName, string #[NoCSRFRequired] public function registerFileActionMenuV2(string $name, string $displayName, string $actionHandler, string $icon = "", string $mime = "file", int $permissions = 31, - int $order = 0, string $version = '2.0'): DataResponse { + int $order = 0): DataResponse { $result = $this->filesActionsMenuService->registerFileActionMenu( - $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, $version); + $this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order, '2.0'); if (!$result) { throw new OCSBadRequestException("File Action Menu entry could not be registered"); } From c6584429aa4d2ecec9503d8c2d888571991b787e Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 11:34:22 +0300 Subject: [PATCH 06/14] update changelog Signed-off-by: Andrey Borysenko --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 040ec458..4e1047ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added File Actions v2 version with redirect to the ExApp UI. #284 +### Changed + +- Reworked scopes for database/cache requests optimization, drop old ex_app_scopes table. #285 + ## [2.5.1 - 2024-05-02] ### Added From f8ef6e6987d42b4895537f25b5131f0b93db4319 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 11:42:41 +0300 Subject: [PATCH 07/14] remove old changelog entry, related to 2.6.0 Signed-off-by: Andrey Borysenko --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e1047ff..c10785fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Test deploy button in Admin settings for each Daemon configuration. #279 -- File Actions option to redirect to the ExApp Top Menu (UI) page with the selected file context. #280 ## [2.5.0 - 2024-04-23] From 723b8b16946aa31cceae19f002e1c883ee47f24f Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 11:48:34 +0300 Subject: [PATCH 08/14] revert back params naming style changes Signed-off-by: Andrey Borysenko --- docs/tech_details/api/fileactionsmenu.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tech_details/api/fileactionsmenu.rst b/docs/tech_details/api/fileactionsmenu.rst index 837e6aca..dbc4a55c 100644 --- a/docs/tech_details/api/fileactionsmenu.rst +++ b/docs/tech_details/api/fileactionsmenu.rst @@ -32,8 +32,8 @@ Complete list of params (including optional): { "name": "unique_name_of_file_actions_menu", - "display_name": "Display name (for UI listing)", - "action_handler": "/action_handler_route" + "displayName": "Display name (for UI listing)", + "actionHandler": "/action_handler_route" "mime": "mime of files where to display action menu", "icon": "img/icon.svg", "permissions": "permissions", From af3be865dcb1baff2f93c1a7f576c93c3fb60916 Mon Sep 17 00:00:00 2001 From: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Date: Tue, 7 May 2024 13:45:41 +0300 Subject: [PATCH 09/14] added missing API SCOPE Signed-off-by: Alexander Piskun --- lib/Service/ExAppApiScopeService.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Service/ExAppApiScopeService.php b/lib/Service/ExAppApiScopeService.php index 905e3b3d..302a5b59 100644 --- a/lib/Service/ExAppApiScopeService.php +++ b/lib/Service/ExAppApiScopeService.php @@ -15,9 +15,11 @@ class ExAppApiScopeService { public function __construct( ) { $aeApiV1Prefix = '/apps/' . Application::APP_ID . '/api/v1'; + $aeApiV2Prefix = '/apps/' . Application::APP_ID . '/api/v2'; $this->apiScopes = [ // AppAPI scopes ['api_route' => $aeApiV1Prefix . '/ui/files-actions-menu', 'scope_group' => 1, 'name' => 'BASIC', 'user_check' => 0], + ['api_route' => $aeApiV2Prefix . '/ui/files-actions-menu', 'scope_group' => 1, 'name' => 'BASIC', 'user_check' => 0], ['api_route' => $aeApiV1Prefix . '/ui/top-menu', 'scope_group' => 1, 'name' => 'BASIC', 'user_check' => 0], ['api_route' => $aeApiV1Prefix . '/ui/initial-state', 'scope_group' => 1, 'name' => 'BASIC', 'user_check' => 0], ['api_route' => $aeApiV1Prefix . '/ui/script', 'scope_group' => 1, 'name' => 'BASIC', 'user_check' => 0], From 1b128c51a5fd2e649f2fb52a47b8445a88120dd7 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 14:27:05 +0300 Subject: [PATCH 10/14] fix: correct payload as an array Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index d35df3e2..4df414c5 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -65,7 +65,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { }, async exec(node, view, dir) { const exAppFileActionHandler = generateAppAPIProxyUrl(fileAction.appid, fileAction.action_handler) - return axios.post(exAppFileActionHandler, buildNodeInfo(node)) + return axios.post(exAppFileActionHandler, {files: [buildNodeInfo(node)]}) .then((response) => { if ('redirect_handler' in response.data) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) From 5ba10af1099eeb7c78d74699af5cd67f993c044a Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 15:16:50 +0300 Subject: [PATCH 11/14] fix eslint Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index 4df414c5..9971292b 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -65,7 +65,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { }, async exec(node, view, dir) { const exAppFileActionHandler = generateAppAPIProxyUrl(fileAction.appid, fileAction.action_handler) - return axios.post(exAppFileActionHandler, {files: [buildNodeInfo(node)]}) + return axios.post(exAppFileActionHandler, { files: [buildNodeInfo(node)] }) .then((response) => { if ('redirect_handler' in response.data) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) From 611faf53805da294808608bcae93376dc1453af1 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Tue, 7 May 2024 16:54:14 +0300 Subject: [PATCH 12/14] keep v1 handler for single file action Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index 9971292b..479c096b 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -65,15 +65,25 @@ function registerFileAction28(fileAction, inlineSvgIcon) { }, async exec(node, view, dir) { const exAppFileActionHandler = generateAppAPIProxyUrl(fileAction.appid, fileAction.action_handler) - return axios.post(exAppFileActionHandler, { files: [buildNodeInfo(node)] }) - .then((response) => { - if ('redirect_handler' in response.data) { - const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) - window.location.assign(`${redirectPage}?fileIds=${node.fileid}`) + if ('version' in fileAction && fileAction.version === '2.0') { + return axios.post(exAppFileActionHandler, { files: [buildNodeInfo(node)] }) + .then((response) => { + if ('redirect_handler' in response.data) { + const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) + window.location.assign(`${redirectPage}?fileIds=${node.fileid}`) + return true + } return true - } + }).catch((error) => { + console.error('Failed to send FileAction request to ExApp', error) + return false + }) + } + return axios.post(exAppFileActionHandler, buildNodeInfo(node)) + .then((response) => { return true - }).catch((error) => { + }) + .catch((error) => { console.error('Failed to send FileAction request to ExApp', error) return false }) From bdbf5c1d6f1532f742bcd0a307a76da5e999da39 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Wed, 8 May 2024 13:54:07 +0300 Subject: [PATCH 13/14] fix empty response, add check for object Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index 479c096b..e34c1074 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -68,7 +68,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { if ('version' in fileAction && fileAction.version === '2.0') { return axios.post(exAppFileActionHandler, { files: [buildNodeInfo(node)] }) .then((response) => { - if ('redirect_handler' in response.data) { + if (typeof response.data === 'object' && 'redirect_handler' in response.data) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) window.location.assign(`${redirectPage}?fileIds=${node.fileid}`) return true @@ -94,7 +94,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { const nodesDataList = nodes.map(buildNodeInfo) return axios.post(exAppFileActionHandler, { files: nodesDataList }) .then((response) => { - if ('redirect_handler' in response.data) { + if (typeof response.data === 'object' && 'redirect_handler' in response.data) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) const fileIds = nodes.map((node) => node.fileid).join(',') window.location.assign(`${redirectPage}?fileIds=${fileIds}`) From 0445586f02e69a5b09c7168dcac6bc575519aae7 Mon Sep 17 00:00:00 2001 From: Andrey Borysenko Date: Wed, 8 May 2024 14:53:51 +0300 Subject: [PATCH 14/14] fix batchExec response Signed-off-by: Andrey Borysenko --- src/filesplugin28.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/filesplugin28.js b/src/filesplugin28.js index e34c1074..1f606322 100644 --- a/src/filesplugin28.js +++ b/src/filesplugin28.js @@ -80,7 +80,7 @@ function registerFileAction28(fileAction, inlineSvgIcon) { }) } return axios.post(exAppFileActionHandler, buildNodeInfo(node)) - .then((response) => { + .then(() => { return true }) .catch((error) => { @@ -98,13 +98,12 @@ function registerFileAction28(fileAction, inlineSvgIcon) { const redirectPage = generateExAppUIPageUrl(fileAction.appid, response.data.redirect_handler) const fileIds = nodes.map((node) => node.fileid).join(',') window.location.assign(`${redirectPage}?fileIds=${fileIds}`) - return true } - return true + return nodes.map(_ => true) }) .catch((error) => { console.error('Failed to send FileAction request to ExApp', error) - return false + return nodes.map(_ => false) }) } // for version 1.0 behavior is not changed