Skip to content
Snippets Groups Projects
Select Git revision
  • efe29f1a86d9e76f73abd7fdd583a8abc0ff0644
  • master default protected
  • forbid-save-as
  • upload-via-token
  • moodle-integration
  • patch-double-tap-seek
  • patch_datum_anzeigen
  • patch_raum_anzeigen
  • intros
  • live_sources
  • bootstrap4
  • modules
12 results

server.py

Blame
  • Forked from Video AG Infrastruktur / website
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    CourseListing.tsx 16.68 KiB
    import { useBackendContext } from "./BackendProvider";
    import Link from "next/link";
    import {
        OMCreate,
        OMDelete,
        OMEdit,
        OMHistory,
        EmbeddedOMFieldComponent,
    } from "./OMConfigComponent";
    import { useEditMode } from "./EditModeProvider";
    import { DownloadSources, EditSources } from "./Player";
    import Title from "./TitleComponent";
    import DownloadAllModal from "./DownloadManager";
    
    import type { GetCourseResponse, lecture } from "@/api/api_v1_types";
    import { ResourceType } from "@/misc/PromiseHelpers";
    import { AuthenticationMethodIcons } from "@/misc/Util";
    import { useLanguage } from "./LanguageProvider";
    
    function ListingHeader({ course }: { course: GetCourseResponse }) {
        const { editMode } = useEditMode();
        const { language } = useLanguage();
    
        return (
            <div className="card mb-3">
                <div className="card-body">
                    <h5 className="card-title d-flex">
                        <span className="panel-title flex-fill align-self-center">
                            <EmbeddedOMFieldComponent
                                object_type="course"
                                object_id={course.id!}
                                field_id="full_name"
                                field_type="string"
                                initialValue={course.full_name}
                            />
                        </span>
                        <div style={{ fontSize: "1rem" /* Reset font size for icons */ }}>
                            {editMode && (
                                <>
                                    <OMHistory object_type="course" object_id={course.id!} />
                                    <OMEdit object_type="course" object_id={course.id!} />
                                    <OMDelete object_type="course" object_id={course.id!} />
                                </>
                            )}
                            <AuthenticationMethodIcons
                                authentication_methods={course.default_authentication_methods}
                            />
                        </div>
                    </h5>
                    <div className="row">
                        <div className="col-12">
                            <Link
                                href={`/courses#course-${course.id}`}
                                className="btn btn-primary mb-1"
                            >
                                <span className="bi bi-chevron-left" />{" "}
                                {language.get("ui.course.back_to_list")}
                            </Link>
                            <table className="table table-sm">
                                <tbody>
                                    <tr>
                                        <td>{language.get("object.course.semester")}:</td>
                                        <td>
                                            <EmbeddedOMFieldComponent
                                                object_type="course"
                                                object_id={course.id!}
                                                field_id="semester"
                                                field_type="semester_string"
                                                initialValue={course.semester}
                                            />
                                        </td>
                                    </tr>
                                    <tr>
                                        <td>{language.get("object.course.organizer")}:</td>
                                        <td>
                                            <EmbeddedOMFieldComponent
                                                object_type="course"
                                                object_id={course.id!}
                                                field_id="organizer"
                                                field_type="string"
                                                initialValue={course.organizer}
                                                allowMarkdown={true}
                                            />
                                        </td>
                                    </tr>
                                    <tr>
                                        <td className="w-25">
                                            {language.get("object.course.description")}:
                                        </td>
                                        <td>
                                            <EmbeddedOMFieldComponent
                                                object_type="course"
                                                object_id={course.id!}
                                                field_id="description"
                                                field_type="string"
                                                initialValue={course.description}
                                                allowMarkdown={true}
                                            />
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            {course.lectures &&
                                course.lectures.some(
                                    (lecture) =>
                                        lecture.media_sources &&
                                        lecture.media_sources.some(
                                            (ele) => ele.download_url !== undefined,
                                        ),
                                ) && <DownloadAllModal course={course} />}
                        </div>
                    </div>
                </div>
            </div>
        );
    }
    
    export function LectureListItem({
        lecture,
        course_id_string,
        ...props
    }: {
        lecture: lecture;
        course_id_string?: string;
        [key: string]: any;
    }) {
        const api = useBackendContext();
        const { editMode } = useEditMode();
        const { language } = useLanguage();
    
        let content = <></>;
    
        if (lecture.media_sources && lecture.media_sources.length > 0) {
            let thumbUrl = lecture.thumbnail_url ?? `${api.assetUrl()}/thumbnail/l_${lecture.id}.jpg`;
            const showDownloadSourcesButton =
                editMode === false &&
                lecture.media_sources &&
                lecture.media_sources.some((ele) => ele.download_url !== undefined);
    
            content = (
                <>
                    <div
                        style={{
                            backgroundImage: `url('${thumbUrl}')`,
                        }}
                        className="col-sm-2 col-12 thumbnailimg"
                    >
                        <Link href={`/${course_id_string ?? lecture.course_id}/${lecture.id}`}>
                            <span aria-hidden="true" className={"playpreviewbtn bi bi-play-circle"} />
                        </Link>
                    </div>
                    <ul className="list-unstyled col-sm-3 col-12">
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="title"
                                field_type="string"
                                initialValue={lecture.title}
                            />
                        </li>
                        {lecture.speaker && (
                            <li>
                                {language.get("ui.generic.lecture_given_by")}{" "}
                                <EmbeddedOMFieldComponent
                                    object_type="lecture"
                                    object_id={lecture.id!}
                                    field_id="speaker"
                                    field_type="string"
                                    initialValue={lecture.speaker}
                                    allowMarkdown={true}
                                    inline
                                />
                            </li>
                        )}
    
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="time"
                                field_type="datetime"
                                initialValue={lecture.time}
                            />
                        </li>
                    </ul>
                    <ul className="list-unstyled col-sm-3 col-12">
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="description"
                                field_type="string"
                                initialValue={lecture.description}
                                allowMarkdown={true}
                            />
                        </li>
                        {lecture.chapters?.map((chapter) => (
                            <li
                                key={chapter.name}
                                className={
                                    "d-flex " +
                                    (chapter.is_visible === false ? "bg-danger-subtle rounded" : "")
                                }
                            >
                                <span className="bi bi-play" />
                                <Link
                                    href={`/${course_id_string}/${lecture.id}?t=` + chapter.start_time}
                                >
                                    {chapter.name}
                                </Link>
                                {editMode && (
                                    <>
                                        <div className="flex-fill" />
                                        <EmbeddedOMFieldComponent
                                            object_type="chapter"
                                            object_id={chapter.id!}
                                            field_id="is_visible"
                                            field_type="boolean"
                                            initialValue={chapter.is_visible}
                                            className="me-2 align-self-center py-0"
                                        />
                                        <OMDelete
                                            object_type="chapter"
                                            object_id={chapter.id!}
                                            className="py-0"
                                        />
                                    </>
                                )}
                            </li>
                        ))}
    
                        {/*% if ismod() %}
                            <li>{{ moderator_editor(['lectures',lecture.id,'internal'], lecture.internal) }}</li>
                            <li>Sichtbar: {{ moderator_checkbox(['lectures',lecture.id,'visible'], lecture.visible) }}</li>
                            <li>Livestream geplant: {{ moderator_checkbox(['lectures',lecture.id,'live'], lecture.live) }}</li>
                            <li>Wird nicht aufgenommen: {{ moderator_checkbox(['lectures',lecture.id,'norecording'], lecture.norecording) }}</li>
                            <li>Hörsaal: {{ moderator_editor(['lectures',lecture.id,'place'], lecture.place) }} </li>
                        {% endif %*/}
                    </ul>
                    <ul className="col-sm-4 col-12 list-unstyled d-flex">
                        {showDownloadSourcesButton && (
                            <DownloadSources
                                media_sources={lecture.media_sources}
                                direction="down"
                                tabIndex="-1"
                            />
                        )}
                        {editMode && lecture.media_sources && (
                            <EditSources media_sources={lecture.media_sources} />
                        )}
    
                        <li className="flex-fill" />
                        <li>
                            {editMode && (
                                <>
                                    <OMHistory object_type="lecture" object_id={lecture.id!} />
                                    <OMEdit object_type="lecture" object_id={lecture.id!} />
                                    <OMDelete object_type="lecture" object_id={lecture.id!} />
                                </>
                            )}
                            <AuthenticationMethodIcons
                                authentication_methods={lecture.authentication_methods}
                            />
                        </li>
                    </ul>
                </>
            );
        } else {
            content = (
                <>
                    <div className="col-sm-2 col-12"></div>
                    <ul className="list-unstyled col-sm-3 col-12">
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="title"
                                field_type="string"
                                initialValue={lecture.title}
                            />
                            {/*{livelabel((lecture.live and lecture.time > datetime.now()-timedelta(days=1)), videos|selectattr("livehandle")|list|length)}*/}
                            {/*% if lecture.chapter_count|d(0) > 0 and ismod() %}
    					<span className="label label-info" data-toggle="tooltip" title="Nicht freigegebene Kapitel">{{ lecture.chapter_count }}</span>
    	{% endif %*/}
                        </li>
                    </ul>
                    <ul className="list-unstyled col-sm-3 col-12">
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="time"
                                field_type="datetime"
                                initialValue={lecture.time}
                            />
                        </li>
                    </ul>
                    <ul className="list-inline col-sm-4 col-12">
                        <li>
                            <EmbeddedOMFieldComponent
                                object_type="lecture"
                                object_id={lecture.id!}
                                field_id="description"
                                field_type="string"
                                initialValue={lecture.description}
                                allowMarkdown={true}
                            />
                        </li>
                    </ul>
                </>
            );
        }
    
        return (
            <li
                className={`list-group-item highlighting-list-item ${lecture.no_recording ? "text-muted" : ""}`}
                id={`lecture-${lecture.id}`}
                {...props}
            >
                <div className="row">{content}</div>
            </li>
        );
    }
    
    function ListingBody({ course }: { course: GetCourseResponse }) {
        const { editMode } = useEditMode();
    
        return (
            <div className="card mb-3">
                <div className="card-body">
                    <h5 className="card-title d-flex align-items-center">
                        Videos
                        <div className="flex-fill" />
                        {editMode && (
                            <>
                                <OMCreate
                                    object_type="lecture"
                                    parent_type="course"
                                    parent_id={course.id!}
                                >
                                    <button type="button" className="btn btn-secondary mx-2">
                                        <i className="bi bi-plus" />
                                        Neues Video
                                    </button>
                                </OMCreate>
                                <Link
                                    href={`/internal/import?course_id=${course.id}`}
                                    className="btn btn-secondary"
                                >
                                    <i className="bi bi-box-arrow-in-down" />
                                    {" Import"}
                                </Link>
                            </>
                        )}
                    </h5>
                    <ul className="list-group lectureslist">
                        {course
                            .lectures!.sort((a, b) => {
                                // time looks like this: 2015-10-20T12:15:00
                                return new Date(a.time).valueOf() - new Date(b.time).valueOf();
                            })
                            .map((lecture) => (
                                <LectureListItem
                                    key={lecture.id}
                                    lecture={lecture}
                                    course_id_string={course.id_string}
                                />
                            ))}
                    </ul>
                </div>
            </div>
        );
    }
    
    export default function CourseListing({
        courseData,
    }: {
        courseData: ResourceType<GetCourseResponse>;
    }) {
        const course = courseData.read()!;
    
        if (!course) return <>invalid course listing</>;
    
        return (
            <>
                <Title title={course.full_name} />
                <ListingHeader course={course} />
                <ListingBody course={course} />
            </>
        );
    }