Skip to content
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
4 changes: 2 additions & 2 deletions codewit/client/src/components/codeblock/Codeblock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default function CodeEditor({
{/* submit and reset buttons */}
<div className="inline-flex gap-1 pt-2 pb-3">
<button
className="group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 border-accent-500 rounded-lg focus:outline-none w-1/3"
className="group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 border-accent-500 rounded-lg focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent-500 w-1/3"
onClick={() => {
if (editorInstanceRef.current) {
editorInstanceRef.current.setValue('');
Expand All @@ -70,7 +70,7 @@ export default function CodeEditor({
</button>
<button
className={cn(
"group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 rounded-lg focus:outline-none w-2/3",
"group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 rounded-lg focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent-500 w-2/3",
{
"bg-alternate-background-500 border-foreground-400 hover:bg-alternate-background-500/90": is_submitting,
"border-accent-500": !is_submitting,
Expand Down
5 changes: 5 additions & 0 deletions codewit/client/src/components/nav/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ const NavBar = ({
<button
ref={toggleRef}
data-testid="navbar-toggle"
aria-label={isOpen ? 'Close menu' : 'Open menu'}
aria-expanded={isOpen}
aria-controls="nav-drawer"
className="h-9 px-3 relative flex items-center justify-center text-sm text-accent-600 hover:text-accent-700 bg-transparent dark:bg-transparent rounded-lg text-center font-medium focus:outline-none focus:ring-4"
onClick={toggleNavbar}
>
Expand All @@ -112,6 +115,7 @@ const NavBar = ({

{!loginHref && (
<div
id="nav-drawer"
ref={drawerRef}
className={`fixed top-0 right-0 w-64 h-screen bg-foreground-700 shadow-lg z-50 flex flex-col transform transition-transform duration-300 ease-in-out ${
isOpen ? 'translate-x-0' : 'translate-x-full'
Expand All @@ -120,6 +124,7 @@ const NavBar = ({
<div className="flex justify-end p-2">
<Button
size="sm"
aria-label="Close menu"
className="text-accent-500 hover:text-accent-700 bg-transparent dark:bg-transparent"
color="dark"
onClick={closeNavbar}
Expand Down
3 changes: 2 additions & 1 deletion codewit/client/src/components/videoui/VideoHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const VideoHeader = ({ title, uid, handleClick }: { title: string, uid:number |
onClick={() => handleClick(uid ?? 0)}
type="button"
data-testid="like-button"
className="group px-2 py-1 text-md font-medium text-center flex items-center text-white rounded-lg border-2 border-accent-400 hover:bg-accent-400 focus:outline-none"
aria-label="Like this demo"
className="group px-2 py-1 text-md font-medium text-center flex items-center text-white rounded-lg border-2 border-accent-400 hover:bg-accent-400 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent-400"
>
<HandThumbUpIcon className="w-6 h-6 mr-2 text-accent-400 group-hover:text-white" />
<span className="text-accent-400 group-hover:text-white">Like</span>
Expand Down
6 changes: 4 additions & 2 deletions codewit/client/src/pages/Read.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,10 @@ function LeftPanel({info, module_id, course_id}: LeftPanelProps) {
onClick={() => mutate({uid: info.demo.uid, like_demo: !is_liked})}
type="button"
data-testid="like-button"
aria-pressed={is_liked}
aria-label={is_liked ? 'Unlike this demo' : 'Like this demo'}
className={cn(
"group px-2 py-1 text-md font-medium text-center flex items-center rounded-lg border-2 hover:bg-accent-400 focus:outline-none",
"group px-2 py-1 text-md font-medium text-center flex items-center rounded-lg border-2 hover:bg-accent-400 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent-400",
{"text-green-500 border-green-500": is_liked},
{"text-accent-400 border-accent-400": !is_liked}
)}
Expand Down Expand Up @@ -605,7 +607,7 @@ type ActionBtnProps = ButtonHTMLAttributes<HTMLButtonElement>;
function ActionBtn({className, children, ...rest}: ActionBtnProps) {
return <button
className={cn(
"group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 rounded-lg focus:outline-none w-2/3",
"group px-2 py-1 text-md font-medium text-center flex items-center justify-center border-2 rounded-lg focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-accent-400 w-2/3",
className
)}
{...rest}
Expand Down
62 changes: 50 additions & 12 deletions codewit/client/src/pages/UserManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// codewit/client/src/utils/UserManagement.tsx
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import { MagnifyingGlassIcon, ShieldCheckIcon, ShieldExclamationIcon } from '@heroicons/react/24/outline';
import { User } from '@codewit/interfaces';
import { useFetchUsers, useSearchUser, useSetAdmin } from '../hooks/useUsers';
Expand All @@ -10,18 +10,53 @@ interface ModalProps {
onSave: () => void;
}

const Modal: React.FC<ModalProps> = ({ user, onClose, onSave }) => (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4">
<div className="bg-gray-800 p-6 rounded-lg space-y-4 w-full max-w-md">
<h2 className="text-white text-lg font-semibold">Change Admin Status</h2>
<p className="text-white">Are you sure you want to {user.isAdmin ? 'remove' : 'assign'} admin rights to {user.email}?</p>
<div className="flex justify-end space-x-2">
<button onClick={onClose} className="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded">Cancel</button>
<button onClick={onSave} className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded">Confirm</button>
const Modal: React.FC<ModalProps> = ({ user, onClose, onSave }) => {
const headingId = 'change-admin-status-heading';
const confirmRef = useRef<HTMLButtonElement>(null);

// Move focus to the Confirm button when the modal opens
useEffect(() => {
confirmRef.current?.focus();
}, []);

// Close on Escape
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, [onClose]);

return (
<div
role="dialog"
aria-modal="true"
aria-labelledby={headingId}
className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4"
>
<div className="bg-gray-800 p-6 rounded-lg space-y-4 w-full max-w-md">
<h2 id={headingId} className="text-white text-lg font-semibold">Change Admin Status</h2>
<p className="text-white">Are you sure you want to {user.isAdmin ? 'remove' : 'assign'} admin rights to {user.email}?</p>
<div className="flex justify-end space-x-2">
<button
onClick={onClose}
className="bg-gray-500 hover:bg-gray-600 text-white px-4 py-2 rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
>
Cancel
</button>
<button
ref={confirmRef}
onClick={onSave}
className="bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
>
Confirm
</button>
</div>
</div>
</div>
</div>
);
);
};

const UserManagement: React.FC = () => {
const [searchQuery, setSearchQuery] = useState<string>('');
Expand Down Expand Up @@ -99,15 +134,18 @@ const UserManagement: React.FC = () => {
>
<div className="mb-6 w-full max-w-7xl">
<div className="flex">
<label htmlFor="user-search" className="sr-only">Search users by email</label>
<input
id="user-search"
type="text"
className="w-full md:w-64 py-2 px-5 border border-gray-600 rounded-l-md focus:outline-none focus:ring-2 focus:ring-blue-500 bg-gray-700 text-white"
placeholder="Search by email"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
/>
<button
className="bg-accent-500 hover:bg-accent-600 text-white p-2 px-3 rounded-r-md disabled:opacity-50"
aria-label="Search users"
className="bg-accent-500 hover:bg-accent-600 text-white p-2 px-3 rounded-r-md disabled:opacity-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white"
onClick={handleSearch}
disabled={loading}
>
Expand Down
1 change: 1 addition & 0 deletions codewit/client/src/pages/course/StudentView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ function CourseModuleDemo({course_id, module_id, demo}: CourseModuleDemoProps) {
<div className="absolute inset-0 bg-black bg-opacity-40 flex rounded-xl items-center justify-center group hover:bg-opacity-20">
<Link
to={`/read/${demo.uid}?course_id=${course_id}&module_id=${module_id}`}
aria-label={demo.completion === 1 ? `${demo.title} (completed)` : `Open lesson: ${demo.title}`}
className="text-2xl opacity-70 group-hover:opacity-100"
>
{demo.completion === 1 ?
Expand Down
4 changes: 3 additions & 1 deletion codewit/client/src/pages/course/TeacherView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {

{/* invite link */}
<div className="mt-4 flex items-center gap-2">
<p className="text-foreground-200 text-sm">Class Link</p>
<label htmlFor="invite-link" className="text-foreground-200 text-sm">Class Link</label>
<input
id="invite-link"
className="p-1 bg-background-500 text-foreground-200 w-1/3 border border-accent-500 rounded-sm"
Expand Down Expand Up @@ -225,6 +225,7 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
type="button"
role="switch"
aria-checked={enrolling}
aria-label="Open for Enrollment"
onClick={toggleEnrolling}
disabled={savingFlags}
title={enrolling ? 'Turn off enrollment' : 'Open for enrollment'}
Expand Down Expand Up @@ -254,6 +255,7 @@ export default function TeacherView({ onCourseChange }: TeacherViewProps) {
type="button"
role="switch"
aria-checked={enrolling && autoEnroll}
aria-label="Auto Enroll"
onClick={toggleAutoEnroll}
disabled={!enrolling || savingFlags}
title={!enrolling ? 'Enable Open for Enrollment first' : (autoEnroll ? 'Disable auto enroll' : 'Enable auto enroll')}
Expand Down
Loading
Loading