Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 3 additions & 6 deletions src/frontend/src/lib/components/launchpad/Launchpad.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import { fade } from 'svelte/transition';
import LaunchpadFirstSatellite from '$lib/components/launchpad/LaunchpadFirstSatellite.svelte';
import LaunchpadSegments from '$lib/components/launchpad/LaunchpadSegments.svelte';
import ContainerCentered from '$lib/components/ui/ContainerCentered.svelte';
import Message from '$lib/components/ui/Message.svelte';
import Spinner from '$lib/components/ui/Spinner.svelte';
import { satellitesStore } from '$lib/derived/satellites.derived';
Expand Down Expand Up @@ -35,11 +34,9 @@
</Message>
</div>
{:else}
<div in:fade>
<ContainerCentered>
<LaunchpadFirstSatellite />
</ContainerCentered>
</div>
<section in:fade>
<LaunchpadFirstSatellite />
</section>
{/if}
{:else if ($satellitesStore?.length ?? 0) >= 1}
<section in:fade>
Expand Down
75 changes: 75 additions & 0 deletions src/frontend/src/lib/components/launchpad/LaunchpadButton.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script lang="ts">
import { isNullish, nonNullish } from '@dfinity/utils';
import type { Snippet } from 'svelte';
import type { TestId } from '$lib/types/test-id';
import { testId } from '$lib/utils/test.utils';

interface Props {
summary?: Snippet;
children: Snippet;
disabled?: boolean;
row?: boolean;
testId?: TestId;
onclick: () => Promise<void>;
}

let { children, summary, disabled, testId: testIdProp, row = false, onclick }: Props = $props();
</script>

<button class="article" class:row {...testId(testIdProp)} {disabled} {onclick}>
{#if nonNullish(summary)}
<div class="summary">
{@render summary()}
</div>
{/if}

<div class="content" class:only={isNullish(summary)}>
{@render children()}
</div>
</button>

<style lang="scss">
button {
height: 100%;
min-height: 231px;
margin: 0;
}

.summary {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--padding-4x) var(--padding-4x) var(--padding);
}

.content {
padding: var(--padding-2x) var(--padding-4x) var(--padding);
min-height: 150px;
}

.content,
.summary {
width: 100%;

:global(*::first-letter) {
text-transform: uppercase;
}
}

.only {
height: 100%;
}

.row {
grid-column: 1 / 13;
min-height: 58px;

.content {
display: flex;
align-items: center;

padding: var(--padding-2x) var(--padding-4x);
min-height: auto;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<script lang="ts">
import IconRocket from '$lib/components/icons/IconRocket.svelte';
import LaunchpadButton from '$lib/components/launchpad/LaunchpadButton.svelte';
import LaunchpadHeader from '$lib/components/launchpad/LaunchpadHeader.svelte';
import { testIds } from '$lib/constants/test-ids.constants';
import { authIdentity } from '$lib/derived/auth.derived';
import { missionControlId } from '$lib/derived/console/account.mission-control.derived';
import { initSatelliteWizard } from '$lib/services/factory/factory.create.services';
import { i18n } from '$lib/stores/app/i18n.store';
import { testId } from '$lib/utils/test.utils';

const createSatellite = async () => {
await initSatelliteWizard({
Expand All @@ -15,51 +16,36 @@
};
</script>

<button class="primary" onclick={createSatellite} {...testId(testIds.launchpad.launch)}>
{$i18n.satellites.launch}
<IconRocket />
</button>
<LaunchpadHeader withoutGreetingsReturningLabel />

<style lang="scss">
button {
display: flex;
flex-direction: column;
gap: var(--padding-2x);

aspect-ratio: 1/1;
<LaunchpadButton onclick={createSatellite} testId={testIds.launchpad.launch}>
<div class="new">
<IconRocket size="48px" />

max-width: 160px;
max-height: 160px;
<p>{$i18n.satellites.launch_first}</p>
</div>
</LaunchpadButton>

padding: var(--padding);

border-radius: 50%;
<style lang="scss">
@use '../../styles/mixins/fonts';

box-shadow: 3px 3px var(--color-card-contrast);
.new {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;

animation: push ease-in 750ms 2 forwards;
gap: var(--padding-4x);

&:active {
box-shadow: none;
transform: translateX(3px) translateY(3px);
}
height: 100%;
}

/* -global- */
@keyframes -global-push {
0% {
box-shadow: 3px 3px var(--color-card-contrast);
transform: none;
}
p {
@include fonts.bold(true);

50% {
box-shadow: none;
transform: translateX(3px) translateY(3px);
}
max-width: 150px;
text-align: center;

100% {
box-shadow: 3px 3px var(--color-card-contrast);
transform: none;
}
margin: 0;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
import IconTerminal from '$lib/components/icons/IconTerminal.svelte';
import { i18n } from '$lib/stores/app/i18n.store';

interface Props {
withoutReturningLabel?: boolean;
}

let { withoutReturningLabel = false }: Props = $props();

const timedGreeting = (): string => {
const hour = getHours(new Date());

Expand All @@ -13,7 +19,10 @@
: $i18n.launchpad.good_evening;
};

const genericGreetings = [$i18n.launchpad.welcome_back, $i18n.launchpad.greetings];
let genericGreetings = $derived([
...(withoutReturningLabel ? [] : [$i18n.launchpad.welcome_back]),
$i18n.launchpad.greetings
]);

let greetings = $derived([...genericGreetings, timedGreeting()]);

Expand Down
38 changes: 38 additions & 0 deletions src/frontend/src/lib/components/launchpad/LaunchpadHeader.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<script lang="ts">
import type { Snippet } from 'svelte';
import LaunchpadGreetings from '$lib/components/launchpad/LaunchpadGreetings.svelte';
import { onIntersection } from '$lib/directives/intersection.directives';
import { onLayoutTitleIntersection } from '$lib/stores/app/layout-intersecting.store';

interface Props {
children?: Snippet;
filter?: string;
withoutGreetingsReturningLabel?: boolean;
}

let { filter = $bindable(''), children, withoutGreetingsReturningLabel }: Props = $props();

const customOnIntersection = (element: HTMLElement) =>
onIntersection(element, {
threshold: 0.8,
rootMargin: '-50px 0px'
});
</script>

<div class="header" onjunoIntersecting={onLayoutTitleIntersection} use:customOnIntersection>
<LaunchpadGreetings withoutReturningLabel={withoutGreetingsReturningLabel} />

{@render children?.()}
</div>

<style lang="scss">
@use '../../styles/mixins/media';

.header {
grid-column: 1 / 13;

@include media.min-width(medium) {
grid-column: 1 / 12;
}
}
</style>
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script lang="ts">
import LaunchpadAnalytics from '$lib/components/launchpad/LaunchpadAnalytics.svelte';
import LaunchpadHeader from '$lib/components/launchpad/LaunchpadHeader.svelte';
import LaunchpadMonitoring from '$lib/components/launchpad/LaunchpadMonitoring.svelte';
import LaunchpadSatellite from '$lib/components/launchpad/LaunchpadSatellite.svelte';
import LaunchpadToolbar from '$lib/components/launchpad/LaunchpadToolbar.svelte';
Expand All @@ -15,7 +16,9 @@
);
</script>

<LaunchpadToolbar bind:filter />
<LaunchpadHeader>
<LaunchpadToolbar bind:filter />
</LaunchpadHeader>

<LaunchpadMonitoring />

Expand Down
43 changes: 15 additions & 28 deletions src/frontend/src/lib/components/launchpad/LaunchpadToolbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@
import { debounce } from '@dfinity/utils';
import { run } from 'svelte/legacy';
import AttachActions from '$lib/components/attach-detach/AttachActions.svelte';
import LaunchpadGreetings from '$lib/components/launchpad/LaunchpadGreetings.svelte';
import LaunchpadLayout from '$lib/components/launchpad/LaunchpadLayout.svelte';
import LaunchpadNewActions from '$lib/components/launchpad/LaunchpadNewActions.svelte';
import Input from '$lib/components/ui/Input.svelte';
import { onIntersection } from '$lib/directives/intersection.directives';
import { i18n } from '$lib/stores/app/i18n.store';
import { onLayoutTitleIntersection } from '$lib/stores/app/layout-intersecting.store';

interface Props {
filter?: string;
Expand All @@ -24,36 +21,26 @@
// @ts-expect-error TODO: to be migrated to Svelte v5
(filterInput, debounceUpdateFilter());
});

const customOnIntersection = (element: HTMLElement) =>
onIntersection(element, {
threshold: 0.8,
rootMargin: '-50px 0px'
});
</script>

<div class="header" onjunoIntersecting={onLayoutTitleIntersection} use:customOnIntersection>
<LaunchpadGreetings />

<div role="toolbar">
<div class="filters">
<div class="input">
<Input
name="filter"
inputType="text"
placeholder={$i18n.satellites.search}
spellcheck={false}
bind:value={filterInput}
/>
</div>

<LaunchpadLayout />

<AttachActions />
<div role="toolbar">
<div class="filters">
<div class="input">
<Input
name="filter"
inputType="text"
placeholder={$i18n.satellites.search}
spellcheck={false}
bind:value={filterInput}
/>
</div>

<LaunchpadNewActions />
<LaunchpadLayout />

<AttachActions />
</div>

<LaunchpadNewActions />
</div>

<style lang="scss">
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
"satellites": {
"title": "Satellites",
"launch": "Launch a new Satellite",
"launch_first": "Launch your first Satellite",
"create": "Create Satellite",
"search": "Search",
"satellite": "Satellite",
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/lib/i18n/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,7 @@
"satellites": {
"title": "所有卫星",
"launch": "部署新卫星",
"launch_first": "启动您的第一个 Satellite",
"create": "创建卫星",
"search": "搜索",
"satellite": "卫星",
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/lib/types/i18n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ interface I18nLaunchpad {
interface I18nSatellites {
title: string;
launch: string;
launch_first: string;
create: string;
search: string;
satellite: string;
Expand Down