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.

114 lines
2.4 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(v)
  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, len(arr))
  48. for i, v := range arr {
  49. err := result[i].Decode(v)
  50. if err != nil {
  51. return nil, err
  52. }
  53. }
  54. return result, nil
  55. }
  56. // TagKind represents the kind of tags.
  57. type TagKind string
  58. const (
  59. // TagKindOrganization is a tag kind, see GraphQL documentation.
  60. TagKindOrganization TagKind = "Organization"
  61. // TagKindCharacter is a tag kind, see GraphQL documentation.
  62. TagKindCharacter TagKind = "Character"
  63. // TagKindLocation is a tag kind, see GraphQL documentation.
  64. TagKindLocation TagKind = "Location"
  65. // TagKindEvent is a tag kind, see GraphQL documentation.
  66. TagKindEvent TagKind = "Event"
  67. // TagKindSeries is a tag kind, see GraphQL documentation.
  68. TagKindSeries TagKind = "Series"
  69. )
  70. // UnmarshalGQL unmarshals
  71. func (e *TagKind) UnmarshalGQL(v interface{}) error {
  72. str, ok := v.(string)
  73. if !ok {
  74. return fmt.Errorf("enums must be strings")
  75. }
  76. *e = TagKind(str)
  77. switch *e {
  78. case TagKindOrganization, TagKindCharacter, TagKindLocation, TagKindEvent, TagKindSeries:
  79. return nil
  80. default:
  81. return fmt.Errorf("%s is not a valid TagKind", str)
  82. }
  83. }
  84. // MarshalGQL turns it into a JSON string
  85. func (e TagKind) MarshalGQL(w io.Writer) {
  86. _, _ = fmt.Fprintf(w, "\"%s\"", string(e))
  87. }
  88. // TagFilter is a filter for tag listing.
  89. type TagFilter struct {
  90. Kind *TagKind `bson:"kind,omitempty"`
  91. }