// Create runs the create action. func (c *WorkitemtypeController) Create(ctx *app.CreateWorkitemtypeContext) error { return application.Transactional(c.db, func(appl application.Application) error { var fields = map[string]app.FieldDefinition{} for key, fd := range ctx.Payload.Fields { fields[key] = *fd } wit, err := appl.WorkItemTypes().Create(ctx.Context, ctx.Payload.ExtendedTypeName, ctx.Payload.Name, fields) if err != nil { jerrors, httpStatusCode := jsonapi.ErrorToJSONAPIErrors(err) return ctx.ResponseData.Service.Send(ctx.Context, httpStatusCode, jerrors) } ctx.ResponseData.Header().Set("Location", app.WorkitemtypeHref(wit.Name)) return ctx.Created(wit) }) }
// ConvertWorkItem is responsible for converting given WorkItem model object into a // response resource object by jsonapi.org specifications func ConvertWorkItem(request *goa.RequestData, wi *app.WorkItem, additional ...WorkItemConvertFunc) *app.WorkItem2 { // construct default values from input WI selfURL := rest.AbsoluteURL(request, app.WorkitemHref(wi.ID)) sourceLinkTypesURL := rest.AbsoluteURL(request, app.WorkitemtypeHref(wi.Type)+sourceLinkTypesRouteEnd) targetLinkTypesURL := rest.AbsoluteURL(request, app.WorkitemtypeHref(wi.Type)+targetLinkTypesRouteEnd) op := &app.WorkItem2{ ID: &wi.ID, Type: APIStringTypeWorkItem, Attributes: map[string]interface{}{ "version": wi.Version, }, Relationships: &app.WorkItemRelationships{ BaseType: &app.RelationBaseType{ Data: &app.BaseTypeData{ ID: wi.Type, Type: APIStringTypeWorkItemType, }, }, }, Links: &app.GenericLinksForWorkItem{ Self: &selfURL, SourceLinkTypes: &sourceLinkTypesURL, TargetLinkTypes: &targetLinkTypesURL, }, } // Move fields into Relationships or Attributes as needed // TODO: Loop based on WorKItemType and match against Field.Type instead of directly to field value for name, val := range wi.Fields { switch name { case workitem.SystemAssignees: if val != nil { valArr := val.([]interface{}) op.Relationships.Assignees = &app.RelationGenericList{ Data: ConvertUsersSimple(request, valArr), } } case workitem.SystemCreator: if val != nil { valStr := val.(string) op.Relationships.Creator = &app.RelationGeneric{ Data: ConvertUserSimple(request, valStr), } } case workitem.SystemIteration: if val != nil { valStr := val.(string) op.Relationships.Iteration = &app.RelationGeneric{ Data: ConvertIterationSimple(request, valStr), } } case workitem.SystemArea: if val != nil { valStr := val.(string) op.Relationships.Area = &app.RelationGeneric{ Data: ConvertAreaSimple(request, valStr), } } case workitem.SystemTitle: // 'HTML escape' the title to prevent script injection op.Attributes[name] = html.EscapeString(val.(string)) case workitem.SystemDescription: description := rendering.NewMarkupContentFromValue(val) if description != nil { op.Attributes[name] = (*description).Content op.Attributes[workitem.SystemDescriptionMarkup] = (*description).Markup // let's include the rendered description while 'HTML escaping' it to prevent script injection op.Attributes[workitem.SystemDescriptionRendered] = rendering.RenderMarkupToHTML(html.EscapeString((*description).Content), (*description).Markup) } default: op.Attributes[name] = val } } if op.Relationships.Assignees == nil { op.Relationships.Assignees = &app.RelationGenericList{Data: nil} } if op.Relationships.Iteration == nil { op.Relationships.Iteration = &app.RelationGeneric{Data: nil} } if op.Relationships.Area == nil { op.Relationships.Area = &app.RelationGeneric{Data: nil} } // Always include Comments Link, but optionally use WorkItemIncludeCommentsAndTotal WorkItemIncludeComments(request, wi, op) for _, add := range additional { add(request, wi, op) } return op }