{"version":3,"file":"main.C_IUjc.js","sources":["theme-202/virtual:theme","theme-202/discourse/connectors/static-page-after-content__mod-queue/static-page-after-content__mod-queue.gjs","theme-202/virtual:entrypoint:main"],"sourcesContent":["import { getObjectForTheme } from \"discourse/lib/theme-settings-store\";\n\nexport const settings = getObjectForTheme(202);\n\nexport function themePrefix(key) {\n  return `theme_translations.202.${key}`;\n}\n","import Component from \"@glimmer/component\";\nimport { tracked } from \"@glimmer/tracking\";\nimport { action } from \"@ember/object\";\nimport { service } from \"@ember/service\";\nimport { fn } from \"@ember/helper\";\nimport { on } from \"@ember/modifier\";\nimport { and, eq } from \"truth-helpers\";\nimport { ajax } from \"discourse/lib/ajax\";\nimport { popupAjaxError } from \"discourse/lib/ajax-error\";\n\n// Queue configuration\nconst QUEUES = {\n  badges: {\n    name: \"Badge Review\",\n    settingKey: \"badge_review_query_id\",\n    description: \"Threads tagged with needs-badge-helpful, needs-badge-solved, needs-badge-mcp, or needs-badge-docs\",\n    emptyMessage: \"No badges to review! 🎉\",\n    actions: [\n      \"Review the thread and decide if a badge should be awarded\",\n      \"If badge awarded, grant the badge to the user\",\n      \"Remove the needs-badge-* tag from the topic\"\n    ]\n  },\n  events: {\n    name: \"Events Categorization\",\n    settingKey: \"events_categorization_query_id\",\n    description: \"Posts in Events/Meetups category that need to be moved to the correct subcategory\",\n    emptyMessage: \"All events are properly categorized!\",\n    actions: [\n      \"Review the event details to determine location\",\n      \"Move the topic to the appropriate location-based subcategory\"\n    ]\n  },\n  category: {\n    name: \"Category Review\",\n    settingKey: \"category_review_query_id\",\n    description: \"Posts with #category-review tag that need a category determination\",\n    emptyMessage: \"No category reviews pending!\",\n    actions: [\n      \"Read the topic to understand its content\",\n      \"Move the topic to the correct category\",\n      \"Remove the #category-review tag\"\n    ]\n  },\n  billing: {\n    name: \"Unhidden Billing\",\n    settingKey: \"unhidden_billing_query_id\",\n    description: \"Visible posts in Account/Billing category that should be hidden\",\n    emptyMessage: \"No unhidden billing posts!\",\n    actions: [\n      \"All Account/Billing posts should be hidden for privacy\",\n      \"Unlist or hide the topic\"\n    ]\n  },\n  closeloop: {\n    name: \"Close the Loop\",\n    settingKey: \"close_the_loop_query_id\",\n    description: \"Threads where a linked Linear ticket had a status change (detected via webhook)\",\n    emptyMessage: \"No threads need follow-up! 🎉\",\n    actions: [\n      \"Check the linked Linear ticket for the status update\",\n      \"Reply to the thread with the relevant update for the customer\",\n      \"Remove the #close-the-loop tag from the topic\"\n    ]\n  },\n  guidelines: {\n    name: \"Guidelines Review\",\n    settingKey: \"guidelines_review_query_id\",\n    description: \"Threads tagged with guidelines-review, guidelines-conduct, guidelines-rant, guidelines-misinfo, or guidelines-ragebait\",\n    emptyMessage: \"No guideline violations to review! 🎉\",\n    actions: [\n      \"Review the flagged content for guideline violations\",\n      \"Hide the topic/post if necessary\",\n      \"Remove the guidelines-* tag(s) from the topic\"\n    ]\n  }\n};\n\nexport default class ModQueue extends Component {\n  @service currentUser;\n  @service router;\n  @tracked loading = true;\n  @tracked posts = [];\n  @tracked error = null;\n  @tracked lastRefreshTime = 0;\n  @tracked filters = {};\n  @tracked openFilterColumn = null;\n  @tracked activeQueue = 'badges';\n  @tracked columns = [];\n  @tracked sortColumn = null;\n  @tracked sortDirection = 'asc';\n  @tracked queueCounts = {};\n\n  REFRESH_COOLDOWN = 30000;\n\n  get filterableColumnIndices() {\n    let rawValue = settings.filterable_columns;\n    let columnNumbers;\n    \n    if (Array.isArray(rawValue)) {\n      columnNumbers = rawValue\n        .map(num => parseInt(String(num).trim(), 10))\n        .filter(num => !isNaN(num) && num > 0);\n    } else if (typeof rawValue === 'string' && rawValue.trim()) {\n      columnNumbers = rawValue\n        .split(/[|,]/)\n        .map(num => parseInt(num.trim(), 10))\n        .filter(num => !isNaN(num) && num > 0);\n    } else {\n      columnNumbers = [];\n    }\n    \n    return columnNumbers.map(num => num - 1);\n  }\n\n  get currentQueueConfig() {\n    return QUEUES[this.activeQueue];\n  }\n\n  get queueList() {\n    return Object.entries(QUEUES).map(([key, config]) => ({\n      key,\n      name: config.name,\n      count: this.queueCounts[key] || 0\n    }));\n  }\n\n  constructor() {\n    super(...arguments);\n    this.checkAuthAndLoad();\n    this.setupVisibilityListener();\n    this.setupClickOutsideListener();\n  }\n\n  willDestroy() {\n    super.willDestroy();\n    this.removeVisibilityListener();\n    this.removeClickOutsideListener();\n  }\n\n  @action\n  checkAuthAndLoad() {\n    const isCursorStaff = this.currentUser?.groups?.some(group => group.name === 'CursorStaff');\n    if (!this.currentUser || (!this.currentUser.staff && !isCursorStaff)) {\n      this.router.transitionTo(\"/\");\n      return;\n    }\n\n    this.loadAllQueueCounts();\n    this.loadPosts();\n  }\n\n  @action\n  async loadAllQueueCounts() {\n    // Load counts for all queues in parallel\n    const countPromises = Object.entries(QUEUES).map(async ([key, config]) => {\n      const queryId = settings[config.settingKey];\n      if (!queryId || queryId === 0) {\n        return [key, 0];\n      }\n      \n      try {\n        const response = await ajax(`/admin/plugins/explorer/queries/${queryId}/run`, {\n          type: \"POST\",\n          data: {}\n        });\n        return [key, response?.rows?.length || 0];\n      } catch {\n        return [key, 0];\n      }\n    });\n\n    const results = await Promise.all(countPromises);\n    const counts = {};\n    results.forEach(([key, count]) => {\n      counts[key] = count;\n    });\n    this.queueCounts = counts;\n  }\n\n  @action\n  async loadPosts() {\n    const config = this.currentQueueConfig;\n    const queryId = settings[config.settingKey];\n    \n    console.log(`[ModQueue] Loading ${this.activeQueue} queue with query ID: ${queryId}`);\n    \n    if (!queryId || queryId === 0) {\n      this.error = `No Data Explorer query ID configured for ${config.name}. Please set ${config.settingKey} in theme settings.`;\n      this.loading = false;\n      return;\n    }\n\n    this.loading = true;\n    this.error = null;\n\n    try {\n      const response = await ajax(`/admin/plugins/explorer/queries/${queryId}/run`, {\n        type: \"POST\",\n        data: {}\n      });\n\n      console.log(`[ModQueue] Query ${queryId} returned columns:`, response.columns);\n\n      if (response && response.rows) {\n        this.posts = this.formatPosts(response);\n        // Update count for current queue\n        this.queueCounts = {\n          ...this.queueCounts,\n          [this.activeQueue]: response.rows.length\n        };\n      } else {\n        this.posts = [];\n      }\n      \n      this.lastRefreshTime = Date.now();\n    } catch (error) {\n      console.error(\"Error loading posts from Data Explorer:\", error);\n      this.error = \"Failed to load posts. Check query ID and permissions.\";\n      popupAjaxError(error);\n    } finally {\n      this.loading = false;\n    }\n  }\n\n  formatPosts(response) {\n    const columns = response.columns || [];\n    const rows = response.rows || [];\n\n    this.columns = columns;\n\n    this.filterableColumnIndices.forEach(index => {\n      const columnName = columns[index];\n      if (columnName && !this.filters[columnName]) {\n        this.filters[columnName] = new Set();\n      }\n    });\n\n    this.filters = { ...this.filters };\n\n    return rows.map(row => {\n      const post = {};\n      columns.forEach((col, index) => {\n        post[col] = row[index];\n      });\n      return post;\n    });\n  }\n\n  get tableColumns() {\n    return this.columns || [];\n  }\n\n  getValue = (post, column) => {\n    return post[column];\n  }\n\n  formatColumnName = (columnName) => {\n    return columnName\n      .replace(/[_-]/g, ' ')\n      .split(' ')\n      .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n      .join(' ');\n  }\n\n  isFilterableColumn = (columnIndex) => {\n    return this.filterableColumnIndices.includes(columnIndex);\n  }\n\n  isUrl = (value) => {\n    if (!value || typeof value !== 'string') {\n      return false;\n    }\n    try {\n      const url = new URL(value);\n      return url.protocol === 'http:' || url.protocol === 'https:';\n    } catch {\n      return false;\n    }\n  }\n\n  shouldHideColumn = (columnIndex) => {\n    const columnName = this.columns[columnIndex];\n    if (!columnName) {\n      return false;\n    }\n    \n    const normalizedName = columnName.toLowerCase().replace(/[_\\s]/g, '');\n    \n    // Hide common utility columns\n    if (normalizedName === 'sort') {\n      return true;\n    }\n    \n    return false;\n  }\n\n  // Check if column contains date values (for proper sorting)\n  isDateColumn = (column) => {\n    const normalizedName = column.toLowerCase().replace(/[_\\s]/g, '');\n    return normalizedName.includes('date') || \n           normalizedName.includes('createdat') || \n           normalizedName.includes('updatedat') ||\n           normalizedName.includes('replyat') ||\n           normalizedName.includes('latestreplyat');\n  }\n\n  getUniqueValuesWithCounts = (columnName) => {\n    const valueCounts = new Map();\n    \n    this.posts.forEach(post => {\n      const value = post[columnName];\n      if (value !== null && value !== undefined) {\n        valueCounts.set(value, (valueCounts.get(value) || 0) + 1);\n      }\n    });\n\n    return Array.from(valueCounts.entries())\n      .sort((a, b) => b[1] - a[1])\n      .map(([value, count]) => ({ value, count }));\n  }\n\n  get filteredPosts() {\n    let result = this.posts.filter(post => {\n      for (const [columnName, selectedValues] of Object.entries(this.filters)) {\n        if (selectedValues.size > 0) {\n          const postValue = post[columnName];\n          if (!selectedValues.has(postValue)) {\n            return false;\n          }\n        }\n      }\n      return true;\n    });\n\n    if (this.sortColumn) {\n      const isDate = this.isDateColumn(this.sortColumn);\n      \n      result = [...result].sort((a, b) => {\n        let aVal = a[this.sortColumn];\n        let bVal = b[this.sortColumn];\n        \n        if (aVal == null && bVal == null) return 0;\n        if (aVal == null) return 1;\n        if (bVal == null) return -1;\n        \n        // Date columns - parse and compare as dates\n        if (isDate) {\n          const aDate = new Date(aVal);\n          const bDate = new Date(bVal);\n          if (!isNaN(aDate) && !isNaN(bDate)) {\n            return this.sortDirection === 'asc' ? aDate - bDate : bDate - aDate;\n          }\n        }\n        \n        if (typeof aVal === 'number' && typeof bVal === 'number') {\n          return this.sortDirection === 'asc' ? aVal - bVal : bVal - aVal;\n        }\n        \n        const aNum = parseFloat(aVal);\n        const bNum = parseFloat(bVal);\n        if (!isNaN(aNum) && !isNaN(bNum)) {\n          return this.sortDirection === 'asc' ? aNum - bNum : bNum - aNum;\n        }\n        \n        aVal = String(aVal).toLowerCase();\n        bVal = String(bVal).toLowerCase();\n        \n        if (aVal < bVal) return this.sortDirection === 'asc' ? -1 : 1;\n        if (aVal > bVal) return this.sortDirection === 'asc' ? 1 : -1;\n        return 0;\n      });\n    }\n\n    return result;\n  }\n\n  getSortIndicator = (column) => {\n    if (this.sortColumn !== column) {\n      return '';\n    }\n    return this.sortDirection === 'asc' ? '▲' : '▼';\n  }\n\n  isSortedColumn = (column) => {\n    return this.sortColumn === column;\n  }\n\n  isLinearTicket = (value) => {\n    if (!value || typeof value !== 'string') {\n      return false;\n    }\n    return /^[A-Z]+-\\d+$/.test(value.trim());\n  }\n\n  linearTicketUrl = (value) => {\n    return `https://linear.app/anysphere/issue/${value.trim()}/`;\n  }\n\n  isUrlColumn = (column) => {\n    const normalizedName = column.toLowerCase().replace(/[_\\s]/g, '');\n    if (normalizedName.includes('url') || normalizedName.includes('link')) {\n      return true;\n    }\n    \n    for (const post of this.posts) {\n      const value = post[column];\n      if (value && typeof value === 'string') {\n        return this.isUrl(value);\n      }\n    }\n    return false;\n  }\n\n  isSortableColumn = (column) => {\n    return !this.isUrlColumn(column);\n  }\n\n  @action\n  toggleFilterDropdown(columnName) {\n    if (this.openFilterColumn === columnName) {\n      this.openFilterColumn = null;\n    } else {\n      this.openFilterColumn = columnName;\n      \n      if (this.filters[columnName].size === 0) {\n        const uniqueValues = this.getUniqueValuesWithCounts(columnName);\n        uniqueValues.forEach(({ value }) => {\n          this.filters[columnName].add(value);\n        });\n      }\n    }\n  }\n\n  @action\n  toggleFilterValue(columnName, value) {\n    const filterSet = this.filters[columnName];\n    \n    if (filterSet.has(value)) {\n      filterSet.delete(value);\n    } else {\n      filterSet.add(value);\n    }\n    \n    this.filters = { ...this.filters };\n  }\n\n  isFilterValueSelected = (columnName, value) => {\n    return this.filters[columnName]?.has(value) || false;\n  }\n\n  @action\n  setupVisibilityListener() {\n    this.handleVisibilityChange = () => {\n      if (document.visibilityState === 'visible') {\n        const now = Date.now();\n        if (now - this.lastRefreshTime >= this.REFRESH_COOLDOWN) {\n          this.loadAllQueueCounts();\n          this.loadPosts();\n        }\n      }\n    };\n    \n    document.addEventListener('visibilitychange', this.handleVisibilityChange);\n  }\n\n  @action\n  removeVisibilityListener() {\n    if (this.handleVisibilityChange) {\n      document.removeEventListener('visibilitychange', this.handleVisibilityChange);\n    }\n  }\n\n  @action\n  setupClickOutsideListener() {\n    this.handleClickOutside = (event) => {\n      if (this.openFilterColumn && !event.target.closest('.filter-dropdown') && !event.target.closest('.filter-toggle')) {\n        this.openFilterColumn = null;\n      }\n    };\n    \n    document.addEventListener('click', this.handleClickOutside);\n  }\n\n  @action\n  removeClickOutsideListener() {\n    if (this.handleClickOutside) {\n      document.removeEventListener('click', this.handleClickOutside);\n    }\n  }\n\n  @action\n  refresh() {\n    this.loadAllQueueCounts();\n    this.loadPosts();\n  }\n\n  @action\n  switchQueue(queueKey) {\n    if (this.activeQueue !== queueKey) {\n      this.activeQueue = queueKey;\n      this.filters = {};\n      this.sortColumn = null;\n      this.sortDirection = 'asc';\n      this.loadPosts();\n    }\n  }\n\n  @action\n  toggleSort(column) {\n    if (!this.isSortableColumn(column)) {\n      return;\n    }\n    \n    if (this.sortColumn === column) {\n      this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';\n    } else {\n      this.sortColumn = column;\n      this.sortDirection = 'asc';\n    }\n  }\n\n  <template>\n    <div class=\"mod-queue\">\n      <div class=\"queue-header\">\n        <h2>Mod Queue</h2>\n        <div class=\"header-controls\">\n          <div class=\"queue-selector\">\n            {{#each this.queueList as |queue|}}\n              <button \n                class=\"btn {{if (eq this.activeQueue queue.key) 'btn-primary' 'btn-default'}}\"\n                {{on \"click\" (fn this.switchQueue queue.key)}}>\n                {{queue.name}}\n                <span class=\"queue-count\">{{queue.count}}</span>\n              </button>\n            {{/each}}\n          </div>\n          <button class=\"btn btn-default\" {{on \"click\" this.refresh}}>\n            Refresh\n          </button>\n        </div>\n      </div>\n\n      <div class=\"queue-info\">\n        <div class=\"queue-description\">\n          <strong>{{this.currentQueueConfig.name}}:</strong> {{this.currentQueueConfig.description}}\n        </div>\n        <div class=\"queue-actions\">\n          <strong>Actions:</strong>\n          <ol>\n            {{#each this.currentQueueConfig.actions as |actionItem|}}\n              <li>{{actionItem}}</li>\n            {{/each}}\n          </ol>\n        </div>\n      </div>\n\n      {{#if this.loading}}\n        <div class=\"queue-loading\">\n          <p>Loading posts...</p>\n        </div>\n      {{else if this.error}}\n        <div class=\"queue-error\">\n          <p>{{this.error}}</p>\n        </div>\n      {{else if this.posts.length}}\n        <table class=\"queue-table\">\n          <thead>\n            <tr>\n              {{#each this.tableColumns as |column index|}}\n                {{#unless (this.shouldHideColumn index)}}\n                  <th class=\"{{if (this.isSortedColumn column) 'sorted'}} {{unless (this.isSortableColumn column) 'no-sort'}}\">\n                    <div class=\"th-content\">\n                      {{#if (this.isSortableColumn column)}}\n                        <button class=\"sort-toggle\" {{on \"click\" (fn this.toggleSort column)}}>\n                          <span>{{this.formatColumnName column}}</span>\n                          <span class=\"sort-indicator\">{{this.getSortIndicator column}}</span>\n                        </button>\n                      {{else}}\n                        <span class=\"column-name\">{{this.formatColumnName column}}</span>\n                      {{/if}}\n                      {{#if (this.isFilterableColumn index)}}\n                        <button class=\"filter-toggle\" {{on \"click\" (fn this.toggleFilterDropdown column)}}>\n                          <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n                            <path d=\"M6 9l6 6 6-6\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n                          </svg>\n                        </button>\n                        \n                        {{#if (eq this.openFilterColumn column)}}\n                          <div class=\"filter-dropdown\">\n                            <div class=\"filter-dropdown-content\">\n                              {{#each (this.getUniqueValuesWithCounts column) as |item|}}\n                                <label class=\"filter-option\">\n                                  <input \n                                    type=\"checkbox\" \n                                    checked={{this.isFilterValueSelected column item.value}}\n                                    {{on \"change\" (fn this.toggleFilterValue column item.value)}}\n                                  >\n                                  <span class=\"filter-label\">\n                                    {{item.value}}\n                                    <span class=\"filter-count\">({{item.count}})</span>\n                                  </span>\n                                </label>\n                              {{/each}}\n                            </div>\n                          </div>\n                        {{/if}}\n                      {{/if}}\n                    </div>\n                  </th>\n                {{/unless}}\n              {{/each}}\n            </tr>\n          </thead>\n          <tbody>\n              {{#each this.filteredPosts as |post|}}\n                <tr>\n                  {{#each this.tableColumns as |column index|}}\n                    {{#unless (this.shouldHideColumn index)}}\n                      <td>\n                        {{#if (eq column \"topic_id\")}}\n                          <a href=\"/t/{{this.getValue post column}}\" target=\"_blank\">{{this.getValue post column}}</a>\n                        {{else if (eq column \"post_id\")}}\n                          <a href=\"/p/{{this.getValue post column}}\" target=\"_blank\">{{this.getValue post column}}</a>\n                        {{else if (eq column \"user_id\")}}\n                          <a href=\"/u/{{this.getValue post column}}\" target=\"_blank\">{{this.getValue post column}}</a>\n                        {{else if (eq column \"username\")}}\n                          <a href=\"/u/{{this.getValue post column}}\" target=\"_blank\">{{this.getValue post column}}</a>\n                        {{else}}\n                          {{#if (this.isLinearTicket (this.getValue post column))}}\n                            <a href=\"{{this.linearTicketUrl (this.getValue post column)}}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"linear-ticket-button\">\n                              {{this.getValue post column}}\n                            </a>\n                          {{else if (and settings.convert_urls_to_buttons (this.isUrl (this.getValue post column)))}}\n                            <a href=\"{{this.getValue post column}}\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"url-button\">\n                              Open Link\n                            </a>\n                          {{else}}\n                            {{this.getValue post column}}\n                          {{/if}}\n                        {{/if}}\n                      </td>\n                    {{/unless}}\n                  {{/each}}\n                </tr>\n              {{/each}}\n          </tbody>\n        </table>\n      {{else}}\n        <div class=\"queue-empty\">\n          <div class=\"empty-icon\">✓</div>\n          <p>{{this.currentQueueConfig.emptyMessage}}</p>\n        </div>\n      {{/if}}\n    </div>\n  </template>\n}\n","import * as Mod1 from \"./discourse/connectors/static-page-after-content__mod-queue/static-page-after-content__mod-queue.gjs\";\nconst compatModules = {\n  \"discourse/connectors/static-page-after-content__mod-queue/static-page-after-content__mod-queue\": Mod1,\n};\nexport { compatModules };\nexport default compatModules;\n"],"names":["settings","getObjectForTheme","QUEUES","badges","name","settingKey","description","emptyMessage","actions","events","category","billing","closeloop","guidelines","ModQueue","Component","dt7948","g","this","prototype","service","currentUser","i","router","tracked","loading","posts","error","lastRefreshTime","filters","openFilterColumn","activeQueue","columns","sortColumn","sortDirection","queueCounts","REFRESH_COOLDOWN","filterableColumnIndices","columnNumbers","rawValue","filterable_columns","Array","isArray","map","num","parseInt","String","trim","filter","isNaN","split","currentQueueConfig","queueList","Object","entries","key","config","count","constructor","super","arguments","checkAuthAndLoad","setupVisibilityListener","setupClickOutsideListener","willDestroy","removeVisibilityListener","removeClickOutsideListener","isCursorStaff","groups","some","group","staff","loadAllQueueCounts","loadPosts","transitionTo","n","action","countPromises","async","queryId","response","ajax","type","data","rows","length","results","Promise","all","counts","forEach","console","log","formatPosts","Date","now","popupAjaxError","index","columnName","Set","row","post","col","tableColumns","getValue","column","formatColumnName","replace","word","charAt","toUpperCase","slice","toLowerCase","join","isFilterableColumn","columnIndex","includes","isUrl","value","url","URL","protocol","shouldHideColumn","isDateColumn","normalizedName","getUniqueValuesWithCounts","valueCounts","Map","set","get","from","sort","a","b","filteredPosts","result","selectedValues","size","postValue","has","isDate","aVal","bVal","aDate","bDate","aNum","parseFloat","bNum","getSortIndicator","isSortedColumn","isLinearTicket","test","linearTicketUrl","isUrlColumn","isSortableColumn","toggleFilterDropdown","add","toggleFilterValue","filterSet","delete","isFilterValueSelected","handleVisibilityChange","document","visibilityState","addEventListener","removeEventListener","handleClickOutside","event","target","closest","refresh","switchQueue","queueKey","toggleSort","setComponentTemplate","createTemplateFactory","id","block","moduleName","scope","eq","on","fn","and","isStrictMode","compatModules"],"mappings":"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"}