Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI Package Deploy Routing Refactor #1265

Merged
merged 22 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d7a2c17
perform initial routing refactor
Noxsios Jan 25, 2023
a30517f
fix stepper state
Noxsios Jan 25, 2023
8a65ebe
spdx
Noxsios Jan 25, 2023
d3f8d49
fix yaml code rendering
Noxsios Jan 25, 2023
06eeb2b
re-route if state does not exist
Noxsios Jan 25, 2023
d1c7029
fix @pre-init tests
Noxsios Jan 26, 2023
8b5b73a
uri encode the pkgName
Noxsios Jan 26, 2023
cace5c2
add a simple error page
Noxsios Jan 26, 2023
31f458e
improve error handling on deploy re-routing page
Noxsios Jan 26, 2023
fbeb4ac
initial warning banner if deploying package without initialized zarf
Noxsios Jan 26, 2023
c9cdcda
tweak spinner to work across more components, use as a simple loading…
Noxsios Jan 26, 2023
df844db
Merge branch 'main' into razzle-rework-ui-package-deployment-routing
Noxsios Jan 26, 2023
3becbc8
add updated section header
Noxsios Jan 26, 2023
abfbd07
Merge branch 'main' into razzle-rework-ui-package-deployment-routing
Noxsios Jan 26, 2023
3695565
Merge branch 'main' into razzle-rework-ui-package-deployment-routing
jeff-mccoy Jan 28, 2023
37fe595
greatly simplify package deploy loading flow
Noxsios Jan 30, 2023
95169b9
handle error if init is not found
Noxsios Jan 30, 2023
cb7b665
Merge branch 'main' into razzle-rework-ui-package-deployment-routing
Noxsios Jan 30, 2023
0ceca36
Merge branch 'main' into razzle-rework-ui-package-deployment-routing
Racer159 Jan 30, 2023
9f090a3
get init path on root page load, then pass to deploy route
Noxsios Jan 30, 2023
1f6ec51
catch the error if init is not found
Noxsios Jan 31, 2023
fe9d3ec
cleanup dead css
Noxsios Jan 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/internal/api/packages/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func findPackage(pattern *regexp.Regexp, w http.ResponseWriter, setDir func() (s

files, err := utils.RecursiveFileList(targetDir, pattern)
if err != nil || len(files) == 0 {
pkgNotFoundMsg := fmt.Sprintf("Package not found: %s", pattern.String())
pkgNotFoundMsg := fmt.Sprintf("Unable to locate the package: %s", pattern.String())
message.ErrorWebf(err, w, pkgNotFoundMsg)
return
}
Expand Down
2 changes: 1 addition & 1 deletion src/internal/api/packages/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func Read(w http.ResponseWriter, r *http.Request) {
path := chi.URLParam(r, "path")

if pkg, err := readPackage(path); err != nil {
message.ErrorWebf(err, w, "Unable to read the package")
message.ErrorWebf(err, w, "Unable to read the package at: `%s`", path)
} else {
common.WriteJSONResponse(w, pkg, http.StatusOK)
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/01_start_page.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ test.describe('start page', () => {

await page.locator('span:has-text("Initialize Cluster")').click();

await page.waitForURL('**/initialize/configure');
await page.waitForURL('/package/init/configure');
});
test('page redirects to /packages @post-init', async ({ page }) => {
await page.goto('/auth?token=insecure');
Expand Down
46 changes: 30 additions & 16 deletions src/test/ui/02_initialize_cluster.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,29 @@ test.beforeEach(async ({ page }) => {
page.on('pageerror', (err) => console.log(err.message));
});

const getToConfigurePage = async (page) => {
await page.goto('/auth?token=insecure&next=/');
await page.getByRole('link', { name: 'Initialize Cluster' }).click();
await page.waitForURL('/package/init/configure');
};

const validateHorizontalStepperItems = async (page, activeIndex, steps) => {
const stepperItems = await page.locator('.stepper .stepper-item .step');
for (let i = 0; i < stepperItems.length; i++) {
await expect(stepperItems.nth(i)).toContainText(steps[i]);
if (activeIndex <= i) {
await expect(stepperItems.nth(i).locator('.step-icon')).toHaveClass(/primary/);
} else {
await expect(stepperItems.nth(i).locator('.step-icon')).toHaveClass(/disabled/);
}
}
};

test.describe('initialize a zarf cluster', () => {
test('configure the init package @pre-init', async ({ page }) => {
await page.goto('/auth?token=insecure&next=/initialize/configure');
await getToConfigurePage(page);

// Stepper
const stepperItems = await page.locator('.stepper .stepper-item .step');
await expect(stepperItems.nth(0).locator('.step-icon')).toHaveClass(/primary/);
await expect(stepperItems.nth(0)).toContainText('Configure');
await expect(stepperItems.nth(1).locator('.step-icon')).toHaveClass(/primary/);
await expect(stepperItems.nth(1)).toContainText('2 Review');
await expect(stepperItems.nth(2).locator('.step-icon')).toHaveClass(/disabled/);
await expect(stepperItems.nth(2)).toContainText('3 Deploy');
await validateHorizontalStepperItems(page, 0, ['1 Configure', '2 Review', '3 Deploy']);

// Package details
await expect(page.locator('text=Package Type ZarfInitConfig')).toBeVisible();
Expand Down Expand Up @@ -52,23 +63,26 @@ test.describe('initialize a zarf cluster', () => {
await expect(gitServerDeployToggle).toHaveAttribute('aria-pressed', 'true');

await page.locator('text=review deployment').click();
await expect(page).toHaveURL('/initialize/review');
await expect(page).toHaveURL('/package/init/review');
});

test('review the init package @pre-init', async ({ page }) => {
await page.goto('/auth?token=insecure&next=/initialize/review');
await getToConfigurePage(page);

await page.locator('text=review deployment').click();

await validateHorizontalStepperItems(page, 1, ['Configure', '2 Review', '3 Deploy']);

await validateRequiredCheckboxes(page);
});

test('deploy the init package @init', async ({ page }) => {
await page.goto('/auth?token=insecure&next=/');
await page.getByRole('link', { name: 'Initialize Cluster' }).click();
await page.waitForURL('/initialize/configure');
await getToConfigurePage(page);
await page.getByRole('link', { name: 'review deployment' }).click();
await page.waitForURL('/initialize/review');
await page.waitForURL('/package/init/review');
await page.getByRole('link', { name: 'deploy' }).click();
await page.waitForURL('/initialize/deploy');
await page.waitForURL('/package/init/deploy');
await validateHorizontalStepperItems(page, 2, ['Configure', 'Review', '3 Deploy']);

// expect all steps to have success class
const stepperItems = page.locator('.stepper-vertical .step-icon');
Expand Down
7 changes: 2 additions & 5 deletions src/ui/lib/components/package-component-accordion.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
<script lang="ts">
import YamlCode from './yaml-code.svelte';

import 'prismjs/components/prism-yaml';
import 'prismjs/themes/prism-okaidia.css';

import type { ZarfComponent } from '$lib/api-types';
import { pkgComponentDeployStore } from '$lib/store';
import { Accordion, IconButton, Typography } from '@ui';
Expand Down Expand Up @@ -52,7 +49,7 @@
</Typography>
</div>
{#if !readOnly}
<div style={`gap: 5px; visibility: ${component.required ? "hidden": "initial"}`}>
<div style={`gap: 5px; visibility: ${component.required ? 'hidden' : 'initial'}`}>
<IconButton
toggleable
class="deploy-component-toggle"
Expand All @@ -79,7 +76,7 @@
</div>
{/if}
</div>
<YamlCode slot="content" {component} />
<YamlCode slot="content" code={component} />
</Accordion>

<style>
Expand Down
29 changes: 18 additions & 11 deletions src/ui/lib/components/package-err-not-found.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,21 @@
<script lang="ts">
import { Dialog, Typography, Button } from '@ui';
import bigZarf from '@images/zarf-bubbles-right.png';
export let pkgName: string;
export let message: string;
</script>

<Dialog open clickAway={false}>
<div slot="content" class="dialog-content">
<!-- @Noxsios TODO: replace w/ sad zarf -->
<img class="zarf-logo" width={60} height={60} src={bigZarf} alt="zarf-logo" />
<Typography variant="h6">Package Not Found</Typography>
<Typography variant="body2">
Make sure the following package is in the current working directory:
</Typography>
<Typography variant="code"><code>{pkgName}</code></Typography>
<div class="center">
<img class="zarf-logo" width={60} height={60} src={bigZarf} alt="zarf-logo" />
<Typography variant="h6">Package Not Found</Typography>
</div>

<Typography variant="body2">The current operation encountered the following error:</Typography>
<Typography variant="code"><code>{message}</code></Typography>
<div class="actions">
<Button href="/" color="secondary" variant="flat"
>Return Home</Button
>
<Button href="/" color="secondary" variant="flat">Return Home</Button>
</div>
</div>
</Dialog>
Expand All @@ -30,11 +29,19 @@
display: flex;
gap: 1rem;
flex-direction: column;
max-width: 444px;
width: 100%;
}
.center {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
gap: 1rem;
}
.actions {
display: flex;
width: 100%;
justify-content: flex-end;
}
</style>
</style>
4 changes: 3 additions & 1 deletion src/ui/lib/components/spinner.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import { onMount } from 'svelte';
import { Typography } from '@ui';

export let title = '';

export let msg = 'Loading...';

// Need this to force-enable first onload animation to avoid ugly flash on very fast REST calls
Expand All @@ -22,7 +24,7 @@
<div class="spinner-wrapper" in:fade={{ duration: 1000 }}>
<span class="spinner" />
</div>
<Typography variant="h5">Checking for Cluster</Typography>
<Typography variant="h5">{title}</Typography>
<Typography variant="body2" element="span" class="label">{msg}</Typography>
{/if}
</Hero>
Expand Down
5 changes: 2 additions & 3 deletions src/ui/lib/components/yaml-code.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@
import 'prismjs/themes/prism-okaidia.css';
import { stringify } from 'yaml';

import type { ZarfComponent } from '$lib/api-types';
import { onMount } from 'svelte';

export let component: ZarfComponent;
export let code: any;

const yaml = stringify(component);
const yaml = stringify(code);

onMount(() => {
Prism.highlightAll();
Expand Down
7 changes: 7 additions & 0 deletions src/ui/lib/typography.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ export const ZarfTypography: ThemeTypography = {
lineHeight: '166%',
letterSpacing: '0.4px'
},
code: {
fontSize: '14px',
fontWeight: '400',
lineHeight: '143%',
letterSpacing: '0.17px',
fontFamily: 'monospace, monospace'
},
overline: {
fontSize: '12px',
fontWeight: '400',
Expand Down
24 changes: 24 additions & 0 deletions src/ui/routes/+error.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!--
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
-->
<script lang="ts">
import { Dialog, Typography } from '@ui';
import { page } from '$app/stores';
</script>

<Dialog open clickAway={false}>
<div slot="content" class="dialog-content">
<Typography variant="code"><code>Error: {$page.status} {$page.error?.message}</code></Typography
>
</div>
</Dialog>

<style>
.dialog-content {
display: flex;
gap: 1rem;
flex-direction: column;
align-items: center;
}
</style>
33 changes: 29 additions & 4 deletions src/ui/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@
import { clusterStore } from '$lib/store';
import { Hero, Spinner } from '$lib/components';
import bigZarf from '@images/zarf-bubbles-right.png';
import { Packages } from '$lib/api';

const getInitPath = async () => {
const res = await Packages.findInit();
if (Array.isArray(res)) {
return res[0];
} else {
throw new Error('No init package found');
}
};
</script>

<svelte:head>
Expand All @@ -33,14 +43,29 @@
Click initialize cluster to install the Init Package and deploy a new cluster.
</Typography>
{/if}

<Button variant="raised" color="secondary" href="/initialize/configure" id="init-cluster">
Initialize Cluster
</Button>
{#await getInitPath()}
<Button
variant="raised"
color="secondary"
disabled
>
Initialize Cluster
</Button>
{:then path}
<Button
variant="raised"
color="secondary"
href={`/package/deploy?path=${path}`}
id="init-cluster"
>
Initialize Cluster
</Button>
{/await}
</Hero>
{/if}
{:else}
<Spinner
title="Checking for cluster"
msg="Checking if a Kubernetes cluster is available and initialized by Zarf. This may take a few seconds."
/>
{/if}
Expand Down
Loading