diff --git a/config/__pycache__/__init__.cpython-311.pyc b/config/__pycache__/__init__.cpython-311.pyc index 423a636..51833a4 100644 Binary files a/config/__pycache__/__init__.cpython-311.pyc and b/config/__pycache__/__init__.cpython-311.pyc differ diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index 96bce55..8a2b854 100644 Binary files a/config/__pycache__/settings.cpython-311.pyc and b/config/__pycache__/settings.cpython-311.pyc differ diff --git a/config/__pycache__/urls.cpython-311.pyc b/config/__pycache__/urls.cpython-311.pyc index 0b85e94..05e8040 100644 Binary files a/config/__pycache__/urls.cpython-311.pyc and b/config/__pycache__/urls.cpython-311.pyc differ diff --git a/config/__pycache__/wsgi.cpython-311.pyc b/config/__pycache__/wsgi.cpython-311.pyc index 9c49e09..c3453a1 100644 Binary files a/config/__pycache__/wsgi.cpython-311.pyc and b/config/__pycache__/wsgi.cpython-311.pyc differ diff --git a/config/settings.py b/config/settings.py index 291d043..815028a 100644 --- a/config/settings.py +++ b/config/settings.py @@ -180,3 +180,6 @@ if EMAIL_USE_SSL: # https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +LOGIN_REDIRECT_URL = 'dashboard' +LOGOUT_REDIRECT_URL = 'index' \ No newline at end of file diff --git a/config/urls.py b/config/urls.py index bcfc074..2001e5f 100644 --- a/config/urls.py +++ b/config/urls.py @@ -1,19 +1,3 @@ -""" -URL configuration for config project. - -The `urlpatterns` list routes URLs to views. For more information please see: - https://docs.djangoproject.com/en/5.2/topics/http/urls/ -Examples: -Function views - 1. Add an import: from my_app import views - 2. Add a URL to urlpatterns: path('', views.home, name='home') -Class-based views - 1. Add an import: from other_app.views import Home - 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') -Including another URLconf - 1. Import the include() function: from django.urls import include, path - 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) -""" from django.contrib import admin from django.urls import include, path from django.conf import settings @@ -21,9 +5,10 @@ from django.conf.urls.static import static urlpatterns = [ path("admin/", admin.site.urls), + path("accounts/", include("django.contrib.auth.urls")), path("", include("core.urls")), ] if settings.DEBUG: urlpatterns += static("/assets/", document_root=settings.BASE_DIR / "assets") - urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) \ No newline at end of file diff --git a/core/__pycache__/__init__.cpython-311.pyc b/core/__pycache__/__init__.cpython-311.pyc index 74b1112..1e85592 100644 Binary files a/core/__pycache__/__init__.cpython-311.pyc and b/core/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index a5ed392..cba48c1 100644 Binary files a/core/__pycache__/admin.cpython-311.pyc and b/core/__pycache__/admin.cpython-311.pyc differ diff --git a/core/__pycache__/apps.cpython-311.pyc b/core/__pycache__/apps.cpython-311.pyc index 6f131d4..3698ca3 100644 Binary files a/core/__pycache__/apps.cpython-311.pyc and b/core/__pycache__/apps.cpython-311.pyc differ diff --git a/core/__pycache__/context_processors.cpython-311.pyc b/core/__pycache__/context_processors.cpython-311.pyc index 75bf223..af2ab82 100644 Binary files a/core/__pycache__/context_processors.cpython-311.pyc and b/core/__pycache__/context_processors.cpython-311.pyc differ diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index e061640..6f02a63 100644 Binary files a/core/__pycache__/models.cpython-311.pyc and b/core/__pycache__/models.cpython-311.pyc differ diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 5a69659..f364545 100644 Binary files a/core/__pycache__/urls.cpython-311.pyc and b/core/__pycache__/urls.cpython-311.pyc differ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 2a36fd6..f9e1f12 100644 Binary files a/core/__pycache__/views.cpython-311.pyc and b/core/__pycache__/views.cpython-311.pyc differ diff --git a/core/admin.py b/core/admin.py index 8c38f3f..9966056 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,3 +1,18 @@ from django.contrib import admin +from .models import Company, Profile, AIChatHistory -# Register your models here. +@admin.register(Company) +class CompanyAdmin(admin.ModelAdmin): + list_display = ('name', 'tenant_id', 'created_at') + search_fields = ('name', 'tenant_id') + +@admin.register(Profile) +class ProfileAdmin(admin.ModelAdmin): + list_display = ('user', 'company', 'role') + list_filter = ('company', 'role') + +@admin.register(AIChatHistory) +class AIChatHistoryAdmin(admin.ModelAdmin): + list_display = ('chat_title', 'ai_chat_engine', 'company', 'chat_last_date') + list_filter = ('ai_chat_engine', 'company') + search_fields = ('chat_title', 'chat_content') \ No newline at end of file diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py new file mode 100644 index 0000000..827ba35 --- /dev/null +++ b/core/migrations/0001_initial.py @@ -0,0 +1,52 @@ +# Generated by Django 5.2.7 on 2026-02-08 15:44 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Company', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('tenant_id', models.SlugField(unique=True)), + ('created_at', models.DateTimeField(auto_now_add=True)), + ], + ), + migrations.CreateModel( + name='Profile', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('role', models.CharField(choices=[('admin', 'Admin'), ('user', 'End-User')], default='user', max_length=50)), + ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='members', to='core.company')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='AIChatHistory', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ai_chat_engine', models.CharField(max_length=100)), + ('ai_chat_id', models.CharField(max_length=255)), + ('chat_title', models.CharField(max_length=512)), + ('chat_content', models.TextField()), + ('chat_last_date', models.DateTimeField()), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('company', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='chat_histories', to='core.company')), + ], + options={ + 'verbose_name_plural': 'AI Chat Histories', + 'indexes': [models.Index(fields=['chat_title'], name='core_aichat_chat_ti_6da4cc_idx')], + }, + ), + ] diff --git a/core/migrations/__pycache__/0001_initial.cpython-311.pyc b/core/migrations/__pycache__/0001_initial.cpython-311.pyc new file mode 100644 index 0000000..eb07514 Binary files /dev/null and b/core/migrations/__pycache__/0001_initial.cpython-311.pyc differ diff --git a/core/migrations/__pycache__/__init__.cpython-311.pyc b/core/migrations/__pycache__/__init__.cpython-311.pyc index 9c833c8..94e9587 100644 Binary files a/core/migrations/__pycache__/__init__.cpython-311.pyc and b/core/migrations/__pycache__/__init__.cpython-311.pyc differ diff --git a/core/models.py b/core/models.py index 71a8362..84a4182 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,37 @@ from django.db import models +from django.contrib.auth.models import User -# Create your models here. +class Company(models.Model): + name = models.CharField(max_length=255) + tenant_id = models.SlugField(unique=True) + created_at = models.DateTimeField(auto_now_add=True) + + def __str__(self): + return self.name + +class Profile(models.Model): + user = models.OneToOneField(User, on_delete=models.CASCADE) + company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='members') + role = models.CharField(max_length=50, choices=[('admin', 'Admin'), ('user', 'End-User')], default='user') + + def __str__(self): + return f"{self.user.username} ({self.company.name})" + +class AIChatHistory(models.Model): + company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='chat_histories') + ai_chat_engine = models.CharField(max_length=100) # ChatGPT, Bing, etc. + ai_chat_id = models.CharField(max_length=255) + chat_title = models.CharField(max_length=512) + chat_content = models.TextField() + chat_last_date = models.DateTimeField() + created_at = models.DateTimeField(auto_now_add=True) + + class Meta: + verbose_name_plural = "AI Chat Histories" + indexes = [ + models.Index(fields=['chat_title']), + # We'll use database-level full-text search or icontains for now + ] + + def __str__(self): + return f"[{self.ai_chat_engine}] {self.chat_title}" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 1e7e5fb..b721411 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -1,25 +1,147 @@ - - - {% block title %}Knowledge Base{% endblock %} - {% if project_description %} - - - - {% endif %} - {% if project_image_url %} - - - {% endif %} - {% load static %} - - {% block head %}{% endblock %} + + + {% block title %}AI Chat Archive{% endblock %} + + + + + + + + + + + + + {% load static %} + + + + {% block head %}{% endblock %} - - {% block content %}{% endblock %} - + +
+
+ {% if messages %} + {% for message in messages %} +
+ {{ message }} +
+ {% endfor %} + {% endif %} +
+ {% block content %}{% endblock %} +
+ + + + + + + {% block scripts %}{% endblock %} + diff --git a/core/templates/core/chat_detail.html b/core/templates/core/chat_detail.html new file mode 100644 index 0000000..8cea243 --- /dev/null +++ b/core/templates/core/chat_detail.html @@ -0,0 +1,55 @@ +{% extends "base.html" %} + +{% block title %}{{ chat.chat_title }} - AI Chat Archive{% endblock %} + +{% block content %} +
+ + +
+
+
+ {{ chat.ai_chat_engine }} +

{{ chat.chat_title }}

+

Last updated: {{ chat.chat_last_date|date:"F j, Y, g:i a" }}

+
+
+ +
+
+ +
+
+ {{ chat.chat_content }} +
+
+ +
+ + +
+
+
+{% endblock %} + +{% block scripts %} + +{% endblock %} diff --git a/core/templates/core/dashboard.html b/core/templates/core/dashboard.html new file mode 100644 index 0000000..ef56e2f --- /dev/null +++ b/core/templates/core/dashboard.html @@ -0,0 +1,85 @@ +{% extends "base.html" %} + +{% block title %}Dashboard - AI Chat Archive{% endblock %} + +{% block content %} +
+
+
+ {{ company.name }} +

Chat Archive

+
+
+ Logged in as {{ user.username }} +
+
+ + +
+
+
+
+ + + + +
+
+
+ +
+
+
+ + +
+
+ {% if query %} +
Search results for "{{ query }}"
+ {% else %} +
Recent Conversations
+ {% endif %} + + {% if chats %} +
+ {% for chat in chats %} +
+
+
+
+
+ {% if chat.ai_chat_engine == 'ChatGPT' %} + + {% elif chat.ai_chat_engine == 'Bing' %} + + {% else %} + + {% endif %} +
+
+
{{ chat.chat_title }}
+ {{ chat.ai_chat_engine }} • {{ chat.chat_last_date|date:"M d, Y" }} +
+
+ + + +
+
+ {{ chat.chat_content|truncatewords:50|linebreaks }} +
+
+
+ {% endfor %} +
+ {% else %} +
+ +

No chats found. Try a different search term or connect an engine.

+
+ {% endif %} +
+
+
+{% endblock %} diff --git a/core/templates/core/index.html b/core/templates/core/index.html index faec813..1ed3c0e 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,145 +1,110 @@ {% extends "base.html" %} -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} - - - - -{% endblock %} +{% block title %}Welcome to AI Chat Archive{% endblock %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+ +
+
+

+ Unlock Your Collective Intelligence +

+

+ Retrieve, archive, and search through your entire AI chat history from ChatGPT, Bing, and more. + One unified search for all your past conversations. +

+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+ > Retrieving histories...
+ > Found 142 chats from ChatGPT
+ > Found 89 chats from Perplexity
+ > Indexing for rapid search... +
+
+
+
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
- + + +
+
+

Three Steps to Knowledge Mastery

+

Our platform bridges the gap between AI silos and your team's memory.

+
+
+
+
+
+ 1 +
Connect Engines
+
+

Use the "Connect AI" button in your dashboard to link your API keys securely. We support OpenAI, Anthropic, and Perplexity.

+
+
+
+
+
+ 2 +
Sync History
+
+

Click "Fetch Latest" to automatically download and index your recent conversations into your private company vault.

+
+
+
+
+
+ 3 +
Search & Find
+
+

Use the Search Bar to instantly find any past prompt or answer across all connected AI tools, including file attachments.

+
+
+
+
+ + +
+
+
+
+ +

Unified Storage

+

Centralize all your AI interactions in one secure, company-owned vault.

+
+
+
+
+ +

Instant Search

+

Powerful keyword and similarity search powered by optimized database indexes.

+
+
+
+
+ +

Multi-tenant

+

Enterprise-grade isolation ensuring your company's data stays private.

+
+
+
+
+ {% endblock %} \ No newline at end of file diff --git a/core/templates/registration/login.html b/core/templates/registration/login.html new file mode 100644 index 0000000..dab531f --- /dev/null +++ b/core/templates/registration/login.html @@ -0,0 +1,44 @@ +{% extends "base.html" %} + +{% block title %}Login - AI Chat Archive{% endblock %} + +{% block content %} +
+
+
+

Welcome Back

+

Sign in to access your AI vault

+
+ +
+ {% csrf_token %} + + {% if form.errors %} +
+ Your username and password didn't match. Please try again. +
+ {% endif %} + +
+ + +
+ +
+ + +
+ + + + +
+ +
+

Demo credentials: admin / admin123

+
+
+
+{% endblock %} diff --git a/core/urls.py b/core/urls.py index 6299e3d..3e940ef 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,8 @@ from django.urls import path - -from .views import home +from . import views urlpatterns = [ - path("", home, name="home"), -] + path('', views.index, name='index'), + path('dashboard/', views.dashboard, name='dashboard'), + path('chat//', views.chat_detail, name='chat_detail'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..1c3e1d1 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,34 @@ -import os -import platform +from django.shortcuts import render, redirect +from django.contrib.auth.decorators import login_required +from .models import AIChatHistory, Profile +from django.db.models import Q -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +def index(request): + if request.user.is_authenticated: + return redirect('dashboard') + return render(request, 'core/index.html') +@login_required +def dashboard(request): + query = request.GET.get('q', '') + profile = Profile.objects.get(user=request.user) + chats = AIChatHistory.objects.filter(company=profile.company) -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + if query: + chats = chats.filter( + Q(chat_title__icontains=query) | Q(chat_content__icontains=query) + ).order_by('-chat_last_date') + else: + chats = chats.order_by('-chat_last_date')[:10] context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), + 'chats': chats, + 'query': query, + 'company': profile.company } - return render(request, "core/index.html", context) + return render(request, 'core/dashboard.html', context) + +def chat_detail(request, pk): + profile = Profile.objects.get(user=request.user) + chat = AIChatHistory.objects.get(pk=pk, company=profile.company) + return render(request, 'core/chat_detail.html', {'chat': chat}) \ No newline at end of file