fix: search ux
This commit is contained in:
@@ -176,7 +176,7 @@ def search_course(text):
|
|||||||
"short_introduction": ["like", f"%{text}%"],
|
"short_introduction": ["like", f"%{text}%"],
|
||||||
"description": ["like", f"%{text}%"],
|
"description": ["like", f"%{text}%"],
|
||||||
},
|
},
|
||||||
fields=["name", "title", "image"],
|
fields=["name", "title"],
|
||||||
)
|
)
|
||||||
return courses
|
return courses
|
||||||
|
|
||||||
|
|||||||
@@ -929,13 +929,16 @@ pre {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
|
background-image: url(/assets/frappe/icons/timeless/search.svg);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: 1rem;
|
||||||
|
text-indent: 1rem;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: var(--border-radius-md);
|
border-radius: var(--border-radius-md);
|
||||||
font-size: var(--text-base);
|
font-size: var(--text-base);
|
||||||
padding: 0.625rem 0.75rem;
|
padding: 1.5rem;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
width: 80%;
|
width: 100%;
|
||||||
box-shadow: var(--shadow-base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.search:focus {
|
.search:focus {
|
||||||
@@ -1934,7 +1937,9 @@ select {
|
|||||||
|
|
||||||
.modal-inner {
|
.modal-inner {
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
margin: 15% auto 2rem;
|
margin: 15% auto 2rem;
|
||||||
|
width: 70%;
|
||||||
|
border-radius: var(--border-radius-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1951,3 +1956,28 @@ select {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.result-row {
|
||||||
|
display: block;
|
||||||
|
padding: 1rem;
|
||||||
|
border-top: 1px solid var(--gray-300);
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--gray-900);
|
||||||
|
font-size: var(--text-base);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-row:hover {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-modal .modal-dialog {
|
||||||
|
max-width: 70%;
|
||||||
|
margin: 15% auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-modal .modal-body {
|
||||||
|
padding: 0 !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,22 +2,13 @@
|
|||||||
{% set portal_course_creation = frappe.db.get_single_value("LMS Settings", "portal_course_creation") %}
|
{% set portal_course_creation = frappe.db.get_single_value("LMS Settings", "portal_course_creation") %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade search-modal" id="search-modal" tabindex="-1" role="dialog">
|
||||||
<div id="search-modal" class="modal-container">
|
<div class="modal-dialog" role="document">
|
||||||
<div class="modal-inner">
|
<div class="modal-content">
|
||||||
<input class="search" id="search-course" placeholder="{{ _(search_placeholder) or 'Search for courses' }}">
|
<div class="modal-body">
|
||||||
</div>
|
<input class="search" id="search-course" placeholder="{{ _(search_placeholder) or 'Search for courses' }}">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="empty-state alert alert-dismissible search-empty-state hide">
|
|
||||||
<a href="#" class="close-search-empty-state" aria-label="close">×</a>
|
|
||||||
<div>
|
|
||||||
<img class="icon icon-xl" src="/assets/frappe/images/ui-states/search-empty-state.svg">
|
|
||||||
</div>
|
|
||||||
<div class="empty-state-text">
|
|
||||||
<div class="empty-state-heading">{{ _("No results found") }}</div>
|
|
||||||
<div class="course-meta">{{ _("Try some other keyword or explore our list of courses.") }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script> {% include "lms/templates/search_course/search_course.js" %} </script>
|
<script> {% include "lms/templates/search_course/search_course.js" %} </script>
|
||||||
|
|||||||
@@ -8,25 +8,22 @@ frappe.ready(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#open-search").click((e) => {
|
$("#open-search").click((e) => {
|
||||||
show_search_bar();
|
show_search_bar(e);
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#search-course").focusout((e) => {
|
$('#search-modal').on('hidden.bs.modal', () => {
|
||||||
hide_search_bar();
|
hide_search_bar();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const search_course = (e) => {
|
const search_course = (e) => {
|
||||||
let input = $(e.currentTarget).val();
|
let input = $(e.currentTarget).val();
|
||||||
|
|
||||||
if (input == window.input) return;
|
if (input == window.input) return;
|
||||||
|
|
||||||
window.input = input;
|
window.input = input;
|
||||||
|
|
||||||
if (input.length < 3 || input.trim() == "") {
|
if (input.length < 3 || input.trim() == "") {
|
||||||
$(".course-card").removeClass("hide");
|
$(".result-row").remove();
|
||||||
$(".search-empty-state").addClass("hide");
|
|
||||||
fix_heading_styles();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,51 +33,30 @@ const search_course = (e) => {
|
|||||||
text: input,
|
text: input,
|
||||||
},
|
},
|
||||||
callback: (data) => {
|
callback: (data) => {
|
||||||
let courses = data.message;
|
render_course_list(data);
|
||||||
$(".result-row").remove();
|
|
||||||
for (let i in courses) {
|
|
||||||
let element = `<div class="result-row">
|
|
||||||
${courses[i].title}
|
|
||||||
</div>`;
|
|
||||||
$("#search-result").append(element);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const render_course_list = (courses) => {
|
const render_course_list = (data) => {
|
||||||
fix_heading_styles();
|
let courses = data.message;
|
||||||
$(".search-empty-state").addClass("hide");
|
$(".result-row").remove();
|
||||||
|
|
||||||
if (!courses.length) {
|
if (! courses.length) {
|
||||||
$(".course-card").removeClass("hide");
|
let element = `<a class="result-row">
|
||||||
$(".search-empty-state").removeClass("hide");
|
${__("No result found")}
|
||||||
|
</a>`;
|
||||||
|
$(element).insertAfter("#search-course");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".course-card").addClass("hide");
|
|
||||||
for (course in courses) {
|
for (let i in courses) {
|
||||||
$("[data-course=" + courses[course].name + "]").removeClass("hide");
|
let element = `<a class="result-row" href="/courses/${courses[i].name}">
|
||||||
|
${courses[i].title}
|
||||||
|
</a>`;
|
||||||
|
$(element).insertAfter("#search-course");
|
||||||
}
|
}
|
||||||
|
|
||||||
const visible_live_courses = $(".live-courses .course-card").not(".hide");
|
|
||||||
const visible_upcoming_courses = $(".upcoming-courses .course-card").not(
|
|
||||||
".hide"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!visible_live_courses.length) {
|
|
||||||
$(".live-courses .course-home-headings").addClass("hide");
|
|
||||||
$(".upcoming-courses").removeClass("mt-10");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!visible_upcoming_courses.length) {
|
|
||||||
$(".upcoming-courses .course-home-headings").addClass("hide");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fix_heading_styles = () => {
|
|
||||||
$(".course-home-headings").removeClass("hide");
|
|
||||||
$(".upcoming-courses").addClass("mt-10");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const close_search_empty_state = (e) => {
|
const close_search_empty_state = (e) => {
|
||||||
@@ -88,13 +64,14 @@ const close_search_empty_state = (e) => {
|
|||||||
$("#search-course").val("");
|
$("#search-course").val("");
|
||||||
};
|
};
|
||||||
|
|
||||||
const show_search_bar = () => {
|
const show_search_bar = (e) => {
|
||||||
$("#open-search").addClass("hide");
|
$("#search-modal").modal("show");
|
||||||
$("#search-modal").css("display", "block");
|
setTimeout(() => {
|
||||||
$("#search-course").focus();
|
$("#search-course").focus();
|
||||||
};
|
}, 1000)
|
||||||
|
}
|
||||||
|
|
||||||
const hide_search_bar = () => {
|
const hide_search_bar = (e) => {
|
||||||
$("#open-search").removeClass("hide");
|
$("#search-course").val("");
|
||||||
$("#search-modal").css("display", "none");
|
$(".result-row").remove();
|
||||||
};
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user