make whole card clickable
This commit is contained in:
parent
b1680a11af
commit
1911a1211b
7 changed files with 126 additions and 84 deletions
|
@ -12322,4 +12322,20 @@ a.btn:focus {
|
||||||
|
|
||||||
.page-content .page-action a {
|
.page-content .page-action a {
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable-card {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s, box-shadow 0.2s;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.clickable-button {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
9
hub/services/static/js/servala-addons.js
Normal file
9
hub/services/static/js/servala-addons.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
function cardClicked(event, url) {
|
||||||
|
// Don't navigate if the click was on a button or link
|
||||||
|
if (event.target.closest('.clickable-button') || event.target.closest('.clickable-link')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to the provider detail page
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
<script defer src="{% static "js/htmx204.min.js" %}"></script>
|
<script defer src="{% static "js/htmx204.min.js" %}"></script>
|
||||||
<script defer src="{% static "js/alpine-collapse.min.js" %}"></script>
|
<script defer src="{% static "js/alpine-collapse.min.js" %}"></script>
|
||||||
<script defer src="{% static "js/servala-main.js" %}"></script>
|
<script defer src="{% static "js/servala-main.js" %}"></script>
|
||||||
|
<script defer src="{% static "js/servala-addons.js" %}"></script>
|
||||||
{% block extra_js %}{% endblock %}
|
{% block extra_js %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -41,20 +41,31 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for service in featured_services %}
|
{% for service in featured_services %}
|
||||||
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
||||||
<div class="card h-100 d-flex flex-column">
|
<div class="card h-100 d-flex flex-column clickable-card"
|
||||||
<div class="card__image">
|
onclick="cardClicked(event, '{{ service.get_absolute_url }}')">
|
||||||
<a href="{{ service.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ service.logo.url }}" alt="{{ service.name }} logo"></a>
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
|
<div class="card__header">
|
||||||
|
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
||||||
|
<div class="me-3 d-flex align-items-center" style="height: 100%;">
|
||||||
|
<a href="{{ service.get_absolute_url }}" class="clickable-link">
|
||||||
|
<img src="{{ service.logo.url }}"
|
||||||
|
alt="{{ service.name }}"
|
||||||
|
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 class="card__title">
|
||||||
|
<a href="{{ service.get_absolute_url }}" class="text-decoration-none clickable-link">{{ service.name }}</a>
|
||||||
|
</h3>
|
||||||
|
{% for category in service.categories.all|slice:":1" %}
|
||||||
|
<p class="card__subtitle">{{ category.name }}</p>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="card__desc flex-grow-1">
|
||||||
|
<p>{{ service.description|safe|truncatewords:15 }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card__header">
|
|
||||||
<h3 class="card__title"><a href="{{ service.get_absolute_url }}" class="text-decoration-none">{{ service.name }}</a></h3>
|
|
||||||
{% for category in service.categories.all|slice:":1" %}
|
|
||||||
<p class="card__subtitle">{{ category.name }}</p>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
<div class="card__desc flex-grow-1">
|
|
||||||
<p>{{ service.description|safe|truncatewords:15 }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% empty %}
|
{% empty %}
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
@ -85,29 +96,36 @@
|
||||||
</header>
|
</header>
|
||||||
<div class="section__grid">
|
<div class="section__grid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="section__grid">
|
{% for provider in featured_providers %}
|
||||||
<div class="row">
|
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
||||||
{% for provider in featured_providers %}
|
<div class="card h-100 d-flex flex-column clickable-card"
|
||||||
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
onclick="cardClicked(event, '{{ provider.get_absolute_url }}')">
|
||||||
<div class="card h-100 d-flex flex-column">
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
<div class="card__image__wide mb-4">
|
|
||||||
<a href="{{ provider.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ provider.logo.url }}" alt="{{ provider.name }} logo"></a>
|
|
||||||
</div>
|
|
||||||
<div class="card__header">
|
<div class="card__header">
|
||||||
<h3 class="card__title"><a href="{{ provider.get_absolute_url }}" class="text-decoration-none">{{ provider.name }}</a></h3>
|
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
||||||
|
<div class="me-3 d-flex align-items-center" style="height: 100%;">
|
||||||
|
<a href="{{ provider.get_absolute_url }}" class="clickable-link">
|
||||||
|
<img src="{{ provider.logo.url }}"
|
||||||
|
alt="{{ provider.name }}"
|
||||||
|
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 class="card__title">
|
||||||
|
<a href="{{ provider.get_absolute_url }}" class="text-decoration-none clickable-link">{{ provider.name }}</a>
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="card__desc flex-grow-1">
|
<div class="card__desc flex-grow-1">
|
||||||
<p>{{ provider.description|safe|truncatewords:15 }}</p>
|
<p>{{ provider.description|safe|truncatewords:15 }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% empty %}
|
|
||||||
<div class="col-12">
|
|
||||||
<p class="text-center">No featured provider available at the moment.</p>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% empty %}
|
||||||
|
<div class="col-12">
|
||||||
|
<p class="text-center">No featured provider available at the moment.</p>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-action d-lg-none">
|
<div class="page-action d-lg-none">
|
||||||
|
@ -132,25 +150,36 @@
|
||||||
</header>
|
</header>
|
||||||
<div class="section__grid">
|
<div class="section__grid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for partner in featured_partners %}
|
{% for partner in featured_partners %}
|
||||||
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
<div class="col-12 col-md-6 col-lg-3 mb-20 mb-lg-0">
|
||||||
<div class="card h-100 d-flex flex-column">
|
<div class="card h-100 d-flex flex-column clickable-card"
|
||||||
<div class="card__image__wide mb-4">
|
onclick="cardClicked(event, '{{ partner.get_absolute_url }}')">
|
||||||
<a href="{{ partner.get_absolute_url }}"><img class="img-fluid card-logo" src="{{ partner.logo.url }}" alt="{{ partner.name }} logo"></a>
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
</div>
|
<div class="card__header">
|
||||||
<div class="card__header">
|
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
||||||
<h3 class="card__title"><a href="{{ partner.get_absolute_url }}" class="text-decoration-none">{{ partner.name }}</a></h3>
|
<div class="me-3 d-flex align-items-center" style="height: 100%;">
|
||||||
</div>
|
<a href="{{ partner.get_absolute_url }}" class="clickable-link">
|
||||||
<div class="card__desc flex-grow-1">
|
<img src="{{ partner.logo.url }}"
|
||||||
<p>{{ partner.description|safe|truncatewords:15 }}</p>
|
alt="{{ partner.name }}"
|
||||||
|
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 class="card__title">
|
||||||
|
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none clickable-link">{{ partner.name }}</a>
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card__desc flex-grow-1">
|
||||||
|
<p>{{ partner.description|safe|truncatewords:15 }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{% empty %}
|
||||||
{% empty %}
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<p class="text-center">No featured partner available at the moment.</p>
|
<p class="text-center">No featured partner available at the moment.</p>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-action d-lg-none">
|
<div class="page-action d-lg-none">
|
||||||
|
@ -189,7 +218,7 @@
|
||||||
<header class="section__header text-center mb-30">
|
<header class="section__header text-center mb-30">
|
||||||
<h2 class="section-heading-h2 fs-40 fs-lg-64">Frequenty Asked Questions</h2>
|
<h2 class="section-heading-h2 fs-40 fs-lg-64">Frequenty Asked Questions</h2>
|
||||||
<div class="section__desc fw-medium fs-20 w-lg-40 mx-auto">
|
<div class="section__desc fw-medium fs-20 w-lg-40 mx-auto">
|
||||||
<p>Still need more information? Read our FAQ or contact us to learn more about the Servala.</p>
|
<p>Still need more information? Read our FAQ or contact us to learn more about the Servala.</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div x-data="{ open: null }" class="section__faq">
|
<div x-data="{ open: null }" class="section__faq">
|
||||||
|
@ -215,7 +244,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -108,12 +108,13 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for partner in partners %}
|
{% for partner in partners %}
|
||||||
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
||||||
<div class="card h-100 d-flex flex-column">
|
<div class="card h-100 d-flex flex-column clickable-card"
|
||||||
|
onclick="cardClicked(event, '{{ partner.get_absolute_url }}')">
|
||||||
<div class="card__content d-flex flex-column flex-grow-1">
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
<div class="card__header">
|
<div class="card__header">
|
||||||
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
||||||
<div class="me-3">
|
<div class="me-3">
|
||||||
<a href="{{ partner.get_absolute_url }}">
|
<a href="{{ partner.get_absolute_url }}" class="clickable-link">
|
||||||
<img src="{{ partner.logo.url }}"
|
<img src="{{ partner.logo.url }}"
|
||||||
alt="{{ partner.name }}"
|
alt="{{ partner.name }}"
|
||||||
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
||||||
|
@ -121,7 +122,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="card__title">
|
<h3 class="card__title">
|
||||||
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none">{{ partner.name }}</a>
|
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none clickable-link">{{ partner.name }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -132,9 +133,9 @@
|
||||||
<div class="card__footer mt-3">
|
<div class="card__footer mt-3">
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
{% if partner.website %}
|
{% if partner.website %}
|
||||||
<a href="{{ partner.website }}" class="btn btn-primary btn-sm" target="_blank">Visit Website</a>
|
<a href="{{ partner.website }}" class="btn btn-primary btn-sm clickable-button" target="_blank">Visit Website</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ partner.get_absolute_url }}#services" class="btn btn-primary btn-sm">Available Services</a>
|
<a href="{{ partner.get_absolute_url }}#services" class="btn btn-primary btn-sm clickable-button">Available Services</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -91,12 +91,13 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for provider in providers %}
|
{% for provider in providers %}
|
||||||
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
||||||
<div class="card h-100 d-flex flex-column">
|
<div class="card h-100 d-flex flex-column clickable-card"
|
||||||
|
onclick="cardClicked(event, '{{ provider.get_absolute_url }}')">
|
||||||
<div class="card__content d-flex flex-column flex-grow-1">
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
<div class="card__header">
|
<div class="card__header">
|
||||||
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
<div class="d-flex align-items-start" style="height: 100px; margin-bottom: 1rem;">
|
||||||
<div class="me-3 d-flex align-items-center" style="height: 100%;">
|
<div class="me-3 d-flex align-items-center" style="height: 100%;">
|
||||||
<a href="{{ provider.get_absolute_url }}">
|
<a href="{{ provider.get_absolute_url }}" class="clickable-link">
|
||||||
<img src="{{ provider.logo.url }}"
|
<img src="{{ provider.logo.url }}"
|
||||||
alt="{{ provider.name }}"
|
alt="{{ provider.name }}"
|
||||||
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
style="max-height: 100px; max-width: 250px; object-fit: contain;">
|
||||||
|
@ -104,7 +105,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h3 class="card__title">
|
<h3 class="card__title">
|
||||||
<a href="{{ provider.get_absolute_url }}" class="text-decoration-none">{{ provider.name }}</a>
|
<a href="{{ provider.get_absolute_url }}" class="text-decoration-none clickable-link">{{ provider.name }}</a>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -115,9 +116,9 @@
|
||||||
<div class="card__footer mt-3">
|
<div class="card__footer mt-3">
|
||||||
<div class="d-flex gap-2">
|
<div class="d-flex gap-2">
|
||||||
{% if provider.website %}
|
{% if provider.website %}
|
||||||
<a href="{{ provider.website }}" class="btn btn-primary btn-sm" target="_blank">Visit Website</a>
|
<a href="{{ provider.website }}" class="btn btn-primary btn-sm clickable-button" target="_blank">Visit Website</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ provider.get_absolute_url }}#services" class="btn btn-primary btn-sm">Available Services</a>
|
<a href="{{ provider.get_absolute_url }}#services" class="btn btn-primary btn-sm clickable-button">Available Services</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -150,49 +150,30 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{% for service in services %}
|
{% for service in services %}
|
||||||
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
<div class="col-12 col-md-6 col-lg-4 mb-30">
|
||||||
<div class="card {% if service.is_featured %}card-featured{% endif %} h-100 d-flex flex-column">
|
<div class="card {% if service.is_featured %}card-featured{% endif %} h-100 d-flex flex-column clickable-card"
|
||||||
|
onclick="cardClicked(event, '{% if request.GET.cloud_provider %}{% for offering in service.offerings.all %}{% if offering.cloud_provider.id|stringformat:"i" == request.GET.cloud_provider %}{% url "services:offering_detail" offering.cloud_provider.slug service.slug %}{% endif %}{% endfor %}{% else %}{{ service.get_absolute_url }}{% endif %}')">
|
||||||
{% if service.logo or service.is_featured or service.is_coming_soon %}
|
{% if service.logo or service.is_featured or service.is_coming_soon %}
|
||||||
<div class="d-flex justify-content-between">
|
<div class="d-flex justify-content-between mb-3">
|
||||||
{% if service.logo %}
|
{% if service.logo %}
|
||||||
<div class="card__image flex-shrink-0">
|
<div class="card__image flex-shrink-0">
|
||||||
{% if request.GET.cloud_provider %}
|
<img src="{{ service.logo.url }}" alt="{{ service.name }} logo" class="img-fluid">
|
||||||
{% for offering in service.offerings.all %}
|
|
||||||
{% if offering.cloud_provider.id|stringformat:'i' == request.GET.cloud_provider %}
|
|
||||||
<a href="{% url 'services:offering_detail' offering.cloud_provider.slug service.slug %}">
|
|
||||||
<img src="{{ service.logo.url }}" alt="{{ service.name }} logo" class="img-fluid">
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ service.get_absolute_url }}">
|
|
||||||
<img src="{{ service.logo.url }}" alt="{{ service.name }} logo" class="img-fluid">
|
|
||||||
</a>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if service.is_featured %}
|
{% if service.is_featured %}
|
||||||
<div>
|
<div>
|
||||||
<a class="btn btn-primary btn-sm" href="">Featured</a>
|
<span class="btn btn-primary btn-sm">Featured</span>
|
||||||
</div>
|
</div>
|
||||||
{% elif service.is_coming_soon %}
|
{% elif service.is_coming_soon %}
|
||||||
<div>
|
<div>
|
||||||
<a class="btn btn-secondary btn-sm" href="">Coming Soon</a>
|
<span class="btn btn-secondary btn-sm">Coming Soon</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card__content d-flex flex-column flex-grow-1">
|
<div class="card__content d-flex flex-column flex-grow-1">
|
||||||
<div class="card__header">
|
<div class="card__header">
|
||||||
<h3 class="card__title">
|
<h3 class="card__title {% if service.is_coming_soon %}text-black-50{% endif %}">
|
||||||
{% if request.GET.cloud_provider %}
|
{{ service.name }}
|
||||||
{% for offering in service.offerings.all %}
|
|
||||||
{% if offering.cloud_provider.id|stringformat:'i' == request.GET.cloud_provider %}
|
|
||||||
<a href="{% url 'services:offering_detail' offering.cloud_provider.slug service.slug %}" class="text-decoration-none {% if service.is_coming_soon %}text-black-50{% endif %}">{{ service.name }}</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
<a href="{{ service.get_absolute_url }}" class="text-decoration-none {% if service.is_coming_soon %}text-black-50{% endif %}">{{ service.name }}</a>
|
|
||||||
{% endif %}
|
|
||||||
</h3>
|
</h3>
|
||||||
<p class="card__subtitle">
|
<p class="card__subtitle">
|
||||||
{% for category in service.categories.all %}
|
{% for category in service.categories.all %}
|
||||||
|
@ -211,8 +192,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% empty %}
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-info">
|
||||||
|
No services found matching your criteria.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue