refactor all the things
This commit is contained in:
parent
8ed39690f1
commit
bb5cb708bd
36 changed files with 1563 additions and 931 deletions
|
@ -5,7 +5,7 @@
|
|||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Servala - The Cloud Native Services Hub</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href='{% static "css/bootstrap-icons.min.css" %}'>
|
||||
<link rel="stylesheet" type="text/css" href='{% static "css/bootstrap.min.css" %}'>
|
||||
<style>
|
||||
.rich-text-content {
|
||||
|
@ -26,7 +26,30 @@
|
|||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="{% url 'services:service_list' %}">Servala - The Cloud Native Services Hub</a>
|
||||
<a class="navbar-brand" href="{% url 'services:service_list' %}">Servala</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'services:service_list' %}active{% endif %}"
|
||||
href="{% url 'services:service_list' %}">Services</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'services:offering_list' %}active{% endif %}"
|
||||
href="{% url 'services:offering_list' %}">Service Offerings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'services:provider_list' %}active{% endif %}"
|
||||
href="{% url 'services:provider_list' %}">Cloud Providers</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if request.resolver_match.view_name == 'services:partner_list' %}active{% endif %}"
|
||||
href="{% url 'services:partner_list' %}">Consulting Partners</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
@ -35,6 +58,6 @@
|
|||
{% endblock %}
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="{% static "js/bootstrap.bundle.min.js" %}"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -9,16 +9,28 @@
|
|||
|
||||
<div class="mb-4">
|
||||
<h5>Service Details</h5>
|
||||
<p><strong>Provider:</strong> {{ service.cloud_provider.name }}</p>
|
||||
<p><strong>Plan:</strong> {{ selected_plan.name }}</p>
|
||||
{% if selected_offering %}
|
||||
<p><strong>Provider:</strong> {{ selected_offering.cloud_provider.name }}</p>
|
||||
{% endif %}
|
||||
{% if selected_plan %}
|
||||
<p><strong>Plan:</strong> {{ selected_plan.name }}</p>
|
||||
{% if selected_plan.prices.exists %}
|
||||
<p><strong>Pricing:</strong></p>
|
||||
<ul class="list-unstyled">
|
||||
{% for price in selected_plan.prices.all %}
|
||||
<li>{{ price.currency.symbol }}{{ price.price }} {{ price.currency.code }} per {{ price.term.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }}">
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="post">
|
||||
|
@ -28,9 +40,9 @@
|
|||
<label for="{{ form.name.id_for_label }}" class="form-label">Name</label>
|
||||
{{ form.name }}
|
||||
{% if form.name.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.name.errors }}
|
||||
</div>
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.name.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -38,9 +50,9 @@
|
|||
<label for="{{ form.company.id_for_label }}" class="form-label">Company</label>
|
||||
{{ form.company }}
|
||||
{% if form.company.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.company.errors }}
|
||||
</div>
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.company.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -48,9 +60,9 @@
|
|||
<label for="{{ form.email.id_for_label }}" class="form-label">Email</label>
|
||||
{{ form.email }}
|
||||
{% if form.email.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.email.errors }}
|
||||
</div>
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.email.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
@ -58,9 +70,9 @@
|
|||
<label for="{{ form.phone.id_for_label }}" class="form-label">Phone</label>
|
||||
{{ form.phone }}
|
||||
{% if form.phone.errors %}
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.phone.errors }}
|
||||
</div>
|
||||
<div class="invalid-feedback d-block">
|
||||
{{ form.phone.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
|
|
87
hub/services/templates/services/offering_detail.html
Normal file
87
hub/services/templates/services/offering_detail.html
Normal file
|
@ -0,0 +1,87 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-start mb-4">
|
||||
<div class="d-flex align-items-start">
|
||||
{% if offering.service.logo %}
|
||||
<img src="{{ offering.service.logo.url }}" alt="{{ offering.service.name }} logo" class="me-4"
|
||||
style="max-height: 120px; max-width: 240px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<div>
|
||||
<h2 class="card-title mb-2">{{ offering.service.name }}</h2>
|
||||
<h4 class="text-muted">
|
||||
on
|
||||
<a href="{{ offering.cloud_provider.get_absolute_url }}" class="text-decoration-none">
|
||||
{{ offering.cloud_provider.name }}
|
||||
</a>
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
{% if offering.cloud_provider.logo %}
|
||||
<img src="{{ offering.cloud_provider.logo.url }}"
|
||||
alt="{{ offering.cloud_provider.name }} logo"
|
||||
style="max-height: 80px; max-width: 160px; object-fit: contain;">
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="rich-text-content mb-4">
|
||||
{{ offering.description|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Plans -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-4">Available Plans</h3>
|
||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||
{% for plan in offering.plans.all %}
|
||||
<div class="col">
|
||||
<div class="card h-100 {% if plan.is_default %}border-primary{% endif %}">
|
||||
{% if plan.is_default %}
|
||||
<div class="card-header text-primary">
|
||||
Recommended Plan
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<h4 class="card-title mb-3">{{ plan.name }}</h4>
|
||||
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ plan.description|safe }}
|
||||
</div>
|
||||
|
||||
{% if plan.features %}
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ plan.features|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mb-3">
|
||||
{% for price in plan.prices.all %}
|
||||
<div class="mb-2">
|
||||
<strong>{{ price.currency.symbol }}{{ price.price }}</strong>
|
||||
{{ price.currency.code }} per {{ price.term.name }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<a href="{% url 'services:create_lead' offering.service.slug %}?offering={{ offering.id }}&plan={{ plan.id }}"
|
||||
class="btn btn-success">Select This Plan</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
No plans available yet.
|
||||
<a href="{% url 'services:create_lead' offering.service.slug %}?offering={{ offering.id }}"
|
||||
class="btn btn-success ms-3">Show Interest</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
151
hub/services/templates/services/offering_list.html
Normal file
151
hub/services/templates/services/offering_list.html
Normal file
|
@ -0,0 +1,151 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Filters</h5>
|
||||
<form method="get">
|
||||
<div class="mb-3">
|
||||
<label for="search" class="form-label">Search</label>
|
||||
<input type="text" class="form-control" id="search" name="search" value="{{ request.GET.search }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="cloud_provider" class="form-label">Cloud Provider</label>
|
||||
<select class="form-select" id="cloud_provider" name="cloud_provider">
|
||||
<option value="">All Providers</option>
|
||||
{% for provider in cloud_providers %}
|
||||
<option value="{{ provider.id }}" {% if request.GET.cloud_provider == provider.id|stringformat:'i' %}selected{% endif %}>
|
||||
{{ provider.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="category" class="form-label">Category</label>
|
||||
<select class="form-select" id="category" name="category">
|
||||
<option value="">All Categories</option>
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}" {% if request.GET.category == category.id|stringformat:'i' %}selected{% endif %}>
|
||||
{{ category.name }}
|
||||
</option>
|
||||
{% for subcategory in category.children.all %}
|
||||
<option value="{{ subcategory.id }}" {% if request.GET.category == subcategory.id|stringformat:'i' %}selected{% endif %}>
|
||||
{{ subcategory.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Apply Filters</button>
|
||||
<a href="{% url 'services:offering_list' %}" class="btn btn-secondary">Clear</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||
{% for offering in offerings %}
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start mb-3">
|
||||
<div class="me-3">
|
||||
{% if offering.service.logo %}
|
||||
<img src="{{ offering.service.logo.url }}"
|
||||
alt="{{ offering.service.name }}"
|
||||
style="max-height: 50px; max-width: 100px; object-fit: contain;">
|
||||
{% endif %}
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="card-title mb-1">
|
||||
<a href="{{ offering.service.get_absolute_url }}" class="text-decoration-none">
|
||||
{{ offering.service.name }}
|
||||
</a>
|
||||
</h5>
|
||||
<div class="d-flex align-items-center">
|
||||
{% if offering.cloud_provider.logo %}
|
||||
<a href="{{ offering.cloud_provider.get_absolute_url }}" class="me-2">
|
||||
<img src="{{ offering.cloud_provider.logo.url }}"
|
||||
alt="{{ offering.cloud_provider.name }}"
|
||||
style="max-height: 25px; max-width: 50px; object-fit: contain;">
|
||||
</a>
|
||||
{% endif %}
|
||||
<small class="text-muted">
|
||||
{{ offering.cloud_provider.name }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
{% for category in offering.service.categories.all %}
|
||||
<span class="badge bg-secondary me-1">{{ category.full_path }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ offering.description|safe|truncatewords_html:30 }}
|
||||
</div>
|
||||
|
||||
{% if offering.plans.exists %}
|
||||
<div class="mb-3">
|
||||
<strong>Available Plans:</strong>
|
||||
<ul class="list-unstyled small">
|
||||
{% for plan in offering.plans.all %}
|
||||
<li>• {{ plan.name }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="mt-auto d-flex gap-2">
|
||||
<a href="{{ offering.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||
{% if offering.plans.exists %}
|
||||
{% if offering.plans.count == 1 %}
|
||||
{% with plan=offering.plans.first %}
|
||||
<a href="{% url 'services:create_lead' offering.service.slug %}?offering={{ offering.id }}&plan={{ plan.id }}"
|
||||
class="btn btn-success">Show Interest</a>
|
||||
{% endwith %}
|
||||
{% else %}
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-success dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
Show Interest
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for plan in offering.plans.all %}
|
||||
<li>
|
||||
<a class="dropdown-item"
|
||||
href="{% url 'services:create_lead' offering.service.slug %}?offering={{ offering.id }}&plan={{ plan.id }}">
|
||||
{{ plan.name }}
|
||||
{% if plan.is_default %}(Recommended){% endif %}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<a href="{% url 'services:create_lead' offering.service.slug %}?offering={{ offering.id }}"
|
||||
class="btn btn-success">Show Interest</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
No service offerings found matching your criteria.
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
93
hub/services/templates/services/partner_list.html
Normal file
93
hub/services/templates/services/partner_list.html
Normal file
|
@ -0,0 +1,93 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Filters</h5>
|
||||
<form method="get">
|
||||
<div class="mb-3">
|
||||
<label for="search" class="form-label">Search</label>
|
||||
<input type="text" class="form-control" id="search" name="search" value="{{ request.GET.search }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="cloud_provider" class="form-label">Cloud Provider</label>
|
||||
<select class="form-select" id="cloud_provider" name="cloud_provider">
|
||||
<option value="">All Providers</option>
|
||||
{% for provider in cloud_providers %}
|
||||
<option value="{{ provider.id }}" {% if request.GET.cloud_provider == provider.id|stringformat:'i' %}selected{% endif %}>
|
||||
{{ provider.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Apply Filters</button>
|
||||
<a href="{% url 'services:partner_list' %}" class="btn btn-secondary">Clear</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||
{% for partner in partners %}
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
{% if partner.logo %}
|
||||
<img src="{{ partner.logo.url }}"
|
||||
alt="{{ partner.name }}"
|
||||
class="me-3" style="max-height: 60px; max-width: 120px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<h5 class="card-title mb-0">{{ partner.name }}</h5>
|
||||
</div>
|
||||
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ partner.description|safe|truncatewords_html:50 }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>Cloud Providers:</strong>
|
||||
<div class="mt-2">
|
||||
{% for provider in partner.cloud_providers.all %}
|
||||
<div class="d-inline-block me-2 mb-2">
|
||||
{% if provider.logo %}
|
||||
<img src="{{ provider.logo.url }}"
|
||||
alt="{{ provider.name }}"
|
||||
style="max-height: 25px; max-width: 50px; object-fit: contain;">
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ provider.name }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>Services Available:</strong> {{ partner.services.count }}
|
||||
</div>
|
||||
|
||||
<div class="mt-auto">
|
||||
<a href="{{ partner.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||
{% if partner.website %}
|
||||
<a href="{{ partner.website }}" class="btn btn-outline-secondary" target="_blank">Visit Website</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
No consulting partners found matching your criteria.
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
68
hub/services/templates/services/provider_list.html
Normal file
68
hub/services/templates/services/provider_list.html
Normal file
|
@ -0,0 +1,68 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Filters</h5>
|
||||
<form method="get">
|
||||
<div class="mb-3">
|
||||
<label for="search" class="form-label">Search</label>
|
||||
<input type="text" class="form-control" id="search" name="search" value="{{ request.GET.search }}">
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Apply Filters</button>
|
||||
<a href="{% url 'services:provider_list' %}" class="btn btn-secondary">Clear</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||
{% for provider in providers %}
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
{% if provider.logo %}
|
||||
<img src="{{ provider.logo.url }}"
|
||||
alt="{{ provider.name }}"
|
||||
class="me-3" style="max-height: 60px; max-width: 120px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<h5 class="card-title mb-0">{{ provider.name }}</h5>
|
||||
</div>
|
||||
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ provider.description|safe|truncatewords_html:50 }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>Services Available:</strong> {{ provider.offerings.count }}
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<strong>Partners:</strong> {{ provider.consulting_partners.count }}
|
||||
</div>
|
||||
|
||||
<div class="mt-auto">
|
||||
<a href="{{ provider.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||
{% if provider.website %}
|
||||
<a href="{{ provider.website }}" class="btn btn-outline-secondary" target="_blank">Visit Website</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col">
|
||||
<div class="alert alert-info">
|
||||
No cloud providers found matching your criteria.
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -1,120 +1,132 @@
|
|||
{% extends 'services/base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card">
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start mb-4">
|
||||
{% if service.logo %}
|
||||
<img src="{{ service.logo.url }}" alt="{{ service.name }} logo" class="me-4" style="max-height: 100px; max-width: 200px; object-fit: contain;">
|
||||
<img src="{{ service.logo.url }}" alt="{{ service.name }} logo" class="me-4"
|
||||
style="max-height: 120px; max-width: 240px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<div>
|
||||
<h2 class="card-title">{{ service.name }}</h2>
|
||||
<div class="d-flex align-items-center">
|
||||
{% if service.cloud_provider.logo %}
|
||||
<a href="{% url 'services:provider_detail' service.cloud_provider.slug %}">
|
||||
<img src="{{ service.cloud_provider.logo.url }}" alt="{{ service.cloud_provider.name }} logo"
|
||||
class="me-2" style="max-height: 25px; max-width: 200px; object-fit: contain;">
|
||||
</a>
|
||||
{% else %}
|
||||
<h6 class="card-subtitle text-muted mb-0">
|
||||
<a href="{% url 'services:provider_detail' service.cloud_provider.pk %}"
|
||||
class="text-decoration-none text-muted">{{ service.cloud_provider.name }}</a>
|
||||
</h6>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-8">
|
||||
<h5>Description</h5>
|
||||
<p>{{ service.description|safe }}</p>
|
||||
|
||||
<h5>Features</h5>
|
||||
<p>{{ service.features|safe }}</p>
|
||||
|
||||
{% if service.external_links.exists %}
|
||||
<h5>External Resources</h5>
|
||||
{% for link in service.external_links.all %}
|
||||
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer"
|
||||
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
||||
{{ link.description }}
|
||||
<i class="bi bi-box-arrow-up-right"></i>
|
||||
</a>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-12">
|
||||
<h3 class="mb-4">Plans</h3>
|
||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||
{% for plan in service.plans.all %}
|
||||
<div class="col">
|
||||
<div class="card h-100 {% if plan.is_default %}border-primary{% endif %}">
|
||||
{% if plan.is_default %}
|
||||
<div class="card-header text-primary">
|
||||
Recommended
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{ plan.name }}</h5>
|
||||
<div class="card-text mb-3">{{ plan.description|safe }}</div>
|
||||
|
||||
<div class="mb-3">
|
||||
{% for price in plan.prices.all %}
|
||||
<div class="mb-1">
|
||||
<strong>{{ price.currency.symbol }}</strong> {{ price.price }}
|
||||
<small class="text-muted">{{ price.currency.code }}</small>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if plan.features %}
|
||||
<div class="rich-text-content">
|
||||
{{ plan.features|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<a href="{% url 'services:create_lead' service.slug %}?plan={{ plan.id }}"
|
||||
class="btn btn-primary mt-3">Order</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="card-title mb-3">{{ service.name }}</h2>
|
||||
<div class="mb-3">
|
||||
{% for category in service.categories.all %}
|
||||
<span class="badge bg-secondary me-1">{{ category.full_path }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="{% url 'services:create_lead' service.slug %}" class="btn btn-success">Order</a>
|
||||
<a href="{% url 'services:service_list' %}" class="btn btn-secondary">Back to Services</a>
|
||||
<div class="rich-text-content mb-4">
|
||||
{{ service.description|safe }}
|
||||
</div>
|
||||
|
||||
{% if service.features %}
|
||||
<h3>Features</h3>
|
||||
<div class="rich-text-content mb-4">
|
||||
{{ service.features|safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if service.consulting_partners.exists %}
|
||||
<div class="card mb-3">
|
||||
<!-- Cloud Provider Offerings -->
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Consulting Partners</h5>
|
||||
<h3 class="mb-4">Available Offerings</h3>
|
||||
<div class="row row-cols-1 row-cols-md-2 g-4">
|
||||
{% for offering in service.offerings.all %}
|
||||
<div class="col">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
{% if offering.cloud_provider.logo %}
|
||||
<img src="{{ offering.cloud_provider.logo.url }}"
|
||||
alt="{{ offering.cloud_provider.name }} logo"
|
||||
class="me-3" style="max-height: 50px; max-width: 100px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<div>
|
||||
<h5 class="card-title mb-0">
|
||||
<a href="{{ offering.cloud_provider.get_absolute_url }}" class="text-decoration-none">
|
||||
{{ offering.cloud_provider.name }}
|
||||
</a>
|
||||
</h5>
|
||||
{% if offering.cloud_provider.website %}
|
||||
<a href="{{ offering.cloud_provider.website }}" class="text-muted small" target="_blank">
|
||||
Visit Provider Website
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="rich-text-content mb-3">
|
||||
{{ offering.description|safe|truncatewords_html:50 }}
|
||||
</div>
|
||||
|
||||
{% if offering.plans.exists %}
|
||||
<div class="mb-3">
|
||||
<h6>Plans:</h6>
|
||||
{% for plan in offering.plans.all %}
|
||||
<div class="card mb-2">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">{{ plan.name }}</h6>
|
||||
{% for price in plan.prices.all %}
|
||||
<div class="small text-muted">
|
||||
{{ price.currency.symbol }}{{ price.price }} {{ price.currency.code }} per {{ price.term.name }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<a href="{% url 'services:create_lead' service.slug %}?offering={{ offering.id }}"
|
||||
class="btn btn-success">Show Interest</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<div class="col-12">
|
||||
<div class="alert alert-info">
|
||||
No offerings available yet.
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Consulting Partners -->
|
||||
{% if service.consulting_partners.exists %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h3 class="mb-4">Consulting Partners</h3>
|
||||
<div class="row row-cols-1 row-cols-md-3 g-4">
|
||||
{% for partner in service.consulting_partners.all %}
|
||||
<div class="col">
|
||||
<div class="d-flex align-items-center">
|
||||
{% if partner.logo %}
|
||||
<img src="{{ partner.logo.url }}" alt="{{ partner.name }} logo"
|
||||
class="me-2" style="max-height: 40px; max-width: 80px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<div>
|
||||
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none">
|
||||
{{ partner.name }}
|
||||
</a>
|
||||
{% if partner.website %}
|
||||
<br>
|
||||
<a href="{{ partner.website }}" class="small text-muted" target="_blank">
|
||||
Visit Website
|
||||
</a>
|
||||
{% endif %}
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
{% if partner.logo %}
|
||||
<img src="{{ partner.logo.url }}"
|
||||
alt="{{ partner.name }} logo"
|
||||
class="me-3" style="max-height: 50px; max-width: 100px; object-fit: contain;">
|
||||
{% endif %}
|
||||
<div>
|
||||
<h5 class="card-title mb-0">
|
||||
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none">
|
||||
{{ partner.name }}
|
||||
</a>
|
||||
</h5>
|
||||
{% if partner.website %}
|
||||
<a href="{{ partner.website }}" class="text-muted small" target="_blank">
|
||||
Visit Website
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -123,4 +135,22 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
<!-- External Links -->
|
||||
{% if service.external_links.exists %}
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<h3>Additional Information</h3>
|
||||
<div class="list-group">
|
||||
{% for link in service.external_links.all %}
|
||||
<a href="{{ link.url }}" target="_blank" rel="noopener noreferrer"
|
||||
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center">
|
||||
{{ link.description }}
|
||||
<i class="bi bi-box-arrow-up-right"></i>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -72,18 +72,23 @@
|
|||
{% endif %}
|
||||
<div>
|
||||
<h5 class="card-title mb-0">{{ service.name }}</h5>
|
||||
<div class="d-flex align-items-center mt-2">
|
||||
{% if service.cloud_provider.logo %}
|
||||
<a href="{% url 'services:provider_detail' service.cloud_provider.slug %}">
|
||||
<img src="{{ service.cloud_provider.logo.url }}" alt="{{ service.cloud_provider.name }} logo"
|
||||
class="me-2" style="max-height: 25px; max-width: 200px; object-fit: contain;">
|
||||
</a>
|
||||
{% else %}
|
||||
<h6 class="card-subtitle text-muted mb-0">
|
||||
<a href="{% url 'services:provider_detail' service.cloud_provider.pk %}"
|
||||
class="text-decoration-none text-muted">{{ service.cloud_provider.name }}</a>
|
||||
</h6>
|
||||
{% endif %}
|
||||
<div class="mt-2">
|
||||
{% for offering in service.offerings.all %}
|
||||
<div class="d-inline-block me-2">
|
||||
{% if offering.cloud_provider.logo %}
|
||||
<a href="{% url 'services:provider_detail' offering.cloud_provider.slug %}" title="{{ offering.cloud_provider.name }}">
|
||||
<img src="{{ offering.cloud_provider.logo.url }}"
|
||||
alt="{{ offering.cloud_provider.name }}"
|
||||
style="max-height: 25px; max-width: 50px; object-fit: contain;">
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% url 'services:provider_detail' offering.cloud_provider.slug %}"
|
||||
class="badge bg-secondary text-decoration-none">
|
||||
{{ offering.cloud_provider.name }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -94,8 +99,25 @@
|
|||
</div>
|
||||
<p class="card-text">{{ service.description|safe|truncatewords:30 }}</p>
|
||||
|
||||
<a href="{{ service.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||
<a href="{% url 'services:create_lead' service.slug %}" class="btn btn-success">Show Interest</a>
|
||||
<div class="mt-3">
|
||||
<a href="{{ service.get_absolute_url }}" class="btn btn-primary">View Details</a>
|
||||
{% if service.offerings.exists %}
|
||||
<div class="dropdown d-inline-block">
|
||||
<button class="btn btn-success dropdown-toggle" type="button" data-bs-toggle="dropdown">
|
||||
Show Interest
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
{% for offering in service.offerings.all %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'services:create_lead' service.slug %}?offering={{ offering.id }}">
|
||||
via {{ offering.cloud_provider.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -109,4 +131,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
Loading…
Add table
Add a link
Reference in a new issue