Skip to content

Commit

Permalink
UI: FileActions rework (#141)
Browse files Browse the repository at this point in the history
* changed type of `order` to int in model

---------

Signed-off-by: Andrey Borysenko <andrey18106x@gmail.com>
Co-authored-by: Andrey Borysenko <andrey18106x@gmail.com>
  • Loading branch information
bigcat88 and andrey18106 authored Dec 5, 2023
1 parent 947b0c7 commit 86ae743
Show file tree
Hide file tree
Showing 18 changed files with 254 additions and 341 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/tests-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ jobs:
runs-on: ubuntu-22.04
name: NC In Julius Docker • 🐘8.1
env:
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:latest
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:20231202-1

steps:
- name: Set app env
Expand Down Expand Up @@ -224,7 +224,7 @@ jobs:
runs-on: ubuntu-22.04
name: NC In Julius Docker(Docker by port) • 🐘8.1
env:
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:latest
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:20231202-1

steps:
- name: Set app env
Expand All @@ -238,7 +238,7 @@ jobs:
docker run -d -p 8443:443 -v /var/run/docker.sock:/var/run/docker.sock:ro \
--env CREATE_CERTS_WITH_PW=supersecret --env CERT_HOSTNAME=host.docker.internal \
-v `pwd`/certs:/data/certs kekru/docker-remote-api-tls:master
sleep 30s
sleep 60s
- name: Install AppAPI
run: |
Expand Down Expand Up @@ -305,7 +305,7 @@ jobs:
runs-on: ubuntu-22.04
name: NC In Julius Docker(APP by hostname) • 🐘8.1
env:
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:latest
docker-image: ghcr.io/juliushaertl/nextcloud-dev-php81:20231202-1

steps:
- name: Set app env
Expand All @@ -318,7 +318,7 @@ jobs:
docker run -d -p 8443:443 -v /var/run/docker.sock:/var/run/docker.sock:ro \
--env CREATE_CERTS_WITH_PW=supersecret --env CERT_HOSTNAME=host.docker.internal \
-v `pwd`/certs:/data/certs kekru/docker-remote-api-tls:master
sleep 30s
sleep 60s
- name: Install AppAPI
run: |
Expand Down
9 changes: 4 additions & 5 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,11 @@
['name' => 'TalkBot#registerExAppTalkBot', 'url' => '/api/v1/talk_bot', 'verb' => 'POST'],
['name' => 'TalkBot#unregisterExAppTalkBot', 'url' => '/api/v1/talk_bot', 'verb' => 'DELETE'],

// --- UI ---
// File Actions Menu
['name' => 'OCSUi#registerFileActionMenu', 'url' => '/api/v1/files/actions/menu', 'verb' => 'POST'],
['name' => 'OCSUi#unregisterFileActionMenu', 'url' => '/api/v1/files/actions/menu', 'verb' => 'DELETE'],
['name' => 'OCSUi#getFileActionMenu', 'url' => '/api/v1/files/actions/menu', 'verb' => 'GET'],
['name' => 'OCSUi#handleFileAction', 'url' => '/api/v1/files/action', 'verb' => 'POST'],
['name' => 'OCSUi#loadFileActionIcon', 'url' => '/api/v1/files/action/icon', 'verb' => 'GET'],
['name' => 'OCSUi#registerFileActionMenu', 'url' => '/api/v1/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'],

// Top Menu
['name' => 'OCSUi#registerExAppMenuEntry', 'url' => '/api/v1/ui/top-menu', 'verb' => 'POST'],
Expand Down
5 changes: 5 additions & 0 deletions css/filesactions.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
background-image: url('../img/app-dark.svg');
filter: var(--background-invert-if-dark);
}

/* For Nextcloud 27 */
.menuitem.action > img.icon {
filter: var(--background-invert-if-dark);
}
4 changes: 1 addition & 3 deletions lib/AppInfo/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
use OCA\AppAPI\Notifications\ExAppNotifier;
use OCA\AppAPI\Profiler\AppAPIDataCollector;
use OCA\AppAPI\PublicCapabilities;

use OCA\AppAPI\Service\TopMenuService;
use OCA\AppAPI\Service\UI\TopMenuService;
use OCA\DAV\Events\SabrePluginAuthInitEvent;
use OCA\Files\Event\LoadAdditionalScriptsEvent;
use OCP\AppFramework\App;
Expand All @@ -32,7 +31,6 @@
use OCP\IUserSession;
use OCP\Profiler\IProfiler;
use OCP\SabrePluginEvent;

use OCP\User\Events\UserDeletedEvent;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
Expand Down
151 changes: 33 additions & 118 deletions lib/Controller/OCSUiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,30 @@

use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Attribute\AppAPIAuth;
use OCA\AppAPI\Service\AppAPIService;
use OCA\AppAPI\Service\ExAppInitialStateService;
use OCA\AppAPI\Service\ExAppScriptsService;
use OCA\AppAPI\Service\ExAppStylesService;
use OCA\AppAPI\Service\ExFilesActionsMenuService;

use OCA\AppAPI\Service\TopMenuService;
use OCA\AppAPI\Service\UI\FilesActionsMenuService;
use OCA\AppAPI\Service\UI\InitialStateService;
use OCA\AppAPI\Service\UI\ScriptsService;
use OCA\AppAPI\Service\UI\StylesService;
use OCA\AppAPI\Service\UI\TopMenuService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
use OCP\AppFramework\Http\Attribute\PublicPage;
use OCP\AppFramework\Http\DataDisplayResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCS\OCSBadRequestException;
use OCP\AppFramework\OCS\OCSNotFoundException;
use OCP\AppFramework\OCSController;
use OCP\Http\Client\IResponse;
use OCP\IConfig;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

class OCSUiController extends OCSController {
protected $request;

public function __construct(
IRequest $request,
private readonly ?string $userId,
private readonly ExFilesActionsMenuService $exFilesActionsMenuService,
private readonly TopMenuService $menuEntryService,
private readonly ExAppInitialStateService $initialStateService,
private readonly ExAppScriptsService $scriptsService,
private readonly ExAppStylesService $stylesService,
private readonly AppAPIService $appAPIService,
private readonly IConfig $config,
private readonly LoggerInterface $logger,
IRequest $request,
private readonly FilesActionsMenuService $filesActionsMenuService,
private readonly TopMenuService $menuEntryService,
private readonly InitialStateService $initialStateService,
private readonly ScriptsService $scriptsService,
private readonly StylesService $stylesService,
) {
parent::__construct(Application::APP_ID, $request);

Expand All @@ -51,37 +40,45 @@ public function __construct(
* @PublicPage
* @NoCSRFRequired
*
* @param array $fileActionMenuParams [name, display_name, mime, permissions, order, icon, icon_class, action_handler]
*
* @param string $name
* @param string $displayName
* @param string $actionHandler
* @param string $icon
* @param string $mime
* @param int $permissions
* @param int $order
* @return DataResponse
* @throws OCSBadRequestException
*/
#[AppAPIAuth]
#[PublicPage]
#[NoCSRFRequired]
public function registerFileActionMenu(array $fileActionMenuParams): DataResponse {
$registeredFileActionMenu = $this->exFilesActionsMenuService->registerFileActionMenu(
$this->request->getHeader('EX-APP-ID'), $fileActionMenuParams);
return new DataResponse([
'success' => $registeredFileActionMenu !== null,
'registeredFileActionMenu' => $registeredFileActionMenu,
], Http::STATUS_OK);
public function registerFileActionMenu(string $name, string $displayName, string $actionHandler,
string $icon = "", string $mime = "file", int $permissions = 31,
int $order = 0): DataResponse {
$result = $this->filesActionsMenuService->registerFileActionMenu(
$this->request->getHeader('EX-APP-ID'), $name, $displayName, $actionHandler, $icon, $mime, $permissions, $order);
if (!$result) {
throw new OCSBadRequestException("File Action Menu entry could not be registered");
}
return new DataResponse();
}

/**
* @PublicPage
* @NoCSRFRequired
*
* @param string $fileActionMenuName
* @param string $name
*
* @throws OCSNotFoundException
* @return DataResponse
*/
#[AppAPIAuth]
#[PublicPage]
#[NoCSRFRequired]
public function unregisterFileActionMenu(string $fileActionMenuName): DataResponse {
$unregisteredFileActionMenu = $this->exFilesActionsMenuService->unregisterFileActionMenu(
$this->request->getHeader('EX-APP-ID'), $fileActionMenuName);
public function unregisterFileActionMenu(string $name): DataResponse {
$unregisteredFileActionMenu = $this->filesActionsMenuService->unregisterFileActionMenu(
$this->request->getHeader('EX-APP-ID'), $name);
if ($unregisteredFileActionMenu === null) {
throw new OCSNotFoundException('FileActionMenu not found');
}
Expand All @@ -97,7 +94,7 @@ public function unregisterFileActionMenu(string $fileActionMenuName): DataRespon
#[PublicPage]
#[NoCSRFRequired]
public function getFileActionMenu(string $name): DataResponse {
$result = $this->exFilesActionsMenuService->getExAppFileAction(
$result = $this->filesActionsMenuService->getExAppFileAction(
$this->request->getHeader('EX-APP-ID'), $name);
if (!$result) {
throw new OCSNotFoundException('FileActionMenu not found');
Expand Down Expand Up @@ -310,86 +307,4 @@ public function getExAppStyle(string $type, string $name, string $path): DataRes
}
return new DataResponse($result, Http::STATUS_OK);
}

/**
* @NoCSRFRequired
* @NoAdminRequired
*
* @param string $appId
* @param string $actionName
* @param array $actionFile
* @param string $actionHandler
*
* @return DataResponse
*/
#[NoAdminRequired]
#[NoCSRFRequired]
public function handleFileAction(string $appId, string $actionName, array $actionFile, string $actionHandler): DataResponse {
$result = false;
$exFileAction = $this->exFilesActionsMenuService->getExAppFileAction($appId, $actionName);
if ($exFileAction !== null) {
$handler = $exFileAction->getActionHandler(); // route on ex app
$params = [
'actionName' => $actionName,
'actionHandler' => $actionHandler,
'actionFile' => [
'fileId' => $actionFile['fileId'],
'name' => $actionFile['name'],
'directory' => $actionFile['directory'],
'etag' => $actionFile['etag'],
'mime' => $actionFile['mime'],
'fileType' => $actionFile['fileType'],
'mtime' => $actionFile['mtime'] / 1000, // convert ms to s
'size' => intval($actionFile['size']),
'favorite' => $actionFile['favorite'] ?? "false",
'permissions' => $actionFile['permissions'],
'shareOwner' => $actionFile['shareOwner'] ?? null,
'shareOwnerId' => $actionFile['shareOwnerId'] ?? null,
'shareTypes' => $actionFile['shareTypes'] ?? null,
'shareAttributes' => $actionFile['shareAttributes'] ?? null,
'sharePermissions' => $actionFile['sharePermissions'] ?? null,
'userId' => $this->userId,
'instanceId' => $this->config->getSystemValue('instanceid', null),
],
];
$exApp = $this->appAPIService->getExApp($appId);
if ($exApp !== null) {
$result = $this->appAPIService->aeRequestToExApp($exApp, $handler, $this->userId, 'POST', $params, [], $this->request);
if ($result instanceof IResponse) {
$result = $result->getStatusCode() === 200;
} elseif (isset($result['error'])) {
$this->logger->error(sprintf('Failed to handle ExApp %s FileAction %s. Error: %s', $appId, $actionName, $result['error']));
}
}
}
return new DataResponse([
'success' => $result,
'handleFileActionSent' => $result,
], Http::STATUS_OK);
}

/**
* @NoAdminRequired
* @NoCSRFRequired
*
* @param string $appId
* @param string $exFileActionName
*
* @return DataDisplayResponse
*/
#[NoAdminRequired]
#[NoCSRFRequired]
public function loadFileActionIcon(string $appId, string $exFileActionName): DataDisplayResponse {
$icon = $this->exFilesActionsMenuService->loadFileActionIcon($appId, $exFileActionName);
if ($icon !== null && isset($icon['body'], $icon['headers'])) {
$response = new DataDisplayResponse(
$icon['body'],
Http::STATUS_OK,
['Content-Type' => $icon['headers']['Content-Type'][0] ?? 'image/svg+xml']
);
$response->cacheFor(ExFilesActionsMenuService::ICON_CACHE_TTL, false, true);
return $response;
}
return new DataDisplayResponse('', 400);
}
}
26 changes: 13 additions & 13 deletions lib/Controller/TopMenuController.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@

use OCA\AppAPI\AppInfo\Application;
use OCA\AppAPI\Service\AppAPIService;
use OCA\AppAPI\Service\ExAppInitialStateService;
use OCA\AppAPI\Service\ExAppScriptsService;
use OCA\AppAPI\Service\ExAppStylesService;
use OCA\AppAPI\Service\ExAppUsersService;
use OCA\AppAPI\Service\TopMenuService;
use OCA\AppAPI\Service\UI\InitialStateService;
use OCA\AppAPI\Service\UI\ScriptsService;
use OCA\AppAPI\Service\UI\StylesService;
use OCA\AppAPI\Service\UI\TopMenuService;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
Expand All @@ -26,15 +26,15 @@ class TopMenuController extends Controller {
public array $jsProxyMap = [];

public function __construct(
IRequest $request,
private IInitialState $initialState,
private TopMenuService $menuEntryService,
private ExAppInitialStateService $initialStateService,
private ExAppScriptsService $scriptsService,
private ExAppStylesService $stylesService,
private ExAppUsersService $exAppUsersService,
private AppAPIService $service,
private ?string $userId,
IRequest $request,
private IInitialState $initialState,
private TopMenuService $menuEntryService,
private InitialStateService $initialStateService,
private ScriptsService $scriptsService,
private StylesService $stylesService,
private ExAppUsersService $exAppUsersService,
private AppAPIService $service,
private ?string $userId,
) {
parent::__construct(Application::APP_ID, $request);
}
Expand Down
14 changes: 3 additions & 11 deletions lib/Db/UI/FilesActionsMenu.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,16 @@
* @method string getDisplayName()
* @method string getMime()
* @method string getPermissions()
* @method string getOrder()
* @method int getOrder()
* @method string getIcon()
* @method string getIconClass()
* @method string getActionHandler()
* @method void setAppid(string $appid)
* @method void setName(string $name)
* @method void setDisplayName(string $displayName)
* @method void setMime(string $mime)
* @method void setPermissions(string $permissions)
* @method void setOrder(string $order)
* @method void setOrder(int $order)
* @method void setIcon(string $icon)
* @method void setIconClass(string $iconClass)
* @method void setActionHandler(string $actionHandler)
*/
class FilesActionsMenu extends Entity implements JsonSerializable {
Expand All @@ -39,7 +37,6 @@ class FilesActionsMenu extends Entity implements JsonSerializable {
protected $permissions;
protected $order;
protected $icon;
protected $iconClass;
protected $actionHandler;

/**
Expand All @@ -51,9 +48,8 @@ public function __construct(array $params = []) {
$this->addType('displayName', 'string');
$this->addType('mime', 'string');
$this->addType('permissions', 'string');
$this->addType('order', 'string');
$this->addType('order', 'int');
$this->addType('icon', 'string');
$this->addType('iconClass', 'string');
$this->addType('actionHandler', 'string');

if (isset($params['id'])) {
Expand All @@ -80,9 +76,6 @@ public function __construct(array $params = []) {
if (isset($params['icon'])) {
$this->setIcon($params['icon']);
}
if (isset($params['icon_class'])) {
$this->setIconClass($params['icon_class']);
}
if (isset($params['action_handler'])) {
$this->setActionHandler($params['action_handler']);
}
Expand All @@ -98,7 +91,6 @@ public function jsonSerialize(): array {
'permissions' => $this->getPermissions(),
'order' => $this->getOrder(),
'icon' => $this->getIcon(),
'icon_class' => $this->getIconClass(),
'action_handler' => $this->getActionHandler(),
];
}
Expand Down
Loading

0 comments on commit 86ae743

Please sign in to comment.