diff --git a/src/app/eiffel/web.go b/src/app/eiffel/web.go index c427c6c43c61e8de79b5062bfbafff990937b8c2..3fd5113a85e49e5eccb431c9ee63ee1d1887a319 100644 --- a/src/app/eiffel/web.go +++ b/src/app/eiffel/web.go @@ -383,14 +383,14 @@ func registerNavigation(appCtx *hctx.AppCtx, webCtx *web.Ctx) { Position: 100, }) - // Projekt-Sammlung Button + // GEÄNDERT: URL korrigiert von "/project/list" zu "/project/list" webCtx.Navigation.Add("eiffel.project.collection", web.NavItem{ - URL: "/eiffel/projects", // Die URL zu deiner Projekt-Sammlung-Seite - Name: "Projekt-Sammlung", // Der Name, der angezeigt wird + URL: "/project/list", // Korrekte URL für das neue Project-Modul + Name: "Projekt-Sammlung", Display: func(io web.IO) (bool, error) { return true, nil }, - Position: 110, // Position in der Navigation; erscheint direkt nach dem EIFFEL-Button + Position: 110, }) } diff --git a/src/app/project/model.go b/src/app/project/model.go index 858689c14a6849b76340919bea2bed9176832551..0697f4341777157d9bd2e8a1290fedcf8e5ba0b8 100644 --- a/src/app/project/model.go +++ b/src/app/project/model.go @@ -13,40 +13,40 @@ import ( type Project struct { // ID is the unique MongoDB ObjectID that serves as the primary key // The omitempty tag excludes this field if it's empty during insertion - ID primitive.ObjectID bson:"_id,omitempty" json:"id" + ID primitive.ObjectID `bson:"_id,omitempty" json:"id"` // ProjectID is a human-readable unique identifier (e.g., "PRJ-2025-001") // This allows users to reference projects with meaningful IDs - ProjectID string bson:"project_id" json:"projectId" + ProjectID string `bson:"project_id" json:"projectId"` // Name is the display name of the project (e.g., "HARMONY Mobile") // This is what users see in the interface as the project title - Name string bson:"name" json:"name" + Name string `bson:"name" json:"name"` // Description provides detailed information about the project's purpose // This field is optional and can be empty for simple projects - Description string bson:"description" json:"description" + Description string `bson:"description" json:"description"` // StartDate defines when the project begins // Used for project timeline calculations and reporting - StartDate time.Time bson:"start_date" json:"startDate" + StartDate time.Time `bson:"start_date" json:"startDate"` // EndDate defines when the project is scheduled to complete // Must be after StartDate as enforced by business logic - EndDate time.Time bson:"end_date" json:"endDate" + EndDate time.Time `bson:"end_date" json:"endDate"` // CreatedBy stores the UUID of the user who created this project // This establishes ownership and is used for access control - CreatedBy uuid.UUID bson:"created_by" json:"createdBy" + CreatedBy uuid.UUID `bson:"created_by" json:"createdBy"` // CreatedAt records when this project was first created // Automatically set during project creation for audit trails - CreatedAt time.Time bson:"created_at" json:"createdAt" + CreatedAt time.Time `bson:"created_at" json:"createdAt"` // UpdatedAt tracks the last modification time // Uses pointer to allow nil values when no updates have occurred // The omitempty tag excludes this field if it's nil - UpdatedAt *time.Time bson:"updated_at,omitempty" json:"updatedAt,omitempty" + UpdatedAt *time.Time `bson:"updated_at,omitempty" json:"updatedAt,omitempty"` } // ProjectToCreate represents the data structure used when creating new projects @@ -55,28 +55,26 @@ type Project struct { type ProjectToCreate struct { // ProjectID must be provided by the user and must be unique // Validation ensures this field is not empty - ProjectID string json:"projectId" hvalidate:"required" + ProjectID string `json:"projectId" hvalidate:"required"` // Name is required and serves as the display title // Validation ensures this field is not empty - Name string json:"name" hvalidate:"required" - + Name string `json:"name" hvalidate:"required"` // Description is optional and can be left empty // No validation constraints are applied to this field - Description string json:"description" - + Description string `json:"description"` // StartDate is required and must be a valid date // Validation ensures this field is provided - StartDate time.Time json:"startDate" hvalidate:"required" + StartDate time.Time `json:"startDate" hvalidate:"required"` // EndDate is required and must be after StartDate // Basic validation ensures this field is provided // Business logic validation ensures it's after StartDate - EndDate time.Time json:"endDate" hvalidate:"required" + EndDate time.Time `json:"endDate" hvalidate:"required"` // CreatedBy is set by the system based on the current user // The - tag excludes this from JSON serialization as it's not user input - CreatedBy uuid.UUID json:"-" + CreatedBy uuid.UUID `json:"-"` } // ProjectToUpdate represents the data structure used when updating existing projects @@ -85,23 +83,23 @@ type ProjectToCreate struct { type ProjectToUpdate struct { // ID identifies which project to update using the MongoDB ObjectID // This field is populated from the URL parameter - ID primitive.ObjectID bson:"_id" json:"id" + ID primitive.ObjectID `bson:"_id" json:"id"` // Name can be updated and is required to be non-empty // Users can change the display name of their projects - Name string json:"name" hvalidate:"required" + Name string `json:"name" hvalidate:"required"` // Description can be updated and can be empty // Users can modify or clear the project description - Description string json:"description" + Description string `json:"description"` // StartDate can be updated but must remain valid // Users can adjust project timelines as needed - StartDate time.Time json:"startDate" hvalidate:"required" + StartDate time.Time `json:"startDate" hvalidate:"required"` // EndDate can be updated but must remain after StartDate // Business logic validation ensures timeline consistency - EndDate time.Time json:"endDate" hvalidate:"required" + EndDate time.Time `json:"endDate" hvalidate:"required"` } // ToUpdate converts a Project instance to a ProjectToUpdate structure @@ -127,11 +125,11 @@ type ProjectWithRequirements struct { // Requirements contains summary information for all requirements in this project // This is optimized for display purposes rather than full requirement details - Requirements []*RequirementSummary json:"requirements" + Requirements []*RequirementSummary `json:"requirements"` // RequirementCount provides a quick count of total requirements // This avoids the need to calculate len(Requirements) in templates - RequirementCount int json:"requirementCount" + RequirementCount int `json:"requirementCount"` } // RequirementSummary provides essential requirement information for project views @@ -140,29 +138,27 @@ type ProjectWithRequirements struct { type RequirementSummary struct { // ID is the unique MongoDB ObjectID for this requirement // Used for linking to detailed requirement views - ID primitive.ObjectID bson:"_id" json:"id" + ID primitive.ObjectID `bson:"_id" json:"id"` // RequirementID is a human-readable identifier for this requirement // Generated automatically if not provided (e.g., "REQ-abc123") - RequirementID string bson:"requirement_id" json:"requirementId" + RequirementID string `bson:"requirement_id" json:"requirementId"` // Condition describes the circumstances under which this requirement applies // This field comes from the requirement parsing and validation process - Condition string bson:"condition" json:"condition" - + Condition string `bson:"condition" json:"condition"` // System identifies which system or component this requirement affects // This helps organize requirements by their target systems - System string bson:"system" json:"system" - + System string `bson:"system" json:"system"` // Requirement contains the actual requirement text // This is the main content that describes what must be implemented - Requirement string bson:"requirement" json:"requirement" + Requirement string `bson:"requirement" json:"requirement"` // Status tracks the current state of this requirement // Possible values include "Entwurf", "In Prüfung", "Genehmigt", "Abgelehnt" - Status string bson:"status" json:"status" + Status string `bson:"status" json:"status"` // CreatedAt records when this requirement was first created // Used for sorting and audit purposes - CreatedAt time.Time bson:"created_at" json:"createdAt" -} \ No newline at end of file + CreatedAt time.Time `bson:"created_at" json:"createdAt"` +} diff --git a/src/app/project/web/web.go b/src/app/project/web/web.go index 198aff1e64ff14e07a472e95cdc3ba65d93d5a49..17509a565917357b4521efaf080648c24a8e83d2 100644 --- a/src/app/project/web/web.go +++ b/src/app/project/web/web.go @@ -7,6 +7,7 @@ import ( "net/http" "time" + "github.com/org-harmony/harmony/src/app/project" "github.com/org-harmony/harmony/src/app/user" "github.com/org-harmony/harmony/src/core/hctx" "github.com/org-harmony/harmony/src/core/validation" @@ -238,10 +239,10 @@ func projectDetailController(appCtx *hctx.AppCtx, webCtx *web.Ctx, service *proj // Render the project detail page with multiple template files err = io.Render( data, - "project.detail.page", // Main template name - "templates/project/detail-page.go.html", // Page wrapper template - "templates/project/_detail.go.html", // Project detail content - "templates/project/_requirements-list.go.html", // Requirements list partial + "project.detail.page", // Main template name + "project/detail-page.go.html", // Page wrapper template + "project/_detail.go.html", // Project detail content + "project/_requirements-list.go.html", // Requirements list partial ) if err != nil { diff --git a/src/cmd/web/main.go b/src/cmd/web/main.go index 69d561939125ef93ed71cb1ba6c6cbca19986b97..123ed173c1a8588213bfd2c4a8e78c9317ed9463 100644 --- a/src/cmd/web/main.go +++ b/src/cmd/web/main.go @@ -6,6 +6,8 @@ import ( "github.com/jackc/pgx/v5/pgxpool" "github.com/org-harmony/harmony/src/app/eiffel" homeWeb "github.com/org-harmony/harmony/src/app/home" + "github.com/org-harmony/harmony/src/app/project" + projectWeb "github.com/org-harmony/harmony/src/app/project/web" "github.com/org-harmony/harmony/src/app/template" templateWeb "github.com/org-harmony/harmony/src/app/template/web" "github.com/org-harmony/harmony/src/app/user" @@ -44,6 +46,13 @@ func main() { log.Fatalf("Error initializing MongoDB: %v", err) } + // NEU: MongoDB Manager für Project-Modul initialisieren + mongoManager, err := project.NewMongoManager("mongodb://localhost:27017", "harmony") + if err != nil { + log.Fatalf("Error initializing MongoDB Manager: %v", err) + } + defer mongoManager.Close() + provider, db := initDB(validator) defer db.Close() @@ -55,6 +64,7 @@ func main() { userWeb.RegisterController(appCtx, webCtx) templateWeb.RegisterController(appCtx, webCtx) eiffel.RegisterController(appCtx, webCtx) + projectWeb.RegisterController(appCtx, webCtx, mongoManager) util.Ok(web.Serve(r, webCtx.Config.Server)) }