// Create runs the create action. func (c *SpaceController) Create(ctx *app.CreateSpaceContext) error { _, err := login.ContextIdentity(ctx) if err != nil { return jsonapi.JSONErrorResponse(ctx, goa.ErrUnauthorized(err.Error())) } err = validateCreateSpace(ctx) if err != nil { return jsonapi.JSONErrorResponse(ctx, err) } return application.Transactional(c.db, func(appl application.Application) error { reqSpace := ctx.Payload.Data newSpace := space.Space{ Name: *reqSpace.Attributes.Name, } if reqSpace.Attributes.Description != nil { newSpace.Description = *reqSpace.Attributes.Description } space, err := appl.Spaces().Create(ctx, &newSpace) if err != nil { return jsonapi.JSONErrorResponse(ctx, err) } res := &app.SpaceSingle{ Data: ConvertSpace(ctx.RequestData, space), } ctx.ResponseData.Header().Set("Location", rest.AbsoluteURL(ctx.RequestData, app.SpaceHref(res.Data.ID))) return ctx.Created(res) }) }
// ConvertSpace converts between internal and external REST representation func ConvertSpace(request *goa.RequestData, p *space.Space, additional ...SpaceConvertFunc) *app.Space { selfURL := rest.AbsoluteURL(request, app.SpaceHref(p.ID)) relatedIterationList := rest.AbsoluteURL(request, fmt.Sprintf("/api/spaces/%s/iterations", p.ID.String())) relatedAreaList := rest.AbsoluteURL(request, fmt.Sprintf("/api/spaces/%s/areas", p.ID.String())) return &app.Space{ ID: &p.ID, Type: "spaces", Attributes: &app.SpaceAttributes{ Name: &p.Name, Description: &p.Description, CreatedAt: &p.CreatedAt, UpdatedAt: &p.UpdatedAt, Version: &p.Version, }, Links: &app.GenericLinks{ Self: &selfURL, }, Relationships: &app.SpaceRelationships{ Iterations: &app.RelationGeneric{ Links: &app.GenericLinks{ Related: &relatedIterationList, }, }, Areas: &app.RelationGeneric{ Links: &app.GenericLinks{ Related: &relatedAreaList, }, }, }, } }
// ConvertIteration converts between internal and external REST representation func ConvertIteration(request *goa.RequestData, itr *iteration.Iteration, additional ...IterationConvertFunc) *app.Iteration { iterationType := iteration.APIStringTypeIteration spaceType := "spaces" spaceID := itr.SpaceID.String() selfURL := rest.AbsoluteURL(request, app.IterationHref(itr.ID)) spaceSelfURL := rest.AbsoluteURL(request, app.SpaceHref(spaceID)) workitemsRelatedURL := rest.AbsoluteURL(request, app.WorkitemHref("?filter[iteration]="+itr.ID.String())) i := &app.Iteration{ Type: iterationType, ID: &itr.ID, Attributes: &app.IterationAttributes{ Name: &itr.Name, StartAt: itr.StartAt, EndAt: itr.EndAt, Description: itr.Description, State: &itr.State, }, Relationships: &app.IterationRelations{ Space: &app.RelationGeneric{ Data: &app.GenericData{ Type: &spaceType, ID: &spaceID, }, Links: &app.GenericLinks{ Self: &spaceSelfURL, }, }, Workitems: &app.RelationGeneric{ Links: &app.GenericLinks{ Related: &workitemsRelatedURL, }, }, }, Links: &app.GenericLinks{ Self: &selfURL, }, } if itr.ParentID != uuid.Nil { parentSelfURL := rest.AbsoluteURL(request, app.IterationHref(itr.ParentID)) parentID := itr.ParentID.String() i.Relationships.Parent = &app.RelationGeneric{ Data: &app.GenericData{ Type: &iterationType, ID: &parentID, }, Links: &app.GenericLinks{ Self: &parentSelfURL, }, } } for _, add := range additional { add(request, itr, i) } return i }
// ConvertArea converts between internal and external REST representation func ConvertArea(appl application.Application, request *goa.RequestData, ar *area.Area, additional ...AreaConvertFunc) *app.Area { areaType := area.APIStringTypeAreas spaceType := "spaces" spaceID := ar.SpaceID.String() selfURL := rest.AbsoluteURL(request, app.AreaHref(ar.ID)) childURL := rest.AbsoluteURL(request, app.AreaHref(ar.ID)+"/children") spaceSelfURL := rest.AbsoluteURL(request, app.SpaceHref(spaceID)) pathToTopMostParent := pathSepInService + area.ConvertFromLtreeFormat(ar.Path) // /uuid1/uuid2/uuid3s i := &app.Area{ Type: areaType, ID: &ar.ID, Attributes: &app.AreaAttributes{ Name: &ar.Name, CreatedAt: &ar.CreatedAt, Version: &ar.Version, ParentPath: &pathToTopMostParent, }, Relationships: &app.AreaRelations{ Space: &app.RelationGeneric{ Data: &app.GenericData{ Type: &spaceType, ID: &spaceID, }, Links: &app.GenericLinks{ Self: &spaceSelfURL, }, }, Children: &app.RelationGeneric{ Links: &app.GenericLinks{ Self: &childURL, }, }, }, Links: &app.GenericLinks{ Self: &selfURL, }, } // Now check the path, if the path is empty, then this is the topmost area // in a specific space. if ar.Path != "" { allParents := strings.Split(area.ConvertFromLtreeFormat(ar.Path), pathSepInService) parentID := allParents[len(allParents)-1] // Only the immediate parent's URL. parentSelfURL := rest.AbsoluteURL(request, app.AreaHref(parentID)) i.Relationships.Parent = &app.RelationGeneric{ Data: &app.GenericData{ Type: &areaType, ID: &parentID, }, Links: &app.GenericLinks{ Self: &parentSelfURL, }, } } for _, add := range additional { add(appl, request, ar, i) } return i }