diff --git a/graph/resolvers/issue.resolvers.go b/graph/resolvers/issue.resolvers.go index 2a7527d..7497970 100644 --- a/graph/resolvers/issue.resolvers.go +++ b/graph/resolvers/issue.resolvers.go @@ -85,15 +85,6 @@ func (r *issueResolver) Tasks(ctx context.Context, obj *models.Issue, filter *mo return r.Database.IssueTasks().List(ctx, *filter) } -func (r *issueResolver) Items(ctx context.Context, obj *models.Issue, filter *models.IssueItemFilter) ([]*models.IssueItem, error) { - if filter == nil { - filter = &models.IssueItemFilter{} - } - filter.IssueIDs = []string{obj.ID} - - return r.Database.IssueItems().List(ctx, *filter) -} - func (r *issueResolver) Logs(ctx context.Context, obj *models.Issue) ([]*models.Log, error) { loader := loaders.LogsByIssueLoaderFromContext(ctx) diff --git a/graph/resolvers/issueitem.resolvers.go b/graph/resolvers/issueitem.resolvers.go deleted file mode 100644 index ba5d878..0000000 --- a/graph/resolvers/issueitem.resolvers.go +++ /dev/null @@ -1,46 +0,0 @@ -package resolvers - -// This file will be automatically regenerated based on the schema, any resolver implementations -// will be copied through when generating and any unknown code will be moved to the end. - -import ( - "context" - - "git.aiterp.net/stufflog/server/graph/graphcore" - "git.aiterp.net/stufflog/server/graph/loaders" - "git.aiterp.net/stufflog/server/models" -) - -func (r *issueItemResolver) Issue(ctx context.Context, obj *models.IssueItem) (*models.Issue, error) { - return loaders.IssueLoaderFromContext(ctx).Load(obj.IssueID) -} - -func (r *issueItemResolver) Item(ctx context.Context, obj *models.IssueItem) (*models.Item, error) { - return r.Database.Items().Find(ctx, obj.ItemID) -} - -func (r *issueItemResolver) Remaining(ctx context.Context, obj *models.IssueItem) (int, error) { - if obj.Acquired { - return 0, nil - } - - loader := loaders.LogsByIssueLoaderFromContext(ctx) - logs, err := loader.Load(obj.IssueID) - if err != nil { - return 0, err - } - - remaining := obj.Quantity - for _, log := range logs { - if item := log.Item(obj.ID); item != nil { - remaining -= item.Amount - } - } - - return remaining, nil -} - -// IssueItem returns graphcore.IssueItemResolver implementation. -func (r *Resolver) IssueItem() graphcore.IssueItemResolver { return &issueItemResolver{r} } - -type issueItemResolver struct{ *Resolver } diff --git a/graph/resolvers/log.resolvers.go b/graph/resolvers/log.resolvers.go index 86d8831..418a38a 100644 --- a/graph/resolvers/log.resolvers.go +++ b/graph/resolvers/log.resolvers.go @@ -15,14 +15,6 @@ func (r *logResolver) User(ctx context.Context, obj *models.Log) (*models.User, return r.Database.Users().Find(ctx, obj.UserID) } -func (r *logItemResolver) Issue(ctx context.Context, obj *models.LogItem) (*models.Issue, error) { - return loaders.IssueLoaderFromContext(ctx).Load(obj.IssueID) -} - -func (r *logItemResolver) Item(ctx context.Context, obj *models.LogItem) (*models.IssueItem, error) { - return r.Database.IssueItems().Find(ctx, obj.IssueItemID) -} - func (r *logTaskResolver) Issue(ctx context.Context, obj *models.LogTask) (*models.Issue, error) { return loaders.IssueLoaderFromContext(ctx).Load(obj.IssueID) } @@ -34,12 +26,8 @@ func (r *logTaskResolver) Task(ctx context.Context, obj *models.LogTask) (*model // Log returns graphcore.LogResolver implementation. func (r *Resolver) Log() graphcore.LogResolver { return &logResolver{r} } -// LogItem returns graphcore.LogItemResolver implementation. -func (r *Resolver) LogItem() graphcore.LogItemResolver { return &logItemResolver{r} } - // LogTask returns graphcore.LogTaskResolver implementation. func (r *Resolver) LogTask() graphcore.LogTaskResolver { return &logTaskResolver{r} } type logResolver struct{ *Resolver } -type logItemResolver struct{ *Resolver } type logTaskResolver struct{ *Resolver } diff --git a/graph/resolvers/mutation.resolvers.go b/graph/resolvers/mutation.resolvers.go index 81bd432..f1979db 100644 --- a/graph/resolvers/mutation.resolvers.go +++ b/graph/resolvers/mutation.resolvers.go @@ -6,13 +6,10 @@ package resolvers import ( "context" "errors" - "log" - "sort" "time" "git.aiterp.net/stufflog/server/graph/graphcore" "git.aiterp.net/stufflog/server/graph/loaders" - "git.aiterp.net/stufflog/server/internal/generate" "git.aiterp.net/stufflog/server/internal/slerrors" "git.aiterp.net/stufflog/server/models" ) @@ -127,131 +124,6 @@ func (r *mutationResolver) EditActivity(ctx context.Context, input graphcore.Act return activity, nil } -func (r *mutationResolver) CreateItem(ctx context.Context, input *graphcore.ItemCreateInput) (*models.Item, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - if input.Name == "" { - return nil, errors.New("name cannot be blank") - } - if input.Description == "" { - return nil, errors.New("name cannot be blank") - } - if len(input.Tags) == 0 { - return nil, errors.New("at least one tag is required") - } - - item := models.Item{ - Name: input.Name, - Description: input.Description, - Tags: input.Tags, - QuantityUnit: input.QuantityUnit, - ImageURL: nil, - } - - if input.Image != nil { - url, err := r.Upload.UploadImage( - ctx, - "item-image/"+generate.Generate(16, "I"), - input.Image.ContentType, - input.Image.Size, - input.Image.File, - ) - if err != nil { - return nil, err - } - - item.ImageURL = &url - } - - return r.Database.Items().Insert(ctx, item) -} - -func (r *mutationResolver) EditItem(ctx context.Context, input *graphcore.ItemEditInput) (*models.Item, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - item, err := r.Database.Items().Find(ctx, input.ItemID) - if err != nil { - return nil, err - } - - deleteList := make([]int, 0, len(input.RemoveTags)) - for _, tag := range input.RemoveTags { - for i, tag2 := range item.Tags { - if tag == tag2 { - deleteList = append(deleteList, i-len(deleteList)) - break - } - } - } - for _, index := range deleteList { - item.Tags = append(item.Tags[:index], item.Tags[index+1:]...) - } - for _, tag := range input.AddTags { - found := false - for _, tag2 := range item.Tags { - if tag == tag2 { - found = true - break - } - } - if !found { - item.Tags = append(item.Tags, tag) - } - } - sort.Strings(item.Tags) - - if input.SetQuantityUnit != nil { - item.QuantityUnit = input.SetQuantityUnit - } - if input.ClearQuantityUnit != nil && *input.ClearQuantityUnit { - item.QuantityUnit = nil - } - - if input.SetName != nil { - item.Name = *input.SetName - } - if input.SetDescription != nil { - item.Description = *input.SetDescription - } - - var prevFile *string - if input.UpdateImage != nil { - url, err := r.Upload.UploadImage( - ctx, - "item-image/"+generate.Generate(16, "U"), - input.UpdateImage.ContentType, - input.UpdateImage.Size, - input.UpdateImage.File, - ) - if err != nil { - return nil, err - } - - prevFile = item.ImageURL - item.ImageURL = &url - } - - err = r.Database.Items().Save(ctx, *item) - if err != nil { - return nil, err - } - - if prevFile != nil { - err := r.Upload.Delete(ctx, *prevFile) - if err != nil { - log.Printf("Failed to delete %s: %s", *prevFile, err) - } - } - - return item, nil -} - func (r *mutationResolver) CreateIssue(ctx context.Context, input graphcore.IssueCreateInput) (*models.Issue, error) { user := r.Auth.UserFromContext(ctx) if user == nil { @@ -473,69 +345,6 @@ func (r *mutationResolver) EditIssueTask(ctx context.Context, input graphcore.Is return task, nil } -func (r *mutationResolver) CreateIssueItem(ctx context.Context, input graphcore.IssueItemCreateInput) (*models.IssueItem, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - issue, err := loaders.IssueLoaderFromContext(ctx).Load(input.IssueID) - if err != nil { - return nil, err - } - if perm, err := r.Auth.IssuePermission(ctx, *issue); err != nil || !perm.CanManageOwnIssue() { - return nil, slerrors.PermissionDenied - } - - item, err := r.Database.Items().Find(ctx, input.ItemID) - if err != nil { - return nil, err - } - - issueItem := &models.IssueItem{ - IssueID: issue.ID, - ItemID: item.ID, - Quantity: input.Quanitty, - Acquired: input.Acquired != nil && *input.Acquired, - } - - return r.Database.IssueItems().Insert(ctx, *issueItem) -} - -func (r *mutationResolver) EditIssueItem(ctx context.Context, input graphcore.IssueItemEditInput) (*models.IssueItem, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - item, err := r.Database.IssueItems().Find(ctx, input.IssueItemID) - if err != nil { - return nil, err - } - - issue, err := loaders.IssueLoaderFromContext(ctx).Load(item.IssueID) - if err != nil { - return nil, err - } - if perm, err := r.Auth.IssuePermission(ctx, *issue); err != nil || !perm.CanManageOwnIssue() { - return nil, slerrors.PermissionDenied - } - - if input.SetAcquired != nil { - item.Acquired = *input.SetAcquired - } - if input.SetQuanitty != nil { - item.Quantity = *input.SetQuanitty - } - - err = r.Database.IssueItems().Save(ctx, *item) - if err != nil { - return nil, err - } - - return item, nil -} - func (r *mutationResolver) CreateLog(ctx context.Context, input graphcore.LogCreateInput) (*models.Log, error) { user := r.Auth.UserFromContext(ctx) if user == nil { diff --git a/graph/resolvers/query.resolvers.go b/graph/resolvers/query.resolvers.go index 54abd0d..5f66685 100644 --- a/graph/resolvers/query.resolvers.go +++ b/graph/resolvers/query.resolvers.go @@ -65,107 +65,6 @@ func (r *queryResolver) Issues(ctx context.Context, filter *models.IssueFilter) return issues, nil } -func (r *queryResolver) Item(ctx context.Context, id string) (*models.Item, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - return r.Database.Items().Find(ctx, id) -} - -func (r *queryResolver) Items(ctx context.Context, filter *models.ItemFilter) ([]*models.Item, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - if filter == nil { - filter = &models.ItemFilter{} - } - - return r.Database.Items().List(ctx, *filter) -} - -func (r *queryResolver) ItemTags(ctx context.Context) ([]string, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - return r.Database.Items().GetTags(ctx) -} - -func (r *queryResolver) IssueItem(ctx context.Context, id string) (*models.IssueItem, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - item, err := r.Database.IssueItems().Find(ctx, id) - if err != nil { - return nil, err - } - - issue, err := loaders.IssueLoaderFromContext(ctx).Load(id) - if err != nil { - return nil, err - } - - _, err = r.Auth.IssuePermission(ctx, *issue) - if err != nil { - return nil, err - } - - return item, nil -} - -func (r *queryResolver) IssueItems(ctx context.Context, filter *models.IssueItemFilter) ([]*models.IssueItem, error) { - user := r.Auth.UserFromContext(ctx) - if user == nil { - return nil, slerrors.PermissionDenied - } - - if filter == nil { - filter = &models.IssueItemFilter{} - } - - items, err := r.Database.IssueItems().List(ctx, *filter) - if err != nil { - return nil, err - } - - accessMap := make(map[string]bool) - deleteList := make([]int, 0, len(items)) - for i, item := range items { - if access, ok := accessMap[item.IssueID]; ok && access { - continue - } else if ok && !access { - deleteList = append(deleteList, i-len(deleteList)) - continue - } - - issue, err := loaders.IssueLoaderFromContext(ctx).Load(item.IssueID) - if err != nil { - deleteList = append(deleteList, i-len(deleteList)) - accessMap[item.IssueID] = true - continue - } - - _, err = r.Auth.IssuePermission(ctx, *issue) - if err != nil { - deleteList = append(deleteList, i-len(deleteList)) - } - - accessMap[issue.ID] = err != nil - } - for _, index := range deleteList { - items = append(items[:index], items[index+1:]...) - } - - return items, nil -} - func (r *queryResolver) Project(ctx context.Context, id string) (*models.Project, error) { user := r.Auth.UserFromContext(ctx) if user == nil { diff --git a/graph/schema/issue.gql b/graph/schema/issue.gql index 797829c..6e7edea 100644 --- a/graph/schema/issue.gql +++ b/graph/schema/issue.gql @@ -24,8 +24,6 @@ type Issue { status: ProjectStatus! "Issue tasks." tasks(filter: IssueTaskFilter): [IssueTask!]! - "Issue items." - items(filter: IssueIssueItemFilter): [IssueItem!]! "Logs related to this issue." logs: [Log!]! } diff --git a/graph/schema/issueitem.gql b/graph/schema/issueitem.gql deleted file mode 100644 index 546861d..0000000 --- a/graph/schema/issueitem.gql +++ /dev/null @@ -1,75 +0,0 @@ -""" -An issue item is a requirement of an item under an issue. -""" -type IssueItem { - "ID of the issue item listing." - id: String! - "The amount of the item associated with an issue." - quantity: Int! - "Whether the full quantity of item has been acquired." - acquired: Boolean! - - "Parent issue of the issue item." - issue: Issue! - "The item associated with the issue." - item: Item! - "The amount of items remaining." - remaining: Int! -} - -"Input for the items query." -input IssueItemFilter { - "Filter to only these IDs, used primarily by IDs." - issueItemIds: [String!] - "Filter to only these issues." - issueIds: [String!] - "Filter to only issues where these are the asignees." - issueAssignees: [String!] - "Filter to only issues where these are the owners." - issueOwners: [String!] - "Filter by issue minimum stage (inclusive)." - issueMinStage: Int - "Filter by issue maximum stage (inclusive)." - issueMaxStage: Int - "Filter to only list issue items with these items." - itemIds: [String!] - "Filter to only list issue items where the item has these tags." - itemTags: [String!] - "Only listed acquired or non-acquired items." - acquired: Boolean -} - -"Input for the items query." -input IssueIssueItemFilter { - "Filter to only these IDs, used primarily by IDs." - issueItemIds: [String!] - "Filter to only list issue items with these items." - itemIds: [String!] - "Filter to only list issue items where the item has these tags." - itemTags: [String!] - "Only listed acquired or non-acquired items." - acquired: Boolean -} - -"Input for the createIssueItem mutation." -input IssueItemCreateInput { - "Parent issue." - issueId: String! - "Item to associate with." - itemId: String! - "Quantity of the item." - quanitty: Int! - "Whether the item has already been acquired." - acquired: Boolean -} - -"Input for the editIssueItem mutation." -input IssueItemEditInput { - "The ID of the issue item to edit." - issueItemId: String! - "Update the quantity of the item." - setQuanitty: Int - "Update whether the item has been acquired." - setAcquired: Boolean -} - diff --git a/graph/schema/item.gql b/graph/schema/item.gql deleted file mode 100644 index 419218a..0000000 --- a/graph/schema/item.gql +++ /dev/null @@ -1,60 +0,0 @@ -""" -An item that can be required for an issue. -""" -type Item { - "The item's unique ID." - id: String! - "Name of the item." - name: String! - "A description of the item." - description: String! - "Item tags." - tags: [String!]! - "Quantity unit. Usually absent, but otherwise most often 'g' or 'ml'" - quantityUnit: String - "URL for the image, if available." - imageUrl: String -} - -"Filter for the items query." -input ItemFilter { - "Get these item IDs. Mostly used internally." - itemIds: [String!] - "Limit to items with any of the following tags." - tags: [String!] -} - -"Input for the createItem mutation." -input ItemCreateInput { - "Put a name on it." - name: String! - "Describe it for me." - description: String! - "Add a tag or a few" - tags: [String!]! - "Optional: Quanity unit." - quantityUnit: String - "Optional: Upload an image." - image: Upload -} - -"Input for the editItem mutation." -input ItemEditInput { - "The item to edit." - itemId: String! - - "Update the name." - setName: String - "Update the description." - setDescription: String - "Add new tags. The tags are added after removeTag tags are removed." - addTags: [String!] - "Remove existing tags. If a tag exists both here and in addTags, it will not be removed." - removeTags: [String!] - "Update quantity unit." - setQuantityUnit: String - "Clear quantity unit." - clearQuantityUnit: Boolean - "Update the image URL with a new image." - updateImage: Upload -} \ No newline at end of file diff --git a/graph/schema/log.gql b/graph/schema/log.gql index ca5939a..b291794 100644 --- a/graph/schema/log.gql +++ b/graph/schema/log.gql @@ -13,8 +13,6 @@ type Log { user: User! "The tasks logged." tasks: [LogTask!]! - "The items changed." - items: [LogItem!]! } type LogTask { @@ -28,18 +26,6 @@ type LogTask { duration: Duration! } -""" -Log items are item changes related to a log. -""" -type LogItem { - "Parent issue of the item." - issue: Issue! - "The item that has been acquired." - item: IssueItem! - "The amount of items acquired." - amount: Int! -} - "Filter for the logs query." input LogFilter { "Log IDs to select." diff --git a/graph/schema/mutation.gql b/graph/schema/mutation.gql index fcbf92c..4c991f0 100644 --- a/graph/schema/mutation.gql +++ b/graph/schema/mutation.gql @@ -9,12 +9,6 @@ type Mutation { "Edit an activity." editActivity(input: ActivityEditInput!): Activity! - # ITEM - "Create an item." - createItem(input: ItemCreateInput): Item! - "Edit an item." - editItem(input: ItemEditInput): Item! - # ISSUE "Create a new issue." createIssue(input: IssueCreateInput!): Issue! @@ -25,11 +19,6 @@ type Mutation { createIssueTask(input: IssueTaskCreateInput!): IssueTask! "Edit an issue task." editIssueTask(input: IssueTaskEditInput!): IssueTask! - # ISSUE ITEM - "Create an issue item." - createIssueItem(input: IssueItemCreateInput!): IssueItem! - "Edit an issue item." - editIssueItem(input: IssueItemEditInput!): IssueItem! # LOG "Create a log." diff --git a/graph/schema/query.gql b/graph/schema/query.gql index 023d90c..c35b82e 100644 --- a/graph/schema/query.gql +++ b/graph/schema/query.gql @@ -4,18 +4,6 @@ type Query { "List issues." issues(filter: IssueFilter): [Issue!]! - "Find item." - item(id: String!): Item! - "List items." - items(filter: ItemFilter): [Item!]! - "List item tags." - itemTags: [String!]! - - "Find issue item." - issueItem(id: String!): IssueItem! - "List issue items." - issueItems(filter: IssueItemFilter): [IssueItem!]! - "Find project." project(id: String!): Project! "List projects."