fix: point the app viewer's edit button at the editor for the app's kind (#11009)

Claude-Session: https://claude.ai/code/session_01GDiZaPzhC4R9G4hLPgy1B2

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ruben Fiszel
2026-09-07 17:38:38 +02:00
committed by GitHub
co-authored by Claude Opus 5
parent c6e0302d7c
commit 8f553eab35
4 changed files with 18 additions and 13 deletions
@@ -22,19 +22,22 @@
let {
workspace,
path,
editHref
path
}: {
workspace: string
path: string
/** Where the Edit button points (low-code vs raw editor). */
editHref: string
} = $props()
let app: any = $state(undefined)
let notExists = $state(false)
let noPermission = $state(false)
let canWriteApp = $state(false)
/** Raw vs low-code, read from the app itself rather than from the route:
* both kinds render here and either route serves either kind (links to a raw
* app point at /apps/get all over the app), so only the app can say which
* editor the Edit button must open. */
let isRawApp = $state(false)
let editHref = $derived(`${base}/${isRawApp ? 'apps_raw' : 'apps'}/edit/${path}?nodraft=true`)
let refresh: (() => void) | undefined
// The opaque iframe loads the dedicated cookieless, chrome-less viewer route.
@@ -103,11 +106,14 @@
}
}
// Edit button: determine write access on this real-origin page (cookie).
// Edit button: determine write access and which editor to open on this
// real-origin page (cookie). The sandboxed low-code app never loads on this
// page (it loads inside the opaque iframe), so `app` can't be the source.
async function loadPerms() {
try {
const lite: any = await AppService.getAppLiteByPath({ workspace, path })
canWriteApp = canWrite(lite?.path, lite?.extra_perms ?? {}, $userStore)
isRawApp = !!lite?.raw_app
} catch (_) {
canWriteApp = false
}
@@ -427,7 +427,7 @@
path = `/apps/get/${e.path}`
break
case 'raw_app':
path = `/raw_apps/get/${e.path}`
path = `/apps_raw/get/${e.path}`
break
default:
path = '/'
@@ -1,11 +1,11 @@
<script lang="ts">
/*
* WIN-2006: in-workspace low-code app viewer. Thin wrapper over the shared
* WIN-2006: in-workspace app viewer. Thin wrapper over the shared
* InWorkspaceAppViewer, which renders the app sandboxed (opaque iframe / scoped
* token) through the same machinery as the public viewer. Raw apps use the
* sibling /apps_raw/get route, which wraps the same component.
* token) through the same machinery as the public viewer. Raw apps also render
* here — links to an app point at this route whatever its kind; the sibling
* /apps_raw/get route wraps the same component.
*/
import { base } from '$lib/base'
import InWorkspaceAppViewer from '$lib/components/apps/editor/InWorkspaceAppViewer.svelte'
import { Skeleton } from '$lib/components/common'
import { workspaceStore } from '$lib/stores'
@@ -24,7 +24,7 @@
must fully remount — otherwise the previous app (and in sandbox mode its
path-scoped token) sticks around. -->
{#key `${workspace}/${path}`}
<InWorkspaceAppViewer {workspace} {path} editHref="{base}/apps/edit/{path}?nodraft=true" />
<InWorkspaceAppViewer {workspace} {path} />
{/key}
{:else}
<Skeleton layout={[10]} />
@@ -5,7 +5,6 @@
* apps get the identical sandbox behavior. PublicAppFrame renders raw apps
* inline with the bundle isolated in RawAppPreview's own opaque iframe.
*/
import { base } from '$lib/base'
import InWorkspaceAppViewer from '$lib/components/apps/editor/InWorkspaceAppViewer.svelte'
import { Skeleton } from '$lib/components/common'
import { workspaceStore } from '$lib/stores'
@@ -19,7 +18,7 @@
<!-- Key by target: SvelteKit reuses this page component on in-route
navigation, so the viewer must fully remount (see /apps/get). -->
{#key `${workspace}/${path}`}
<InWorkspaceAppViewer {workspace} {path} editHref="{base}/apps_raw/edit/{path}?nodraft=true" />
<InWorkspaceAppViewer {workspace} {path} />
{/key}
{:else}
<Skeleton layout={[10]} />