diff --git a/model/story/tag.go b/model/story/tag.go index 6863aa3..517c065 100644 --- a/model/story/tag.go +++ b/model/story/tag.go @@ -1,5 +1,12 @@ package story +import ( + "sort" + "strings" + + "github.com/globalsign/mgo/bson" +) + // A Tag associates a story with other content, like other stories, logs and more. type Tag struct { Kind string `bson:"kind"` @@ -10,3 +17,20 @@ type Tag struct { func (tag *Tag) Equal(other Tag) bool { return tag.Kind == other.Kind && tag.Name == other.Name } + +// ListTags lists all tags +func ListTags() ([]Tag, error) { + tags := make([]Tag, 0, 64) + err := storyCollection.Find(bson.M{"tags": bson.M{"$ne": nil}}).Distinct("tags", &tags) + + sort.Slice(tags, func(i, j int) bool { + kindCmp := strings.Compare(tags[i].Kind, tags[j].Kind) + if kindCmp != 0 { + return kindCmp < 0 + } + + return strings.Compare(tags[i].Name, tags[j].Name) < 0 + }) + + return tags, err +} diff --git a/resolver/tag.go b/resolver/tag.go index 383c4c6..102a93e 100644 --- a/resolver/tag.go +++ b/resolver/tag.go @@ -11,6 +11,21 @@ type TagInput struct { Name string } +// Tags implements the tags query +func (r *QueryResolver) Tags() ([]*TagResolver, error) { + tags, err := story.ListTags() + if err != nil { + return nil, err + } + + resolvers := make([]*TagResolver, len(tags)) + for i, tag := range tags { + resolvers[i] = &TagResolver{T: tag} + } + + return resolvers, nil +} + // Kind resolves Tag.kind func (r *TagResolver) Kind() string { return r.T.Kind diff --git a/schema/root.graphql b/schema/root.graphql index f3ff249..6f7b463 100644 --- a/schema/root.graphql +++ b/schema/root.graphql @@ -47,6 +47,10 @@ type Query { chapter(id: String!): Chapter + # Find all distinct tags used in stories + tags: [Tag!]! + + # Find current session session: Session! }