Merge pull request #27898 from rmehta/fix-error-not-found

fix(style): update error, not found pages
This commit is contained in:
Rushabh Mehta 2024-09-25 16:46:35 +05:30 committed by GitHub
commit 30cef42d8f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 172 additions and 249 deletions

View file

@ -12,7 +12,7 @@ context("Awesome Bar", () => {
beforeEach(() => {
let txt = `Search or type a command (${
window.navigator.platform === "MacIntel" ? "⌘" : "Ctrl"
} + G)`;
} + K)`;
cy.findByPlaceholderText(txt).as("awesome_bar");
cy.get("@awesome_bar").type("{selectall}");
});

View file

@ -9,7 +9,6 @@
"engine": "InnoDB",
"field_order": [
"title",
"column_break_oyyj",
"total_subscribers",
"sign_up_and_confirmation_section",
"confirmation_email_template",
@ -46,10 +45,6 @@
"label": "Welcome Email Template",
"options": "Email Template"
},
{
"fieldname": "column_break_oyyj",
"fieldtype": "Column Break"
},
{
"fieldname": "sign_up_and_confirmation_section",
"fieldtype": "Section Break",
@ -78,7 +73,7 @@
"link_fieldname": "email_group"
}
],
"modified": "2024-03-23 16:03:24.125724",
"modified": "2024-09-25 15:24:37.576084",
"modified_by": "Administrator",
"module": "Email",
"name": "Email Group",

View file

@ -258,6 +258,10 @@ Tip: use lucide.svg in /icons for all downloaded icons
fill="#E24C4C"></path>
</symbol>
<symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="icon-ban">
<circle cx="12" cy="12" r="10" /> <path d="m4.9 4.9 14.2 14.2" />
</symbol>
<symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="icon-lock">
<circle cx="12" cy="16" r="1"/><rect x="3" y="10" width="18" height="12" rx="2"/><path d="M7 10V7a5 5 0 0 1 10 0v3"/>
</symbol>

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

View file

@ -187,6 +187,7 @@ frappe.ui.keys.off = function (key, page) {
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+s",
action: function (e) {
document.activeElement?.blur();
frappe.app.trigger_primary_action();
e.preventDefault();
return false;
@ -205,6 +206,16 @@ frappe.ui.keys.add_shortcut({
description: __("Open Awesomebar"),
});
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+k",
action: function (e) {
$("#navbar-search").focus();
e.preventDefault();
return false;
},
description: __("Open Awesomebar"),
});
frappe.ui.keys.add_shortcut({
shortcut: "ctrl+h",
action: function (e) {

View file

@ -154,7 +154,7 @@ frappe.ui.Sidebar = class Sidebar {
{
app_name: "website",
app_title: __("Website"),
app_home: "/",
app_route: "/",
app_logo_url: "/assets/frappe/images/web.svg",
},
app_switcher_menu

View file

@ -26,7 +26,7 @@
id="navbar-search"
type="text"
class="form-control"
placeholder="{%= __('Search or type a command ({0})', [frappe.utils.is_mac() ? '⌘ + G' : 'Ctrl + G']) %}"
placeholder="{%= __('Search or type a command ({0})', [frappe.utils.is_mac() ? '⌘ + K' : 'Ctrl + K']) %}"
aria-haspopup="true"
>
<span class="search-icon">

View file

@ -76,7 +76,7 @@ frappe.breadcrumbs = {
if (
breadcrumbs.workspace &&
frappe.workspace_map[breadcrumbs.workspace].app != frappe.current_app
frappe.workspace_map[breadcrumbs.workspace]?.app != frappe.current_app
) {
frappe.app.sidebar.set_current_app(frappe.workspace_map[breadcrumbs.workspace].app);
}

View file

@ -243,7 +243,7 @@
}
textarea {
height: 46px !important;
height: 39px !important;
}
.form-control,

View file

@ -1,17 +1,24 @@
.error-page {
margin: 3rem 0;
text-align: center;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
.img-404 {
width: 40%;
margin: var(--margin-2xl) auto;
@include media-breakpoint-down(sm) {
width: 80%;
}
p,
h4 {
color: var(--text-light);
}
.back-to-home {
@include get_textstyle("base", "regular");
h4 {
text-align: center;
margin-top: 0px;
}
.details {
border-top: 1px solid var(--border-color);
margin-top: var(--margin-md);
padding-top: var(--padding-md);
max-width: 800px;
text-align: center;
}
}

View file

@ -13,7 +13,7 @@
</div>
{% block page_container %}
<main class="{% if not full_width %}container my-4{% endif %}">
<main class="{% if not full_width %}container{% endif %}">
<div class="page-header-wrapper">
<div class="page-header">
{% block header %}{% endblock %}

View file

@ -5,11 +5,8 @@ import re
from functools import partial
import frappe
from frappe.app import make_form_dict
from frappe.desk.search import get_names_for_mentions, search_link, search_widget
from frappe.tests.utils import FrappeTestCase
from frappe.utils import set_request
from frappe.website.serve import get_response
class TestSearch(FrappeTestCase):
@ -251,21 +248,3 @@ def teardown_test_link_field_order(TestCase):
)
TestCase.tree_doc.delete()
class TestWebsiteSearch(FrappeTestCase):
def get(self, path, user="Guest"):
frappe.set_user(user)
set_request(method="GET", path=path)
make_form_dict(frappe.local.request)
response = get_response()
frappe.set_user("Administrator")
return response
def test_basic_search(self):
no_search = self.get("/search")
self.assertEqual(no_search.status_code, 200)
response = self.get("/search?q=b")
self.assertEqual(response.status_code, 200)
self.assertIn("Search Results", response.get_data(as_text=True))

View file

@ -2,22 +2,29 @@
{%- block title -%}{{_("Not Found")}}{%- endblock -%}
{% block navbar %}{% endblock %}
{% block footer %}{% endblock %}
{% block page_content %}
<style>
body {
background-color: var(--subtle-accent);
font-size: var(--text-base);
}
</style>
<script>
window.is_404 = true;
</script>
<div class="error-page">
<img class="img-404" src="/assets/frappe/images/ui-states/404.png" />
<div>
<h2 class="mb-1 mt-4">
{{ _("There's nothing here") }}
</h2>
<div class="text-muted error-text">
{{ _("The page you are looking for has gone missing.") }}
<h4>
{{ _("Page not found") }}
</h4>
<div class="details">
<a href='/' class="text-muted">{{ _("Back to Home") }}</a>
</div>
<div class="mt-6 back-to-home"><a href='/' class='btn btn-primary'>{{ _("Back to Home") }}</a></div>
</div>
</div>

View file

@ -6,44 +6,50 @@
<link rel="stylesheet" href="/assets/frappe/css/hljs-night-owl.css">
{% endblock -%}
{% block navbar %}{% endblock %}
{% block footer %}{% endblock %}
{% block page_content %}
<style>
body {
background-color: var(--subtle-accent);
font-size: var(--text-base);
}
.error-content {
text-align: left;
margin-top: var(--margin-md);
border-radius: 8px;
background-color: #f5f7fa;
margin: 3rem auto;
max-height: 400px;
overflow: auto;
}
code::-webkit-scrollbar {
display: none;
}
{% include "templates/styles/card_style.css"%}
</style>
<script></script>
<div class="page-card">
<div class="page-card-head">
<span class="indicator red">{{ error_title }}</span>
</div>
<p>{{ error_message }}</p>
<div class="error-page">
<div>
<a href="/" class="btn btn-primary btn-sm">{{ _("Home") }}</a>
<h4>
{{ _("Error: {0}").format(http_status_code) }}
</h4>
<div class="details">
<p>{{ error_message }}</p>
<button class="btn btn-xs btn-secondary text-muted small view-error" >
{{ _("Show Error") }}
</button>
<div class="error-content hidden">
<pre><code>{{ error }}</code></pre>
</div>
</div>
</div>
</div>
<p class="text-muted text-center small" style="margin-top: -20px;">
{{ _("Error Code: {0}").format(http_status_code) }}
</p>
<div class="text-center mt-3">
<p class="text-muted text-center small">
If you don't know what just happened, and wish to file a ticket
please </br> <b>copy the error below </b> and share it.
</p>
<button class="btn btn-xs btn-secondary text-muted small view-error" >{{ _("Show Error") if not dev_server else _("Hide Error") }}</a>
</div>
<div class="error-content {{ 'hidden' if not dev_server else '' }}">
<pre><code>{{ error }}</code></pre>
</div>
{% endblock %}
{% block script %}

View file

@ -1,44 +1,35 @@
{% extends "templates/web.html" %}
{% block title %}{{ title or _("Message") }}{% endblock %}
{% block navbar %}{% endblock %}
{% block footer %}{% endblock %}
{% block page_content %}
<style>
{% include "templates/styles/card_style.css" %}
{% if fullpage %}
header, footer {
display: none;
}
html, body {
background-color: #f5f7fa;
}
{% endif %}
{% if card_width %}
.page-card {
max-width: {{ card_width }}px;
}
{% endif %}
body {
background-color: var(--subtle-accent);
font-size: var(--text-base);
}
</style>
<div class='page-card'>
<h5 class='page-card-head'>
<span class='indicator {{ indicator_color or "blue" }}'>
{{ title or _("Message") }}</span>
</h5>
<div class="page-card-body">
{% block message_body %}
{% if message %}
<p>{{ message }}</p>
{% endif %}
{% if primary_action %}
<div><a href='{{ primary_action or "/" }}' class='btn btn-primary btn-sm btn-block'>
{{ primary_label or _("Home") }}</a></div>
{% endif %}
{% endblock %}
<div class='error-page'>
<div>
<h4 class='page-card-head'>{{ title or _("Message") }}</h4>
<div class="details">
{% block message_body %}
{% if message %}
<p>{{ message }}</p>
{% if error_code %}
<p class='text-muted text-center small' style='margin-top: -20px;'>{{ _("Status: {0}").format(error_code) }}</p>
{% endif %}
{% endif %}
{% if primary_action %}
<div><a href='{{ primary_action or "/" }}' class='btn btn-primary btn-sm btn-block'>
{{ primary_label or _("Home") }}</a></div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
{% if error_code %}
<p class='text-muted text-center small' style='margin-top: -20px;'>{{ _("Status: {0}").format(error_code) }}</p>
{% endif %}
<script>
frappe.ready(function() {
if (window.location.hash || window.location.href.includes('/app')) {

View file

@ -1,25 +0,0 @@
{% extends "templates/web.html" %}
{% block page_content %}
{% include "templates/includes/search_template.html" %}
<script>
frappe.ready(function() {
$('.btn-more').on('click', function() {
frappe.call({
method: 'frappe.www.search.get_search_results',
args: {
text: '{{ query }}',
start: $('.search-result-item').length,
as_html: 1
},
callback: function(r) {
$(r.message.results).appendTo('.search-result');
$('.btn-more').toggleClass('hidden', !!!r.message.has_more);
}
});
});
});
</script>
{% endblock %}

View file

@ -1,63 +0,0 @@
import markupsafe
import frappe
from frappe import _
from frappe.core.utils import html2text
from frappe.utils import sanitize_html
from frappe.utils.global_search import web_search
def get_context(context):
context.no_cache = 1
if frappe.form_dict.q:
query = str(markupsafe.escape(sanitize_html(frappe.form_dict.q)))
context.title = _("Search Results for")
context.query = query
context.route = "/search"
context.update(get_search_results(query, frappe.utils.sanitize_html(frappe.form_dict.scope)))
else:
context.title = _("Search")
@frappe.whitelist(allow_guest=True)
def get_search_results(text: str, scope: str | None = None, start: int = 0, as_html: bool = False):
results = web_search(text, scope, start, limit=21)
out = frappe._dict()
if len(results) == 21:
out.has_more = 1
results = results[:20]
for d in results:
try:
d.content = html2text(d.content)
index = d.content.lower().index(text.lower())
d.content = (
d.content[:index]
+ "<mark>"
+ d.content[index:][: len(text)]
+ "</mark>"
+ d.content[index + len(text) :]
)
if index < 40:
start = 0
prefix = ""
else:
start = index - 40
prefix = "..."
suffix = ""
if (index + len(text) + 47) < len(d.content):
suffix = "..."
d.preview = prefix + d.content[start : start + len(text) + 87] + suffix
except Exception:
d.preview = html2text(d.content)[:97] + "..."
out.results = results
if as_html:
out.results = frappe.render_template("templates/includes/search_result.html", out)
return out

View file

@ -2,93 +2,106 @@
{% block title %} Unsubscribe from Newsletter {% endblock %}
{% block navbar %}{% endblock %}
{% block footer %}{% endblock %}
{% block page_content %}
<style>
body {
background-color: var(--subtle-accent);
font-size: var(--text-base);
}
</style>
<script>
frappe.ready(function() {
$("#select-all-btn").click(function() {
$(".group").prop('checked', true);
<script>
frappe.ready(function() {
$("#select-all-btn").click(function() {
$(".group").prop('checked', true);
});
$("#unselect-all-btn").click(function() {
$(".group").prop('checked', false);
});
});
</script>
$("#unselect-all-btn").click(function() {
$(".group").prop('checked', false);
});
});
</script>
{% if status == "waiting_for_confirmation" %}
<!-- Confirmation page to select the group to unsubscribe -->
<div class="page-card ">
<div class='page-card-head'>
<span class='indicator blue'>Unsubscribe</span>
</div>
{% if email_groups %}
<div>
Select groups you wish to unsubscribe from.
<span class="text-muted">{{ email }}</span>
</div>
<!-- Show 'Select All' or 'Unselect All' buttons only if there are more than 5 groups -->
{% if email_groups|length > 5 %}
<button id="select-all-btn"class="small-btn">Select All</button>
<button id="unselect-all-btn"class="small-btn">Unselect All</button>
{% endif %}
{% if status == "waiting_for_confirmation" %}
<!-- Confirmation page to select the group to unsubscribe -->
<div class="portal-container ">
<div class='portal-section head d-block'>
<div class="title">{{_("Unsubscribe")}}</div>
<div class="text-muted">Select groups you wish to unsubscribe from ({{ email }})</div>
<!-- Show 'Select All' or 'Unselect All' buttons only if there are more than 5 groups -->
{% if email_groups|length > 5 %}
<button id="select-all-btn"class="small-btn">Select All</button>
<button id="unselect-all-btn"class="small-btn">Unselect All</button>
{% endif %}
</div>
{% if email_groups %}
<form method="post">
<input type="hidden" name="user_email" value="{{ email }}">
<input type="hidden" name="csrf_token" value="{{ frappe.session.csrf_token }}">
<!-- Break into columns if there are more than 20 groups -->
<div class="checkbox-container {% if email_groups|length > 10 %} row {% endif %}">
<div class="portal-items">
{% for group in email_groups %}
<div class="checkbox {% if email_groups|length > 10 %} col-sm-6 {% endif %}">
<div class="checkbox portal-section d-block">
<label>
<input
type="checkbox"
{% if current_group[0].email_group == group.email_group %} checked {% endif %}
{% if current_group[0] and current_group[0].email_group == group.email_group %} checked {% endif %}
class="group"
name='{{ group.email_group }}'>
<span style="padding-left: 10px">{{ group.email_group }}</span>
<span style="padding-left: 5px">{{ group.email_group }}</span>
</label>
</div>
{% endfor %}
</div>
<div class="portal-section mt-3">
<button
type="submit"
id="unsubscribe"
class="btn btn-primary">
Unsubscribe
</button>
</div>
</form>
{% else %}
<div>
You are not registered to any mailing list.
<span class="text-muted">{{ email }}</span>
</div>
{% endif %}
</div>
{% elif status == "unsubscribed" %}
<!-- Unsubscribed page comes after submission -->
<div class="page-card">
<div class='page-card-head'>
<span class='indicator green'>Unsubscribed</span>
</div>
{% else %}
<div>
You are not registered to any mailing list.
<span class="text-muted">{{ email }}</span>
</div>
{% endif %}
</div>
</div>
{% elif status == "unsubscribed" %}
<!-- Unsubscribed page comes after submission -->
<div class="portal-container">
<div class='portal-section head'>
<div class="title">Unsubscribed</div>
</div>
<div class="portal-section">
You have been unsubscribed from selected mailing list.
</div>
</div>
{% else %}
<!-- For invalid and unsigned request -->
<div class="page-card">
<div class='page-card-head'>
<span class='indicator red'>Unsubscribe</span>
</div>
<b>Invalid Request.</b>
</div>
{% endif %}
{% else %}
<!-- For invalid and unsigned request -->
<div class="portal-container">
<div class='portal-section head'>
<div class="title">Unsubscribe</div>
</div>
<div class="portal-section">
Invalid request
</div>
</div>
{% endif %}
{% endblock %}
{% block style %}
<style>
{% include "templates/styles/card_style.css" %}
.small-btn {
padding: 1px 5px;
font-size: 12px;
@ -99,9 +112,6 @@
border-color: transparent;
margin: 15px 5px 0 0;
}
.checkbox-container {
margin-top: 20px;
}
.main-div {
width: 500px;
height: auto;

View file

@ -12,10 +12,11 @@ def get_context(context):
if verify_request():
user_email = frappe.form_dict["email"]
context.email = user_email
title = frappe.form_dict["name"]
title = frappe.form_dict.get("name")
context.email_groups = get_email_groups(user_email)
context.current_group = get_current_groups(title)
context.status = "waiting_for_confirmation"
print(context)
# Called when form is submitted.
elif "user_email" in frappe.form_dict and frappe.request.method == "POST":