Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add backend for table archive and favorite flag #865

Merged
merged 23 commits into from
Mar 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
32e3100
feat: Add backend for table archive and favorite flag
juliusknorr Feb 22, 2024
c2bb58b
fix: Adapt reset of the update methods to use the new archived flag
juliusknorr Feb 22, 2024
f4d478b
fix: Proper error handling and validation of passed in node type and …
juliusknorr Feb 22, 2024
40af3b7
chore: Make psalm output more readable for the main usage when we are…
juliusknorr Feb 22, 2024
988571e
feat: Expose api feature flags thorugh capabilities
juliusknorr Feb 22, 2024
19d1574
tests: Add integration tests for archive and favorites
juliusknorr Feb 23, 2024
513b660
fix: Expose favorites of views
juliusknorr Feb 26, 2024
3e61728
fix: Do not use userId as cache key prefix
juliusknorr Feb 26, 2024
c816afe
fix: Add index to query favorites by user id
juliusknorr Feb 26, 2024
cc66f12
added archive table action button
elzody Feb 26, 2024
c4ab1a4
added unarchive action button and archive/unarchive logic
elzody Feb 26, 2024
484cb6c
added archived tables navigation item
elzody Feb 26, 2024
7584017
added logic for archived tables navigation item
elzody Feb 26, 2024
895b038
updated counter bubble on archived tables nav item
elzody Feb 26, 2024
7bc339e
removed unneeded console log statements
elzody Feb 27, 2024
ad5bcc9
hide archived tables if there are none
elzody Feb 27, 2024
5332909
add favorite/unfavorite buttons
elzody Feb 27, 2024
dca2d4e
added (un)favorite logic to store
elzody Feb 27, 2024
bf89c47
reworked computed properties and added favorites section
elzody Feb 28, 2024
7875154
removed ownership limit on favoriting tables/views
elzody Feb 28, 2024
5e2f1c1
added proper (un)favorite logic for views
elzody Feb 28, 2024
8b75e0a
adjusted front end logic for views
elzody Feb 28, 2024
8c9fc70
fix: Make sure that nodeType is called using numeric values
juliusknorr Mar 1, 2024
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
3 changes: 3 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,5 +125,8 @@
['name' => 'ApiColumns#createTextColumn', 'url' => '/api/2/columns/text', 'verb' => 'POST'],
['name' => 'ApiColumns#createSelectionColumn', 'url' => '/api/2/columns/selection', 'verb' => 'POST'],
['name' => 'ApiColumns#createDatetimeColumn', 'url' => '/api/2/columns/datetime', 'verb' => 'POST'],

['name' => 'ApiFavorite#create', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'POST', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
['name' => 'ApiFavorite#destroy', 'url' => '/api/2/favorites/{nodeType}/{nodeId}', 'verb' => 'DELETE', 'requirements' => ['nodeType' => '(\d+)', 'nodeId' => '(\d+)']],
]
];
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"lint": "find . -name \\*.php -not -path './vendor/*' -not -path './build/*' -print0 | xargs -0 -n1 php -l",
"cs:check": "php-cs-fixer fix --dry-run --diff",
"cs:fix": "php-cs-fixer fix",
"psalm": "./vendor/bin/psalm.phar --show-info=true --no-cache",
"psalm": "./vendor/bin/psalm.phar --show-info=false --no-cache",
"psalm:update-baseline": "./vendor/bin/psalm.phar --update-baseline",
"psalm:fix": "./vendor/bin/psalm.phar --no-cache --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType",
"psalm:fix:dry": "./vendor/bin/psalm.phar --no-cache --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType --dry-run",
Expand Down
6 changes: 5 additions & 1 deletion lib/Capabilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct(IAppManager $appManager, LoggerInterface $logger, IC

/**
*
* @return array{tables: array{enabled: bool, version: string, apiVersions: string[], column_types: string[]}}
* @return array{tables: array{enabled: bool, version: string, apiVersions: string[], features: string[], column_types: string[]}}
*
* @inheritDoc
*/
Expand All @@ -63,6 +63,10 @@ public function getCapabilities(): array {
'apiVersions' => [
'1.0'
],
'features' => [
'favorite',
'archive',
],
'column_types' => [
'text-line',
$textColumnVariant,
Expand Down
12 changes: 10 additions & 2 deletions lib/Command/RenameTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public function __construct(TableService $tableService, LoggerInterface $logger)

protected function configure(): void {
$this
->setName('tables:rename')
->setName('tables:update')
->setAliases(['tables:rename'])
->setDescription('Rename a table.')
->addArgument(
'ID',
Expand All @@ -62,6 +63,12 @@ protected function configure(): void {
InputOption::VALUE_OPTIONAL,
'New emoji.'
)
->addOption(
'archived',
'a',
InputOption::VALUE_NONE,
'Archived'
)
;
}

Expand All @@ -74,9 +81,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$id = $input->getArgument('ID');
$title = $input->getArgument('title');
$emoji = $input->getOption('emoji');
$archived = $input->getOption('archived');

try {
$table = $this->tableService->update($id, $title, $emoji, '');
$table = $this->tableService->update($id, $title, $emoji, $archived, '');

$arr = $table->jsonSerialize();
unset($arr['hasShares']);
Expand Down
4 changes: 2 additions & 2 deletions lib/Controller/Api1Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ public function getTable(int $tableId): DataResponse {
* 403: No permissions
* 404: Not found
*/
public function updateTable(int $tableId, string $title = null, string $emoji = null): DataResponse {
public function updateTable(int $tableId, string $title = null, string $emoji = null, ?bool $archived = false): DataResponse {
try {
return new DataResponse($this->tableService->update($tableId, $title, $emoji, $this->userId)->jsonSerialize());
return new DataResponse($this->tableService->update($tableId, $title, $emoji, $archived, $this->userId)->jsonSerialize());
} catch (PermissionError $e) {
$this->logger->warning('A permission error occurred: ' . $e->getMessage());
$message = ['message' => $e->getMessage()];
Expand Down
86 changes: 86 additions & 0 deletions lib/Controller/ApiFavoriteController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

declare(strict_types=1);

namespace OCA\Tables\Controller;

use Exception;
use OCA\Tables\Errors\InternalError;
use OCA\Tables\Errors\NotFoundError;
use OCA\Tables\Errors\PermissionError;
use OCA\Tables\ResponseDefinitions;
use OCA\Tables\Service\FavoritesService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\DB\Exception as DBException;
use OCP\IL10N;
use OCP\IRequest;
use Psr\Log\LoggerInterface;

/**
* @psalm-import-type TablesTable from ResponseDefinitions
*/
class ApiFavoriteController extends AOCSController {
private FavoritesService $service;

public function __construct(
IRequest $request,
LoggerInterface $logger,
FavoritesService $service,
IL10N $n,
string $userId) {
parent::__construct($request, $logger, $n, $userId);
$this->service = $service;
}

/**
* [api v2] Add a node (table or view) to user favorites
*
* @NoAdminRequired
*
* @param int $nodeType
* @param int $nodeId
* @return DataResponse<Http::STATUS_OK, array{}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
*
* 200: Tables returned
*/
public function create(int $nodeType, int $nodeId): DataResponse {
try {
$this->service->addFavorite($nodeType, $nodeId);
return new DataResponse();
} catch (NotFoundError $e) {
return $this->handleNotFoundError($e);
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError|DBException|Exception $e) {
return $this->handleError($e);
}
}


/**
* [api v2] Remove a node (table or view) to from favorites
*
* @NoAdminRequired
*
* @param int $nodeType
* @param int $nodeId
* @return DataResponse<Http::STATUS_OK, array{}, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND, array{message: string}, array{}>
*
* 200: Deleted table returned
* 403: No permissions
* 404: Not found
*/
public function destroy(int $nodeType, int $nodeId): DataResponse {
try {
$this->service->removeFavorite($nodeType, $nodeId);
return new DataResponse();
} catch (NotFoundError $e) {
return $this->handleNotFoundError($e);
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError|DBException|Exception $e) {
return $this->handleError($e);
}
}
}
4 changes: 2 additions & 2 deletions lib/Controller/ApiTablesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@ public function create(string $title, ?string $emoji, string $template = 'custom
* 403: No permissions
* 404: Not found
*/
public function update(int $id, string $title = null, string $emoji = null): DataResponse {
public function update(int $id, ?string $title = null, ?string $emoji = null, ?bool $archived = null): DataResponse {
try {
return new DataResponse($this->service->update($id, $title, $emoji, $this->userId)->jsonSerialize());
return new DataResponse($this->service->update($id, $title, $emoji, $archived, $this->userId)->jsonSerialize());
} catch (PermissionError $e) {
return $this->handlePermissionError($e);
} catch (InternalError $e) {
Expand Down
6 changes: 3 additions & 3 deletions lib/Controller/TableController.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ public function destroy(int $id): DataResponse {
/**
* @NoAdminRequired
*/
public function update(int $id, string $title = null, string $emoji = null): DataResponse {
return $this->handleError(function () use ($id, $title, $emoji) {
return $this->service->update($id, $title, $emoji, $this->userId);
public function update(int $id, string $title = null, string $emoji = null, ?bool $archived = null): DataResponse {
return $this->handleError(function () use ($id, $title, $emoji, $archived) {
return $this->service->update($id, $title, $emoji, $archived, $this->userId);
});
}
}
9 changes: 9 additions & 0 deletions lib/Db/Table.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* @method setTitle(string $title)
* @method getEmoji(): string
* @method setEmoji(string $emoji)
* @method getArchived(): bool
* @method setArchived(bool $archived)
* @method getOwnership(): string
* @method setOwnership(string $ownership)
* @method getOwnerDisplayName(): string
Expand All @@ -26,6 +28,8 @@
* @method setOnSharePermissions(array $onSharePermissions)
* @method getHasShares(): bool
* @method setHasShares(bool $hasShares)
* @method getFavorite(): bool
* @method setFavorite(bool $favorite)
* @method getRowsCount(): int
* @method setRowsCount(int $rowsCount)
* @method getColumnsCount(): int
Expand All @@ -52,17 +56,20 @@ class Table extends Entity implements JsonSerializable {
protected ?string $createdAt = null;
protected ?string $lastEditBy = null;
protected ?string $lastEditAt = null;
protected bool $archived = false;
protected ?bool $isShared = null;
protected ?array $onSharePermissions = null;

protected ?bool $hasShares = false;
protected ?bool $favorite = false;
protected ?int $rowsCount = 0;
protected ?int $columnsCount = 0;
protected ?array $views = null;
protected ?array $columns = null;

public function __construct() {
$this->addType('id', 'integer');
$this->addType('archived', 'boolean');
}

/**
Expand All @@ -79,7 +86,9 @@ public function jsonSerialize(): array {
'createdAt' => $this->createdAt ?: '',
'lastEditBy' => $this->lastEditBy ?: '',
'lastEditAt' => $this->lastEditAt ?: '',
'archived' => $this->archived,
'isShared' => !!$this->isShared,
'favorite' => $this->favorite,
'onSharePermissions' => $this->getSharePermissions(),
'hasShares' => !!$this->hasShares,
'rowsCount' => $this->rowsCount ?: 0,
Expand Down
4 changes: 4 additions & 0 deletions lib/Db/View.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
* @method setOnSharePermissions(array $onSharePermissions)
* @method getHasShares(): bool
* @method setHasShares(bool $hasShares)
* @method getFavorite(): bool
* @method setFavorite(bool $favorite)
* @method getRowsCount(): int
* @method setRowsCount(int $rowCount)
* @method getOwnership(): string
Expand All @@ -57,6 +59,7 @@ class View extends Entity implements JsonSerializable {
protected ?bool $isShared = null;
protected ?array $onSharePermissions = null;
protected ?bool $hasShares = false;
protected bool $favorite = false;
protected ?int $rowsCount = 0;
protected ?string $ownership = null;
protected ?string $ownerDisplayName = null;
Expand Down Expand Up @@ -137,6 +140,7 @@ public function jsonSerialize(): array {
'columns' => $this->getColumnsArray(),
'sort' => $this->getSortArray(),
'isShared' => !!$this->isShared,
'favorite' => $this->favorite,
'onSharePermissions' => $this->getSharePermissions(),
'hasShares' => !!$this->hasShares,
'rowsCount' => $this->rowsCount ?: 0,
Expand Down
60 changes: 60 additions & 0 deletions lib/Migration/Version000800Date20240222000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

/** @noinspection PhpUnused */

declare(strict_types=1);

namespace OCA\Tables\Migration;

use Closure;
use OCP\DB\Exception;
use OCP\DB\ISchemaWrapper;
use OCP\DB\Types;
use OCP\Migration\IOutput;
use OCP\Migration\SimpleMigrationStep;

class Version000800Date20240222000000 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
* @throws Exception
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

if ($schema->hasTable('tables_tables')) {
$table = $schema->getTable('tables_tables');
$table->addColumn('archived', Types::BOOLEAN, [
'default' => false,
'notnull' => true,
]);
}

if (!$schema->hasTable('tables_favorites')) {
$table = $schema->createTable('tables_favorites');
$table->addColumn('id', Types::BIGINT, [
'notnull' => true,
'autoincrement' => true,
'unsigned' => true,
]);
$table->addColumn('node_type', Types::SMALLINT, [
'notnull' => true,
]);
$table->addColumn('node_id', Types::BIGINT, [
'notnull' => true,
]);
$table->addColumn('user_id', Types::STRING, [
'notnull' => true,
'length' => 64,
]);
$table->setPrimaryKey(['id']);
$table->addIndex(['user_id'], 'idx_tables_fav_uid');
}

return $schema;
}

}
3 changes: 3 additions & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* sort: list<array{columnId: int, mode: 'ASC'|'DESC'}>,
* filter: list<list<array{columnId: int, operator: 'begins-with'|'ends-with'|'contains'|'is-equal'|'is-greater-than'|'is-greater-than-or-equal'|'is-lower-than'|'is-lower-than-or-equal'|'is-empty', value: string|int|float}>>,
* isShared: bool,
* favorite: bool,
* onSharePermissions: ?array{
* read: bool,
* create: bool,
Expand All @@ -44,6 +45,8 @@
* createdAt: string,
* lastEditBy: string,
* lastEditAt: string,
* archived: bool,
* favorite: bool,
* isShared: bool,
* onSharePermissions: ?array{
* read: bool,
Expand Down
Loading
Loading