Add document types filtering and rename ISMS to GOVERNANCE
Adds 5 new document types (PLAN, REGISTER, RECORD, REPORT, TEMPLATE), renames ISMS to GOVERNANCE, and implements type-based filtering across GraphQL, MCP, and frontend. Includes migration, enum updates, filter implementation with SQL array support, and frontend dropdown UI with Relay refetch pattern. Signed-off-by: Bryan Frimin <bryan@getprobo.com>
This commit is contained in:
@@ -25,6 +25,7 @@ type (
|
||||
trustCenterVisibilities []TrustCenterVisibility
|
||||
published *bool
|
||||
userEmail *mail.Addr
|
||||
documentTypes []DocumentType
|
||||
}
|
||||
)
|
||||
|
||||
@@ -55,6 +56,11 @@ func (f *DocumentFilter) WithUserEmail(userEmail *mail.Addr) *DocumentFilter {
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *DocumentFilter) WithDocumentTypes(documentTypes []DocumentType) *DocumentFilter {
|
||||
f.documentTypes = documentTypes
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *DocumentFilter) SQLArguments() pgx.NamedArgs {
|
||||
var visibilities []string
|
||||
if f.trustCenterVisibilities != nil {
|
||||
@@ -63,11 +69,21 @@ func (f *DocumentFilter) SQLArguments() pgx.NamedArgs {
|
||||
visibilities[i] = v.String()
|
||||
}
|
||||
}
|
||||
|
||||
var documentTypes []string
|
||||
if f.documentTypes != nil {
|
||||
documentTypes = make([]string, len(f.documentTypes))
|
||||
for i, dt := range f.documentTypes {
|
||||
documentTypes[i] = dt.String()
|
||||
}
|
||||
}
|
||||
|
||||
return pgx.NamedArgs{
|
||||
"query": f.query,
|
||||
"trust_center_visibilities": visibilities,
|
||||
"published": f.published,
|
||||
"user_email": f.userEmail,
|
||||
"document_types": documentTypes,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,5 +125,11 @@ func (f *DocumentFilter) SQLFragment() string {
|
||||
AND dvs.state IN ('REQUESTED', 'SIGNED')
|
||||
)
|
||||
END
|
||||
AND
|
||||
CASE
|
||||
WHEN @document_types::document_type[] IS NOT NULL THEN
|
||||
document_type = ANY(@document_types::document_type[])
|
||||
ELSE TRUE
|
||||
END
|
||||
)`
|
||||
}
|
||||
|
||||
@@ -24,18 +24,28 @@ type (
|
||||
)
|
||||
|
||||
const (
|
||||
DocumentTypeOther DocumentType = "OTHER"
|
||||
DocumentTypeISMS DocumentType = "ISMS"
|
||||
DocumentTypePolicy DocumentType = "POLICY"
|
||||
DocumentTypeProcedure DocumentType = "PROCEDURE"
|
||||
DocumentTypeOther DocumentType = "OTHER"
|
||||
DocumentTypeGovernance DocumentType = "GOVERNANCE"
|
||||
DocumentTypePolicy DocumentType = "POLICY"
|
||||
DocumentTypeProcedure DocumentType = "PROCEDURE"
|
||||
DocumentTypePlan DocumentType = "PLAN"
|
||||
DocumentTypeRegister DocumentType = "REGISTER"
|
||||
DocumentTypeRecord DocumentType = "RECORD"
|
||||
DocumentTypeReport DocumentType = "REPORT"
|
||||
DocumentTypeTemplate DocumentType = "TEMPLATE"
|
||||
)
|
||||
|
||||
func DocumentTypes() []DocumentType {
|
||||
return []DocumentType{
|
||||
DocumentTypeOther,
|
||||
DocumentTypeISMS,
|
||||
DocumentTypeGovernance,
|
||||
DocumentTypePolicy,
|
||||
DocumentTypeProcedure,
|
||||
DocumentTypePlan,
|
||||
DocumentTypeRegister,
|
||||
DocumentTypeRecord,
|
||||
DocumentTypeReport,
|
||||
DocumentTypeTemplate,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,12 +59,22 @@ func (dt *DocumentType) UnmarshalText(data []byte) error {
|
||||
switch val {
|
||||
case DocumentTypeOther.String():
|
||||
*dt = DocumentTypeOther
|
||||
case DocumentTypeISMS.String():
|
||||
*dt = DocumentTypeISMS
|
||||
case DocumentTypeGovernance.String():
|
||||
*dt = DocumentTypeGovernance
|
||||
case DocumentTypePolicy.String():
|
||||
*dt = DocumentTypePolicy
|
||||
case DocumentTypeProcedure.String():
|
||||
*dt = DocumentTypeProcedure
|
||||
case DocumentTypePlan.String():
|
||||
*dt = DocumentTypePlan
|
||||
case DocumentTypeRegister.String():
|
||||
*dt = DocumentTypeRegister
|
||||
case DocumentTypeRecord.String():
|
||||
*dt = DocumentTypeRecord
|
||||
case DocumentTypeReport.String():
|
||||
*dt = DocumentTypeReport
|
||||
case DocumentTypeTemplate.String():
|
||||
*dt = DocumentTypeTemplate
|
||||
default:
|
||||
return fmt.Errorf("invalid DocumentType value: %q", val)
|
||||
}
|
||||
|
||||
6
pkg/coredata/migrations/20260319T130000Z.sql
Normal file
6
pkg/coredata/migrations/20260319T130000Z.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
ALTER TYPE document_type RENAME VALUE 'ISMS' TO 'GOVERNANCE';
|
||||
ALTER TYPE document_type ADD VALUE 'PLAN';
|
||||
ALTER TYPE document_type ADD VALUE 'REGISTER';
|
||||
ALTER TYPE document_type ADD VALUE 'RECORD';
|
||||
ALTER TYPE document_type ADD VALUE 'REPORT';
|
||||
ALTER TYPE document_type ADD VALUE 'TEMPLATE';
|
||||
@@ -971,10 +971,18 @@ enum VendorCategory
|
||||
enum DocumentType
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
ISMS @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeISMS")
|
||||
GOVERNANCE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeGovernance")
|
||||
POLICY @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
PROCEDURE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
|
||||
PLAN @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePlan")
|
||||
REGISTER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRegister")
|
||||
RECORD @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRecord")
|
||||
REPORT @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeReport")
|
||||
TEMPLATE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeTemplate")
|
||||
}
|
||||
|
||||
enum DocumentClassification
|
||||
@@ -1571,6 +1579,7 @@ input ControlFilter {
|
||||
|
||||
input DocumentFilter {
|
||||
query: String
|
||||
documentTypes: [DocumentType!]
|
||||
}
|
||||
|
||||
input MeasureFilter {
|
||||
|
||||
@@ -567,7 +567,8 @@ func (r *controlResolver) Documents(ctx context.Context, obj *types.Control, fir
|
||||
|
||||
var documentFilter = coredata.NewDocumentFilter(nil)
|
||||
if filter != nil {
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query)
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query).
|
||||
WithDocumentTypes(filter.DocumentTypes)
|
||||
}
|
||||
|
||||
page, err := prb.Documents.ListForControlID(ctx, obj.ID, cursor, documentFilter)
|
||||
@@ -6477,7 +6478,8 @@ func (r *organizationResolver) Documents(ctx context.Context, obj *types.Organiz
|
||||
|
||||
var documentFilter = coredata.NewDocumentFilter(nil)
|
||||
if filter != nil {
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query)
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query).
|
||||
WithDocumentTypes(filter.DocumentTypes)
|
||||
}
|
||||
|
||||
page, err := prb.Documents.ListByOrganizationID(ctx, obj.ID, cursor, documentFilter)
|
||||
@@ -7844,7 +7846,8 @@ func (r *riskResolver) Documents(ctx context.Context, obj *types.Risk, first *in
|
||||
|
||||
var documentFilter = coredata.NewDocumentFilter(nil)
|
||||
if filter != nil {
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query)
|
||||
documentFilter = coredata.NewDocumentFilter(filter.Query).
|
||||
WithDocumentTypes(filter.DocumentTypes)
|
||||
}
|
||||
|
||||
page, err := prb.Documents.ListForRiskID(ctx, obj.ID, cursor, documentFilter)
|
||||
|
||||
@@ -2019,7 +2019,8 @@ func (r *Resolver) ListDocumentsTool(ctx context.Context, req *mcp.CallToolReque
|
||||
query = input.Filter.Query
|
||||
}
|
||||
|
||||
documentFilter = coredata.NewDocumentFilter(query)
|
||||
documentFilter = coredata.NewDocumentFilter(query).
|
||||
WithDocumentTypes(input.Filter.DocumentTypes)
|
||||
}
|
||||
|
||||
docPage, err := prb.Documents.ListByOrganizationID(ctx, input.OrganizationID, cursor, documentFilter)
|
||||
|
||||
@@ -5038,9 +5038,14 @@ components:
|
||||
type: string
|
||||
enum:
|
||||
- OTHER
|
||||
- ISMS
|
||||
- GOVERNANCE
|
||||
- POLICY
|
||||
- PROCEDURE
|
||||
- PLAN
|
||||
- REGISTER
|
||||
- RECORD
|
||||
- REPORT
|
||||
- TEMPLATE
|
||||
go.probo.inc/mcpgen/type: go.probo.inc/probo/pkg/coredata.DocumentType
|
||||
|
||||
DocumentClassification:
|
||||
@@ -5314,6 +5319,11 @@ components:
|
||||
items:
|
||||
$ref: "#/components/schemas/TrustCenterVisibility"
|
||||
description: Trust center visibilities
|
||||
document_types:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/DocumentType"
|
||||
description: Document types
|
||||
|
||||
ListDocumentsOutput:
|
||||
type: object
|
||||
|
||||
@@ -52,10 +52,18 @@ type Organization implements Node {
|
||||
enum DocumentType
|
||||
@goModel(model: "go.probo.inc/probo/pkg/coredata.DocumentType") {
|
||||
OTHER @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeOther")
|
||||
ISMS @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeISMS")
|
||||
GOVERNANCE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeGovernance")
|
||||
POLICY @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePolicy")
|
||||
PROCEDURE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeProcedure")
|
||||
PLAN @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypePlan")
|
||||
REGISTER
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRegister")
|
||||
RECORD @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeRecord")
|
||||
REPORT @goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeReport")
|
||||
TEMPLATE
|
||||
@goEnum(value: "go.probo.inc/probo/pkg/coredata.DocumentTypeTemplate")
|
||||
}
|
||||
|
||||
type Document implements Node @nda {
|
||||
|
||||
@@ -177,7 +177,7 @@ func (s *DocumentService) exportPDFData(
|
||||
switch document.DocumentType {
|
||||
case coredata.DocumentTypePolicy:
|
||||
classification = docgen.ClassificationConfidential
|
||||
case coredata.DocumentTypeISMS:
|
||||
case coredata.DocumentTypeGovernance:
|
||||
classification = docgen.ClassificationSecret
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user