Fix issue with URL <-> state binding in design section preventing navigating to roles with no screens in them
This commit is contained in:
parent
6a7e137ff6
commit
09d3a54c7e
|
@ -1,110 +0,0 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { get } from "svelte/store"
|
||||
import { params, leftover, goto } from "@sveltech/routify"
|
||||
import { FrontendTypes } from "constants"
|
||||
import { store, allScreens, currentAsset } from "builderStore"
|
||||
import { findComponent, findComponentPath } from "builderStore/storeUtils"
|
||||
|
||||
let initialised = false
|
||||
|
||||
// Cache previous values so we don't update the URL more than necessary
|
||||
let previousType
|
||||
let previousAsset
|
||||
let previousComponentId
|
||||
|
||||
// Hydrate state from query param on mount
|
||||
onMount(() => {
|
||||
const assetId = decodeURI($params.asset)
|
||||
let assetList
|
||||
let actions
|
||||
|
||||
// Determine screens or layouts based on the URL
|
||||
if ($params.assetType === FrontendTypes.SCREEN) {
|
||||
assetList = $allScreens
|
||||
actions = store.actions.screens
|
||||
} else {
|
||||
assetList = $store.layouts
|
||||
actions = store.actions.layouts
|
||||
}
|
||||
|
||||
// Find and select the current asset
|
||||
const asset = assetList.find(asset => asset._id === assetId)
|
||||
if (asset) {
|
||||
actions.select(assetId)
|
||||
|
||||
// Select the component ID if one is present in the URL
|
||||
const selectedComponentId = $leftover.split("/").pop()
|
||||
if (selectedComponentId) {
|
||||
const component = findComponent(asset.props, selectedComponentId)
|
||||
if (component) {
|
||||
store.actions.components.select(component)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initialised = true
|
||||
})
|
||||
|
||||
// Updates the route params in the URL to the specified values
|
||||
const updateParams = (assetType, asset, componentId) => {
|
||||
// Wait until the initial state rehydration to avoid a wasted update
|
||||
if (!initialised) {
|
||||
return
|
||||
}
|
||||
|
||||
// Check we have different params than last invocation
|
||||
if (
|
||||
assetType === previousType &&
|
||||
asset === previousAsset &&
|
||||
componentId === previousComponentId
|
||||
) {
|
||||
return
|
||||
} else {
|
||||
previousType = assetType
|
||||
previousAsset = asset
|
||||
previousComponentId = componentId
|
||||
}
|
||||
|
||||
// Extract current URL params
|
||||
const currentParams = get(params)
|
||||
const currentLeftover = get(leftover)
|
||||
const paramAssetType = currentParams.assetType
|
||||
const paramAssetId = currentParams.asset
|
||||
const paramComponentId = currentLeftover.split("/").pop()
|
||||
|
||||
// Only update params if the params actually changed
|
||||
if (
|
||||
assetType !== paramAssetType ||
|
||||
asset?._id !== paramAssetId ||
|
||||
componentId !== paramComponentId
|
||||
) {
|
||||
// Build and navigate to a valid URL
|
||||
let url = "../../"
|
||||
if ([FrontendTypes.SCREEN, FrontendTypes.LAYOUT].includes(assetType)) {
|
||||
url += `${assetType}`
|
||||
if (asset?._id) {
|
||||
url += `/${asset._id}`
|
||||
if (componentId) {
|
||||
const componentPath = findComponentPath(asset.props, componentId)
|
||||
const componentURL = componentPath
|
||||
.slice(1)
|
||||
.map(comp => comp._id)
|
||||
.join("/")
|
||||
url += `/${componentURL}`
|
||||
}
|
||||
}
|
||||
}
|
||||
$goto(url)
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically keep URL up to date with state
|
||||
$: updateParams(
|
||||
$store.currentFrontEndType,
|
||||
$currentAsset,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
</script>
|
||||
|
||||
<slot />
|
|
@ -1,21 +1,135 @@
|
|||
<script>
|
||||
import {
|
||||
store,
|
||||
backendUiStore,
|
||||
currentAsset,
|
||||
selectedComponent,
|
||||
allScreens,
|
||||
} from "builderStore"
|
||||
import { onMount } from "svelte"
|
||||
import CurrentItemPreview from "components/design/AppPreview"
|
||||
import PropertiesPanel from "components/design/PropertiesPanel/PropertiesPanel.svelte"
|
||||
import ComponentSelectionList from "components/design/AppPreview/ComponentSelectionList.svelte"
|
||||
import FrontendNavigatePane from "components/design/NavigationPanel/FrontendNavigatePane.svelte"
|
||||
import { goto, leftover, params } from "@sveltech/routify"
|
||||
import { FrontendTypes } from "constants"
|
||||
import { findComponent, findComponentPath } from "builderStore/storeUtils"
|
||||
import { get } from "svelte/store"
|
||||
|
||||
onMount(async () => {
|
||||
if ($store.appInstance && !$backendUiStore.database) {
|
||||
backendUiStore.actions.database.select($store.appInstance)
|
||||
// Cache previous values so we don't update the URL more than necessary
|
||||
let previousType
|
||||
let previousAsset
|
||||
let previousComponentId
|
||||
|
||||
// Hydrate state from URL params
|
||||
$: hydrateStateFromURL($params, $leftover)
|
||||
|
||||
// Keep URL in sync with state
|
||||
$: updateURLFromState(
|
||||
$store.currentFrontEndType,
|
||||
$currentAsset,
|
||||
$store.selectedComponentId
|
||||
)
|
||||
|
||||
const hydrateStateFromURL = (params, leftover) => {
|
||||
// Do nothing if no asset type, as that means we've left the page
|
||||
if (!params.assetType) {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
const state = get(store)
|
||||
const selectedAsset = get(currentAsset)
|
||||
|
||||
// Hydrate asset type
|
||||
let assetType = params.assetType
|
||||
if (![FrontendTypes.LAYOUT, FrontendTypes.SCREEN].includes(assetType)) {
|
||||
assetType = FrontendTypes.SCREEN
|
||||
}
|
||||
if (assetType !== state.currentFrontEndType) {
|
||||
store.update(state => {
|
||||
state.currentFrontEndType = assetType
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
// Hydrate asset
|
||||
const assetId = decodeURI(params.asset)
|
||||
let asset
|
||||
if (assetId) {
|
||||
let assetList
|
||||
let actions
|
||||
|
||||
// Determine screens or layouts based on the URL
|
||||
if (assetType === FrontendTypes.SCREEN) {
|
||||
assetList = get(allScreens)
|
||||
actions = store.actions.screens
|
||||
} else {
|
||||
assetList = state.layouts
|
||||
actions = store.actions.layouts
|
||||
}
|
||||
|
||||
// Find and select the current asset
|
||||
asset = assetList.find(asset => asset._id === assetId)
|
||||
if (asset && asset._id !== selectedAsset?._id) {
|
||||
actions.select(assetId)
|
||||
}
|
||||
}
|
||||
|
||||
// Hydrate component ID if one is present in the URL
|
||||
const selectedComponentId = leftover.split("/").pop()
|
||||
if (asset && selectedComponentId) {
|
||||
const component = findComponent(asset.props, selectedComponentId)
|
||||
if (component && component._id !== state.selectedComponentId) {
|
||||
store.actions.components.select(component)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Updates the route params in the URL to the specified values
|
||||
const updateURLFromState = (assetType, asset, componentId) => {
|
||||
// Check we have different params than last invocation
|
||||
if (
|
||||
assetType === previousType &&
|
||||
asset === previousAsset &&
|
||||
componentId === previousComponentId
|
||||
) {
|
||||
return
|
||||
} else {
|
||||
previousType = assetType
|
||||
previousAsset = asset
|
||||
previousComponentId = componentId
|
||||
}
|
||||
|
||||
// Extract current URL params
|
||||
const currentParams = get(params)
|
||||
const currentLeftover = get(leftover)
|
||||
const paramAssetType = currentParams.assetType
|
||||
const paramAssetId = currentParams.asset
|
||||
const paramComponentId = currentLeftover.split("/").pop()
|
||||
|
||||
// Only update params if the params actually changed
|
||||
if (
|
||||
assetType !== paramAssetType ||
|
||||
asset?._id !== paramAssetId ||
|
||||
componentId !== paramComponentId
|
||||
) {
|
||||
// Build and navigate to a valid URL
|
||||
let url = "../"
|
||||
if ([FrontendTypes.SCREEN, FrontendTypes.LAYOUT].includes(assetType)) {
|
||||
url += `${assetType}`
|
||||
if (asset?._id) {
|
||||
url += `/${asset._id}`
|
||||
if (componentId) {
|
||||
const componentPath = findComponentPath(asset.props, componentId)
|
||||
const componentURL = componentPath
|
||||
.slice(1)
|
||||
.map(comp => comp._id)
|
||||
.join("/")
|
||||
url += `/${componentURL}`
|
||||
}
|
||||
}
|
||||
}
|
||||
$goto(url)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- routify:options index=1 -->
|
||||
|
|
|
@ -1,45 +1,51 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { goto } from "@sveltech/routify"
|
||||
import { store, allScreens } from "builderStore"
|
||||
import { get } from "svelte/store"
|
||||
import { store, allScreens, selectedAccessRole } from "builderStore"
|
||||
import { FrontendTypes } from "constants"
|
||||
import { params } from "@sveltech/routify"
|
||||
|
||||
onMount(() => {
|
||||
$: selectValidAsset($params.assetType)
|
||||
|
||||
// If we ever land on this index page we want to correctly update state
|
||||
// to select a valid asset. The layout page will in turn update the URL
|
||||
// to reflect state.
|
||||
const selectValidAsset = assetType => {
|
||||
let id
|
||||
const state = get(store)
|
||||
const screens = get(allScreens)
|
||||
const role = get(selectedAccessRole)
|
||||
|
||||
// Get valid asset type
|
||||
let assetType = $params.assetType
|
||||
if (![FrontendTypes.LAYOUT, FrontendTypes.SCREEN].includes(assetType)) {
|
||||
assetType = FrontendTypes.SCREEN
|
||||
}
|
||||
|
||||
// Get ID or first correct asset type
|
||||
// Get ID or first correct asset type and select it
|
||||
if (assetType === FrontendTypes.LAYOUT) {
|
||||
if (
|
||||
$store.selectedLayoutId &&
|
||||
$store.layouts.find(layout => layout._id === $store.selectedLayoutId)
|
||||
state.selectedLayoutId &&
|
||||
state.layouts.find(layout => layout._id === state.selectedLayoutId)
|
||||
) {
|
||||
id = $store.selectedLayoutId
|
||||
id = state.selectedLayoutId
|
||||
} else {
|
||||
id = $store.layouts[0]?._id
|
||||
id = state.layouts[0]?._id
|
||||
}
|
||||
if (id) {
|
||||
store.actions.layouts.select(id)
|
||||
}
|
||||
} else if (assetType === FrontendTypes.SCREEN) {
|
||||
if (
|
||||
$store.selectedScreenId &&
|
||||
$allScreens.find(screen => screen._id === $store.selectedScreenId)
|
||||
state.selectedScreenId &&
|
||||
screens.find(screen => screen._id === state.selectedScreenId)
|
||||
) {
|
||||
id = $store.selectedScreenId
|
||||
id = state.selectedScreenId
|
||||
} else {
|
||||
id = $allScreens[0]?._id
|
||||
// Select the first screen matching the selected role ID
|
||||
const filteredScreens = screens.filter(screen => {
|
||||
return screen.routing?.roleId === role
|
||||
})
|
||||
id = filteredScreens[0]?._id
|
||||
}
|
||||
if (id) {
|
||||
store.actions.screens.select(id)
|
||||
}
|
||||
}
|
||||
|
||||
// Send correct URL which will then update state
|
||||
if (id) {
|
||||
$goto(`../../${assetType}/${id}`)
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- routify:options index=false -->
|
||||
|
|
Loading…
Reference in New Issue