Fixing issue #3915 so that when using the short hand URL for apps you will be redirected correctly if not logged in, allows all users to make use of it and updating the builder to send the user to the short form factor URL if not in cloud.
This commit is contained in:
parent
7732d8de3e
commit
efc691f238
|
@ -1,126 +0,0 @@
|
||||||
<script>
|
|
||||||
import {
|
|
||||||
Heading,
|
|
||||||
Icon,
|
|
||||||
Body,
|
|
||||||
Layout,
|
|
||||||
ActionMenu,
|
|
||||||
MenuItem,
|
|
||||||
StatusLight,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { gradient } from "actions"
|
|
||||||
import { processStringSync } from "@budibase/string-templates"
|
|
||||||
|
|
||||||
export let app
|
|
||||||
export let exportApp
|
|
||||||
export let viewApp
|
|
||||||
export let editApp
|
|
||||||
export let updateApp
|
|
||||||
export let deleteApp
|
|
||||||
export let unpublishApp
|
|
||||||
export let releaseLock
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="wrapper">
|
|
||||||
<Layout noPadding gap="XS" alignContent="start">
|
|
||||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
|
||||||
<div class="title">
|
|
||||||
{#if app.lockedBy}
|
|
||||||
<Icon name="LockClosed" />
|
|
||||||
{/if}
|
|
||||||
<div class="name" on:click={() => editApp(app)}>
|
|
||||||
<Heading size="XS">
|
|
||||||
{app.name}
|
|
||||||
</Heading>
|
|
||||||
</div>
|
|
||||||
<ActionMenu align="right">
|
|
||||||
<Icon slot="control" name="More" hoverable />
|
|
||||||
{#if app.deployed}
|
|
||||||
<MenuItem on:click={() => viewApp(app)} icon="GlobeOutline">
|
|
||||||
View published app
|
|
||||||
</MenuItem>
|
|
||||||
{/if}
|
|
||||||
{#if app.lockedYou}
|
|
||||||
<MenuItem on:click={() => releaseLock(app)} icon="LockOpen">
|
|
||||||
Release lock
|
|
||||||
</MenuItem>
|
|
||||||
{/if}
|
|
||||||
<MenuItem on:click={() => exportApp(app)} icon="Download">
|
|
||||||
Export
|
|
||||||
</MenuItem>
|
|
||||||
{#if app.deployed}
|
|
||||||
<MenuItem on:click={() => unpublishApp(app)} icon="GlobeRemove">
|
|
||||||
Unpublish
|
|
||||||
</MenuItem>
|
|
||||||
{/if}
|
|
||||||
{#if !app.deployed}
|
|
||||||
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
|
|
||||||
<MenuItem on:click={() => deleteApp(app)} icon="Delete">
|
|
||||||
Delete
|
|
||||||
</MenuItem>
|
|
||||||
{/if}
|
|
||||||
</ActionMenu>
|
|
||||||
</div>
|
|
||||||
<div class="status">
|
|
||||||
<Body size="S">
|
|
||||||
{#if app.updatedAt}
|
|
||||||
{processStringSync("Updated {{ duration time 'millisecond' }} ago", {
|
|
||||||
time: new Date().getTime() - new Date(app.updatedAt).getTime(),
|
|
||||||
})}
|
|
||||||
{:else}
|
|
||||||
Never updated
|
|
||||||
{/if}
|
|
||||||
</Body>
|
|
||||||
<StatusLight active={app.deployed} neutral={!app.deployed}>
|
|
||||||
{#if app.deployed}Published{:else}Unpublished{/if}
|
|
||||||
</StatusLight>
|
|
||||||
</div>
|
|
||||||
</Layout>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.wrapper {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.wrapper :global(.spectrum-StatusLight) {
|
|
||||||
padding: 0;
|
|
||||||
min-height: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview {
|
|
||||||
height: 135px;
|
|
||||||
border-radius: var(--border-radius-s);
|
|
||||||
margin-bottom: var(--spacing-m);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--spacing-m);
|
|
||||||
}
|
|
||||||
.title :global(.spectrum-Icon) {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
.title :global(h1) {
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
.title :global(h1:hover) {
|
|
||||||
color: var(--spectrum-global-color-blue-600);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: color 130ms ease;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -12,7 +12,7 @@
|
||||||
Modal,
|
Modal,
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { apps, organisation, auth } from "stores/portal"
|
import { apps, organisation, auth, admin } from "stores/portal"
|
||||||
import { goto } from "@roxi/routify"
|
import { goto } from "@roxi/routify"
|
||||||
import { AppStatus } from "constants"
|
import { AppStatus } from "constants"
|
||||||
import { gradient } from "actions"
|
import { gradient } from "actions"
|
||||||
|
@ -34,12 +34,16 @@
|
||||||
const publishedAppsOnly = app => app.status === AppStatus.DEPLOYED
|
const publishedAppsOnly = app => app.status === AppStatus.DEPLOYED
|
||||||
|
|
||||||
$: publishedApps = $apps.filter(publishedAppsOnly)
|
$: publishedApps = $apps.filter(publishedAppsOnly)
|
||||||
|
$: isCloud = $admin.cloud
|
||||||
$: userApps = $auth.user?.builder?.global
|
$: userApps = $auth.user?.builder?.global
|
||||||
? publishedApps
|
? publishedApps
|
||||||
: publishedApps.filter(app =>
|
: publishedApps.filter(app =>
|
||||||
Object.keys($auth.user?.roles).includes(app.prodId)
|
Object.keys($auth.user?.roles).includes(app.prodId)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
function getUrl(app) {
|
||||||
|
return !isCloud ? `/app/${encodeURIComponent(app.name)}` : `/${app.prodId}`
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $auth.user && loaded}
|
{#if $auth.user && loaded}
|
||||||
|
@ -93,7 +97,7 @@
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<Layout gap="S" noPadding>
|
<Layout gap="S" noPadding>
|
||||||
{#each userApps as app, idx (app.appId)}
|
{#each userApps as app, idx (app.appId)}
|
||||||
<a class="app" target="_blank" href={`/${app.prodId}`}>
|
<a class="app" target="_blank" href={getUrl(app)}>
|
||||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
<div class="preview" use:gradient={{ seed: app.name }} />
|
||||||
<div class="app-info">
|
<div class="app-info">
|
||||||
<Heading size="XS">{app.name}</Heading>
|
<Heading size="XS">{app.name}</Heading>
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
$: filteredApps = enrichedApps.filter(app =>
|
$: filteredApps = enrichedApps.filter(app =>
|
||||||
app?.name?.toLowerCase().includes(searchTerm.toLowerCase())
|
app?.name?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||||
)
|
)
|
||||||
|
$: isCloud = $admin.cloud
|
||||||
|
|
||||||
const enrichApps = (apps, user, sortBy) => {
|
const enrichApps = (apps, user, sortBy) => {
|
||||||
const enrichedApps = apps.map(app => ({
|
const enrichedApps = apps.map(app => ({
|
||||||
|
@ -158,8 +159,13 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
const viewApp = app => {
|
const viewApp = app => {
|
||||||
const id = app.deployed ? app.prodId : app.devId
|
if (!isCloud && app.deployed) {
|
||||||
window.open(`/${id}`, "_blank")
|
// special case to use the short form name if self hosted
|
||||||
|
window.open(`/app/${encodeURIComponent(app.name)}`)
|
||||||
|
} else {
|
||||||
|
const id = app.deployed ? app.prodId : app.devId
|
||||||
|
window.open(`/${id}`, "_blank")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const editApp = app => {
|
const editApp = app => {
|
||||||
|
|
|
@ -1,18 +1,29 @@
|
||||||
const { getAllApps } = require("@budibase/auth/db")
|
const {
|
||||||
|
getAllApps,
|
||||||
|
getDeployedAppID,
|
||||||
|
isProdAppID,
|
||||||
|
} = require("@budibase/auth/db")
|
||||||
const CouchDB = require("../../db")
|
const CouchDB = require("../../db")
|
||||||
|
|
||||||
const URL_REGEX_SLASH = /\/|\\/g
|
const URL_REGEX_SLASH = /\/|\\/g
|
||||||
|
|
||||||
exports.getApps = async ctx => {
|
exports.getApps = async ctx => {
|
||||||
const apps = await getAllApps(CouchDB, { dev: true })
|
const apps = await getAllApps(CouchDB, { all: true })
|
||||||
const body = {}
|
const body = {}
|
||||||
for (let app of apps) {
|
for (let app of apps) {
|
||||||
let url = app.url || encodeURI(`${app.name}`)
|
let url = app.url || encodeURI(`${app.name}`)
|
||||||
url = `/${url.replace(URL_REGEX_SLASH, "")}`
|
url = `/${url.replace(URL_REGEX_SLASH, "")}`
|
||||||
body[url] = {
|
const appId = app.appId,
|
||||||
appId: app.appId,
|
isProd = isProdAppID(app.appId)
|
||||||
name: app.name,
|
if (!body[url]) {
|
||||||
url,
|
body[url] = {
|
||||||
|
appId: getDeployedAppID(appId),
|
||||||
|
name: app.name,
|
||||||
|
url,
|
||||||
|
deployed: isProd,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body[url].deployed = isProd || body[url].deployed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.body = body
|
ctx.body = body
|
||||||
|
|
Loading…
Reference in New Issue