diff --git a/files/client/custom/modules/smart-assistant/src/views/floating-chat.js b/files/client/custom/modules/smart-assistant/src/views/floating-chat.js index 92e88b6..397256d 100644 --- a/files/client/custom/modules/smart-assistant/src/views/floating-chat.js +++ b/files/client/custom/modules/smart-assistant/src/views/floating-chat.js @@ -24,6 +24,9 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) ' ' + + ' ' + ' ' + @@ -67,7 +70,10 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) '.sa-fab:hover { transform: scale(1.08); }' + '.sa-fab-avatar { width: 100%; height: 100%; object-fit: cover; }' + '.sa-fab-badge { position: absolute; top: -4px; right: -4px; background: #c62828; color: #fff; border-radius: 10px; min-width: 20px; height: 20px; font-size: 11px; font-weight: bold; display: flex; align-items: center; justify-content: center; padding: 0 5px; z-index: 1; }' + - '.sa-chat-panel { position: absolute; bottom: 68px; left: 0; width: 400px; max-height: 600px; background: #fff; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.18); display: flex; flex-direction: column; overflow: hidden; animation: sa-slide-up 0.25s ease-out; }' + + '.sa-chat-panel { position: absolute; bottom: 68px; left: 0; width: 400px; max-height: 600px; background: #fff; border-radius: 12px; box-shadow: 0 8px 32px rgba(0,0,0,0.18); display: flex; flex-direction: column; overflow: hidden; animation: sa-slide-up 0.25s ease-out; transition: width 0.3s ease, max-height 0.3s ease; }' + + '.sa-chat-panel.sa-expanded { width: 700px; max-height: 85vh; }' + + '.sa-chat-panel.sa-expanded .sa-chat-messages { max-height: calc(85vh - 180px); }' + + '.sa-chat-panel.sa-expanded .sa-history-list, .sa-chat-panel.sa-expanded .sa-memory-list { max-height: calc(85vh - 200px); }' + '@keyframes sa-slide-up { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } }' + '.sa-chat-header { display: flex; align-items: center; padding: 10px 16px; background: #5c6bc0; color: #fff; gap: 8px; }' + '.sa-chat-title { font-size: 15px; font-weight: 600; white-space: nowrap; }' + @@ -122,7 +128,7 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) '.sa-badge-source { background: #f3e5f5; color: #7b1fa2; }' + '.sa-memory-entry-content { font-size: 12px; color: #555; line-height: 1.4; max-height: 60px; overflow: hidden; }' + '.sa-memory-entry-meta { font-size: 10px; color: #999; margin-top: 4px; }' + - '@media (max-width: 480px) { .sa-chat-panel { width: calc(100vw - 48px); left: 0; } .smart-assistant-fab-container { bottom: 16px; left: 16px; } }' + + '@media (max-width: 480px) { .sa-chat-panel { width: calc(100vw - 48px); left: 0; } .sa-chat-panel.sa-expanded { width: calc(100vw - 48px); } .smart-assistant-fab-container { bottom: 16px; left: 16px; } }' + '', conversationId: null, @@ -131,12 +137,14 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) currentCaseId: null, currentCaseName: null, currentView: 'chat', + isExpanded: false, currentMemoryCategory: null, memoryData: null, events: { 'click .sa-fab': function () { this.togglePanel(); }, 'click .sa-close-btn': function () { this.closePanel(); }, + 'click .sa-expand-btn': function () { this.toggleExpand(); }, 'click .sa-chat-send': function () { this.sendMessage(); }, 'click .sa-history-btn': function () { this.showHistory(); }, 'click .sa-new-btn': function () { this.startNewConversation(); }, @@ -260,7 +268,26 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) closePanel: function () { this.isOpen = false; - this.$el.find('.sa-chat-panel').css('display', 'none'); + this.isExpanded = false; + var $panel = this.$el.find('.sa-chat-panel'); + $panel.removeClass('sa-expanded').css('display', 'none'); + this.$el.find('.sa-expand-btn .fas').removeClass('fa-compress-alt').addClass('fa-expand-alt'); + }, + + toggleExpand: function () { + this.isExpanded = !this.isExpanded; + var $panel = this.$el.find('.sa-chat-panel'); + var $icon = this.$el.find('.sa-expand-btn .fas'); + + if (this.isExpanded) { + $panel.addClass('sa-expanded'); + $icon.removeClass('fa-expand-alt').addClass('fa-compress-alt'); + } else { + $panel.removeClass('sa-expanded'); + $icon.removeClass('fa-compress-alt').addClass('fa-expand-alt'); + } + + this.scrollToBottom(); }, showChat: function () { @@ -741,7 +768,7 @@ define('modules/smart-assistant/views/floating-chat', ['view'], function (View) recordView.model.trigger('update-all'); } - if (entityType === 'Task' || entityType === 'Meeting') { + if (entityType === 'Task' || entityType === 'Meeting' || entityType === 'Call') { var sideView = currentView.getView('side'); if (sideView) { diff --git a/files/custom/Espo/Modules/SmartAssistant/Services/ActionExecutor.php b/files/custom/Espo/Modules/SmartAssistant/Services/ActionExecutor.php index f80a0a8..fd1034e 100644 --- a/files/custom/Espo/Modules/SmartAssistant/Services/ActionExecutor.php +++ b/files/custom/Espo/Modules/SmartAssistant/Services/ActionExecutor.php @@ -42,6 +42,9 @@ class ActionExecutor 'change_status' => $this->changeStatus($params, $caseId), 'create_meeting' => $this->createMeeting($params, $caseId, $userId), 'create_call' => $this->createCall($params, $caseId, $userId), + 'delete_meeting' => $this->deleteMeeting($params), + 'delete_call' => $this->deleteCall($params), + 'delete_note' => $this->deleteNote($params), 'schedule_hearing' => $this->scheduleHearing($params, $caseId, $userId), 'list_documents' => $this->listDocuments($caseId), 'analyze_document' => $this->analyzeDocument($params, $caseId), @@ -217,6 +220,74 @@ class ActionExecutor return ['success' => true, 'message' => "✅ שיחה \"{$params['name']}\" תועדה בהצלחה", 'entityType' => 'Call', 'entityId' => $call->get('id')]; } + private function deleteMeeting(array $params): array + { + $entityId = $params['entityId'] ?? null; + if (!$entityId) { + throw new Error('entityId parameter is required.'); + } + + $entity = $this->entityManager->getEntityById('Meeting', $entityId); + if (!$entity) { + throw new NotFound("Meeting {$entityId} not found."); + } + + $name = $entity->get('name') ?? ''; + $this->entityManager->removeEntity($entity); + + return [ + 'success' => true, + 'message' => "✅ פגישה \"{$name}\" נמחקה בהצלחה", + 'entityType' => 'Meeting', + 'entityId' => $entityId, + ]; + } + + private function deleteCall(array $params): array + { + $entityId = $params['entityId'] ?? null; + if (!$entityId) { + throw new Error('entityId parameter is required.'); + } + + $entity = $this->entityManager->getEntityById('Call', $entityId); + if (!$entity) { + throw new NotFound("Call {$entityId} not found."); + } + + $name = $entity->get('name') ?? ''; + $this->entityManager->removeEntity($entity); + + return [ + 'success' => true, + 'message' => "✅ שיחה \"{$name}\" נמחקה בהצלחה", + 'entityType' => 'Call', + 'entityId' => $entityId, + ]; + } + + private function deleteNote(array $params): array + { + $entityId = $params['entityId'] ?? null; + if (!$entityId) { + throw new Error('entityId parameter is required.'); + } + + $entity = $this->entityManager->getEntityById('Note', $entityId); + if (!$entity) { + throw new NotFound("Note {$entityId} not found."); + } + + $this->entityManager->removeEntity($entity); + + return [ + 'success' => true, + 'message' => '✅ הערה נמחקה בהצלחה', + 'entityType' => 'Note', + 'entityId' => $entityId, + ]; + } + private function scheduleHearing(array $params, ?string $caseId, string $userId): array { $case = $this->entityManager->getEntityById('Case', $caseId); diff --git a/manifest.json b/manifest.json index cb087b0..58f1c3f 100644 --- a/manifest.json +++ b/manifest.json @@ -3,7 +3,7 @@ "module": "SmartAssistant", "description": "Unified AI Assistant for Legal CRM — floating chat with case memory, office alerts, and AI Gateway integration", "author": "klear", - "version": "2.4.0", + "version": "2.5.0", "acceptableVersions": [ ">=8.0.0" ],