mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-12 08:05:44 +00:00
feat(apps): added deployment history browser
This commit is contained in:
@@ -48,16 +48,16 @@
|
||||
|
||||
export let app: App
|
||||
export let path: string
|
||||
export let initialMode: EditorMode = 'dnd'
|
||||
export let policy: Policy
|
||||
export let summary: string
|
||||
export let fromHub: boolean = false
|
||||
export let versions: number[]
|
||||
|
||||
migrateApp(app)
|
||||
|
||||
const appStore = writable<App>(app)
|
||||
const selectedComponent = writable<string[] | undefined>(undefined)
|
||||
const mode = writable<EditorMode>(initialMode)
|
||||
const mode = writable<EditorMode>('dnd')
|
||||
const breakpoint = writable<EditorBreakpoint>('lg')
|
||||
const summaryStore = writable(summary)
|
||||
const connectingInput = writable<ConnectingInput>({
|
||||
@@ -205,9 +205,7 @@
|
||||
|
||||
{#if !$userStore?.operator}
|
||||
{#if $appStore}
|
||||
{#if initialMode !== 'preview'}
|
||||
<AppEditorHeader {policy} {fromHub} />
|
||||
{/if}
|
||||
<AppEditorHeader on:restore {versions} {policy} {fromHub} />
|
||||
|
||||
{#if $mode === 'preview'}
|
||||
<SplitPanesWrapper>
|
||||
|
||||
@@ -17,7 +17,13 @@
|
||||
import { AppService, DraftService, Job, Policy } from '$lib/gen'
|
||||
import { redo, undo } from '$lib/history'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import { faClipboard, faFileExport, faSave, faSlidersH } from '@fortawesome/free-solid-svg-icons'
|
||||
import {
|
||||
faClipboard,
|
||||
faFileExport,
|
||||
faHistory,
|
||||
faSave,
|
||||
faSlidersH
|
||||
} from '@fortawesome/free-solid-svg-icons'
|
||||
import {
|
||||
AlignHorizontalSpaceAround,
|
||||
Bug,
|
||||
@@ -52,6 +58,7 @@
|
||||
import Tooltip from '$lib/components/Tooltip.svelte'
|
||||
import { Sha256 } from '@aws-crypto/sha256-js'
|
||||
import { sendUserToast } from '$lib/toast'
|
||||
import DeploymentHistory from './DeploymentHistory.svelte'
|
||||
|
||||
async function hash(message) {
|
||||
try {
|
||||
@@ -72,6 +79,7 @@
|
||||
|
||||
export let policy: Policy
|
||||
export let fromHub: boolean = false
|
||||
export let versions: number[]
|
||||
|
||||
const {
|
||||
app,
|
||||
@@ -111,6 +119,7 @@
|
||||
let saveDrawerOpen = false
|
||||
let jobsDrawerOpen = false
|
||||
let inputsDrawerOpen = fromHub
|
||||
let historyBrowserDrawerOpen = false
|
||||
|
||||
function closeSaveDrawer() {
|
||||
saveDrawerOpen = false
|
||||
@@ -514,6 +523,12 @@
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<Drawer bind:open={historyBrowserDrawerOpen} size="1200px">
|
||||
<DrawerContent title="Deployment History" on:close={() => historyBrowserDrawerOpen}>
|
||||
<DeploymentHistory on:restore {versions} />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<Drawer bind:open={jobsDrawerOpen} size="900px">
|
||||
<DrawerContent
|
||||
noPadding
|
||||
@@ -690,6 +705,13 @@
|
||||
placement="bottom-end"
|
||||
btnClasses="!rounded-md"
|
||||
dropdownItems={[
|
||||
{
|
||||
displayName: 'Deployment History',
|
||||
icon: faHistory,
|
||||
action: () => {
|
||||
historyBrowserDrawerOpen = true
|
||||
}
|
||||
},
|
||||
{
|
||||
displayName: 'JSON',
|
||||
icon: faFileExport,
|
||||
|
||||
@@ -22,14 +22,15 @@
|
||||
import { deepEqual } from 'fast-equals'
|
||||
import { dfs } from './appUtils'
|
||||
import { BG_PREFIX, migrateApp } from '../utils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
|
||||
export let app: App
|
||||
export let appPath: string
|
||||
export let breakpoint: Writable<EditorBreakpoint>
|
||||
export let policy: Policy
|
||||
export let summary: string
|
||||
export let workspace: string
|
||||
export let isEditor: boolean
|
||||
export let appPath: string = ''
|
||||
export let breakpoint: Writable<EditorBreakpoint> = writable('lg')
|
||||
export let policy: Policy = {}
|
||||
export let summary: string = ''
|
||||
export let workspace: string = $workspaceStore!
|
||||
export let isEditor: boolean = false
|
||||
export let context: Record<string, any>
|
||||
export let noBackend: boolean = false
|
||||
export let isLocked = false
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<script lang="ts">
|
||||
import { Pane, Splitpanes } from 'svelte-splitpanes'
|
||||
import PanelSection from './settingsPanel/common/PanelSection.svelte'
|
||||
import { classNames, displayDate } from '$lib/utils'
|
||||
import { AppService, AppWithLastVersion } from '$lib/gen'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import AppPreview from './AppPreview.svelte'
|
||||
import { Skeleton } from '$lib/components/common'
|
||||
import Button from '$lib/components/common/button/Button.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let versions: number[]
|
||||
|
||||
let selectedVersion: number | undefined = undefined
|
||||
let selected: AppWithLastVersion | undefined = undefined
|
||||
|
||||
$: selectedVersion !== undefined && loadValue(selectedVersion)
|
||||
|
||||
async function loadValue(version: number) {
|
||||
let app = await AppService.getAppByVersion({ workspace: $workspaceStore!, id: version })
|
||||
|
||||
selected = app
|
||||
}
|
||||
|
||||
$: reversedVersions = versions.slice().reverse()
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<Splitpanes class="!overflow-visible">
|
||||
<Pane size={20}>
|
||||
<PanelSection title="Past Deployments">
|
||||
<div class="flex flex-col gap-2 w-full">
|
||||
{#if versions.length > 0}
|
||||
<div class="flex gap-2 flex-col">
|
||||
{#each reversedVersions ?? [] as version}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class={classNames(
|
||||
'border flex gap-1 truncate justify-between flex-row w-full items-center p-2 rounded-md cursor-pointer hover:bg-blue-50 hover:text-blue-400',
|
||||
selectedVersion == version ? 'bg-blue-100 text-blue-600' : ''
|
||||
)}
|
||||
on:click={() => (selectedVersion = version)}
|
||||
>
|
||||
<span class="text-xs truncate">{version}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="text-sm text-gray-500">No items</div>
|
||||
{/if}
|
||||
</div>
|
||||
</PanelSection>
|
||||
</Pane>
|
||||
<Pane size={80}>
|
||||
<div class="h-full w-full overflow-auto">
|
||||
{#if selectedVersion}
|
||||
{#if selected}
|
||||
<div class="flex justify-between">
|
||||
<h3 class="p-1">Deployed {displayDate(selected.created_at)} by {selected.created_by}</h3
|
||||
>
|
||||
<div class="flex gap-2">
|
||||
<Button on:click={() => window.open(`/apps/add?template_id=${selectedVersion}`)}
|
||||
>Restore as fork</Button
|
||||
>
|
||||
<Button on:click={() => dispatch('restore', selected)}>Restore here</Button>
|
||||
</div>
|
||||
</div>
|
||||
<AppPreview noBackend app={selected.value} context={{}} />
|
||||
{:else}
|
||||
<Skeleton layout={[[40]]} />
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="text-sm p-2 text-gray-500">Select a deployment version to see its details</div>
|
||||
{/if}
|
||||
</div>
|
||||
</Pane>
|
||||
</Splitpanes>
|
||||
@@ -14,6 +14,7 @@
|
||||
let nodraft = $page.url.searchParams.get('nodraft')
|
||||
const hubId = $page.url.searchParams.get('hub')
|
||||
const templatePath = $page.url.searchParams.get('template')
|
||||
const templateId = $page.url.searchParams.get('template_id')
|
||||
|
||||
const importJson = $importStore
|
||||
if ($importStore) {
|
||||
@@ -63,6 +64,14 @@
|
||||
value = template.value
|
||||
sendUserToast('App loaded from template')
|
||||
goto('?', { replaceState: true })
|
||||
} else if (templateId) {
|
||||
const template = await AppService.getAppByVersion({
|
||||
workspace: $workspaceStore!,
|
||||
id: parseInt(templateId)
|
||||
})
|
||||
value = template.value
|
||||
sendUserToast('App loaded from template')
|
||||
goto('?', { replaceState: true })
|
||||
} else if (hubId) {
|
||||
const hub = await AppService.getHubAppById({ id: Number(hubId) })
|
||||
value = {
|
||||
@@ -99,7 +108,7 @@
|
||||
{#if value}
|
||||
<div class="h-screen">
|
||||
{#key value}
|
||||
<AppEditor {summary} app={value} path={''} {policy} fromHub={hubId != null} />
|
||||
<AppEditor versions={[]} {summary} app={value} path={''} {policy} fromHub={hubId != null} />
|
||||
{/key}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -77,7 +77,18 @@
|
||||
{#key redraw}
|
||||
{#if app}
|
||||
<div class="h-screen">
|
||||
<AppEditor summary={app.summary} app={app.value} path={app.path} policy={app.policy} />
|
||||
<AppEditor
|
||||
on:restore={(e) => {
|
||||
sendUserToast('App restored from previous deployment')
|
||||
app = e.detail
|
||||
redraw++
|
||||
}}
|
||||
versions={app.versions}
|
||||
summary={app.summary}
|
||||
app={app.value}
|
||||
path={app.path}
|
||||
policy={app.policy}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
{/key}
|
||||
|
||||
Reference in New Issue
Block a user