Skip to content

Commit

Permalink
feat: provider creation form
Browse files Browse the repository at this point in the history
Creating an instance of a Podman Machine or Kubernetes provider currently has
a UI that doesn't quite match other places. Switching it to be a FormPage
aligns the look and feel with the rest of our UI (header, breadcrumbs, etc.)
and fixes things that we've already solved once in all the form pages,
e.g. clicking Esc to close (#2853).

Since this page was done a while ago there was some minor restructuring to
make this happen:
- The Resources page has to be marked as a details navigation hint so that
  the backlink/close button goes back to the correct page.
- The code to find the provider display name and image (header info) is moved
  up from the connection creation page to the provider rendering form and
  onboardig.
- This makes the provider image 'always hidden' on the component, so the
  property could be removed.

Fixes #2853.

Signed-off-by: Tim deBoer <git@tdeboer.ca>
  • Loading branch information
deboer-tim committed Oct 16, 2023
1 parent c55638b commit 602f2ab
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 87 deletions.
13 changes: 11 additions & 2 deletions packages/renderer/src/lib/onboarding/OnboardingComponent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ let providers: ProviderInfo[];
let providerInfo: ProviderInfo | undefined;
$: providerInfo;
let providerDisplayName: string;
$: providerDisplayName =
(providerInfo?.containerProviderConnectionCreation
? providerInfo?.containerProviderConnectionCreationDisplayName || undefined
: providerInfo?.kubernetesProviderConnectionCreation
? providerInfo?.kubernetesProviderConnectionCreationDisplayName
: undefined) || providerInfo?.name;
onMount(() => {
configurationProperties.subscribe(value => {
configurationItems = value;
Expand All @@ -31,14 +39,16 @@ onMount(() => {
</script>

{#if providerInfo && configurationItems}
<h1 class="font-semibold px-6 pb-2" aria-label="title">
Create a {providerDisplayName}
</h1>
{#if component === 'createContainerProviderConnection' && providerInfo?.containerProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
providerInfo="{providerInfo}"
properties="{configurationItems}"
propertyScope="ContainerProviderConnectionFactory"
callback="{window.createContainerProviderConnection}"
disableEmptyScreen="{true}"
hideProviderImage="{true}"
hideCloseButton="{true}" />
{:else if component === 'createKubernetesProviderConnection' && providerInfo?.kubernetesProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
Expand All @@ -47,7 +57,6 @@ onMount(() => {
propertyScope="KubernetesProviderConnectionFactory"
callback="{window.createKubernetesProviderConnection}"
disableEmptyScreen="{true}"
hideProviderImage="{true}"
hideCloseButton="{true}" />
{:else}
<div aria-label="not supported warning" class="flex flex-row min-h-[500px] items-center justify-center">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ export let callback: (
) => Promise<void>;
export let taskId: number | undefined = undefined;
export let disableEmptyScreen = false;
export let hideProviderImage = false;
export let hideCloseButton = false;
$: configurationValues = new Map<string, string>();
Expand Down Expand Up @@ -362,23 +361,6 @@ function closePage() {
</Button>
</EmptyScreen>
{:else}
{#if !hideProviderImage}
<div class="my-2 px-6" aria-label="main image">
{#if providerInfo?.images?.icon}
{#if typeof providerInfo.images.icon === 'string'}
<img src="{providerInfo.images.icon}" alt="{providerInfo.name}" class="max-h-10" />
<!-- TODO check theme used for image, now use dark by default -->
{:else}
<img src="{providerInfo.images.icon.dark}" alt="{providerInfo.name}" class="max-h-10" />
{/if}
{/if}
</div>
{/if}
<h1 class="font-semibold px-6 pb-2" aria-label="title">
{creationInProgress ? 'Creating' : 'Create a'}
{providerDisplayName}
{creationInProgress ? '...' : ''}
</h1>
<div class="flex flex-col px-6 w-full h-full overflow-auto">
{#if pageIsLoading}
<div class="text-center mt-16 p-2" role="status">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ onMount(async () => {
<Route path="/extension/:extensionId/*" breadcrumb="Extensions" let:meta>
<PreferencesExtensionRendering extensionId="{meta.params.extensionId}" />
</Route>
<Route path="/provider/:providerInternalId/*" breadcrumb="Resources" let:meta>
<Route path="/provider/:providerInternalId/*" breadcrumb="Resources" let:meta navigationHint="details">
<PreferencesProviderRendering providerInternalId="{meta.params.providerInternalId}" properties="{properties}" />
</Route>
<Route path="/provider-task/:providerInternalId/:taskId/*" breadcrumb="Resources" let:meta>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import { writeToTerminal } from './Util';
import PreferencesConnectionCreationRendering from './PreferencesConnectionCreationRendering.svelte';
import ErrorMessage from '../ui/ErrorMessage.svelte';
import Route from '../../Route.svelte';
import { faHistory, faPlay, faStop, faXmark } from '@fortawesome/free-solid-svg-icons';
import Fa from 'svelte-fa';
import { faHistory, faPlay, faStop } from '@fortawesome/free-solid-svg-icons';
import type { Terminal } from 'xterm';
import Button from '../ui/Button.svelte';
import FormPage from '../ui/FormPage.svelte';
export let properties: IConfigurationPropertyRecordedSchema[] = [];
export let providerInternalId: string | undefined = undefined;
Expand All @@ -38,6 +38,14 @@ onMount(() => {
let providerInfo: ProviderInfo;
$: providerInfo = providers.filter(provider => provider.internalId === providerInternalId)[0];
let providerDisplayName: string;
$: providerDisplayName =
(providerInfo?.containerProviderConnectionCreation
? providerInfo?.containerProviderConnectionCreationDisplayName || undefined
: providerInfo?.kubernetesProviderConnectionCreation
? providerInfo?.kubernetesProviderConnectionCreationDisplayName
: undefined) || providerInfo?.name;
let logsTerminal: Terminal;
async function startProvider(): Promise<void> {
Expand All @@ -62,79 +70,87 @@ async function stopReceivingLogs(providerInternalId: string): Promise<void> {
}
</script>

<Route path="/*" breadcrumb="{providerInfo?.name}">
<div class="flex flex-col bg-charcoal-800 py-1 w-full h-full overflow-hidden">
<div class="px-6">
<button
aria-label="Close"
class="hover:text-gray-700 float-right text-lg"
on:click="{() => router.goto('/preferences/resources')}">
<Fa icon="{faXmark}" />
</button>
</div>
<h1 class="capitalize text-sm px-6">Resources > {providerInfo?.name}</h1>
<!-- Manage lifecycle-->
{#if providerInfo?.lifecycleMethods}
<div class="pl-1 py-2 px-6">
<div class="text-sm italic text-gray-700">Status</div>
<div class="pl-3">{providerInfo.status}</div>
</div>

<div class="py-2 px-6 flex flex:row">
<!-- start is enabled only in stopped mode-->
{#if providerInfo?.lifecycleMethods.includes('start')}
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{providerInfo.status !== 'stopped'}" on:click="{() => startProvider()}" icon="{faPlay}">
Start
</Button>
</div>
<Route path="/*" breadcrumb="{providerInfo?.name}" navigationHint="details">
<FormPage title="Create a {providerDisplayName}">
<svelte:fragment slot="icon">
{#if providerInfo?.images?.icon}
{#if typeof providerInfo.images.icon === 'string'}
<img src="{providerInfo.images.icon}" alt="{providerInfo.name}" class="max-h-10" />
<!-- TODO check theme used for image, now use dark by default -->
{:else}
<img src="{providerInfo.images.icon.dark}" alt="{providerInfo.name}" class="max-h-10" />
{/if}
{/if}
</svelte:fragment>

<svelte:fragment slot="actions">
<!-- Manage lifecycle-->
{#if providerInfo?.lifecycleMethods}
<div class="pl-1 py-2 px-6">
<div class="text-sm italic text-gray-700">Status</div>
<div class="pl-3">{providerInfo.status}</div>
</div>

<!-- stop is enabled only in started mode-->
{#if providerInfo.lifecycleMethods.includes('stop')}
<div class="py-2 px-6 flex flex:row">
<!-- start is enabled only in stopped mode-->
{#if providerInfo?.lifecycleMethods.includes('start')}
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{providerInfo.status !== 'stopped'}" on:click="{() => startProvider()}" icon="{faPlay}">
Start
</Button>
</div>
{/if}

<!-- stop is enabled only in started mode-->
{#if providerInfo.lifecycleMethods.includes('stop')}
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{providerInfo.status !== 'started'}" on:click="{() => stopProvider()}" icon="{faStop}">
Stop
</Button>
</div>
{/if}
<div class="px-2 text-sm italic text-gray-700">
<Button disabled="{providerInfo.status !== 'started'}" on:click="{() => stopProvider()}" icon="{faStop}">
Stop
<Button
on:click="{() => {
showModalProviderInfo = providerInfo;
// startReceivinLogs(providerInfo);
}}"
icon="{faHistory}">
Show Logs
</Button>
</div>
{/if}
<div class="px-2 text-sm italic text-gray-700">
<Button
on:click="{() => {
showModalProviderInfo = providerInfo;
// startReceivinLogs(providerInfo);
}}"
icon="{faHistory}">
Show Logs
</Button>

{#if providerLifecycleError}
<ErrorMessage error="{providerLifecycleError}" />
{/if}
</div>
{/if}
</svelte:fragment>

<div slot="content" class="p-5 min-w-full h-fit">
<div class="bg-charcoal-700 px-6 py-4">
<!-- Create connection panel-->
{#if providerInfo?.containerProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
providerInfo="{providerInfo}"
properties="{properties}"
propertyScope="ContainerProviderConnectionFactory"
callback="{window.createContainerProviderConnection}"
taskId="{taskId}" />
{/if}

{#if providerLifecycleError}
<ErrorMessage error="{providerLifecycleError}" />
<!-- Create connection panel-->
{#if providerInfo?.kubernetesProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
providerInfo="{providerInfo}"
properties="{properties}"
propertyScope="KubernetesProviderConnectionFactory"
callback="{window.createKubernetesProviderConnection}"
taskId="{taskId}" />
{/if}
</div>
{/if}

<!-- Create connection panel-->
{#if providerInfo?.containerProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
providerInfo="{providerInfo}"
properties="{properties}"
propertyScope="ContainerProviderConnectionFactory"
callback="{window.createContainerProviderConnection}"
taskId="{taskId}" />
{/if}

<!-- Create connection panel-->
{#if providerInfo?.kubernetesProviderConnectionCreation === true}
<PreferencesConnectionCreationRendering
providerInfo="{providerInfo}"
properties="{properties}"
propertyScope="KubernetesProviderConnectionFactory"
callback="{window.createKubernetesProviderConnection}"
taskId="{taskId}" />
{/if}
</div>
</div>
</FormPage>
</Route>
{#if showModalProviderInfo}
{@const showModalProviderInfoInternalId = showModalProviderInfo.internalId}
Expand Down

0 comments on commit 602f2ab

Please sign in to comment.