This commit is contained in:
+5
-1
@@ -6,4 +6,8 @@ debug
|
|||||||
build
|
build
|
||||||
rpdata-graphiql
|
rpdata-graphiql
|
||||||
rpdata-*
|
rpdata-*
|
||||||
.vscode
|
!rpdata-*/
|
||||||
|
.vscode
|
||||||
|
|
||||||
|
generated.gql
|
||||||
|
generated.go
|
||||||
Generated
+83
-7
@@ -2,10 +2,32 @@
|
|||||||
|
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
name = "github.com/99designs/gqlgen"
|
||||||
name = "git.aiterp.net/aiterp/wikiauth"
|
packages = [
|
||||||
|
".",
|
||||||
|
"cmd",
|
||||||
|
"codegen",
|
||||||
|
"codegen/templates",
|
||||||
|
"complexity",
|
||||||
|
"graphql",
|
||||||
|
"graphql/introspection",
|
||||||
|
"handler",
|
||||||
|
"internal/gopath"
|
||||||
|
]
|
||||||
|
revision = "636435b68700211441303f1a5ed92f3768ba5774"
|
||||||
|
version = "v0.5.1"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/agnivade/levenshtein"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "33860de804ddcec4fc17998745233b4ec477e7c2"
|
revision = "3d21ba515fe27b856f230847e856431ae1724adc"
|
||||||
|
version = "v1.0.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/dgrijalva/jwt-go"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
|
||||||
|
version = "v3.2.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
@@ -37,6 +59,12 @@
|
|||||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||||
version = "v1.4.0"
|
version = "v1.4.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/gorilla/websocket"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "66b9c49e59c6c48f0ffce28c2d8b8a5678502c6d"
|
||||||
|
version = "v1.4.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/graph-gophers/dataloader"
|
name = "github.com/graph-gophers/dataloader"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
@@ -64,6 +92,15 @@
|
|||||||
]
|
]
|
||||||
revision = "9ebf33af539ab8cb832c7107bc0a978ca8dbc0de"
|
revision = "9ebf33af539ab8cb832c7107bc0a978ca8dbc0de"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/hashicorp/golang-lru"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"simplelru"
|
||||||
|
]
|
||||||
|
revision = "20f1fb78b0740ba8c3cb143a61e86ba5c8669768"
|
||||||
|
version = "v0.5.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/jmoiron/sqlx"
|
name = "github.com/jmoiron/sqlx"
|
||||||
@@ -103,10 +140,10 @@
|
|||||||
version = "v1.0.2"
|
version = "v1.0.2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/sadbox/mediawiki"
|
name = "github.com/pkg/errors"
|
||||||
packages = ["."]
|
packages = ["."]
|
||||||
revision = "39fea8a1336076a961a300d1d95765dcd17e8a3c"
|
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
|
||||||
version = "v0.1"
|
version = "v0.8.0"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "github.com/sirupsen/logrus"
|
name = "github.com/sirupsen/logrus"
|
||||||
@@ -114,6 +151,26 @@
|
|||||||
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
|
||||||
version = "v1.0.5"
|
version = "v1.0.5"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "github.com/urfave/cli"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1"
|
||||||
|
version = "v1.20.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/vektah/gqlparser"
|
||||||
|
packages = [
|
||||||
|
".",
|
||||||
|
"ast",
|
||||||
|
"gqlerror",
|
||||||
|
"lexer",
|
||||||
|
"parser",
|
||||||
|
"validator",
|
||||||
|
"validator/rules"
|
||||||
|
]
|
||||||
|
revision = "14e83ae06ec152e6d0afb9766a00e0c0918aa8fc"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "golang.org/x/crypto"
|
name = "golang.org/x/crypto"
|
||||||
@@ -164,15 +221,34 @@
|
|||||||
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
|
||||||
version = "v0.3.0"
|
version = "v0.3.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "golang.org/x/tools"
|
||||||
|
packages = [
|
||||||
|
"go/ast/astutil",
|
||||||
|
"go/buildutil",
|
||||||
|
"go/internal/cgo",
|
||||||
|
"go/loader",
|
||||||
|
"imports",
|
||||||
|
"internal/fastwalk"
|
||||||
|
]
|
||||||
|
revision = "677d2ff680c188ddb7dcd2bfa6bc7d3f2f2f75b2"
|
||||||
|
|
||||||
[[projects]]
|
[[projects]]
|
||||||
name = "google.golang.org/appengine"
|
name = "google.golang.org/appengine"
|
||||||
packages = ["cloudsql"]
|
packages = ["cloudsql"]
|
||||||
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
|
||||||
version = "v1.1.0"
|
version = "v1.1.0"
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
name = "gopkg.in/yaml.v2"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183"
|
||||||
|
version = "v2.2.1"
|
||||||
|
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "16fd84401bc5796ffeaa895f31d099e1a23b363b15b87386877de0829ac9575b"
|
inputs-digest = "5395eefae297e64dc7575e2e7a24cd739dabbeaae561de7d876249f57a23619a"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|||||||
+3
-1
@@ -24,6 +24,8 @@
|
|||||||
# go-tests = true
|
# go-tests = true
|
||||||
# unused-packages = true
|
# unused-packages = true
|
||||||
|
|
||||||
|
required = [ "github.com/99designs/gqlgen" ]
|
||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/globalsign/mgo"
|
name = "github.com/globalsign/mgo"
|
||||||
@@ -38,4 +40,4 @@
|
|||||||
|
|
||||||
[[constraint]]
|
[[constraint]]
|
||||||
branch = "master"
|
branch = "master"
|
||||||
name = "github.com/graph-gophers/graphql-go"
|
name = "github.com/graph-gophers/graphql-go"
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"runtime/debug"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/graph2"
|
||||||
|
"git.aiterp.net/rpdata/api/internal/store"
|
||||||
|
logModel "git.aiterp.net/rpdata/api/model/log"
|
||||||
|
"github.com/99designs/gqlgen/handler"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := store.Init()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln("Failed to init store:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Handle("/", handler.Playground("RPData API", "/query"))
|
||||||
|
http.Handle("/query", handler.GraphQL(
|
||||||
|
graph2.New(),
|
||||||
|
handler.RecoverFunc(func(ctx context.Context, err interface{}) error {
|
||||||
|
// send this panic somewhere
|
||||||
|
log.Println(err)
|
||||||
|
log.Println(string(debug.Stack()))
|
||||||
|
|
||||||
|
return fmt.Errorf("shit")
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
|
||||||
|
go updateCharacters()
|
||||||
|
|
||||||
|
log.Fatal(http.ListenAndServe(":8081", nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateCharacters() {
|
||||||
|
n, err := logModel.UpdateAllCharacters()
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Charcter updated stopped:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Updated characters on", n, "logs")
|
||||||
|
}
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "# Generated by stiching together the files under schema/ – DO NOT EDIT" >generated.gql
|
||||||
|
cat schema/root.gql schema/**/*.gql >>generated.gql
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
schema: generated.gql
|
||||||
|
|
||||||
|
exec:
|
||||||
|
filename: generated.go
|
||||||
|
package: graph2
|
||||||
|
|
||||||
|
model:
|
||||||
|
filename: input/generated.go
|
||||||
|
package: input
|
||||||
|
|
||||||
|
models:
|
||||||
|
Tag:
|
||||||
|
model: git.aiterp.net/rpdata/api/model/story.Tag
|
||||||
|
TagKind:
|
||||||
|
model: git.aiterp.net/rpdata/api/model/story.TagKind
|
||||||
|
Character:
|
||||||
|
model: git.aiterp.net/rpdata/api/model/character.Character
|
||||||
|
CharactersFilter:
|
||||||
|
model: git.aiterp.net/rpdata/api/model/character.Filter
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package graph2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.aiterp.net/rpdata/api/graph2/queries"
|
||||||
|
graphql "github.com/99designs/gqlgen/graphql"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate ./combine.sh
|
||||||
|
//go:generate gorunpkg github.com/99designs/gqlgen -v
|
||||||
|
|
||||||
|
func New() graphql.ExecutableSchema {
|
||||||
|
return NewExecutableSchema(Config{
|
||||||
|
Resolvers: &rootResolver{},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type rootResolver struct{}
|
||||||
|
|
||||||
|
func (r *rootResolver) Query() QueryResolver {
|
||||||
|
return &queries.Resolver
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/model/character"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) Character(ctx context.Context, id *string, nick *string) (character.Character, error) {
|
||||||
|
if id != nil {
|
||||||
|
return character.FindID(*id)
|
||||||
|
} else if nick != nil {
|
||||||
|
return character.FindNick(*nick)
|
||||||
|
} else {
|
||||||
|
return character.Character{}, errors.New("You must specify either an ID or a nick")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *resolver) Characters(ctx context.Context, filter *character.Filter) ([]character.Character, error) {
|
||||||
|
return character.List(filter)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
type resolver struct{}
|
||||||
|
|
||||||
|
// Resolver has all the queries
|
||||||
|
var Resolver resolver
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package queries
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.aiterp.net/rpdata/api/model/story"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (r *resolver) Tags(ctx context.Context) ([]story.Tag, error) {
|
||||||
|
return story.ListTags()
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
schema {
|
||||||
|
query: Query
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
# Find character by either an ID or a nick.
|
||||||
|
character(id: String, nick: String): Character!
|
||||||
|
|
||||||
|
# Find characters
|
||||||
|
characters(filter: CharactersFilter): [Character!]!
|
||||||
|
|
||||||
|
|
||||||
|
# Find all distinct tags used in stories
|
||||||
|
tags: [Tag!]!
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
# A Character represents an RP character
|
||||||
|
type Character {
|
||||||
|
# A unique identifier for the character
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# The primary IRC nick belonging to the character
|
||||||
|
nick: String
|
||||||
|
|
||||||
|
# All IRC nicks associated with this character
|
||||||
|
nicks: [String!]!
|
||||||
|
|
||||||
|
# The character's author
|
||||||
|
author: String!
|
||||||
|
|
||||||
|
# The character's name
|
||||||
|
name: String!
|
||||||
|
|
||||||
|
# The name to display when space is scarce, usually the first/given name
|
||||||
|
shortName: String!
|
||||||
|
|
||||||
|
# A short description of the character
|
||||||
|
description: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Filter for characters query
|
||||||
|
input CharactersFilter {
|
||||||
|
# Filter by character IDs
|
||||||
|
ids: [String!]
|
||||||
|
|
||||||
|
# Filter by nicks
|
||||||
|
nicks: [String!]
|
||||||
|
|
||||||
|
# Filter by names
|
||||||
|
names: [String!]
|
||||||
|
|
||||||
|
# Filter by author
|
||||||
|
author: String
|
||||||
|
|
||||||
|
# Filter by text search matching against the character's description
|
||||||
|
search: String
|
||||||
|
|
||||||
|
# Filter by whether they've been part of a log.
|
||||||
|
logged: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for adding characters
|
||||||
|
input CharacterAddInput {
|
||||||
|
# The primary IRC nick name to recognize this character by
|
||||||
|
nick: String!
|
||||||
|
|
||||||
|
# The character's name
|
||||||
|
name: String!
|
||||||
|
|
||||||
|
# Optioanl shortened name. By default, it uses the first token in the name
|
||||||
|
shortName: String
|
||||||
|
|
||||||
|
# Description for a character.
|
||||||
|
description: String
|
||||||
|
|
||||||
|
# Optioanlly, specify another author. This needs special permissions if it's not
|
||||||
|
# your own username
|
||||||
|
author: String
|
||||||
|
}
|
||||||
|
|
||||||
|
# Input for addNick and removeNick mutation
|
||||||
|
input CharacterNickInput {
|
||||||
|
# The ID of the character
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# The nick to add or remove
|
||||||
|
nick: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
input CharacterEditInput {
|
||||||
|
# The id for the character to edit
|
||||||
|
id: String!
|
||||||
|
|
||||||
|
# The full name of the character -- not the salarian full name!
|
||||||
|
name: String
|
||||||
|
|
||||||
|
# The character's short name that is used in compact lists
|
||||||
|
shortName: String
|
||||||
|
|
||||||
|
# A short description for the character
|
||||||
|
description: String
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# A Tag is a means of associating stories that have details in common with one another.
|
||||||
|
type Tag {
|
||||||
|
# The tag's kind
|
||||||
|
kind: TagKind!
|
||||||
|
|
||||||
|
# The tag's name
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# A Tag is a means of associating stories that have details in common with one another.
|
||||||
|
input TagInput {
|
||||||
|
# The tag's kind
|
||||||
|
kind: TagKind!
|
||||||
|
|
||||||
|
# The tag's name
|
||||||
|
name: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
# Allowed values for Tag.kind
|
||||||
|
enum TagKind {
|
||||||
|
# An organization is a catch all term for in-universe corporations, teams, groups, cults, forces, etc...
|
||||||
|
Organization
|
||||||
|
|
||||||
|
# A character tag should have the exact full name of the character.
|
||||||
|
Character
|
||||||
|
|
||||||
|
# A location is anything from a planet to an establishment. This may overlap with an organization, and if so, both
|
||||||
|
# kinds of tags should be used.
|
||||||
|
Location
|
||||||
|
|
||||||
|
# An event is a plot or a part of a plot.
|
||||||
|
Event
|
||||||
|
|
||||||
|
# None of the above, but it does still tie multiple stories together. The new story/chapter format may obsolete this tag kind.
|
||||||
|
Series
|
||||||
|
}
|
||||||
|
|
||||||
@@ -26,6 +26,25 @@ type Character struct {
|
|||||||
Description string `json:"description" bson:"description"`
|
Description string `json:"description" bson:"description"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter is used to filter the list of characters
|
||||||
|
type Filter struct {
|
||||||
|
IDs []string `json:"ids"`
|
||||||
|
Nicks []string `json:"nicks"`
|
||||||
|
Names []string `json:"names"`
|
||||||
|
Author *string `json:"author"`
|
||||||
|
Search *string `json:"search"`
|
||||||
|
Logged *bool `json:"logged"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nick gets the character's nick.
|
||||||
|
func (character *Character) Nick() *string {
|
||||||
|
if len(character.Nicks[0]) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &character.Nicks[0]
|
||||||
|
}
|
||||||
|
|
||||||
// HasNick returns true if the character has that nick
|
// HasNick returns true if the character has that nick
|
||||||
func (character *Character) HasNick(nick string) bool {
|
func (character *Character) HasNick(nick string) bool {
|
||||||
for i := range character.Nicks {
|
for i := range character.Nicks {
|
||||||
@@ -136,8 +155,48 @@ func FindName(name string) (Character, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List lists all characters
|
// List lists all characters
|
||||||
func List() ([]Character, error) {
|
func List(filter *Filter) ([]Character, error) {
|
||||||
return list(bson.M{})
|
query := bson.M{}
|
||||||
|
|
||||||
|
if filter != nil {
|
||||||
|
if len(filter.IDs) > 1 {
|
||||||
|
query["id"] = bson.M{"$in": filter.IDs}
|
||||||
|
} else if len(filter.IDs) == 1 {
|
||||||
|
query["id"] = filter.IDs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filter.Nicks) > 1 {
|
||||||
|
query["nicks"] = bson.M{"$in": filter.Nicks}
|
||||||
|
} else if len(filter.Nicks) == 1 {
|
||||||
|
query["nicks"] = filter.Nicks[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filter.Names) > 1 {
|
||||||
|
query["$or"] = bson.M{
|
||||||
|
"name": bson.M{"$in": filter.Names},
|
||||||
|
"shortName": bson.M{"$in": filter.Names},
|
||||||
|
}
|
||||||
|
} else if len(filter.Names) == 1 {
|
||||||
|
query["$or"] = bson.M{
|
||||||
|
"name": filter.Names[0],
|
||||||
|
"shortName": filter.Names[0],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Logged != nil {
|
||||||
|
query["logged"] = *filter.Logged
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Author != nil {
|
||||||
|
query["author"] = *filter.Author
|
||||||
|
}
|
||||||
|
|
||||||
|
if filter.Search != nil {
|
||||||
|
query["$text"] = bson.M{"$search": *filter.Search}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return list(query)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListAuthor lists all characters by author
|
// ListAuthor lists all characters by author
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package story
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TagKind represents the kind of tags.
|
||||||
|
type TagKind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// TagKindOrganization is a tag kind, see GraphQL documentation.
|
||||||
|
TagKindOrganization TagKind = "Organization"
|
||||||
|
|
||||||
|
// TagKindCharacter is a tag kind, see GraphQL documentation.
|
||||||
|
TagKindCharacter TagKind = "Character"
|
||||||
|
|
||||||
|
// TagKindLocation is a tag kind, see GraphQL documentation.
|
||||||
|
TagKindLocation TagKind = "Location"
|
||||||
|
|
||||||
|
// TagKindEvent is a tag kind, see GraphQL documentation.
|
||||||
|
TagKindEvent TagKind = "Event"
|
||||||
|
|
||||||
|
// TagKindSeries is a tag kind, see GraphQL documentation.
|
||||||
|
TagKindSeries TagKind = "Series"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsValid returns true if the TagKind is one of the constants
|
||||||
|
func (e TagKind) IsValid() bool {
|
||||||
|
switch e {
|
||||||
|
case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e TagKind) String() string {
|
||||||
|
return string(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalGQL unmarshals
|
||||||
|
func (e *TagKind) UnmarshalGQL(v interface{}) error {
|
||||||
|
str, ok := v.(string)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("enums must be strings")
|
||||||
|
}
|
||||||
|
|
||||||
|
*e = TagKind(str)
|
||||||
|
if !e.IsValid() {
|
||||||
|
return fmt.Errorf("%s is not a valid TagKind", str)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalGQL turns it into a JSON string
|
||||||
|
func (e TagKind) MarshalGQL(w io.Writer) {
|
||||||
|
fmt.Fprint(w, "\""+e.String(), "\"")
|
||||||
|
}
|
||||||
+3
-3
@@ -9,8 +9,8 @@ import (
|
|||||||
|
|
||||||
// A Tag associates a story with other content, like other stories, logs and more.
|
// A Tag associates a story with other content, like other stories, logs and more.
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
Kind string `bson:"kind"`
|
Kind TagKind `bson:"kind"`
|
||||||
Name string `bson:"name"`
|
Name string `bson:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal returns true if the tags match one another.
|
// Equal returns true if the tags match one another.
|
||||||
@@ -24,7 +24,7 @@ func ListTags() ([]Tag, error) {
|
|||||||
err := storyCollection.Find(bson.M{"listed": true, "tags": bson.M{"$ne": nil}}).Distinct("tags", &tags)
|
err := storyCollection.Find(bson.M{"listed": true, "tags": bson.M{"$ne": nil}}).Distinct("tags", &tags)
|
||||||
|
|
||||||
sort.Slice(tags, func(i, j int) bool {
|
sort.Slice(tags, func(i, j int) bool {
|
||||||
kindCmp := strings.Compare(tags[i].Kind, tags[j].Kind)
|
kindCmp := strings.Compare(string(tags[i].Kind), string(tags[j].Kind))
|
||||||
if kindCmp != 0 {
|
if kindCmp != 0 {
|
||||||
return kindCmp < 0
|
return kindCmp < 0
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user