GraphQL API and utilities for the rpdata project
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

115 lines
2.5 KiB

  1. package models
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "strings"
  7. )
  8. // A Tag associates a story with other content, like other stories, logs and more.
  9. type Tag struct {
  10. Kind TagKind `bson:"kind"`
  11. Name string `bson:"name"`
  12. }
  13. func (tag *Tag) Decode(v string) error {
  14. split := strings.SplitN(v, ":", 2)
  15. if len(split) == 1 {
  16. return errors.New("bad tag name: " + v)
  17. }
  18. kind := TagKind("")
  19. err := kind.UnmarshalGQL(split[0])
  20. if err != nil {
  21. return err
  22. }
  23. tag.Kind = kind
  24. tag.Name = split[1]
  25. return nil
  26. }
  27. func (tag *Tag) String() string {
  28. return string(tag.Kind) + ":" + tag.Name
  29. }
  30. // Equal returns true if the tags match one another.
  31. func (tag *Tag) Equal(other Tag) bool {
  32. return tag.Kind == other.Kind && tag.Name == other.Name
  33. }
  34. // IsChangeObject is an interface implementation to identify it as a valid
  35. // ChangeObject in GQL.
  36. func (*Tag) IsChangeObject() {
  37. panic("this method is a dummy, and so is its caller")
  38. }
  39. func EncodeTagArray(arr []Tag) []string {
  40. result := make([]string, len(arr))
  41. for i, v := range arr {
  42. result[i] = v.String()
  43. }
  44. return result
  45. }
  46. func DecodeTagArray(arr []string) ([]*Tag, error) {
  47. result := make([]*Tag, 0, len(arr))
  48. for i, v := range arr {
  49. result = append(result, &Tag{})
  50. err := result[i].Decode(v)
  51. if err != nil {
  52. return nil, err
  53. }
  54. }
  55. return result, nil
  56. }
  57. // TagKind represents the kind of tags.
  58. type TagKind string
  59. const (
  60. // TagKindOrganization is a tag kind, see GraphQL documentation.
  61. TagKindOrganization TagKind = "Organization"
  62. // TagKindCharacter is a tag kind, see GraphQL documentation.
  63. TagKindCharacter TagKind = "Character"
  64. // TagKindLocation is a tag kind, see GraphQL documentation.
  65. TagKindLocation TagKind = "Location"
  66. // TagKindEvent is a tag kind, see GraphQL documentation.
  67. TagKindEvent TagKind = "Event"
  68. // TagKindSeries is a tag kind, see GraphQL documentation.
  69. TagKindSeries TagKind = "Series"
  70. )
  71. // UnmarshalGQL unmarshals
  72. func (e *TagKind) UnmarshalGQL(v interface{}) error {
  73. str, ok := v.(string)
  74. if !ok {
  75. return fmt.Errorf("enums must be strings")
  76. }
  77. *e = TagKind(str)
  78. switch *e {
  79. case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
  80. return nil
  81. default:
  82. return fmt.Errorf("%s is not a valid TagKind", str)
  83. }
  84. }
  85. // MarshalGQL turns it into a JSON string
  86. func (e TagKind) MarshalGQL(w io.Writer) {
  87. _, _ = fmt.Fprintf(w, "\"%s\"", string(e))
  88. }
  89. // TagFilter is a filter for tag listing.
  90. type TagFilter struct {
  91. Kind *TagKind `bson:"kind,omitempty"`
  92. }