Skip to content

Commit

Permalink
Package URL (#3052)
Browse files Browse the repository at this point in the history
  • Loading branch information
fonsp authored Oct 11, 2024
1 parent 6fc6022 commit d255211
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 16 deletions.
2 changes: 1 addition & 1 deletion frontend/components/Editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ export class Editor extends Component {
allow_other_selected_cells ? this.state.selected_cells : [cell_id],
get_avaible_versions: async ({ package_name, notebook_id }) => {
const { message } = await this.client.send("nbpkg_available_versions", { package_name: package_name }, { notebook_id: notebook_id })
return message.versions
return message
},
}
this.actions = { ...this.real_actions }
Expand Down
38 changes: 24 additions & 14 deletions frontend/components/PkgStatusMark.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { open_pluto_popup } from "../common/open_pluto_popup.js"
import _ from "../imports/lodash.js"
import { html, useEffect, useState } from "../imports/Preact.js"
import { open_icon } from "./Popup.js"

export const nbpkg_fingerprint = (nbpkg) => (nbpkg == null ? [null] : Object.entries(nbpkg).flat())

Expand All @@ -23,28 +24,35 @@ const can_update = (installed, available) => {
* @property {string} hint_raw
* @property {string[]?} available_versions
* @property {string?} chosen_version
* @property {string?} package_url
* @property {boolean} busy
* @property {boolean} offer_update
*/

/**
* @param {{
* package_name: string,
* package_url?: string,
* is_disable_pkg: boolean,
* available_versions: string[]?,
* available_versions?: string[],
* nbpkg: import("./Editor.js").NotebookPkgData?,
* }} props
* @returns {PackageStatus}
*/
export const package_status = ({ nbpkg, package_name, available_versions, is_disable_pkg }) => {
export const package_status = ({ nbpkg, package_name, available_versions, is_disable_pkg, package_url }) => {
let status = "error"
let hint_raw = "error"
let hint = html`error`
let offer_update = false

package_url = package_url ?? `https://juliahub.com/ui/Packages/General/${package_name}`

const chosen_version = nbpkg?.installed_versions[package_name] ?? null
const nbpkg_waiting_for_permission = nbpkg?.waiting_for_permission ?? false
const busy = !nbpkg_waiting_for_permission && ((nbpkg?.busy_packages ?? []).includes(package_name) || !(nbpkg?.instantiated ?? true))

const package_name_pretty = html`<a class="package-name" href=${package_url}><b>${package_name}</b></a> `

if (is_disable_pkg) {
const f_name = package_name
status = "disable_pkg"
Expand All @@ -54,22 +62,25 @@ export const package_status = ({ nbpkg, package_name, available_versions, is_dis
if (chosen_version == null || chosen_version === "stdlib") {
status = "installed"
hint_raw = `${package_name} is part of Julia's pre-installed 'standard library'.`
hint = html`<b>${package_name}</b> is part of Julia's pre-installed <em>standard library</em>.`
hint = html`${package_name_pretty} is part of Julia's pre-installed <em>standard library</em>.`
} else {
if (nbpkg_waiting_for_permission) {
status = "will_be_installed"
hint_raw = `${package_name} (v${_.last(available_versions)}) will be installed when you run this notebook.`
hint = html`<header><b>${package_name}</b> <pkg-version>v${_.last(available_versions)}</pkg-version></header>
hint = html`<header>${package_name_pretty} <pkg-version>v${_.last(available_versions)}</pkg-version></header>
will be installed when you run this notebook.`
} else if (busy) {
status = "busy"
hint_raw = `${package_name} (v${chosen_version}) is installing...`
hint = html`<header><b>${package_name}</b> <pkg-version>v${chosen_version}</pkg-version></header>
hint = html`<header>${package_name_pretty} <pkg-version>v${chosen_version}</pkg-version></header>
is installing...`
} else {
status = "installed"
hint_raw = `${package_name} (v${chosen_version}) is installed in the notebook.`
hint = html`<header><b>${package_name}</b> <pkg-version>v${chosen_version}</pkg-version></header>
hint = html`<header>
${package_name_pretty}
<pkg-version>v${chosen_version}</pkg-version>
</header>
is installed in the notebook.`
offer_update = can_update(chosen_version, available_versions)
}
Expand All @@ -84,13 +95,13 @@ export const package_status = ({ nbpkg, package_name, available_versions, is_dis
} else {
status = "will_be_installed"
hint_raw = `${package_name} (v${_.last(available_versions)}) will be installed in the notebook when you run this cell.`
hint = html`<header><b>${package_name}</b> <pkg-version>v${_.last(available_versions)}</pkg-version></header>
hint = html`<header>${package_name_pretty} <pkg-version>v${_.last(available_versions)}</pkg-version></header>
will be installed in the notebook when you run this cell.`
}
}
}

return { status, hint, hint_raw, available_versions, chosen_version, busy, offer_update }
return { status, hint, hint_raw, available_versions: available_versions ?? null, chosen_version, busy, offer_update, package_url }
}

/**
Expand All @@ -103,20 +114,20 @@ export const package_status = ({ nbpkg, package_name, available_versions, is_dis
* }} props
*/
export const PkgStatusMark = ({ package_name, pluto_actions, notebook_id, nbpkg }) => {
const [available_versions, set_available_versions] = useState(/** @type {string[]?} */ (null))
const [available_versions_msg, set_available_versions_msg] = useState(/** @type {{ versions?: string[], package_url?: string }?} */ (null))
const [package_url, set_package_url] = useState(/** @type {string[]?} */ (null))

useEffect(() => {
let available_version_promise = pluto_actions.get_avaible_versions({ package_name, notebook_id }) ?? Promise.resolve([])
available_version_promise.then((available_versions) => {
set_available_versions(available_versions)
})
available_version_promise.then(set_available_versions_msg)
}, [package_name])

const { status, hint_raw } = package_status({
nbpkg: nbpkg,
package_name: package_name,
is_disable_pkg: false,
available_versions,
available_versions: available_versions_msg?.versions,
package_url: available_versions_msg?.package_url,
})

return html`
Expand Down Expand Up @@ -154,7 +165,6 @@ export const PkgActivateMark = ({ package_name }) => {
nbpkg: null,
package_name: package_name,
is_disable_pkg: true,
available_versions: null,
})

return html`
Expand Down
5 changes: 4 additions & 1 deletion frontend/components/Popup.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useEventListener } from "../common/useEventListener.js"
export const arrow_up_circle_icon = new URL("https://cdn.jsdelivr.net/gh/ionic-team/[email protected]/src/svg/arrow-up-circle-outline.svg", import.meta.url)
export const document_text_icon = new URL("https://cdn.jsdelivr.net/gh/ionic-team/[email protected]/src/svg/document-text-outline.svg", import.meta.url)
export const help_circle_icon = new URL("https://cdn.jsdelivr.net/gh/ionic-team/[email protected]/src/svg/help-circle-outline.svg", import.meta.url)
export const open_icon = new URL("https://cdn.jsdelivr.net/gh/ionic-team/[email protected]/src/svg/open-outline.svg", import.meta.url)

/**
* @typedef PkgPopupDetails
Expand Down Expand Up @@ -180,14 +181,16 @@ const PkgPopup = ({ notebook, recent_event, clear_recent_event, disable_input })
set_pkg_status(null)
} else if (recent_event?.type === "nbpkg") {
;(pluto_actions.get_avaible_versions({ package_name: recent_event.package_name, notebook_id: notebook.notebook_id }) ?? Promise.resolve([])).then(
(versions) => {
({ versions, url }) => {
console.log({ url })
if (still_valid) {
set_pkg_status(
package_status({
nbpkg: notebook.nbpkg,
package_name: recent_event.package_name,
is_disable_pkg: recent_event.is_disable_pkg,
available_versions: versions,
package_url: url,
})
)
}
Expand Down
8 changes: 8 additions & 0 deletions frontend/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -2047,6 +2047,14 @@ pkg-popup .pkg-buttons {
flex-direction: row;
}

.ionicon {
filter: var(--image-filters);
}

.package-name .ionicon {
margin-bottom: -0.1ch;
}

a.stdout-info img,
pkg-popup .pkg-buttons img {
filter: var(--image-filters);
Expand Down
21 changes: 21 additions & 0 deletions src/packages/PkgCompat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,27 @@ function package_versions(package_name::AbstractString)::Vector
end
end

function package_url(package_name::AbstractString)::Union{String,Nothing}
if is_stdlib(package_name)
"https://docs.julialang.org/en/v1/stdlib/$(package_name)/"
else
try
for reg in _parsed_registries[]
uuids_with_name = RegistryInstances.uuids_from_name(reg, package_name)
for u in uuids_with_name
pkg = get(reg, u, nothing)
if pkg !== nothing
info = RegistryInstances.registry_info(pkg)
return info.repo
end
end
end
catch e
@warn "Pkg compat: failed to get installable versions." exception=(e,catch_backtrace())
end
end
end

# ⚠️ Internal API with fallback
"Does a package with this name exist in one of the installed registries?"
package_exists(package_name::AbstractString)::Bool =
Expand Down
2 changes: 2 additions & 0 deletions src/webserver/Dynamic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -557,8 +557,10 @@ end
responses[:nbpkg_available_versions] = function response_nbpkg_available_versions(πŸ™‹::ClientRequest)
# require_notebook(πŸ™‹)
all_versions = PkgCompat.package_versions(πŸ™‹.body["package_name"])
url = PkgCompat.package_url(πŸ™‹.body["package_name"])
putclientupdates!(πŸ™‹.session, πŸ™‹.initiator, UpdateMessage(:πŸ•, Dict(
:versions => string.(all_versions),
:url => url,
), nothing, nothing, πŸ™‹.initiator))
end

Expand Down
6 changes: 6 additions & 0 deletions test/packages/PkgCompat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ import Pkg

end

@testset "URL" begin
@test PkgCompat.package_url("HTTP") == "https://github.com/JuliaWeb/HTTP.jl.git"
@test PkgCompat.package_url("HefefTTP") === nothing
@test PkgCompat.package_url("Downloads") == "https://docs.julialang.org/en/v1/stdlib/Downloads/"
end

@testset "Registry queries" begin
Pkg.Registry.add(pluto_test_registry_spec)
PkgCompat.refresh_registry_cache()
Expand Down

0 comments on commit d255211

Please sign in to comment.