Skip to content

Commit 9ee182e

Browse files
committed
Edge case if no Category and no Tutorial available for my role
1 parent 31b53c8 commit 9ee182e

File tree

2 files changed

+109
-99
lines changed

2 files changed

+109
-99
lines changed

frontend/src/lib/tutorials/config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface TabConfig {
2323
active?: boolean // Whether this tab category is active and should be displayed (default: true)
2424
}
2525

26-
export type TabId = 'quickstart' | 'app_editor'
26+
export type TabId = 'quickstart' | 'app_editor'
2727

2828
/**
2929
* Get tutorial index from config by tutorial ID.
@@ -45,7 +45,7 @@ export function getTutorialIndex(id: string): number {
4545
export const TUTORIALS_CONFIG: Record<TabId, TabConfig> = {
4646
quickstart: {
4747
label: 'Quickstart',
48-
roles: ['developer', 'operator', 'admin'],
48+
roles: ['developer', 'admin'],
4949
progressBar: true,
5050
active: true,
5151
tutorials: [
@@ -60,7 +60,7 @@ export const TUTORIALS_CONFIG: Record<TabId, TabConfig> = {
6060
index: 1,
6161
active: true,
6262
comingSoon: false,
63-
roles: ['operator', 'developer', 'admin'],
63+
roles: ['developer', 'admin'],
6464
order: 1
6565
},
6666
{
@@ -110,7 +110,7 @@ export const TUTORIALS_CONFIG: Record<TabId, TabConfig> = {
110110
index: 4,
111111
active: true,
112112
comingSoon: false,
113-
roles: ['admin'],
113+
roles: ['developer','admin'],
114114
order: 4
115115
},
116116
{

frontend/src/routes/(root)/(logged)/tutorials/+page.svelte

Lines changed: 105 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -199,109 +199,119 @@
199199
tooltip="Learn how to use Windmill with our interactive tutorials"
200200
documentationLink="https://www.windmill.dev/docs/intro"
201201
>
202-
<div class="flex gap-2">
203-
<Button
204-
size="xs"
205-
variant="default"
206-
startIcon={{ icon: CheckCheck }}
207-
onclick={async () => {
208-
await skipAllTodos()
209-
await syncTutorialsTodos()
210-
}}
211-
>
212-
Mark all as completed
213-
</Button>
214-
<Button
215-
size="xs"
216-
variant="default"
217-
startIcon={{ icon: RefreshCw }}
218-
onclick={async () => {
219-
await resetAllTodos()
220-
await syncTutorialsTodos()
221-
}}
222-
>
223-
Reset all
224-
</Button>
225-
</div>
202+
{#if activeTabs.length > 0}
203+
<div class="flex gap-2">
204+
<Button
205+
size="xs"
206+
variant="default"
207+
startIcon={{ icon: CheckCheck }}
208+
onclick={async () => {
209+
await skipAllTodos()
210+
await syncTutorialsTodos()
211+
}}
212+
>
213+
Mark all as completed
214+
</Button>
215+
<Button
216+
size="xs"
217+
variant="default"
218+
startIcon={{ icon: RefreshCw }}
219+
onclick={async () => {
220+
await resetAllTodos()
221+
await syncTutorialsTodos()
222+
}}
223+
>
224+
Reset all
225+
</Button>
226+
</div>
227+
{/if}
226228
</PageHeader>
227229

228-
<div class="flex justify-between pt-4">
229-
<Tabs class="w-full" bind:selected={tab}>
230-
{#each activeTabs as [tabId, config]}
231-
{@const badge = getTabBadge(tabId as TabId)}
232-
{#if badge.type === 'progress'}
233-
<Tab value={tabId} label={config.label}>
234-
{#snippet extra()}
235-
<span class="text-xs text-secondary ml-1.5 flex-shrink-0">{badge.text}</span>
236-
{/snippet}
237-
</Tab>
238-
{:else if badge.type === 'check'}
239-
<Tab value={tabId} label={config.label}>
240-
{#snippet extra()}
241-
<CheckCircle2 size={14} class="ml-1.5 flex-shrink-0" />
242-
{/snippet}
243-
</Tab>
244-
{:else if badge.type === 'dot'}
245-
<Tab value={tabId} label={config.label}>
246-
{#snippet extra()}
247-
<Circle size={14} class="ml-1.5 flex-shrink-0" />
248-
{/snippet}
249-
</Tab>
250-
{:else}
251-
<Tab value={tabId} label={config.label} />
252-
{/if}
253-
{/each}
254-
</Tabs>
255-
</div>
230+
{#if activeTabs.length > 0}
231+
<div class="flex justify-between pt-4">
232+
<Tabs class="w-full" bind:selected={tab}>
233+
{#each activeTabs as [tabId, config]}
234+
{@const badge = getTabBadge(tabId as TabId)}
235+
{#if badge.type === 'progress'}
236+
<Tab value={tabId} label={config.label}>
237+
{#snippet extra()}
238+
<span class="text-xs text-secondary ml-1.5 flex-shrink-0">{badge.text}</span>
239+
{/snippet}
240+
</Tab>
241+
{:else if badge.type === 'check'}
242+
<Tab value={tabId} label={config.label}>
243+
{#snippet extra()}
244+
<CheckCircle2 size={14} class="ml-1.5 flex-shrink-0" />
245+
{/snippet}
246+
</Tab>
247+
{:else if badge.type === 'dot'}
248+
<Tab value={tabId} label={config.label}>
249+
{#snippet extra()}
250+
<Circle size={14} class="ml-1.5 flex-shrink-0" />
251+
{/snippet}
252+
</Tab>
253+
{:else}
254+
<Tab value={tabId} label={config.label} />
255+
{/if}
256+
{/each}
257+
</Tabs>
258+
</div>
256259

257-
{#if currentTabConfig && currentTabConfig.tutorials.length > 0}
258-
<div class="pt-8">
259-
<div class="flex items-start gap-4 mb-6">
260-
{#if currentTabConfig.progressBar !== false}
261-
<TutorialProgressBar
262-
completed={completedTutorials}
263-
total={totalTutorials}
264-
label="tutorials"
265-
/>
266-
{/if}
267-
<div class="flex gap-2 flex-shrink-0 pt-1">
268-
<Button
269-
size="xs"
270-
variant="default"
271-
startIcon={{ icon: CheckCheck }}
272-
onclick={skipCurrentTabTutorials}
273-
>
274-
Mark as completed
275-
</Button>
276-
<Button
277-
size="xs"
278-
variant="default"
279-
startIcon={{ icon: RefreshCw }}
280-
onclick={resetCurrentTabTutorials}
281-
>
282-
Reset
283-
</Button>
260+
{#if tutorials.length > 0}
261+
<div class="pt-8">
262+
<div class="flex items-start gap-4 mb-6">
263+
{#if currentTabConfig.progressBar !== false}
264+
<TutorialProgressBar
265+
completed={completedTutorials}
266+
total={totalTutorials}
267+
label="tutorials"
268+
/>
269+
{/if}
270+
<div class="flex gap-2 flex-shrink-0 pt-1">
271+
<Button
272+
size="xs"
273+
variant="default"
274+
startIcon={{ icon: CheckCheck }}
275+
onclick={skipCurrentTabTutorials}
276+
>
277+
Mark as completed
278+
</Button>
279+
<Button
280+
size="xs"
281+
variant="default"
282+
startIcon={{ icon: RefreshCw }}
283+
onclick={resetCurrentTabTutorials}
284+
>
285+
Reset
286+
</Button>
287+
</div>
284288
</div>
285-
</div>
286289

287-
<div class="border rounded-md bg-surface-tertiary">
288-
{#each tutorials as tutorial}
289-
<TutorialButton
290-
icon={tutorial.icon}
291-
title={tutorial.title}
292-
description={tutorial.description}
293-
onclick={tutorial.onClick}
294-
isCompleted={isTutorialCompleted(tutorial.id)}
295-
disabled={tutorial.active === false}
296-
comingSoon={tutorial.comingSoon}
297-
/>
298-
{/each}
290+
<div class="border rounded-md bg-surface-tertiary">
291+
{#each tutorials as tutorial}
292+
<TutorialButton
293+
icon={tutorial.icon}
294+
title={tutorial.title}
295+
description={tutorial.description}
296+
onclick={tutorial.onClick}
297+
isCompleted={isTutorialCompleted(tutorial.id)}
298+
disabled={tutorial.active === false}
299+
comingSoon={tutorial.comingSoon}
300+
/>
301+
{/each}
302+
</div>
299303
</div>
300-
</div>
301-
{:else if currentTabConfig}
304+
{:else if currentTabConfig}
305+
<div class="pt-8">
306+
<div class="text-center text-secondary text-sm py-8">
307+
No tutorials available for this section yet.
308+
</div>
309+
</div>
310+
{/if}
311+
{:else}
302312
<div class="pt-8">
303313
<div class="text-center text-secondary text-sm py-8">
304-
No tutorials available for this section yet.
314+
No tutorials available for now. Coming soon.
305315
</div>
306316
</div>
307317
{/if}

0 commit comments

Comments
 (0)