Files
classroomio/apps/dashboard/src/lib/features/course/components/course-context-menu-content.svelte
T
Victor JackandRotimi Best 60056a6236 fix: validation of allowing teachers create compliance courses without setting deadline (#778)
* Fixed Validation of allowing teachers create compliance courses without setting deadline

* greptile highlightCertificateSettings decraration suggestion

* greptile multiple error bar showing fix suggestion

* organization race condition

* Delete screenshots/Screenshot 2026-07-22 at 11.52.00 AM.png

* deleted unwanted files

* code review fixes

* Changed AttentionHightlight component to work with just one parameter

created fixed Route Enums, Paths and Sections for

* Kebab-case naming fix

* Changes for code comments

---------

Co-authored-by: Rotimi Best <[email protected]>
2026-08-05 13:28:32 +01:00

172 lines
5.1 KiB
Svelte

<script lang="ts">
import * as DropdownMenu from '@cio/ui/base/dropdown-menu';
import { page } from '$app/state';
import { goto } from '$app/navigation';
import { resolve } from '$app/paths';
import { copyCourseModal, deleteCourseModal } from '$features/course/utils/store';
import { copyPublicCoursePageUrl, openCoursePreview } from '$features/course/utils/course-preview';
import { currentOrgDomain } from '$lib/utils/store/org';
import { t } from '$lib/utils/functions/translations';
import { goAndHighlight } from '$lib/routing/go-and-highlight';
import { ROUTE_NAME, ROUTE_SECTIONS } from '$lib/routing/routes';
interface Props {
id: string;
title: string;
description: string;
isPublished?: boolean;
courseType?: string | null;
slug?: string;
/** Compact menu for LMS course cards */
lmsPublicQuickOnly?: boolean;
/** Include "View as student" (course header menu) */
includeViewAsStudent?: boolean;
onViewAsStudent?: () => void;
/** List view includes an explicit Open action */
includeOpen?: boolean;
/** Hide org management actions (clone, share, invite, delete) */
hideOrgActions?: boolean;
}
let {
id,
title,
description,
isPublished = false,
courseType = null,
slug = '',
lmsPublicQuickOnly = false,
includeViewAsStudent = false,
onViewAsStudent,
includeOpen = false,
hideOrgActions = false
}: Props = $props();
const showPublicCourseLinks = $derived(isPublished && courseType === 'PUBLIC' && slug.trim().length > 0);
const courseSettingsPath = $derived(resolve(`/courses/${id}/settings`, {}));
function redirect(url: string) {
goto(resolve(url, {}));
}
function scrollToSettingsSection(sectionId: string) {
document.getElementById(sectionId)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function handleShareCourse() {
if (page.url.pathname === courseSettingsPath) {
scrollToSettingsSection('share');
return;
}
redirect(`/courses/${id}/settings#share`);
}
function handleInvite() {
redirect(`/courses/${id}/people?add=true`);
}
function handlePublishCourse() {
goAndHighlight(ROUTE_NAME.COURSE_SETTINGS, ROUTE_SECTIONS[ROUTE_NAME.COURSE_SETTINGS].PUBLISH, { id });
}
function handleDeleteCourse() {
if (page.url.pathname === courseSettingsPath) {
scrollToSettingsSection('delete');
return;
}
const isOnOrgCoursesList = /\/org\/[^/]+\/courses\/?$/.test(page.url.pathname);
if (isOnOrgCoursesList) {
$deleteCourseModal.open = true;
$deleteCourseModal.id = id;
$deleteCourseModal.title = title;
return;
}
redirect(`/courses/${id}/settings#delete`);
}
function handleCloneCourse() {
$copyCourseModal.open = true;
$copyCourseModal.id = id;
$copyCourseModal.title = title;
$copyCourseModal.description = description;
}
function handleOpenCourse() {
redirect(`/courses/${id}`);
}
function handleViewCourseSite() {
openCoursePreview({
courseId: id,
courseSlug: slug,
currentOrgDomain: $currentOrgDomain
});
}
async function handleCopyCourseUrl() {
await copyPublicCoursePageUrl(slug, $currentOrgDomain);
}
</script>
{#if lmsPublicQuickOnly}
<DropdownMenu.Item onclick={handleViewCourseSite}>
{$t('courses.course_card.context_menu.view_course_site')}
</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => void handleCopyCourseUrl()}>
{$t('courses.course_card.context_menu.copy_course_url')}
</DropdownMenu.Item>
{:else}
{#if includeViewAsStudent}
<DropdownMenu.Item onclick={() => onViewAsStudent?.()}>
{$t('course.header.view_as_student')}
</DropdownMenu.Item>
<DropdownMenu.Separator />
{/if}
{#if isPublished}
<DropdownMenu.Item onclick={handleViewCourseSite}>
{$t('courses.course_card.context_menu.view_course_site')}
</DropdownMenu.Item>
{#if showPublicCourseLinks}
<DropdownMenu.Item onclick={() => void handleCopyCourseUrl()}>
{$t('courses.course_card.context_menu.copy_course_url')}
</DropdownMenu.Item>
{/if}
{#if !hideOrgActions || includeOpen}
<DropdownMenu.Separator />
{/if}
{:else}
<DropdownMenu.Item onclick={handlePublishCourse}>
{$t('courses.course_card.context_menu.publish_course')}
</DropdownMenu.Item>
{#if !hideOrgActions || includeOpen}
<DropdownMenu.Separator />
{/if}
{/if}
{#if includeOpen}
<DropdownMenu.Item onclick={handleOpenCourse}>
{$t('courses.course_card.context_menu.open')}
</DropdownMenu.Item>
{/if}
{#if !hideOrgActions}
<DropdownMenu.Item onclick={handleCloneCourse}>
{$t('courses.course_card.context_menu.clone')}
</DropdownMenu.Item>
<DropdownMenu.Item onclick={handleShareCourse}>
{$t('courses.course_card.context_menu.share')}
</DropdownMenu.Item>
<DropdownMenu.Item onclick={handleInvite}>
{$t('courses.course_card.context_menu.invite')}
</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item class="text-red-600" onclick={handleDeleteCourse}>
{$t('courses.course_card.context_menu.delete')}
</DropdownMenu.Item>
{/if}
{/if}