Skip to content

Commit

Permalink
Merge pull request #28 from nattvara/show-failures
Browse files Browse the repository at this point in the history
Show failures
  • Loading branch information
nattvara authored Mar 8, 2023
2 parents bb8fa83 + f43a06c commit 3c20177
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 1 deletion.
5 changes: 5 additions & 0 deletions api/routers/lectures.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
get_lecture_by_public_id_and_language,
delete_lecture_course_relation,
get_all_denied_lectures,
get_all_failed_lectures,
get_unfinished_lectures,
find_course_code,
get_all_lectures,
Expand Down Expand Up @@ -86,6 +87,7 @@ def get_all(
summary: Union[bool, None] = None,
only_unfinished: Union[bool, None] = None,
only_denied: Union[bool, None] = None,
only_failed: Union[bool, None] = None,
include_denied: Union[bool, None] = False,
include_failed: Union[bool, None] = False,
random: Union[bool, None] = None,
Expand All @@ -95,6 +97,9 @@ def get_all(
elif only_denied:
include_denied = True
lectures = get_all_denied_lectures()
elif only_failed:
include_failed = True
lectures = get_all_failed_lectures()
else:
lectures = get_all_lectures()

Expand Down
12 changes: 12 additions & 0 deletions db/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@ def get_all_denied_lectures():
return out


def get_all_failed_lectures():
from db.models.lecture import Analysis
lectures = get_all_lectures()

out = []
for lecture in lectures:
if lecture.get_last_analysis().state == Analysis.State.FAILURE:
out.append(lecture)

return out


def get_unfinished_lectures():
from db.models.lecture import Analysis
lectures = get_all_lectures()
Expand Down
1 change: 1 addition & 0 deletions web-ui/.umirc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default defineConfig({
{ path: '/questions/lectures/:id/:language', component: 'questions' },
{ path: '/queue', component: 'queue' },
{ path: '/denied', component: 'denied' },
{ path: '/failures', component: 'failures' },
{ path: '/about', component: 'about' },

{ path: '*', component: '404' },
Expand Down
2 changes: 1 addition & 1 deletion web-ui/src/components/selector/lecture-adder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ export default function LectureAdder() {
</Paragraph>

<Paragraph className={styles.length_note}>
This process usually takes between 10 and 30 minutes, depending on the
This process usually takes between 5 and 15 minutes, depending on the
length of the lecture and how many other lectures are being watched.
</Paragraph>

Expand Down
10 changes: 10 additions & 0 deletions web-ui/src/components/tables/failures-table.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

.flag {
width: 100% !important;
height: 50px;
border-radius: 3px;
}

.logo {
border-radius: 3px;
}
157 changes: 157 additions & 0 deletions web-ui/src/components/tables/failures-table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { Table, Image, Typography } from 'antd';
import { notification } from 'antd';
import { useEffect, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import apiClient, { ServerErrorResponse, ServerResponse } from '@/http';
import { Lecture } from '@/components/lecture';
import styles from './denied-table.less';
import { ColumnsType } from 'antd/es/table';
import svFlag from '@/assets/flag-sv.svg';
import enFlag from '@/assets/flag-en.svg';
import kthLogo from '@/assets/kth.svg';
import youtubeLogo from '@/assets/youtube.svg';

const { Link } = Typography;

const UPDATE_INTERVAL = 5000;

const columns: ColumnsType<Lecture> = [
{
title: 'Source',
dataIndex: 'source',
render: (source: string) => {
let icon = '';
if (source === 'youtube') {
icon = youtubeLogo;
} else if (source === 'kth') {
icon = kthLogo;
}
return (
<Image src={icon} height={30} className={styles.logo} preview={false} />
);
},
},
{
title: 'Title',
dataIndex: 'title',
},
{
title: 'Analysis',
dataIndex: 'combined_public_id_and_lang',
render: (combined_public_id_and_lang: string) => (
<>
<Link
href={`/analyse/lectures/${combined_public_id_and_lang}`}
type="dashed"
>
View Progress
</Link>
</>
),
},
{
title: 'Content Link',
dataIndex: 'content_link',
render: (content_link: string) => (
<>
<Link href={content_link} target="_blank">
{content_link}
</Link>
</>
),
},
{
title: 'Language',
dataIndex: 'language',
render: (val: string) => {
let flagIcon = '';
if (val === 'sv') {
flagIcon = svFlag;
} else if (val === 'en') {
flagIcon = enFlag;
}
return (
<Image
src={flagIcon}
height={30}
className={styles.flag}
preview={false}
/>
);
},
},
{
title: 'Added At',
dataIndex: 'created_at',
render: (val: string) => {
const d = new Date(val);
const date = d.toDateString();
const time = d.toLocaleTimeString('sv');
return (
<>
{date}, {time}
</>
);
},
},
{
title: 'Progress',
dataIndex: 'overall_progress',
render: (val: string) => <>{val}%</>,
},
];

interface LectureResponse extends ServerResponse {
data: Lecture[];
}

export default function FailuresTable() {
const [lectures, setLectures] = useState<Lecture[]>([]);
const [notificationApi, contextHolder] = notification.useNotification();

const { mutate: fetchLectures } = useMutation(
async () => {
return await apiClient.get(`/lectures?summary=true&only_failed=true`);
},
{
onSuccess: (res: LectureResponse) => {
const result = {
status: res.status + '-' + res.statusText,
headers: res.headers,
data: res.data,
};
for (let i = 0; i < res.data.length; i++) {
const lecture = res.data[i];
lecture.combined_public_id_and_lang = `${lecture.public_id}/${lecture.language}`;
lecture['key'] = lecture.combined_public_id_and_lang;
}
setLectures(result.data as Lecture[]);
},
onError: (err: ServerErrorResponse) => {
notificationApi['error']({
message: 'Failed to get lectures',
description: err.response.data.detail,
});
},
}
);

useEffect(() => {
fetchLectures();
}, [fetchLectures]);

useEffect(() => {
const interval = setInterval(() => {
fetchLectures();
}, UPDATE_INTERVAL);

return () => clearInterval(interval);
}, [fetchLectures]);

return (
<>
{contextHolder}
<Table columns={columns} dataSource={lectures} />
</>
);
}
24 changes: 24 additions & 0 deletions web-ui/src/pages/failures.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Frame from '@/components/main/frame';
import DeniedTable from '@/components/tables/failures-table';
import { registerPageLoad } from '@/matomo';
import { useEffect } from 'react';
import { Typography } from 'antd';

const { Title } = Typography;

export default function FailuresPage() {
useEffect(() => {
registerPageLoad();
}, []);

return (
<>
<Frame>
<>
<Title level={3}>Lectures that has failed</Title>
<DeniedTable />
</>
</Frame>
</>
);
}

0 comments on commit 3c20177

Please sign in to comment.