This commit is contained in:
Oliver
2025-10-06 16:59:23 -03:00
parent ff60112ddf
commit 018e60896c
6 changed files with 571 additions and 0 deletions

View File

@@ -0,0 +1,214 @@
/* ================= Chat Toggle Button ================= */
#cw-chatToggle {
position: fixed;
bottom: 24px;
right: 24px;
width: 100px;
height: 50px;
border: none;
border-radius: 25px;
padding: 0;
background: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
z-index: 100000;
box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px,
rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
transition: transform 0.3s ease;
}
#cw-chatToggle:hover {
transform: translateY(-5px);
}
#cw-chatToggle img {
width: 80%;
height: 80%;
object-fit: contain;
display: block;
user-select: none;
}
/* ================= Chat Widget ================= */
#cw-chatWidget {
display: none;
position: fixed;
bottom: 100px;
right: 24px;
width: 500px;
max-height: 70vh;
background: white;
border: 1px solid #ccc;
border-radius: 12px;
flex-direction: column;
z-index: 100000;
font-family: system-ui, sans-serif;
overflow: hidden;
}
#cw-chatWidget.active {
display: flex;
}
#cw-chatWidget .cw-header {
display: flex;
justify-content: center;
padding: 16px 0 10px 0;
background: #f8f9f9;
}
#cw-chatWidget .cw-header img {
width: 80%;
height: auto;
object-fit: contain;
user-select: none;
}
/* Status Bar */
#cw-status {
padding: 10px;
background-color: #f0f0f0;
border-bottom: 1px solid #ddd;
max-height: 0;
transition: max-height 0.5s ease, padding 0.5s ease;
}
/* Messages */
#cw-chatMessages {
flex: 1;
overflow-y: auto;
padding: 16px;
font-size: 0.875rem;
line-height: 1.4;
background: #fafafa;
scroll-behavior: smooth;
}
/* Form */
#cw-chatForm {
display: flex;
border-top: 1px solid #ddd;
}
#cw-chatInput {
flex: 1;
border: none;
padding: 8px 20px;
font-size: 1rem;
border-radius: 0 0 0 12px;
outline: none;
}
#cw-chatForm button {
background-color: #0070c0;
border: none;
color: white;
padding: 0 16px;
cursor: pointer;
font-weight: 600;
border-radius: 0 0 12px 0;
transition: background-color 0.3s ease;
}
#cw-chatForm button:hover {
background-color: #005a9e;
}
/* Messages Bubbles */
.cw-message {
max-width: 75%;
margin-bottom: 8px;
padding: 8px 12px;
border-radius: 12px;
word-wrap: break-word;
white-space: pre-wrap;
}
.cw-message.user {
background-color: #DCF8C6;
color: #333;
margin-left: auto;
text-align: right;
}
.cw-message.bot {
background-color: #E0E0E0;
color: #333;
margin-right: auto;
text-align: left;
}
/* ================= Wizard ================= */
.wizard-headline {
text-align: center;
font-size: 24px;
font-weight: bold;
padding: 20px 0;
background-color: #f8f9f9;
color: #2c3e50;
border-bottom: 2px solid #ddd;
}
.wizard {
display: flex;
justify-content: space-between;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
background-color: #e0e0e0;
}
.wizard li {
flex: 1;
display: flex;
flex-direction: column;
border-right: 2px solid #fff;
color: white;
box-sizing: border-box;
}
.wizard li:last-child {
border-right: none;
}
.wizard .header {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
padding: 10px;
font-weight: bold;
font-size: 16px;
text-align: center;
}
.wizard .text {
padding: 20px 10px;
text-align: center;
font-size: 14px;
flex-grow: 1;
}
/* Wizard state colors */
.wizard li.open {
background-color: #7f8c8d;
}
.wizard li.open .header {
background-color: #5d6d7e;
}
.wizard li.done {
background-color: #1e8449;
}
.wizard li.done .header {
background-color: #145a32;
}
.wizard i {
font-size: 18px;
}

View File

@@ -0,0 +1,127 @@
// ================= CONFIG =================
const baseUrl = 'http://localhost:8000'; // Base URL for all resources
const config = {
cssUrl: `${baseUrl}/agent.css`, // CSS file
api: `https://002-001-5dd6e535-4d1c-46bc-9bd9-42ad4bc5f082.odoo4projects.com/webhook/702862fd-dd17-4a34-8efb-e9056d2c50df/chat`, // Backend webhook endpoint
buttonImage: `${baseUrl}/images/4.svg`, // Chat toggle button image
logoImage: `${baseUrl}/images/logo.svg`, // Logo image for chat widget
preamble: 'Hallo! Wie kann ich Ihnen helfen?' // Initial bot message
};
// ================= WIDGET HTML =================
const widgetHTML = `
<div id="cw-chatWidget">
<div class="cw-header">
<img src="${config.logoImage}" alt="Logo" class="cw-logo"/>
</div>
<div id="cw-chatMessages" class="cw-messages"></div>
<form id="cw-chatForm" class="cw-form">
<input type="text" id="cw-chatInput" placeholder="Type your message..." />
<button type="submit">Send</button>
</form>
<div id="cw-status" class="cw-status"></div>
</div>
<button id="cw-chatToggle">
<img src="${config.buttonImage}" alt="Chat"/>
</button>
`;
// ================= UTILS =================
function loadCSS(url) {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
document.head.appendChild(link);
}
function appendMessage(chatMessages, text, sender) {
const msg = document.createElement('div');
msg.classList.add('cw-message', sender === 'user' ? 'user' : 'bot');
msg.innerHTML = text;
chatMessages.appendChild(msg);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
// ================= MAIN =================
document.addEventListener('DOMContentLoaded', () => {
try {
// Load CSS
loadCSS(config.cssUrl);
// Inject chat widget HTML
document.body.insertAdjacentHTML('beforeend', widgetHTML);
document.dispatchEvent(new CustomEvent('JSsucks'));
// ================= DOM REFERENCES =================
const chatToggle = document.getElementById('cw-chatToggle');
const chatWidget = document.getElementById('cw-chatWidget');
const chatForm = document.getElementById('cw-chatForm');
const chatInput = document.getElementById('cw-chatInput');
const chatMessages = document.getElementById('cw-chatMessages');
const statusDiv = document.getElementById('cw-status');
const chatid = crypto.randomUUID();
let chatOpened = false;
// ================= BOT COMMUNICATION =================
async function sendMessageToBot(messageText) {
chatWidget.classList.add('active');
appendMessage(chatMessages, messageText, 'user');
chatInput.value = '';
chatInput.focus();
try {
const res = await fetch(config.api, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
action: 'sendMessage',
chatid,
chatInput: messageText
})
});
const data = await res.json();
if (data.status) {
statusDiv.innerHTML = data.status;
requestAnimationFrame(() => {
statusDiv.style.maxHeight = statusDiv.scrollHeight + 'px';
statusDiv.style.padding = '10px';
});
} else {
statusDiv.style.maxHeight = '0';
statusDiv.style.padding = '0 10px';
}
appendMessage(chatMessages, data.output, 'bot');
} catch (error) {
appendMessage(chatMessages, 'Fehler beim Verbinden mit dem Server. Bitte versuchen Sie es später erneut.', 'bot');
console.error(error);
}
}
window.sendMessageToBot = sendMessageToBot;
// ================= EVENT LISTENERS =================
chatToggle.addEventListener('click', () => {
const isVisible = chatWidget.classList.contains('active');
chatWidget.classList.toggle('active', !isVisible);
if (!isVisible && !chatOpened) {
appendMessage(chatMessages, config.preamble, 'bot');
chatOpened = true;
}
});
chatForm.addEventListener('submit', (e) => {
e.preventDefault();
const input = chatInput.value.trim();
if (input) sendMessageToBot(input);
});
} catch (err) {
console.error('Failed to initialize chat widget:', err);
}
});

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="26.458334mm"
height="26.458334mm"
viewBox="0 0 26.458334 26.458334"
version="1.1"
id="svg351"
inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
sodipodi:docname="4.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview353"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="false"
inkscape:zoom="2"
inkscape:cx="141.75"
inkscape:cy="-67.25"
inkscape:window-width="1920"
inkscape:window-height="1127"
inkscape:window-x="1920"
inkscape:window-y="37"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs348" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-27.042028,-166.7327)">
<g
id="g22"
transform="matrix(0.15346171,0,0,0.15347061,-71.664544,106.29597)">
<polygon
class="st1"
points="713.07,486.53 750.82,441.47 742.83,486.53 "
id="polygon14"
style="fill:#ed703e" />
<polygon
class="st1"
points="752.1,393.8 669.3,488.25 663.26,523.19 733.12,523.19 725.6,566.2 643.2,566.2 643.2,393.8 "
id="polygon16"
style="fill:#ed703e" />
<polygon
class="st1"
points="798.47,393.8 815.61,393.8 815.61,486.53 782.29,486.53 "
id="polygon18"
style="fill:#ed703e" />
<polygon
class="st1"
points="767.94,566.2 775.83,523.19 815.61,523.19 815.61,566.2 "
id="polygon20"
style="fill:#ed703e" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 27.3.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 671.21002 172.39999"
xml:space="preserve"
sodipodi:docname="logo-01.svg"
width="671.21002"
height="172.39999"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs47" /><sodipodi:namedview
id="namedview45"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
showgrid="false"
inkscape:zoom="0.86041667"
inkscape:cx="335.30266"
inkscape:cy="86.004843"
inkscape:window-width="1920"
inkscape:window-height="1007"
inkscape:window-x="0"
inkscape:window-y="37"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style2">
.st0{fill:#68696D;}
.st1{fill:#ED703E;}
</style>
<g
id="g42"
transform="translate(-144.4,-393.8)">
<g
id="g8">
<path
class="st0"
d="m 427.65,509.26 c -9.27,-5.19 -16.61,-12.39 -22.02,-21.6 -5.42,-9.21 -8.12,-19.62 -8.12,-31.23 0,-11.61 2.71,-22.02 8.12,-31.23 5.41,-9.21 12.75,-16.38 22.02,-21.52 9.26,-5.13 19.42,-7.7 30.47,-7.7 11.16,0 21.35,2.57 30.56,7.7 9.21,5.14 16.49,12.31 21.85,21.52 5.36,9.21 8.04,19.62 8.04,31.23 0,11.61 -2.68,22.02 -8.04,31.23 -5.36,9.21 -12.67,16.41 -21.93,21.6 -9.27,5.19 -19.42,7.79 -30.47,7.79 -11.06,-0.01 -21.22,-2.6 -30.48,-7.79 z m 50.31,-30.9 c 4.86,-5.47 7.28,-12.78 7.28,-21.93 0,-9.38 -2.43,-16.77 -7.28,-22.19 -4.86,-5.41 -11.47,-8.12 -19.84,-8.12 -8.48,0 -15.13,2.71 -19.93,8.12 -4.8,5.42 -7.2,12.81 -7.2,22.19 0,9.27 2.4,16.61 7.2,22.02 4.8,5.42 11.44,8.12 19.93,8.12 8.37,0 14.99,-2.74 19.84,-8.21 z"
id="path4" />
<path
class="st0"
d="m 528.4,509.26 c -9.27,-5.19 -16.61,-12.39 -22.02,-21.6 -5.42,-9.21 -8.12,-19.62 -8.12,-31.23 0,-11.61 2.71,-22.02 8.12,-31.23 5.41,-9.21 12.75,-16.38 22.02,-21.52 9.26,-5.13 19.42,-7.7 30.47,-7.7 11.16,0 21.35,2.57 30.56,7.7 9.21,5.14 16.49,12.31 21.85,21.52 5.36,9.21 8.04,19.62 8.04,31.23 0,11.61 -2.68,22.02 -8.04,31.23 -5.36,9.21 -12.67,16.41 -21.93,21.6 -9.27,5.19 -19.42,7.79 -30.47,7.79 -11.05,-0.01 -21.21,-2.6 -30.48,-7.79 z m 50.32,-30.9 c 4.86,-5.47 7.28,-12.78 7.28,-21.93 0,-9.38 -2.43,-16.77 -7.28,-22.19 -4.86,-5.41 -11.47,-8.12 -19.84,-8.12 -8.48,0 -15.13,2.71 -19.93,8.12 -4.8,5.42 -7.2,12.81 -7.2,22.19 0,9.27 2.4,16.61 7.2,22.02 4.8,5.42 11.44,8.12 19.93,8.12 8.37,0 14.98,-2.74 19.84,-8.21 z"
id="path6" />
</g>
<path
class="st0"
d="M 260.51,423.82 C 255,414.35 247.52,407 238.07,401.72 c -9.47,-5.28 -19.93,-7.92 -31.39,-7.92 -11.35,0 -21.79,2.64 -31.32,7.92 -9.52,5.28 -17.05,12.64 -22.62,22.1 -5.57,9.47 -8.34,20.16 -8.34,32.08 0,11.94 2.77,22.63 8.34,32.08 5.56,9.47 13.09,16.86 22.62,22.19 9.52,5.33 19.96,8 31.32,8 11.35,0 21.78,-2.67 31.3,-8 9.52,-5.33 17.03,-12.73 22.54,-22.19 5.51,-9.45 8.26,-20.14 8.26,-32.08 -0.01,-11.92 -2.77,-22.61 -8.27,-32.08 z m -33.46,54.62 c -4.99,5.62 -11.79,8.44 -20.38,8.44 -8.72,0 -15.54,-2.78 -20.48,-8.34 -4.93,-5.56 -7.39,-13.11 -7.39,-22.63 0,-9.63 2.46,-17.23 7.39,-22.79 4.93,-5.56 11.75,-8.34 20.48,-8.34 8.6,0 15.39,2.78 20.38,8.34 4.99,5.56 7.47,13.16 7.47,22.79 0.01,9.4 -2.48,16.91 -7.47,22.53 z"
id="path10" />
<path
class="st0"
d="m 381.04,424.95 c -5.15,-9.18 -12.52,-16.32 -22.1,-21.41 -9.58,-5.1 -20.73,-7.66 -33.46,-7.66 h -48 v 121.28 h 48 c 12.61,0 23.7,-2.61 33.28,-7.83 9.58,-5.22 16.97,-12.41 22.19,-21.59 5.22,-9.18 7.83,-19.62 7.83,-31.31 0.01,-11.82 -2.58,-22.31 -7.74,-31.48 z m -34.92,54.35 c -5.62,5.39 -13.36,8.09 -23.22,8.09 h -11.7 v -62.27 h 11.7 c 9.87,0 17.6,2.72 23.22,8.17 5.62,5.45 8.44,13.16 8.44,23.13 -0.01,9.87 -2.82,17.49 -8.44,22.88 z"
id="path12" />
<g
id="g22">
<polygon
class="st1"
points="742.83,486.53 713.07,486.53 750.82,441.47 "
id="polygon14" />
<polygon
class="st1"
points="669.3,488.25 663.26,523.19 733.12,523.19 725.6,566.2 643.2,566.2 643.2,393.8 752.1,393.8 "
id="polygon16" />
<polygon
class="st1"
points="782.29,486.53 798.47,393.8 815.61,393.8 815.61,486.53 "
id="polygon18" />
<polygon
class="st1"
points="815.61,566.2 767.94,566.2 775.83,523.19 815.61,523.19 "
id="polygon20" />
</g>
<g
id="g40">
<path
class="st0"
d="m 162.99,549.74 c -1.81,1.75 -4.58,2.63 -8.3,2.63 h -6.13 v 13.31 H 144.4 V 533.8 h 10.29 c 3.6,0 6.34,0.87 8.21,2.61 1.87,1.74 2.81,3.98 2.81,6.72 0,2.65 -0.91,4.85 -2.72,6.61 z m -3.18,-2.31 c 1.1,-1.01 1.65,-2.44 1.65,-4.3 0,-3.93 -2.26,-5.9 -6.77,-5.9 h -6.13 v 11.71 h 6.13 c 2.31,0 4.02,-0.51 5.12,-1.51 z"
id="path24" />
<path
class="st0"
d="m 224.26,565.68 -7.59,-13.04 h -5.03 v 13.04 h -4.16 V 533.8 h 10.29 c 2.41,0 4.44,0.41 6.11,1.23 1.66,0.82 2.9,1.94 3.73,3.34 0.82,1.4 1.23,3 1.23,4.8 0,2.2 -0.63,4.13 -1.9,5.81 -1.27,1.68 -3.16,2.79 -5.7,3.34 l 8.01,13.36 z M 211.64,549.3 h 6.13 c 2.26,0 3.95,-0.56 5.08,-1.67 1.13,-1.11 1.69,-2.6 1.69,-4.46 0,-1.89 -0.56,-3.35 -1.67,-4.39 -1.11,-1.04 -2.81,-1.56 -5.1,-1.56 h -6.13 z"
id="path26" />
<path
class="st0"
d="m 278.24,563.92 c -2.44,-1.39 -4.37,-3.32 -5.79,-5.81 -1.42,-2.49 -2.13,-5.28 -2.13,-8.39 0,-3.11 0.71,-5.91 2.13,-8.39 1.42,-2.49 3.35,-4.42 5.79,-5.81 2.44,-1.39 5.14,-2.08 8.1,-2.08 2.99,0 5.7,0.69 8.14,2.08 2.44,1.39 4.36,3.32 5.76,5.79 1.4,2.47 2.1,5.28 2.1,8.42 0,3.14 -0.7,5.95 -2.1,8.42 -1.4,2.47 -3.32,4.4 -5.76,5.79 -2.44,1.39 -5.15,2.08 -8.14,2.08 -2.96,-0.02 -5.66,-0.71 -8.1,-2.1 z m 14.12,-3.09 c 1.78,-1.04 3.19,-2.52 4.21,-4.44 1.02,-1.92 1.53,-4.15 1.53,-6.68 0,-2.56 -0.51,-4.8 -1.53,-6.7 -1.02,-1.91 -2.42,-3.38 -4.19,-4.41 -1.77,-1.04 -3.78,-1.56 -6.04,-1.56 -2.26,0 -4.27,0.52 -6.04,1.56 -1.77,1.04 -3.16,2.51 -4.19,4.41 -1.02,1.91 -1.53,4.14 -1.53,6.7 0,2.53 0.51,4.76 1.53,6.68 1.02,1.92 2.42,3.4 4.21,4.44 1.78,1.04 3.79,1.56 6.02,1.56 2.23,-0.01 4.23,-0.52 6.02,-1.56 z"
id="path28" />
<path
class="st0"
d="m 360.5,533.79 v 23.56 c 0,2.62 -0.81,4.72 -2.42,6.29 -1.62,1.57 -3.75,2.36 -6.4,2.36 -2.68,0 -4.83,-0.8 -6.45,-2.4 -1.62,-1.6 -2.42,-3.79 -2.42,-6.56 h 4.16 c 0.03,1.56 0.43,2.82 1.21,3.8 0.78,0.98 1.94,1.46 3.5,1.46 1.56,0 2.71,-0.46 3.48,-1.39 0.76,-0.93 1.14,-2.11 1.14,-3.55 V 533.8 h 4.2 z"
id="path30" />
<path
class="st0"
d="m 409.44,537.18 v 10.66 h 11.62 v 3.43 h -11.62 v 10.98 h 12.99 v 3.43 h -17.15 v -31.93 h 17.15 v 3.43 z"
id="path32" />
<path
class="st0"
d="m 465.89,541.32 c 1.4,-2.49 3.32,-4.43 5.74,-5.83 2.42,-1.4 5.12,-2.1 8.07,-2.1 3.48,0 6.51,0.84 9.1,2.52 2.59,1.68 4.48,4.06 5.67,7.14 h -4.99 c -0.89,-1.92 -2.16,-3.4 -3.82,-4.44 -1.66,-1.04 -3.65,-1.56 -5.97,-1.56 -2.23,0 -4.22,0.52 -5.99,1.56 -1.77,1.04 -3.16,2.51 -4.16,4.41 -1.01,1.91 -1.51,4.14 -1.51,6.7 0,2.53 0.5,4.75 1.51,6.66 1.01,1.91 2.39,3.38 4.16,4.41 1.77,1.04 3.77,1.56 5.99,1.56 2.32,0 4.31,-0.51 5.97,-1.53 1.66,-1.02 2.93,-2.49 3.82,-4.41 h 4.99 c -1.19,3.05 -3.08,5.41 -5.67,7.07 -2.59,1.66 -5.63,2.49 -9.1,2.49 -2.96,0 -5.65,-0.69 -8.07,-2.08 -2.42,-1.39 -4.34,-3.32 -5.74,-5.79 -1.4,-2.47 -2.1,-5.26 -2.1,-8.37 0,-3.11 0.7,-5.92 2.1,-8.41 z"
id="path34" />
<path
class="st0"
d="m 556.88,533.79 v 3.38 h -8.69 v 28.5 h -4.16 v -28.5 h -8.74 v -3.38 z"
id="path36" />
<path
class="st0"
d="m 603.06,564.88 c -1.66,-0.75 -2.97,-1.78 -3.91,-3.11 -0.95,-1.33 -1.43,-2.86 -1.46,-4.6 h 4.44 c 0.15,1.49 0.77,2.75 1.85,3.77 1.08,1.02 2.66,1.53 4.73,1.53 1.98,0 3.55,-0.49 4.69,-1.49 1.14,-0.99 1.72,-2.26 1.72,-3.82 0,-1.22 -0.34,-2.21 -1.01,-2.97 -0.67,-0.76 -1.51,-1.34 -2.52,-1.74 -1.01,-0.4 -2.36,-0.82 -4.07,-1.28 -2.1,-0.55 -3.79,-1.1 -5.06,-1.65 -1.27,-0.55 -2.35,-1.41 -3.25,-2.59 -0.9,-1.17 -1.35,-2.75 -1.35,-4.73 0,-1.74 0.44,-3.28 1.33,-4.62 0.88,-1.34 2.13,-2.38 3.73,-3.11 1.6,-0.73 3.44,-1.1 5.51,-1.1 2.99,0 5.44,0.75 7.34,2.24 1.91,1.5 2.98,3.48 3.22,5.95 h -4.57 c -0.15,-1.22 -0.79,-2.29 -1.92,-3.23 -1.13,-0.93 -2.62,-1.39 -4.48,-1.39 -1.74,0 -3.16,0.45 -4.25,1.35 -1.1,0.9 -1.65,2.16 -1.65,3.77 0,1.16 0.33,2.11 0.98,2.84 0.66,0.73 1.46,1.29 2.42,1.67 0.96,0.38 2.31,0.82 4.05,1.3 2.1,0.58 3.8,1.15 5.08,1.72 1.28,0.57 2.38,1.43 3.29,2.61 0.91,1.17 1.37,2.77 1.37,4.78 0,1.56 -0.41,3.02 -1.24,4.39 -0.83,1.37 -2.04,2.49 -3.66,3.34 -1.62,0.85 -3.52,1.28 -5.72,1.28 -2.08,0.01 -3.97,-0.36 -5.63,-1.11 z"
id="path38" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OD8N - Odoo & n8n Automation Experts</title>
<script type="module" src="agent.js"></script>
</head>
<body>
</body>
</html>

View File

@@ -0,0 +1,20 @@
#!/usr/bin/env python3
from flask import Flask, send_from_directory
import os
app = Flask(__name__)
directory = os.getcwd() # serve current directory
@app.route("/", defaults={"path": "index.html"})
@app.route("/<path:path>")
def serve_file(path):
# If file exists, serve it
if os.path.isfile(os.path.join(directory, path)):
return send_from_directory(directory, path)
else:
return f"File not found: {path}", 404
if __name__ == "__main__":
# debug=True enables auto-reload when this file changes
app.run(host="0.0.0.0", port=8000, debug=True)