From 8b740a935dfbb383cc825d9e847719664eebe1b1 Mon Sep 17 00:00:00 2001 From: silver Date: Thu, 11 Sep 2025 17:31:28 +0200 Subject: [PATCH 01/22] add mandatory key to ViewColumnInformation Signed-off-by: silver --- lib/Service/ValueObject/ViewColumnInformation.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/Service/ValueObject/ViewColumnInformation.php b/lib/Service/ValueObject/ViewColumnInformation.php index 61b4ccf24b..590fed09df 100644 --- a/lib/Service/ValueObject/ViewColumnInformation.php +++ b/lib/Service/ValueObject/ViewColumnInformation.php @@ -18,23 +18,27 @@ class ViewColumnInformation implements ArrayAccess, JsonSerializable { public const KEY_ID = 'columnId'; public const KEY_ORDER = 'order'; public const KEY_READONLY = 'readonly'; + public const KEY_MANDATORY = 'mandatory'; - /** @var array{columndId?: int, order?: int, readonly?: bool} */ + /** @var array{columndId?: int, order?: int, readonly?: bool, mandatory?: bool} */ protected array $data = []; protected const KEYS = [ self::KEY_ID, self::KEY_ORDER, self::KEY_READONLY, + self::KEY_MANDATORY, ]; public function __construct( int $columnId, int $order, bool $readonly = false, + bool $mandatory = false, ) { $this->offsetSet(self::KEY_ID, $columnId); $this->offsetSet(self::KEY_ORDER, $order); $this->offsetSet(self::KEY_READONLY, $readonly); + $this->offsetSet(self::KEY_MANDATORY, $mandatory); } public function getId(): int { @@ -49,11 +53,16 @@ public function isReadonly(): bool { return $this->offsetGet(self::KEY_READONLY) ?? false; } + public function isMandatory(): bool { + return $this->offsetGet(self::KEY_MANDATORY) ?? false; + } + public static function fromArray(array $data): static { $vci = new static( $data[self::KEY_ID], $data[self::KEY_ORDER], $data[self::KEY_READONLY] ?? false, + $data[self::KEY_MANDATORY] ?? false, ); return $vci; @@ -91,6 +100,7 @@ protected function ensureType(string $offset, mixed $value): mixed { self::KEY_ID, self::KEY_ORDER => (int)$value, self::KEY_READONLY => (bool)$value, + self::KEY_MANDATORY => (bool)$value, default => throw new \InvalidArgumentException("Invalid offset: $offset"), }; } From 97dd91526eeecfef1651fdc9c92e506ae1eefa21 Mon Sep 17 00:00:00 2001 From: silver Date: Thu, 11 Sep 2025 17:36:04 +0200 Subject: [PATCH 02/22] add mandatory key to viewsettings Signed-off-by: silver --- .../editViewPartials/SelectedViewColumns.vue | 37 +++++++++++++++++-- src/modules/modals/ViewSettings.vue | 1 + 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue b/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue index 00d579174e..a89c020cc5 100644 --- a/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue +++ b/src/modules/main/partials/editViewPartials/SelectedViewColumns.vue @@ -23,7 +23,10 @@ :checked="selectedColumns.includes(column.id)" class="display-checkbox" @update:checked="onToggle(column.id)" /> - {{ column.title }} + + {{ column.title }} + * +
({{ t('tables', 'Metadata') }})
@@ -31,13 +34,24 @@
+ {{ t('tables', 'Read only') }} + + + {{ t('tables', 'Mandatory') }} +
@@ -146,8 +160,18 @@ export default { }, onReadonlyChanged(columnId, readonly) { const column = this.mutableColumns.find(col => col.id === columnId) - if (column) { - column.viewColumnInformation.readonly = readonly + if (!column) return + column.viewColumnInformation.readonly = readonly + if (readonly) { + column.viewColumnInformation.mandatory = false + } + }, + onMandatoryChanged(columnId, mandatory) { + const column = this.mutableColumns.find(col => col.id === columnId) + if (!column) return + column.viewColumnInformation.mandatory = mandatory + if (mandatory) { + column.viewColumnInformation.readonly = false } }, async dragEnd(goalIndex) { @@ -249,4 +273,11 @@ export default { .locallyRemoved { background-color: var(--color-error-hover); } + +.mandatory-indicator { + color: var(--color-error); + margin-left: 4px; + font-size: 16px; + line-height: 1; +} diff --git a/src/modules/modals/ViewSettings.vue b/src/modules/modals/ViewSettings.vue index 795d1fe196..afd18480a7 100644 --- a/src/modules/modals/ViewSettings.vue +++ b/src/modules/modals/ViewSettings.vue @@ -309,6 +309,7 @@ export default { columnId: col.id, order: index, readonly: col.viewColumnInformation?.readonly, + mandatory: col.viewColumnInformation?.mandatory ?? false, })) const data = { data: { From 60e2c8085aa85ea51a76ed319717804d4d0942c4 Mon Sep 17 00:00:00 2001 From: silver Date: Thu, 11 Sep 2025 17:38:01 +0200 Subject: [PATCH 03/22] check for mandatory in view col in rowhelper Signed-off-by: silver --- src/shared/components/ncTable/mixins/rowHelper.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shared/components/ncTable/mixins/rowHelper.js b/src/shared/components/ncTable/mixins/rowHelper.js index 172b093543..c45d7bf755 100644 --- a/src/shared/components/ncTable/mixins/rowHelper.js +++ b/src/shared/components/ncTable/mixins/rowHelper.js @@ -10,6 +10,7 @@ export default { isValueValidForColumn(value, column) { const type = column?.type?.split('-')[0] const columnTypeDefault = type + 'Default' + if (column.type === ColumnTypes.Selection) { if ( (value instanceof Array && value.length > 0) @@ -30,7 +31,8 @@ export default { checkMandatoryFields(row) { let mandatoryFieldsEmpty = false this.columns.forEach(col => { - if (col.mandatory) { + const isMandatory = col.viewColumnInformation?.mandatory ?? col.mandatory + if (isMandatory) { const validValue = this.isValueValidForColumn(row[col.id], col) mandatoryFieldsEmpty = mandatoryFieldsEmpty || !validValue } From 402e6baa2e6a349577e8c18a5e43310c6c4c504f Mon Sep 17 00:00:00 2001 From: silver Date: Thu, 11 Sep 2025 18:05:51 +0200 Subject: [PATCH 04/22] check for mandatory view cols in different types Signed-off-by: silver --- src/shared/components/ncTable/partials/TableCellDateTime.vue | 2 +- .../ncTable/partials/rowTypePartials/DatetimeDateForm.vue | 4 ++-- .../ncTable/partials/rowTypePartials/DatetimeForm.vue | 2 +- .../ncTable/partials/rowTypePartials/DatetimeTimeForm.vue | 2 +- .../ncTable/partials/rowTypePartials/NumberForm.vue | 2 +- .../ncTable/partials/rowTypePartials/NumberProgressForm.vue | 2 +- .../ncTable/partials/rowTypePartials/NumberStarsForm.vue | 2 +- .../ncTable/partials/rowTypePartials/SelectionCheckForm.vue | 2 +- .../ncTable/partials/rowTypePartials/SelectionForm.vue | 2 +- .../ncTable/partials/rowTypePartials/SelectionMultiForm.vue | 2 +- .../ncTable/partials/rowTypePartials/TextLineForm.vue | 2 +- .../ncTable/partials/rowTypePartials/TextLinkForm.vue | 2 +- .../ncTable/partials/rowTypePartials/TextLongForm.vue | 2 +- .../ncTable/partials/rowTypePartials/TextRichForm.vue | 2 +- .../ncTable/partials/rowTypePartials/UsergroupForm.vue | 2 +- 15 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/shared/components/ncTable/partials/TableCellDateTime.vue b/src/shared/components/ncTable/partials/TableCellDateTime.vue index 9a623c3caa..bce5d6da7f 100644 --- a/src/shared/components/ncTable/partials/TableCellDateTime.vue +++ b/src/shared/components/ncTable/partials/TableCellDateTime.vue @@ -89,7 +89,7 @@ export default { }, canBeCleared() { - return !this.column.mandatory + return !(this.column.viewColumnInformation?.mandatory ?? this.column.mandatory) }, }, diff --git a/src/shared/components/ncTable/partials/rowTypePartials/DatetimeDateForm.vue b/src/shared/components/ncTable/partials/rowTypePartials/DatetimeDateForm.vue index a59c8b5916..7d3373cc06 100644 --- a/src/shared/components/ncTable/partials/rowTypePartials/DatetimeDateForm.vue +++ b/src/shared/components/ncTable/partials/rowTypePartials/DatetimeDateForm.vue @@ -3,7 +3,7 @@ - SPDX-License-Identifier: AGPL-3.0-or-later -->