app improvements

This commit is contained in:
Ruben Fiszel
2022-12-30 19:04:50 +01:00
parent a1fec7c4b7
commit e9488f1b66
16 changed files with 148 additions and 91 deletions
+3 -3
View File
@@ -3947,7 +3947,7 @@ paths:
required: true
schema:
type: string
enum: [script, group_, resource, schedule, variable, flow, folder]
enum: [script, group_, resource, schedule, variable, flow, folder, app]
responses:
"200":
description: acls
@@ -3972,7 +3972,7 @@ paths:
required: true
schema:
type: string
enum: [script, group_, resource, schedule, variable, flow, folder]
enum: [script, group_, resource, schedule, variable, flow, folder, app]
requestBody:
description: acl to add
required: true
@@ -4008,7 +4008,7 @@ paths:
required: true
schema:
type: string
enum: [script, group_, resource, schedule, variable, flow, folder]
enum: [script, group_, resource, schedule, variable, flow, folder, app]
requestBody:
description: acl to add
required: true
+1 -1
View File
@@ -37,7 +37,7 @@ pub fn workspaced_service() -> Router {
.route("/list", get(list_apps))
.route("/get/p/*path", get(get_app))
.route("/get/v/*id", get(get_app_by_id))
.route("/exists/*path", post(exists_app))
.route("/exists/*path", get(exists_app))
.route("/update/*path", post(update_app))
.route("/delete/*path", delete(delete_app))
.route("/create", post(create_app))
@@ -5,7 +5,7 @@
import { Alert, Button, Drawer } from './common'
import DrawerContent from './common/drawer/DrawerContent.svelte'
import Path from './Path.svelte'
import { FlowService, ScriptService } from '$lib/gen'
import { AppService, FlowService, ScriptService } from '$lib/gen'
const dispatch = createEventDispatcher()
@@ -25,7 +25,6 @@
drawer.openDrawer()
}
async function loadOwner() {
own = await isOwner(path, $userStore!, $workspaceStore!)
}
@@ -61,6 +60,14 @@
path
}
})
} else if (kind == 'app') {
await AppService.updateApp({
workspace: $workspaceStore!,
path: initialPath,
requestBody: {
path
}
})
}
dispatch('update', path)
drawer.closeDrawer()
+4 -1
View File
@@ -2,6 +2,7 @@
import { type Meta, pathToMeta } from '$lib/common'
import {
AppService,
FlowService,
FolderService,
GroupService,
@@ -151,6 +152,8 @@
})
} else if (kind == 'schedule') {
return await ScheduleService.existsSchedule({ workspace: $workspaceStore!, path: path })
} else if (kind == 'app') {
return await AppService.existsApp({ workspace: $workspaceStore!, path: path })
} else {
return false
}
@@ -237,7 +240,7 @@
>
<div class="flex flex-row">
<input class="mr-2" placeholder="New group name" bind:value={newGroupName} />
<Button size="md" startIcon={{ icon: faPlus }} disabled={!newGroupName} on:click={addGroup}>
<Button size="md" endIcon={{ icon: faPlus }} disabled={!newGroupName} on:click={addGroup}>
New&nbsp;group
</Button>
</div>
@@ -13,7 +13,7 @@
const dispatch = createEventDispatcher()
type Kind = 'script' | 'group_' | 'resource' | 'schedule' | 'variable' | 'flow'
type Kind = 'script' | 'group_' | 'resource' | 'schedule' | 'variable' | 'flow' | 'app'
let kind: Kind
let path: string = ''
@@ -51,7 +51,7 @@
</script>
<Drawer bind:open={drawerOpen} size="800px">
<DrawerContent title="Add an app" on:close={() => closeDrawer()}>
<DrawerContent title="Create an App" on:close={() => closeDrawer()}>
<Path bind:error={pathError} bind:path {initialPath} namePlaceholder="my_app" kind="app">
<div slot="ownerToolkit">
App permissions depend on their path. Select the group <span class="font-mono">all</span>
@@ -25,7 +25,7 @@
<button
on:pointerdown|preventDefault|stopPropagation
on:click|preventDefault|stopPropagation={refresh}
class="center-center p-1 rounded border bg-white/60 z-40"
class="center-center p-1 rounded border bg-white/60 hover:bg-gray-200 z-10"
>
<RefreshCw class={loading ? 'animate-spin' : ''} size={16} />
</button>
@@ -33,6 +33,7 @@
await executeComponent()
}
}
executeComponent()
})
let pagePath = $page.params.path
@@ -12,6 +12,7 @@
faHand,
faMobileAlt
} from '@fortawesome/free-solid-svg-icons'
import { Eye, Laptop2, Pencil, PenTool, Smartphone } from 'lucide-svelte'
import { getContext } from 'svelte'
import { Icon } from 'svelte-awesome'
import { sendUserToast } from '../../../utils'
@@ -55,40 +56,37 @@
<div class="border-b flex flex-row justify-between py-1 px-4 items-center">
<input class="text-sm w-64" bind:value={title} />
<div class="flex gap-4 items-center">
<div class="flex gap-8 items-center">
<div>
<ToggleButtonGroup bind:selected={mode}>
<ToggleButton position="left" value="dnd" size="xs">
<Icon data={faHand} class="h-3 mr-1" />
Editor
<div class="inline-flex gap-1 items-center">
<Pencil size={14} />
Editor
</div>
</ToggleButton>
<ToggleButton position="right" value="preview" size="xs">
<Icon data={faDisplay} class="h-4 mr-1" />
Preview
</ToggleButton>
<div class="inline-flex gap-1 items-center"> <Eye size={14} /> Preview</div></ToggleButton
>
</ToggleButtonGroup>
</div>
<div>
<ToggleButtonGroup bind:selected={breakpoint}>
<ToggleButton
position="left"
value="sm"
startIcon={{ icon: faMobileAlt }}
size="xs"
iconOnly
/>
<ToggleButton
position="right"
value="lg"
startIcon={{ icon: faDesktopAlt }}
size="xs"
iconOnly
/>
<ToggleButton position="left" value="sm" size="xs">
<Smartphone size={14} />
</ToggleButton>
<ToggleButton position="right" value="lg" size="xs"><Laptop2 size={14} /></ToggleButton>
</ToggleButtonGroup>
</div>
</div>
<div class="flex flex-row gap-2 w-64 justify-end">
<Button color="dark" size="xs" variant="border" startIcon={{ icon: faExternalLink }}>
<Button
on:click={() => sendUserToast('Publishing apps publically at secret urls is coming soon')}
color="dark"
size="xs"
variant="border"
startIcon={{ icon: faExternalLink }}
>
Publish
</Button>
<Button loading={loading.save} on:click={save} color="dark" size="xs">Save</Button>
@@ -100,57 +100,52 @@
}
</script>
<div
on:pointerdown={onpointerdown}
on:pointerleave={onpointerup}
on:pointerup={onpointerup}
class="bg-white h-full relative"
>
<div class="bg-white h-full relative">
<div class="w-full flex justify-between border-b px-4 py-2 mb-4 items-center gap-4">
<h2>{$app.title}</h2>
<RecomputeAllComponents />
<div class="text-2xs text-gray-600"
>{policy.execution_mode} mode {policy.on_behalf_of
? `on behalf of ${policy.on_behalf_of}`
: ''}</div
>{policy.on_behalf_of ? `on behalf of ${policy.on_behalf_of}` : ''}</div
>
</div>
<Grid
bind:items={$app.grid}
let:dataItem
rowHeight={46}
cols={columnConfiguration}
fastStart={true}
on:pointerup={({ detail }) => selectComponent(detail.id)}
gap={[4, 2]}
>
{#each $lazyGrid as gridComponent (gridComponent.id)}
{#if gridComponent.data.id === dataItem.data.id}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class={classNames(
'h-full w-full flex justify-center align-center',
gridComponent.data.card ? 'border border-gray-100' : ''
)}
on:click|preventDefault|capture|once
>
<ComponentEditor
{pointerdown}
bind:component={gridComponent.data}
selected={$selectedComponent === dataItem.data.id}
locked={isFixed(gridComponent)}
on:delete={() => removeGridElement(gridComponent.data)}
on:lock={() => {
let fComponent = $app.grid.find((c) => c.id === gridComponent.id)
if (fComponent) {
fComponent = toggleFixed(fComponent)
}
}}
/>
</div>
{/if}
{/each}
</Grid>
<div on:pointerdown={onpointerdown} on:pointerleave={onpointerup} on:pointerup={onpointerup}>
<Grid
bind:items={$app.grid}
let:dataItem
rowHeight={46}
cols={columnConfiguration}
fastStart={true}
on:pointerup={({ detail }) => selectComponent(detail.id)}
gap={[4, 2]}
>
{#each $lazyGrid as gridComponent (gridComponent.id)}
{#if gridComponent.data.id === dataItem.data.id}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class={classNames(
'h-full w-full flex justify-center align-center',
gridComponent.data.card ? 'border border-gray-100' : ''
)}
on:click|preventDefault|capture|once
>
<ComponentEditor
{pointerdown}
bind:component={gridComponent.data}
selected={$selectedComponent === dataItem.data.id}
locked={isFixed(gridComponent)}
on:delete={() => removeGridElement(gridComponent.data)}
on:lock={() => {
let fComponent = $app.grid.find((c) => c.id === gridComponent.id)
if (fComponent) {
fComponent = toggleFixed(fComponent)
}
}}
/>
</div>
{/if}
{/each}
</Grid>
</div>
</div>
<style>
@@ -1,4 +1,6 @@
<script lang="ts">
import Dropdown from '$lib/components/Dropdown.svelte'
import Toggle from '$lib/components/Toggle.svelte'
import { RefreshCw } from 'lucide-svelte'
import { getContext } from 'svelte'
import type { AppEditorContext } from '../types'
@@ -16,12 +18,26 @@
)
loading = false
}
let timeout: NodeJS.Timeout | undefined = undefined
</script>
<button
on:click|preventDefault|stopPropagation={onRefresh}
class="center-center p-1 rounded border bg-white/60 inline-flex gap-2"
>
<RefreshCw class={loading ? 'animate-spin' : ''} size={20} /> ({Object.keys($runnableComponents)
.length})
</button>
<div class="flex gap-4 items-center">
<button
on:click|preventDefault|stopPropagation={onRefresh}
class="center-center p-1 rounded border bg-white/60 hover:bg-gray-200 inline-flex gap-2"
>
<RefreshCw class={loading ? 'animate-spin' : ''} size={20} /> ({Object.keys($runnableComponents)
.length})
</button>
<Toggle
size="xs"
on:change={(e) => {
if (e.detail) {
timeout = setInterval(onRefresh, 15000)
} else {
timeout && clearInterval(timeout)
}
}}
options={{ right: 'auto (15s)' }}
/>
</div>
@@ -1,9 +1,17 @@
<script lang="ts">
import Dropdown from '$lib/components/Dropdown.svelte'
import type MoveDrawer from '$lib/components/MoveDrawer.svelte'
import SharedBadge from '$lib/components/SharedBadge.svelte'
import type ShareModal from '$lib/components/ShareModal.svelte'
import { AppService, type ListableApp } from '$lib/gen'
import { userStore, workspaceStore } from '$lib/stores'
import { faEdit, faEye, faTrashAlt } from '@fortawesome/free-solid-svg-icons'
import {
faEdit,
faEye,
faFileExport,
faShare,
faTrashAlt
} from '@fortawesome/free-solid-svg-icons'
import { MoreVertical } from 'lucide-svelte'
import { createEventDispatcher } from 'svelte'
import Button from '../button/Button.svelte'
@@ -12,6 +20,8 @@
export let app: ListableApp & { canWrite: boolean }
export let marked: string | undefined
export let starred: boolean
export let shareModal: ShareModal
export let moveDrawer: MoveDrawer
let { summary, path, extra_perms, canWrite, workspace_id } = app
@@ -48,6 +58,7 @@
</div>
{/if}
{/if}
<Button
href="/apps/get/{path}"
color="dark"
@@ -67,6 +78,21 @@
icon: faEye,
href: `/apps/get/${path}`
},
{
displayName: 'Move',
icon: faFileExport,
action: () => {
moveDrawer.openDrawer(path, 'app')
},
disabled: !canWrite
},
{
displayName: canWrite ? 'Share' : 'See Permissions',
icon: faShare,
action: () => {
shareModal.openDrawer && shareModal.openDrawer(path, 'app')
}
},
{
displayName: 'Delete',
icon: faTrashAlt,
@@ -321,6 +321,8 @@
marked={item.marked}
on:change={loadApps}
app={item}
{moveDrawer}
{shareModal}
/>
{/if}
{/each}
@@ -130,7 +130,7 @@
</Alert>
{/if}
<PageHeader title="Home">
<div class="flex flex-row gap-2 flex-wrap">
<div class="flex flex-row gap-3 flex-wrap">
{#if !$userStore?.operator}
<CreateApp />
<CreateActionsScript />
@@ -79,9 +79,16 @@
placeholder="New folder name"
bind:value={newFolderName}
/>
<Button size="md" startIcon={{ icon: faPlus }} disabled={!newFolderName} on:click={addFolder}>
New&nbsp;folder
</Button>
<div>
<Button
size="md"
startIcon={{ icon: faPlus }}
disabled={!newFolderName}
on:click={addFolder}
>
New&nbsp;folder
</Button>
</div>
</div>
</PageHeader>
@@ -70,9 +70,11 @@
placeholder="New group name"
bind:value={newGroupName}
/>
<Button size="md" startIcon={{ icon: faPlus }} disabled={!newGroupName} on:click={addGroup}>
New&nbsp;group
</Button>
<div>
<Button size="md" startIcon={{ icon: faPlus }} disabled={!newGroupName} on:click={addGroup}>
New&nbsp;group
</Button>
</div>
</div>
</PageHeader>