diff --git a/frontend/resources/vue/ActionButton.vue b/frontend/resources/vue/ActionButton.vue index d1df11a..649979c 100644 --- a/frontend/resources/vue/ActionButton.vue +++ b/frontend/resources/vue/ActionButton.vue @@ -61,6 +61,11 @@ const props = defineProps({ type: String, required: false, default: '' + }, + prefilledArguments: { + type: Object, + required: false, + default: () => ({}) } }) @@ -248,7 +253,16 @@ async function handleClick() { return } if (needsArgumentForm(props.actionData)) { - router.push(`/actionBinding/${props.actionData.bindingId}/argumentForm`) + const bindingId = props.actionData.bindingId + const prefilled = props.prefilledArguments || {} + if (Object.keys(prefilled).length > 0) { + router.push({ + path: `/actionBinding/${bindingId}/argumentForm`, + state: { prefilledArguments: prefilled } + }) + } else { + router.push(`/actionBinding/${bindingId}/argumentForm`) + } } else { await startAction() } diff --git a/frontend/resources/vue/components/EntityDefinitionSection.vue b/frontend/resources/vue/components/EntityDefinitionSection.vue new file mode 100644 index 0000000..2be54c7 --- /dev/null +++ b/frontend/resources/vue/components/EntityDefinitionSection.vue @@ -0,0 +1,173 @@ + + + + + diff --git a/frontend/resources/vue/components/EntityInstancesTable.vue b/frontend/resources/vue/components/EntityInstancesTable.vue new file mode 100644 index 0000000..0f0ff9b --- /dev/null +++ b/frontend/resources/vue/components/EntityInstancesTable.vue @@ -0,0 +1,103 @@ + + + + + diff --git a/frontend/resources/vue/components/EntityListFilter.vue b/frontend/resources/vue/components/EntityListFilter.vue new file mode 100644 index 0000000..ee75051 --- /dev/null +++ b/frontend/resources/vue/components/EntityListFilter.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/frontend/resources/vue/utils/prefilledArguments.js b/frontend/resources/vue/utils/prefilledArguments.js new file mode 100644 index 0000000..ee8c7e6 --- /dev/null +++ b/frontend/resources/vue/utils/prefilledArguments.js @@ -0,0 +1,17 @@ +export function readPrefilledArgumentsFromNavigation() { + const state = window.history.state + if (state?.prefilledArguments && typeof state.prefilledArguments === 'object') { + return { ...state.prefilledArguments } + } + + return {} +} + +export function getInitialArgumentValue(paramName, prefilledArguments) { + if (Object.prototype.hasOwnProperty.call(prefilledArguments, paramName)) { + return prefilledArguments[paramName] + } + + const params = new URLSearchParams(window.location.search.substring(1)) + return params.get(paramName) +} diff --git a/frontend/resources/vue/utils/prefilledArguments.test.mjs b/frontend/resources/vue/utils/prefilledArguments.test.mjs new file mode 100644 index 0000000..b18bd44 --- /dev/null +++ b/frontend/resources/vue/utils/prefilledArguments.test.mjs @@ -0,0 +1,39 @@ +import test from 'node:test' +import assert from 'node:assert/strict' + +import { getInitialArgumentValue, readPrefilledArgumentsFromNavigation } from './prefilledArguments.js' + +test('readPrefilledArgumentsFromNavigation returns navigation state values', () => { + const originalState = window.history.state + window.history.replaceState({ prefilledArguments: { ansible_host: '10.0.0.1' } }, '') + + assert.deepEqual(readPrefilledArgumentsFromNavigation(), { ansible_host: '10.0.0.1' }) + + window.history.replaceState(originalState, '') +}) + +test('getInitialArgumentValue prefers navigation state over query params', () => { + const originalState = window.history.state + const originalSearch = window.location.search + + window.history.replaceState({ prefilledArguments: { ansible_host: '10.0.0.1' } }, '') + window.history.replaceState(window.history.state, '', '?ansible_host=10.0.0.2') + + assert.equal(getInitialArgumentValue('ansible_host', readPrefilledArgumentsFromNavigation()), '10.0.0.1') + + window.history.replaceState(originalState, '') + window.history.replaceState(window.history.state, '', originalSearch || '/') +}) + +test('getInitialArgumentValue falls back to query params when state is absent', () => { + const originalState = window.history.state + const originalSearch = window.location.search + + window.history.replaceState({}, '') + window.history.replaceState(window.history.state, '', '?ansible_host=10.0.0.2') + + assert.equal(getInitialArgumentValue('ansible_host', readPrefilledArgumentsFromNavigation()), '10.0.0.2') + + window.history.replaceState(originalState, '') + window.history.replaceState(window.history.state, '', originalSearch || '/') +}) diff --git a/frontend/resources/vue/views/ArgumentForm.vue b/frontend/resources/vue/views/ArgumentForm.vue index e00f23e..23e827f 100644 --- a/frontend/resources/vue/views/ArgumentForm.vue +++ b/frontend/resources/vue/views/ArgumentForm.vue @@ -1,7 +1,18 @@