mirror of https://github.com/zulip/zulip.git
parent
b859cc4a3d
commit
379c6acbea
|
@ -9,6 +9,7 @@ from corporate.views.event_status import event_status, event_status_page
|
||||||
from corporate.views.portico import (
|
from corporate.views.portico import (
|
||||||
app_download_link_redirect,
|
app_download_link_redirect,
|
||||||
apps_view,
|
apps_view,
|
||||||
|
communities_view,
|
||||||
hello_view,
|
hello_view,
|
||||||
landing_view,
|
landing_view,
|
||||||
plans_view,
|
plans_view,
|
||||||
|
@ -125,6 +126,7 @@ landing_page_urls = [
|
||||||
landing_view,
|
landing_view,
|
||||||
{"template_name": "corporate/case-studies/recurse-center-case-study.html"},
|
{"template_name": "corporate/case-studies/recurse-center-case-study.html"},
|
||||||
),
|
),
|
||||||
|
path("communities/", communities_view),
|
||||||
]
|
]
|
||||||
i18n_urlpatterns += landing_page_urls
|
i18n_urlpatterns += landing_page_urls
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ from django.template.response import TemplateResponse
|
||||||
from zerver.context_processors import get_realm_from_request, latest_info_context
|
from zerver.context_processors import get_realm_from_request, latest_info_context
|
||||||
from zerver.decorator import add_google_analytics
|
from zerver.decorator import add_google_analytics
|
||||||
from zerver.lib.github import InvalidPlatform, get_latest_github_release_download_link_for_platform
|
from zerver.lib.github import InvalidPlatform, get_latest_github_release_download_link_for_platform
|
||||||
|
from zerver.lib.realm_description import get_realm_text_description
|
||||||
|
from zerver.lib.realm_icon import get_realm_icon_url
|
||||||
from zerver.lib.subdomains import is_subdomain_root_or_alias
|
from zerver.lib.subdomains import is_subdomain_root_or_alias
|
||||||
from zerver.models import Realm
|
from zerver.models import Realm
|
||||||
|
|
||||||
|
@ -103,3 +105,47 @@ def landing_view(request: HttpRequest, template_name: str) -> HttpResponse:
|
||||||
@add_google_analytics
|
@add_google_analytics
|
||||||
def hello_view(request: HttpRequest) -> HttpResponse:
|
def hello_view(request: HttpRequest) -> HttpResponse:
|
||||||
return TemplateResponse(request, "corporate/hello.html", latest_info_context())
|
return TemplateResponse(request, "corporate/hello.html", latest_info_context())
|
||||||
|
|
||||||
|
|
||||||
|
@add_google_analytics
|
||||||
|
def communities_view(request: HttpRequest) -> HttpResponse:
|
||||||
|
eligible_realms = []
|
||||||
|
unique_org_type_ids = set()
|
||||||
|
want_to_be_advertised_realms = Realm.objects.filter(
|
||||||
|
want_advertise_in_communities_directory=True
|
||||||
|
).order_by("name")
|
||||||
|
for realm in want_to_be_advertised_realms:
|
||||||
|
if realm.allow_web_public_streams_access():
|
||||||
|
eligible_realms.append(
|
||||||
|
{
|
||||||
|
"id": realm.id,
|
||||||
|
"name": realm.name,
|
||||||
|
"realm_url": realm.uri,
|
||||||
|
"logo_url": get_realm_icon_url(realm),
|
||||||
|
"description": get_realm_text_description(realm),
|
||||||
|
"org_type_key": [
|
||||||
|
org_type
|
||||||
|
for org_type in Realm.ORG_TYPES
|
||||||
|
if Realm.ORG_TYPES[org_type]["id"] == realm.org_type
|
||||||
|
][0],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
unique_org_type_ids.add(realm.org_type)
|
||||||
|
|
||||||
|
# Remove org_types for which there are no open organizations.
|
||||||
|
org_types = dict()
|
||||||
|
for org_type in Realm.ORG_TYPES:
|
||||||
|
if Realm.ORG_TYPES[org_type]["id"] in unique_org_type_ids:
|
||||||
|
org_types[org_type] = Realm.ORG_TYPES[org_type]
|
||||||
|
|
||||||
|
# Remove `Unspecified` ORG_TYPE
|
||||||
|
org_types.pop("unspecified", None)
|
||||||
|
|
||||||
|
return TemplateResponse(
|
||||||
|
request,
|
||||||
|
"corporate/communities.html",
|
||||||
|
context={
|
||||||
|
"eligible_realms": eligible_realms,
|
||||||
|
"org_types": org_types,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import $ from "jquery";
|
||||||
|
|
||||||
|
function sync_open_organizations_page_with_current_hash() {
|
||||||
|
const hash = window.location.hash;
|
||||||
|
if (!hash || hash === "#all" || hash === "#undefined") {
|
||||||
|
$(".eligible_realm").show();
|
||||||
|
$(".realm-category").removeClass("selected");
|
||||||
|
$(`[data-category="all"]`).addClass("selected");
|
||||||
|
} else {
|
||||||
|
$(".eligible_realm").hide();
|
||||||
|
$(`.eligible_realm[data-org-type="${CSS.escape(hash.slice(1))}"]`).show();
|
||||||
|
$(".realm-category").removeClass("selected");
|
||||||
|
$(`[data-category="${CSS.escape(hash.slice(1))}"]`).addClass("selected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// init
|
||||||
|
$(() => {
|
||||||
|
sync_open_organizations_page_with_current_hash();
|
||||||
|
$(window).on("hashchange", () => {
|
||||||
|
sync_open_organizations_page_with_current_hash();
|
||||||
|
});
|
||||||
|
});
|
|
@ -342,7 +342,8 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.integration-category {
|
.integration-category,
|
||||||
|
.realm-category {
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
@ -390,7 +391,8 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.integration-category {
|
.integration-category,
|
||||||
|
.realm-category {
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +418,8 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.integration-category {
|
.integration-category,
|
||||||
|
.realm-category {
|
||||||
font-size: 0.77em;
|
font-size: 0.77em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -465,7 +468,8 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
margin: 0 21px 20px;
|
margin: 0 21px 20px;
|
||||||
order: 1;
|
order: 1;
|
||||||
|
|
||||||
.integration-category {
|
.integration-category,
|
||||||
|
.realm-category {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,7 +505,8 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
.categories {
|
.categories {
|
||||||
order: 2;
|
order: 2;
|
||||||
|
|
||||||
.integration-category {
|
.integration-category,
|
||||||
|
.realm-category {
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
padding: 6px 3px;
|
padding: 6px 3px;
|
||||||
|
@ -585,3 +590,89 @@ $category-text: hsl(219, 23%, 33%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.portico-landing.integrations.communities {
|
||||||
|
.main {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portico-page-heading {
|
||||||
|
color: hsl(0, 0%, 0%);
|
||||||
|
font-size: 44px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.portico-page-subheading {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: hsl(0, 0%, 20%);
|
||||||
|
max-width: 340px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.integration-categories-sidebar h3 {
|
||||||
|
color: hsl(0, 0%, 0%);
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog {
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eligible_realms {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 30px;
|
||||||
|
|
||||||
|
.eligible_realm {
|
||||||
|
display: flex;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid hsl(167, 34%, 56%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.eligible_realm_logo {
|
||||||
|
display: flex;
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eligible_realm_details {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.eligible_realm_name {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 21px;
|
||||||
|
color: hsl(220.6, 20%, 33.3%);
|
||||||
|
line-height: 23px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eligible_realm_description {
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 15px;
|
||||||
|
color: hsl(220, 2.7%, 56.5%);
|
||||||
|
line-height: 19px;
|
||||||
|
margin: 0;
|
||||||
|
width: min(600px, 50vw);
|
||||||
|
/* For restricting text to only two lines.
|
||||||
|
See https://caniuse.com/?search=display%3A%20-webkit-box for support. */
|
||||||
|
overflow: hidden;
|
||||||
|
display: -webkit-box; /* stylelint-disable-line value-no-vendor-prefix */
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.eligible_realm_end_notice {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
{% extends "zerver/portico.html" %}
|
||||||
|
{% set entrypoint = "communities" %}
|
||||||
|
|
||||||
|
{% block customhead %}
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block hello_page_container %} hello-main{% endblock %}
|
||||||
|
|
||||||
|
{% block portico_content %}
|
||||||
|
|
||||||
|
{% include 'zerver/landing_nav.html' %}
|
||||||
|
{% include 'zerver/gradients.html' %}
|
||||||
|
|
||||||
|
<div class="portico-landing integrations communities">
|
||||||
|
<div class="main">
|
||||||
|
<div class="padded-content">
|
||||||
|
<div class="inner-content">
|
||||||
|
|
||||||
|
<div class="integration-main-text">
|
||||||
|
<header>
|
||||||
|
<h1 class="portico-page-heading">
|
||||||
|
{% trans %}Open communities directory{% endtrans %}
|
||||||
|
</h1>
|
||||||
|
<p class="portico-page-subheading">
|
||||||
|
These Zulip communities are open to the public, and have
|
||||||
|
<a href="/help/communities-directory">asked to be listed</a>.
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="integration-categories-dropdown">
|
||||||
|
<div class="dropdown-toggle">
|
||||||
|
<h3 class="dropdown-category-label">{% trans %}Filter by category{% endtrans %}</h3>
|
||||||
|
<i class="fa fa-angle-down" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="dropdown-list">
|
||||||
|
<a href="#all">
|
||||||
|
<h4 class="realm-category selected" data-category="all">All</h4>
|
||||||
|
</a>
|
||||||
|
{% for org_type in org_types.keys() %}
|
||||||
|
<a href="#{{ org_type }}">
|
||||||
|
<h4 class="realm-category" data-category="{{ org_type }}">
|
||||||
|
{{ org_types[org_type]["name"] }}
|
||||||
|
</h4>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="catalog">
|
||||||
|
<div class="integration-categories-sidebar">
|
||||||
|
<h3>{% trans %}Categories{% endtrans %}</h3>
|
||||||
|
<a href="#all">
|
||||||
|
<h4 data-category="all" class="realm-category selected">{% trans %}All{% endtrans %}</h4>
|
||||||
|
</a>
|
||||||
|
{% for org_type in org_types.keys() %}
|
||||||
|
<a href="#{{ org_type }}">
|
||||||
|
<h4 data-category="{{ org_type }}" class="realm-category">
|
||||||
|
{{ org_types[org_type]["name"] }}
|
||||||
|
</h4>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
<div class="eligible_realms">
|
||||||
|
{% for eligible_realm in eligible_realms %}
|
||||||
|
<a class="eligible_realm" data-org-type="{{ eligible_realm.org_type_key }}" href="{{ eligible_realm.realm_url }}">
|
||||||
|
<img class="eligible_realm_logo" src="{{ eligible_realm.logo_url }}" alt="{{ eligible_realm.name }} logo"/>
|
||||||
|
<div class="eligible_realm_details">
|
||||||
|
<h3 class="eligible_realm_name">{{ eligible_realm.name }}</h3>
|
||||||
|
<h4 class="eligible_realm_description">
|
||||||
|
{{ eligible_realm.description }}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
<hr />
|
||||||
|
<div class="eligible_realm_end_notice">
|
||||||
|
<p>Learn how Zulip can be a <a href="/for/communities">home for your community</a>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div> <!-- .inner-content -->
|
||||||
|
</div> <!-- .padded-content -->
|
||||||
|
</div> <!-- .main -->
|
||||||
|
</div> <!-- .portico-landing -->
|
||||||
|
|
||||||
|
{% endblock %}
|
|
@ -57,6 +57,12 @@
|
||||||
"./static/styles/portico/landing_page.css",
|
"./static/styles/portico/landing_page.css",
|
||||||
"./static/styles/portico/integrations.css"
|
"./static/styles/portico/integrations.css"
|
||||||
],
|
],
|
||||||
|
"communities": [
|
||||||
|
"./static/js/bundles/portico",
|
||||||
|
"./static/js/portico/communities",
|
||||||
|
"./static/styles/portico/landing_page.css",
|
||||||
|
"./static/styles/portico/integrations.css"
|
||||||
|
],
|
||||||
"signup": ["./static/js/bundles/portico", "jquery-validation", "./static/js/portico/signup"],
|
"signup": ["./static/js/bundles/portico", "jquery-validation", "./static/js/portico/signup"],
|
||||||
"register": ["./static/js/bundles/portico", "jquery-validation", "./static/js/portico/signup"],
|
"register": ["./static/js/bundles/portico", "jquery-validation", "./static/js/portico/signup"],
|
||||||
"confirm-preregistrationuser": [
|
"confirm-preregistrationuser": [
|
||||||
|
|
|
@ -199,6 +199,13 @@ class DocPageTest(ZulipTestCase):
|
||||||
result = self.client_get("/for/companies/", follow=True)
|
result = self.client_get("/for/companies/", follow=True)
|
||||||
self.assert_in_success_response(["Communication efficiency represents"], result)
|
self.assert_in_success_response(["Communication efficiency represents"], result)
|
||||||
|
|
||||||
|
def test_open_organizations_endpoint(self) -> None:
|
||||||
|
realm = get_realm("zulip")
|
||||||
|
realm.want_advertise_in_communities_directory = True
|
||||||
|
realm.save()
|
||||||
|
|
||||||
|
self._test("/communities/", "Open communities directory")
|
||||||
|
|
||||||
def test_portico_pages_open_graph_metadata(self) -> None:
|
def test_portico_pages_open_graph_metadata(self) -> None:
|
||||||
# Why Zulip
|
# Why Zulip
|
||||||
url = "/why-zulip/"
|
url = "/why-zulip/"
|
||||||
|
|
Loading…
Reference in New Issue