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

Add interactive tutorial guide to enhance user experience #858

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
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
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"apexcharts": "4",
"cypress": "13",
"d3": "7",
"driver.js": "1",
"pinia": "<2.2.3",
"pinia-plugin-persistedstate-2": "2",
"vee-validate": "4",
Expand Down
13 changes: 13 additions & 0 deletions webapp/src/assets/svg/QuestionMarkIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
class="w-6 h-6"
viewBox="0 0 512 512"
stroke="currentColor"
>
<path
d="M80 160c0-35.3 28.7-64 64-64h32c35.3 0 64 28.7 64 64v3.6c0 21.8-11.1 42.1-29.4 53.8l-42.2 27.1c-25.2 16.2-40.4 44.1-40.4 74v1.4c0 17.7 14.3 32 32 32s32-14.3 32-32v-1.4c0-8.2 4.2-15.8 11-20.2l42.2-27.1c36.6-23.6 58.8-64.1 58.8-107.7V160c0-70.7-57.3-128-128-128H144C73.3 32 16 89.3 16 160c0 17.7 14.3 32 32 32s32-14.3 32-32zm80 320a40 40 0 1 0 0-80 40 40 0 1 0 0 80z"
/>
</svg>
</template>
37 changes: 25 additions & 12 deletions webapp/src/components/dataset_input/DataDescription.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,30 @@
<template #title> Expected Data Format </template>

<!-- Sample dataset link and instructions -->
<div class="mb-5 text-left" v-show="task.displayInformation.sampleDatasetLink !== undefined">
<b>Don't have any data?</b> You can download an example dataset <a target="_blank" class='underline text-blue-400' :href="task.displayInformation.sampleDatasetLink">here</a>.
<br/><span v-html="task.displayInformation.sampleDatasetInstructions"/><br/>
<div
class="mb-5 text-left"
v-show="task.displayInformation.sampleDatasetLink !== undefined"
>
<b>Don't have any data?</b> You can download an example dataset
<a
id="data-link-download"
target="_blank"
class="underline text-blue-400"
:href="task.displayInformation.sampleDatasetLink"
>here</a
>. <br /><span
v-html="task.displayInformation.sampleDatasetInstructions"
/><br />
</div>

<div v-if="task.displayInformation.dataFormatInformation !== undefined">
<div v-html="task.displayInformation.dataFormatInformation" /><br>
<div v-html="task.displayInformation.dataFormatInformation" />
<br />
</div>

<!-- Tabular data example -->
<div v-if="task.displayInformation.dataExampleText !== undefined" >
<span v-html="task.displayInformation.dataExampleText" /><br>
<div v-if="task.displayInformation.dataExampleText !== undefined">
<span v-html="task.displayInformation.dataExampleText" /><br />
<div
v-if="['tabular', 'text'].includes(task.trainingInformation.dataType)"
class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4"
Expand All @@ -24,19 +36,20 @@
v-for="(column, idx) in task.displayInformation.dataExample"
:key="idx"
>
<span class="font-bold">{{ column.columnName }}:</span> {{ column.columnData }}
<span class="font-bold">{{ column.columnName }}:</span>
{{ column.columnData }}
</span>
</div>
</div>

<!-- Image data example -->
<div v-if="task.displayInformation.dataExampleImage !== undefined">
<br>
<br />
<img
class="mx-auto"
:src="task.displayInformation.dataExampleImage"
alt="Error! Image not found"
>
/>
</div>
</DropdownCard>
</div>
Expand All @@ -45,10 +58,10 @@
<script setup lang="ts">
import type { DataType, Task } from "@epfml/discojs";

import DropdownCard from '@/components/containers/DropdownCard.vue'
import DropdownCard from "@/components/containers/DropdownCard.vue";

interface Props {
task: Task<DataType>
task: Task<DataType>;
}
const _ = defineProps<Props>()
const _ = defineProps<Props>();
</script>
5 changes: 4 additions & 1 deletion webapp/src/components/dataset_input/FileSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
@dragleave="onDragLeave"
@drop="async (e: DragEvent) => await dragFiles(e)"
>
<p class="p-4 text-lg text-disco-blue dark:text-disco-light-blue flex-wrap justify-center">
<p
class="p-4 text-lg text-disco-blue dark:text-disco-light-blue flex-wrap justify-center"
>
<span>Drag and drop the {{ fileType }} or</span>
</p>
<label class="mb-6">
<span
id="select-data-bttn"
class="px-4 py-2 min-w-[8rem] text-lg uppercase text-white bg-disco-cyan rounded duration-200 hover:bg-white hover:dark:bg-slate-950 hover:outline hover:outline-disco-cyan hover:outline-2 hover:text-disco-cyan hover:cursor-pointer"
>
select {{ fileType }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<div class="flex justify-center">
<button
id="group-data-bttn"
class="w-40 py-2 uppercase text-lg rounded-l-lg border-2 border-disco-cyan focus:outline-none"
:class="
connectImagesByGroup
Expand All @@ -19,6 +20,7 @@
group
</button>
<button
id="csv-file-bttn"
class="w-40 py-2 uppercase text-lg rounded-r-lg border-2 border-disco-cyan focus:outline-none"
:class="
!connectImagesByGroup
Expand Down
84 changes: 84 additions & 0 deletions webapp/src/components/home/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,89 @@ import GetStarted from "@/components/home/GetStarted.vue";
import FeedbackIcon from "@/assets/svg/FeedbackIcon.vue";
import InfoIcon from "@/assets/svg/InfoIcon.vue";

import { nextTick, watch } from "vue";
import { useRouter } from "vue-router";

import { driver, type DriveStep } from "driver.js";
import "driver.js/dist/driver.css";

import { useTutorialStore } from "@/store";

const started = ref(false);
const router = useRouter();
const tutorialStore = useTutorialStore();

// Create a driver object
const driverObj = driver({
showProgress: false,
});

const steps: DriveStep[] = [
{
element: "#task-icon",
popover: {
title: "Collaborate on ML Tasks",
description:
"DISCOllaboratives let users collaboratively train ML models while keeping their datasets private.",
side: "left",
align: "start",
},
},
{
element: "#create-icon",
popover: {
title: "Create a Collaborative ML Task",
description:
"Create a DISCOllaborative by defining an ML model and task, allowing others to join and contribute while keeping their data private.",
side: "left",
align: "start",
},
},
{
element: "#evaluate-icon",
popover: {
title: "Evaluate ML Models",
description:
"Test locally stored models or download models from the DISCO server to evaluate their performance.",
side: "left",
align: "start",
},
},
{
element: ".theme-button",
popover: {
title: "Switch Theme",
description:
"Toggle between light and dark themes for a personalized visual experience.",
side: "left",
align: "start",
},
},
{
element: "#help-icon",
popover: {
title: "Show help",
description: "You can access a hint at any time if something is unclear.",
side: "left",
align: "start",
},
},
];

driverObj.setSteps(steps);
// driverObj.drive();

watch(
() => tutorialStore.showGuide,
async (_) => {
if (driverObj.isActive()) {
await driverObj.destroy();
}
if (router.currentRoute.value.path === "/") {
driverObj.setSteps(steps);
await nextTick();
driverObj.drive();
}
},
);
</script>
28 changes: 20 additions & 8 deletions webapp/src/components/sidebar/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@

<!-- Mini Sidebar content-->
<div class="flex flex-col items-center justify-center flex-1 space-y-4">
<SidebarButton to="/" text="Home"> <HomeIcon /> </SidebarButton>
<SidebarButton to="/" text="Home" id="home-icon">
<HomeIcon />
</SidebarButton>

<SidebarButton to="/list" text="DISCOllaboratives">
<TasksIcon class="w-6 h-6" />
<TasksIcon class="w-6 h-6" id="task-icon" />
</SidebarButton>

<SidebarButton to="/create" text="Create a new DISCOllaborative">
<CreateIcon />
<CreateIcon id="create-icon" />
</SidebarButton>

<SidebarButton to="/evaluate" text="Evaluate models">
<EvaluateIcon />
<EvaluateIcon id="evaluate-icon" />
</SidebarButton>

<SidebarButton to="/information" text="More on DISCO">
Expand All @@ -37,8 +39,12 @@
:text="currentTheme === 'light' ? 'Switch to Dark Mode' : 'Switch to Light Mode'"
@click="toggleDarkMode"
>
<MoonIcon v-if="currentTheme === 'light'"/>
<SunIcon v-else/>
<MoonIcon v-if="currentTheme === 'light'" class="theme-button" />
<SunIcon v-else class="theme-button" />
</SidebarButton>

<SidebarButton text="Show tutorial" to="" @click="showGuide">
<QuestionMarkIcon id="help-icon" />
</SidebarButton>
</div>
</nav>
Expand All @@ -58,8 +64,12 @@ import DISCO from "@/components/simple/DISCO.vue";
import SidebarButton from "./SidebarButton.vue";
import MoonIcon from "@/assets/svg/MoonIcon.vue";
import SunIcon from "@/assets/svg/SunIcon.vue";
import QuestionMarkIcon from "@/assets/svg/QuestionMarkIcon.vue";

const currentTheme = ref(localStorage.getItem('theme') || 'light');
import { useTutorialStore } from "@/store";

const currentTheme = ref(localStorage.getItem("theme") || "light");
const tutorialStore = useTutorialStore();

// Apply the initial theme on mount
onMounted(() => {
Expand All @@ -75,5 +85,7 @@ const toggleDarkMode = () => {
currentTheme.value = newTheme;
};


const showGuide = () => {
tutorialStore.toggleGuide();
};
</script>
Loading
Loading