custom instructions
This commit is contained in:
parent
e2769f2d2d
commit
1566d6c207
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,5 +1,8 @@
|
||||
from django.contrib import admin
|
||||
from .models import Article, TodoItem
|
||||
from .models import Article, TodoItem, Setting, Conversation, Message
|
||||
|
||||
admin.site.register(Article)
|
||||
admin.site.register(TodoItem)
|
||||
admin.site.register(TodoItem)
|
||||
admin.site.register(Setting)
|
||||
admin.site.register(Conversation)
|
||||
admin.site.register(Message)
|
||||
|
||||
21
core/migrations/0006_setting.py
Normal file
21
core/migrations/0006_setting.py
Normal file
@ -0,0 +1,21 @@
|
||||
# Generated by Django 5.2.7 on 2025-11-20 10:50
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('core', '0005_alter_message_options_remove_message_is_from_user_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Setting',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('key', models.CharField(max_length=255, unique=True)),
|
||||
('value', models.TextField()),
|
||||
],
|
||||
),
|
||||
]
|
||||
BIN
core/migrations/__pycache__/0006_setting.cpython-311.pyc
Normal file
BIN
core/migrations/__pycache__/0006_setting.cpython-311.pyc
Normal file
Binary file not shown.
@ -42,4 +42,11 @@ class Message(models.Model):
|
||||
ordering = ['created_at']
|
||||
|
||||
def __str__(self):
|
||||
return f"Message from {self.get_sender_display()} at {self.created_at}"
|
||||
return f"Message from {self.get_sender_display()} at {self.created_at}"
|
||||
|
||||
class Setting(models.Model):
|
||||
key = models.CharField(max_length=255, unique=True)
|
||||
value = models.TextField()
|
||||
|
||||
def __str__(self):
|
||||
return self.key
|
||||
|
||||
@ -30,6 +30,9 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'core:chat' %}">Chat</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'core:settings' %}">Settings</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
18
core/templates/core/settings.html
Normal file
18
core/templates/core/settings.html
Normal file
@ -0,0 +1,18 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container mt-4">
|
||||
<h2>Settings</h2>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="custom_instructions" class="form-label">Custom AI Instructions</label>
|
||||
<textarea class="form-control" id="custom_instructions" name="custom_instructions" rows="10">{{ custom_instructions.value }}</textarea>
|
||||
<div class="form-text">
|
||||
These instructions will be added to the AI's system prompt.
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -12,4 +12,5 @@ urlpatterns = [
|
||||
path('chat/', views.chat_view, name='chat'),
|
||||
path('chat/<int:conversation_id>/', views.chat_view, name='chat_detail'),
|
||||
path('cleanup_tasks/', views.cleanup_tasks, name='cleanup_tasks'),
|
||||
path('settings/', views.settings_view, name='settings'),
|
||||
]
|
||||
@ -3,7 +3,7 @@ from django.http import JsonResponse
|
||||
from django.views.decorators.http import require_POST
|
||||
import json
|
||||
import logging
|
||||
from .models import Article, TodoItem, Conversation, Message
|
||||
from .models import Article, TodoItem, Conversation, Message, Setting
|
||||
from .forms import TodoItemForm
|
||||
import time
|
||||
from ai.local_ai_api import LocalAIApi
|
||||
@ -170,9 +170,15 @@ def chat_view(request, conversation_id=None):
|
||||
history.append({"role": role, "content": msg.content})
|
||||
|
||||
try:
|
||||
custom_instructions, created = Setting.objects.get_or_create(
|
||||
key='custom_instructions',
|
||||
defaults={'value': ''}
|
||||
)
|
||||
custom_instructions_text = custom_instructions.value + '\n\n' if custom_instructions.value else ''
|
||||
|
||||
system_message = {
|
||||
"role": "system",
|
||||
"content": '''You are a project management assistant. To communicate with the user, you MUST use the `send_message` command.
|
||||
"content": custom_instructions_text + '''You are a project management assistant. To communicate with the user, you MUST use the `send_message` command.
|
||||
|
||||
**Commands must be in a specific JSON format.** Your response must be a JSON object with the following structure:
|
||||
|
||||
@ -333,3 +339,23 @@ def chat_view(request, conversation_id=None):
|
||||
'selected_conversation': selected_conversation,
|
||||
'timestamp': int(time.time()),
|
||||
})
|
||||
|
||||
def conversation_list(request):
|
||||
conversations = Conversation.objects.order_by('-created_at')
|
||||
return render(request, 'core/conversation_list.html', {'conversation_list': conversations})
|
||||
|
||||
def settings_view(request):
|
||||
# Get or create the custom_instructions setting
|
||||
custom_instructions, created = Setting.objects.get_or_create(
|
||||
key='custom_instructions',
|
||||
defaults={'value': ''}
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
custom_instructions.value = request.POST.get('custom_instructions', '')
|
||||
custom_instructions.save()
|
||||
return redirect('core:settings')
|
||||
|
||||
return render(request, 'core/settings.html', {
|
||||
'custom_instructions': custom_instructions
|
||||
})
|
||||
@ -227,4 +227,71 @@ body {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kanban Board Styles */
|
||||
.kanban-board-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.kanban-board {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
min-width: max-content; /* Ensure board expands horizontally */
|
||||
}
|
||||
|
||||
.kanban-column {
|
||||
flex: 1 1 300px; /* Flex-grow, flex-shrink, and basis */
|
||||
min-width: 300px;
|
||||
max-width: 320px;
|
||||
background-color: #f0f2f5;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 250px); /* Adjust based on your layout */
|
||||
}
|
||||
|
||||
.kanban-column h2 {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.kanban-cards {
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
min-height: 150px; /* Ensure drop zone is available even when empty */
|
||||
}
|
||||
|
||||
.kanban-card {
|
||||
cursor: grab;
|
||||
transition: background-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.kanban-card:hover {
|
||||
background-color: #f8f9fa;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.kanban-card .btn-close {
|
||||
transition: opacity 0.2s;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.kanban-card:hover .btn-close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* For the drag-and-drop placeholder */
|
||||
.sortable-ghost {
|
||||
background-color: #e9ecef;
|
||||
border: 2px dashed #ced4da;
|
||||
}
|
||||
|
||||
.sortable-drag {
|
||||
opacity: 1 !important; /* Override Sortable.js default opacity */
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
||||
transform: rotate(3deg);
|
||||
}
|
||||
|
||||
230
static/css/custom.css.bak
Normal file
230
static/css/custom.css.bak
Normal file
@ -0,0 +1,230 @@
|
||||
/* General App Body & Layout */
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
/* Main Chat Layout */
|
||||
.chat-container {
|
||||
display: flex;
|
||||
height: calc(100vh - 120px); /* Adjusted for header/footer */
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/* Sidebar Styles */
|
||||
.chat-sidebar {
|
||||
width: 280px;
|
||||
background-color: #f8f9fa;
|
||||
border-right: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.new-chat-form {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.new-chat-form input {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem 0 0 0.375rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.new-chat-form button {
|
||||
padding: 0.75rem 1rem;
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
border: 1px solid #0d6efd;
|
||||
border-radius: 0 0.375rem 0.375rem 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.conversation-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.conversation-list a {
|
||||
display: block;
|
||||
padding: 0.75rem 1rem;
|
||||
color: #495057;
|
||||
text-decoration: none;
|
||||
border-radius: 0.375rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.conversation-list a:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.conversation-list a.active {
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Main Content Area */
|
||||
.chat-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
position: relative; /* Needed for loader overlay */
|
||||
}
|
||||
|
||||
/* Chat Header */
|
||||
.chat-header {
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chat-header h3 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Message Area */
|
||||
.chat-messages {
|
||||
flex: 1;
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
max-width: 80%;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.message.user .message-content {
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message.ai .message-content {
|
||||
background-color: #e9ecef;
|
||||
color: #343a40;
|
||||
}
|
||||
|
||||
.message-author {
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
/* Message Input Form */
|
||||
.chat-form-container {
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.chat-form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chat-form textarea {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 1rem;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.chat-form button {
|
||||
margin-left: 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Empty State for Chat */
|
||||
.no-conversation-selected {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Loader Styles */
|
||||
.loader-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: 5px solid #f3f3f3; /* Light grey */
|
||||
border-top: 5px solid #0d6efd; /* Blue */
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* System and AI Command Messages */
|
||||
.message.system .message-content {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.message.ai_command .message-content {
|
||||
background-color: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.message.ai_command .message-content pre {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.kanban-card .card-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.delete-task-form {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
@ -227,4 +227,71 @@ body {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kanban Board Styles */
|
||||
.kanban-board-container {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.kanban-board {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
min-width: max-content; /* Ensure board expands horizontally */
|
||||
}
|
||||
|
||||
.kanban-column {
|
||||
flex: 1 1 300px; /* Flex-grow, flex-shrink, and basis */
|
||||
min-width: 300px;
|
||||
max-width: 320px;
|
||||
background-color: #f0f2f5;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-height: calc(100vh - 250px); /* Adjust based on your layout */
|
||||
}
|
||||
|
||||
.kanban-column h2 {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.kanban-cards {
|
||||
overflow-y: auto;
|
||||
flex-grow: 1;
|
||||
min-height: 150px; /* Ensure drop zone is available even when empty */
|
||||
}
|
||||
|
||||
.kanban-card {
|
||||
cursor: grab;
|
||||
transition: background-color 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.kanban-card:hover {
|
||||
background-color: #f8f9fa;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.kanban-card .btn-close {
|
||||
transition: opacity 0.2s;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.kanban-card:hover .btn-close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* For the drag-and-drop placeholder */
|
||||
.sortable-ghost {
|
||||
background-color: #e9ecef;
|
||||
border: 2px dashed #ced4da;
|
||||
}
|
||||
|
||||
.sortable-drag {
|
||||
opacity: 1 !important; /* Override Sortable.js default opacity */
|
||||
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
|
||||
transform: rotate(3deg);
|
||||
}
|
||||
|
||||
230
staticfiles/css/custom.css.bak
Normal file
230
staticfiles/css/custom.css.bak
Normal file
@ -0,0 +1,230 @@
|
||||
/* General App Body & Layout */
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
/* Main Chat Layout */
|
||||
.chat-container {
|
||||
display: flex;
|
||||
height: calc(100vh - 120px); /* Adjusted for header/footer */
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/* Sidebar Styles */
|
||||
.chat-sidebar {
|
||||
width: 280px;
|
||||
background-color: #f8f9fa;
|
||||
border-right: 1px solid #dee2e6;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.new-chat-form {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.new-chat-form input {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem 0 0 0.375rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.new-chat-form button {
|
||||
padding: 0.75rem 1rem;
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
border: 1px solid #0d6efd;
|
||||
border-radius: 0 0.375rem 0.375rem 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.conversation-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.conversation-list a {
|
||||
display: block;
|
||||
padding: 0.75rem 1rem;
|
||||
color: #495057;
|
||||
text-decoration: none;
|
||||
border-radius: 0.375rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.conversation-list a:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.conversation-list a.active {
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Main Content Area */
|
||||
.chat-main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
position: relative; /* Needed for loader overlay */
|
||||
}
|
||||
|
||||
/* Chat Header */
|
||||
.chat-header {
|
||||
padding: 1rem 1.5rem;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.chat-header h3 {
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Message Area */
|
||||
.chat-messages {
|
||||
flex: 1;
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
max-width: 80%;
|
||||
padding: 0.75rem 1rem;
|
||||
border-radius: 0.5rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.message.user {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.message.user .message-content {
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.message.ai .message-content {
|
||||
background-color: #e9ecef;
|
||||
color: #343a40;
|
||||
}
|
||||
|
||||
.message-author {
|
||||
font-weight: bold;
|
||||
font-size: 0.8rem;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
/* Message Input Form */
|
||||
.chat-form-container {
|
||||
padding: 1rem 1.5rem;
|
||||
border-top: 1px solid #dee2e6;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.chat-form {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.chat-form textarea {
|
||||
flex: 1;
|
||||
padding: 0.75rem;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 0.375rem;
|
||||
font-size: 1rem;
|
||||
resize: none;
|
||||
}
|
||||
|
||||
.chat-form button {
|
||||
margin-left: 1rem;
|
||||
padding: 0.75rem 1.5rem;
|
||||
background-color: #0d6efd;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 0.375rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Empty State for Chat */
|
||||
.no-conversation-selected {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
color: #6c757d;
|
||||
}
|
||||
|
||||
/* Loader Styles */
|
||||
.loader-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.loader {
|
||||
border: 5px solid #f3f3f3; /* Light grey */
|
||||
border-top: 5px solid #0d6efd; /* Blue */
|
||||
border-radius: 50%;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* System and AI Command Messages */
|
||||
.message.system .message-content {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
border: 1px solid #f5c6cb;
|
||||
}
|
||||
|
||||
.message.ai_command .message-content {
|
||||
background-color: #d1ecf1;
|
||||
color: #0c5460;
|
||||
border: 1px solid #bee5eb;
|
||||
}
|
||||
|
||||
.message.ai_command .message-content pre {
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.kanban-card .card-body {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.delete-task-form {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user