From b1f2d6fb4804b48c3e9a6a14ea7b68dd011ee2a9 Mon Sep 17 00:00:00 2001
From: Michael Haufe
Date: Thu, 10 Oct 2024 11:31:48 -0500
Subject: [PATCH] Created history UI and DB auditing (#391)
---
components/XDataTable.vue | 81 ++++++++-
migrations/.snapshot-cathedral.json | 161 +++++++++++-------
migrations/Migration20241009234603.ts | 16 ++
.../environment/assumptions.client.vue | 3 +-
.../environment/components.client.vue | 3 +-
.../environment/constraints.client.vue | 2 +-
.../environment/effects.client.vue | 3 +-
.../environment/glossary.client.vue | 3 +-
.../environment/invariants.client.vue | 3 +-
.../goals/functionality.client.vue | 3 +-
.../goals/limitations.client.vue | 3 +-
.../goals/obstacles.client.vue | 3 +-
.../[solution-slug]/goals/outcomes.client.vue | 3 +-
.../goals/scenarios.client.vue | 3 +-
.../goals/stakeholders.client.vue | 2 +-
.../project/roles-personnel.client.vue | 3 +-
.../system/components.client.vue | 2 +-
.../system/functionality.client.vue | 2 +-
.../system/scenarios.client.vue | 6 +-
pages/o/[organization-slug]/users.vue | 7 +-
server/api/audit-log/index.get.ts | 34 ++++
server/data/subscribers/AuditSubscriber.ts | 2 +
server/domain/AuditLog.ts | 29 +++-
23 files changed, 287 insertions(+), 90 deletions(-)
create mode 100644 migrations/Migration20241009234603.ts
create mode 100644 server/api/audit-log/index.get.ts
diff --git a/components/XDataTable.vue b/components/XDataTable.vue
index 02e55c91..b7074fc1 100644
--- a/components/XDataTable.vue
+++ b/components/XDataTable.vue
@@ -3,6 +3,7 @@ import type Dialog from 'primevue/dialog'
import type DataTable from 'primevue/datatable'
import { FilterMatchMode } from 'primevue/api';
import camelCaseToTitle from '~/utils/camelCaseToTitle.js';
+import { AuditLog } from '~/server/domain';
export type ViewFieldType = 'text' | 'textarea' | 'number' | 'date' | 'boolean' | 'hidden' | 'object'
@@ -15,6 +16,8 @@ const props = defineProps<{
createModel: { [K in keyof RowType]?: FormFieldType },
editModel: { [K in keyof RowType]?: FormFieldType },
loading: boolean,
+ showHistory: boolean,
+ organizationSlug: string,
onCreate: (data: RowType) => Promise,
onDelete: (id: string) => Promise,
onUpdate: (data: RowType) => Promise
@@ -35,7 +38,12 @@ const dataTable = ref(),
createDialogItem = ref(Object.create(null)),
editDialog = ref
+ :on-delete="onDelete" :on-update="onUpdate" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/environment/components.client.vue b/pages/o/[organization-slug]/[solution-slug]/environment/components.client.vue
index c8385ba1..5989c323 100644
--- a/pages/o/[organization-slug]/[solution-slug]/environment/components.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/environment/components.client.vue
@@ -68,6 +68,7 @@ const onUpdate = async (data: EnvironmentComponent) => {
+ :on-create="onCreate" :on-delete="onDelete" :on-update="onUpdate" :loading="status === 'pending'"
+ :show-history="true" :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/environment/constraints.client.vue b/pages/o/[organization-slug]/[solution-slug]/environment/constraints.client.vue
index 29ed8bdc..914520d7 100644
--- a/pages/o/[organization-slug]/[solution-slug]/environment/constraints.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/environment/constraints.client.vue
@@ -75,6 +75,6 @@ const onUpdate = async (data: Constraint) => {
:createModel="{ name: 'text', category: Object.values(ConstraintCategory), statement: 'text' }"
:editModel="{ id: 'hidden', name: 'text', category: Object.values(ConstraintCategory), statement: 'text' }"
:datasource="constraints" :on-create="onCreate" :on-delete="onDelete" :on-update="onUpdate"
- :loading="status === 'pending'">
+ :loading="status === 'pending'" :show-history="true" :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/environment/effects.client.vue b/pages/o/[organization-slug]/[solution-slug]/environment/effects.client.vue
index 8778f849..aecc3889 100644
--- a/pages/o/[organization-slug]/[solution-slug]/environment/effects.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/environment/effects.client.vue
@@ -70,6 +70,7 @@ const onDelete = async (id: string) => {
+ :on-delete="onDelete" :on-update="onUpdate" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/environment/glossary.client.vue b/pages/o/[organization-slug]/[solution-slug]/environment/glossary.client.vue
index 8ed04911..d81fb0e1 100644
--- a/pages/o/[organization-slug]/[solution-slug]/environment/glossary.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/environment/glossary.client.vue
@@ -70,6 +70,7 @@ const onDelete = async (id: string) => {
+ :on-delete="onDelete" :on-update="onUpdate" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/environment/invariants.client.vue b/pages/o/[organization-slug]/[solution-slug]/environment/invariants.client.vue
index a98d2405..950e3d7a 100644
--- a/pages/o/[organization-slug]/[solution-slug]/environment/invariants.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/environment/invariants.client.vue
@@ -72,6 +72,7 @@ const onDelete = async (id: string) => {
+ :on-update="onUpdate" :on-delete="onDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/functionality.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/functionality.client.vue
index dd07e027..fade1150 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/functionality.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/functionality.client.vue
@@ -74,6 +74,7 @@ const onDelete = async (id: string) => {
+ :on-create="onCreate" :on-update="onUpdate" :on-delete="onDelete" :loading="status === 'pending'"
+ :show-history="true" :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/limitations.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/limitations.client.vue
index c5c6a1c8..e437091c 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/limitations.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/limitations.client.vue
@@ -71,6 +71,7 @@ const onDelete = async (id: string) => {
+ :on-update="onUpdate" :on-delete="onDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/obstacles.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/obstacles.client.vue
index 4fd61af6..085bf4a5 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/obstacles.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/obstacles.client.vue
@@ -68,6 +68,7 @@ const onDelete = async (id: string) => {
+ :on-update="onUpdate" :on-delete="onDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/outcomes.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/outcomes.client.vue
index b94c2510..db478df6 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/outcomes.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/outcomes.client.vue
@@ -72,6 +72,7 @@ const onDelete = async (id: string) => {
+ :onUpdate="onUpdate" :onDelete="onDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/scenarios.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/scenarios.client.vue
index 6c11ee4b..f534ee24 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/scenarios.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/scenarios.client.vue
@@ -119,6 +119,7 @@ const onUserStoryDelete = async (id: string) => {
functionalBehavior: { type: 'requirement', options: functionalBehaviors ?? [] },
outcome: { type: 'requirement', options: outcomes ?? [] }
}" :datasource="userStories" :onCreate="onUserStoryCreate" :onUpdate="onUserStoryUpdate"
- :onDelete="onUserStoryDelete" :loading="status === 'pending'">
+ :onDelete="onUserStoryDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/goals/stakeholders.client.vue b/pages/o/[organization-slug]/[solution-slug]/goals/stakeholders.client.vue
index 4333224b..bf17aae2 100644
--- a/pages/o/[organization-slug]/[solution-slug]/goals/stakeholders.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/goals/stakeholders.client.vue
@@ -139,7 +139,7 @@ const onDelete = async (id: string) => {
category: Object.values(StakeholderCategory),
segmentation: Object.values(StakeholderSegmentation)
}" :datasource="stakeholders" :on-create="onCreate" :on-update="onUpdate" :on-delete="onDelete"
- :loading="status === 'pending'">
+ :loading="status === 'pending'" :show-history="true" :organizationSlug="organizationslug">
diff --git a/pages/o/[organization-slug]/[solution-slug]/project/roles-personnel.client.vue b/pages/o/[organization-slug]/[solution-slug]/project/roles-personnel.client.vue
index f768e31f..3d5bdbde 100644
--- a/pages/o/[organization-slug]/[solution-slug]/project/roles-personnel.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/project/roles-personnel.client.vue
@@ -72,6 +72,7 @@ const onDelete = async (id: string) => {
+ :on-update="onUpdate" :on-delete="onDelete" :loading="status === 'pending'" :show-history="true"
+ :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/system/components.client.vue b/pages/o/[organization-slug]/[solution-slug]/system/components.client.vue
index f3130e42..1cb2efc3 100644
--- a/pages/o/[organization-slug]/[solution-slug]/system/components.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/system/components.client.vue
@@ -83,6 +83,6 @@ const onDelete = async (id: string) => {
statement: 'text',
parentComponent: { type: 'requirement', options: systemComponents ?? [] }
}" :datasource="systemComponents" :onCreate="onCreate" :onUpdate="onUpdate" :onDelete="onDelete"
- :loading="status === 'pending'">
+ :loading="status === 'pending'" :show-history="true" :organizationSlug="organizationslug">
\ No newline at end of file
diff --git a/pages/o/[organization-slug]/[solution-slug]/system/functionality.client.vue b/pages/o/[organization-slug]/[solution-slug]/system/functionality.client.vue
index 182bf0ee..8d3949c1 100644
--- a/pages/o/[organization-slug]/[solution-slug]/system/functionality.client.vue
+++ b/pages/o/[organization-slug]/[solution-slug]/system/functionality.client.vue
@@ -105,7 +105,7 @@ const componentSortField = ref('name')
{ This section is disabled temporarily. }