Browse Source

Att: chatbot painel primeiro commit

chatbot
Felipe Fontana 5 months ago
parent
commit
7f4af6f8f3
  1. 23
      app/Http/Controllers/Admin/ChatBotController.php
  2. 713
      resources/views/admin/cadastros/chatBots.blade.php
  3. 7
      resources/views/layouts/menu.blade.php
  4. 2
      routes/web.php

23
app/Http/Controllers/Admin/ChatBotController.php

@ -0,0 +1,23 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Agentes;
use App\Models\Grupos;
use App\Models\PermissoesAgente;
use App\Models\Filas;
use App\Models\LicencaFixa;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Validator;
class ChatBotController extends Controller
{
public function index(Request $request)
{
return view('admin.cadastros.chatBots');
}
}

713
resources/views/admin/cadastros/chatBots.blade.php

@ -0,0 +1,713 @@
<x-app-layout>
<div class="py-8 px-8 flex-grow h-full flex">
<div class="pr-4 h-full" id="canvas-container" style="width: 80%;">
<div id="canvas" class="h-full"></div>
</div>
<div class="h-full" id="toolbar" style="width: 20%;">
<div class="p-4 h-full">
<div class="toolbar-item" onclick="addTextNode()">Text</div>
<div class="toolbar-item" onclick="addButtonNode()">Input Buttons</div>
<div class="toolbar-item" onclick="addInputNode()">Input Text</div>
<div class="flex flex-col gap-4">
<select name="variaveis[]" class="filas" id="variaveis" multiple="multiple"></select>
<div class="flex gap-2">
<input type="text" id="nova-variavel" placeholder="Nova variável">
<button onclick="adicionarVariavel()">Adicionar</button>
<button onclick="excluirVariavel()">Excluir</button>
</div>
</div>
</div>
</div>
</div>
<div id="properties-panel" style="display: none;">
<textarea id="text-property" rows="4" cols="50"></textarea>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.4.0/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/3.4.0/joint.min.js"></script>
<script>
var jsonBlocks = [];
var jsonVariaveisGlobais = [];
var variaveisGlobais = []; // Variável global para armazenar variáveis
// Função para adicionar nova variável ao select
function adicionarVariavel() {
var novaVariavel = document.getElementById('nova-variavel').value.trim();
if (novaVariavel !== '' && !Object.values(variaveisGlobais).includes(novaVariavel)) {
var uniqueId = 'var_' + Date.now(); // Gerar um unique ID
variaveisGlobais[uniqueId] = novaVariavel;
atualizarSelectVariaveis();
}
}
// Função para excluir variável selecionada do select
function excluirVariavel() {
var selectVariaveis = document.getElementById('variaveis');
var opcoesSelecionadas = Array.from(selectVariaveis.selectedOptions);
opcoesSelecionadas.forEach(function(opcao) {
var uniqueId = opcao.value;
delete variaveisGlobais[uniqueId];
});
atualizarSelectVariaveis();
}
// Função para atualizar as opções do select com as variáveis globais
function atualizarSelectVariaveis() {
var selectVariaveis = document.getElementById('variaveis');
selectVariaveis.innerHTML = '';
Object.entries(variaveisGlobais).forEach(function([uniqueId, nomeVariavel]) {
var option = document.createElement('option');
option.value = uniqueId;
option.text = nomeVariavel;
selectVariaveis.appendChild(option);
});
atualizarVariaveisJSON();
}
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#canvas'),
model: graph,
width: '100%',
height: '100%',
gridSize: 1,
defaultLink: () => new joint.shapes.standard.Link(),
linkPinning: false
});
var selectedNode = null;
paper.on('cell:pointerdblclick', function(cellView) {
if (!selectedNode) {
selectedNode = cellView.model;
}
$(document).keydown(function(event) {
if (event.key === "Delete" && selectedNode !== null) {
selectedNode.remove();
selectedNode = null;
$('#properties-panel').hide();
}
});
});
function addInputNode() {
var portsIn = {
position: {
name: 'left'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#023047',
stroke: '#023047'
}
},
label: {
position: {
name: 'left',
args: { y: 6 }
},
markup: [{
tagName: 'text',
selector: 'label',
className: 'label-text'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
var portsOut = {
position: {
name: 'right'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#E6A502',
stroke:'#023047'
}
},
label: {
position: {
name: 'right',
args: { y: 6 }
},
markup: [{
tagName: 'text',
selector: 'label',
className: 'label-text'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
var rect = new joint.shapes.standard.Rectangle({
position: { x: 275, y: 50 },
size: { width: 150, height: 50 },
attrs: {
body: {
fill: '#f3f4f6',
},
label: {
text: 'Input',
fontSize: 16,
}
},
ports: {
groups: {
'in': portsIn,
'out': portsOut
}
}
});
rect.addPorts([
{
group: 'in'
},
{
group: 'out'
}
]);
rect.position(50, 50);
// Adicionar um ID exclusivo para o nó de texto
rect.attr('id', rect.id);
rect.attr('properties/text', '');
rect.attr('properties/store-variable', 'false');
rect.attr('properties/selected-variable', '');
graph.addCell(rect);
// Adicione o bloco com uniqueId ao JSON
jsonBlocks.push({
title: rect.id,
blocks: [{
id: rect.id, // Use o ID correto aqui
type: 'text input',
options: {
labels : {
placeholder : ''
}
},
outgoingId: ''
}],
graphCoordinates: {
x: rect.position().x,
y: rect.position().y
}
});
}
function addButtonNode() {
var portsIn = {
position: {
name: 'left'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#023047',
stroke: '#023047'
}
},
label: {
position: {
name: 'left',
args: { y: 6 }
},
markup: [{
tagName: 'text',
selector: 'label',
className: 'label-text'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
var rect = new joint.shapes.standard.Rectangle({
position: { x: 275, y: 50 },
size: { width: 150, height: 90 },
attrs: {
body: {
fill: '#f3f4f6',
},
label: {
text: 'Botões',
fontSize: 16,
}
},
ports: {
groups: {
'in': portsIn,
'out': { // Define as portas de saída na posição 'right'
position: {
name: 'right'
}
}
}
}
});
rect.addPorts([
{
group: 'in'
}
]);
rect.position(50, 50);
rect.attr('id', rect.id);
rect.attr('properties/text', '');
rect.attr('properties/store-variable', 'false');
rect.attr('properties/selected-variable', '');
graph.addCell(rect);
// Define um novo botão de adição
joint.elementTools.AddButton = joint.elementTools.Button.extend({
name: 'add-button',
options: {
markup: [{
tagName: 'circle',
selector: 'button',
attributes: {
'r': 7,
'fill': '#FF0000',
'cursor': 'pointer'
}
}, {
tagName: 'path',
selector: 'icon',
attributes: {
'd': 'M -3 0 3 0 M 0 -3 0 3',
'fill': 'none',
'stroke': '#FFFFFF',
'stroke-width': 2,
'pointer-events': 'none'
}
}],
x: '100%',
y: '100%',
offset: {
x: -25,
y: -10
},
rotate: true,
action: function(evt) {
// Adiciona uma porta de saída ao nó
var label = prompt('Digite um rótulo para a porta:', '');
if (label !== null) {
var portsOut = {
group : 'out',
position: {
name: 'right'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#E6A502',
stroke:'#023047'
},
label: {
text: label
}
},
label: {
position: {
name: 'outside',
args: { } // Extra arguments for the label layout function, see `layout.PortLabel` section
},
markup: [{
tagName: 'text',
selector: 'label'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
rect.addPort(portsOut);
}
}
}
});
var addButton = new joint.elementTools.AddButton();
var toolsView = new joint.dia.ToolsView({
tools: [addButton]
});
var elementView = rect.findView(paper);
elementView.addTools(toolsView);
jsonBlocks.push({
title: rect.id,
blocks: [{
id: rect.id,
type: 'choice input',
body: '',
items: [],
options: ''
}],
graphCoordinates: {
x: rect.position().x,
y: rect.position().y
}
});
}
function addTextNode() {
var portsIn = {
position: {
name: 'left'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#023047',
stroke: '#023047'
}
},
label: {
position: {
name: 'left',
args: { y: 6 }
},
markup: [{
tagName: 'text',
selector: 'label',
className: 'label-text'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
var portsOut = {
position: {
name: 'right'
},
attrs: {
portBody: {
magnet: true,
r: 10,
fill: '#E6A502',
stroke:'#023047'
}
},
label: {
position: {
name: 'right',
args: { y: 6 }
},
markup: [{
tagName: 'text',
selector: 'label',
className: 'label-text'
}]
},
markup: [{
tagName: 'circle',
selector: 'portBody'
}]
};
var rect = new joint.shapes.standard.Rectangle({
position: { x: 275, y: 50 },
size: { width: 150, height: 50 },
attrs: {
body: {
fill: '#f3f4f6',
},
label: {
text: 'Texto',
fontSize: 16,
}
},
ports: {
groups: {
'in': portsIn,
'out': portsOut
}
}
});
rect.addPorts([
{
group: 'in'
},
{
group: 'out'
}
]);
rect.position(50, 50);
// Adicionar um ID exclusivo para o nó de texto
rect.attr('id', rect.id);
rect.attr('properties/text', '');
graph.addCell(rect);
// Adicione o bloco com uniqueId ao JSON
jsonBlocks.push({
title: rect.id,
blocks: [{
id: rect.id, // Use o ID correto aqui
type: 'text',
content: '',
outgoingId: ''
}],
graphCoordinates: {
x: rect.position().x,
y: rect.position().y
}
});
}
// Add link tools
var removeButton = new joint.linkTools.Remove();
var toolsView = new joint.dia.ToolsView({
tools: [
removeButton
]
});
paper.on('cell:pointerclick', function(cellView) {
if (cellView.model.isLink()) {
var linkView = paper.findViewByModel(cellView.model);
linkView.addTools(toolsView);
}
});
paper.on('cell:pointerdblclick', function(cellView) {
if (cellView.model.isElement()) {
// Remover o destaque de outros nós
paper.findViewsInArea(paper.clientToLocalRect({ x: 0, y: 0, width: paper.el.clientWidth, height: paper.el.clientHeight })).forEach(view => {
if (view !== cellView) {
view.unhighlight();
}
});
// Destacar o nó selecionado
cellView.highlight();
}
});
// Exibir tela de propriedades quando um nó é selecionado
paper.on('cell:pointerdblclick', function(cellView) {
var minhaDiv = document.getElementById('properties-panel');
var inputs = minhaDiv.querySelectorAll('input, textarea, label, br, checkbox, select, div');
inputs.forEach(function(input) {
if (input.tagName.toLowerCase() !== 'textarea') {
input.remove();
}
});
var cell = cellView.model;
if (cell.isElement()) {
var nodeId = cell.attr('id');
if (nodeId) {
var propertiesPanel = $('#properties-panel');
var textArea = $('#text-property');
textArea.val(cell.attr('properties/text'));
textArea.off('input').on('input', function() {
cell.attr('properties/text', $(this).val());
});
var labelText = cell.attributes.attrs.label['text'];
if (labelText === 'Botões' || labelText === 'Input') {
var portsInputs = '<br>';
var prefix = nodeId + '-';
portsInputs += `<label for="${prefix}store-variable">Armazenar em variável? </label>`;
portsInputs += `<input type="checkbox" id="${prefix}store-variable" name="${prefix}store-variable"><br><br>`;
portsInputs += `<div id="${prefix}select-container" style="display:none;">`;
portsInputs += `<label for="${prefix}select-variable">Escolha a variável:</label>`;
portsInputs += `<select id="${prefix}select-variable" name="${prefix}select-variable"></select><br><br>`;
portsInputs += '</div>';
$("#properties-panel").append(portsInputs);
$('#' + prefix + 'store-variable').on('change', function() {
var isChecked = $(this).is(':checked');
if (isChecked) {
$('#' + prefix + 'select-container').show();
} else {
$('#' + prefix + 'select-container').hide();
}
});
var selectOptions = Object.entries(variaveisGlobais).map(function([uniqueId, nomeVariavel]) {
return `<option value="${uniqueId}">${nomeVariavel}</option>`;
});
$('#' + prefix + 'select-variable').append(selectOptions);
propertiesPanel.on('change', '#' + prefix + 'store-variable', function() {
var isChecked = $(this).is(':checked');
cell.attr('properties/store-variable', isChecked);
});
propertiesPanel.on('change', '#' + prefix + 'select-variable', function() {
var selectedVariable = $(this).val();
cell.attr('properties/selected-variable', selectedVariable);
});
var storeVariable = cell.attr('properties/store-variable');
if (storeVariable === true || storeVariable === 'true') {
$('#' + prefix + 'store-variable').prop('checked', true).trigger('change');
var selectedVariable = cell.attr('properties/selected-variable');
$('#' + prefix + 'select-variable').val(selectedVariable);
}
if (labelText === 'Botões') {
var portsOut = cell.getPorts('out');
var portsInputs = '<br>';
var cont = 1;
if (portsOut.length > 0) {
portsOut.forEach(function(link) {
if (link.group == 'out') {
var portId = link.id;
var portLabel = link.attrs.label['text'];
portsInputs += `<label for="${portId}"> Botão ${cont}</label><br>`;
portsInputs += `<input type="text" id="${portId}" value="${portLabel || ''}"><br><br>`;
cont++;
}
});
}
$("#properties-panel").append(portsInputs);
// Salvar as alterações do rótulo da porta quando o usuário alterar o valor no campo de entrada
propertiesPanel.find('input').on('input', function() {
var portId = $(this).attr('id');
var newLabel = $(this).val();
var port = cell.getPort(portId);
if (port) {
cell.portProp(portId, 'attrs/label', { text: newLabel });
}
});
}
}
propertiesPanel.show();
} else {
$('#properties-panel').hide();
}
}
});
paper.on('blank:pointerdown', function() {
$('#properties-panel').hide();
// Remover o destaque de todos os nós quando clicar no espaço em branco
paper.findViewsInArea(paper.clientToLocalRect({ x: 0, y: 0, width: paper.el.clientWidth, height: paper.el.clientHeight })).forEach(view => {
view.unhighlight();
});
});
function updateJson() {
jsonBlocks.forEach(block => {
if (block.blocks[0].type == 'text') {
var cell = graph.getCell(block.blocks[0].id);
if (cell) {
block.blocks[0].content = cell.attr('properties/text');
var connectedLinks = graph.getConnectedLinks(cell, { outbound: true });
if (connectedLinks.length > 0) {
block.blocks[0].outgoingId = connectedLinks[0].get('target').id;
} else {
block.blocks[0].outgoingId = '';
}
}
} else if (block.blocks[0].type == 'choice input') {
var cell = graph.getCell(block.blocks[0].id);
if (cell) {
var ports = cell.getPorts('out');
block.blocks[0].items = [];
var connectedLinks = graph.getConnectedLinks(cell, { outbound: true });
if (connectedLinks.length > 0) {
connectedLinks.forEach(function(conexao) {
var port = cell.getPort(conexao.attributes.source.port);
if (port.group == 'out') {
block.blocks[0].items.push({
id: conexao.attributes.source.port,
content : port.attrs.label['text'],
outgoingId : conexao.attributes.target.id
});
}
});
}
if ((cell.attr('properties/store-variable') == true) && (cell.attr('properties/selected-variable') != '')) {
block.blocks[0].options = {variableId : cell.attr('properties/selected-variable')};
}
block.blocks[0].body = cell.attr('properties/text');
}
} else if (block.blocks[0].type == 'text input') {
var cell = graph.getCell(block.blocks[0].id);
if (cell) {
block.blocks[0].options = {labels : {placeholder : cell.attr('properties/text')}};
var connectedLinks = graph.getConnectedLinks(cell, { outbound: true });
if (connectedLinks.length > 0) {
block.blocks[0].outgoingId = connectedLinks[0].get('target').id;
} else {
block.blocks[0].outgoingId = '';
}
if ((cell.attr('properties/store-variable') == true) && (cell.attr('properties/selected-variable') != '')) {
block.blocks[0].options = {labels : {placeholder : cell.attr('properties/text')},variableId : cell.attr('properties/selected-variable')};
}
}
}
});
console.log(JSON.stringify(jsonBlocks)); // Exibir JSON atualizado no console
}
graph.on('add', updateJson);
graph.on('change', updateJson);
graph.on('remove', updateJson);
// Função para atualizar o JSON global de variáveis
function atualizarVariaveisJSON() {
// Mapear as variáveis globais para o formato desejado
var novoJSON = Object.entries(variaveisGlobais).map(function([uniqueId, nomeVariavel]) {
return { id: uniqueId, name: nomeVariavel };
});
// Atualizar o JSON global de variáveis
jsonVariaveisGlobais = novoJSON;
console.log(JSON.stringify(jsonVariaveisGlobais));
}
</script>
</x-app-layout>

7
resources/views/layouts/menu.blade.php

@ -149,6 +149,13 @@
</x-nav-link>
</li>
@endcan
<li>
<x-nav-link class="p-2 mt-3 ml-4 flex items-center flex-row rounded-md px-2 md:px-4 duration-300 cursor-pointer hover:bg-blue-600 text-white" :href="route('bots.index')" :active="request()->routeIs('bots')">
<i class="fas fa-headphones text-sm"></i>
<span class="text-[14px] ml-3 text-gray-300">Bots</span>
</x-nav-link>
</li>
</ul>
</div>
@endcan

2
routes/web.php

@ -27,6 +27,7 @@ use App\Http\Controllers\Admin\NumberChannelController;
use App\Http\Controllers\Admin\PesquisaSatisfacaoController;
use App\Http\Controllers\Admin\PesquisaSatisfacaoPerguntaController;
use App\Http\Controllers\Admin\QuickMessageController;
use App\Http\Controllers\Admin\ChatBotController;
use Illuminate\Support\Facades\Route;
Route::middleware(['auth', 'verified'])->group(function () {
@ -45,6 +46,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
'pesquisas.perguntas' => PesquisaSatisfacaoPerguntaController::class,
'quick_messages' => QuickMessageController::class,
'relatorio_conversas' => RelatorioQuantidadeConversas::class,
'bots' => ChatBotController::class,
]);
Route::delete('/templates/deletar/{id}', [TemplatesController::class, 'deletar'])->name('templatesDeletar');

Loading…
Cancel
Save