A bunch of updates
This commit is contained in:
BIN
company_site/Inoivce Template.pdf
Normal file
BIN
company_site/Inoivce Template.pdf
Normal file
Binary file not shown.
@@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/5.0/ref/settings/
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
@@ -20,6 +20,7 @@ from django.urls import include, path
|
||||
|
||||
urlpatterns = [
|
||||
path("public/", include("public.urls")),
|
||||
path("", include("public.urls")),
|
||||
path("financial/", include("financial.urls")),
|
||||
path("planning/", include("planning.urls")),
|
||||
path("accounts/", include("django.contrib.auth.urls")),
|
||||
|
||||
18
company_site/financial/admin.py
Normal file → Executable file
18
company_site/financial/admin.py
Normal file → Executable file
@@ -1,8 +1,24 @@
|
||||
from django.contrib import admin
|
||||
from .models import Contract
|
||||
from .models import Contract, Employee, ChargeNumber, TimeCard, TimeCardCell
|
||||
# Register your models here.
|
||||
|
||||
class ContractAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class EmployeeAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class ChargeNumberAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class TimeCardAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
class TimeCardCellAdmin(admin.ModelAdmin):
|
||||
pass
|
||||
|
||||
admin.site.register(Contract, ContractAdmin)
|
||||
admin.site.register(Employee, EmployeeAdmin)
|
||||
admin.site.register(ChargeNumber, ChargeNumberAdmin)
|
||||
admin.site.register(TimeCard, TimeCardAdmin)
|
||||
admin.site.register(TimeCardCell, TimeCardCellAdmin)
|
||||
18
company_site/financial/migrations/0014_chargenumber_name.py
Normal file
18
company_site/financial/migrations/0014_chargenumber_name.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.0 on 2026-03-26 14:46
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('financial', '0013_alter_employee_primaryaddress_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='chargenumber',
|
||||
name='name',
|
||||
field=models.CharField(blank=True, max_length=100, null=True),
|
||||
),
|
||||
]
|
||||
3
company_site/financial/models.py
Normal file → Executable file
3
company_site/financial/models.py
Normal file → Executable file
@@ -192,6 +192,7 @@ class ChargeNumber(IdMixin, TimeMixin):
|
||||
MAX_NUM_TASK_TYPES = "MAX", "MAX_NUM_TASK_TYPES"
|
||||
|
||||
charge_number_type = EnumField(ChargeNumberTypeEnum)
|
||||
name = models.CharField(max_length=100, blank=True, null=True)
|
||||
|
||||
contract = models.ForeignKey(Contract, on_delete=models.CASCADE)
|
||||
amount = models.FloatField(default=0.0)
|
||||
@@ -202,7 +203,7 @@ class ChargeNumber(IdMixin, TimeMixin):
|
||||
end_date = models.DateField(null=True, blank=True, default = None)
|
||||
|
||||
def __str__(self):
|
||||
return self.slug or f"CN-{self.id}"
|
||||
return self.name or self.slug or f"CN-{self.id}"
|
||||
|
||||
@property
|
||||
def get_percent_complete(self):
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
<button type="submit" class="btn" style="margin-top: 1rem;">Update</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr style="margin: 40px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
|
||||
@@ -40,7 +41,8 @@
|
||||
<h2 class="section-title" style="text-align: left; font-size: 2rem;">Earned Value Management</h2>
|
||||
|
||||
<!-- EVM KPI Cards -->
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 2rem;">
|
||||
<div
|
||||
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 2rem;">
|
||||
<!-- BAC -->
|
||||
<div class="card evm-kpi-card">
|
||||
<span class="evm-kpi-label">BAC (Budget)</span>
|
||||
@@ -68,7 +70,8 @@
|
||||
</div>
|
||||
|
||||
<!-- Variance & Index Cards -->
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 2rem;">
|
||||
<div
|
||||
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 16px; margin-bottom: 2rem;">
|
||||
<!-- SV -->
|
||||
<div class="card evm-kpi-card">
|
||||
<span class="evm-kpi-label">Schedule Variance</span>
|
||||
@@ -88,34 +91,40 @@
|
||||
<!-- SPI -->
|
||||
<div class="card evm-kpi-card">
|
||||
<span class="evm-kpi-label">SPI</span>
|
||||
<span class="evm-kpi-value {% if evm.spi >= 1 %}evm-positive{% elif evm.spi > 0 %}evm-negative{% endif %}">
|
||||
<span
|
||||
class="evm-kpi-value {% if evm.spi >= 1 %}evm-positive{% elif evm.spi > 0 %}evm-negative{% endif %}">
|
||||
{{ evm.spi }}
|
||||
</span>
|
||||
<span class="evm-kpi-sub">{% if evm.spi >= 1 %}On/ahead{% elif evm.spi > 0 %}Behind{% else %}No data{% endif %}</span>
|
||||
<span class="evm-kpi-sub">{% if evm.spi >= 1 %}On/ahead{% elif evm.spi > 0 %}Behind{% else %}No data{%
|
||||
endif %}</span>
|
||||
</div>
|
||||
<!-- CPI -->
|
||||
<div class="card evm-kpi-card">
|
||||
<span class="evm-kpi-label">CPI</span>
|
||||
<span class="evm-kpi-value {% if evm.cpi >= 1 %}evm-positive{% elif evm.cpi > 0 %}evm-negative{% endif %}">
|
||||
<span
|
||||
class="evm-kpi-value {% if evm.cpi >= 1 %}evm-positive{% elif evm.cpi > 0 %}evm-negative{% endif %}">
|
||||
{{ evm.cpi }}
|
||||
</span>
|
||||
<span class="evm-kpi-sub">{% if evm.cpi >= 1 %}Efficient{% elif evm.cpi > 0 %}Over-spending{% else %}No data{% endif %}</span>
|
||||
<span class="evm-kpi-sub">{% if evm.cpi >= 1 %}Efficient{% elif evm.cpi > 0 %}Over-spending{% else %}No
|
||||
data{% endif %}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Charts Row -->
|
||||
<div style="display: grid; grid-template-columns: 2fr 1fr; gap: 20px; margin-bottom: 2rem;">
|
||||
<!-- S-Curve Chart -->
|
||||
<div class="card" style="padding: 20px;">
|
||||
<h3 style="margin-bottom: 1rem; font-size: 1.1rem; color: var(--text-muted);">S-Curve (PV vs EV vs AC)</h3>
|
||||
<!-- Charts: full-width rows -->
|
||||
<div class="evm-charts-stack">
|
||||
<div class="card evm-chart-card">
|
||||
<h3 class="evm-chart-title">S-Curve (PV vs EV vs AC)</h3>
|
||||
<div class="evm-chart-canvas-wrap">
|
||||
<canvas id="evmSCurveChart"></canvas>
|
||||
</div>
|
||||
<!-- SPI / CPI Bar Chart -->
|
||||
<div class="card" style="padding: 20px;">
|
||||
<h3 style="margin-bottom: 1rem; font-size: 1.1rem; color: var(--text-muted);">Performance Indices</h3>
|
||||
</div>
|
||||
<div class="card evm-chart-card">
|
||||
<h3 class="evm-chart-title">Performance Indices</h3>
|
||||
<div class="evm-chart-canvas-wrap evm-chart-canvas-wrap--compact">
|
||||
<canvas id="evmIndexChart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<hr style="margin: 40px 0; border: 0; border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
@@ -123,11 +132,14 @@
|
||||
<h2 class="section-title" style="text-align: left; font-size: 2rem;">Charge Numbers</h2>
|
||||
{% if charge_numbers %}
|
||||
{% if mermaid_gantt %}
|
||||
<div class="card" style="margin-bottom: 2rem; background: var(--surface-color);">
|
||||
<div class="card charge-gantt-card" style="margin-bottom: 2rem; background: var(--surface-color);">
|
||||
<h3 class="evm-chart-title" style="margin-bottom: 1rem;">Timeline</h3>
|
||||
<div class="charge-gantt-scroll">
|
||||
<div class="mermaid">
|
||||
{{ mermaid_gantt|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="card" style="margin-bottom: 2rem;">
|
||||
@@ -135,7 +147,7 @@
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Slug/ID</th>
|
||||
<th>Slug/ID/Name</th>
|
||||
<th>Type</th>
|
||||
<th>Amount</th>
|
||||
<th>% Complete</th>
|
||||
@@ -147,18 +159,20 @@
|
||||
<tbody>
|
||||
{% for cn in charge_numbers %}
|
||||
<tr>
|
||||
<td>{{ cn.slug }}</td>
|
||||
<td>{{ cn }}</td>
|
||||
<td>{{ cn.get_charge_number_type_display }}</td>
|
||||
<td>${{ cn.amount|floatformat:2 }}</td>
|
||||
<td>
|
||||
<span class="badge" style="background: rgba(0, 243, 255, 0.1); border: 1px solid var(--primary-color); color: var(--primary-color);">
|
||||
<span class="badge"
|
||||
style="background: rgba(0, 243, 255, 0.1); border: 1px solid var(--primary-color); color: var(--primary-color);">
|
||||
{{ cn.percent_complete|floatformat:0 }}%
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ cn.start_date|default:"-" }}</td>
|
||||
<td>{{ cn.end_date|default:"-" }}</td>
|
||||
<td class="charge-date-cell">{{ cn.start_date|default:"-" }}</td>
|
||||
<td class="charge-date-cell">{{ cn.end_date|default:"-" }}</td>
|
||||
<td>
|
||||
<a href="{% url 'update_charge_number' cn.slug %}" class="text-cyber-cyan" style="font-size: 0.9rem;">Edit</a>
|
||||
<a href="{% url 'update_charge_number' cn.slug %}" class="text-cyber-cyan"
|
||||
style="font-size: 0.9rem;">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -177,7 +191,8 @@
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="card" style="max-width: 600px;">
|
||||
<p style="color: var(--text-muted); margin-bottom: 1.5rem;">There are no charge numbers for this contract.</p>
|
||||
<p style="color: var(--text-muted); margin-bottom: 1.5rem;">There are no charge numbers for this contract.
|
||||
</p>
|
||||
<form method="post" action='{% url "new_charge_number" contract.slug %}'>
|
||||
{% csrf_token %}
|
||||
{{ charge_number_form.as_p }}
|
||||
@@ -202,10 +217,12 @@
|
||||
border-radius: 12px;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.evm-kpi-card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0, 243, 255, 0.08);
|
||||
}
|
||||
|
||||
.evm-kpi-label {
|
||||
font-size: 0.75rem;
|
||||
text-transform: uppercase;
|
||||
@@ -214,19 +231,71 @@
|
||||
margin-bottom: 6px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.evm-kpi-value {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.evm-kpi-sub {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-muted, #888);
|
||||
margin-top: 4px;
|
||||
}
|
||||
.evm-positive { color: #39ff14 !important; }
|
||||
.evm-negative { color: #ff4444 !important; }
|
||||
|
||||
.evm-positive {
|
||||
color: #39ff14 !important;
|
||||
}
|
||||
|
||||
.evm-negative {
|
||||
color: #ff4444 !important;
|
||||
}
|
||||
|
||||
.evm-charts-stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
margin-bottom: 2rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.evm-chart-card {
|
||||
padding: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.evm-chart-title {
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1.1rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.evm-chart-canvas-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 320px;
|
||||
}
|
||||
|
||||
.evm-chart-canvas-wrap--compact {
|
||||
height: 260px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
.charge-gantt-scroll {
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.charge-gantt-scroll .mermaid {
|
||||
min-width: 720px;
|
||||
}
|
||||
|
||||
.charge-date-cell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="module">
|
||||
@@ -295,6 +364,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
interaction: { mode: 'index', intersect: false },
|
||||
plugins: {
|
||||
legend: { labels: { color: '#e0e0e0', usePointStyle: true, padding: 16 } },
|
||||
@@ -372,6 +442,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}],
|
||||
options: {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
|
||||
@@ -17,6 +17,110 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-bottom: 2rem; padding: 1.25rem;">
|
||||
<form method="get" action="{% url 'time_logs' %}"
|
||||
style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1rem; align-items: end;">
|
||||
<div>
|
||||
<label for="filter-employee"
|
||||
style="display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.35rem;">Employee <span style="opacity: 0.75;">(Ctrl/Cmd+click for multiple)</span></label>
|
||||
<select name="employee" id="filter-employee" multiple size="5"
|
||||
style="width: 100%; padding: 0.5rem; background: var(--surface-color); color: var(--text-color); border: 1px solid rgba(255,255,255,0.15); border-radius: 6px;">
|
||||
{% for emp in employees %}
|
||||
<option value="{{ emp.id }}" {% if emp.id|stringformat:"s" in filters.employees %}selected{% endif %}>{{ emp }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="filter-month"
|
||||
style="display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.35rem;">Month</label>
|
||||
<input type="month" name="month" id="filter-month" value="{{ filters.month }}"
|
||||
style="width: 100%; padding: 0.5rem; background: var(--surface-color); color: var(--text-color); border: 1px solid rgba(255,255,255,0.15); border-radius: 6px;">
|
||||
</div>
|
||||
<div>
|
||||
<label for="filter-contract"
|
||||
style="display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.35rem;">Contract</label>
|
||||
<select name="contract" id="filter-contract"
|
||||
style="width: 100%; padding: 0.5rem; background: var(--surface-color); color: var(--text-color); border: 1px solid rgba(255,255,255,0.15); border-radius: 6px;">
|
||||
<option value="">All contracts</option>
|
||||
{% for c in contracts %}
|
||||
<option value="{{ c.id }}" {% if filters.contract == c.id|stringformat:"s" %}selected{% endif %}>{{ c.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label for="filter-charge-number"
|
||||
style="display: block; font-size: 0.8rem; color: var(--text-muted); margin-bottom: 0.35rem;">Charge Number</label>
|
||||
<select name="charge_number" id="filter-charge-number"
|
||||
style="width: 100%; padding: 0.5rem; background: var(--surface-color); color: var(--text-color); border: 1px solid rgba(255,255,255,0.15); border-radius: 6px;">
|
||||
<option value="">All charge numbers</option>
|
||||
{% for cn in charge_numbers %}
|
||||
<option value="{{ cn.id }}" {% if filters.charge_number == cn.id|stringformat:"s" %}selected{% endif %}>{{ cn }} ({{ cn.contract.name }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap;">
|
||||
<button type="submit" class="btn" style="padding: 0.5rem 1.25rem; font-size: 0.9rem;">Apply</button>
|
||||
<a href="{% url 'time_logs' %}" class="btn"
|
||||
style="padding: 0.5rem 1.25rem; font-size: 0.9rem; background: var(--surface-color); color: var(--text-color); border: 1px solid rgba(255,255,255,0.1);">Clear</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.5rem; margin-bottom: 2rem;">
|
||||
<div class="card" style="padding: 1.25rem;">
|
||||
<h2 style="font-size: 1rem; margin: 0 0 1rem 0; color: var(--text-muted);">Hours by Contract</h2>
|
||||
{% if contract_totals %}
|
||||
<table class="table" style="margin-bottom: 0;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Contract</th>
|
||||
<th style="text-align: right;">Hours</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in contract_totals %}
|
||||
<tr>
|
||||
<td>{{ row.charge_number__contract__name }}</td>
|
||||
<td style="text-align: right;">{{ row.total_hours|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p style="color: var(--text-muted); margin: 0;">No contract totals for current filters.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card" style="padding: 1.25rem;">
|
||||
<h2 style="font-size: 1rem; margin: 0 0 1rem 0; color: var(--text-muted);">Hours by Charge Number</h2>
|
||||
{% if charge_number_totals %}
|
||||
<table class="table" style="margin-bottom: 0;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Charge Number</th>
|
||||
<th>Contract</th>
|
||||
<th style="text-align: right;">Hours</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in charge_number_totals %}
|
||||
<tr>
|
||||
<td>{{ row.charge_number__name|default:"—" }}</td>
|
||||
<td>{{ row.charge_number__contract__name }}</td>
|
||||
<td style="text-align: right;">{{ row.total_hours|floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p style="color: var(--text-muted); margin: 0;">No charge number totals for current filters.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin: -1rem 0 2rem 0; font-size: 0.95rem; color: var(--text-muted);">
|
||||
<strong style="color: var(--text-color);">Grand total:</strong> {{ grand_total|floatformat:2 }} hrs
|
||||
<span style="opacity: 0.75;">(all filtered rows, including entries without a charge number)</span>
|
||||
</p>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
|
||||
@@ -114,7 +114,7 @@ def contract_detail(request, contract_slug):
|
||||
has_dates = True
|
||||
start = cn.start_date.strftime("%Y-%m-%d")
|
||||
end = cn.end_date.strftime("%Y-%m-%d")
|
||||
slug_label = cn.slug or f"ID-{cn.id}"
|
||||
slug_label = cn.name or cn.slug or f"ID-{cn.id}"
|
||||
mermaid_gantt_lines.append(f" {slug_label} : {start}, {end}")
|
||||
|
||||
mermaid_gantt = None
|
||||
@@ -178,8 +178,72 @@ def timekeeping(request):
|
||||
|
||||
@user_passes_test(is_admin)
|
||||
def time_logs(request):
|
||||
logs = TimeCardCell.objects.all().order_by('-date', '-created')
|
||||
return render(request, 'financial/time_logs.html', {'logs': logs})
|
||||
logs = TimeCardCell.objects.select_related(
|
||||
'timeCard__employee__user',
|
||||
'charge_number__contract',
|
||||
).order_by('-date', '-created')
|
||||
|
||||
employee_ids = []
|
||||
for raw in request.GET.getlist('employee'):
|
||||
if raw:
|
||||
try:
|
||||
employee_ids.append(int(raw))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
month = request.GET.get('month')
|
||||
contract_id = request.GET.get('contract')
|
||||
charge_number_id = request.GET.get('charge_number')
|
||||
|
||||
if employee_ids:
|
||||
logs = logs.filter(timeCard__employee_id__in=employee_ids)
|
||||
if month:
|
||||
try:
|
||||
year, mon = month.split('-', 1)
|
||||
logs = logs.filter(date__year=int(year), date__month=int(mon))
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
if contract_id:
|
||||
logs = logs.filter(charge_number__contract_id=contract_id)
|
||||
if charge_number_id:
|
||||
logs = logs.filter(charge_number_id=charge_number_id)
|
||||
|
||||
charge_numbers = ChargeNumber.objects.select_related('contract').order_by('contract__name', 'name')
|
||||
if contract_id:
|
||||
charge_numbers = charge_numbers.filter(contract_id=contract_id)
|
||||
|
||||
contract_totals = (
|
||||
logs.filter(charge_number__isnull=False)
|
||||
.values('charge_number__contract_id', 'charge_number__contract__name')
|
||||
.annotate(total_hours=Sum('hour'))
|
||||
.order_by('charge_number__contract__name')
|
||||
)
|
||||
charge_number_totals = (
|
||||
logs.filter(charge_number__isnull=False)
|
||||
.values(
|
||||
'charge_number_id',
|
||||
'charge_number__name',
|
||||
'charge_number__contract__name',
|
||||
)
|
||||
.annotate(total_hours=Sum('hour'))
|
||||
.order_by('charge_number__contract__name', 'charge_number__name')
|
||||
)
|
||||
grand_total = logs.aggregate(total_hours=Sum('hour'))['total_hours'] or 0.0
|
||||
|
||||
return render(request, 'financial/time_logs.html', {
|
||||
'logs': logs,
|
||||
'employees': Employee.objects.select_related('user').order_by('user__last_name', 'user__first_name'),
|
||||
'contracts': Contract.objects.order_by('name'),
|
||||
'charge_numbers': charge_numbers,
|
||||
'contract_totals': contract_totals,
|
||||
'charge_number_totals': charge_number_totals,
|
||||
'grand_total': grand_total,
|
||||
'filters': {
|
||||
'employees': [str(eid) for eid in employee_ids],
|
||||
'month': month or '',
|
||||
'contract': contract_id or '',
|
||||
'charge_number': charge_number_id or '',
|
||||
},
|
||||
})
|
||||
|
||||
@user_passes_test(is_admin)
|
||||
def edit_time_log(request, log_id):
|
||||
|
||||
@@ -8,24 +8,58 @@
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
|
||||
<h2 class="section-title" style="margin-bottom: 0;">Backlog</h2>
|
||||
<div>
|
||||
<a href="{% url 'planning:board_view' %}" class="btn" style="padding: 0.5rem 1rem; border-radius: 8px; margin-right: 1rem; background: var(--surface-color); color: var(--text-color); border: 1px solid var(--primary-color);">View Board</a>
|
||||
<a href="{% url 'planning:board_view' %}" class="btn"
|
||||
style="padding: 0.5rem 1rem; border-radius: 8px; margin-right: 1rem; background: var(--surface-color); color: var(--text-color); border: 1px solid var(--primary-color);">View
|
||||
Board</a>
|
||||
{% if is_developer %}
|
||||
<button class="btn" id="openAddModalBtn" style="padding: 0.5rem 1rem; border-radius: 8px;">Add Item</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form method="get" action="{% url 'planning:backlog_view' %}" style="margin-bottom: 2rem; display: flex; gap: 1rem; align-items: center;">
|
||||
<label for="status" style="color: var(--text-muted);">Filter by Status:</label>
|
||||
<select name="status" id="status" class="form-control" style="width: 200px; margin-bottom: 0;" onchange="this.form.submit()">
|
||||
<form method="get" action="{% url 'planning:backlog_view' %}"
|
||||
style="margin-bottom: 2rem; display: flex; gap: 1rem; align-items: center; flex-wrap: wrap;">
|
||||
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||
<label for="status" style="color: var(--text-muted);">Status:</label>
|
||||
<select name="status" id="status" class="form-control" style="width: 150px; margin-bottom: 0;"
|
||||
onchange="this.form.submit()">
|
||||
<option value="">All</option>
|
||||
{% for status_value, status_label in statuses %}
|
||||
<option value="{{ status_value }}" {% if request.GET.status == status_value %}selected{% endif %}>{{ status_label }}</option>
|
||||
<option value="{{ status_value }}" {% if request.GET.status == status_value %}selected{% endif %}>{{
|
||||
status_label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||
<label for="contract" style="color: var(--text-muted);">Contract:</label>
|
||||
<select name="contract" id="contract" class="form-control" style="width: 200px; margin-bottom: 0;"
|
||||
onchange="this.form.submit()">
|
||||
<option value="">All</option>
|
||||
{% for contract in contracts %}
|
||||
<option value="{{ contract.id }}" {% if request.GET.contract == contract.id|stringformat:"i" %}selected{% endif %}>{{ contract.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
||||
<label for="charge_number" style="color: var(--text-muted);">Charge Number:</label>
|
||||
<select name="charge_number" id="charge_number" class="form-control" style="width: 200px; margin-bottom: 0;"
|
||||
onchange="this.form.submit()">
|
||||
<option value="">All</option>
|
||||
{% for cn in charge_numbers %}
|
||||
<option value="{{ cn.id }}" {% if request.GET.charge_number == cn.id|stringformat:"i" %}selected{% endif %}>{{ cn }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<a href="{% url 'planning:backlog_view' %}" class="btn"
|
||||
style="padding: 0.5rem 1rem; border-radius: 8px; background: transparent; border: 1px solid var(--text-muted); color: var(--text-muted);">Clear
|
||||
Filters</a>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive" style="background: var(--surface-color); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.05); padding: 1rem;">
|
||||
<div class="table-responsive"
|
||||
style="background: var(--surface-color); border-radius: 12px; border: 1px solid rgba(255, 255, 255, 0.05); padding: 1rem;">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -38,10 +72,21 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr style="cursor: pointer; transition: background 0.2s;" onmouseover="this.style.background='rgba(255,255,255,0.05)'" onmouseout="this.style.background='transparent'" onclick="showItemDetails({{ item.id }})">
|
||||
<tr style="cursor: pointer; transition: background 0.2s;"
|
||||
onmouseover="this.style.background='rgba(255,255,255,0.05)'"
|
||||
onmouseout="this.style.background='transparent'" onclick="showItemDetails({{ item.id }})">
|
||||
<td style="font-weight: 500; color: white;">{{ item.title }}</td>
|
||||
<td>{% if item.charge_number %}<span class="badge" style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">{{ item.charge_number.contract.name }} - {{ item.charge_number.slug }} ({{ item.charge_number.get_percent_complete|floatformat:0 }}%)</span>{% else %}-{% endif %}</td>
|
||||
<td><span class="badge" style="border: 1px solid var(--primary-color);">{{ item.get_status_display }}</span></td>
|
||||
<td>
|
||||
{% if item.charge_number %}<span class="badge"
|
||||
style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">{{
|
||||
item.charge_number }} ({{ item.charge_number.get_percent_complete|floatformat:0
|
||||
}}%)</span>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td><span class="badge" style="border: 1px solid var(--primary-color);">
|
||||
{{ item.get_status_display }}</span></td>
|
||||
<td style="color: var(--text-muted); font-size: 0.9rem;">{{ item.created_at|date:"M d, Y" }}</td>
|
||||
<td style="color: var(--text-muted); font-size: 0.9rem;">{{ item.updated_at|date:"M d, Y" }}</td>
|
||||
</tr>
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
padding: 2rem 0;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.kanban-column {
|
||||
background: rgba(26, 26, 26, 0.6);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
@@ -21,6 +22,7 @@
|
||||
min-height: 500px;
|
||||
transition: border-color 0.3s;
|
||||
}
|
||||
|
||||
.kanban-column h3 {
|
||||
margin-bottom: 1rem;
|
||||
color: var(--primary-color);
|
||||
@@ -30,9 +32,12 @@
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.kanban-items {
|
||||
min-height: 400px; /* For drop zone */
|
||||
min-height: 400px;
|
||||
/* For drop zone */
|
||||
}
|
||||
|
||||
.kanban-item {
|
||||
background: var(--surface-color);
|
||||
border: 1px solid rgba(0, 243, 255, 0.1);
|
||||
@@ -42,23 +47,28 @@
|
||||
cursor: grab;
|
||||
transition: transform 0.2s, box-shadow 0.2s;
|
||||
}
|
||||
|
||||
.kanban-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 5px 15px rgba(0, 243, 255, 0.2);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.kanban-item:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
.kanban-item-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.5rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.kanban-item-desc {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Modal Styles */
|
||||
.modal {
|
||||
display: none;
|
||||
@@ -71,6 +81,7 @@
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: var(--surface-color);
|
||||
margin: 10% auto;
|
||||
@@ -82,6 +93,7 @@
|
||||
color: var(--text-color);
|
||||
box-shadow: 0 0 30px rgba(0, 243, 255, 0.2);
|
||||
}
|
||||
|
||||
.close {
|
||||
color: var(--text-muted);
|
||||
float: right;
|
||||
@@ -89,9 +101,11 @@
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
color: var(--secondary-color);
|
||||
}
|
||||
|
||||
.badge {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
padding: 0.2rem 0.5rem;
|
||||
@@ -99,6 +113,7 @@
|
||||
font-size: 0.8rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (max-width: 968px) {
|
||||
.kanban-board {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -110,7 +125,9 @@
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 2rem;">
|
||||
<h2 class="section-title" style="margin-bottom: 0;">Planning Board</h2>
|
||||
<div>
|
||||
<a href="{% url 'planning:backlog_view' %}" class="btn" style="padding: 0.5rem 1rem; border-radius: 8px; margin-right: 1rem; background: var(--surface-color); color: var(--text-color); border: 1px solid var(--primary-color);">View Backlog</a>
|
||||
<a href="{% url 'planning:backlog_view' %}" class="btn"
|
||||
style="padding: 0.5rem 1rem; border-radius: 8px; margin-right: 1rem; background: var(--surface-color); color: var(--text-color); border: 1px solid var(--primary-color);">View
|
||||
Backlog</a>
|
||||
{% if is_developer %}
|
||||
<button class="btn" id="openAddModalBtn">Add Item</button>
|
||||
{% endif %}
|
||||
@@ -123,10 +140,13 @@
|
||||
<h3>Todo <span class="badge">{{ todo_items.count }}</span></h3>
|
||||
<div class="kanban-items" data-status="TODO">
|
||||
{% for item in todo_items %}
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}" data-id="{{ item.id }}">
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}"
|
||||
data-id="{{ item.id }}">
|
||||
<div class="kanban-item-title">{{ item.title }}</div>
|
||||
{% if item.charge_number %}
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge" style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">{{ item.charge_number.contract.name }} ({{ item.charge_number.slug }})</span></div>
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge"
|
||||
style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">
|
||||
{{ item.charge_number.contract.name }} ({{ item.charge_number }})</span></div>
|
||||
{% endif %}
|
||||
{% if item.description %}
|
||||
<div class="kanban-item-desc">{{ item.description|truncatechars:50 }}</div>
|
||||
@@ -141,10 +161,13 @@
|
||||
<h3>In Progress <span class="badge">{{ in_progress_items.count }}</span></h3>
|
||||
<div class="kanban-items" data-status="IN_PROGRESS">
|
||||
{% for item in in_progress_items %}
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}" data-id="{{ item.id }}">
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}"
|
||||
data-id="{{ item.id }}">
|
||||
<div class="kanban-item-title">{{ item.title }}</div>
|
||||
{% if item.charge_number %}
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge" style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">{{ item.charge_number.contract.name }} ({{ item.charge_number.slug }})</span></div>
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge"
|
||||
style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">
|
||||
{{ item.charge_number.contract.name }} ({{ item.charge_number }})</span></div>
|
||||
{% endif %}
|
||||
{% if item.description %}
|
||||
<div class="kanban-item-desc">{{ item.description|truncatechars:50 }}</div>
|
||||
@@ -159,10 +182,13 @@
|
||||
<h3>Done <span class="badge">{{ done_items.count }}</span></h3>
|
||||
<div class="kanban-items" data-status="DONE">
|
||||
{% for item in done_items %}
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}" data-id="{{ item.id }}">
|
||||
<div class="kanban-item" draggable="{% if is_developer %}true{% else %}false{% endif %}"
|
||||
data-id="{{ item.id }}">
|
||||
<div class="kanban-item-title">{{ item.title }}</div>
|
||||
{% if item.charge_number %}
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge" style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">{{ item.charge_number.contract.name }} ({{ item.charge_number.slug }})</span></div>
|
||||
<div style="margin-bottom: 0.5rem;"><span class="badge"
|
||||
style="background: rgba(188, 19, 254, 0.2); color: var(--secondary-color); border: 1px solid var(--secondary-color);">
|
||||
{{ item.charge_number.contract.name }} ({{ item.charge_number }})</span></div>
|
||||
{% endif %}
|
||||
{% if item.description %}
|
||||
<div class="kanban-item-desc">{{ item.description|truncatechars:50 }}</div>
|
||||
@@ -186,7 +212,8 @@
|
||||
<input type="text" name="title" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label style="color: var(--text-muted); margin-bottom: 0.5rem; display: block;">Charge Number (QBD)</label>
|
||||
<label style="color: var(--text-muted); margin-bottom: 0.5rem; display: block;">Charge Number
|
||||
(QBD)</label>
|
||||
<select name="charge_number" class="form-control">
|
||||
<option value="">-- No Charge Number --</option>
|
||||
{% for cn in qbd_charge_numbers %}
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<input type="hidden" name="next" id="editItemNext">
|
||||
<div class="form-group" style="margin-bottom: 1.5rem;">
|
||||
<label style="color: var(--text-muted); display: block; margin-bottom: 0.5rem;">Title</label>
|
||||
<input type="text" name="title" class="form-control" value="{{ item.title }}" style="font-size: 1.2rem; font-weight: bold; color: var(--primary-color);" required>
|
||||
<input type="text" name="title" class="form-control" value="{{ item.title }}"
|
||||
style="font-size: 1.2rem; font-weight: bold; color: var(--primary-color);" required>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; gap: 1rem; margin-bottom: 1.5rem;">
|
||||
@@ -22,7 +23,7 @@
|
||||
<select name="charge_number" class="form-control">
|
||||
<option value="">-- No Charge Number --</option>
|
||||
{% for cn in qbd_charge_numbers %}
|
||||
<option value="{{ cn.id }}" {% if item.charge_number_id == cn.id %}selected{% endif %}>{{ cn.contract.name }} - {{ cn.slug }}</option>
|
||||
<option value="{{ cn.id }}" {% if item.charge_number_id == cn.id %}selected{% endif %}>{{ cn }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
@@ -41,7 +42,10 @@
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button type="submit" class="btn" style="padding: 0.8rem 2rem;">Save Changes</button>
|
||||
<button type="button" class="btn" style="background: transparent; border: 1px solid #ff4444; color: #ff4444; padding: 0.8rem 2rem;" onclick="if(confirm('Are you sure you want to delete this ticket?')) document.getElementById('deleteItemForm').submit();">Delete Ticket</button>
|
||||
<button type="button" class="btn"
|
||||
style="background: transparent; border: 1px solid #ff4444; color: #ff4444; padding: 0.8rem 2rem;"
|
||||
onclick="if(confirm('Are you sure you want to delete this ticket?')) document.getElementById('deleteItemForm').submit();">Delete
|
||||
Ticket</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -54,13 +58,44 @@
|
||||
// Ensure form redirects to the current page upon save or delete
|
||||
document.getElementById('editItemNext').value = window.location.pathname;
|
||||
document.getElementById('deleteItemNext').value = window.location.pathname;
|
||||
|
||||
// Handle AJAX submission for editing
|
||||
const editForm = document.querySelector('form[action*="edit"]');
|
||||
if (editForm) {
|
||||
editForm.onsubmit = (e) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(editForm);
|
||||
fetch(editForm.action, {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
headers: {
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
'X-CSRFToken': formData.get('csrf_token')
|
||||
}
|
||||
}).then(res => res.json())
|
||||
.then(data => {
|
||||
if (data.status === 'success') {
|
||||
// Close modal and refresh the current page to show updates
|
||||
// (Alternatively, we could update the item in the DOM dynamically)
|
||||
location.reload();
|
||||
} else {
|
||||
alert('Error updating item: ' + (data.message || 'Unknown error'));
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
</script>
|
||||
{% else %}
|
||||
<h2 style="color: var(--primary-color); margin-bottom: 1rem;">{{ item.title }}</h2>
|
||||
<div style="margin-bottom: 1.5rem; display: flex; gap: 1rem; align-items: center;">
|
||||
<span style="background: var(--surface-color); padding: 0.3rem 0.6rem; border-radius: 4px; font-size: 0.8rem; border: 1px solid var(--secondary-color);">{{ item.get_status_display }}</span>
|
||||
<span
|
||||
style="background: var(--surface-color); padding: 0.3rem 0.6rem; border-radius: 4px; font-size: 0.8rem; border: 1px solid var(--secondary-color);">{{
|
||||
item.get_status_display }}</span>
|
||||
{% if item.charge_number %}
|
||||
<span style="background: rgba(188, 19, 254, 0.1); padding: 0.3rem 0.6rem; border-radius: 4px; font-size: 0.8rem; border: 1px solid var(--secondary-color); color: var(--secondary-color);">Charge Number: <strong>{{ item.charge_number.contract.name }} ({{ item.charge_number.slug }})</strong> ({{ item.charge_number.get_percent_complete|floatformat:0 }}% Complete)</span>
|
||||
<span
|
||||
style="background: rgba(188, 19, 254, 0.1); padding: 0.3rem 0.6rem; border-radius: 4px; font-size: 0.8rem; border: 1px solid var(--secondary-color); color: var(--secondary-color);">Charge
|
||||
Number: <strong>{{ item.charge_number.contract.name }} ({{ item.charge_number.slug }})</strong> ({{
|
||||
item.charge_number.get_percent_complete|floatformat:0 }}% Complete)</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div style="color: var(--text-color); line-height: 1.6; white-space: pre-wrap;">
|
||||
|
||||
@@ -7,25 +7,25 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}AI ML Operations, LLC{% endblock %}</title>
|
||||
<meta name="description"
|
||||
content="{% block meta_description %}AI ML Operations, LLC provides cutting-edge AI, Machine Learning, and Web Development solutions.{% endblock %}">
|
||||
content="{% block meta_description %}AI ML Operations, LLC — forward-deployed AI engineering. We embed with your team to build and deploy custom agentic workflows and production AI systems.{% endblock %}">
|
||||
|
||||
<!-- Open Graph / Facebook -->
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="og:title" content="{% block og_title %}AI ML Operations, LLC{% endblock %}">
|
||||
<meta property="og:description"
|
||||
content="{% block og_description %}AI ML Operations, LLC provides cutting-edge AI, Machine Learning, and Web Development solutions.{% endblock %}">
|
||||
content="{% block og_description %}Forward-deployed AI engineering — custom agentic workflows deployed in your environment.{% endblock %}">
|
||||
<meta property="og:image"
|
||||
content="{% block og_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'public/img/favicon.jpg' %}{% endblock %}">
|
||||
content="{% block og_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'public/img/logo.png' %}{% endblock %}">
|
||||
|
||||
<!-- Twitter -->
|
||||
<meta property="twitter:card" content="summary_large_image">
|
||||
<meta property="twitter:url" content="{{ request.build_absolute_uri }}">
|
||||
<meta property="twitter:title" content="{% block twitter_title %}AI ML Operations, LLC{% endblock %}">
|
||||
<meta property="twitter:description"
|
||||
content="{% block twitter_description %}AI ML Operations, LLC provides cutting-edge AI, Machine Learning, and Web Development solutions.{% endblock %}">
|
||||
content="{% block twitter_description %}Forward-deployed AI engineering — custom agentic workflows deployed in your environment.{% endblock %}">
|
||||
<meta property="twitter:image"
|
||||
content="{% block twitter_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'public/img/favicon.jpg' %}{% endblock %}">
|
||||
content="{% block twitter_image %}{{ request.scheme }}://{{ request.get_host }}{% static 'public/img/logo.png' %}{% endblock %}">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
<!-- Custom CSS -->
|
||||
<link href="{% static 'public/css/style.css' %}" rel="stylesheet">
|
||||
<link rel="icon" type="image/xicon" href="{% static 'public/img/favicon.jpg' %}">
|
||||
<link rel="icon" type="image/png" href="{% static 'public/img/favicon.png' %}">
|
||||
|
||||
{% if not debug %}
|
||||
<script async defer src="https://tianji.aimloperations.com/tracker.js"
|
||||
@@ -47,8 +47,7 @@
|
||||
<!-- Navigation Bar -->
|
||||
<nav>
|
||||
<a href="{% url 'public_index' %}" class="brand-logo">
|
||||
AI ML<span class="text-cyber-cyan"> OPERATIONS</span>
|
||||
|
||||
<img src="{% static 'public/img/logo.png' %}" alt="AI ML Operations" class="brand-logo-img" width="243" height="28">
|
||||
</a>
|
||||
<button class="mobile-menu-btn" aria-label="Menu">☰</button>
|
||||
<ul class="nav-links">
|
||||
@@ -56,32 +55,37 @@
|
||||
class="{% if request.resolver_match.url_name == 'public_index' %}active{% endif %}">Home</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#"
|
||||
class="{% if request.resolver_match.url_name in 'ai_education,ai_sensor,bot,chat,computers,file_hosting,ml_model,web_design' %}active{% endif %}">Services</a>
|
||||
class="{% if request.resolver_match.url_name in 'forward_deployed,ai_education,ai_sensor,bot,chat,computers,file_hosting,ml_model,web_design' %}active{% endif %}">Services</a>
|
||||
<ul class="dropdown-content">
|
||||
<li><a href="{% url 'ai_education' %}">Education</a></li>
|
||||
<li><a href="{% url 'ai_sensor' %}">Sensors</a></li>
|
||||
<li><a href="{% url 'bot' %}">Bots</a></li>
|
||||
<li><a href="{% url 'forward_deployed' %}">Forward-Deployed AI</a></li>
|
||||
<li><a href="{% url 'bot' %}">AI Agents</a></li>
|
||||
<li><a href="{% url 'ml_model' %}">ML Models</a></li>
|
||||
<li><a href="{% url 'chat' %}">Chat</a></li>
|
||||
<li><a href="{% url 'ai_sensor' %}">Sensors</a></li>
|
||||
<li><a href="{% url 'ai_education' %}">Education</a></li>
|
||||
<li><a href="{% url 'computers' %}">Hardware</a></li>
|
||||
<li><a href="{% url 'file_hosting' %}">Hosting</a></li>
|
||||
<li><a href="{% url 'ml_model' %}">ML Models</a></li>
|
||||
<li><a href="{% url 'web_design' %}">Web Design</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="{% url 'contact' %}"
|
||||
class="{% if request.resolver_match.url_name == 'contact' %}active{% endif %}">Contact</a></li>
|
||||
{% if user.is_authenticated %}
|
||||
<li><a href="{% url 'planning:board_view' %}" class="{% if 'planning' in request.path %}active{% endif %}">Planning</a></li>
|
||||
<li><a href="{% url 'financial_index' %}" class="{% if 'financial' in request.path %}active{% endif %}">Financials</a></li>
|
||||
<li><a href="{% url 'planning:board_view' %}"
|
||||
class="{% if 'planning' in request.path %}active{% endif %}">Planning</a></li>
|
||||
<li><a href="{% url 'financial_index' %}"
|
||||
class="{% if 'financial' in request.path %}active{% endif %}">Financials</a></li>
|
||||
<li class="dropdown" id="user-profile-dropdown">
|
||||
<a href="#" class="profile-icon-link" title="{{ user.get_full_name|default:user.username }}">
|
||||
<svg class="profile-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<svg class="profile-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||||
stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="8" r="4" />
|
||||
<path d="M4 21v-1a6 6 0 0 1 12 0v1" />
|
||||
</svg>
|
||||
</a>
|
||||
<ul class="dropdown-content profile-dropdown-content">
|
||||
<li class="profile-name-item">{{ user.get_full_name|default:user.username }}</li>
|
||||
<li><a href="{% url 'change_password' %}">Change Password</a></li>
|
||||
<li>
|
||||
<form action="{% url 'logout' %}" method="post" style="margin: 0;">
|
||||
{% csrf_token %}
|
||||
@@ -91,7 +95,9 @@
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li><a href="{% url 'login' %}" class="btn text-cyber-cyan" style="border: 1px solid var(--primary-color); padding: 0.4rem 1rem; border-radius: 4px; margin-left: 1rem;">Sign In</a></li>
|
||||
<li><a href="{% url 'login' %}" class="btn"
|
||||
style="border: 1px solid var(--primary-color); padding: 0.4rem 1rem; border-radius: 4px; margin-left: 1rem; color: #000;">Sign
|
||||
In</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
@@ -104,8 +110,9 @@
|
||||
<!-- Footer -->
|
||||
<footer class="footer">
|
||||
<div class="container">
|
||||
<p class="footer-text">© 2023 -
|
||||
<script>document.write(new Date().getFullYear());</script> AI ML Operations, LLC. All rights reserved.
|
||||
<p class="footer-text">AI ML Operations, LLC — Forward-deployed AI engineering.</p>
|
||||
<p class="footer-text footer-text--muted">© 2023 -
|
||||
<script>document.write(new Date().getFullYear());</script> All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@@ -1,55 +1,97 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Agentic Bots - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}Intelligent agentic bots for automation and engagement. AI ML Operations, LLC develops
|
||||
custom bots for Telegram and other platforms.{% endblock %}
|
||||
{% block title %}AI Agents & Automation - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}Custom proprietary AI agents for workflow automation and conversations. Web-hosted, scalable, with real-time performance analytics by AI ML Operations, LLC.{% endblock %}
|
||||
{% block og_title %}AI Agents & Automation - AI ML Operations, LLC{% endblock %}
|
||||
{% block og_description %}Proprietary web-hosted AI agents with scalable hosting and real-time performance analytics.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Hero Section -->
|
||||
<div class="hero-section" style="height: 40vh; min-height: 300px;">
|
||||
<div class="hero-section" style="height: 45vh; min-height: 320px;">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Agentic Bots</h1>
|
||||
<p class="hero-subtitle">Intelligent Bots for Automation and Engagement</p>
|
||||
<h1 class="hero-title">AI Agents & Automation</h1>
|
||||
<p class="hero-subtitle hero-subtitle--wide">
|
||||
Proprietary agents built for your workflows and conversations—hosted, scalable, and observable.
|
||||
</p>
|
||||
<div class="hero-cta">
|
||||
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn">Build Your Agent</a>
|
||||
<a href="{% url 'forward_deployed' %}" class="btn btn-secondary">Forward-Deployed AI</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- About Agentic Bots Section -->
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">About Agentic Bots</h2>
|
||||
<p style="text-align: center; max-width: 800px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
At AI ML Operations, we create intelligent, agentic bots designed to automate tasks, engage users, and streamline
|
||||
workflows. Our bots currently integrate seamlessly with Telegram, but we can customize them to suit your specific
|
||||
platform or needs. Whether you need a bot for customer support, data collection, or process automation, we deliver
|
||||
solutions that are reliable, scalable, and easy to use.
|
||||
<h2 class="section-title">About Our AI Agents</h2>
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
We design and deploy proprietary AI agents that automate tasks, support customers, and orchestrate multi-step workflows.
|
||||
Agents are web-hosted and built to scale with your business. As part of our forward-deployed engagements—or as standalone
|
||||
products—we integrate with your platforms (including Telegram and custom channels) and give you visibility into how
|
||||
agents perform in the real world.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Features Section -->
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">What We Offer</h2>
|
||||
<div class="card-grid">
|
||||
<div class="card" style="text-align: center;">
|
||||
<h5 class="card-title">Custom Bot Development</h5>
|
||||
<p class="card-text">Tailored bots designed to meet your unique business requirements.</p>
|
||||
<h5 class="card-title">Custom Agent Development</h5>
|
||||
<p class="card-text">Agents tailored to your data, policies, and workflows—not generic chatbots.</p>
|
||||
</div>
|
||||
<div class="card" style="text-align: center;">
|
||||
<h5 class="card-title">Web-Hosted & Scalable</h5>
|
||||
<p class="card-text">Production hosting and maintenance so your agents stay available 24/7.</p>
|
||||
</div>
|
||||
<div class="card" style="text-align: center;">
|
||||
<h5 class="card-title">Analytics & Insights</h5>
|
||||
<p class="card-text">Real-time performance metrics and conversation analytics so you can improve outcomes continuously.</p>
|
||||
</div>
|
||||
<div class="card" style="text-align: center;">
|
||||
<h5 class="card-title">Platform Integration</h5>
|
||||
<p class="card-text">Bots that integrate with Telegram or other platforms of your choice.</p>
|
||||
</div>
|
||||
<div class="card" style="text-align: center;">
|
||||
<h5 class="card-title">Hosting & Maintenance</h5>
|
||||
<p class="card-text">We host and maintain your bots, ensuring they run smoothly 24/7.</p>
|
||||
<p class="card-text">Telegram, web embeds, APIs, and custom channels connected to your operations.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Applications Section -->
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">How We Build</h2>
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto 2.5rem; color: var(--text-muted); font-size: 1.05rem;">
|
||||
Robust agentic orchestration—not simple API wrappers. Representative stack:
|
||||
</p>
|
||||
<div class="card-grid card-grid--stack">
|
||||
<div class="card">
|
||||
<span class="card-title">LangChain & LangGraph</span>
|
||||
<p class="card-text">Stateful agent workflows and multi-step orchestration.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">LangSmith</span>
|
||||
<p class="card-text">Tracing, evaluation, and observability for LLM pipelines.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Pydantic AI</span>
|
||||
<p class="card-text">Type-safe agents with structured inputs and outputs.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Pipecat AI</span>
|
||||
<p class="card-text">Real-time voice and multimodal conversation pipelines.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Model Context Protocol (MCP)</span>
|
||||
<p class="card-text">Standardized tool and data access for agent systems.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Local & Self-Hosted LLM Inference</span>
|
||||
<p class="card-text">On-prem and air-gapped deployment for sensitive workloads.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Applications</h2>
|
||||
<div class="card-grid">
|
||||
@@ -57,30 +99,29 @@ custom bots for Telegram and other platforms.{% endblock %}
|
||||
<img src="{% static 'public/img/bot/card-1.jpg' %}" alt="Customer Support"
|
||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
||||
<span class="card-title">Customer Support</span>
|
||||
<p class="card-text">Automate responses and provide instant support to your customers.</p>
|
||||
<p class="card-text">Automate responses and escalate intelligently when human judgment is required.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<img src="{% static 'public/img/bot/card-2.jpg' %}" alt="Data Collection"
|
||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
||||
<span class="card-title">Data Collection</span>
|
||||
<p class="card-text">Gather and organize data efficiently using intelligent bots.</p>
|
||||
<p class="card-text">Gather and structure data from conversations and workflows automatically.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<img src="{% static 'public/img/bot/card-3.jpg' %}" alt="Process Automation"
|
||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
||||
<span class="card-title">Process Automation</span>
|
||||
<p class="card-text">Streamline workflows and reduce manual effort with automated bots.</p>
|
||||
<p class="card-text">Multi-step agent workflows that reduce manual effort across departments.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Call to Action Section -->
|
||||
<div class="section" style="text-align: center;">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Ready to Automate?</h2>
|
||||
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to create your custom agentic bot.</p>
|
||||
<a href="{% url 'contact' %}" class="btn">Get Started</a>
|
||||
<p class="hero-subtitle" style="margin-bottom: 2rem;">Tell us the workflow you want an agent to own—we will design, deploy, and monitor it.</p>
|
||||
<a href="{% url 'contact' %}?subject=AI%20Agents" class="btn">Get Started</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
74
company_site/public/templates/public/change_password.html
Normal file
74
company_site/public/templates/public/change_password.html
Normal file
@@ -0,0 +1,74 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Change Password - AI ML Operations, LLC{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="section">
|
||||
<div class="container" style="max-width: 600px; margin: 0 auto; padding: 4rem 1rem;">
|
||||
<h2 class="section-title">Change Password</h2>
|
||||
|
||||
<div class="card"
|
||||
style="padding: 2rem; background: var(--card-bg); border-radius: 8px; border: 1px solid var(--border-color);">
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert {% if message.tags %}alert-{{ message.tags }}{% endif %}"
|
||||
style="margin-bottom: 1rem; padding: 1rem; border-radius: 4px; {% if message.tags == 'error' %}background-color: rgba(255, 0, 0, 0.1); color: #ff4444; border: 1px solid #ff4444;{% else %}background-color: rgba(0, 255, 255, 0.1); color: var(--cyber-cyan); border: 1px solid var(--cyber-cyan);{% endif %}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
{% for field in form %}
|
||||
<div class="form-group" style="margin-bottom: 1.5rem;">
|
||||
<label for="{{ field.id_for_label }}"
|
||||
style="display: block; margin-bottom: 0.5rem; color: var(--text-color);">{{ field.label
|
||||
}}</label>
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<small class="form-text"
|
||||
style="display: block; margin-top: 0.25rem; color: var(--text-muted); font-size: 0.85rem;">{{
|
||||
field.help_text }}</small>
|
||||
{% endif %}
|
||||
{% for error in field.errors %}
|
||||
<p class="error-message" style="margin-top: 0.25rem; color: #ff4444; font-size: 0.85rem;">{{ error
|
||||
}}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div style="margin-top: 2rem;">
|
||||
<button type="submit" class="btn"
|
||||
style="width: 100%; padding: 0.75rem; background: var(--primary-color); color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; background: linear-gradient(90deg, #00d4ff 0%, #0099ff 100%);">Update
|
||||
Password</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div style="margin-top: 1.5rem; text-align: center;">
|
||||
<a href="{% url 'public_index' %}"
|
||||
style="color: var(--text-muted); text-decoration: none; font-size: 0.9rem;">← Back to Home</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.form-group input {
|
||||
width: 100%;
|
||||
padding: 0.75rem;
|
||||
background: #1a1a1a;
|
||||
border: 1px solid #333;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-group input:focus {
|
||||
outline: none;
|
||||
border-color: var(--cyber-cyan);
|
||||
box-shadow: 0 0 5px rgba(0, 255, 255, 0.3);
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
@@ -2,8 +2,7 @@
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Secure AI Chat - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}Secure, private AI chat solution by AI ML Operations, LLC. Host locally, analyze files
|
||||
securely, and keep your data safe.{% endblock %}
|
||||
{% block meta_description %}Secure, hosted AI chat by AI ML Operations, LLC—an example of scalable, privacy-first AI products with production deployment.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
@@ -12,8 +11,8 @@ securely, and keep your data safe.{% endblock %}
|
||||
<div class="product-hero-content">
|
||||
<h1 class="product-hero-title">Your Private, Secure AI Workspace</h1>
|
||||
<p class="product-hero-subtitle">
|
||||
Experience the power of a locally hosted Large Language Model.
|
||||
Keep your data safe, analyze files securely, and never worry about third-party access.
|
||||
A production-ready, hosted LLM workspace—built the way we deliver forward-deployed systems: scalable, observable, and
|
||||
designed to keep your data under your control.
|
||||
</p>
|
||||
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
||||
<a href="https://chat.aimloperations.com" class="btn">Launch Chat</a>
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Contact Us - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}Get in touch with AI ML Operations, LLC. Contact us for AI solutions, web design, hosting,
|
||||
and more. We'd love to hear from you.{% endblock %}
|
||||
{% block meta_description %}Tell AI ML Operations about your operational bottleneck. Forward-deployed AI engineering, custom agents, and production ML deployments.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Hero Section -->
|
||||
<div class="hero-section" style="height: 40vh; min-height: 300px;">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Get in Touch</h1>
|
||||
<p class="hero-subtitle">We'd love to hear from you.</p>
|
||||
<p class="hero-subtitle hero-subtitle--wide">Describe the workflow or bottleneck you want to automate—we will help you scope a forward-deployed solution.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -46,11 +45,11 @@ and more. We'd love to hear from you.{% endblock %}
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="subject" placeholder="Subject">
|
||||
<input type="text" class="form-control" name="subject" id="contact-subject" placeholder="Subject" value="{{ request.GET.subject|default:'' }}">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<textarea name="message" class="form-control" rows="5" placeholder="Your message"></textarea>
|
||||
<textarea name="message" class="form-control" rows="5" placeholder="What workflow is costing you the most time? What systems does it touch?"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
152
company_site/public/templates/public/forward_deployed.html
Normal file
152
company_site/public/templates/public/forward_deployed.html
Normal file
@@ -0,0 +1,152 @@
|
||||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Forward-Deployed AI Engineering - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}AI ML Operations embeds with your team to architect, build, and deploy custom AI workflows and agentic automation in your environment—not slide decks.{% endblock %}
|
||||
{% block og_title %}Forward-Deployed AI Engineering - AI ML Operations, LLC{% endblock %}
|
||||
{% block og_description %}Embed with your team. Map bottlenecks. Build and deploy production AI workflows in your stack.{% endblock %}
|
||||
{% block twitter_title %}Forward-Deployed AI Engineering - AI ML Operations, LLC{% endblock %}
|
||||
{% block twitter_description %}Embed with your team. Map bottlenecks. Build and deploy production AI workflows in your stack.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="hero-section" style="height: 50vh; min-height: 360px;">
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">Forward-Deployed AI</h1>
|
||||
<p class="hero-subtitle hero-subtitle--wide">
|
||||
We embed with your team to architect, build, and deploy custom AI workflows that solve real operational bottlenecks.
|
||||
</p>
|
||||
<div class="hero-cta">
|
||||
<a href="{% url 'bot' %}" class="btn btn-secondary">AI Agents & Automation</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">What Is Forward-Deployed AI?</h2>
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
Instead of handing you a strategy deck and walking away, we work inside your organization—onsite or embedded remotely.
|
||||
We map messy, real-world workflows, integrate with your existing systems, and ship production automation that your team
|
||||
can run day to day. You get faster time-to-value without hiring a full-time specialized AI engineering team.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">How We Work</h2>
|
||||
<div class="card-grid card-grid--steps">
|
||||
<div class="card">
|
||||
<span class="card-step-num">01</span>
|
||||
<span class="card-title">Embed</span>
|
||||
<p class="card-text">Join your team to understand operations, stakeholders, and constraints—not just the tech stack.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">02</span>
|
||||
<span class="card-title">Map</span>
|
||||
<p class="card-text">Audit workflows, data sources, and integration points. Identify where AI removes friction.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">03</span>
|
||||
<span class="card-title">Build</span>
|
||||
<p class="card-text">Design agentic workflows, APIs, and orchestration tailored to your environment and security needs.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">04</span>
|
||||
<span class="card-title">Deploy</span>
|
||||
<p class="card-text">Ship to production with monitoring, documentation, and handoff so the system keeps running after we leave.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<span class="card-step-num">05</span>
|
||||
<span class="card-title">Monitor</span>
|
||||
<p class="card-text">Track performance, refine workflows, and iterate for continuous improvement.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">06</span>
|
||||
<span class="card-title">Handoff</span>
|
||||
<p class="card-text">Transfer ownership and documentation to your team for ongoing maintenance.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">What We Deliver</h2>
|
||||
<div class="card-grid">
|
||||
<div class="card">
|
||||
<h5 class="card-title">Workflow Automation</h5>
|
||||
<p class="card-text">Multi-step agentic pipelines that connect LLMs, tools, and your internal systems—not one-off chat wrappers.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h5 class="card-title">Deep Integrations</h5>
|
||||
<p class="card-text">CRM, ticketing, databases, document stores, and custom APIs wired into solutions that fit how you already work.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h5 class="card-title">Enterprise-Ready Architecture</h5>
|
||||
<p class="card-text">Self-hosted and air-gapped options, sensitive-data handling, and architectures designed with compliance-minded teams in mind.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Technical Stack</h2>
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto 2.5rem; color: var(--text-muted); font-size: 1.05rem;">
|
||||
We build robust, observable agent systems—not demos. Representative tools and frameworks we use:
|
||||
</p>
|
||||
<div class="card-grid card-grid--stack">
|
||||
<div class="card">
|
||||
<span class="card-title">LangChain & LangGraph</span>
|
||||
<p class="card-text">Stateful agent workflows and multi-step orchestration.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">LangSmith</span>
|
||||
<p class="card-text">Tracing, evaluation, and observability for LLM pipelines.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Pydantic AI</span>
|
||||
<p class="card-text">Type-safe agents with structured inputs and outputs.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Pipecat AI</span>
|
||||
<p class="card-text">Real-time voice and multimodal conversation pipelines.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Model Context Protocol (MCP)</span>
|
||||
<p class="card-text">Standardized tool and data access for agent systems.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">Local & Self-Hosted LLM Inference</span>
|
||||
<p class="card-text">On-prem and air-gapped deployment for sensitive workloads.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-title">n8n</span>
|
||||
<p class="card-text">Workflow automation connecting APIs, triggers, and internal systems.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Who This Is For</h2>
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
Leaders who have access to LLMs but struggle to wire them into daily operations. Teams suffering from “AI fatigue”—lots of
|
||||
pilots, little production impact. Organizations that need an engineer in the trenches, not another advisory engagement.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section" style="text-align: center;">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Ready to Deploy?</h2>
|
||||
<p class="hero-subtitle" style="margin-bottom: 2rem;">Tell us the workflow that is costing you the most time. We will help you automate it.</p>
|
||||
<div class="hero-cta" style="margin-top: 0;">
|
||||
<a href="{% url 'contact' %}?subject=Forward-Deployed%20AI" class="btn">Start a Conversation</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
143
company_site/public/templates/public/index.html
Executable file
143
company_site/public/templates/public/index.html
Executable file
@@ -0,0 +1,143 @@
|
||||
<!doctype html>
|
||||
{% load static %}
|
||||
<html lang="en"">
|
||||
<head>
|
||||
<title>AI/ML Operations, LLC</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<link rel="icon" type="image/xicon" href="{% static 'public/img/logo.png' %}">
|
||||
<body>
|
||||
<header>
|
||||
<div class="page-header text-light" style="background-image: url({% static 'public/img/background_w_logo.png' %}); background-repeat: no-repeat; background-size: 100% 100%; background-attachment: fixed;" >
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="row" style="text-align: center;">
|
||||
<div style="height: 60vh; padding: 30vh">
|
||||
<h1 > </h1>
|
||||
<!-- <p>Taking AI and ML from concept to Production</p> -->
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
<section class="bg-light text-dark" >
|
||||
<div class="container" style="text-align: center; height: 20vh; padding: 7vh">
|
||||
<div class="row">
|
||||
<h2><u>About Us</u></h2>
|
||||
<p>At AI/ML Operations, we're are commited to bringing production ready AI and ML to workflows. We have over a decad of experience create both ML models as well as AI algorithms to solve some of the the most demanding problem spaces.</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="bg-dark text-light" >
|
||||
<div class="container text-center">
|
||||
<h2><u>Services</u></h2>
|
||||
<div class="row justify-content-start">
|
||||
<div class="col-4">
|
||||
<h3>ML Model Creation</h3>
|
||||
<p>Unleash the power of data with our cutting-edge ML model creation services, tailored to your unique needs. From data preprocessing to model training and deployment, we streamline the process to unlock actionable insights.</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h3>Pipeline Optimization</h3>
|
||||
<p>Boost efficiency and productivity with our pipeline optimization solutions. We fine-tune your workflows, automate repetitive tasks, and integrate advanced analytics to optimize your business processes for peak performance.</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h3>AI Algorithms for Sensors</h3>
|
||||
<p>Harness the potential of sensor data with our advanced AI algorithms tailored for diverse applications. From real-time processing to post collection data analysis, our algorithms empower you to extract valuable insights, optimize processes, and drive innovation.</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h3>Web Design</h3>
|
||||
<p>Elevate your online presence with captivating web design that blends creativity with functionality. Our expert designers craft visually stunning websites that engage your audience and drive conversions, ensuring a seamless user experience across all devices.</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h3>File Hosting</h3>
|
||||
<p>Securely store and share your files with ease using our reliable file hosting platform. With robust encryption and flexible access controls, you can confidently manage your data, collaborate seamlessly, and streamline your workflow.</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<h3>App Virtualization</h3>
|
||||
<p>Transform your software delivery with our app virtualization solutions, enabling seamless access to applications from any device, anywhere. Experience enhanced flexibility, scalability, and security as we optimize your IT infrastructure for the digital age.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<section class="bg-light text-dark" >
|
||||
<div class="container" style="text-align: center; height: 20vh; padding: 7vh">
|
||||
<div class="row">
|
||||
<h2>Partners</h2>
|
||||
<div class="col-12">
|
||||
<img src="{% static 'public/img/ansys_logo.png' %}" alt="Ansys" height="100" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="bg-dark text-light">
|
||||
<div class="container" style="padding-top: 1rem; padding-bottom: 1rem;">
|
||||
<h2 >Contact Us</h2>
|
||||
<form action="{% url 'contact' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<div class="row">
|
||||
{% if success %}
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
<span class="alert-text"> We'll be in contact shortly!</span>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<span class="alert-text">{{ errors }}</span>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
<!-- <div class="col-md-6">
|
||||
<p> something</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
-->
|
||||
|
||||
<div class="form-group col-6" style="padding-left:1rem">
|
||||
<input type="email" class="form-control" name="email" placeholder="Your Email">
|
||||
</div>
|
||||
<div class="form-group col-6" style="padding-right:1rem">
|
||||
<input type="text" class="form-control" name="name" placeholder="Your Name">
|
||||
</div>
|
||||
<div class="form-group col-12" style="padding:1rem">
|
||||
<textarea name="message" type="text" class="form-control" rows="5" placeholder="Your message"></textarea>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
{% if capchaForm %}
|
||||
{{ capchaForm }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" class="btn btn-primary" value="Send">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
<footer>
|
||||
<div class="container">
|
||||
<div class="row" style="padding-top: 1rem;">
|
||||
<p> © <script>document.write( new Date().getFullYear() );</script> AI/ML Operations, LLC. ALL RIGHTS RESERVED</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</footer>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -18,11 +18,15 @@ supervised, unsupervised, and reinforcement learning.{% endblock %}
|
||||
<div class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">About ML Model Creation</h2>
|
||||
<p style="text-align: center; max-width: 800px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
At AI ML Operations, we specialize in creating custom machine learning models to solve complex problems across
|
||||
industries. With extensive expertise in supervised, unsupervised, and reinforcement learning, we design models
|
||||
that deliver accurate, scalable, and actionable insights. Whether you need predictive analytics, pattern
|
||||
recognition, or decision-making systems, we provide end-to-end solutions tailored to your needs.
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
We build custom machine learning models and deploy them inside your pipelines—not as disconnected experiments.
|
||||
With expertise in supervised, unsupervised, and reinforcement learning, we deliver models that integrate with
|
||||
forward-deployed engagements: predictive analytics, pattern recognition, and decision systems wired into how you operate.
|
||||
</p>
|
||||
<p style="text-align: center; max-width: 820px; margin: 1.5rem auto 0; color: var(--text-muted); font-size: 1.05rem;">
|
||||
Need full workflow automation around your models? See our
|
||||
<a href="{% url 'forward_deployed' %}" class="text-cyber-cyan">forward-deployed AI</a> and
|
||||
<a href="{% url 'bot' %}" class="text-cyber-cyan">AI agents</a> services.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Home - AI ML Operations, LLC{% endblock %}
|
||||
{% block meta_description %}AI ML Operations, LLC specializes in delivering production-ready AI and ML solutions, custom
|
||||
web design, and reliable hosting services.{% endblock %}
|
||||
{% block meta_description %}Forward-deployed AI engineering by AI ML Operations, LLC. We embed with your team to build and deploy custom agentic workflows, integrations, and production AI systems.{% endblock %}
|
||||
{% block og_title %}Forward-Deployed AI Engineering - AI ML Operations, LLC{% endblock %}
|
||||
{% block og_description %}We embed with your team to architect, build, and deploy custom AI workflows that solve real operational bottlenecks.{% endblock %}
|
||||
{% block twitter_title %}Forward-Deployed AI Engineering - AI ML Operations, LLC{% endblock %}
|
||||
{% block twitter_description %}We embed with your team to architect, build, and deploy custom AI workflows that solve real operational bottlenecks.{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<!-- Hero Section -->
|
||||
@@ -11,74 +14,152 @@ web design, and reliable hosting services.{% endblock %}
|
||||
<canvas id="hero-canvas"></canvas>
|
||||
<div class="hero-content">
|
||||
<h1 class="hero-title">AI ML Operations</h1>
|
||||
<p class="hero-subtitle">Taking concepts to production with intelligent solutions.</p>
|
||||
<p class="hero-subtitle hero-subtitle--wide">
|
||||
Forward-deployed AI engineering. We embed with your team to architect, build, and deploy custom AI workflows that solve complex operational bottlenecks.
|
||||
</p>
|
||||
<div class="hero-cta">
|
||||
<a href="{% url 'forward_deployed' %}" class="btn btn-secondary">See How We Deploy</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- About Us Section -->
|
||||
<div class="section">
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">About Us</h2>
|
||||
<p style="text-align: center; max-width: 800px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
At AI/ML Operations, we are dedicated to delivering production-ready AI and ML solutions that seamlessly integrate
|
||||
into your workflows. With over a decade of experience, we specialize in crafting cutting-edge machine learning
|
||||
models and AI algorithms to tackle the most complex and demanding challenges across various industries.
|
||||
<p style="text-align: center; max-width: 820px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
||||
At AI ML Operations, we deliver production-ready AI by embedding with your team—not handing off strategy decks.
|
||||
With over a decade of experience, we audit your real workflows, integrate with your infrastructure, and deploy
|
||||
agentic automation and machine learning where it creates measurable impact. You reduce time-to-value without building
|
||||
a full-time specialized AI engineering org from scratch.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- How We Work -->
|
||||
<!-- <div id="how-we-work" class="section" style="background: var(--surface-color);"> -->
|
||||
<div id="how-we-work" class="section" >
|
||||
<div class="container">
|
||||
<h2 class="section-title">How We Work</h2>
|
||||
<div class="card-grid card-grid--steps">
|
||||
<div class="card">
|
||||
<span class="card-step-num">01</span>
|
||||
<span class="card-title">Embed</span>
|
||||
<p class="card-text">Work alongside your team—onsite or remote—to understand operations and constraints.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">02</span>
|
||||
<span class="card-title">Map</span>
|
||||
<p class="card-text">Document workflows, data flows, and integration points across your stack.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">03</span>
|
||||
<span class="card-title">Build</span>
|
||||
<p class="card-text">Ship agents, orchestration, and integrations tailored to your environment.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">04</span>
|
||||
<span class="card-title">Deploy</span>
|
||||
<p class="card-text">Launch to production with monitoring, analytics, and a clean handoff.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">05</span>
|
||||
<span class="card-title">Monitor</span>
|
||||
<p class="card-text">Track performance, refine workflows, and iterate for continuous improvement.</p>
|
||||
</div>
|
||||
<div class="card">
|
||||
<span class="card-step-num">06</span>
|
||||
<span class="card-title">Handoff</span>
|
||||
<p class="card-text">Transfer ownership and documentation to your team for ongoing maintenance.</p>
|
||||
</div>
|
||||
</div>
|
||||
<p style="text-align: center; margin-top: 2.5rem;">
|
||||
<a href="{% url 'forward_deployed' %}" class="text-cyber-cyan" style="font-weight: 600;">Learn more about forward-deployed AI →</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workflow Transformations -->
|
||||
<!-- <div id="case-studies" class="section">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Workflow Transformations</h2>
|
||||
<p style="text-align: center; max-width: 720px; margin: -1.5rem auto 2.5rem; color: var(--text-muted); font-size: 1.05rem;">
|
||||
Real deployments, real outcomes—problem, deployment, and measurable results.
|
||||
</p>
|
||||
<div class="card-grid">
|
||||
<div class="card case-study-placeholder">
|
||||
<span class="case-study-label">Coming Soon</span>
|
||||
<h5 class="card-title">Client Workflow #1</h5>
|
||||
<p class="card-text"><strong>Problem:</strong> Manual process consuming hours each week.</p>
|
||||
<p class="card-text"><strong>Deployment:</strong> Embedded engineering, mapped data, built automated agent workflow.</p>
|
||||
<p class="card-text"><strong>Outcome:</strong> Testimonials and metrics arriving soon.</p>
|
||||
</div>
|
||||
<div class="card case-study-placeholder">
|
||||
<span class="case-study-label">Coming Soon</span>
|
||||
<h5 class="card-title">Client Workflow #2</h5>
|
||||
<p class="card-text"><strong>Problem:</strong> Disconnected tools and no path from LLM pilots to production.</p>
|
||||
<p class="card-text"><strong>Deployment:</strong> Integrated orchestration into existing operations.</p>
|
||||
<p class="card-text"><strong>Outcome:</strong> Case study in progress—check back shortly.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- Services Section -->
|
||||
<div class="section">
|
||||
<div class="section" style="background: var(--surface-color);">
|
||||
<div class="container">
|
||||
<h2 class="section-title">Our Services</h2>
|
||||
<p style="text-align: center; max-width: 640px; margin: -1.5rem auto 2rem; color: var(--text-muted);">
|
||||
Core delivery: embedded AI engineering and production agents.
|
||||
</p>
|
||||
<div class="card-grid">
|
||||
|
||||
<a href="{% url 'ai_sensor' %}" class="card">
|
||||
<span class="card-title">AI Sensor Algorithms</span>
|
||||
<p class="card-text">Develop intelligent algorithms that enhance sensor data processing, enabling real-time
|
||||
insights and decision-making for IoT and industrial applications.</p>
|
||||
<a href="{% url 'forward_deployed' %}" class="card card-featured">
|
||||
<span class="card-badge">Primary</span>
|
||||
<span class="card-title">Forward-Deployed AI</span>
|
||||
<p class="card-text">Embed with your team to map bottlenecks, build integrations, and deploy custom AI workflows in your environment.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'ai_education' %}" class="card">
|
||||
<span class="card-title">AI Education</span>
|
||||
<p class="card-text">Stay ahead of the AI technology curve with our AI Education classes. Classes are tailored
|
||||
to the audience familiarity with AI. Held in-person or virtual.</p>
|
||||
<a href="{% url 'bot' %}" class="card card-featured">
|
||||
<span class="card-badge">Primary</span>
|
||||
<span class="card-title">AI Agents & Automation</span>
|
||||
<p class="card-text">Proprietary web-hosted agents for your workflows and conversations—scalable hosting plus performance and real-time analytics.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'bot' %}" class="card">
|
||||
<span class="card-title">Bot Creation</span>
|
||||
<p class="card-text">Build agentic intelligent bots for workflow automation, customer support, and data
|
||||
collection for enhancing productivity and user experience.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'chat' %}" class="card">
|
||||
<span class="card-title">Chat</span>
|
||||
<p class="card-text">Chat is a closed-source Large Language Model (LLM) designed specifically for small and
|
||||
medium businesses.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'computers' %}" class="card">
|
||||
<span class="card-title">Computer Builds</span>
|
||||
<p class="card-text">Whether you're looking for a server for storage or compute or a workstation computer, we
|
||||
will build your next system for you.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'file_hosting' %}" class="card">
|
||||
<span class="card-title">File Hosting</span>
|
||||
<p class="card-text">Secure and scalable file hosting solutions to store, manage, and share your data with ease
|
||||
and confidence.</p>
|
||||
<a href="{% url 'web_design' %}" class="card">
|
||||
<span class="card-badge">Primary</span>
|
||||
<span class="card-title">Web Design and Hosting</span>
|
||||
<p class="card-text">Modern websites with reliable hosting for your online presence.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'ml_model' %}" class="card">
|
||||
<span class="card-title">ML Model Creation</span>
|
||||
<p class="card-text">Design and deploy custom machine learning models tailored to your business needs, ensuring
|
||||
accuracy, scalability, and performance.</p>
|
||||
<p class="card-text">Custom models designed for deployment inside your pipelines—not experiments that never ship.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'web_design' %}" class="card">
|
||||
<span class="card-title">Web Design and Hosting</span>
|
||||
<p class="card-text">Create visually stunning and highly functional websites, coupled with reliable hosting
|
||||
solutions to ensure your online presence is always at its best.</p>
|
||||
<a href="{% url 'chat' %}" class="card">
|
||||
<span class="card-title">Secure AI Chat</span>
|
||||
<p class="card-text">Hosted LLM workspace with privacy-first architecture—an example of how we deliver scalable, observable AI products.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'ai_sensor' %}" class="card">
|
||||
<span class="card-title">AI Sensor Algorithms</span>
|
||||
<p class="card-text">Intelligent algorithms for sensor data processing, real-time insights, and IoT applications.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'ai_education' %}" class="card">
|
||||
<span class="card-title">AI Education</span>
|
||||
<p class="card-text">Tailored AI training for your team—in-person or virtual.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'computers' %}" class="card">
|
||||
<span class="card-title">Computer Builds</span>
|
||||
<p class="card-text">Servers and workstations for compute, storage, and local inference workloads.</p>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'file_hosting' %}" class="card">
|
||||
<span class="card-title">File Hosting</span>
|
||||
<p class="card-text">Secure, scalable file hosting to store and share your data.</p>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -93,12 +93,15 @@ visually stunning, functional websites tailored to your business.{% endblock %}
|
||||
<h2 class="section-title">Web Hosting Plans</h2>
|
||||
|
||||
<!-- Pricing toggle -->
|
||||
<div style="text-align: center; margin-bottom: 3rem;">
|
||||
<label style="color: var(--text-color); font-size: 1.1rem; cursor: pointer;">
|
||||
Monthly
|
||||
<input type="checkbox" id="pricingToggle" style="margin: 0 10px;">
|
||||
Yearly
|
||||
<div class="pricing-toggle-wrap">
|
||||
<div class="pricing-toggle" role="group" aria-label="Billing period">
|
||||
<span class="pricing-toggle-label active" id="monthlyLabel">Monthly</span>
|
||||
<label class="pricing-switch" for="pricingToggle">
|
||||
<input type="checkbox" id="pricingToggle" role="switch" aria-labelledby="monthlyLabel yearlyLabel">
|
||||
<span class="pricing-switch-slider"></span>
|
||||
</label>
|
||||
<span class="pricing-toggle-label" id="yearlyLabel">Yearly</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Pricing cards -->
|
||||
@@ -139,12 +142,18 @@ visually stunning, functional websites tailored to your business.{% endblock %}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// Toggle functionality
|
||||
document.getElementById('pricingToggle').addEventListener('change', function () {
|
||||
const pricingToggle = document.getElementById('pricingToggle');
|
||||
const monthlyLabel = document.getElementById('monthlyLabel');
|
||||
const yearlyLabel = document.getElementById('yearlyLabel');
|
||||
|
||||
function updatePricing(isYearly) {
|
||||
const prices = document.querySelectorAll('.price');
|
||||
const periods = document.querySelectorAll('.billing-period');
|
||||
|
||||
if (this.checked) {
|
||||
monthlyLabel.classList.toggle('active', !isYearly);
|
||||
yearlyLabel.classList.toggle('active', isYearly);
|
||||
|
||||
if (isYearly) {
|
||||
prices[0].textContent = '100';
|
||||
periods[0].textContent = 'per year';
|
||||
prices[1].textContent = '150';
|
||||
@@ -155,6 +164,20 @@ visually stunning, functional websites tailored to your business.{% endblock %}
|
||||
prices[1].textContent = '15';
|
||||
periods[1].textContent = 'per month';
|
||||
}
|
||||
}
|
||||
|
||||
pricingToggle.addEventListener('change', function () {
|
||||
updatePricing(this.checked);
|
||||
});
|
||||
|
||||
monthlyLabel.addEventListener('click', function () {
|
||||
pricingToggle.checked = false;
|
||||
updatePricing(false);
|
||||
});
|
||||
|
||||
yearlyLabel.addEventListener('click', function () {
|
||||
pricingToggle.checked = true;
|
||||
updatePricing(true);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
2
company_site/public/urls.py
Normal file → Executable file
2
company_site/public/urls.py
Normal file → Executable file
@@ -11,7 +11,9 @@ urlpatterns = [
|
||||
path("ai_sensor", views.ai_sensor, name="ai_sensor"),
|
||||
path("file_hosting", views.file_hosting, name="file_hosting"),
|
||||
path("bot_creation", views.bot, name="bot"),
|
||||
path("forward-deployed-ai", views.forward_deployed, name="forward_deployed"),
|
||||
path("ml_model", views.ml_model, name="ml_model"),
|
||||
path("contact", views.contact, name="contact"),
|
||||
path("change_password", views.change_password, name="change_password"),
|
||||
path("preview_email/<int:pk>/", views.preview_email, name="preview_email")
|
||||
]
|
||||
25
company_site/public/views.py
Normal file → Executable file
25
company_site/public/views.py
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
|
||||
from django.http import HttpResponse
|
||||
from .models import Contact, EmailMessage
|
||||
@@ -8,6 +8,9 @@ from django.conf import settings
|
||||
from django.core.mail import send_mail
|
||||
from .forms import FormWithCaptcha
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.forms import PasswordChangeForm
|
||||
from django.contrib.auth import update_session_auth_hash
|
||||
from django.contrib import messages
|
||||
|
||||
def send_contact_email(email, subject, message):
|
||||
subject = "New Contact Request for AI ML Operations, LLC"
|
||||
@@ -46,6 +49,9 @@ def file_hosting(request):
|
||||
def bot(request):
|
||||
return render(request, "public/bot.html", {})
|
||||
|
||||
def forward_deployed(request):
|
||||
return render(request, "public/forward_deployed.html", {})
|
||||
|
||||
def ml_model(request):
|
||||
return render(request, "public/ml_model.html", {})
|
||||
|
||||
@@ -102,3 +108,20 @@ def contact(request):
|
||||
capcha = None if settings.DEBUG else FormWithCaptcha()
|
||||
return render(request, "public/contact.html", {'capchaForm': capcha})
|
||||
|
||||
@login_required
|
||||
def change_password(request):
|
||||
if request.method == 'POST':
|
||||
form = PasswordChangeForm(request.user, request.POST)
|
||||
if form.is_valid():
|
||||
user = form.save()
|
||||
update_session_auth_hash(request, user) # Important!
|
||||
messages.success(request, 'Your password was successfully updated!')
|
||||
return redirect('public_index')
|
||||
else:
|
||||
messages.error(request, 'Please correct the error below.')
|
||||
else:
|
||||
form = PasswordChangeForm(request.user)
|
||||
return render(request, 'public/change_password.html', {
|
||||
'form': form
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user