Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e2dcefa
Feat app card layout (#18)
taiebot Oct 3, 2026
dbbca31
Refactor ContextResourceCards for improved tab handling
taiebot Oct 3, 2026
fa97eb3
Clarify description rendering in card mode
taiebot Oct 3, 2026
e8e2a91
Merge branch 'nextcloud:main' into Feat-App-card-view2
taiebot Oct 5, 2026
be2618a
Refactor ContextResourceCards for improved tab handling
taiebot Oct 5, 2026
8f135ef
Enhance tooltip and preview in ContextResourceCards
taiebot Oct 5, 2026
5d4bf0c
Improve TableDescription editor handling
taiebot Oct 5, 2026
8c59480
Prevent editor from running if unmounted during loading
taiebot Oct 10, 2026
2a14bb9
Refactor tooltip preview to use TableDescription
taiebot Oct 10, 2026
de8c383
Refactor ContextResourceCards for better tooltip and tab handling
taiebot Oct 10, 2026
307a1cb
Enhance tooltip and panel height handling
taiebot Oct 10, 2026
1caa261
Adjust hidden table styles for better layout control
taiebot Oct 10, 2026
40fec37
Refactor view setting management in Context.vue
taiebot Oct 10, 2026
9b889d7
Optimize context sharing by removing unnecessary reload
taiebot Oct 11, 2026
bac9677
Merge branch 'nextcloud:main' into Feat-App-card-view2
taiebot Oct 11, 2026
3b0082e
Refactor context resource cards to tabs
taiebot Oct 11, 2026
8fecc9c
Add 'tab_view_enabled' column to contexts table
taiebot Oct 11, 2026
ca22cc6
Replace card_view_enabled with tab_view_enabled
taiebot Oct 11, 2026
dac3b35
Update tooltip text for tab view option
taiebot Oct 11, 2026
cee7055
Update text for tab view description in EditContext
taiebot Oct 11, 2026
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
8 changes: 6 additions & 2 deletions lib/Controller/ContextController.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ public function show(int $contextId): DataResponse {
* @param string $iconName Material design icon name of the context
* @param string $description Descriptive text of the context
* @psalm-param list<array{id: int, type: int, permissions?: int}> $nodes optional nodes to be connected to this context
* @param bool $tabViewEnabled Show the resources of the context as tabs instead of stacked
*
* @return DataResponse<Http::STATUS_OK, TablesContext, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_BAD_REQUEST|Http::STATUS_FORBIDDEN, array{message: string}, array{}>
*
Expand All @@ -108,7 +109,7 @@ public function show(int $contextId): DataResponse {
* 403: lacking permissions on a resource
*/
#[NoAdminRequired]
public function create(string $name, string $iconName, string $description = '', array $nodes = []): DataResponse {
public function create(string $name, string $iconName, string $description = '', array $nodes = [], bool $tabViewEnabled = false): DataResponse {
try {
if (!$this->isValidIcon($iconName)) {
return new DataResponse(['message' => 'Invalid icon name'], Http::STATUS_BAD_REQUEST);
Expand All @@ -120,6 +121,7 @@ public function create(string $name, string $iconName, string $description = '',
$this->sanitizeInputNodes($nodes),
$this->userId,
0,
$tabViewEnabled,
)->jsonSerialize());
} catch (Exception $e) {
return $this->handleError($e);
Expand All @@ -138,6 +140,7 @@ public function create(string $name, string $iconName, string $description = '',
* @param ?string $iconName provide this parameter to set a new icon
* @param ?string $description provide this parameter to set a new description
* @param ?array{id: int, type: int, permissions: int, order: int} $nodes provide this parameter to set a new list of nodes.
* @param ?bool $tabViewEnabled provide this parameter to show (or stop showing) the resources as tabs
*
* @return DataResponse<Http::STATUS_OK, TablesContext, array{}>|DataResponse<Http::STATUS_INTERNAL_SERVER_ERROR|Http::STATUS_NOT_FOUND|Http::STATUS_FORBIDDEN|Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
*
Expand All @@ -149,7 +152,7 @@ public function create(string $name, string $iconName, string $description = '',
* @CanManageContext
*/
#[NoAdminRequired]
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): DataResponse {
public function update(int $contextId, ?string $name, ?string $iconName, ?string $description, ?array $nodes, ?bool $tabViewEnabled = null): DataResponse {
try {
if ($iconName !== null && !$this->isValidIcon($iconName)) {
return new DataResponse(['message' => 'Invalid icon name'], Http::STATUS_BAD_REQUEST);
Expand All @@ -162,6 +165,7 @@ public function update(int $contextId, ?string $name, ?string $iconName, ?string
$iconName,
$description,
$nodes,
$tabViewEnabled,
)->jsonSerialize());
} catch (Exception|MultipleObjectsReturnedException $e) {
return $this->handleError($e);
Expand Down
7 changes: 6 additions & 1 deletion lib/Db/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
* @method setOwnerId(string $value): void
* @method getOwnerType(): int
* @method setOwnerType(int $value): void
* @method getTabViewEnabled(): ?bool
* @method setTabViewEnabled(?bool $value): void
*
* @method getSharing(): array
* @method setSharing(array $value): void
Expand All @@ -35,6 +37,7 @@ class Context extends EntitySuper implements JsonSerializable {
protected ?string $description = null;
protected ?string $ownerId = null;
protected ?int $ownerType = null;
protected ?bool $tabViewEnabled = null;

// virtual properties
protected ?array $sharing = null;
Expand All @@ -46,6 +49,7 @@ class Context extends EntitySuper implements JsonSerializable {
public function __construct() {
$this->addType('id', 'integer');
$this->addType('owner_type', 'integer');
$this->addType('tabViewEnabled', 'boolean');
}

public function jsonSerialize(): array {
Expand All @@ -56,7 +60,8 @@ public function jsonSerialize(): array {
'iconName' => $this->getIcon(),
'description' => $this->getDescription(),
'owner' => $this->getOwnerId(),
'ownerType' => $this->getOwnerType()
'ownerType' => $this->getOwnerType(),
'tabViewEnabled' => (bool)$this->getTabViewEnabled(),
];

// extended data
Expand Down
9 changes: 7 additions & 2 deletions lib/Db/ContextMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ protected function formatResultRows(array $rows, ?string $userId) {
'description' => $rows[0]['description'],
'owner_id' => $rows[0]['owner_id'],
'owner_type' => $rows[0]['owner_type'],
'tab_view_enabled' => $rows[0]['tab_view_enabled'] ?? null,
];

$formatted['sharing'] = array_reduce($rows, function (array $carry, array $item) use ($userId) {
Expand All @@ -103,7 +104,9 @@ protected function formatResultRows(array $rows, ?string $userId) {
'display_mode_default' => (int)$item['display_mode_default'],
];
if ($userId !== null) {
$item['display_mode'] ??= $item['display_mode_default'];
if ($item['display_mode'] === null) {
$item['display_mode'] = $item['display_mode_default'];
}
$carry[$item['share_id']]['display_mode'] = (int)$item['display_mode'];
}
return $carry;
Expand All @@ -128,7 +131,9 @@ protected function formatResultRows(array $rows, ?string $userId) {
// empty Context
return $carry;
}
$carry[$item['page_id']] ??= ['content' => []];
if (!isset($carry[$item['page_id']])) {
$carry[$item['page_id']] = ['content' => []];
}
$carry[$item['page_id']]['id'] = (int)$item['page_id'];
$carry[$item['page_id']]['page_type'] = $item['page_type'];
if ($item['node_rel_id'] !== null) {
Expand Down
42 changes: 42 additions & 0 deletions lib/Migration/Version2301Date20260930000000.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Tables\Migration;

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

class Version2301Date20260930000000 extends SimpleMigrationStep {

#[Override]
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();

if (!$schema->hasTable('tables_contexts_context')) {
return null;
}

$contexts = $schema->getTable('tables_contexts_context');

if (!$contexts->hasColumn('tab_view_enabled')) {
$contexts->addColumn('tab_view_enabled', Types::BOOLEAN, [
'notnull' => false,
'default' => false,
'comment' => 'Show the application resources as tabs instead of stacked',
]);
}

return $schema;
}
}
1 change: 1 addition & 0 deletions lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@
* description: string,
* owner: string,
* ownerType: int,
* tabViewEnabled: bool,
* }
*
* @psalm-type TablesContextNavigation = array{
Expand Down
8 changes: 6 additions & 2 deletions lib/Service/ContextService.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,14 @@ public function findById(int $id, ?string $userId): Context {
* @psalm-param list<array{id: int, type: int, permissions?: int, order?: int}> $nodes
* @throws Exception|PermissionError|InvalidArgumentException
*/
public function create(string $name, string $iconName, string $description, array $nodes, string $ownerId, int $ownerType): Context {
public function create(string $name, string $iconName, string $description, array $nodes, string $ownerId, int $ownerType, bool $tabViewEnabled = false): Context {
$context = new Context();
$context->setName(trim($name));
$context->setIcon(trim($iconName));
$context->setDescription(trim($description));
$context->setOwnerId($ownerId);
$context->setOwnerType($ownerType);
$context->setTabViewEnabled($tabViewEnabled);

$this->atomic(function () use ($context, $nodes): void {
$this->contextMapper->insert($context);
Expand All @@ -159,7 +160,7 @@ public function create(string $name, string $iconName, string $description, arra
* @throws DoesNotExistException
* @throws PermissionError|MultipleObjectsReturnedException
*/
public function update(int $contextId, string $userId, ?string $name, ?string $iconName, ?string $description, ?array $nodes): Context {
public function update(int $contextId, string $userId, ?string $name, ?string $iconName, ?string $description, ?array $nodes, ?bool $tabViewEnabled = null): Context {
$context = $this->contextMapper->findById($contextId, $userId);

if ($name !== null) {
Expand All @@ -171,6 +172,9 @@ public function update(int $contextId, string $userId, ?string $name, ?string $i
if ($description !== null) {
$context->setDescription(trim($description));
}
if ($tabViewEnabled !== null) {
$context->setTabViewEnabled($tabViewEnabled);
}

$hasUpdatedNodeInformation = false;
if ($nodes !== null) {
Expand Down
Loading
Loading