further changes to support persisting values when component changes
This commit is contained in:
parent
deeb1fc29f
commit
af0c722af1
|
@ -1,37 +1,71 @@
|
|||
<script>
|
||||
<script lang="ts">
|
||||
import { onMount } from "svelte"
|
||||
import { Input, Icon, Body, AbsTooltip } from "@budibase/bbui"
|
||||
import { previewStore } from "@/stores/builder"
|
||||
import {
|
||||
Input,
|
||||
Icon,
|
||||
Body,
|
||||
AbsTooltip,
|
||||
TooltipPosition,
|
||||
} from "@budibase/bbui"
|
||||
import { previewStore, selectedScreen } from "@/stores/builder"
|
||||
import { ComponentContext } from "@budibase/types"
|
||||
|
||||
export let baseRoute = ""
|
||||
export let testValue = ""
|
||||
|
||||
$: routeParams = baseRoute.match(/:[a-zA-Z]+/g) || []
|
||||
$: placeholder = (() => {
|
||||
// Helper function to extract the route parameters
|
||||
// e.g /employees/:id/:name becomes /employees/1/John for the placeholder
|
||||
if (!routeParams.length) return "Add test values"
|
||||
const segments = baseRoute.split("/").slice(2)
|
||||
let paramCount = 1
|
||||
let testValue: string | undefined
|
||||
|
||||
$: placeholder = getPlaceholder(baseRoute)
|
||||
$: baseInput = createBaseInput(baseRoute)
|
||||
$: updateTestValueFromContext($previewStore.selectedComponentContext)
|
||||
$: if ($selectedScreen) {
|
||||
testValue = ""
|
||||
}
|
||||
|
||||
const getPlaceholder = (route: string) => {
|
||||
const trimmed = route.replace(/\/$/, "")
|
||||
if (trimmed.startsWith("/:")) {
|
||||
return "1"
|
||||
}
|
||||
const segments = trimmed.split("/").slice(2)
|
||||
let count = 1
|
||||
return segments
|
||||
.map(segment => {
|
||||
if (segment.startsWith(":")) {
|
||||
return paramCount++
|
||||
}
|
||||
return segment
|
||||
})
|
||||
.map(segment => (segment.startsWith(":") ? count++ : segment))
|
||||
.join("/")
|
||||
})()
|
||||
}
|
||||
|
||||
$: {
|
||||
if ($previewStore.selectedComponentContext?.url?.testValue !== undefined) {
|
||||
testValue = $previewStore.selectedComponentContext.url.testValue
|
||||
// This function is needed to repopulate the test value from componentContext
|
||||
// when a user navigates to another component and then back again
|
||||
const updateTestValueFromContext = (context: ComponentContext | null) => {
|
||||
if (context?.url && !testValue) {
|
||||
const { wild, ...urlParams } = context.url
|
||||
const queryParams = context.query
|
||||
if (Object.values(urlParams).some(v => Boolean(v))) {
|
||||
let value = baseRoute
|
||||
.split("/")
|
||||
.slice(2)
|
||||
.map(segment =>
|
||||
segment.startsWith(":")
|
||||
? urlParams[segment.slice(1)] || ""
|
||||
: segment
|
||||
)
|
||||
.join("/")
|
||||
const qs = new URLSearchParams(queryParams).toString()
|
||||
if (qs) {
|
||||
value += `?${qs}`
|
||||
}
|
||||
testValue = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const onVariableChange = e => {
|
||||
const createBaseInput = (baseRoute: string) => {
|
||||
return baseRoute === "/" || baseRoute.split("/")[1]?.startsWith(":")
|
||||
? "/"
|
||||
: `/${baseRoute.split("/")[1]}/`
|
||||
}
|
||||
|
||||
const onVariableChange = (e: CustomEvent) => {
|
||||
previewStore.updateUrl({ route: baseRoute, testValue: e.detail })
|
||||
previewStore.requestComponentContext()
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
|
@ -43,8 +77,8 @@
|
|||
<div class="info">
|
||||
<Body size="XS">URL Variable Testing</Body>
|
||||
<AbsTooltip
|
||||
text="Test how your screen behaves with different URL parameters. Enter values in the format shown in the placeholder."
|
||||
position={"bottom"}
|
||||
text="Test how your screen behaves with different URL parameters. Enter values in the format shown in the placeholder below."
|
||||
position={TooltipPosition.Top}
|
||||
noWrap
|
||||
>
|
||||
<div class="icon">
|
||||
|
@ -54,7 +88,7 @@
|
|||
</div>
|
||||
<div class="url-test-container">
|
||||
<div class="base-input">
|
||||
<Input disabled={true} value={`/${baseRoute.split("/")[1]}/`} />
|
||||
<Input disabled={true} value={baseInput} />
|
||||
</div>
|
||||
<div class="variable-input">
|
||||
<Input
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
$: bindings = getBindableProperties($selectedScreen, null)
|
||||
$: screenSettings = getScreenSettings($selectedScreen)
|
||||
let urlTestValue = ""
|
||||
|
||||
let errors = {}
|
||||
|
||||
|
@ -100,7 +99,6 @@
|
|||
control: URLVariableTestInput,
|
||||
props: {
|
||||
baseRoute: screen.routing?.route,
|
||||
testValue: urlTestValue,
|
||||
},
|
||||
},
|
||||
]
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import { get } from "svelte/store"
|
||||
import { BudiStore } from "../BudiStore"
|
||||
import { PreviewDevice, ComponentContext } from "@budibase/types"
|
||||
|
||||
type PreviewDevice = "desktop" | "tablet" | "mobile"
|
||||
type PreviewEventHandler = (name: string, payload?: any) => void
|
||||
type ComponentContext = Record<string, any>
|
||||
|
||||
interface PreviewState {
|
||||
previewDevice: PreviewDevice
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
componentStore,
|
||||
navigationStore,
|
||||
selectedComponent,
|
||||
previewStore,
|
||||
} from "@/stores/builder"
|
||||
import { createHistoryStore, HistoryStore } from "@/stores/builder/history"
|
||||
import { API } from "@/api"
|
||||
|
@ -110,6 +111,9 @@ export class ScreenStore extends BudiStore<ScreenState> {
|
|||
return
|
||||
}
|
||||
|
||||
// When we select a screen, we want to clear the url binding test value
|
||||
previewStore.updateUrl({ route: screen.routing.route, testValue: "" })
|
||||
|
||||
// Select new screen
|
||||
this.update(state => {
|
||||
state.selectedScreenId = screen._id
|
||||
|
|
|
@ -120,15 +120,36 @@ const createRouteStore = () => {
|
|||
return `${base}#${relativeURL}`
|
||||
}
|
||||
const setTestUrlParams = (route: string, testValue: string) => {
|
||||
const routeSegments = route.split("/").slice(2)
|
||||
const testSegments = testValue.split("/")
|
||||
if (route === "/") {
|
||||
return
|
||||
}
|
||||
|
||||
const [pathPart, queryPart] = testValue.split("?")
|
||||
const routeSegments = route.split("/").filter(Boolean)
|
||||
|
||||
// If first segment is a parameter (e.g. /:foo), include it in processing
|
||||
const startIndex = routeSegments[0]?.startsWith(":") ? 0 : 1
|
||||
const segments = routeSegments.slice(startIndex)
|
||||
const testSegments = pathPart.split("/")
|
||||
|
||||
const params: Record<string, string> = {}
|
||||
routeSegments.forEach((segment, index) => {
|
||||
segments.forEach((segment, index) => {
|
||||
if (segment.startsWith(":") && index < testSegments.length) {
|
||||
params[segment.slice(1)] = testSegments[index]
|
||||
}
|
||||
})
|
||||
|
||||
const queryParams: Record<string, string> = {}
|
||||
if (queryPart) {
|
||||
queryPart.split("&").forEach(param => {
|
||||
const [key, value] = param.split("=")
|
||||
if (key && value) {
|
||||
queryParams[key] = value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
setQueryParams({ ...queryParams })
|
||||
store.update(state => ({ ...state, testUrlParams: params }))
|
||||
}
|
||||
return {
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export type PreviewDevice = "desktop" | "tablet" | "mobile"
|
||||
export type ComponentContext = Record<string, any>
|
||||
|
|
Loading…
Reference in New Issue