From 8a37176baaba649b97787fe4e728a58e6201a11d Mon Sep 17 00:00:00 2001 From: Ruben van der Linde Date: Fri, 20 Mar 2026 10:13:48 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20Implement=20case-types=20spec=20?= =?UTF-8?q?=E2=80=94=20V1=20admin=20tabs=20for=20result=20types,=20role=20?= =?UTF-8?q?types,=20properties,=20document=20types?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create ResultTypesTab.vue with CRUD for result types including archival action and retention period - Create RoleTypesTab.vue with CRUD for role types with generic role selection - Create PropertiesTab.vue with CRUD for property definitions with type and required flag - Create DocumentTypesTab.vue with CRUD for document types with category and required flag - Create shared sub-entity-tab.css for consistent tab styling - Update CaseTypeDetail.vue with 6-tab layout: General, Statuses, Results, Roles, Properties, Docs Implements: openspec/specs/case-types --- openspec/changes/case-types/.openspec.yaml | 2 + openspec/changes/case-types/design.md | 8 + openspec/changes/case-types/proposal.md | 12 ++ openspec/changes/case-types/tasks.md | 7 + openspec/config.yaml | 2 +- src/views/settings/CaseTypeDetail.vue | 40 +++- src/views/settings/tabs/DocumentTypesTab.vue | 181 ++++++++++++++++++ src/views/settings/tabs/PropertiesTab.vue | 182 +++++++++++++++++++ src/views/settings/tabs/ResultTypesTab.vue | 179 ++++++++++++++++++ src/views/settings/tabs/RoleTypesTab.vue | 158 ++++++++++++++++ src/views/settings/tabs/sub-entity-tab.css | 91 ++++++++++ 11 files changed, 855 insertions(+), 7 deletions(-) create mode 100644 openspec/changes/case-types/.openspec.yaml create mode 100644 openspec/changes/case-types/design.md create mode 100644 openspec/changes/case-types/proposal.md create mode 100644 openspec/changes/case-types/tasks.md create mode 100644 src/views/settings/tabs/DocumentTypesTab.vue create mode 100644 src/views/settings/tabs/PropertiesTab.vue create mode 100644 src/views/settings/tabs/ResultTypesTab.vue create mode 100644 src/views/settings/tabs/RoleTypesTab.vue create mode 100644 src/views/settings/tabs/sub-entity-tab.css diff --git a/openspec/changes/case-types/.openspec.yaml b/openspec/changes/case-types/.openspec.yaml new file mode 100644 index 0000000..d8b0ed0 --- /dev/null +++ b/openspec/changes/case-types/.openspec.yaml @@ -0,0 +1,2 @@ +schema: spec-driven +created: 2026-03-20 diff --git a/openspec/changes/case-types/design.md b/openspec/changes/case-types/design.md new file mode 100644 index 0000000..8a0e87e --- /dev/null +++ b/openspec/changes/case-types/design.md @@ -0,0 +1,8 @@ +# Case Types Design + +## Components +1. **ResultTypesTab.vue** - CRUD for result types with archival rules +2. **RoleTypesTab.vue** - CRUD for role types with generic role selection +3. **PropertiesTab.vue** - CRUD for property definitions +4. **DocumentTypesTab.vue** - CRUD for document types with direction +5. **CaseTypeDetail.vue** - Updated with new tabs diff --git a/openspec/changes/case-types/proposal.md b/openspec/changes/case-types/proposal.md new file mode 100644 index 0000000..fd983ae --- /dev/null +++ b/openspec/changes/case-types/proposal.md @@ -0,0 +1,12 @@ +# Case Types Implementation + +## Summary +Implement the V1 admin tabs for case type configuration: Result Types, Role Types, Property Definitions, and Document Types tabs. Also add publish validation and active case deletion blocking. + +## Scope +- REQ-CT-07: Result type management tab +- REQ-CT-08: Role type management tab +- REQ-CT-09: Property definition management tab +- REQ-CT-10: Document type management tab +- REQ-CT-15: Tab layout with all V1 tabs +- REQ-CT-02: Publish validation improvements diff --git a/openspec/changes/case-types/tasks.md b/openspec/changes/case-types/tasks.md new file mode 100644 index 0000000..cb2da05 --- /dev/null +++ b/openspec/changes/case-types/tasks.md @@ -0,0 +1,7 @@ +# Tasks + +- [x] TASK-CT-01: Create ResultTypesTab.vue +- [x] TASK-CT-02: Create RoleTypesTab.vue +- [x] TASK-CT-03: Create PropertiesTab.vue +- [x] TASK-CT-04: Create DocumentTypesTab.vue +- [x] TASK-CT-05: Integrate new tabs into CaseTypeDetail.vue diff --git a/openspec/config.yaml b/openspec/config.yaml index 28fd5a0..54eb1e1 100644 --- a/openspec/config.yaml +++ b/openspec/config.yaml @@ -1,4 +1,4 @@ -schema: conduction +schema: spec-driven context: | Project: Procest diff --git a/src/views/settings/CaseTypeDetail.vue b/src/views/settings/CaseTypeDetail.vue index 638f4c3..5594f54 100644 --- a/src/views/settings/CaseTypeDetail.vue +++ b/src/views/settings/CaseTypeDetail.vue @@ -41,18 +41,18 @@

{{ t('procest', 'Cannot publish:') }}

-

- {{ saveError }} +

+ {{ saveError }}

-

- {{ t('procest', 'Saved successfully') }} +

+ {{ t('procest', 'Saved successfully') }}

@@ -81,6 +81,22 @@ v-else-if="activeTab === 'statuses'" :case-type-id="caseTypeId" :is-create="isCreate" /> + + + + @@ -91,6 +107,10 @@ import { NcButton, NcLoadingIcon } from '@nextcloud/vue' import ArrowLeftIcon from 'vue-material-design-icons/ArrowLeft.vue' import GeneralTab from './tabs/GeneralTab.vue' import StatusesTab from './tabs/StatusesTab.vue' +import ResultTypesTab from './tabs/ResultTypesTab.vue' +import RoleTypesTab from './tabs/RoleTypesTab.vue' +import PropertiesTab from './tabs/PropertiesTab.vue' +import DocumentTypesTab from './tabs/DocumentTypesTab.vue' import { useObjectStore } from '../../store/modules/object.js' import { validateCaseType, validateForPublish } from '../../utils/caseTypeValidation.js' @@ -128,6 +148,10 @@ export default { ArrowLeftIcon, GeneralTab, StatusesTab, + ResultTypesTab, + RoleTypesTab, + PropertiesTab, + DocumentTypesTab, }, props: { caseTypeId: { @@ -159,6 +183,10 @@ export default { return [ { id: 'general', label: t('procest', 'General') }, { id: 'statuses', label: t('procest', 'Statuses') }, + { id: 'results', label: t('procest', 'Results') }, + { id: 'roles', label: t('procest', 'Roles') }, + { id: 'properties', label: t('procest', 'Properties') }, + { id: 'docs', label: t('procest', 'Docs') }, ] }, }, diff --git a/src/views/settings/tabs/DocumentTypesTab.vue b/src/views/settings/tabs/DocumentTypesTab.vue new file mode 100644 index 0000000..307f40a --- /dev/null +++ b/src/views/settings/tabs/DocumentTypesTab.vue @@ -0,0 +1,181 @@ + + + + + diff --git a/src/views/settings/tabs/PropertiesTab.vue b/src/views/settings/tabs/PropertiesTab.vue new file mode 100644 index 0000000..b5e811a --- /dev/null +++ b/src/views/settings/tabs/PropertiesTab.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/src/views/settings/tabs/ResultTypesTab.vue b/src/views/settings/tabs/ResultTypesTab.vue new file mode 100644 index 0000000..eae0de9 --- /dev/null +++ b/src/views/settings/tabs/ResultTypesTab.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/src/views/settings/tabs/RoleTypesTab.vue b/src/views/settings/tabs/RoleTypesTab.vue new file mode 100644 index 0000000..c47ef5d --- /dev/null +++ b/src/views/settings/tabs/RoleTypesTab.vue @@ -0,0 +1,158 @@ + + + + + diff --git a/src/views/settings/tabs/sub-entity-tab.css b/src/views/settings/tabs/sub-entity-tab.css new file mode 100644 index 0000000..cc23b30 --- /dev/null +++ b/src/views/settings/tabs/sub-entity-tab.css @@ -0,0 +1,91 @@ +.sub-entity-tab__notice { + color: var(--color-text-maxcontrast); + padding: 12px; + background: var(--color-background-dark); + border-radius: var(--border-radius); +} + +.sub-entity-tab__list { + display: flex; + flex-direction: column; + gap: 4px; + margin-bottom: 16px; +} + +.sub-entity-tab__empty { + color: var(--color-text-maxcontrast); + padding: 16px; + text-align: center; +} + +.sub-entity-row { + display: flex; + align-items: center; + gap: 10px; + padding: 8px 12px; + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + flex-wrap: wrap; +} + +.sub-entity-row__name { + font-weight: 500; + flex: 1; + min-width: 120px; +} + +.sub-entity-row__badge { + display: inline-block; + padding: 2px 8px; + border-radius: var(--border-radius-pill); + font-size: 11px; + font-weight: 500; + background: var(--color-background-dark); + color: var(--color-text-maxcontrast); +} + +.sub-entity-row__meta { + font-size: 12px; + color: var(--color-text-maxcontrast); +} + +.sub-entity-row__actions { + display: flex; + gap: 4px; + margin-left: auto; +} + +.sub-entity-row__edit-form { + width: 100%; +} + +.edit-row { + display: flex; + gap: 12px; + margin-bottom: 8px; +} + +.edit-field { + flex: 1; + min-width: 140px; +} + +.edit-field--full { + flex: 1 1 100%; +} + +.edit-field--small { + max-width: 100px; +} + +.edit-error { + color: var(--color-error); + font-size: 13px; + margin: 4px 0; +} + +.edit-actions { + display: flex; + gap: 8px; + margin-top: 8px; +}