Skip to content

Commit a466d82

Browse files
authored
Merge pull request #33 from szymon-rd/no-result-page
No result page
2 parents 6c73d2b + 3c6ebd3 commit a466d82

File tree

8 files changed

+122
-62
lines changed

8 files changed

+122
-62
lines changed
Lines changed: 6 additions & 0 deletions
Loading

scaladoc-js/main/src/searchbar/SearchbarComponent.scala

Lines changed: 65 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -101,64 +101,78 @@ class SearchbarComponent(engine: PageSearchEngine, inkuireEngine: InkuireJSSearc
101101
def handleNewFluffQuery(query: NameAndKindQuery) =
102102
val searchTask: Future[List[MatchResult]] = Future(engine.query(query))
103103
searchTask.map { result =>
104-
val resultWithDocBonus = result
105-
.map(entry =>
106-
// add bonus score for static pages when in documentation section
107-
if entry.pageEntry.kind == "static" && !window.location.href.contains("api") then
108-
entry.copy(score = entry.score + 7)
109-
else entry
110-
)
111-
val fragment = document.createDocumentFragment()
112-
113-
def createLoadMoreElement =
114-
div(cls := "scaladoc-searchbar-row mono-small-inline", "loadmore" := "")(
115-
a(
116-
span("Load more")
117-
)
118-
).tap { loadMoreElement =>
119-
loadMoreElement
120-
.addEventListener("mouseover", _ => handleHover(loadMoreElement))
121-
}
104+
if result.isEmpty then
105+
val noResultsDiv = div(id := "no-results-container")(
106+
// TODO fix path to the element
107+
img(src := "./icons/no-results.svg", alt := "Sick face"),
108+
h2(cls := "h200 no-result-header")("No results match your filter criteria."),
109+
p(cls := "body-small no-result-content")("Try adjusting or clearing your filters", p("to display better result")),
110+
button(id := "searchbar-clear-button", cls := "clearButton label-only-button")("Clear all filters").tap(_.addEventListener("click", _ => {
111+
inputElem.value = ""
112+
inputElem.dispatchEvent(new Event("input"))
113+
}))
114+
)
115+
resultsDiv.scrollTop = 0
116+
resultsDiv.appendChild(noResultsDiv)
117+
else
118+
val resultWithDocBonus = result
119+
.map(entry =>
120+
// add bonus score for static pages when in documentation section
121+
if entry.pageEntry.kind == "static" && !window.location.href.contains("api") then
122+
entry.copy(score = entry.score + 7)
123+
else entry
124+
)
125+
val fragment = document.createDocumentFragment()
126+
127+
def createLoadMoreElement =
128+
div(cls := "scaladoc-searchbar-row mono-small-inline", "loadmore" := "")(
129+
a(
130+
span("Load more")
131+
)
132+
).tap { loadMoreElement =>
133+
loadMoreElement
134+
.addEventListener("mouseover", _ => handleHover(loadMoreElement))
135+
}
122136

123-
val groupedResults = resultWithDocBonus.groupBy(_.pageEntry.kind)
124-
val groupedResultsSortedByScore = groupedResults.map {
125-
case (kind, results) => (kind, results.maxByOption(_.score).map(_.score), results)
126-
}.toList.sortBy {
127-
case (_, topScore, _) => -topScore.getOrElse(0)
128-
}.map {
129-
case (kind, _, results) => (kind, results.take(40)) // limit to 40 results per category
130-
}
137+
val groupedResults = resultWithDocBonus.groupBy(_.pageEntry.kind)
138+
val groupedResultsSortedByScore = groupedResults.map {
139+
case (kind, results) => (kind, results.maxByOption(_.score).map(_.score), results)
140+
}.toList.sortBy {
141+
case (_, topScore, _) => -topScore.getOrElse(0)
142+
}.map {
143+
case (kind, _, results) => (kind, results.take(40)) // limit to 40 results per category
144+
}
131145

132-
groupedResultsSortedByScore.map {
133-
case (kind, results) =>
134-
val kindSeparator = createKindSeparator(kind)
135-
val htmlEntries = results.map(result => result.pageEntry.toHTML(result.indices))
136-
val loadMoreElement = createLoadMoreElement
137-
138-
def loadMoreResults(entries: List[raw.HTMLElement]): Unit = {
139-
loadMoreElement.onclick = (event: Event) => {
140-
entries.take(resultsChunkSize).foreach(_.classList.remove("hidden"))
141-
val nextElems = entries.drop(resultsChunkSize)
142-
if nextElems.nonEmpty then loadMoreResults(nextElems) else loadMoreElement.classList.add("hidden")
146+
groupedResultsSortedByScore.map {
147+
case (kind, results) =>
148+
val kindSeparator = createKindSeparator(kind)
149+
val htmlEntries = results.map(result => result.pageEntry.toHTML(result.indices))
150+
val loadMoreElement = createLoadMoreElement
151+
152+
def loadMoreResults(entries: List[raw.HTMLElement]): Unit = {
153+
loadMoreElement.onclick = (event: Event) => {
154+
entries.take(resultsChunkSize).foreach(_.classList.remove("hidden"))
155+
val nextElems = entries.drop(resultsChunkSize)
156+
if nextElems.nonEmpty then loadMoreResults(nextElems) else loadMoreElement.classList.add("hidden")
157+
}
143158
}
144-
}
145159

146-
fragment.appendChild(kindSeparator)
147-
htmlEntries.foreach(fragment.appendChild)
148-
fragment.appendChild(loadMoreElement)
160+
fragment.appendChild(kindSeparator)
161+
htmlEntries.foreach(fragment.appendChild)
162+
fragment.appendChild(loadMoreElement)
149163

150-
val nextElems = htmlEntries.drop(initialChunkSize)
151-
if nextElems.nonEmpty then {
152-
nextElems.foreach(_.classList.add("hidden"))
153-
loadMoreResults(nextElems)
154-
} else {
155-
loadMoreElement.classList.add("hidden")
156-
}
164+
val nextElems = htmlEntries.drop(initialChunkSize)
165+
if nextElems.nonEmpty then {
166+
nextElems.foreach(_.classList.add("hidden"))
167+
loadMoreResults(nextElems)
168+
} else {
169+
loadMoreElement.classList.add("hidden")
170+
}
157171

158-
}
172+
}
159173

160-
resultsDiv.scrollTop = 0
161-
resultsDiv.appendChild(fragment)
174+
resultsDiv.scrollTop = 0
175+
resultsDiv.appendChild(fragment)
162176
}
163177

164178
def handleRecentQueries(query: String) = {

scaladoc/noResultStructure.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<div id='no-results-container'>
2+
<img src="./images/no-results.svg" alt="Sick face" >
3+
<h2 class='h200 no-result-header'>No results match your filter criteria</h2>
4+
<p class=''>Try adjusting or clearing your filters<br>to display better result</p>
5+
<button class='clearButton label-only-button'>Clear all filters</button>
6+
</div>

scaladoc/resources/dotty_res/scripts/ux.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,8 +339,10 @@ window.addEventListener("dynamicPageLoad", () => {
339339
window.addEventListener("DOMContentLoaded", () => {
340340
hljs.registerLanguage("scala", highlightDotty);
341341
hljs.registerAliases(["dotty", "scala3"], "scala");
342-
window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD))
343-
})
342+
window.dispatchEvent(new Event(DYNAMIC_PAGE_LOAD));
343+
});
344+
345+
344346

345347
// show/hide side menu on mobile view
346348
const sideMenuToggler = document.getElementById("mobile-sidebar-toggle");

scaladoc/resources/dotty_res/styles/theme/layout/content.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,16 @@ main :is(ul, ol) li .snippet {
538538
display: block;
539539
}
540540

541+
.member-group-header,
542+
.documentableList-expander {
543+
display: flex;
544+
cursor: pointer;
545+
flex-direction: row-reverse;
546+
justify-content: space-between;
547+
align-items: center;
548+
}
549+
550+
541551
#content section:last-child {
542552
margin-bottom: calc(6 * var(--base-spacing));
543553
}

scaladoc/resources/dotty_res/styles/theme/layout/header.css

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,4 @@
100100
}
101101
}
102102

103-
.member-group-header,
104-
.documentableList-expander {
105-
display: flex;
106-
cursor: pointer;
107-
flex-direction: row-reverse;
108-
justify-content: space-between;
109-
align-items: center;
110-
}
111103

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#no-results-container {
2+
display: flex;
3+
flex-direction: column;
4+
justify-content: center;
5+
align-items: center;
6+
text-align: center;
7+
margin: calc(10 * var(--base-spacing));
8+
}
9+
10+
#no-results-container .no-result-header {
11+
margin-block-start: 27px;
12+
margin-block-end: var(--base-spacing);
13+
color: var(--text-primary);
14+
}
15+
16+
#no-results-container .no-result-content {
17+
margin-top: 0;
18+
margin-bottom: 34px;
19+
color: var(--text-secondary);
20+
}
21+
22+
#no-results-container .no-result-content p{
23+
margin: 0;
24+
}
25+

scaladoc/src/dotty/tools/scaladoc/renderers/Resources.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ trait Resources(using ctx: DocContext) extends Locations, Writer:
3232

3333
private def scaladocVersionFile = Resource.Text("scaladoc.version", BuildInfo.version)
3434

35+
lazy val noResultsIcon = {
36+
val path = Paths.get("docs/_assets/images/no-results-icon.svg")
37+
Resource.File("icons/no-results.svg", path)
38+
}
39+
3540
lazy val projectLogo = ctx.args.projectLogo.map { p =>
3641
val path = Paths.get(p)
3742
Resource.File(s"project-logo/${path.getFileName()}", path)
@@ -133,7 +138,7 @@ trait Resources(using ctx: DocContext) extends Locations, Writer:
133138
"https://scastie.scala-lang.org/embedded.js"
134139
).map(Resource.URL.apply)
135140

136-
fromResources ++ urls ++ projectLogo ++ darkProjectLogo ++ Seq(scaladocVersionFile, dynamicJsData)
141+
fromResources ++ urls ++ projectLogo ++ darkProjectLogo ++ Seq(noResultsIcon, scaladocVersionFile, dynamicJsData)
137142
}
138143

139144
val apiOnlyResources = List(

0 commit comments

Comments
 (0)