Files
speckle-server/packages/frontend-2/lib/common/composables/url.ts
T
Kristaps Fabians Geikins 34290877fa feat: list & create groups (#5206)
* WIP group create

* create and list group works

* test fix

* safe router
2025-08-12 11:28:52 +03:00

77 lines
1.9 KiB
TypeScript

import { reduce } from 'lodash-es'
import type { Nullable, Optional } from '@speckle/shared'
import { writableAsyncComputed } from '~~/lib/common/composables/async'
export function serializeHashState(
state: Record<string, Nullable<string>>
): Optional<string> {
return !Object.values(state).filter((i) => i !== null).length
? undefined
: `#${Object.entries(state)
.filter((entry): entry is [string, string] => !!entry[1])
.map(([key, val]) => `${key}=${val}`)
.join('&')}`
}
export function deserializeHashState(hashString: string) {
if (hashString.length < 2 || !hashString.startsWith('#')) return {}
const keyValuePairs = hashString.substring(1).split('&')
const result = reduce(
keyValuePairs,
(result, item) => {
const [key, value] = item.split('=')
if (key && value) {
result[key] = value
}
return result
},
{} as Record<string, Nullable<string>>
)
return result
}
/**
* Read/writable state similar to one in the querystring, but one that uses anchor (#) data instead
*/
export function useRouteHashState() {
const route = useRoute()
const router = useSafeRouter()
const hashState = writableAsyncComputed({
get: () => {
return deserializeHashState(route.hash)
},
set: async (newVal) => {
const hashString = serializeHashState(newVal)
await router.push(() => ({
query: route.query,
hash: hashString
}))
},
initialState: {},
asyncRead: false
})
return { hashState }
}
export const useAppUrlUtils = () => {
const {
public: { baseUrl }
} = useRuntimeConfig()
const buildUrl = (relativeUrl: string | URL): string => {
const url = new URL(relativeUrl, baseUrl)
return decodeURI(url.toString()) // url encoded looks ugly
}
return {
/**
* Build full/absolute URL
*/
buildUrl
}
}