Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Office Procedure Expert System</title> | |
<style> | |
:root { | |
--primary: #1a3a6b; | |
--secondary: #3498db; | |
--accent: #f39c12; | |
--background: #f5f7fa; | |
--text: #2c3e50; | |
--light: #ecf0f1; | |
--success: #2ecc71; | |
--danger: #e74c3c; | |
--shadow-light: rgba(0, 0, 0, 0.08); | |
--shadow-medium: rgba(0, 0, 0, 0.12); | |
--border-radius-small: 4px; | |
--border-radius-medium: 8px; | |
--border-radius-large: 1rem; | |
--border-radius-round: 50%; | |
--transition-speed: 0.3s; | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; | |
} | |
body { | |
background-color: var(--background); | |
color: var(--text); | |
display: flex; | |
flex-direction: column; | |
min-height: 100vh; | |
transition: background-color var(--transition-speed) ease; /* Smooth transition for potential theme changes */ | |
} | |
/* Drag over effect */ | |
body.drag-active::before { | |
content: 'Drop JSON file to import rules'; | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background-color: rgba(52, 152, 219, 0.8); | |
color: white; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
font-size: 1.5rem; | |
font-weight: bold; | |
z-index: 1000; | |
pointer-events: none; /* Important */ | |
opacity: 0; | |
animation: fadeIn 0.3s ease forwards; | |
} | |
header { | |
background-color: var(--primary); | |
color: white; | |
padding: 1rem; | |
text-align: center; | |
box-shadow: 0 2px 5px var(--shadow-medium); | |
} | |
h1 { | |
margin-bottom: 0.5rem; | |
} | |
main { | |
display: flex; | |
flex-direction: column; | |
flex: 1; | |
padding: 1.5rem; /* Slightly increased padding */ | |
max-width: 1300px; /* Slightly wider max-width */ | |
margin: 1rem auto; /* Add margin top/bottom */ | |
width: 100%; | |
gap: 1.5rem; /* Increased gap */ | |
} | |
@media (min-width: 768px) { | |
main { | |
flex-direction: row; | |
} | |
} | |
/* Card Styles */ | |
.card { | |
background: white; | |
border-radius: var(--border-radius-medium); | |
box-shadow: 0 3px 10px var(--shadow-light); | |
overflow: hidden; | |
display: flex; | |
flex-direction: column; | |
transition: box-shadow var(--transition-speed) ease; | |
} | |
.card:hover { | |
box-shadow: 0 6px 15px var(--shadow-medium); /* Subtle lift on hover */ | |
} | |
.chat-container { | |
flex: 2; | |
margin-bottom: 1rem; /* Keep margin for mobile */ | |
height: calc(100vh - 150px); /* Limit height on desktop */ | |
max-height: 800px; /* Max height */ | |
} | |
.rules-container { | |
flex: 1; | |
padding: 1.5rem; | |
max-height: calc(100vh - 150px); /* Match chat height */ | |
overflow: hidden; /* Ensure padding is respected */ | |
margin-bottom: 1rem; /* Keep margin for mobile */ | |
} | |
@media (min-width: 768px) { | |
.chat-container, .rules-container { | |
margin-bottom: 0; /* Remove bottom margin on desktop */ | |
} | |
} | |
.rules-header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 1rem; | |
padding-bottom: 0.8rem; | |
border-bottom: 1px solid var(--light); | |
} | |
.chat-header { | |
background-color: var(--primary); | |
color: white; | |
padding: 1rem 1.5rem; | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
.chat-header h2 { font-size: 1.1rem; } | |
.chat-messages { | |
flex: 1; | |
padding: 1.5rem; | |
overflow-y: auto; | |
display: flex; | |
flex-direction: column; | |
gap: 1rem; | |
/* Custom Scrollbar */ | |
scrollbar-width: thin; | |
scrollbar-color: var(--secondary) var(--light); | |
} | |
.chat-messages::-webkit-scrollbar { width: 8px; } | |
.chat-messages::-webkit-scrollbar-track { background: var(--light); border-radius: 4px; } | |
.chat-messages::-webkit-scrollbar-thumb { background-color: var(--secondary); border-radius: 4px; } | |
.message { | |
max-width: 80%; | |
padding: 0.8rem 1.2rem; | |
border-radius: var(--border-radius-large); | |
margin-bottom: 0.5rem; | |
box-shadow: 0 1px 3px var(--shadow-light); | |
position: relative; | |
word-wrap: break-word; | |
opacity: 0; /* Start hidden for animation */ | |
transform: translateY(10px); /* Start slightly lower */ | |
animation: messageFadeIn 0.5s ease forwards; | |
} | |
@keyframes messageFadeIn { | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
.user-message { | |
background-color: var(--secondary); | |
color: white; | |
align-self: flex-end; | |
border-bottom-right-radius: var(--border-radius-small); | |
} | |
.bot-message { | |
background-color: var(--light); | |
color: var(--text); | |
align-self: flex-start; | |
border-bottom-left-radius: var(--border-radius-small); | |
} | |
.chat-input { | |
display: flex; | |
padding: 1rem 1.5rem; | |
border-top: 1px solid var(--light); | |
background-color: white; | |
gap: 0.5rem; /* Add gap */ | |
} | |
.chat-input input { | |
flex: 1; | |
padding: 0.8rem 1.2rem; | |
border: 1px solid var(--light); | |
border-radius: var(--border-radius-round); /* Fully rounded */ | |
outline: none; | |
transition: border-color var(--transition-speed) ease, box-shadow var(--transition-speed) ease; | |
} | |
.chat-input input:focus { | |
border-color: var(--secondary); | |
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2); /* Focus ring */ | |
} | |
/* Button Base Styles */ | |
button { | |
padding: 0.7rem 1.2rem; /* Adjusted padding */ | |
background-color: var(--secondary); | |
color: white; | |
border: none; | |
border-radius: var(--border-radius-small); | |
cursor: pointer; | |
transition: all var(--transition-speed) ease; /* Smooth transitions */ | |
display: inline-flex; /* Align icon and text */ | |
align-items: center; | |
justify-content: center; | |
gap: 0.5rem; | |
font-weight: 500; /* Slightly bolder */ | |
white-space: nowrap; /* Prevent wrapping */ | |
} | |
button:hover:not(:disabled) { | |
background-color: var(--primary); | |
filter: brightness(1.1); /* Brighter on hover */ | |
transform: translateY(-2px); /* Lift effect */ | |
box-shadow: 0 4px 8px var(--shadow-light); | |
} | |
button:active:not(:disabled) { | |
transform: translateY(0); /* Press down effect */ | |
filter: brightness(0.9); | |
box-shadow: none; | |
} | |
button:disabled { | |
opacity: 0.6; | |
cursor: not-allowed; | |
} | |
button.danger { background-color: var(--danger); } | |
button.danger:hover:not(:disabled) { background-color: #c0392b; } /* Darker red */ | |
button.success { background-color: var(--success); } | |
button.success:hover:not(:disabled) { background-color: #27ae60; } /* Darker green */ | |
button.outline { | |
background-color: transparent; | |
color: var(--secondary); | |
border: 1px solid var(--secondary); | |
} | |
button.outline:hover:not(:disabled) { | |
background-color: var(--secondary); | |
color: white; | |
filter: none; /* Remove brightness filter for outline */ | |
} | |
.rule-form { | |
display: flex; | |
flex-direction: column; | |
gap: 0.8rem; /* Increased gap */ | |
margin-bottom: 1.5rem; /* Increased margin */ | |
} | |
.rule-form textarea { | |
padding: 0.8rem; | |
border: 1px solid var(--light); | |
border-radius: var(--border-radius-medium); /* Match card radius */ | |
resize: vertical; | |
min-height: 80px; | |
font-size: 0.9rem; | |
transition: border-color var(--transition-speed) ease, box-shadow var(--transition-speed) ease; | |
} | |
.rule-form textarea:focus { | |
border-color: var(--secondary); | |
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2); /* Focus ring */ | |
outline: none; | |
} | |
.rule-actions { | |
display: flex; | |
gap: 0.5rem; | |
} | |
.rules-list { | |
overflow-y: auto; | |
flex: 1; | |
padding-right: 0.5rem; /* Space for scrollbar */ | |
/* Custom Scrollbar */ | |
scrollbar-width: thin; | |
scrollbar-color: var(--secondary) var(--light); | |
} | |
.rules-list::-webkit-scrollbar { width: 6px; } | |
.rules-list::-webkit-scrollbar-track { background: var(--light); border-radius: 3px; } | |
.rules-list::-webkit-scrollbar-thumb { background-color: var(--secondary); border-radius: 3px; } | |
.rule-item { | |
padding: 1rem; | |
border: 1px solid var(--light); | |
border-radius: var(--border-radius-medium); | |
margin-bottom: 1rem; /* Increased spacing */ | |
position: relative; | |
background-color: white; /* Ensure background for shadow */ | |
box-shadow: 0 1px 3px var(--shadow-light); | |
transition: all var(--transition-speed) ease; /* Transition all properties */ | |
opacity: 0; /* Start hidden for animation */ | |
animation: ruleFadeIn 0.4s ease forwards; | |
} | |
@keyframes ruleFadeIn { | |
to { opacity: 1; } | |
} | |
.rule-item.deleting { | |
animation: ruleFadeOut 0.4s ease forwards; | |
} | |
@keyframes ruleFadeOut { | |
to { | |
opacity: 0; | |
transform: scale(0.95); | |
margin-bottom: 0; | |
padding-top: 0; | |
padding-bottom: 0; | |
height: 0; | |
border: none; | |
} | |
} | |
.rule-item:hover { | |
border-color: var(--secondary); | |
box-shadow: 0 4px 8px var(--shadow-medium); | |
transform: translateY(-2px); /* Subtle lift */ | |
} | |
.rule-item p { | |
margin-bottom: 1rem; /* Increased spacing */ | |
word-wrap: break-word; | |
line-height: 1.6; /* Improve readability */ | |
} | |
.rule-actions-inline { | |
display: flex; | |
justify-content: flex-end; | |
gap: 0.5rem; | |
} | |
/* Smaller buttons for inline actions */ | |
.rule-actions-inline button { | |
padding: 0.4rem 0.8rem; | |
font-size: 0.8rem; | |
} | |
.language-selector { | |
padding: 0.5rem 0.8rem; | |
border-radius: var(--border-radius-small); | |
border: 1px solid var(--light); | |
background-color: white; | |
margin-left: 0.5rem; | |
transition: border-color var(--transition-speed) ease, box-shadow var(--transition-speed) ease; | |
cursor: pointer; | |
} | |
.language-selector:hover { | |
border-color: var(--secondary); | |
} | |
.language-selector:focus { | |
border-color: var(--secondary); | |
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2); /* Focus ring */ | |
outline: none; | |
} | |
.system-message { | |
text-align: center; | |
color: var(--text); | |
opacity: 0.7; | |
margin: 0.5rem 0; | |
font-size: 0.85rem; /* Slightly larger */ | |
font-style: italic; | |
} | |
.loader { | |
display: inline-block; | |
width: 18px; /* Slightly smaller */ | |
height: 18px; | |
border: 3px solid rgba(255, 255, 255, 0.3); | |
border-radius: var(--border-radius-round); | |
border-top-color: white; | |
animation: spin 1s ease-in-out infinite; | |
/* margin-right: 0.5rem; /* Gap handles spacing */ | |
} | |
@keyframes spin { | |
to { transform: rotate(360deg); } | |
} | |
.hidden { | |
display: none ; /* Ensure it's hidden */ | |
} | |
.visually-hidden { /* For animated hiding */ | |
opacity: 0 ; | |
transform: scale(0.95) translateY(-10px) ; | |
pointer-events: none ; | |
} | |
.settings-btn { | |
background: none; | |
border: none; | |
color: white; | |
font-size: 1.5rem; /* Larger icon */ | |
cursor: pointer; | |
padding: 0.3rem; /* Add padding for easier clicking */ | |
border-radius: var(--border-radius-round); | |
transition: background-color var(--transition-speed) ease, transform var(--transition-speed) ease; | |
} | |
.settings-btn:hover { | |
background-color: rgba(255, 255, 255, 0.2); /* Subtle background */ | |
transform: rotate(15deg); /* Rotation effect */ | |
filter: none; | |
box-shadow: none; | |
} | |
.settings-panel { | |
position: absolute; | |
top: 70px; /* Position below header */ | |
right: 2rem; /* Align with main content padding */ | |
background: white; | |
border-radius: var(--border-radius-medium); | |
box-shadow: 0 5px 20px var(--shadow-medium); | |
padding: 1.5rem; | |
z-index: 100; | |
width: 320px; /* Slightly wider */ | |
/* Animation */ | |
transition: opacity var(--transition-speed) ease, transform var(--transition-speed) ease; | |
opacity: 1; | |
transform: translateY(0); | |
} | |
.settings-header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
margin-bottom: 1.5rem; /* Increased spacing */ | |
padding-bottom: 0.8rem; | |
border-bottom: 1px solid var(--light); | |
} | |
.settings-header h3 { font-size: 1.2rem; } | |
.close-btn { | |
background: none; | |
border: none; | |
font-size: 1.5rem; | |
cursor: pointer; | |
color: var(--text); | |
padding: 0.2rem; | |
line-height: 1; /* Prevent extra space */ | |
transition: color var(--transition-speed) ease, transform var(--transition-speed) ease; | |
} | |
.close-btn:hover { | |
color: var(--danger); | |
transform: scale(1.1); | |
filter: none; | |
box-shadow: none; | |
} | |
.settings-body { | |
display: flex; | |
flex-direction: column; | |
gap: 1.2rem; /* Increased spacing */ | |
} | |
.setting-item { | |
display: flex; | |
flex-direction: column; | |
gap: 0.5rem; | |
} | |
.setting-item label { | |
font-weight: 600; /* Slightly bolder */ | |
display: flex; /* Align icon */ | |
align-items: center; | |
} | |
.setting-item input { | |
padding: 0.7rem 1rem; | |
border: 1px solid var(--light); | |
border-radius: var(--border-radius-small); | |
transition: border-color var(--transition-speed) ease, box-shadow var(--transition-speed) ease; | |
} | |
.setting-item input:focus { | |
border-color: var(--secondary); | |
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2); /* Focus ring */ | |
outline: none; | |
} | |
.tooltip { | |
position: relative; | |
display: inline-block; | |
margin-left: 0.5rem; | |
cursor: help; | |
color: var(--secondary); /* Make icon color consistent */ | |
} | |
.tooltip .tooltiptext { | |
visibility: hidden; | |
width: 220px; /* Wider tooltip */ | |
background-color: var(--text); | |
color: white; | |
text-align: center; | |
border-radius: var(--border-radius-small); | |
padding: 0.6rem; /* Adjusted padding */ | |
position: absolute; | |
z-index: 1; | |
bottom: 135%; /* Position higher */ | |
left: 50%; | |
transform: translateX(-50%); | |
opacity: 0; | |
transition: opacity var(--transition-speed) ease, visibility var(--transition-speed) ease; | |
font-size: 0.85rem; | |
line-height: 1.4; | |
box-shadow: 0 2px 5px var(--shadow-medium); | |
} | |
.tooltip .tooltiptext::after { /* Tooltip arrow */ | |
content: ""; | |
position: absolute; | |
top: 100%; | |
left: 50%; | |
margin-left: -5px; | |
border-width: 5px; | |
border-style: solid; | |
border-color: var(--text) transparent transparent transparent; | |
} | |
.tooltip:hover .tooltiptext { | |
visibility: visible; | |
opacity: 1; | |
} | |
/* Add some subtle animations */ | |
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } | |
</style> | |
</head> | |
<body> | |
<header> | |
<h1>Office Procedure Expert System</h1> | |
<p>General Administration Department</p> | |
</header> | |
<main> | |
<!-- Added card class --> | |
<div class="chat-container card"> | |
<div class="chat-header"> | |
<div> | |
<h2>Office Procedure Assistant</h2> | |
</div> | |
<div class="chat-controls"> | |
<select id="language-selector" class="language-selector" title="Select language"> | |
<option value="en">English</option> | |
<option value="gu">Gujarati</option> | |
<option value="hi">Hindi</option> | |
</select> | |
<button id="settings-btn" class="settings-btn" title="Settings">⚙️</button> | |
</div> | |
</div> | |
<div class="chat-messages" id="chat-messages"> | |
<div class="message bot-message"> | |
Hello! I'm your Office Procedure Assistant. Ask me any questions about office procedures and rules, and I'll help you find the information you need. | |
</div> | |
<div class="system-message"> | |
Add rules in the panel to the right or drag & drop a JSON file onto the page to import rules. | |
</div> | |
</div> | |
<div class="chat-input"> | |
<input type="text" id="user-input" placeholder="Type your question here..."> | |
<button id="send-btn" title="Send message"> | |
<span id="loader" class="loader hidden"></span> | |
<span id="send-text">Send</span> | |
<!-- Feather icons replacement for Send icon --> | |
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-send"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg> | |
</button> | |
</div> | |
</div> | |
<!-- Added card class --> | |
<div class="rules-container card"> | |
<div class="rules-header"> | |
<h2>Knowledge Base</h2> | |
<!-- Added outline class and icon --> | |
<button id="export-rules" class="outline" title="Export rules as JSON"> | |
Export | |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-download"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg> | |
</button> | |
</div> | |
<div class="rule-form"> | |
<textarea id="rule-content" placeholder="Enter a rule or procedure here..."></textarea> | |
<div class="rule-actions"> | |
<!-- Added icon --> | |
<button id="add-rule" class="success" title="Add or update rule"> | |
<span id="add-rule-text">Add Rule</span> | |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus-circle"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg> | |
</button> | |
<!-- Added outline class and icon --> | |
<button id="clear-form" class="outline" title="Clear form"> | |
Clear | |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x-circle"><circle cx="12" cy="12" r="10"></circle><line x1="15" y1="9" x2="9" y2="15"></line><line x1="9" y1="9" x2="15" y2="15"></line></svg> | |
</button> | |
</div> | |
</div> | |
<div class="rules-list" id="rules-list"> | |
<!-- Rules will be added here dynamically --> | |
</div> | |
</div> | |
</main> | |
<!-- Added visually-hidden class for animation --> | |
<div id="settings-panel" class="settings-panel visually-hidden"> | |
<div class="settings-header"> | |
<h3>Settings</h3> | |
<button id="close-settings" class="close-btn" title="Close settings">×</button> | |
</div> | |
<div class="settings-body"> | |
<div class="setting-item"> | |
<label for="api-endpoint"> | |
API Endpoint | |
<div class="tooltip">ℹ️ | |
<span class="tooltiptext">The base URL for the AI model API (e.g., Hugging Face Space, local endpoint).</span> | |
</div> | |
</label> | |
<input type="text" id="api-endpoint" value="https://parthsadaria-lokiai.hf.space/chat/completions"> | |
</div> | |
<div class="setting-item"> | |
<label for="api-model"> | |
Model | |
<div class="tooltip">ℹ️ | |
<span class="tooltiptext">The specific model identifier to use (e.g., 'gemini', 'mistralai/Mistral-7B-Instruct-v0.1').</span> | |
</div> | |
</label> | |
<input type="text" id="api-model" value="gemini"> | |
</div> | |
<div class="setting-item"> | |
<label for="api-key"> | |
Authorization Key | |
<div class="tooltip">ℹ️ | |
<span class="tooltiptext">Your API key or token for authentication (often prefixed with 'Bearer '). Keep this secure.</span> | |
</div> | |
</label> | |
<input type="password" id="api-key" value="sigma"> | |
</div> | |
<!-- Added icon --> | |
<button id="save-settings" class="success" title="Save API settings"> | |
Save Settings | |
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-save"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg> | |
</button> | |
</div> | |
</div> | |
<script> | |
</script> | |
</body> | |
</html> |