Skip to content

Commit dbad929

Browse files
authored
Add support for latest in query string (#16)
1 parent 0d5a41c commit dbad929

File tree

7 files changed

+80
-3
lines changed

7 files changed

+80
-3
lines changed

src/hexdocs.gleam

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ fn update(model: Model, msg: Msg) {
4949
msg.ApiReturnedPackages(response) -> api_returned_packages(model, response)
5050
msg.ApiReturnedTypesenseSearch(response) ->
5151
api_returned_typesense_search(model, response)
52+
msg.ApiReturnedInitialLatestPackages(versions) ->
53+
api_returned_initial_latest_packages(model, versions)
5254

5355
msg.DocumentChangedLocation(location:) ->
5456
model.update_route(model, location)
@@ -161,6 +163,18 @@ fn api_returned_typesense_search(model: Model, response: Loss(decode.Dynamic)) {
161163
|> result.unwrap(#(model, effect.none()))
162164
}
163165

166+
fn api_returned_initial_latest_packages(
167+
model: Model,
168+
versions: Loss(List(hexpm.Package)),
169+
) -> #(Model, Effect(a)) {
170+
case versions {
171+
Error(_) -> #(model, toast.error("Server error. Retry later."))
172+
Ok(versions) ->
173+
model.add_packages_versions(model, versions)
174+
|> model.replace_search_packages
175+
}
176+
}
177+
164178
fn document_registered_event_listener(model: Model, unsubscriber: fn() -> Nil) {
165179
let dom_click_unsubscriber = Some(unsubscriber)
166180
Model(..model, dom_click_unsubscriber:)

src/hexdocs/data/model.gleam

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,14 +229,44 @@ pub fn update_route(model: Model, route: uri.Uri) {
229229
case string.is_empty(q) {
230230
True -> #(set_search_results(model, #(-1, [])), effect.none())
231231
False -> {
232+
let latest = list.filter(packages, fn(p) { p.1 == "latest" })
232233
Model(..model, search_input: q, search_packages_filters: packages)
233-
|> pair.new(effects.typesense_search(q, packages))
234+
|> pair.new({
235+
case latest {
236+
[] -> effects.typesense_search(q, packages)
237+
latest -> {
238+
latest
239+
|> list.map(pair.first)
240+
|> effects.initial_latest_packages
241+
}
242+
}
243+
})
234244
}
235245
}
236246
}
237247
}
238248
}
239249

250+
pub fn replace_search_packages(model: Model) {
251+
let model =
252+
Model(..model, search_packages_filters: {
253+
use #(package, version) <- list.map(model.search_packages_filters)
254+
use <- bool.guard(when: version != "latest", return: #(package, version))
255+
case dict.get(model.packages_versions, package) {
256+
Error(_) -> #(package, version)
257+
Ok(versions) -> {
258+
case versions.releases {
259+
[] -> #(package, version)
260+
[release, ..] -> #(package, release.version)
261+
}
262+
}
263+
}
264+
})
265+
route.Search(q: model.search_input, packages: model.search_packages_filters)
266+
|> route.replace
267+
|> pair.new(model, _)
268+
}
269+
240270
pub fn select_autocomplete_option(model: Model, package: String) {
241271
case model.autocomplete, model.route {
242272
None, _ -> model

src/hexdocs/data/model/route.gleam

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ pub fn push(route: Route) {
4747
modem.push(route.path, route.query, route.fragment)
4848
}
4949

50+
pub fn replace(route: Route) {
51+
let route = to_uri(route)
52+
modem.replace(route.path, route.query, route.fragment)
53+
}
54+
5055
fn create_query(
5156
query: List(#(String, String)),
5257
packages: List(#(String, String)),

src/hexdocs/data/model/version.gleam

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import gleam/option.{type Option, None, Some}
22
import gleam/regexp
33

4-
const version_regexp = "^#([a-zA-Z_0-9]+)(:(([0-9]+|\\.){1,5}))?"
4+
const version_regexp = "^#([a-zA-Z_0-9]+)(:((([0-9]+|\\.){1,5})|latest))?"
55

66
pub fn match_package(word: String) -> Result(#(String, Option(String)), Nil) {
77
let regexp = version_search()

src/hexdocs/data/msg.gleam

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub type Msg {
99
ApiReturnedPackages(Loss(String))
1010
ApiReturnedTypesenseSearch(Loss(Dynamic))
1111
ApiReturnedPackagesVersions(packages: Loss(List(hexpm.Package)))
12+
ApiReturnedInitialLatestPackages(versions: Loss(List(hexpm.Package)))
1213

1314
// Application messages.
1415
DocumentChangedLocation(location: uri.Uri)

src/hexdocs/effects.gleam

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import browser/document
22
import gleam/function
33
import gleam/http/response.{type Response}
44
import gleam/javascript/promise
5+
import gleam/list
6+
import gleam/result
57
import hexdocs/data/msg
68
import hexdocs/loss.{type Loss}
79
import hexdocs/services/hex
@@ -24,6 +26,27 @@ pub fn package_versions(package: String) {
2426
dispatch(msg.ApiReturnedPackageVersions(response:))
2527
}
2628

29+
pub fn initial_latest_packages(packages: List(String)) {
30+
use dispatch <- effect.from()
31+
use _ <- function.tap(Nil)
32+
use response <- promise.map({
33+
promise.await_list({
34+
use package <- list.map(packages)
35+
hex.package_versions(package)
36+
})
37+
})
38+
let versions = case result.all(response) {
39+
Error(error) -> Error(error)
40+
Ok(response) -> {
41+
case list.any(response, fn(r) { r.status != 200 }) {
42+
True -> Error(loss.HttpError)
43+
False -> Ok(list.map(response, fn(r) { r.body }))
44+
}
45+
}
46+
}
47+
dispatch(msg.ApiReturnedInitialLatestPackages(versions:))
48+
}
49+
2750
pub fn subscribe_blurred_search() {
2851
use dispatch <- effect.from()
2952
document.add_listener(fn() { dispatch(msg.UserBlurredSearch) })

src/hexdocs/view/search.gleam

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,11 @@ pub fn search(model: Model) {
253253
"self-stretch justify-start text-slate-700 dark:text-slate-400 text-sm font-normal leading-none",
254254
),
255255
],
256-
[html.text(version)],
256+
// You can add any loader you want here.
257+
case version {
258+
"latest" -> [html.text("Loading…")]
259+
version -> [html.text(version)]
260+
},
257261
),
258262
],
259263
),

0 commit comments

Comments
 (0)