Compare commits
3 Commits
3de1c033c5
...
ed70c742df
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed70c742df | ||
|
|
320bdda242 | ||
|
|
35362b48c1 |
@ -1,5 +1,5 @@
|
||||
.newsletter-page {
|
||||
background: #0e1b42 url("../img/newsletter_bg.png") center center / cover no-repeat fixed;
|
||||
background: #0e1b42 url("../img/newsletter_bg.webp") center center / cover no-repeat fixed;
|
||||
}
|
||||
|
||||
.newsletter-page .site-main > .site-container {
|
||||
@ -170,4 +170,4 @@
|
||||
.newsletter-back-link__text {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
innovedus_cms/base/static/img/email/facebook-white.original.png
Normal file
|
After Width: | Height: | Size: 922 B |
BIN
innovedus_cms/base/static/img/email/instagram-white.original.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
innovedus_cms/base/static/img/email/logo.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
innovedus_cms/base/static/img/email/mailback.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
innovedus_cms/base/static/img/email/threads-white.original.png
Normal file
|
After Width: | Height: | Size: 841 B |
BIN
innovedus_cms/base/static/img/newsletter_bg.webp
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
innovedus_cms/base/static/img/og_default.jpg
Normal file
|
After Width: | Height: | Size: 49 KiB |
@ -143,46 +143,46 @@ def contact_form_submit(request):
|
||||
except Exception as exc:
|
||||
logger.warning("contact form admin notification email failed: %s", exc)
|
||||
|
||||
if submission.email:
|
||||
values_text = {
|
||||
"name": submission.name,
|
||||
"email": submission.email,
|
||||
"contact": submission.contact,
|
||||
"category": submission.get_category_display(),
|
||||
"message": submission.message,
|
||||
"source_page": submission.source_page or "",
|
||||
}
|
||||
values_html = {
|
||||
"name": escape(submission.name),
|
||||
"email": escape(submission.email),
|
||||
"contact": escape(submission.contact),
|
||||
"category": escape(submission.get_category_display()),
|
||||
"message": escape(submission.message).replace("\n", "<br>"),
|
||||
"source_page": escape(submission.source_page or ""),
|
||||
}
|
||||
user_subject = _render_contact_template(
|
||||
notification_settings.contact_form_user_subject_template,
|
||||
values_text,
|
||||
)
|
||||
user_text = _render_contact_template(
|
||||
notification_settings.contact_form_user_text_template,
|
||||
values_text,
|
||||
)
|
||||
user_html = _render_contact_template(
|
||||
notification_settings.contact_form_user_html_template,
|
||||
values_html,
|
||||
)
|
||||
try:
|
||||
send_contact_user_email(
|
||||
to_email=submission.email,
|
||||
subject=user_subject,
|
||||
text_body=user_text,
|
||||
html_body=user_html,
|
||||
notification_config=notification_settings,
|
||||
smtp_config=smtp_settings,
|
||||
)
|
||||
except Exception as exc:
|
||||
logger.warning("contact form user copy email failed: %s", exc)
|
||||
# if submission.email:
|
||||
# values_text = {
|
||||
# "name": submission.name,
|
||||
# "email": submission.email,
|
||||
# "contact": submission.contact,
|
||||
# "category": submission.get_category_display(),
|
||||
# "message": submission.message,
|
||||
# "source_page": submission.source_page or "",
|
||||
# }
|
||||
# values_html = {
|
||||
# "name": escape(submission.name),
|
||||
# "email": escape(submission.email),
|
||||
# "contact": escape(submission.contact),
|
||||
# "category": escape(submission.get_category_display()),
|
||||
# "message": escape(submission.message).replace("\n", "<br>"),
|
||||
# "source_page": escape(submission.source_page or ""),
|
||||
# }
|
||||
# user_subject = _render_contact_template(
|
||||
# notification_settings.contact_form_user_subject_template,
|
||||
# values_text,
|
||||
# )
|
||||
# user_text = _render_contact_template(
|
||||
# notification_settings.contact_form_user_text_template,
|
||||
# values_text,
|
||||
# )
|
||||
# user_html = _render_contact_template(
|
||||
# notification_settings.contact_form_user_html_template,
|
||||
# values_html,
|
||||
# )
|
||||
# try:
|
||||
# send_contact_user_email(
|
||||
# to_email=submission.email,
|
||||
# subject=user_subject,
|
||||
# text_body=user_text,
|
||||
# html_body=user_html,
|
||||
# notification_config=notification_settings,
|
||||
# smtp_config=smtp_settings,
|
||||
# )
|
||||
# except Exception as exc:
|
||||
# logger.warning("contact form user copy email failed: %s", exc)
|
||||
|
||||
if request.headers.get("x-requested-with") == "XMLHttpRequest":
|
||||
return JsonResponse({"success": True})
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import os
|
||||
|
||||
from django.contrib.syndication.views import Feed
|
||||
from django.utils.feedgenerator import Rss201rev2Feed
|
||||
from django.utils.html import strip_tags
|
||||
@ -5,6 +7,20 @@ from django.utils.html import strip_tags
|
||||
from .models import ArticlePage
|
||||
|
||||
|
||||
def _get_env_int(name, default):
|
||||
value = os.environ.get(name)
|
||||
if value is None:
|
||||
return default
|
||||
try:
|
||||
parsed = int(value)
|
||||
except ValueError:
|
||||
return default
|
||||
return parsed if parsed > 0 else default
|
||||
|
||||
|
||||
ARTICLE_FEED_SIZE = _get_env_int("ARTICLE_FEED_SIZE", 50)
|
||||
|
||||
|
||||
class LatestArticlesFeed(Feed):
|
||||
feed_type = Rss201rev2Feed
|
||||
title = "DeBuT AI 最新文章"
|
||||
@ -12,7 +28,7 @@ class LatestArticlesFeed(Feed):
|
||||
description = "DeBuT AI 最新文章 RSS feed"
|
||||
|
||||
def items(self):
|
||||
return ArticlePage.objects.live().order_by("-date", "-id")[:20]
|
||||
return ArticlePage.objects.live().order_by("-date", "-id")[:ARTICLE_FEED_SIZE]
|
||||
|
||||
def item_title(self, item):
|
||||
return item.title
|
||||
|
||||
@ -141,23 +141,27 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin: 40px 0 20px;
|
||||
font-size: 14px;
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 15px;
|
||||
letter-spacing: 0.3em;
|
||||
}
|
||||
|
||||
.page-size-label {
|
||||
color: #0e1b4266;
|
||||
color: #0e1b42;
|
||||
}
|
||||
|
||||
.page-size-option {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 40px;
|
||||
height: 32px;
|
||||
min-width: 37px;
|
||||
height: 24px;
|
||||
border: 1px solid #0e1b42;
|
||||
border-radius: 4px;
|
||||
color: #0e1b42;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.page-size-option.is-current {
|
||||
|
||||
@ -11,6 +11,21 @@
|
||||
line-height: 60px;
|
||||
}
|
||||
|
||||
.category-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.category-toolbar .category-title {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.category-toolbar .page-size-selector {
|
||||
margin: 0 0 0 auto;
|
||||
}
|
||||
|
||||
.subcategory-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -38,6 +53,16 @@
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.category-toolbar {
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.category-toolbar .page-size-selector {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.subcategory-title::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
BIN
innovedus_cms/home/static/img/default_cover_1.jpg
Normal file
|
After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 247 KiB |
BIN
innovedus_cms/home/static/img/default_cover_2.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 212 KiB |
BIN
innovedus_cms/home/static/img/default_cover_3.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 150 KiB |
@ -27,8 +27,11 @@
|
||||
</nav>
|
||||
{% endif %}
|
||||
<div class="site-hero-band full-bleed">
|
||||
<div class="site-container">
|
||||
<div class="site-container category-toolbar">
|
||||
<div class="block-title category-title"><span>{{ self.title}}</span></div>
|
||||
{% if not page.has_subcategories %}
|
||||
{% include "home/includes/page_size_selector.html" with category=category_sections.0 %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if page.has_subcategories %}
|
||||
|
||||
@ -5,8 +5,9 @@
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<div class="site-hero-band full-bleed">
|
||||
<div class="site-container">
|
||||
<div class="site-container category-toolbar">
|
||||
<div class="block-title category-title"><span>#{{ tag.name }}</span></div>
|
||||
{% include "home/includes/page_size_selector.html" with category=category_sections.0 %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -6,19 +6,6 @@
|
||||
<div class="page-article-list">
|
||||
{% include "home/includes/article_list.html" with items=category.items show_hero=show_hero empty_message=empty_message %}
|
||||
|
||||
{% if category.pagination.page_size_options %}
|
||||
<div class="page-size-selector" aria-label="每頁文章數">
|
||||
<span class="page-size-label">每頁</span>
|
||||
{% for option in category.pagination.page_size_options %}
|
||||
{% if option.is_current %}
|
||||
<span class="page-size-option is-current">{{ option.value }}</span>
|
||||
{% else %}
|
||||
<a class="page-size-option" href="{{ option.url }}">{{ option.value }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if category.items.paginator.num_pages > 1 %}
|
||||
<div class="pagination">
|
||||
{% if category.items.has_previous %}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
{% if category.pagination.page_size_options %}
|
||||
<div class="page-size-selector" aria-label="每頁文章數">
|
||||
<span class="page-size-label">每頁顯示</span>
|
||||
{% for option in category.pagination.page_size_options %}
|
||||
{% if option.is_current %}
|
||||
<span class="page-size-option is-current">{{ option.value }}</span>
|
||||
{% else %}
|
||||
<span class="page-size-option">
|
||||
<a href="{{ option.url }}">{{ option.value }}</a>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -9,8 +9,8 @@ register = template.Library()
|
||||
@register.simple_tag
|
||||
def random_default_cover():
|
||||
choices = (
|
||||
"img/default_cover_1.png",
|
||||
"img/default_cover_2.png",
|
||||
"img/default_cover_3.png",
|
||||
"img/default_cover_1.jpg",
|
||||
"img/default_cover_2.jpg",
|
||||
"img/default_cover_3.jpg",
|
||||
)
|
||||
return static(random.choice(choices))
|
||||
|
||||
@ -1,7 +1,19 @@
|
||||
from django.conf import settings
|
||||
from django.templatetags.static import static
|
||||
|
||||
|
||||
def ga4(request):
|
||||
return {
|
||||
"ga4_measurement_id": getattr(settings, "GA4_MEASUREMENT_ID", ""),
|
||||
}
|
||||
|
||||
|
||||
def default_og_image(request):
|
||||
return {
|
||||
"default_og_image": {
|
||||
"url": request.build_absolute_uri(static("img/og_default.jpg")),
|
||||
"width": 528,
|
||||
"height": 337,
|
||||
"alt": "DeBuT AI",
|
||||
},
|
||||
}
|
||||
|
||||
@ -177,6 +177,7 @@ TEMPLATES = [
|
||||
"wagtail.contrib.settings.context_processors.settings",
|
||||
"home.context_processors.navigation_pages",
|
||||
"mysite.context_processors.ga4",
|
||||
"mysite.context_processors.default_og_image",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
@ -321,6 +321,21 @@ a {
|
||||
color: #0e1b42;
|
||||
}
|
||||
|
||||
.template-darkbackground .page-size-label {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.template-darkbackground .page-size-option {
|
||||
border-color: #ffffffb3;
|
||||
color: #ffffffb3;
|
||||
}
|
||||
|
||||
.template-darkbackground .page-size-option.is-current {
|
||||
background-color: #ffffffb3;
|
||||
background-clip: padding-box;
|
||||
color: #0e1b42;
|
||||
}
|
||||
|
||||
.template-darkbackground .site-hero-band .news-title {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
@ -16,11 +16,12 @@
|
||||
{% if page.search_description %}
|
||||
<meta name="description" content="{{ page.search_description }}" />
|
||||
{% endif %}
|
||||
{% if og_image %}
|
||||
<meta property="og:image" content="{{ og_image.url }}" />
|
||||
<meta property="og:image:width" content="{{ og_image.width }}" />
|
||||
<meta property="og:image:height" content="{{ og_image.height }}" />
|
||||
<meta property="og:image:alt" content="{{ og_image.alt }}" />
|
||||
{% firstof og_image default_og_image as resolved_og_image %}
|
||||
{% if resolved_og_image %}
|
||||
<meta property="og:image" content="{{ resolved_og_image.url }}" />
|
||||
<meta property="og:image:width" content="{{ resolved_og_image.width }}" />
|
||||
<meta property="og:image:height" content="{{ resolved_og_image.height }}" />
|
||||
<meta property="og:image:alt" content="{{ resolved_og_image.alt }}" />
|
||||
{% endif %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="alternate" type="application/rss+xml" title="DeBuT AI 最新文章 RSS" href="{% url 'article_feed' %}">
|
||||
|
||||
@ -14,8 +14,11 @@
|
||||
{% block content %}
|
||||
{% if search_query %}
|
||||
<div class="site-hero-band full-bleed">
|
||||
<div class="site-container">
|
||||
<div class="site-container category-toolbar">
|
||||
<div class="block-title category-title"><span>{{ search_query }}</span></div>
|
||||
{% if results_count %}
|
||||
{% include "home/includes/page_size_selector.html" with category=category_sections.0 %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||