mirror of
				https://github.com/abhinavxd/libredesk.git
				synced 2025-11-04 05:53:30 +00:00 
			
		
		
		
	Compare commits
	
		
			8 Commits
		
	
	
		
			v0.7.0-alp
			...
			v0.7.2-alp
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					e0dc0285a4 | ||
| 
						 | 
					b971619ea6 | ||
| 
						 | 
					69accaebef | ||
| 
						 | 
					27de73536e | ||
| 
						 | 
					df108a3363 | ||
| 
						 | 
					266c3dab72 | ||
| 
						 | 
					bf2c1fff6f | ||
| 
						 | 
					2930af0c4f | 
							
								
								
									
										16
									
								
								.github/ISSUE_TEMPLATE/confirmed-bug.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/ISSUE_TEMPLATE/confirmed-bug.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					name: Confirmed Bug Report
 | 
				
			||||||
 | 
					about: Report a confirmed bug in Libredesk
 | 
				
			||||||
 | 
					title: "[Bug] <brief summary>"
 | 
				
			||||||
 | 
					labels: bug
 | 
				
			||||||
 | 
					assignees: ""
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Version:**
 | 
				
			||||||
 | 
					- libredesk: [eg: v0.7.0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Description of the bug and steps to reproduce:**
 | 
				
			||||||
 | 
					A clear and concise description of what the bug is.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Logs / Screenshots:**
 | 
				
			||||||
 | 
					Attach any relevant logs or screenshots to help diagnose the issue.
 | 
				
			||||||
							
								
								
									
										16
									
								
								.github/ISSUE_TEMPLATE/possible-bug.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								.github/ISSUE_TEMPLATE/possible-bug.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					name: Possible Bug Report
 | 
				
			||||||
 | 
					about: Something in Libredesk might be broken but needs confirmation
 | 
				
			||||||
 | 
					title: "[Possible Bug] <brief summary>"
 | 
				
			||||||
 | 
					labels: bug, needs-investigation
 | 
				
			||||||
 | 
					assignees: ""
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Version:**
 | 
				
			||||||
 | 
					 - libredesk: [eg: v0.7.0]
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					**Description of the bug and steps to reproduce:**
 | 
				
			||||||
 | 
					A clear and concise description of what the bug is.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Logs / Screenshots:**
 | 
				
			||||||
 | 
					Attach any relevant logs or screenshots to help diagnose the issue.
 | 
				
			||||||
@@ -3,7 +3,6 @@ package main
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	amodels "github.com/abhinavxd/libredesk/internal/auth/models"
 | 
						amodels "github.com/abhinavxd/libredesk/internal/auth/models"
 | 
				
			||||||
	"github.com/abhinavxd/libredesk/internal/envelope"
 | 
						"github.com/abhinavxd/libredesk/internal/envelope"
 | 
				
			||||||
	umodels "github.com/abhinavxd/libredesk/internal/user/models"
 | 
					 | 
				
			||||||
	realip "github.com/ferluci/fast-realip"
 | 
						realip "github.com/ferluci/fast-realip"
 | 
				
			||||||
	"github.com/valyala/fasthttp"
 | 
						"github.com/valyala/fasthttp"
 | 
				
			||||||
	"github.com/zerodha/fastglue"
 | 
						"github.com/zerodha/fastglue"
 | 
				
			||||||
@@ -42,12 +41,6 @@ func handleLogin(r *fastglue.Request) error {
 | 
				
			|||||||
		return sendErrorEnvelope(r, envelope.NewError(envelope.GeneralError, app.i18n.T("user.accountDisabled"), nil))
 | 
							return sendErrorEnvelope(r, envelope.NewError(envelope.GeneralError, app.i18n.T("user.accountDisabled"), nil))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set user availability status to online.
 | 
					 | 
				
			||||||
	if err := app.user.UpdateAvailability(user.ID, umodels.Online); err != nil {
 | 
					 | 
				
			||||||
		return sendErrorEnvelope(r, err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	user.AvailabilityStatus = umodels.Online
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err := app.auth.SaveSession(amodels.User{
 | 
						if err := app.auth.SaveSession(amodels.User{
 | 
				
			||||||
		ID:        user.ID,
 | 
							ID:        user.ID,
 | 
				
			||||||
		Email:     user.Email.String,
 | 
							Email:     user.Email.String,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										30
									
								
								docs/docs/api-getting-started.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								docs/docs/api-getting-started.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					# API getting started
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can access the Libredesk API to interact with your instance programmatically.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Generating API keys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1. **Edit agent**: Go to Admin → Teammate → Agent → Edit
 | 
				
			||||||
 | 
					2. **Generate new API key**: An API Key and API Secret will be generated for the agent
 | 
				
			||||||
 | 
					3. **Save the credentials**: Keep both the API Key and API Secret secure
 | 
				
			||||||
 | 
					4. **Key management**: You can revoke / regenerate API keys at any time from the same page
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Using the API
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LibreDesk supports two authentication schemes:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Basic authentication
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					curl -X GET "https://your-libredesk-instance.com/api/endpoint" \
 | 
				
			||||||
 | 
					  -H "Authorization: Basic <base64_encoded_key:secret>"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Token authentication
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					curl -X GET "https://your-libredesk-instance.com/api/endpoint" \
 | 
				
			||||||
 | 
					  -H "Authorization: token your_api_key:your_api_secret"
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## API Documentation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Complete API documentation with available endpoints and examples coming soon.
 | 
				
			||||||
@@ -32,6 +32,7 @@ nav:
 | 
				
			|||||||
      - Email Templates: templating.md
 | 
					      - Email Templates: templating.md
 | 
				
			||||||
      - SSO Setup: sso.md
 | 
					      - SSO Setup: sso.md
 | 
				
			||||||
      - Webhooks: webhooks.md
 | 
					      - Webhooks: webhooks.md
 | 
				
			||||||
 | 
					      - API Getting Started: api-getting-started.md
 | 
				
			||||||
  - Contributions:
 | 
					  - Contributions:
 | 
				
			||||||
      - Developer Setup: developer-setup.md
 | 
					      - Developer Setup: developer-setup.md
 | 
				
			||||||
      - Translate Libredesk: translations.md
 | 
					      - Translate Libredesk: translations.md
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,105 +1,139 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="max-w-5xl mx-auto p-6 min-h-screen">
 | 
					  <div class="max-w-5xl mx-auto p-6 min-h-screen">
 | 
				
			||||||
    <div class="space-y-8">
 | 
					    <Tabs :default-value="defaultTab" v-model="activeTab">
 | 
				
			||||||
      <div
 | 
					      <TabsList class="grid w-full mb-6" :class="tabsGridClass">
 | 
				
			||||||
        v-for="(items, type) in results"
 | 
					        <TabsTrigger v-for="(items, type) in results" :key="type" :value="type" class="capitalize">
 | 
				
			||||||
        :key="type"
 | 
					          {{ type }} ({{ items.length }})
 | 
				
			||||||
        class="bg-card rounded shadow overflow-hidden"
 | 
					        </TabsTrigger>
 | 
				
			||||||
      >
 | 
					      </TabsList>
 | 
				
			||||||
        <!-- Header for each section -->
 | 
					 | 
				
			||||||
        <h2
 | 
					 | 
				
			||||||
          class="bg-primary dark:bg-primary text-lg font-bold text-white dark:text-primary-foreground py-2 px-6 capitalize"
 | 
					 | 
				
			||||||
        >
 | 
					 | 
				
			||||||
          {{ type }}
 | 
					 | 
				
			||||||
        </h2>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- No results message -->
 | 
					      <TabsContent v-for="(items, type) in results" :key="type" :value="type" class="mt-0">
 | 
				
			||||||
        <div v-if="items.length === 0" class="p-6 text-gray-500 dark:text-muted-foreground">
 | 
					        <div class="bg-background rounded border overflow-hidden">
 | 
				
			||||||
          {{
 | 
					          <!-- No results message -->
 | 
				
			||||||
            $t('globals.messages.noResults', {
 | 
					          <div v-if="items.length === 0" class="p-8 text-center text-muted-foreground">
 | 
				
			||||||
              name: type
 | 
					            <div class="text-lg font-medium mb-2">
 | 
				
			||||||
            })
 | 
					              {{
 | 
				
			||||||
          }}
 | 
					                $t('globals.messages.noResults', {
 | 
				
			||||||
        </div>
 | 
					                  name: type
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					              }}
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            <div class="text-sm">{{ $t('search.adjustSearchTerms') }}</div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <!-- Results list -->
 | 
					          <!-- Results list -->
 | 
				
			||||||
        <div class="divide-y divide-gray-200 dark:divide-border">
 | 
					          <div v-else class="divide-y divide-border">
 | 
				
			||||||
          <div
 | 
					            <div
 | 
				
			||||||
            v-for="item in items"
 | 
					              v-for="item in items"
 | 
				
			||||||
            :key="item.id || item.uuid"
 | 
					              :key="item.id || item.uuid"
 | 
				
			||||||
            class="p-6 hover:bg-gray-100 dark:hover:bg-accent transition duration-300 ease-in-out group"
 | 
					              class="p-6 hover:bg-accent/50 transition duration-200 ease-in-out group"
 | 
				
			||||||
          >
 | 
					 | 
				
			||||||
            <router-link
 | 
					 | 
				
			||||||
              :to="{
 | 
					 | 
				
			||||||
                name: 'inbox-conversation',
 | 
					 | 
				
			||||||
                params: {
 | 
					 | 
				
			||||||
                  uuid: type === 'conversations' ? item.uuid : item.conversation_uuid,
 | 
					 | 
				
			||||||
                  type: 'assigned'
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
              }"
 | 
					 | 
				
			||||||
              class="block"
 | 
					 | 
				
			||||||
            >
 | 
					            >
 | 
				
			||||||
              <div class="flex justify-between items-start">
 | 
					              <router-link
 | 
				
			||||||
                <div class="flex-grow">
 | 
					                :to="{
 | 
				
			||||||
                  <!-- Reference number -->
 | 
					                  name: 'inbox-conversation',
 | 
				
			||||||
                  <div
 | 
					                  params: {
 | 
				
			||||||
                    class="text-sm font-semibold mb-2 group-hover:text-primary dark:group-hover:text-primary transition duration-300"
 | 
					                    uuid: type === 'conversations' ? item.uuid : item.conversation_uuid,
 | 
				
			||||||
                  >
 | 
					                    type: 'assigned'
 | 
				
			||||||
                    #{{
 | 
					                  }
 | 
				
			||||||
                      type === 'conversations'
 | 
					                }"
 | 
				
			||||||
                        ? item.reference_number
 | 
					                class="block"
 | 
				
			||||||
                        : item.conversation_reference_number
 | 
					              >
 | 
				
			||||||
                    }}
 | 
					                <div class="flex justify-between items-start">
 | 
				
			||||||
 | 
					                  <div class="flex-grow">
 | 
				
			||||||
 | 
					                    <!-- Reference number -->
 | 
				
			||||||
 | 
					                    <div
 | 
				
			||||||
 | 
					                      class="text-sm font-semibold mb-2 text-muted-foreground group-hover:text-primary transition duration-200"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      #{{
 | 
				
			||||||
 | 
					                        type === 'conversations'
 | 
				
			||||||
 | 
					                          ? item.reference_number
 | 
				
			||||||
 | 
					                          : item.conversation_reference_number
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <!-- Content -->
 | 
				
			||||||
 | 
					                    <div
 | 
				
			||||||
 | 
					                      class="text-foreground font-medium mb-2 text-lg group-hover:text-primary transition duration-200"
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {{
 | 
				
			||||||
 | 
					                        truncateText(
 | 
				
			||||||
 | 
					                          type === 'conversations' ? item.subject : item.text_content,
 | 
				
			||||||
 | 
					                          100
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    <!-- Timestamp -->
 | 
				
			||||||
 | 
					                    <div class="text-sm text-muted-foreground flex items-center">
 | 
				
			||||||
 | 
					                      <ClockIcon class="h-4 w-4 mr-1" />
 | 
				
			||||||
 | 
					                      {{
 | 
				
			||||||
 | 
					                        formatDate(
 | 
				
			||||||
 | 
					                          type === 'conversations' ? item.created_at : item.conversation_created_at
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                      }}
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  <!-- Content -->
 | 
					                  <!-- Right arrow icon -->
 | 
				
			||||||
                  <div
 | 
					                  <div
 | 
				
			||||||
                    class="text-gray-900 dark:text-card-foreground font-medium mb-2 text-lg group-hover:text-gray-950 dark:group-hover:text-foreground transition duration-300"
 | 
					                    class="bg-secondary rounded-full p-2 group-hover:bg-primary transition duration-200"
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    {{
 | 
					                    <ChevronRightIcon
 | 
				
			||||||
                      truncateText(type === 'conversations' ? item.subject : item.text_content, 100)
 | 
					                      class="h-5 w-5 text-secondary-foreground group-hover:text-primary-foreground"
 | 
				
			||||||
                    }}
 | 
					                      aria-hidden="true"
 | 
				
			||||||
                  </div>
 | 
					                    />
 | 
				
			||||||
 | 
					 | 
				
			||||||
                  <!-- Timestamp -->
 | 
					 | 
				
			||||||
                  <div class="text-sm text-gray-500 dark:text-muted-foreground flex items-center">
 | 
					 | 
				
			||||||
                    <ClockIcon class="h-4 w-4 mr-1" />
 | 
					 | 
				
			||||||
                    {{
 | 
					 | 
				
			||||||
                      formatDate(
 | 
					 | 
				
			||||||
                        type === 'conversations' ? item.created_at : item.conversation_created_at
 | 
					 | 
				
			||||||
                      )
 | 
					 | 
				
			||||||
                    }}
 | 
					 | 
				
			||||||
                  </div>
 | 
					                  </div>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
 | 
					              </router-link>
 | 
				
			||||||
                <!-- Right arrow icon -->
 | 
					            </div>
 | 
				
			||||||
                <div
 | 
					 | 
				
			||||||
                  class="bg-gray-200 dark:bg-secondary rounded-full p-2 group-hover:bg-primary dark:group-hover:bg-primary transition duration-300"
 | 
					 | 
				
			||||||
                >
 | 
					 | 
				
			||||||
                  <ChevronRightIcon
 | 
					 | 
				
			||||||
                    class="h-5 w-5 text-gray-700 dark:text-secondary-foreground group-hover:text-white dark:group-hover:text-primary-foreground"
 | 
					 | 
				
			||||||
                    aria-hidden="true"
 | 
					 | 
				
			||||||
                  />
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </router-link>
 | 
					 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </div>
 | 
					      </TabsContent>
 | 
				
			||||||
    </div>
 | 
					    </Tabs>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
<script setup>
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { computed, ref, watch } from 'vue'
 | 
				
			||||||
import { ChevronRightIcon, ClockIcon } from 'lucide-vue-next'
 | 
					import { ChevronRightIcon, ClockIcon } from 'lucide-vue-next'
 | 
				
			||||||
import { format, parseISO } from 'date-fns'
 | 
					import { format, parseISO } from 'date-fns'
 | 
				
			||||||
 | 
					import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineProps({
 | 
					const props = defineProps({
 | 
				
			||||||
  results: {
 | 
					  results: {
 | 
				
			||||||
    type: Object,
 | 
					    type: Object,
 | 
				
			||||||
    required: true
 | 
					    required: true
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get the first available tab as default
 | 
				
			||||||
 | 
					const defaultTab = computed(() => {
 | 
				
			||||||
 | 
					  const types = Object.keys(props.results)
 | 
				
			||||||
 | 
					  return types.length > 0 ? types[0] : ''
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const activeTab = ref('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Watch for changes in results and set the first tab as active
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
					  () => props.results,
 | 
				
			||||||
 | 
					  (newResults) => {
 | 
				
			||||||
 | 
					    const types = Object.keys(newResults)
 | 
				
			||||||
 | 
					    if (types.length > 0 && !activeTab.value) {
 | 
				
			||||||
 | 
					      activeTab.value = types[0]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  { immediate: true }
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Dynamic grid class based on number of tabs
 | 
				
			||||||
 | 
					const tabsGridClass = computed(() => {
 | 
				
			||||||
 | 
					  const tabCount = Object.keys(props.results).length
 | 
				
			||||||
 | 
					  if (tabCount <= 2) return 'grid-cols-2'
 | 
				
			||||||
 | 
					  if (tabCount <= 3) return 'grid-cols-3'
 | 
				
			||||||
 | 
					  if (tabCount <= 4) return 'grid-cols-4'
 | 
				
			||||||
 | 
					  return 'grid-cols-5'
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const formatDate = (dateString) => {
 | 
					const formatDate = (dateString) => {
 | 
				
			||||||
  const date = parseISO(dateString)
 | 
					  const date = parseISO(dateString)
 | 
				
			||||||
  return format(date, 'MMM d, yyyy HH:mm')
 | 
					  return format(date, 'MMM d, yyyy HH:mm')
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
									
									
									
									
								
							@@ -38,7 +38,7 @@ require (
 | 
				
			|||||||
	github.com/zerodha/simplesessions/v3 v3.0.0
 | 
						github.com/zerodha/simplesessions/v3 v3.0.0
 | 
				
			||||||
	golang.org/x/crypto v0.38.0
 | 
						golang.org/x/crypto v0.38.0
 | 
				
			||||||
	golang.org/x/mod v0.17.0
 | 
						golang.org/x/mod v0.17.0
 | 
				
			||||||
	golang.org/x/oauth2 v0.21.0
 | 
						golang.org/x/oauth2 v0.27.0
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
									
									
									
									
								
							@@ -140,8 +140,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 | 
				
			|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
					github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
				
			||||||
github.com/redis/go-redis/v9 v9.5.5 h1:51VEyMF8eOO+NUHFm8fpg+IOc1xFuFOhxs3R+kPu1FM=
 | 
					github.com/redis/go-redis/v9 v9.5.5 h1:51VEyMF8eOO+NUHFm8fpg+IOc1xFuFOhxs3R+kPu1FM=
 | 
				
			||||||
github.com/redis/go-redis/v9 v9.5.5/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
 | 
					github.com/redis/go-redis/v9 v9.5.5/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
 | 
				
			||||||
github.com/rhnvrm/simples3 v0.9.0 h1:It6/glyqRTRooRzXcYOuqpKwjGg3lsXgNmeGgxpBtjA=
 | 
					 | 
				
			||||||
github.com/rhnvrm/simples3 v0.9.0/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
 | 
					 | 
				
			||||||
github.com/rhnvrm/simples3 v0.9.1 h1:pYfEe2wTjx8B2zFzUdy4kZn3I3Otd9ZvzIhHkFR85kE=
 | 
					github.com/rhnvrm/simples3 v0.9.1 h1:pYfEe2wTjx8B2zFzUdy4kZn3I3Otd9ZvzIhHkFR85kE=
 | 
				
			||||||
github.com/rhnvrm/simples3 v0.9.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
 | 
					github.com/rhnvrm/simples3 v0.9.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
 | 
				
			||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 | 
					github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 | 
				
			||||||
@@ -211,8 +209,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 | 
				
			|||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
					golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
				
			||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
 | 
					golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
 | 
				
			||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
 | 
					golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
 | 
				
			||||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
 | 
					golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
 | 
				
			||||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 | 
					golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -568,6 +568,7 @@
 | 
				
			|||||||
  "search.noResultsForQuery": "No results found for query `{query}`. Try a different search term.",
 | 
					  "search.noResultsForQuery": "No results found for query `{query}`. Try a different search term.",
 | 
				
			||||||
  "search.minQueryLength": " Please enter at least {length} characters to search.",
 | 
					  "search.minQueryLength": " Please enter at least {length} characters to search.",
 | 
				
			||||||
  "search.searchBy": "Search by reference number, contact email address or messages in conversations.",
 | 
					  "search.searchBy": "Search by reference number, contact email address or messages in conversations.",
 | 
				
			||||||
 | 
					  "search.adjustSearchTerms": "Try adjusting your search terms or filters.",
 | 
				
			||||||
  "sla.overdueBy": "Overdue by",
 | 
					  "sla.overdueBy": "Overdue by",
 | 
				
			||||||
  "sla.met": "SLA met",
 | 
					  "sla.met": "SLA met",
 | 
				
			||||||
  "view.form.description": "Create and save custom filter views for quick access to your conversations.",
 | 
					  "view.form.description": "Create and save custom filter views for quick access to your conversations.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -438,6 +438,7 @@ SELECT
 | 
				
			|||||||
    m.sender_type,
 | 
					    m.sender_type,
 | 
				
			||||||
    m.sender_id,
 | 
					    m.sender_id,
 | 
				
			||||||
    m.meta,
 | 
					    m.meta,
 | 
				
			||||||
 | 
					    c.uuid as conversation_uuid,
 | 
				
			||||||
    COALESCE(
 | 
					    COALESCE(
 | 
				
			||||||
        json_agg(
 | 
					        json_agg(
 | 
				
			||||||
            json_build_object(
 | 
					            json_build_object(
 | 
				
			||||||
@@ -452,10 +453,11 @@ SELECT
 | 
				
			|||||||
        '[]'::json
 | 
					        '[]'::json
 | 
				
			||||||
    ) AS attachments
 | 
					    ) AS attachments
 | 
				
			||||||
FROM conversation_messages m
 | 
					FROM conversation_messages m
 | 
				
			||||||
 | 
					INNER JOIN conversations c ON c.id = m.conversation_id
 | 
				
			||||||
LEFT JOIN media ON media.model_type = 'messages' AND media.model_id = m.id
 | 
					LEFT JOIN media ON media.model_type = 'messages' AND media.model_id = m.id
 | 
				
			||||||
WHERE m.uuid = $1
 | 
					WHERE m.uuid = $1
 | 
				
			||||||
GROUP BY 
 | 
					GROUP BY 
 | 
				
			||||||
    m.id, m.created_at, m.updated_at, m.status, m.type, m.content, m.uuid, m.private, m.sender_type
 | 
					    m.id, m.created_at, m.updated_at, m.status, m.type, m.content, m.uuid, m.private, m.sender_type, c.uuid
 | 
				
			||||||
ORDER BY m.created_at;
 | 
					ORDER BY m.created_at;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- name: get-messages
 | 
					-- name: get-messages
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user