From edb7fb6f1d51f0ad71a33c8534687cb9a9c31adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 25 Apr 2024 13:51:25 +0200 Subject: [PATCH 1/6] fix: Avoid failing if a view filter contains a meta column MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/Row2Mapper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/Db/Row2Mapper.php b/lib/Db/Row2Mapper.php index f7bbdd167..c999821d7 100644 --- a/lib/Db/Row2Mapper.php +++ b/lib/Db/Row2Mapper.php @@ -272,7 +272,8 @@ private function getFilter(IQueryBuilder &$qb, array $filterGroup): array { $filterExpressions = []; foreach ($filterGroup as $filter) { $columnId = $filter['columnId']; - if (!isset($this->columns[$columnId]) && !isset($this->allColumns[$columnId])) { + // Fail if the filter is for a column that is not in the list and no meta column + if (!isset($this->columns[$columnId]) && !isset($this->allColumns[$columnId]) && $columnId > 0) { throw new InternalError('No column found to build filter with for id ' . $columnId); } $column = $this->columns[$columnId] ?? $this->allColumns[$columnId]; From 5c329039934942527b88dddfbada1148b18e8e39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 25 Apr 2024 13:51:51 +0200 Subject: [PATCH 2/6] chore: Move meta column identifiers to constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/Column.php | 7 +++++++ lib/Db/Row2Mapper.php | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/Db/Column.php b/lib/Db/Column.php index 60a15bcc6..a1c820c48 100644 --- a/lib/Db/Column.php +++ b/lib/Db/Column.php @@ -62,6 +62,13 @@ * @method setDatetimeDefault(?string $datetimeDefault) */ class Column extends Entity implements JsonSerializable { + // Meta column types + public const TYPE_META_ID = -1; + public const TYPE_META_CREATED = -2; + public const TYPE_META_CREATED_AT = -3; + public const TYPE_META_UPDATED = -4; + public const TYPE_META_UPDATED_AT = -5; + public const TYPE_SELECTION = 'selection'; public const TYPE_TEXT = 'text'; public const TYPE_NUMBER = 'number'; diff --git a/lib/Db/Row2Mapper.php b/lib/Db/Row2Mapper.php index c999821d7..3f1e909c4 100644 --- a/lib/Db/Row2Mapper.php +++ b/lib/Db/Row2Mapper.php @@ -407,20 +407,20 @@ private function getMetaFilterExpression(IQueryBuilder $qb, int $columnId, strin $qb2->from('tables_row_sleeves'); switch ($columnId) { - case -1: // row ID + case Column::TYPE_META_ID: $qb2->where($this->getSqlOperator($operator, $qb, 'id', (int)$value, IQueryBuilder::PARAM_INT)); break; - case -2: // created by + case Column::TYPE_META_CREATED: $qb2->where($this->getSqlOperator($operator, $qb, 'created_by', $value, IQueryBuilder::PARAM_STR)); break; - case -3: // created at + case Column::TYPE_META_CREATED_AT: $value = new \DateTimeImmutable($value); $qb2->where($this->getSqlOperator($operator, $qb, 'created_at', $value, IQueryBuilder::PARAM_DATE)); break; - case -4: // last edit by + case Column::TYPE_META_UPDATED: $qb2->where($this->getSqlOperator($operator, $qb, 'last_edit_by', $value, IQueryBuilder::PARAM_STR)); break; - case -5: // last edit at + case Column::TYPE_META_UPDATED_AT: $value = new \DateTimeImmutable($value); $qb2->where($this->getSqlOperator($operator, $qb, 'last_edit_at', $value, IQueryBuilder::PARAM_DATE)); break; From d8ba95430f519782ab424cf31b29182759efbda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 25 Apr 2024 16:31:09 +0200 Subject: [PATCH 3/6] Revert "fix: do not use negative indices" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 91c8db91f819e3a7c19121369fe5e148e61cca5a. Signed-off-by: Julius Härtl --- lib/Service/TableTemplateService.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Service/TableTemplateService.php b/lib/Service/TableTemplateService.php index 4ccd945b1..d26d2eb37 100644 --- a/lib/Service/TableTemplateService.php +++ b/lib/Service/TableTemplateService.php @@ -469,8 +469,8 @@ private function makeVacationRequests(Table $table):void { 'title' => $this->l->t('Create Vacation Request'), 'emoji' => '️➕', 'columns' => json_encode([$columns['employee']->getId(), $columns['from']->getId(), $columns['to']->getId(), $columns['workingDays']->getId(), $columns['dateRequest']->getId()]), - 'sort' => json_encode([["columnId" => $columns['from']->getId(), "mode" => "ASC"]]), - 'filter' => json_encode([[["columnId" => $columns['employee']->getId(), "operator" => "is-equal", "value" => "@my-name"], ["columnId" => $columns['approved']->getId(), "operator" => "is-empty", "value" => ""]]]), + 'sort' => json_encode([["columnId" => -5, "mode" => "ASC"]]), + 'filter' => json_encode([[["columnId" => -2, "operator" => "is-equal", "value" => "@my-name"], ["columnId" => $columns['approved']->getId(), "operator" => "is-empty", "value" => ""]]]), ] ); $this->createView($table, @@ -491,8 +491,8 @@ private function makeVacationRequests(Table $table):void { 'columns' => json_encode(array_values(array_map(function ($col) { return $col->getId(); }, $columns))), - 'sort' => json_encode([["columnId" => $columns['dateRequest']->getId(), "mode" => "ASC"]]), - 'filter' => json_encode([[["columnId" => $columns['employee']->getId(), "operator" => "is-equal", "value" => "@my-name"]]]), + 'sort' => json_encode([["columnId" => -3, "mode" => "ASC"]]), + 'filter' => json_encode([[["columnId" => -2, "operator" => "is-equal", "value" => "@my-name"]]]), ] ); $this->createView($table, @@ -502,7 +502,7 @@ private function makeVacationRequests(Table $table):void { 'columns' => json_encode(array_values(array_map(function ($col) { return $col->getId(); }, $columns))), - 'sort' => json_encode([["columnId" => $columns['dateRequest']->getId(), "mode" => "ASC"]]), + 'sort' => json_encode([["columnId" => -3, "mode" => "ASC"]]), 'filter' => json_encode([[["columnId" => $columns['approved']->getId(), "operator" => "is-equal", "value" => "@checked"]], [["columnId" => $columns['approved']->getId(), "operator" => "is-equal", "value" => "@unchecked"]]]), ] ); From ea87e4c4b9b9bd5a38fc173e6a84fb93310bc189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 25 Apr 2024 16:44:28 +0200 Subject: [PATCH 4/6] fix: Use proper old mapping of meta column ids MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/Column.php | 6 +++--- lib/Db/ColumnTypes/SuperColumnQB.php | 11 ++++++----- lib/Db/Row2Mapper.php | 13 ++++--------- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/lib/Db/Column.php b/lib/Db/Column.php index a1c820c48..a59fd586b 100644 --- a/lib/Db/Column.php +++ b/lib/Db/Column.php @@ -64,9 +64,9 @@ class Column extends Entity implements JsonSerializable { // Meta column types public const TYPE_META_ID = -1; - public const TYPE_META_CREATED = -2; - public const TYPE_META_CREATED_AT = -3; - public const TYPE_META_UPDATED = -4; + public const TYPE_META_CREATED_BY = -2; + public const TYPE_META_UPDATED_BY = -3; + public const TYPE_META_CREATED_AT = -4; public const TYPE_META_UPDATED_AT = -5; public const TYPE_SELECTION = 'selection'; diff --git a/lib/Db/ColumnTypes/SuperColumnQB.php b/lib/Db/ColumnTypes/SuperColumnQB.php index 0607dfd9c..140925c21 100644 --- a/lib/Db/ColumnTypes/SuperColumnQB.php +++ b/lib/Db/ColumnTypes/SuperColumnQB.php @@ -2,6 +2,7 @@ namespace OCA\Tables\Db\ColumnTypes; +use OCA\Tables\Db\Column; use OCA\Tables\Errors\InternalError; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryFunction; @@ -96,15 +97,15 @@ private function getFormattedDataCellValue(string $columnPlaceHolder, int $colum */ public static function getMetaColumnName(int $metaId): string { switch ($metaId) { - case -1: + case Column::TYPE_META_ID: return 'id'; - case -2: + case Column::TYPE_META_CREATED_BY: return 'created_by'; - case -3: + case Column::TYPE_META_UPDATED_BY: return 'last_edit_by'; - case -4: + case Column::TYPE_META_CREATED_AT: return 'created_at'; - case -5: + case Column::TYPE_META_UPDATED_AT: return 'last_edit_at'; default: throw new InternalError('No meta data column exists with id ' . $metaId); diff --git a/lib/Db/Row2Mapper.php b/lib/Db/Row2Mapper.php index 3f1e909c4..65a4077fa 100644 --- a/lib/Db/Row2Mapper.php +++ b/lib/Db/Row2Mapper.php @@ -276,10 +276,11 @@ private function getFilter(IQueryBuilder &$qb, array $filterGroup): array { if (!isset($this->columns[$columnId]) && !isset($this->allColumns[$columnId]) && $columnId > 0) { throw new InternalError('No column found to build filter with for id ' . $columnId); } - $column = $this->columns[$columnId] ?? $this->allColumns[$columnId]; // if is normal column if ($columnId >= 0) { + $column = $this->columns[$columnId] ?? $this->allColumns[$columnId]; + $sql = $qb->expr()->in( 'id', $qb->createFunction($this->getFilterExpression($qb, $column, $filter['operator'], $filter['value'])->getSQL()) @@ -393,12 +394,6 @@ private function getFilterExpression(IQueryBuilder $qb, Column $column, string $ } /** - * - * -1 => 'number', ID - * -2 => 'text-line', Created - * -3 => 'datetime', At - * -4 => 'text-line', LastEdit - * -5 => 'datetime', At * @throws InternalError */ private function getMetaFilterExpression(IQueryBuilder $qb, int $columnId, string $operator, string $value): IQueryBuilder { @@ -410,14 +405,14 @@ private function getMetaFilterExpression(IQueryBuilder $qb, int $columnId, strin case Column::TYPE_META_ID: $qb2->where($this->getSqlOperator($operator, $qb, 'id', (int)$value, IQueryBuilder::PARAM_INT)); break; - case Column::TYPE_META_CREATED: + case Column::TYPE_META_CREATED_BY: $qb2->where($this->getSqlOperator($operator, $qb, 'created_by', $value, IQueryBuilder::PARAM_STR)); break; case Column::TYPE_META_CREATED_AT: $value = new \DateTimeImmutable($value); $qb2->where($this->getSqlOperator($operator, $qb, 'created_at', $value, IQueryBuilder::PARAM_DATE)); break; - case Column::TYPE_META_UPDATED: + case Column::TYPE_META_UPDATED_BY: $qb2->where($this->getSqlOperator($operator, $qb, 'last_edit_by', $value, IQueryBuilder::PARAM_STR)); break; case Column::TYPE_META_UPDATED_AT: From a57296b50edf0546999277bc1a435ec8d7c67875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Thu, 25 Apr 2024 16:45:28 +0200 Subject: [PATCH 5/6] chore: Move frontend to meta type constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- .../components/ncTable/mixins/exportTableMixin.js | 13 ++++++++----- src/shared/components/ncTable/partials/TableRow.vue | 13 ++++++++----- .../components/ncTable/sections/CustomTable.vue | 13 ++++++++----- src/shared/constants.js | 11 +++++++++++ 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/shared/components/ncTable/mixins/exportTableMixin.js b/src/shared/components/ncTable/mixins/exportTableMixin.js index 4beb21a1c..b89d2a2f9 100644 --- a/src/shared/components/ncTable/mixins/exportTableMixin.js +++ b/src/shared/components/ncTable/mixins/exportTableMixin.js @@ -1,5 +1,8 @@ import moment from '@nextcloud/moment' import generalHelper from '../../../mixins/generalHelper.js' +import { + TYPE_META_ID, TYPE_META_CREATED_BY, TYPE_META_CREATED_AT, TYPE_META_UPDATED_BY, TYPE_META_UPDATED_AT, +} from '../../../../shared/constants.js' export default { @@ -23,19 +26,19 @@ export default { } else { // if is a meta data column (id < 0) switch (column.id) { - case -1: + case TYPE_META_ID: rowData[column.title] = row.id break - case -2: + case TYPE_META_CREATED_BY: rowData[column.title] = row.createdBy break - case -3: + case TYPE_META_UPDATED_BY: rowData[column.title] = row.lastEditBy break - case -4: + case TYPE_META_CREATED_AT: rowData[column.title] = row.createdAt break - case -5: + case TYPE_META_UPDATED_AT: rowData[column.title] = row.lastEditAt break } diff --git a/src/shared/components/ncTable/partials/TableRow.vue b/src/shared/components/ncTable/partials/TableRow.vue index 40cbbe76a..483e563e7 100644 --- a/src/shared/components/ncTable/partials/TableRow.vue +++ b/src/shared/components/ncTable/partials/TableRow.vue @@ -35,6 +35,9 @@ import TableCellMultiSelection from './TableCellMultiSelection.vue' import TableCellTextRich from './TableCellEditor.vue' import { ColumnTypes } from './../mixins/columnHandler.js' import { translate as t } from '@nextcloud/l10n' +import { + TYPE_META_ID, TYPE_META_CREATED_BY, TYPE_META_CREATED_AT, TYPE_META_UPDATED_BY, TYPE_META_UPDATED_AT, +} from '../../../../shared/constants.js' export default { name: 'TableRow', @@ -110,19 +113,19 @@ export default { // See metaColumns.js for mapping let value switch (columnId) { - case -1: + case TYPE_META_ID: value = this.row.id break - case -2: + case TYPE_META_CREATED_BY: value = this.row.createdBy break - case -3: + case TYPE_META_UPDATED_BY: value = this.row.lastEditBy break - case -4: + case TYPE_META_CREATED_AT: value = this.row.createdAt break - case -5: + case TYPE_META_UPDATED_AT: value = this.row.lastEditAt break } diff --git a/src/shared/components/ncTable/sections/CustomTable.vue b/src/shared/components/ncTable/sections/CustomTable.vue index e0dc0ed41..0acd674cb 100644 --- a/src/shared/components/ncTable/sections/CustomTable.vue +++ b/src/shared/components/ncTable/sections/CustomTable.vue @@ -39,6 +39,9 @@ import TableHeader from '../partials/TableHeader.vue' import TableRow from '../partials/TableRow.vue' import { subscribe, unsubscribe } from '@nextcloud/event-bus' import { MagicFields } from '../mixins/magicFields.js' +import { + TYPE_META_ID, TYPE_META_CREATED_BY, TYPE_META_CREATED_AT, TYPE_META_UPDATED_BY, TYPE_META_UPDATED_AT, +} from '../../../../shared/constants.js' export default { name: 'CustomTable', @@ -140,19 +143,19 @@ export default { if (column.id < 0) { cell = { columnId: column.id } switch (column.id) { - case -1: + case TYPE_META_ID: cell.value = row.id break - case -2: + case TYPE_META_CREATED_BY: cell.value = row.createdBy break - case -3: + case TYPE_META_UPDATED_BY: cell.value = row.editedBy break - case -4: + case TYPE_META_CREATED_AT: cell.value = row.createdAt break - case -5: + case TYPE_META_UPDATED_AT: cell.value = row.editedAt break } diff --git a/src/shared/constants.js b/src/shared/constants.js index ceb32e169..98ac005ec 100644 --- a/src/shared/constants.js +++ b/src/shared/constants.js @@ -29,3 +29,14 @@ export const PERMISSION_UPDATE = 4 export const PERMISSION_DELETE = 8 export const PERMISSION_MANAGE = 16 export const PERMISSION_ALL = 31 + +export const TYPE_META_ID = -1 +export const TYPE_META_CREATED_BY = -2 +export const TYPE_META_UPDATED_BY = -3 +export const TYPE_META_CREATED_AT = -4 +export const TYPE_META_UPDATED_AT = -5 + +export const TYPE_SELECTION = 'selection' +export const TYPE_TEXT = 'text' +export const TYPE_NUMBER = 'number' +export const TYPE_DATETIME = 'datetime' From abdafbf6bff7cddc208ccc837764430137a2c871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Mon, 29 Apr 2024 09:58:28 +0200 Subject: [PATCH 6/6] chore: Use constants for meta columns everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/ColumnMapper.php | 10 +++++----- lib/Service/TableTemplateService.php | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/Db/ColumnMapper.php b/lib/Db/ColumnMapper.php index ea76c0d95..4029b5232 100644 --- a/lib/Db/ColumnMapper.php +++ b/lib/Db/ColumnMapper.php @@ -110,11 +110,11 @@ public function getColumnTypes(array $neededColumnIds): array { // Initialise return array with column types of the meta columns: id, created_by, created_at, last_edit_by, last_edit_at $out = [ - -1 => 'number', - -2 => 'text-line', - -3 => 'datetime', - -4 => 'text-line', - -5 => 'datetime', + Column::TYPE_META_ID => 'number', + Column::TYPE_META_CREATED_BY => 'text-line', + Column::TYPE_META_CREATED_AT => 'datetime', + Column::TYPE_META_UPDATED_BY => 'text-line', + Column::TYPE_META_UPDATED_AT => 'datetime', ]; $result = $qb->executeQuery(); try { diff --git a/lib/Service/TableTemplateService.php b/lib/Service/TableTemplateService.php index d26d2eb37..9f3d2213b 100644 --- a/lib/Service/TableTemplateService.php +++ b/lib/Service/TableTemplateService.php @@ -469,8 +469,8 @@ private function makeVacationRequests(Table $table):void { 'title' => $this->l->t('Create Vacation Request'), 'emoji' => '️➕', 'columns' => json_encode([$columns['employee']->getId(), $columns['from']->getId(), $columns['to']->getId(), $columns['workingDays']->getId(), $columns['dateRequest']->getId()]), - 'sort' => json_encode([["columnId" => -5, "mode" => "ASC"]]), - 'filter' => json_encode([[["columnId" => -2, "operator" => "is-equal", "value" => "@my-name"], ["columnId" => $columns['approved']->getId(), "operator" => "is-empty", "value" => ""]]]), + 'sort' => json_encode([["columnId" => Column::TYPE_META_UPDATED_AT, "mode" => "ASC"]]), + 'filter' => json_encode([[["columnId" => Column::TYPE_META_CREATED_BY, "operator" => "is-equal", "value" => "@my-name"], ["columnId" => $columns['approved']->getId(), "operator" => "is-empty", "value" => ""]]]), ] ); $this->createView($table, @@ -491,8 +491,8 @@ private function makeVacationRequests(Table $table):void { 'columns' => json_encode(array_values(array_map(function ($col) { return $col->getId(); }, $columns))), - 'sort' => json_encode([["columnId" => -3, "mode" => "ASC"]]), - 'filter' => json_encode([[["columnId" => -2, "operator" => "is-equal", "value" => "@my-name"]]]), + 'sort' => json_encode([["columnId" => Column::TYPE_META_UPDATED_BY, "mode" => "ASC"]]), + 'filter' => json_encode([[["columnId" => Column::TYPE_META_CREATED_BY, "operator" => "is-equal", "value" => "@my-name"]]]), ] ); $this->createView($table, @@ -502,7 +502,7 @@ private function makeVacationRequests(Table $table):void { 'columns' => json_encode(array_values(array_map(function ($col) { return $col->getId(); }, $columns))), - 'sort' => json_encode([["columnId" => -3, "mode" => "ASC"]]), + 'sort' => json_encode([["columnId" => Column::TYPE_META_UPDATED_BY, "mode" => "ASC"]]), 'filter' => json_encode([[["columnId" => $columns['approved']->getId(), "operator" => "is-equal", "value" => "@checked"]], [["columnId" => $columns['approved']->getId(), "operator" => "is-equal", "value" => "@unchecked"]]]), ] );