The frontend/UI server, written in JS using the MarkoJS library
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.

144 lines
3.3 KiB

  1. const {channelApi} = require("../../../../../rpdata/api/Channel")
  2. const {logHeaderApi} = require("../../../../../rpdata/api/LogHeader")
  3. module.exports = class {
  4. onCreate() {
  5. this.state = {
  6. search: "",
  7. filters: [],
  8. channels: [],
  9. eventNames: [],
  10. }
  11. this.first = true
  12. }
  13. onInput(input) {
  14. if (input.filters) {
  15. if (this.timeout != null) {
  16. setTimeout(() => {
  17. this.searchFilters()
  18. }, 1)
  19. }
  20. }
  21. }
  22. onMount() {
  23. this.timeout = null
  24. if (this.state.channels.length === 0) {
  25. channelApi.list().then(channels => {
  26. this.state.channels = channels
  27. this.searchFilters()
  28. }).catch(err => {
  29. console.warn("Failed to fetch channels:", err)
  30. })
  31. }
  32. if (this.state.eventNames.length === 0) {
  33. logHeaderApi.eventNames().then(eventNames => {
  34. this.state.eventNames = eventNames
  35. this.searchFilters()
  36. }).catch(err => {
  37. console.warn("Failed to fetch eventNames:", err)
  38. })
  39. }
  40. this.getEl("search").addEventListener("keydown", ev => {
  41. if (this.waiting) {
  42. return
  43. }
  44. if (this.timeout != null) {
  45. clearTimeout(this.timeout)
  46. }
  47. this.timeout = setTimeout(() => {
  48. this.timeout = null
  49. this.state.search = ev.target.value
  50. this.searchFilters()
  51. }, 200)
  52. })
  53. }
  54. onUnmount() {
  55. clearTimeout(this.timeout)
  56. this.timeout = null
  57. this.state.search = ""
  58. this.state.filters = []
  59. }
  60. add(type, value, filter) {
  61. this.emit("add", type, value)
  62. this.state.filters = this.state.filters.filter(f => f != filter)
  63. }
  64. searchFilters() {
  65. const filters = []
  66. const search = this.state.search.toLowerCase()
  67. for (const channel of this.state.channels) {
  68. if (search == "" || channel.name.toLowerCase().includes(search)) {
  69. if (this.input.filter.channels && this.input.filter.channels.includes(channel.name)) {
  70. continue
  71. }
  72. filters.push({
  73. colorClass: "color-tag-location",
  74. text: channel.name,
  75. type: "channels",
  76. value: channel.name,
  77. })
  78. }
  79. }
  80. for (const name of this.state.eventNames) {
  81. if (search == "" || name.toLowerCase().includes(search)) {
  82. if (this.input.filter.events && this.input.filter.events.includes(name)) {
  83. continue
  84. }
  85. filters.push({
  86. colorClass: "color-tag-event",
  87. text: name,
  88. type: "events",
  89. value: name,
  90. })
  91. }
  92. }
  93. for (const character of this.input.characters) {
  94. if (search == "" || character.name.toLowerCase().includes(search)) {
  95. if (this.input.filter.characters && this.input.filter.characters.includes(character.id)) {
  96. continue
  97. }
  98. filters.push({
  99. colorClass: "color-tag-character",
  100. text: character.name,
  101. type: "characters",
  102. value: character.id,
  103. })
  104. }
  105. }
  106. filters.sort((a, b) => {
  107. let aCompare = a.text
  108. let bCompare = b.text
  109. if (a.text.charAt(0) === "#") {
  110. aCompare = a.text.slice(1)
  111. }
  112. if (b.text.charAt(0) === "#") {
  113. bCompare = b.text.slice(1)
  114. }
  115. return aCompare.localeCompare(bCompare)
  116. })
  117. this.state.filters = filters
  118. }
  119. }