feat: trigger confirm with unsaved changes (#378)

* trigger confirm with unsaved changes

* feat: add warning banner to course settings

* feat: implement on settings page.

* rename
This commit is contained in:
Rotimi Best
2024-11-20 10:33:28 +01:00
committed by GitHub
parent dc9e00a7ae
commit 02571e5ea7
3 changed files with 11022 additions and 12137 deletions
@@ -13,6 +13,7 @@
import { env } from '$env/dynamic/public'; import { env } from '$env/dynamic/public';
import SectionTitle from '$lib/components/Org/SectionTitle.svelte'; import SectionTitle from '$lib/components/Org/SectionTitle.svelte';
import UnsavedChanges from '$lib/components/UnsavedChanges/index.svelte';
import TextField from '$lib/components/Form/TextField.svelte'; import TextField from '$lib/components/Form/TextField.svelte';
import TextArea from '$lib/components/Form/TextArea.svelte'; import TextArea from '$lib/components/Form/TextArea.svelte';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte'; import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
@@ -44,6 +45,7 @@
description: string | undefined; description: string | undefined;
} = { title: undefined, description: undefined }; } = { title: undefined, description: undefined };
let avatar: string | undefined; let avatar: string | undefined;
let hasUnsavedChanges = false;
function widgetControl() { function widgetControl() {
$handleOpenWidget.open = !$handleOpenWidget.open; $handleOpenWidget.open = !$handleOpenWidget.open;
@@ -60,6 +62,7 @@
const downloadCourse = async () => { const downloadCourse = async () => {
isLoading = true; isLoading = true;
try { try {
const lessonsList = $lessons.map((lesson) => ({ const lessonsList = $lessons.map((lesson) => ({
lessonTitle: lesson.title, lessonTitle: lesson.title,
@@ -85,6 +88,7 @@
if (!response.ok) { if (!response.ok) {
throw new Error(await response.text()); throw new Error(await response.text());
} }
const data = await response.blob(); const data = await response.blob();
const file = new Blob([data], { type: 'application/pdf' }); const file = new Blob([data], { type: 'application/pdf' });
const fileURL = URL.createObjectURL(file); const fileURL = URL.createObjectURL(file);
@@ -100,6 +104,7 @@
} catch (error) { } catch (error) {
snackbar.error('snackbar.course_settings.error.not_right'); snackbar.error('snackbar.course_settings.error.not_right');
} }
isLoading = false; isLoading = false;
}; };
@@ -124,11 +129,14 @@
errors.title = $t('snackbar.course_settings.error.title'); errors.title = $t('snackbar.course_settings.error.title');
return; return;
} }
if (!$settings.course_description) { if (!$settings.course_description) {
errors.description = $t('snackbar.course_settings.error.description'); errors.description = $t('snackbar.course_settings.error.description');
return; return;
} }
isSaving = true; isSaving = true;
try { try {
const updatedCourse = { const updatedCourse = {
title: $settings.course_title, title: $settings.course_title,
@@ -153,6 +161,8 @@
}; };
snackbar.success('snackbar.course_settings.success.saved'); snackbar.success('snackbar.course_settings.success.saved');
hasUnsavedChanges = false;
} catch (error) { } catch (error) {
snackbar.error(); snackbar.error();
} }
@@ -160,30 +170,42 @@
isSaving = false; isSaving = false;
}; };
function setDefault(course: Course) {
if (course && Object.keys(course).length && $settings.course_title !== course.title) {
$settings = {
course_title: course.title,
type: course.type,
course_description: course.description,
logo: course.logo || '',
tabs: course.metadata.lessonTabsOrder || $settings.tabs,
grading: !!course.metadata.grading,
lesson_download: !!course.metadata.lessonDownload,
is_published: !!course.is_published,
allow_new_students: course.metadata.allowNewStudent
};
}
}
const generateNewCourseLink = () => { const generateNewCourseLink = () => {
$course.slug = generateSlug($course.title); $course.slug = generateSlug($course.title);
}; };
let hasInitialized = false;
async function setDefault(course: Course) {
if (!course || !Object.keys(course).length || hasInitialized) return;
settings.set({
course_title: course.title,
type: course.type,
course_description: course.description,
logo: course.logo || '',
tabs: course.metadata.lessonTabsOrder || $settings.tabs,
grading: !!course.metadata.grading,
lesson_download: !!course.metadata.lessonDownload,
is_published: !!course.is_published,
allow_new_students: course.metadata.allowNewStudent
});
settings.subscribe((s) => {
if (!hasInitialized) return;
hasUnsavedChanges = true;
});
hasInitialized = true;
}
$: setDefault($course); $: setDefault($course);
$: courseLink = `${$currentOrgDomain}/course/${$course.slug}`; $: courseLink = `${$currentOrgDomain}/course/${$course.slug}`;
</script> </script>
<UnsavedChanges {hasUnsavedChanges} />
<Grid class="border-c rounded border-gray-200 dark:border-neutral-600"> <Grid class="border-c rounded border-gray-200 dark:border-neutral-600">
<Row class="flex lg:flex-row flex-col py-7 border-bottom-c"> <Row class="flex lg:flex-row flex-col py-7 border-bottom-c">
<Column sm={8} md={8} lg={8}> <Column sm={8} md={8} lg={8}>
@@ -231,6 +253,7 @@
label={$t('course.navItem.settings.course_title')} label={$t('course.navItem.settings.course_title')}
placeholder="Write the course title here" placeholder="Write the course title here"
className="w-full mb-5" className="w-full mb-5"
isRequired
bind:value={$settings.course_title} bind:value={$settings.course_title}
errorMessage={errors.title} errorMessage={errors.title}
/> />
@@ -238,6 +261,7 @@
label={$t('course.navItem.settings.course_description')} label={$t('course.navItem.settings.course_description')}
placeholder={$t('course.navItem.settings.placeholder')} placeholder={$t('course.navItem.settings.placeholder')}
className="w-full mb-5" className="w-full mb-5"
isRequired
bind:value={$settings.course_description} bind:value={$settings.course_description}
errorMessage={errors.description} errorMessage={errors.description}
/> />
@@ -0,0 +1,24 @@
<script lang="ts">
import { beforeNavigate } from '$app/navigation';
export let hasUnsavedChanges = false;
export let message = 'You have unsaved changes. Are you sure you want to leave?';
beforeNavigate(({ cancel }) => {
if (!shouldAbandonChanges()) cancel();
});
function shouldAbandonChanges() {
if (!hasUnsavedChanges) return true;
return confirm(message);
}
</script>
<svelte:window
on:beforeunload={(e) => {
const result = shouldAbandonChanges();
if (!result) e.preventDefault();
}}
/>
<slot />
+10958 -12121
View File
File diff suppressed because it is too large Load Diff