diff --git a/database/mongodb/stories.go b/database/mongodb/stories.go index 9de602b..b5ce6b8 100644 --- a/database/mongodb/stories.go +++ b/database/mongodb/stories.go @@ -145,6 +145,10 @@ func (r *storyRepository) Update(ctx context.Context, story models.Story, update updateBson["listed"] = *update.Listed story.Listed = *update.Listed } + if update.SortByFictionalDate != nil { + updateBson["sortByFictionalDate"] = *update.SortByFictionalDate + story.SortByFictionalDate = *update.SortByFictionalDate + } err := r.stories.UpdateId(story.ID, bson.M{"$set": updateBson}) if err != nil { diff --git a/graph2/resolvers/story.go b/graph2/resolvers/story.go index 1ce03f9..50027f3 100644 --- a/graph2/resolvers/story.go +++ b/graph2/resolvers/story.go @@ -36,7 +36,9 @@ func (r *mutationResolver) AddStory(ctx context.Context, input graphcore.StoryAd fictionalDate = *input.FictionalDate } - return r.s.Stories.CreateStory(ctx, input.Name, input.Author, input.Category, listed, open, tags, time.Now(), fictionalDate) + sortByFictionalDate := input.SortByFictionalDate != nil && *input.SortByFictionalDate + + return r.s.Stories.CreateStory(ctx, input.Name, input.Author, input.Category, listed, open, tags, time.Now(), fictionalDate, sortByFictionalDate) } func (r *mutationResolver) AddStoryTag(ctx context.Context, input graphcore.StoryTagAddInput) (*models.Story, error) { @@ -63,7 +65,7 @@ func (r *mutationResolver) EditStory(ctx context.Context, input graphcore.StoryE return nil, err } - return r.s.Stories.EditStory(ctx, story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate) + return r.s.Stories.EditStory(ctx, story, input.Name, input.Category, input.Listed, input.Open, input.FictionalDate, input.SortByFictionalDate) } func (r *mutationResolver) RemoveStory(ctx context.Context, input graphcore.StoryRemoveInput) (*models.Story, error) { diff --git a/graph2/schema/types/Story.gql b/graph2/schema/types/Story.gql index cf81921..31edaef 100644 --- a/graph2/schema/types/Story.gql +++ b/graph2/schema/types/Story.gql @@ -33,6 +33,9 @@ type Story { # The date of the last major update to the story. This being bumped means a new chapter has been added. updatedDate: Time! + + # Whether to sort by fictional date. + sortByFictionalDate: Boolean! } # Filter for stories query. @@ -86,6 +89,9 @@ input StoryAddInput { # Set the fictional date of the story. fictionalDate: Time + + # Whether to sort by fictional date. + sortByFictionalDate: Boolean } # Input for the editStory mutation @@ -115,6 +121,9 @@ input StoryEditInput { # Clear the fictional date of the story. clearFictionalDate: Boolean + + # Whether to sort by fictional date. + sortByFictionalDate: Boolean } # Input for the addStoryTag mutation diff --git a/models/story.go b/models/story.go index 439b04b..48206cc 100644 --- a/models/story.go +++ b/models/story.go @@ -5,16 +5,17 @@ import "time" // A Story is user content that does not have a wiki-suitable format. Documents, new stories, short stories, and so on. // The story model is a container for multiple chapters this time, in contrast to the previous version. type Story struct { - ID string `bson:"_id"` - Author string `bson:"author"` - Name string `bson:"name"` - Category StoryCategory `bson:"category"` - Open bool `bson:"open"` - Listed bool `bson:"listed"` - Tags []Tag `bson:"tags"` - CreatedDate time.Time `bson:"createdDate"` - FictionalDate time.Time `bson:"fictionalDate,omitempty"` - UpdatedDate time.Time `bson:"updatedDate"` + ID string `bson:"_id"` + Author string `bson:"author"` + Name string `bson:"name"` + Category StoryCategory `bson:"category"` + Open bool `bson:"open"` + Listed bool `bson:"listed"` + Tags []Tag `bson:"tags"` + CreatedDate time.Time `bson:"createdDate"` + FictionalDate time.Time `bson:"fictionalDate,omitempty"` + UpdatedDate time.Time `bson:"updatedDate"` + SortByFictionalDate bool `bson:"sortByFictionalDate"` } // IsChangeObject is an interface implementation to identify it as a valid @@ -35,11 +36,12 @@ type StoryFilter struct { } type StoryUpdate struct { - Name *string - Category *StoryCategory - Author *string - Open *bool - Listed *bool - FictionalDate *time.Time - UpdatedDate *time.Time + Name *string + Category *StoryCategory + Author *string + Open *bool + Listed *bool + FictionalDate *time.Time + UpdatedDate *time.Time + SortByFictionalDate *bool } diff --git a/services/stories.go b/services/stories.go index afaab10..da343be 100644 --- a/services/stories.go +++ b/services/stories.go @@ -7,6 +7,7 @@ import ( "git.aiterp.net/rpdata/api/models" "git.aiterp.net/rpdata/api/models/changekeys" "git.aiterp.net/rpdata/api/repositories" + "sort" "time" ) @@ -37,14 +38,37 @@ func (s *StoryService) ListStories(ctx context.Context, filter models.StoryFilte } func (s *StoryService) ListChapters(ctx context.Context, story models.Story) ([]*models.Chapter, error) { - return s.chapters.List(ctx, models.ChapterFilter{StoryID: &story.ID, Limit: 0}) + chapters, err := s.chapters.List(ctx, models.ChapterFilter{StoryID: &story.ID, Limit: 0}) + if err != nil { + return nil, err + } + + if story.SortByFictionalDate { + sort.Slice(chapters, func(i, j int) bool { + if !chapters[i].FictionalDate.IsZero() && !chapters[j].FictionalDate.IsZero() { + if chapters[i].FictionalDate.Equal(chapters[j].FictionalDate) { + return chapters[i].CreatedDate.Before(chapters[j].CreatedDate) + } + + return chapters[i].FictionalDate.Before(chapters[j].FictionalDate) + } else if chapters[i].FictionalDate.IsZero() && !chapters[j].FictionalDate.IsZero() { + return false + } else if !chapters[i].FictionalDate.IsZero() && chapters[j].FictionalDate.IsZero() { + return true + } else { + return chapters[i].CreatedDate.Before(chapters[j].CreatedDate) + } + }) + } + + return chapters, nil } func (s *StoryService) ListComments(ctx context.Context, chapter models.Chapter, limit int) ([]*models.Comment, error) { return s.comments.List(ctx, models.CommentFilter{ChapterID: &chapter.ID, Limit: limit}) } -func (s *StoryService) CreateStory(ctx context.Context, name string, author *string, category models.StoryCategory, listed, open bool, tags []models.Tag, createdDate, fictionalDate time.Time) (*models.Story, error) { +func (s *StoryService) CreateStory(ctx context.Context, name string, author *string, category models.StoryCategory, listed, open bool, tags []models.Tag, createdDate, fictionalDate time.Time, sortByFictionalDate bool) (*models.Story, error) { if author == nil { token := s.authService.TokenFromContext(ctx) if token == nil { @@ -55,15 +79,16 @@ func (s *StoryService) CreateStory(ctx context.Context, name string, author *str } story := &models.Story{ - Name: name, - Author: *author, - Category: category, - Listed: listed, - Open: open, - Tags: tags, - CreatedDate: createdDate, - FictionalDate: fictionalDate, - UpdatedDate: createdDate, + Name: name, + Author: *author, + Category: category, + Listed: listed, + Open: open, + Tags: tags, + CreatedDate: createdDate, + FictionalDate: fictionalDate, + UpdatedDate: createdDate, + SortByFictionalDate: sortByFictionalDate, } if err := s.authService.CheckPermission(ctx, "add", story); err != nil { @@ -180,7 +205,7 @@ func (s *StoryService) CreateComment(ctx context.Context, chapter models.Chapter return comment, nil } -func (s *StoryService) EditStory(ctx context.Context, story *models.Story, name *string, category *models.StoryCategory, listed, open *bool, fictionalDate *time.Time) (*models.Story, error) { +func (s *StoryService) EditStory(ctx context.Context, story *models.Story, name *string, category *models.StoryCategory, listed, open *bool, fictionalDate *time.Time, sortByFictionalDate *bool) (*models.Story, error) { if story == nil { panic("StoryService.Edit called with nil story") } @@ -190,11 +215,12 @@ func (s *StoryService) EditStory(ctx context.Context, story *models.Story, name } story, err := s.stories.Update(ctx, *story, models.StoryUpdate{ - Name: name, - Open: open, - Listed: listed, - Category: category, - FictionalDate: fictionalDate, + Name: name, + Open: open, + Listed: listed, + Category: category, + FictionalDate: fictionalDate, + SortByFictionalDate: sortByFictionalDate, }) if err != nil { return nil, err