feat(frontend): Add onboarding tour to home page
This commit is contained in:
42
frontend/package-lock.json
generated
42
frontend/package-lock.json
generated
@@ -64,6 +64,7 @@
|
||||
"postcss-load-config": "^4.0.1",
|
||||
"prettier": "^2.8.3",
|
||||
"prettier-plugin-svelte": "^2.9.0",
|
||||
"shepherd.js": "^10.0.1",
|
||||
"simple-svelte-autocomplete": "^2.5.1",
|
||||
"stylelint-config-recommended": "^9.0.0",
|
||||
"svelte": "^3.55.1",
|
||||
@@ -6653,6 +6654,24 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shepherd.js": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shepherd.js/-/shepherd.js-10.0.1.tgz",
|
||||
"integrity": "sha512-R32v4b4b0N1gK/vxvRtdhty+SBZlBPcPTSYCwcaAQvFd0n6Xki7cRH6Sx0oD9WB/HCkqCNM1msyIyylXmq635w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"deepmerge": "^4.2.2",
|
||||
"smoothscroll-polyfill": "^0.4.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "12.* || 14.* || >= 16"
|
||||
},
|
||||
"funding": {
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/rwwagner90"
|
||||
}
|
||||
},
|
||||
"node_modules/signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
@@ -6739,6 +6758,12 @@
|
||||
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/smoothscroll-polyfill": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz",
|
||||
"integrity": "sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sorcery": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz",
|
||||
@@ -12989,6 +13014,17 @@
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true
|
||||
},
|
||||
"shepherd.js": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shepherd.js/-/shepherd.js-10.0.1.tgz",
|
||||
"integrity": "sha512-R32v4b4b0N1gK/vxvRtdhty+SBZlBPcPTSYCwcaAQvFd0n6Xki7cRH6Sx0oD9WB/HCkqCNM1msyIyylXmq635w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@popperjs/core": "^2.11.5",
|
||||
"deepmerge": "^4.2.2",
|
||||
"smoothscroll-polyfill": "^0.4.4"
|
||||
}
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.7",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
|
||||
@@ -13049,6 +13085,12 @@
|
||||
"is-fullwidth-code-point": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"smoothscroll-polyfill": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz",
|
||||
"integrity": "sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==",
|
||||
"dev": true
|
||||
},
|
||||
"sorcery": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/sorcery/-/sorcery-0.11.0.tgz",
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"postcss-load-config": "^4.0.1",
|
||||
"prettier": "^2.8.3",
|
||||
"prettier-plugin-svelte": "^2.9.0",
|
||||
"shepherd.js": "^10.0.1",
|
||||
"simple-svelte-autocomplete": "^2.5.1",
|
||||
"stylelint-config-recommended": "^9.0.0",
|
||||
"svelte": "^3.55.1",
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
<span class="{$$props.class} z-auto">
|
||||
<span class="{$$props.class ?? ''} z-auto">
|
||||
<label
|
||||
for={id}
|
||||
class="inline-flex items-center mt-2 duration-200 {disabled
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}[kind]
|
||||
</script>
|
||||
|
||||
<div
|
||||
<li
|
||||
class="hover:bg-gray-50 w-full inline-flex items-center p-4 gap-4 first-of-type:!border-t-0
|
||||
first-of-type:rounded-t-md last-of-type:rounded-b-md {color}"
|
||||
>
|
||||
@@ -61,4 +61,4 @@ first-of-type:rounded-t-md last-of-type:rounded-b-md {color}"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</li>
|
||||
|
||||
@@ -242,69 +242,74 @@
|
||||
/>
|
||||
|
||||
<CenteredPage>
|
||||
<div class="flex flex-wrap gap-2 items-center justify-between w-full">
|
||||
<div class="flex justify-start">
|
||||
<ToggleButtonGroup bind:selected={itemKind}>
|
||||
<ToggleButton light position="left" value="all" size="sm">All</ToggleButton>
|
||||
<ToggleButton light position="center" value="script" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<Code2 size={16} />
|
||||
Scripts
|
||||
</div>
|
||||
</ToggleButton>
|
||||
<ToggleButton light position="center" value="flow" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<Icon data={faBarsStaggered} scale={0.8} class="mr-1" />
|
||||
Flows
|
||||
</div>
|
||||
</ToggleButton>
|
||||
<ToggleButton light position="right" value="app" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<LayoutDashboard size={16} />
|
||||
Apps
|
||||
</div>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<div id="welcome-tutorial-1">
|
||||
<div class="flex flex-wrap gap-2 items-center justify-between w-full">
|
||||
<div class="flex justify-start">
|
||||
<ToggleButtonGroup bind:selected={itemKind}>
|
||||
<ToggleButton light position="left" value="all" size="sm">All</ToggleButton>
|
||||
<ToggleButton light position="center" value="script" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<Code2 size={16} />
|
||||
Scripts
|
||||
</div>
|
||||
</ToggleButton>
|
||||
<ToggleButton light position="center" value="flow" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<Icon data={faBarsStaggered} scale={0.8} class="mr-1" />
|
||||
Flows
|
||||
</div>
|
||||
</ToggleButton>
|
||||
<ToggleButton light position="right" value="app" size="sm">
|
||||
<div class="flex gap-1 items-center">
|
||||
<LayoutDashboard size={16} />
|
||||
Apps
|
||||
</div>
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</div>
|
||||
<div class="relative text-gray-600 grow min-w-[100px]">
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
placeholder="Search Scripts, Flows & Apps"
|
||||
bind:value={filter}
|
||||
class="bg-white !h-10 !px-4 !pr-10 !rounded-lg text-sm focus:outline-none"
|
||||
/>
|
||||
<button type="submit" class="absolute right-0 top-0 mt-3 mr-4">
|
||||
<svg
|
||||
class="h-4 w-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 56.966 56.966"
|
||||
style="enable-background:new 0 0 56.966 56.966;"
|
||||
xml:space="preserve"
|
||||
width="512px"
|
||||
height="512px"
|
||||
>
|
||||
<path
|
||||
d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23 s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92 c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17 s-17-7.626-17-17S14.61,6,23.984,6z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="relative text-gray-600 grow min-w-[100px]">
|
||||
<!-- svelte-ignore a11y-autofocus -->
|
||||
<input
|
||||
autofocus
|
||||
placeholder="Search Scripts, Flows & Apps"
|
||||
bind:value={filter}
|
||||
class="bg-white !h-10 !px-4 !pr-10 !rounded-lg text-sm focus:outline-none"
|
||||
/>
|
||||
<button type="submit" class="absolute right-0 top-0 mt-3 mr-4">
|
||||
<svg
|
||||
class="h-4 w-4 fill-current"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
version="1.1"
|
||||
id="Capa_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 56.966 56.966"
|
||||
style="enable-background:new 0 0 56.966 56.966;"
|
||||
xml:space="preserve"
|
||||
width="512px"
|
||||
height="512px"
|
||||
>
|
||||
<path
|
||||
d="M55.146,51.887L41.588,37.786c3.486-4.144,5.396-9.358,5.396-14.786c0-12.682-10.318-23-23-23s-23,10.318-23,23 s10.318,23,23,23c4.761,0,9.298-1.436,13.177-4.162l13.661,14.208c0.571,0.593,1.339,0.92,2.162,0.92 c0.779,0,1.518-0.297,2.079-0.837C56.255,54.982,56.293,53.08,55.146,51.887z M23.984,6c9.374,0,17,7.626,17,17s-7.626,17-17,17 s-17-7.626-17-17S14.61,6,23.984,6z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="relative flex justify-between items-start">
|
||||
<ListFilters bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
{#if !loading}
|
||||
<Toggle
|
||||
size="xs"
|
||||
bind:checked={archived}
|
||||
options={{ right: 'Show archived' }}
|
||||
class="pt-2"
|
||||
textClass="whitespace-nowrap"
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative">
|
||||
<ListFilters bind:selectedFilter={ownerFilter} filters={owners} />
|
||||
{#if !loading}
|
||||
<div class="absolute -bottom-2 right-0 bg-white/90">
|
||||
<Toggle size="xs" bind:checked={archived} options={{ right: 'Show archived' }} /></div
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
<div>
|
||||
{#if filteredItems == undefined}
|
||||
<div class="mt-4" />
|
||||
@@ -315,7 +320,7 @@
|
||||
{:else if filteredItems.length === 0}
|
||||
<NoItemFound />
|
||||
{:else}
|
||||
<div class="border rounded-md divide-y divide-gray-200">
|
||||
<ul class="border rounded-md divide-y divide-gray-200">
|
||||
<!-- <VirtualList {items} let:item bind:start bind:end> -->
|
||||
{#each (items ?? []).slice(0, nbDisplayed) as item, i (item.type + '/' + item.path + (item.summary ?? ''))}
|
||||
{#if item.type == 'script'}
|
||||
@@ -348,7 +353,7 @@
|
||||
{/if}
|
||||
{/each}
|
||||
<!-- </VirtualList> -->
|
||||
</div>
|
||||
</ul>
|
||||
{#if items && items?.length > 30}
|
||||
<span class="text-xs"
|
||||
>{nbDisplayed} items out of {items.length}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
export let icon: IconDefinition
|
||||
export let isCollapsed: boolean
|
||||
export let disabled: boolean = false
|
||||
export let id: string = ''
|
||||
|
||||
let isSelected = false
|
||||
|
||||
@@ -33,6 +34,7 @@
|
||||
$$props.class
|
||||
)}
|
||||
target={href.includes('http') ? '_blank' : null}
|
||||
{id}
|
||||
>
|
||||
<Icon
|
||||
data={icon}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
const mainMenuLinks = [
|
||||
{ label: 'Home', href: '/', icon: faHomeAlt },
|
||||
{ label: 'Runs', href: '/runs', icon: faPlay },
|
||||
{ label: 'Runs', href: '/runs', icon: faPlay, id: 'welcome-tutorial-4' },
|
||||
{ label: 'Variables', href: '/variables', icon: faDollarSign, disabled: $userStore?.operator },
|
||||
{ label: 'Resources', href: '/resources', icon: faCubes, disabled: $userStore?.operator }
|
||||
]
|
||||
|
||||
134
frontend/src/lib/components/tutorial/Tour.svelte
Normal file
134
frontend/src/lib/components/tutorial/Tour.svelte
Normal file
@@ -0,0 +1,134 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte'
|
||||
import Shepherd from 'shepherd.js'
|
||||
import { steps, type TutorialName } from './'
|
||||
|
||||
export let tutorial: TutorialName
|
||||
/**
|
||||
* If the index of a step is added to a tour, the custom footer will not be added
|
||||
* (ie. the steps won't be shown and the buttons won't be positioned)
|
||||
*/
|
||||
const noCustomFooter: Partial<Record<TutorialName, number[]>> = {
|
||||
welcome: [0]
|
||||
}
|
||||
let tour: Shepherd.Tour | undefined
|
||||
|
||||
onMount(() => {
|
||||
tour?.cancel()
|
||||
tour = new Shepherd.Tour({
|
||||
tourName: tutorial,
|
||||
useModalOverlay: true,
|
||||
defaultStepOptions: {
|
||||
classes: 'max-w-[460px] shadow-xl bg-white border rounded px-6 py-4 z-[1100]',
|
||||
scrollTo: true
|
||||
}
|
||||
})
|
||||
tour.addSteps(steps[tutorial](tour))
|
||||
tour.steps.forEach((step, i) => {
|
||||
if (noCustomFooter[tutorial]?.includes(i)) {
|
||||
return
|
||||
}
|
||||
step.on('show', () => {
|
||||
const currentStep = tour?.getCurrentStep()
|
||||
const currentStepElement = currentStep?.getElement()
|
||||
const header = currentStepElement?.querySelector('.shepherd-header')
|
||||
if (currentStep && currentStepElement && header) {
|
||||
const progress = document.createElement('span')
|
||||
progress.className = 'shepherd-progress text-sm text-gray-500 pr-2'
|
||||
progress.innerText = `${(tour?.steps.indexOf(currentStep) ?? 0) + 1}/${
|
||||
tour?.steps.length
|
||||
}`
|
||||
header.prepend(progress)
|
||||
}
|
||||
})
|
||||
})
|
||||
tour.start()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style global>
|
||||
.shepherd-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.shepherd-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.shepherd-button {
|
||||
padding: 4px 12px;
|
||||
border-radius: 4px;
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
|
||||
/* Simple primary button */
|
||||
.shepherd-button:not(.shepherd-button-secondary.special) {
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
.shepherd-button:not(.shepherd-button-secondary.special):hover,
|
||||
.shepherd-button:not(.shepherd-button-secondary.special):focus {
|
||||
background-color: #eff6ff;
|
||||
}
|
||||
|
||||
/* Simple secondary button */
|
||||
.shepherd-button.shepherd-button-secondary:not(.special) {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
.shepherd-button.shepherd-button-secondary:not(.special):hover,
|
||||
.shepherd-button.shepherd-button-secondary:not(.special):focus {
|
||||
background-color: #f3f4f6;
|
||||
}
|
||||
|
||||
/* Special primary button */
|
||||
.shepherd-button.special:not(.shepherd-button-secondary) {
|
||||
background-color: #3b82f6;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.shepherd-button.special:not(.shepherd-button-secondary):hover,
|
||||
.shepherd-button.special:not(.shepherd-button-secondary):focus {
|
||||
background-color: #2563eb;
|
||||
}
|
||||
|
||||
/* Special secondary button */
|
||||
.shepherd-button.special.shepherd-button-secondary {
|
||||
background-color: #eff6ff;
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
.shepherd-button.special.shepherd-button-secondary:hover,
|
||||
.shepherd-button.special.shepherd-button-secondary:focus {
|
||||
background-color: #dbeafe;
|
||||
}
|
||||
|
||||
.shepherd-cancel-icon {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 16px;
|
||||
background-color: #fff;
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
|
||||
.shepherd-cancel-icon:hover,
|
||||
.shepherd-cancel-icon:focus {
|
||||
background-color: #ededed;
|
||||
}
|
||||
|
||||
.shepherd-highlighted-element {
|
||||
box-shadow: 0 0 0 6px #93c4fdbb;
|
||||
background-color: #93c4fd3a;
|
||||
position: relative;
|
||||
z-index: 1090;
|
||||
}
|
||||
</style>
|
||||
12
frontend/src/lib/components/tutorial/index.ts
Normal file
12
frontend/src/lib/components/tutorial/index.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import welcome from './welcome-steps'
|
||||
import type Shepherd from 'shepherd.js'
|
||||
|
||||
export { default as Tour } from './Tour.svelte'
|
||||
|
||||
export type TutorialName = 'welcome' | 'script' | 'flow' | 'app'
|
||||
export const steps: Record<TutorialName, (tour: Shepherd.Tour) => object[] | Shepherd.Step[]> = {
|
||||
welcome,
|
||||
script: (tour: Shepherd.Tour) => [],
|
||||
flow: (tour: Shepherd.Tour) => [],
|
||||
app: (tour: Shepherd.Tour) => []
|
||||
}
|
||||
114
frontend/src/lib/components/tutorial/welcome-steps.ts
Normal file
114
frontend/src/lib/components/tutorial/welcome-steps.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
import type Shepherd from 'shepherd.js'
|
||||
|
||||
export default (tour: Shepherd.Tour) => {
|
||||
const steps: object[] | Shepherd.Step[] = [
|
||||
{
|
||||
id: 'welcome',
|
||||
text: `<div class="text-xl font-bold mb-6">Welcome to Windmill Cloud App!</div>
|
||||
<p class="mb-6">Thank your for your interest in Windmill. Let us guide you through the home screen in strictly less than a minute.</p>`,
|
||||
buttons: [
|
||||
{
|
||||
text: 'See by myself',
|
||||
action: tour.cancel,
|
||||
secondary: true,
|
||||
classes: 'special'
|
||||
},
|
||||
{
|
||||
text: 'Give me an overview',
|
||||
action: tour.next,
|
||||
classes: 'special'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'workspace',
|
||||
text: `<div class="text-xl font-bold mb-2">Workspace</div>
|
||||
<p>You can see all the scripts, flows and apps here.</p>
|
||||
<p class="mb-2">Use the search and filters to find just what you are looking for.</p>`,
|
||||
cancelIcon: {
|
||||
enabled: true
|
||||
},
|
||||
attachTo: { element: '#welcome-tutorial-1', on: 'bottom-start' },
|
||||
highlightClass: 'shepherd-highlighted-element',
|
||||
scrollTo: false,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Back',
|
||||
action: tour.back,
|
||||
secondary: true
|
||||
},
|
||||
{
|
||||
text: 'Next',
|
||||
action: tour.next
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'create',
|
||||
text: `<div class="text-xl font-bold mb-2">Create</div>
|
||||
<p class="mb-2">Build your own tools in minutes.</p>`,
|
||||
cancelIcon: {
|
||||
enabled: true
|
||||
},
|
||||
attachTo: { element: '#welcome-tutorial-2', on: 'bottom-end' },
|
||||
highlightClass: 'shepherd-highlighted-element',
|
||||
scrollTo: false,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Back',
|
||||
action: tour.back,
|
||||
secondary: true
|
||||
},
|
||||
{
|
||||
text: 'Next',
|
||||
action: tour.next
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'inspiration',
|
||||
text: `<div class="text-xl font-bold mb-2">Take inspiration</div>
|
||||
<p class="mb-2">Explore templates built by the community and import them directly from <a href="https://hub.windmill.dev" target="_blank">Windmill Hub</a>.</p>`,
|
||||
cancelIcon: {
|
||||
enabled: true
|
||||
},
|
||||
attachTo: { element: '#welcome-tutorial-3', on: 'bottom-start' },
|
||||
highlightClass: 'shepherd-highlighted-element',
|
||||
scrollTo: false,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Back',
|
||||
action: tour.back,
|
||||
secondary: true
|
||||
},
|
||||
{
|
||||
text: 'Next',
|
||||
action: tour.next
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'monitor',
|
||||
text: `<div class="text-xl font-bold mb-2">Monitor</div>
|
||||
<p class="mb-2">Keep an eye an all past and scheduled executions of scripts and flows.</p>`,
|
||||
cancelIcon: {
|
||||
enabled: true
|
||||
},
|
||||
attachTo: { element: '#welcome-tutorial-4-wrapper #welcome-tutorial-4', on: 'right-start' },
|
||||
highlightClass: 'shepherd-highlighted-element',
|
||||
scrollTo: false,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Back',
|
||||
action: tour.back,
|
||||
secondary: true
|
||||
},
|
||||
{
|
||||
text: 'Finish',
|
||||
action: tour.complete
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
return steps
|
||||
}
|
||||
@@ -202,7 +202,10 @@
|
||||
isCollapsed ? 'md:w-12' : 'md:w-40'
|
||||
)}
|
||||
>
|
||||
<div class="flex-1 flex flex-col min-h-0 h-screen shadow-lg bg-[#2e3440]">
|
||||
<div
|
||||
id="welcome-tutorial-4-wrapper"
|
||||
class="flex-1 flex flex-col min-h-0 h-screen shadow-lg bg-[#2e3440]"
|
||||
>
|
||||
<button
|
||||
on:click={() => {
|
||||
goto('/')
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import PickHubFlow from '$lib/components/flows/pickers/PickHubFlow.svelte'
|
||||
import FlowViewer from '$lib/components/FlowViewer.svelte'
|
||||
import HighlightCode from '$lib/components/HighlightCode.svelte'
|
||||
import { Building, ExternalLink, Globe2 } from 'lucide-svelte'
|
||||
import { Building, Globe2 } from 'lucide-svelte'
|
||||
|
||||
import ItemsList from '$lib/components/home/ItemsList.svelte'
|
||||
import CreateActionsApp from '$lib/components/flows/CreateActionsApp.svelte'
|
||||
@@ -20,6 +20,7 @@
|
||||
import AppPreview from '$lib/components/apps/editor/AppPreview.svelte'
|
||||
import { writable } from 'svelte/store'
|
||||
import type { EditorBreakpoint } from '$lib/components/apps/types'
|
||||
import { Tour } from '../../../lib/components/tutorial'
|
||||
|
||||
type Tab = 'hubscripts' | 'hubflows' | 'hubapps' | 'workspace'
|
||||
|
||||
@@ -62,6 +63,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Tour tutorial="welcome" />
|
||||
<Drawer bind:this={codeViewer} size="900px">
|
||||
<DrawerContent title={codeViewerObj?.summary ?? ''} on:close={codeViewer.closeDrawer}>
|
||||
<svelte:fragment slot="actions">
|
||||
@@ -181,7 +183,7 @@
|
||||
</Alert>
|
||||
{/if}
|
||||
<PageHeader title="Home">
|
||||
<div class="flex flex-row gap-4 flex-wrap justify-end items-center">
|
||||
<div id="welcome-tutorial-2" class="flex flex-row gap-4 flex-wrap justify-end items-center">
|
||||
{#if !$userStore?.operator}
|
||||
<span class="text-sm text-gray-500">Create a new:</span>
|
||||
<CreateActionsScript />
|
||||
@@ -192,7 +194,7 @@
|
||||
</PageHeader>
|
||||
|
||||
{#if !$userStore?.operator}
|
||||
<div class="w-full overflow-auto scrollbar-hidden">
|
||||
<div id="welcome-tutorial-3" class="w-full">
|
||||
<Tabs bind:selected={tab}>
|
||||
<Tab size="md" value="workspace">
|
||||
<div class="flex gap-2 items-center my-1">
|
||||
|
||||
Reference in New Issue
Block a user