Merge pull request #354 from chrishollandaise/fix/activity-chapter-elements

Fixing various bugs in the `ActivityElement` component
This commit is contained in:
Badr B. 2024-10-20 23:37:32 +02:00 committed by GitHub
commit 19cc3ea0d7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 97 additions and 112 deletions

View file

@ -88,7 +88,7 @@ function ActivityElement(props: ActivitiyElementProps) {
modifiedActivity?.activityId === activityId && modifiedActivity?.activityId === activityId &&
selectedActivity !== undefined selectedActivity !== undefined
) { ) {
setSelectedActivity(undefined)
let modifiedActivityCopy = { let modifiedActivityCopy = {
...props.activity, ...props.activity,
name: modifiedActivity.activityName, name: modifiedActivity.activityName,
@ -99,6 +99,7 @@ function ActivityElement(props: ActivitiyElementProps) {
await revalidateTags(['courses'], props.orgslug) await revalidateTags(['courses'], props.orgslug)
router.refresh() router.refresh()
} }
setSelectedActivity(undefined)
} }
return ( return (
@ -109,7 +110,7 @@ function ActivityElement(props: ActivitiyElementProps) {
> >
{(provided, snapshot) => ( {(provided, snapshot) => (
<div <div
className="flex flex-row py-2 my-2 w-full rounded-md bg-gray-50 text-gray-500 hover:bg-gray-100 hover:scale-102 hover:shadow space-x-1 items-center ring-1 ring-inset ring-gray-400/10 shadow-sm transition-all delay-100 duration-75 ease-linear" className="flex flex-row py-2 my-2 w-full rounded-md bg-gray-50 text-gray-500 hover:bg-gray-100 hover:scale-102 hover:shadow space-x-1 items-center ring-1 ring-inset ring-gray-400/10 shadow-sm"
key={props.activity.id} key={props.activity.id}
{...provided.draggableProps} {...provided.draggableProps}
{...provided.dragHandleProps} {...provided.dragHandleProps}
@ -143,8 +144,7 @@ function ActivityElement(props: ActivitiyElementProps) {
className="bg-transparent text-neutral-700 hover:cursor-pointer hover:text-neutral-900" className="bg-transparent text-neutral-700 hover:cursor-pointer hover:text-neutral-900"
> >
<Save <Save
size={11} size={12}
onClick={() => updateActivityName(props.activity.id)}
/> />
</button> </button>
</div> </div>
@ -153,68 +153,69 @@ function ActivityElement(props: ActivitiyElementProps) {
)} )}
<Pencil <Pencil
onClick={() => setSelectedActivity(props.activity.id)} onClick={() => setSelectedActivity(props.activity.id)}
size={12} className="text-neutral-400 hover:cursor-pointer size-3 min-w-3"
className="text-neutral-400 hover:cursor-pointer"
/> />
</div> </div>
{/* Edit and View Button */} {/* Edit and View Button */}
<div className="flex flex-row space-x-2"> <div className="flex basis-1/2 justify-end">
<ActivityElementOptions activity={props.activity} /> <div className="flex flex-row space-x-2">
{/* Publishing */} <ActivityElementOptions activity={props.activity} />
<div {/* Publishing */}
className={`hover:cursor-pointer p-1 px-3 border shadow-lg rounded-md font-bold text-xs flex items-center space-x-1 ${!props.activity.published <div
? 'bg-gradient-to-bl text-green-800 from-green-400/50 to-lime-200/80 border-green-600/10 shadow-green-900/10' className={`hover:cursor-pointer p-1 px-3 border shadow-lg rounded-md font-bold text-xs flex items-center space-x-1 ${!props.activity.published
: 'bg-gradient-to-bl text-gray-800 from-gray-400/50 to-gray-200/80 border-gray-600/10 shadow-gray-900/10' ? 'bg-gradient-to-bl text-green-800 from-green-400/50 to-lime-200/80 border-green-600/10 shadow-green-900/10'
}`} : 'bg-gradient-to-bl text-gray-800 from-gray-400/50 to-gray-200/80 border-gray-600/10 shadow-gray-900/10'
rel="noopener noreferrer" }`}
onClick={() => changePublicStatus()} rel="noopener noreferrer"
> onClick={() => changePublicStatus()}
{!props.activity.published ? ( >
<Globe strokeWidth={2} size={12} className="text-green-600" /> {!props.activity.published ? (
) : ( <Globe strokeWidth={2} size={12} className="text-green-600" />
<Lock strokeWidth={2} size={12} className="text-gray-600" /> ) : (
)} <Lock strokeWidth={2} size={12} className="text-gray-600" />
<span>{!props.activity.published ? 'Publish' : 'Unpublish'}</span> )}
<span>{!props.activity.published ? 'Publish' : 'Unpublish'}</span>
</div>
<Link
href={
getUriWithOrg(props.orgslug, '') +
`/course/${props.course_uuid.replace(
'course_',
''
)}/activity/${props.activity.activity_uuid.replace(
'activity_',
''
)}`
}
prefetch
className=" hover:cursor-pointer p-1 px-3 bg-gradient-to-bl text-cyan-800 from-sky-400/50 to-cyan-200/80 border border-cyan-600/10 shadow-cyan-900/10 shadow-lg rounded-md font-bold text-xs flex items-center space-x-1"
rel="noopener noreferrer"
>
<Eye strokeWidth={2} size={12} className="text-sky-600" />
<span>Preview</span>
</Link>
</div>
{/* Delete Button */}
<div className="flex flex-row pr-3 space-x-1 items-center">
<MoreVertical size={15} className="text-gray-300" />
<ConfirmationModal
confirmationMessage="Are you sure you want to delete this activity ?"
confirmationButtonText="Delete Activity"
dialogTitle={'Delete ' + props.activity.name + ' ?'}
dialogTrigger={
<div
className=" hover:cursor-pointer p-1 px-5 bg-red-600 rounded-md"
rel="noopener noreferrer"
>
<X size={15} className="text-rose-200 font-bold" />
</div>
}
functionToExecute={() => deleteActivityUI()}
status="warning"
></ConfirmationModal>
</div> </div>
<Link
href={
getUriWithOrg(props.orgslug, '') +
`/course/${props.course_uuid.replace(
'course_',
''
)}/activity/${props.activity.activity_uuid.replace(
'activity_',
''
)}`
}
prefetch
className=" hover:cursor-pointer p-1 px-3 bg-gradient-to-bl text-cyan-800 from-sky-400/50 to-cyan-200/80 border border-cyan-600/10 shadow-cyan-900/10 shadow-lg rounded-md font-bold text-xs flex items-center space-x-1"
rel="noopener noreferrer"
>
<Eye strokeWidth={2} size={12} className="text-sky-600" />
<span>Preview</span>
</Link>
</div>
{/* Delete Button */}
<div className="flex flex-row pr-3 space-x-1 items-center">
<MoreVertical size={15} className="text-gray-300" />
<ConfirmationModal
confirmationMessage="Are you sure you want to delete this activity ?"
confirmationButtonText="Delete Activity"
dialogTitle={'Delete ' + props.activity.name + ' ?'}
dialogTrigger={
<div
className=" hover:cursor-pointer p-1 px-5 bg-red-600 rounded-md"
rel="noopener noreferrer"
>
<X size={15} className="text-rose-200 font-bold" />
</div>
}
functionToExecute={() => deleteActivityUI()}
status="warning"
></ConfirmationModal>
</div> </div>
</div> </div>
)} )}
@ -222,53 +223,36 @@ function ActivityElement(props: ActivitiyElementProps) {
) )
} }
const ActivityTypeIndicator = (props: { activityType: string }) => { const ACTIVITIES = {
'TYPE_VIDEO': {
displayName: 'Video',
Icon: Video
},
'TYPE_DOCUMENT': {
displayName: 'Document',
Icon: File
},
'TYPE_ASSIGNMENT': {
displayName: 'Assignment',
Icon: Backpack
},
'TYPE_DYNAMIC': {
displayName: 'Dynamic',
Icon: Sparkles
}
}
const ActivityTypeIndicator = ({activityType} : { activityType: keyof typeof ACTIVITIES}) => {
const {displayName, Icon} = ACTIVITIES[activityType]
return ( return (
<div className="px-3 text-gray-300 space-x-1 w-28"> <div className="px-3 text-gray-300 space-x-1 w-28 flex">
{props.activityType === 'TYPE_VIDEO' && ( <div className="flex space-x-2 items-center">
<> <Icon className="size-4" />{' '}
<div className="flex space-x-2 items-center">
<Video size={16} />{' '}
<div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full mx-auto justify-center align-middle"> <div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full mx-auto justify-center align-middle">
Video {displayName}
</div>{' '} </div>{' '}
</div> </div>
</>
)}
{props.activityType === 'TYPE_DOCUMENT' && (
<>
<div className="flex space-x-2 items-center">
<div className="w-[30px]">
<File size={16} />{' '}
</div>
<div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">
Document
</div>{' '}
</div>
</>
)}
{props.activityType === 'TYPE_ASSIGNMENT' && (
<>
<div className="flex space-x-2 items-center">
<div className="w-[30px]">
<Backpack size={16} />{' '}
</div>
<div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">
Assignment
</div>{' '}
</div>
</>
)}
{props.activityType === 'TYPE_DYNAMIC' && (
<>
<div className="flex space-x-2 items-center">
<Sparkles size={16} />{' '}
<div className="text-xs bg-gray-200 text-gray-400 font-bold px-2 py-1 rounded-full">
Dynamic
</div>{' '}
</div>
</>
)}
</div> </div>
) )
} }
@ -280,7 +264,7 @@ const ActivityElementOptions = ({ activity }: any) => {
const session = useLHSession() as any; const session = useLHSession() as any;
const access_token = session?.data?.tokens?.access_token; const access_token = session?.data?.tokens?.access_token;
async function getAssignmentUUIDFromActivityUUID(activityUUID: string) { async function getAssignmentUUIDFromActivityUUID(activityUUID: string): Promise<string | undefined> {
const activity = await getAssignmentFromActivityUUID(activityUUID, access_token); const activity = await getAssignmentFromActivityUUID(activityUUID, access_token);
if (activity) { if (activity) {
return activity.data.assignment_uuid; return activity.data.assignment_uuid;
@ -290,7 +274,8 @@ const ActivityElementOptions = ({ activity }: any) => {
const fetchAssignmentUUID = async () => { const fetchAssignmentUUID = async () => {
if (activity.activity_type === 'TYPE_ASSIGNMENT') { if (activity.activity_type === 'TYPE_ASSIGNMENT') {
const assignment_uuid = await getAssignmentUUIDFromActivityUUID(activity.activity_uuid); const assignment_uuid = await getAssignmentUUIDFromActivityUUID(activity.activity_uuid);
setAssignmentUUID(assignment_uuid.replace('assignment_', '')); if(assignment_uuid)
setAssignmentUUID(assignment_uuid.replace('assignment_', ''));
} }
}; };
@ -323,7 +308,7 @@ const ActivityElementOptions = ({ activity }: any) => {
</Link> </Link>
</> </>
)} )}
{activity.activity_type === 'TYPE_ASSIGNMENT' && assignmentUUID && ( {activity.activity_type === 'TYPE_ASSIGNMENT' && (
<> <>
<Link <Link
href={ href={
@ -339,7 +324,7 @@ const ActivityElementOptions = ({ activity }: any) => {
</Link> </Link>
</> </>
)} )}
</> </>
); );
}; };

View file

@ -52,7 +52,6 @@ function ChapterElement(props: ChapterElementProps) {
async function updateChapterName(chapterId: string) { async function updateChapterName(chapterId: string) {
if (modifiedChapter?.chapterId === chapterId) { if (modifiedChapter?.chapterId === chapterId) {
setSelectedChapter(undefined)
let modifiedChapterCopy = { let modifiedChapterCopy = {
name: modifiedChapter.chapterName, name: modifiedChapter.chapterName,
} }
@ -61,6 +60,7 @@ function ChapterElement(props: ChapterElementProps) {
await revalidateTags(['courses'], props.orgslug) await revalidateTags(['courses'], props.orgslug)
router.refresh() router.refresh()
} }
setSelectedChapter(undefined)
} }
return ( return (
@ -155,7 +155,7 @@ function ChapterElement(props: ChapterElementProps) {
<div className="flex flex-col"> <div className="flex flex-col">
{activities.map((activity: any, index: any) => { {activities.map((activity: any, index: any) => {
return ( return (
<div key={index} className="flex items-center "> <div key={activity.activity_uuid} className="flex items-center ">
<ActivityElement <ActivityElement
orgslug={props.orgslug} orgslug={props.orgslug}
course_uuid={props.course_uuid} course_uuid={props.course_uuid}

View file

@ -46,17 +46,17 @@ function Activity(props: any) {
modifiedActivity?.activityId === activityId && modifiedActivity?.activityId === activityId &&
selectedActivity !== undefined selectedActivity !== undefined
) { ) {
setSelectedActivity(undefined)
let modifiedActivityCopy = { let modifiedActivityCopy = {
...props.activity, ...props.activity,
name: modifiedActivity.activityName, name: modifiedActivity.activityName,
} }
await updateActivity(modifiedActivityCopy, activityId, session.data?.tokens?.access_token) await updateActivity(modifiedActivityCopy, activityId, session.data?.tokens?.access_token)
await mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`) await mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`)
await revalidateTags(['courses'], props.orgslug) await revalidateTags(['courses'], props.orgslug)
router.refresh() router.refresh()
} }
setSelectedActivity(undefined)
} }
return ( return (

View file

@ -28,7 +28,6 @@ function Chapter(props: any) {
async function updateChapterName(chapterId: string) { async function updateChapterName(chapterId: string) {
if (modifiedChapter?.chapterId === chapterId) { if (modifiedChapter?.chapterId === chapterId) {
setSelectedChapter(undefined)
let modifiedChapterCopy = { let modifiedChapterCopy = {
name: modifiedChapter.chapterName, name: modifiedChapter.chapterName,
} }
@ -37,6 +36,7 @@ function Chapter(props: any) {
await revalidateTags(['courses'], props.orgslug) await revalidateTags(['courses'], props.orgslug)
router.refresh() router.refresh()
} }
setSelectedChapter(undefined)
} }
return ( return (