fix(dashboard): hide compliance in-progress badge and enforce deadline on view-site publish (#913)
* fix(dashboard): hide in-progress badge on compliance learner cards Keep the due date on My Learning and LMS current-course cards, and only show compliance status badges for states that need attention. Co-authored-by: best <best@classroomio.com> * fix(dashboard): enforce compliance deadline when publishing from view course site Reuse the settings deadline-required dialog and navigate to the completion deadline section so unpublished-site publish matches settings and the API. Co-authored-by: best <best@classroomio.com> * fix(dashboard): keep attention highlight visible after deadline navigation Prevent goto and dialog focus restoration from scrolling away from the completion deadline section before the highlight pulse can render. Co-authored-by: best <best@classroomio.com> * fix(dashboard): keep deadline attention highlight visible longer Use onMount plus afterNavigate so the completion deadline ring is not lost to navigation scroll races, and show a stronger primary ring for five seconds. Co-authored-by: best <best@classroomio.com> * test(dashboard): use Jest APIs in compliance badge tests Drop the Vitest import so the new test matches the dashboard's declared Jest runner and @types/jest globals. Co-authored-by: best <best@classroomio.com> ---------
This commit is contained in:
@@ -23,7 +23,8 @@
|
||||
import {
|
||||
getStudentCourseComplianceDate,
|
||||
getStudentCourseComplianceStatusKey,
|
||||
getStudentCourseComplianceStatusVariant
|
||||
getStudentCourseComplianceStatusVariant,
|
||||
shouldShowStudentCourseComplianceStatusBadge
|
||||
} from '$features/course/utils/compliance-utils';
|
||||
import CardDropdown from './card-dropdown.svelte';
|
||||
import CoursePublishBadge from './course-publish-badge.svelte';
|
||||
@@ -195,6 +196,11 @@
|
||||
? getStudentCourseComplianceStatusKey(course as UserEnrolledCourses[number])
|
||||
: null
|
||||
);
|
||||
const showComplianceStatusBadge = $derived(
|
||||
isLMS && type === 'COMPLIANCE' && !isExplore
|
||||
? shouldShowStudentCourseComplianceStatusBadge(course as UserEnrolledCourses[number])
|
||||
: false
|
||||
);
|
||||
const complianceStatusVariant = $derived(
|
||||
isLMS && type === 'COMPLIANCE' && !isExplore
|
||||
? getStudentCourseComplianceStatusVariant(course as UserEnrolledCourses[number])
|
||||
@@ -300,7 +306,7 @@
|
||||
|
||||
{#if type === 'COMPLIANCE'}
|
||||
<div class="mt-2 flex flex-wrap items-center gap-2">
|
||||
{#if complianceStatusKey}
|
||||
{#if showComplianceStatusBadge && complianceStatusKey}
|
||||
<Badge variant={complianceStatusVariant}>
|
||||
{$t(complianceStatusKey)}
|
||||
</Badge>
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
import * as Dialog from '@cio/ui/base/dialog';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
|
||||
interface Props {
|
||||
open?: boolean;
|
||||
onGoToDeadline: () => void;
|
||||
}
|
||||
|
||||
let { open = $bindable(false), onGoToDeadline }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Dialog.Root bind:open>
|
||||
<Dialog.Content class="max-w-md" onCloseAutoFocus={(e) => e.preventDefault()}>
|
||||
<Dialog.Header>
|
||||
<Dialog.Title>{$t('course.navItem.settings.certificate_deadline_required')}</Dialog.Title>
|
||||
<Dialog.Description>
|
||||
{$t('course.navItem.settings.certificate_deadline_required_description')}
|
||||
</Dialog.Description>
|
||||
</Dialog.Header>
|
||||
<Dialog.Footer>
|
||||
<Button variant="outline" onclick={() => (open = false)}>
|
||||
{$t('cancel')}
|
||||
</Button>
|
||||
<Button onclick={onGoToDeadline}>
|
||||
{$t('course.navItem.settings.go_to_completion_deadline')}
|
||||
</Button>
|
||||
</Dialog.Footer>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
+28
-3
@@ -1,10 +1,13 @@
|
||||
<script lang="ts">
|
||||
import { tick } from 'svelte';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
import * as Dialog from '@cio/ui/base/dialog';
|
||||
import { courseApi } from '$features/course/api';
|
||||
import { publishCourse } from '$features/course/utils/publish-course';
|
||||
import { openCoursePreview } from '$features/course/utils/course-preview';
|
||||
import { goToCourseCompletionDeadline } from '$features/course/utils/compliance-deadline';
|
||||
import { t } from '$lib/utils/functions/translations';
|
||||
import CertificateDeadlineRequiredDialog from './certificate-deadline-required-dialog.svelte';
|
||||
|
||||
interface Props {
|
||||
open?: boolean;
|
||||
@@ -14,6 +17,7 @@
|
||||
let { open = $bindable(false), currentOrgDomain = '' }: Props = $props();
|
||||
|
||||
let isPublishing = $state(false);
|
||||
let openDeadlineDialog = $state(false);
|
||||
|
||||
async function handlePublishCourse() {
|
||||
const course = courseApi.course;
|
||||
@@ -23,10 +27,17 @@
|
||||
|
||||
isPublishing = true;
|
||||
|
||||
const published = await publishCourse(course);
|
||||
const result = await publishCourse(course);
|
||||
isPublishing = false;
|
||||
|
||||
if (!published) {
|
||||
if (!result.ok && result.reason === 'missing_deadline') {
|
||||
open = false;
|
||||
await tick();
|
||||
openDeadlineDialog = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -38,6 +49,18 @@
|
||||
currentOrgDomain
|
||||
});
|
||||
}
|
||||
|
||||
async function goToCompletionDeadline() {
|
||||
const courseId = courseApi.course?.id;
|
||||
openDeadlineDialog = false;
|
||||
|
||||
if (!courseId) {
|
||||
return;
|
||||
}
|
||||
|
||||
await tick();
|
||||
goToCourseCompletionDeadline(courseId);
|
||||
}
|
||||
</script>
|
||||
|
||||
<Dialog.Root
|
||||
@@ -48,7 +71,7 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Dialog.Content class="w-[calc(100%-2rem)] max-w-md! p-4">
|
||||
<Dialog.Content class="w-[calc(100%-2rem)] max-w-md! p-4" onCloseAutoFocus={(e) => e.preventDefault()}>
|
||||
<Dialog.Header>
|
||||
<Dialog.Title>{$t('course.view_course_site.unpublished_title')}</Dialog.Title>
|
||||
<Dialog.Description>{$t('course.view_course_site.unpublished_description')}</Dialog.Description>
|
||||
@@ -64,3 +87,5 @@
|
||||
</Dialog.Footer>
|
||||
</Dialog.Content>
|
||||
</Dialog.Root>
|
||||
|
||||
<CertificateDeadlineRequiredDialog bind:open={openDeadlineDialog} onGoToDeadline={goToCompletionDeadline} />
|
||||
|
||||
Reference in New Issue
Block a user