Compare commits

...

5 commits

Author SHA1 Message Date
9ce96674c0
show partner and provider name on listing
All checks were successful
Build and Deploy / build (push) Successful in 36s
Build and Deploy / deploy (push) Successful in 4s
2025-03-14 15:34:53 +01:00
1105fc7605
add static announcement banner 2025-03-14 15:25:56 +01:00
31844f1b13
move base template to better folder 2025-03-14 15:21:14 +01:00
15293dfa11
update about page text 2025-03-14 15:13:25 +01:00
1daa288cdd
allow manual ordering of consulting partner 2025-03-14 14:57:34 +01:00
21 changed files with 88 additions and 39 deletions

View file

@ -137,11 +137,19 @@ class ServiceOfferingAdmin(admin.ModelAdmin):
@admin.register(ConsultingPartner) @admin.register(ConsultingPartner)
class ConsultingPartnerAdmin(admin.ModelAdmin): class ConsultingPartnerAdmin(SortableAdminMixin, admin.ModelAdmin):
list_display = ("name", "website", "logo_preview", "disable_listing", "is_featured") list_display = (
"name",
"website",
"logo_preview",
"disable_listing",
"is_featured",
"order",
)
search_fields = ("name", "description") search_fields = ("name", "description")
prepopulated_fields = {"slug": ("name",)} prepopulated_fields = {"slug": ("name",)}
filter_horizontal = ("services", "cloud_providers") filter_horizontal = ("services", "cloud_providers")
ordering = ("order",)
def logo_preview(self, obj): def logo_preview(self, obj):
if obj.logo: if obj.logo:

View file

@ -0,0 +1,22 @@
# Generated by Django 5.1.5 on 2025-03-14 13:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("services", "0020_alter_cloudprovider_options_cloudprovider_order"),
]
operations = [
migrations.AlterModelOptions(
name="consultingpartner",
options={"ordering": ["order"]},
),
migrations.AddField(
model_name="consultingpartner",
name="order",
field=models.IntegerField(default=0),
),
]

View file

@ -183,12 +183,16 @@ class ConsultingPartner(models.Model):
CloudProvider, related_name="consulting_partners", blank=True CloudProvider, related_name="consulting_partners", blank=True
) )
order = models.IntegerField(default=0)
is_featured = models.BooleanField(default=False) is_featured = models.BooleanField(default=False)
disable_listing = models.BooleanField(default=False) disable_listing = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True) created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["order"]
def __str__(self): def __str__(self):
return self.name return self.name

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block title %}Bad Request (400){% endblock %} {% block title %}Bad Request (400){% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block title %}Page Not Found (404){% endblock %} {% block title %}Page Not Found (404){% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block title %}Server Error (500){% endblock %} {% block title %}Server Error (500){% endblock %}

View file

@ -24,6 +24,16 @@
</head> </head>
<body> <body>
<div class="overflow-hidden"> <div class="overflow-hidden">
<!-- Announcement Bar -->
<div class="bg-primary text-white py-2 text-center">
<div class="container">
<a href="https://www.vshn.ch/en/blog/vshn-launches-servala-open-cloud-native-service-hub/" class="text-white text-decoration-none" target="_blank">
VSHN launches Servala Open Cloud Native Service Hub
</a>
<i class="bi bi-box-arrow-up-right"></i>
</div>
</div>
<header x-data="{sideNav: false, atTop: true}" class="site-header position-relative"> <header x-data="{sideNav: false, atTop: true}" class="site-header position-relative">
<div class="header-nav" :class="{ 'header-nav--top': atTop, 'header-nav--fixed': !atTop }" <div class="header-nav" :class="{ 'header-nav--top': atTop, 'header-nav--fixed': !atTop }"
x-on:scroll.window="atTop = (window.pageYOffset > 200) ? false : true;"> x-on:scroll.window="atTop = (window.pageYOffset > 200) ? false : true;">

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% load contact_tags %} {% load contact_tags %}
@ -26,9 +26,9 @@
<h2 class="fs-32 fw-semibold mb-12">Overview</h2> <h2 class="fs-32 fw-semibold mb-12">Overview</h2>
</header> </header>
<div class="text-gray-500 fs-19 lh-1-7"> <div class="text-gray-500 fs-19 lh-1-7">
<p>Servala connects businesses, developers, and cloud service providers on one unique hub with secure, scalable, and easy-to-use cloud-native services.</p> <p>Servala connects businesses, developers, and cloud providers on one unified hub, offering secure, scalable, and easy-to-use cloud-native services and applications.</p>
<p>With Servala, businesses can seamlessly access and deploy a vast range of software, databases, applications, and DevOps tools such as PostgreSQL, Red Hat OpenShift, Keycloak, GitLab or Forgejo across multiple cloud providers and regions. This ensures businesses can seamlessly access and deploy services, applications, and DevOps tools across different cloud environments without being tied to a single provider.</p> <p>With Servala, businesses can seamlessly access and deploy a vast range of software, databases, applications, and DevOps tools such as PostgreSQL, Red Hat OpenShift, Keycloak, GitLab or Forgejo across multiple cloud providers and regions. This ensures businesses can seamlessly access and deploy services, applications, and DevOps tools across different cloud environments without being tied to a single provider.</p>
<p>With Servala, businesses can stay agile, avoid vendor lock-in, optimize cloud costs, and ensure security and compliance. For Independent Software Vendors (ISVs), Servala opens up additional channels to offer their software products. At the same time, Cloud Service Providers (CSPs) can add value on top of their existing core offerings (compute, storage, network).</p> <p>Servala helps businesses stay agile and independent, reduce cloud costs, and ensure security and compliance. For Software Vendors, Servala opens up additional channels to offer their software products. At the same time, Cloud Providers can add value on top of their existing core offerings through Servala.</p>
</div> </div>
</div> </div>
<div class="page-action"> <div class="page-action">
@ -46,30 +46,31 @@
<div> <div>
<h2 class="fs-32 fw-semibold mt-3">Who benefits from using Servala?</h2> <h2 class="fs-32 fw-semibold mt-3">Who benefits from using Servala?</h2>
<div class="text-gray-500 fs-19 lh-1-7"> <div class="text-gray-500 fs-19 lh-1-7">
<p>Servala is designed for CSPs, ISVs, and Enterprises and their users, enabling them to offer, integrate, and consume cloud-native services and applications and DevOps tools with ease. It bridges the gap between CSPs seeking value-added services, ISVs looking to distribute and monetize their applications and services, and Enterprises needing scalable, secure, and cost-efficient cloud solutions and their users who need to access those services easily - all within an open, cloud-agnostic ecosystem.</p> <p>Servala is designed for Software Vendors, Cloud Providers and Enterprises and their users, enabling them to offer, integrate, and consume cloud-native services and applications and DevOps tools with ease.</p>
<p>For <strong>Software Vendors</strong>, Servala provides a powerful channel to distribute, monetize, and operate their software as managed services. <strong>Cloud Providers</strong> can extend their core infrastructure offerings with value-added services. <strong>Enterprise Private Clouds</strong> gain seamless access to trusted services and applications while maintaining full control over security and compliance - all within an open and agnostic ecosystem.</p>
</div> </div>
<article class="pt-20"> <article class="pt-20">
<h3 class="fs-24 fw-semibold">Independent Software Vendors (ISVs)</h3> <h3 class="fs-24 fw-semibold">Software Vendors</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19"> <ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Transform applications into SaaS offerings.</li> <li>Transform software into SaaS offerings.</li>
<li>Leverage the Servala Hub to distribute, monetize, and efficiently operate your software.</li> <li>Reach new markets and ecosystems through our existing partner network.</li>
<li>Extend your reach to new markets and ecosystems.</li> <li>Streamline operations and monetization.</li>
</ul> </ul>
</article> </article>
<article class="pt-20"> <article class="pt-20">
<h3 class="fs-24 fw-semibold">Cloud Service Providers (CSPs)</h3> <h3 class="fs-24 fw-semibold">Cloud Providers</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19"> <ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Offer value-added services and applications to end users.</li> <li>Offer value-added services and applications to customers.</li>
<li>Respond effectively to fast-paced market changes.</li> <li>Enhance operational efficiency and market reach.</li>
<li>Gain tools to enhance operational efficiency and market relevance.</li> <li>Keep pace with fast-changing industry demands.</li>
</ul> </ul>
</article> </article>
<article class="pt-20"> <article class="pt-20">
<h3 class="fs-24 fw-semibold">Enterprises and Their Users</h3> <h3 class="fs-24 fw-semibold">Enterprise Private Clouds</h3>
<ul class="list-disc pl-8 text-gray-500 fs-19"> <ul class="list-disc pl-8 text-gray-500 fs-19">
<li>Access scalable, secure, and cost-efficient services.</li> <li>Access scalable, secure, and cost-efficient services.</li>
<li>Enable self-service installation of trusted applications without managing infrastructure.</li> <li>Enable self-service installation of trusted applications without managing infrastructure.</li>
<li>Benefit from built-in compliance, developer productivity boosts, and operational simplicity.</li> <li>Ensure compliance, boost developer productivity, and simplify operations.</li>
</ul> </ul>
</article> </article>
</div> </div>
@ -84,8 +85,7 @@
<i class="bi bi-lightning-charge-fill fs-2 text-primary me-3"></i> <i class="bi bi-lightning-charge-fill fs-2 text-primary me-3"></i>
<h3 class="fs-24 fw-semibold card-title mb-0">Agility &amp; Faster Time-to-Market</h3> <h3 class="fs-24 fw-semibold card-title mb-0">Agility &amp; Faster Time-to-Market</h3>
</div> </div>
<p class="text-gray-500 fs-19 card-text">Access a vast catalog of services and applications for rapid deployment and <p class="text-gray-500 fs-19 card-text">Access a vast catalog of services and applications for rapid deployment and innovation.</p>
innovation.</p>
</div> </div>
</div> </div>
</div> </div>
@ -94,10 +94,9 @@
<div class="card-body"> <div class="card-body">
<div class="d-flex align-items-center mb-3"> <div class="d-flex align-items-center mb-3">
<i class="bi bi-cloud-check-fill fs-2 text-primary me-3"></i> <i class="bi bi-cloud-check-fill fs-2 text-primary me-3"></i>
<h3 class="fs-24 fw-semibold card-title mb-0">Cloud-Agnostic &amp; Vendor-Independent</h3> <h3 class="fs-24 fw-semibold card-title mb-0">Sovereign &amp; Open</h3>
</div> </div>
<p class="text-gray-500 fs-19 card-text">Deploy services on any cloud or on-premises, ensuring maximum <p class="text-gray-500 fs-19 card-text">Deploy services on any cloud or on-premises, ensuring maximum flexibility.</p>
flexibility.</p>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block title %}Open Cloud Native Services Hub{% endblock %} {% block title %}Open Cloud Native Services Hub{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load contact_tags %} {% load contact_tags %}
{% block title %}Contact Us{% endblock %} {% block title %}Contact Us{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load form_tags %} {% load form_tags %}
{% block title %}Contact Us{% endblock %} {% block title %}Contact Us{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% block title %}{{ offering.service.name }} on {{ offering.cloud_provider.name }}{% endblock %} {% block title %}{{ offering.service.name }} on {{ offering.cloud_provider.name }}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% block title %}Service Offerings{% endblock %} {% block title %}Service Offerings{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load contact_tags %} {% load contact_tags %}
{% block title %}Consulting Partner {{ partner.name }}{% endblock %} {% block title %}Consulting Partner {{ partner.name }}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% load contact_tags %} {% load contact_tags %}
@ -120,6 +120,9 @@
</a> </a>
</div> </div>
</div> </div>
<h3 class="card__title">
<a href="{{ partner.get_absolute_url }}" class="text-decoration-none">{{ partner.name }}</a>
</h3>
</div> </div>
<div class="card__desc flex-grow-1 rich-text-content"> <div class="card__desc flex-grow-1 rich-text-content">

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load contact_tags %} {% load contact_tags %}
{% block title %}Service Provider {{ provider.name }}{% endblock %} {% block title %}Service Provider {{ provider.name }}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% load contact_tags %} {% load contact_tags %}
@ -103,6 +103,9 @@
</a> </a>
</div> </div>
</div> </div>
<h3 class="card__title">
<a href="{{ provider.get_absolute_url }}" class="text-decoration-none">{{ provider.name }}</a>
</h3>
</div> </div>
<div class="card__desc flex-grow-1 rich-text-content"> <div class="card__desc flex-grow-1 rich-text-content">

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% block title %}Service {{ service.name }}{% endblock %} {% block title %}Service {{ service.name }}{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% load static %} {% load static %}
{% load contact_tags %} {% load contact_tags %}

View file

@ -1,4 +1,4 @@
{% extends 'services/base.html' %} {% extends 'base.html' %}
{% block title %}Thanks{% endblock %} {% block title %}Thanks{% endblock %}

View file

@ -10,7 +10,7 @@ def partner_list(request):
cloud_provider_id = request.GET.get("cloud_provider", "") cloud_provider_id = request.GET.get("cloud_provider", "")
# Start with all active partners # Start with all active partners
partners = ConsultingPartner.objects.filter(disable_listing=False).order_by("name") partners = ConsultingPartner.objects.filter(disable_listing=False).order_by("order")
# Apply filters based on request parameters # Apply filters based on request parameters
if search_query: if search_query:
@ -36,7 +36,7 @@ def partner_list(request):
).distinct() ).distinct()
available_cloud_providers = CloudProvider.objects.filter( available_cloud_providers = CloudProvider.objects.filter(
id__in=available_cloud_provider_ids, disable_listing=False id__in=available_cloud_provider_ids, disable_listing=False
).order_by("name") ).order_by("order")
# For the current selection, we need to make sure we include the selected items # For the current selection, we need to make sure we include the selected items
# even if they don't match other filters # even if they don't match other filters
@ -64,7 +64,7 @@ def partner_list(request):
"partners": partners.prefetch_related("services", "cloud_providers"), "partners": partners.prefetch_related("services", "cloud_providers"),
"services": Service.objects.filter(disable_listing=False).order_by("name"), "services": Service.objects.filter(disable_listing=False).order_by("name"),
"cloud_providers": CloudProvider.objects.filter(disable_listing=False).order_by( "cloud_providers": CloudProvider.objects.filter(disable_listing=False).order_by(
"name" "order"
), ),
"available_services": available_services, "available_services": available_services,
"available_cloud_providers": available_cloud_providers, "available_cloud_providers": available_cloud_providers,