feat: links to argument forms (#551)

Co-authored-by: James Read <contact@jread.com>
This commit is contained in:
Noah Perks Sloan 2025-04-08 16:07:01 -05:00 committed by GitHub
parent 4ccfd0f993
commit ec1f974f67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 91 additions and 4 deletions

View File

@ -45,6 +45,8 @@ class ActionButton extends ExecutionFeedbackButton {
oldArgumentForm.remove()
}
this.updateUrlWithAction()
const frm = document.createElement('argument-form')
frm.setup(json, (args) => {
this.startAction(args)
@ -132,6 +134,17 @@ class ActionButton extends ExecutionFeedbackButton {
})
}
updateUrlWithAction () {
// Get the current URL and create a new URL object
const url = new URL(window.location.href)
// Set the action parameter
url.searchParams.set('action', this.btn.title)
// Update the URL without reloading the page
window.history.replaceState({}, '', url.toString())
}
onActionStarted (executionTrackingId) {
if (this.popupOnStart === 'execution-button') {
const btnExecution = document.createElement('execution-button')

View File

@ -1,5 +1,9 @@
class ArgumentForm extends window.HTMLElement {
getQueryParams () {
return new URLSearchParams(window.location.search.substring(1))
}
setup (json, callback) {
this.setAttribute('class', 'action-arguments')
@ -23,6 +27,7 @@ class ArgumentForm extends window.HTMLElement {
}
this.domBtnCancel.onclick = () => {
this.clearBookmark()
this.remove()
}
}
@ -189,7 +194,19 @@ class ArgumentForm extends window.HTMLElement {
}
domEl.name = arg.name
domEl.value = arg.defaultValue
// Use query parameter value if available
const params = this.getQueryParams()
const paramValue = params.get(arg.name)
if (paramValue !== null) {
domEl.value = paramValue
} else {
domEl.value = arg.defaultValue
}
// update the URL when a parameter is changed
domEl.addEventListener('change', this.updateUrlWithArg)
if (typeof arg.suggestions === 'object' && Object.keys(arg.suggestions).length > 0) {
domEl.setAttribute('list', arg.name + '-choices')
@ -200,6 +217,20 @@ class ArgumentForm extends window.HTMLElement {
return domEl
}
updateUrlWithArg (ev) {
if (!ev.target.name) {
return
}
// Get the current URL and create a new URL object
const url = new URL(window.location.href)
// copy the parameter value
url.searchParams.set(ev.target.name, ev.target.value)
// Update the URL without reloading the page
window.history.replaceState({}, '', url.toString())
}
createDomDescription (arg) {
const domArgumentDescription = document.createElement('span')
domArgumentDescription.classList.add('argument-description')
@ -216,6 +247,13 @@ class ArgumentForm extends window.HTMLElement {
return domEl
}
clearBookmark () {
// remove the action from the URL
window.history.replaceState({
path: window.location.pathname
}, '', window.location.pathname)
}
}
window.customElements.define('argument-form', ArgumentForm)

View File

@ -2,6 +2,33 @@ import './ActionButton.js' // To define action-button
import { ExecutionDialog } from './ExecutionDialog.js'
import { ActionStatusDisplay } from './ActionStatusDisplay.js'
function getQueryParams () {
return new URLSearchParams(window.location.search.substring(1))
}
function checkAndTriggerActionFromQueryParam () {
const params = getQueryParams()
const action = params.get('action')
if (action && window.actionButtons) {
// Look for an action button with matching title
const actionButton = window.actionButtons[action]
if (actionButton) {
// Only trigger actions that have arguments
const jsonButton = window.actionButtonsJson[action]
if (jsonButton && jsonButton.arguments && jsonButton.arguments.length > 0) {
// Trigger the action button click
setTimeout(() => {
actionButton.btn.click()
}, 500) // Small delay to ensure UI is fully loaded
return true
}
}
}
return false
}
function createElement (tag, attributes) {
const el = document.createElement(tag)
@ -106,6 +133,7 @@ function marshalActionsJsonToHtml (json) {
const currentIterationTimestamp = Date.now()
window.actionButtons = {}
window.actionButtonsJson = {} // Store the JSON representation
for (const jsonButton of json.actions) {
let htmlButton = window.actionButtons[jsonButton.id]
@ -115,6 +143,7 @@ function marshalActionsJsonToHtml (json) {
htmlButton.constructFromJson(jsonButton)
window.actionButtons[jsonButton.title] = htmlButton
window.actionButtonsJson[jsonButton.title] = jsonButton // Store the JSON representation
}
htmlButton.updateFromJson(jsonButton)
@ -169,7 +198,7 @@ function onExecutionFinished (evt) {
}
break
case 'execution-dialog-output-html':
case 'execution-dialog-output-html':
case 'execution-dialog-stdout-only':
case 'execution-dialog':
// We don't need to fetch the logEntry for the dialog because we already
@ -246,7 +275,10 @@ function showSection (pathName) {
}
}
pushNewNavigationPath(pathName)
// Check for action parameter in query string
if (!checkAndTriggerActionFromQueryParam()) {
pushNewNavigationPath(pathName)
}
setSectionNavigationVisible(false)
@ -254,9 +286,13 @@ function showSection (pathName) {
}
function pushNewNavigationPath (pathName) {
// Get the current query string
const queryString = window.location.search
// Push the new state with the path and preserve the query string
window.history.pushState({
path: pathName
}, null, pathName)
}, null, pathName + queryString)
}
function setSectionNavigationVisible (visible) {