mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	 4cc2f6d6ad
			
		
	
	4cc2f6d6ad
	
	
	
		
			
			# Pull Request Template ## Description This PR includes: 1. Ensuring dropdowns always stay within the screen, with auto top/bottom/left/right positioning. 2. Fixing the dropdown truncation issue. 3. Removing the display of IDs from dropdowns. 4. Increasing the width of the inbox limit input field. 5. Updating the position of the **Update** button in the agent assignment edit page. ## Type of change - [x] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? ### Loom video https://www.loom.com/share/f20afc854edc42fab69a003f347d089b?sid=5e5f45f3-5950-46ff-b25c-0d1894daaede ## Checklist: - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my code - [x] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
		
			
				
	
	
		
			178 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <script setup>
 | |
| import { computed } from 'vue';
 | |
| import { useI18n } from 'vue-i18n';
 | |
| import Button from 'dashboard/components-next/button/Button.vue';
 | |
| import Spinner from 'dashboard/components-next/spinner/Spinner.vue';
 | |
| import AddDataDropdown from 'dashboard/components-next/AssignmentPolicy/components/AddDataDropdown.vue';
 | |
| 
 | |
| const props = defineProps({
 | |
|   inboxList: {
 | |
|     type: Array,
 | |
|     default: () => [],
 | |
|   },
 | |
|   isFetching: {
 | |
|     type: Boolean,
 | |
|     default: false,
 | |
|   },
 | |
| });
 | |
| 
 | |
| const emit = defineEmits(['delete', 'add', 'update']);
 | |
| 
 | |
| const inboxCapacityLimits = defineModel('inboxCapacityLimits', {
 | |
|   type: Array,
 | |
|   default: () => [],
 | |
| });
 | |
| 
 | |
| const { t } = useI18n();
 | |
| 
 | |
| const BASE_KEY = 'ASSIGNMENT_POLICY.AGENT_CAPACITY_POLICY';
 | |
| const DEFAULT_CONVERSATION_LIMIT = 10;
 | |
| const MIN_CONVERSATION_LIMIT = 1;
 | |
| const MAX_CONVERSATION_LIMIT = 100000;
 | |
| 
 | |
| const selectedInboxIds = computed(
 | |
|   () => new Set(inboxCapacityLimits.value.map(limit => limit.inboxId))
 | |
| );
 | |
| 
 | |
| const availableInboxes = computed(() =>
 | |
|   props.inboxList.filter(
 | |
|     inbox => inbox && !selectedInboxIds.value.has(inbox.id)
 | |
|   )
 | |
| );
 | |
| 
 | |
| const isLimitValid = limit => {
 | |
|   return (
 | |
|     limit.conversationLimit >= MIN_CONVERSATION_LIMIT &&
 | |
|     limit.conversationLimit <= MAX_CONVERSATION_LIMIT
 | |
|   );
 | |
| };
 | |
| 
 | |
| const inboxMap = computed(
 | |
|   () => new Map(props.inboxList.map(inbox => [inbox.id, inbox]))
 | |
| );
 | |
| 
 | |
| const handleAddInbox = inbox => {
 | |
|   emit('add', {
 | |
|     inboxId: inbox.id,
 | |
|     conversationLimit: DEFAULT_CONVERSATION_LIMIT,
 | |
|   });
 | |
| };
 | |
| 
 | |
| const handleRemoveLimit = limitId => {
 | |
|   emit('delete', limitId);
 | |
| };
 | |
| 
 | |
| const handleLimitChange = limit => {
 | |
|   if (isLimitValid(limit)) {
 | |
|     emit('update', limit);
 | |
|   }
 | |
| };
 | |
| 
 | |
| const getInboxName = inboxId => {
 | |
|   return inboxMap.value.get(inboxId)?.name || '';
 | |
| };
 | |
| </script>
 | |
| 
 | |
| <template>
 | |
|   <div class="py-4 flex-col flex gap-3">
 | |
|     <div class="flex items-center w-full gap-8 justify-between pt-1 pb-3">
 | |
|       <label class="text-sm font-medium text-n-slate-12">
 | |
|         {{ t(`${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.LABEL`) }}
 | |
|       </label>
 | |
| 
 | |
|       <AddDataDropdown
 | |
|         :label="t(`${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.ADD_BUTTON`)"
 | |
|         :search-placeholder="
 | |
|           t(`${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.FIELD.SELECT_INBOX`)
 | |
|         "
 | |
|         :items="availableInboxes"
 | |
|         @add="handleAddInbox"
 | |
|       />
 | |
|     </div>
 | |
| 
 | |
|     <div
 | |
|       v-if="isFetching"
 | |
|       class="flex items-center justify-center py-3 w-full text-n-slate-11"
 | |
|     >
 | |
|       <Spinner />
 | |
|     </div>
 | |
| 
 | |
|     <div
 | |
|       v-else-if="!inboxCapacityLimits.length"
 | |
|       class="custom-dashed-border flex items-center justify-center py-6 w-full"
 | |
|     >
 | |
|       <span class="text-sm text-n-slate-11">
 | |
|         {{ t(`${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.EMPTY_STATE`) }}
 | |
|       </span>
 | |
|     </div>
 | |
| 
 | |
|     <div v-else class="flex-col flex gap-3">
 | |
|       <div
 | |
|         v-for="(limit, index) in inboxCapacityLimits"
 | |
|         :key="limit.id || `temp-${index}`"
 | |
|         class="flex flex-col xs:flex-row items-stretch gap-3"
 | |
|       >
 | |
|         <div
 | |
|           class="flex items-center rounded-lg outline-1 outline cursor-not-allowed text-n-slate-11 outline-n-weak py-2.5 px-3 text-sm w-full min-w-0"
 | |
|           :title="getInboxName(limit.inboxId)"
 | |
|         >
 | |
|           <span class="truncate min-w-0">
 | |
|             {{ getInboxName(limit.inboxId) }}
 | |
|           </span>
 | |
|         </div>
 | |
| 
 | |
|         <div class="flex items-center gap-3 w-full xs:w-auto">
 | |
|           <div
 | |
|             class="py-2.5 px-3 rounded-lg gap-2 outline outline-1 flex-1 xs:flex-shrink-0 flex items-center min-w-0"
 | |
|             :class="[
 | |
|               !isLimitValid(limit) ? 'outline-n-ruby-8' : 'outline-n-weak',
 | |
|             ]"
 | |
|           >
 | |
|             <label
 | |
|               class="text-sm text-n-slate-12 ltr:pr-2 rtl:pl-2 truncate min-w-0 flex-shrink"
 | |
|               :title="
 | |
|                 t(
 | |
|                   `${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.FIELD.MAX_CONVERSATIONS`
 | |
|                 )
 | |
|               "
 | |
|             >
 | |
|               {{
 | |
|                 t(
 | |
|                   `${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.FIELD.MAX_CONVERSATIONS`
 | |
|                 )
 | |
|               }}
 | |
|             </label>
 | |
| 
 | |
|             <div class="h-5 w-px bg-n-weak" />
 | |
| 
 | |
|             <input
 | |
|               v-model.number="limit.conversationLimit"
 | |
|               type="number"
 | |
|               :min="MIN_CONVERSATION_LIMIT"
 | |
|               :max="MAX_CONVERSATION_LIMIT"
 | |
|               class="reset-base bg-transparent focus:outline-none min-w-16 w-24 text-sm flex-shrink-0"
 | |
|               :class="[
 | |
|                 !isLimitValid(limit)
 | |
|                   ? 'placeholder:text-n-ruby-9 !text-n-ruby-9'
 | |
|                   : 'placeholder:text-n-slate-10 text-n-slate-12',
 | |
|               ]"
 | |
|               :placeholder="
 | |
|                 t(`${BASE_KEY}.FORM.INBOX_CAPACITY_LIMIT.FIELD.SET_LIMIT`)
 | |
|               "
 | |
|               @blur="handleLimitChange(limit)"
 | |
|             />
 | |
|           </div>
 | |
| 
 | |
|           <Button
 | |
|             type="button"
 | |
|             slate
 | |
|             icon="i-lucide-trash"
 | |
|             class="flex-shrink-0"
 | |
|             @click="handleRemoveLimit(limit.id)"
 | |
|           />
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 |