1
0
Fork 0
mirror of synced 2024-05-16 18:33:53 +12:00
budibase/packages/builder/src/pages/builder/portal/apps/[appId]/index.svelte
Gerard Burns d9033b2636
Un-revert Skeleton Loader PR (#13180)
* wip

* wip

* wip

* client versions init

* wip

* wip

* wip

* wip

* wip

* linting

* remove log

* comment client version script

* lint

* skeleton loader type fix

* fix types

* lint

* fix types again

* fix manifest not being served locally

* remove preinstalled old client version

* add constant for dev client version

* linting

* Dean PR Feedback

* linting

* pr feedback

* wip

* wip

* clientVersions empty array

* delete from git

* empty array again

* fix tests

* pr feedback

---------

Co-authored-by: Andrew Kingston <andrew@kingston.dev>
2024-03-25 16:39:42 +00:00

224 lines
5.1 KiB
Svelte

<script>
import { onMount, onDestroy } from "svelte"
import { params, goto } from "@roxi/routify"
import {
licensing,
auth,
sideBarCollapsed,
enrichedApps,
} from "stores/portal"
import AppRowContext from "components/start/AppRowContext.svelte"
import FavouriteAppButton from "../FavouriteAppButton.svelte"
import {
Link,
Body,
Button,
Icon,
TooltipPosition,
TooltipType,
} from "@budibase/bbui"
import { sdk } from "@budibase/shared-core"
import { API } from "api"
import ErrorSVG from "./ErrorSVG.svelte"
import { ClientAppSkeleton } from "@budibase/frontend-core"
$: app = $enrichedApps.find(app => app.appId === $params.appId)
$: iframeUrl = getIframeURL(app)
$: isBuilder = sdk.users.isBuilder($auth.user, app?.devId)
let loading = true
const getIframeURL = app => {
loading = true
if (app.status === "published") {
return `/app${app.url}`
}
return `/${app.devId}`
}
let noScreens = false
// Normally fetched in builder/src/pages/builder/app/[application]/_layout.svelte
const fetchScreens = async appId => {
if (!appId) return
const pkg = await API.fetchAppPackage(appId)
noScreens = pkg.screens.length === 0
}
$: fetchScreens(app?.devId)
const receiveMessage = async message => {
if (message.data.type === "docLoaded") {
loading = false
}
}
onMount(() => {
window.addEventListener("message", receiveMessage)
})
onDestroy(() => {
window.removeEventListener("message", receiveMessage)
})
</script>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div class="container">
<div class="header">
{#if $sideBarCollapsed}
<div class="headerButton" on:click={() => sideBarCollapsed.set(false)}>
<Icon
name={"Rail"}
hoverable
tooltip="Expand"
tooltipPosition={TooltipPosition.Right}
tooltipType={TooltipType.Info}
hoverColor={"var(--ink)"}
/>
</div>
{:else}
<div class="headerButton" on:click={() => sideBarCollapsed.set(true)}>
<Icon
name={"RailRightOpen"}
hoverable
tooltip="Collapse"
tooltipType={TooltipType.Info}
tooltipPosition={TooltipPosition.Top}
hoverColor={"var(--ink)"}
size="S"
/>
</div>
{/if}
{#if isBuilder}
<Button
size="M"
secondary
on:click={() => $goto(`/builder/app/${app.devId}`)}
>
Edit
</Button>
{/if}
<div class="headerButton">
<FavouriteAppButton {app} />
</div>
<div class="headerButton" on:click={() => window.open(iframeUrl, "_blank")}>
<Icon
name="LinkOut"
disabled={noScreens}
hoverable
tooltip="Open in new tab"
tooltipType={TooltipType.Info}
tooltipPosition={TooltipPosition.Top}
hoverColor={"var(--ink)"}
size="S"
/>
</div>
<AppRowContext
{app}
options={["duplicate", "delete", "exportDev", "exportProd"]}
align="left"
/>
</div>
{#if noScreens}
<div class="noScreens">
<ErrorSVG />
<Body>You haven't added any screens to your app yet.</Body>
<Body>
<Link size="L" href={`/builder/app/${app.devId}/design`}
>Click here</Link
> to add some.
</Body>
</div>
{:else}
<div
class:hide={!loading || !app?.features?.skeletonLoader}
class="loading"
>
<div class={`loadingThemeWrapper ${app.theme}`}>
<ClientAppSkeleton
noAnimation
hideDevTools={app?.status === "published"}
sideNav={app?.navigation.navigation === "Left"}
hideFooter={$licensing.brandingEnabled}
/>
</div>
</div>
<iframe
class:hide={loading && app?.features?.skeletonLoader}
src={iframeUrl}
title={app.name}
/>
{/if}
</div>
<style>
.headerButton {
color: var(--grey-7);
cursor: pointer;
}
.headerButton:hover {
color: var(--ink);
}
.container {
flex: 1 1 auto;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
padding: 0 var(--spacing-l) var(--spacing-l) var(--spacing-l);
}
.header {
display: flex;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-xl);
flex: 0 0 50px;
}
.loading {
height: 100%;
border: 1px solid var(--spectrum-global-color-gray-300);
border-radius: var(--spacing-s);
overflow: hidden;
}
.loadingThemeWrapper {
height: 100%;
container-type: inline-size;
}
.hide {
visibility: hidden;
height: 0;
border: none;
}
iframe {
flex: 1 1 auto;
border-radius: var(--spacing-s);
border: 1px solid var(--spectrum-global-color-gray-300);
}
.noScreens {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
padding: 20px;
box-sizing: border-box;
}
.noScreens :global(svg) {
width: 100px;
height: 100px;
margin-bottom: 10px;
}
</style>