Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: interactive courses #736

Merged
merged 58 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
805253c
add courses page
an-lee Jun 28, 2024
1c472d9
add api for courses
an-lee Jun 28, 2024
adc46dd
add course page
an-lee Jul 1, 2024
1f28727
update course type
an-lee Jul 1, 2024
12453c5
update client
an-lee Jul 1, 2024
76079fd
update course page
an-lee Jul 4, 2024
bff2e08
refactor courses pages
an-lee Jul 5, 2024
5fd3218
render chapter content
an-lee Jul 5, 2024
48e9191
shadow in course
an-lee Jul 5, 2024
9c96836
fix video handler
an-lee Jul 5, 2024
abfbf62
update style
an-lee Jul 7, 2024
9bf2c9c
mark finished examples
an-lee Jul 7, 2024
2dafadc
fix media player
an-lee Jul 8, 2024
ebc5d3b
update locale
an-lee Jul 8, 2024
d061fe2
finish chapter
an-lee Jul 8, 2024
4ddeecd
refactor
an-lee Jul 8, 2024
268c9a9
auto update chapter status
an-lee Jul 8, 2024
b1d2f0a
audo finish chapter
an-lee Jul 8, 2024
31d53a5
fix media provider
an-lee Jul 8, 2024
b0c1e2a
fix wavesurfer player
an-lee Jul 8, 2024
6c56ab2
update continue btn
an-lee Jul 8, 2024
c22c684
refactor chapters & page
an-lee Jul 8, 2024
b92e919
minor fix
an-lee Jul 8, 2024
c1ea021
fix undefined
an-lee Jul 8, 2024
43ad4b2
refactor
an-lee Jul 8, 2024
1982d12
refactor
an-lee Jul 8, 2024
08fc3c3
disable sentry in dev
an-lee Jul 8, 2024
1bd4268
clean markdown format before alignment
an-lee Jul 8, 2024
0d2aeb3
refactor
an-lee Jul 8, 2024
eac507e
fix regenerate
an-lee Jul 8, 2024
1ba99f0
fix transcription pre-process for `-` connector
an-lee Jul 8, 2024
dc29934
upgrade deps
an-lee Jul 8, 2024
114da32
handle no chapters
an-lee Jul 8, 2024
18d8f22
add llm chat api
an-lee Jul 10, 2024
d3a646b
create llm chat
an-lee Jul 10, 2024
f106682
display llm message
an-lee Jul 10, 2024
785b800
create message
an-lee Jul 10, 2024
f8870b8
handle error
an-lee Jul 10, 2024
c983f20
generate llm message
an-lee Jul 10, 2024
d9640b0
display llm datetime
an-lee Jul 10, 2024
afb4466
scroll to message
an-lee Jul 10, 2024
8db1d2a
tts for llm message
an-lee Jul 10, 2024
b16466c
add course provider
an-lee Jul 10, 2024
7063fe0
refactor
an-lee Jul 10, 2024
67e54df
translate llm message
an-lee Jul 10, 2024
384a97f
fix llm chat introduction
an-lee Jul 11, 2024
a44fa0f
refacotr
an-lee Jul 11, 2024
218b2bf
upgrade deps
an-lee Jul 11, 2024
05ebcb0
refactor style
an-lee Jul 11, 2024
1f0f727
handle undefined
an-lee Jul 11, 2024
d675049
fix posts
an-lee Jul 11, 2024
32e0646
update locales
an-lee Jul 11, 2024
a0350a8
update courses api
an-lee Jul 11, 2024
867e32e
add enrollments count
an-lee Jul 11, 2024
f7c45c0
upgrade yarn
an-lee Jul 11, 2024
e8ceff6
upgrade deps
an-lee Jul 11, 2024
0c5d13a
restore dep to fix package in mac
an-lee Jul 11, 2024
9899a93
upgrade deps
an-lee Jul 11, 2024
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
894 changes: 0 additions & 894 deletions .yarn/releases/yarn-4.2.1.cjs

This file was deleted.

626 changes: 313 additions & 313 deletions .yarn/releases/yarn-4.2.2.cjs → .yarn/releases/yarn-4.3.1.cjs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ nmHoistingLimits: workspaces

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.2.1.cjs
yarnPath: .yarn/releases/yarn-4.3.1.cjs
2 changes: 1 addition & 1 deletion 1000-hours/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"markdown-it-sup": "^2.0.0",
"mermaid": "^10.9.1",
"sass": "^1.77.6",
"vitepress": "^1.2.3",
"vitepress": "^1.3.0",
"vitepress-plugin-mermaid": "^2.0.16",
"vue": "^3.4.30"
},
Expand Down
43 changes: 22 additions & 21 deletions enjoy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@electron-forge/plugin-vite": "^7.4.0",
"@electron-forge/publisher-github": "^7.4.0",
"@electron/fuses": "^1.8.0",
"@playwright/test": "^1.45.0",
"@playwright/test": "^1.45.1",
"@tailwindcss/typography": "^0.5.13",
"@types/ahoy.js": "^0.4.2",
"@types/autosize": "^4.0.3",
Expand All @@ -52,40 +52,40 @@
"@types/intl-tel-input": "^18.1.4",
"@types/lodash": "^4.17.6",
"@types/mark.js": "^8.11.12",
"@types/node": "^20.14.9",
"@types/node": "^20.14.10",
"@types/rails__actioncable": "^6.1.11",
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@types/validator": "^13.12.0",
"@types/wavesurfer.js": "^6.0.12",
"@typescript-eslint/eslint-plugin": "^7.15.0",
"@typescript-eslint/parser": "^7.15.0",
"@typescript-eslint/eslint-plugin": "^7.16.0",
"@typescript-eslint/parser": "^7.16.0",
"@vitejs/plugin-react": "^4.3.1",
"autoprefixer": "^10.4.19",
"electron": "^31.1.0",
"electron": "^31.2.0",
"electron-playwright-helpers": "^1.7.1",
"eslint": "^9.6.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"flora-colossus": "^2.0.0",
"octokit": "^4.0.2",
"progress": "^2.0.3",
"tailwind-merge": "^2.3.0",
"tailwind-merge": "^2.4.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss": "^3.4.4",
"tailwindcss-animate": "^1.0.7",
"ts-node": "^10.9.2",
"tslib": "^2.6.3",
"typescript": "^5.5.3",
"vite": "^5.3.2",
"vite-plugin-static-copy": "^1.0.5",
"zx": "^8.1.3"
"vite": "^5.3.3",
"vite-plugin-static-copy": "^1.0.6",
"zx": "^8.1.4"
},
"dependencies": {
"@andrkrn/ffprobe-static": "^5.2.0",
"@electron-forge/publisher-s3": "^7.4.0",
"@hookform/resolvers": "^3.6.0",
"@langchain/community": "^0.2.16",
"@hookform/resolvers": "^3.9.0",
"@langchain/community": "^0.2.17",
"@langchain/google-genai": "^0.0.21",
"@mozilla/readability": "^0.5.0",
"@radix-ui/react-accordion": "^1.2.0",
Expand All @@ -112,9 +112,9 @@
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@rails/actioncable": "7.1.3",
"@sentry/electron": "^5.1.0",
"@sentry/electron": "^5.2.0",
"@uidotdev/usehooks": "^2.4.1",
"@vidstack/react": "^1.11.24",
"@vidstack/react": "^1.11.27",
"ahoy.js": "^0.4.4",
"autosize": "^6.0.1",
"axios": "^1.7.2",
Expand Down Expand Up @@ -143,37 +143,38 @@
"html-to-text": "^9.0.5",
"https-proxy-agent": "^7.0.5",
"i18next": "^23.11.5",
"intl-tel-input": "^23.1.0",
"intl-tel-input": "^23.3.0",
"js-md5": "^0.8.3",
"langchain": "^0.2.8",
"lodash": "^4.17.21",
"lucide-react": "^0.400.0",
"lucide-react": "^0.407.0",
"mark.js": "^8.11.1",
"microsoft-cognitiveservices-speech-sdk": "^1.38.0",
"next-themes": "^0.3.0",
"openai": "^4.52.2",
"openai": "^4.52.5",
"pitchfinder": "^2.3.2",
"postcss": "^8.4.38",
"proxy-agent": "^6.4.0",
"react": "^18.3.1",
"react-activity-calendar": "^2.2.11",
"react-dom": "^18.3.1",
"react-hook-form": "^7.52.0",
"react-hook-form": "^7.52.1",
"react-hotkeys-hook": "^4.5.0",
"react-i18next": "^14.1.2",
"react-markdown": "^9.0.1",
"react-router-dom": "^6.24.0",
"react-tooltip": "^5.27.0",
"react-resizable-panels": "^2.0.20",
"react-router-dom": "^6.24.1",
"react-tooltip": "^5.27.1",
"reflect-metadata": "^0.2.2",
"rimraf": "^5.0.7",
"rimraf": "^6.0.1",
"sequelize": "^6.37.3",
"sequelize-typescript": "^2.1.6",
"sonner": "^1.5.0",
"sqlite3": "^5.1.7",
"tailwind-scrollbar-hide": "^1.1.7",
"umzug": "^3.8.1",
"update-electron-app": "^3.0.0",
"wavesurfer.js": "^7.8.0",
"wavesurfer.js": "^7.8.1",
"zod": "^3.23.8",
"zod-to-json-schema": "^3.23.1"
}
Expand Down
104 changes: 104 additions & 0 deletions enjoy/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,4 +473,108 @@ export class Client {
params: decamelizeKeys(params),
});
}

courses(params?: {
language?: string;
page?: number;
items?: number;
query?: string;
}): Promise<
{
courses: CourseType[];
} & PagyResponseType
> {
return this.api.get("/api/courses", { params: decamelizeKeys(params) });
}

course(id: string): Promise<CourseType> {
return this.api.get(`/api/courses/${id}`);
}

createEnrollment(courseId: string): Promise<EnrollmentType> {
return this.api.post(`/api/enrollments`, decamelizeKeys({ courseId }));
}

courseChapters(
courseId: string,
params?: {
page?: number;
items?: number;
query?: string;
}
): Promise<
{
chapters: ChapterType[];
} & PagyResponseType
> {
return this.api.get(`/api/courses/${courseId}/chapters`, {
params: decamelizeKeys(params),
});
}

coursechapter(courseId: string, id: number | string): Promise<ChapterType> {
return this.api.get(`/api/courses/${courseId}/chapters/${id}`);
}

finishCourseChapter(courseId: string, id: number | string): Promise<void> {
return this.api.post(`/api/courses/${courseId}/chapters/${id}/finish`);
}

enrollments(params?: { page?: number; items?: number }): Promise<
{
enrollments: EnrollmentType[];
} & PagyResponseType
> {
return this.api.get("/api/enrollments", { params: decamelizeKeys(params) });
}

updateEnrollment(
id: string,
params: {
currentChapterId?: string;
}
): Promise<EnrollmentType> {
return this.api.put(`/api/enrollments/${id}`, decamelizeKeys(params));
}

createLlmChat(params: {
agentId: string;
agentType: string;
}): Promise<LLmChatType> {
return this.api.post("/api/chats", decamelizeKeys(params));
}

llmChat(id: string): Promise<LLmChatType> {
return this.api.get(`/api/chats/${id}`);
}

createLlmMessage(
chatId: string,
params: {
query: string;
agentId?: string;
agentType?: string;
}
): Promise<LlmMessageType> {
return this.api.post(
`/api/chats/${chatId}/messages`,
decamelizeKeys(params)
);
}

llmMessages(
chatId: string,
params: {
page?: number;
items?: number;
}
): Promise<
{
messages: LlmMessageType[];
} & PagyResponseType
> {
return this.api.get(`/api/chats/${chatId}/messages`, {
params: decamelizeKeys(params),
});
}
}
9 changes: 8 additions & 1 deletion enjoy/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
},
"sidebar": {
"home": "Home",
"courses": "Courses",
"community": "Community",
"audios": "Audios",
"videos": "Videos",
Expand Down Expand Up @@ -632,5 +633,11 @@
"noData": "No data",
"selectedFiles": "Selected files",
"moreOptions": "More options",
"lessOptions": "Less options"
"lessOptions": "Less options",
"previousChapter": "Previous",
"nextChapter": "Next",
"examples": "Examples",
"continueLearning": "Continue learning",
"enrollNow": "Enroll now",
"enrollments": "Enrollments"
}
9 changes: 8 additions & 1 deletion enjoy/src/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
},
"sidebar": {
"home": "主页",
"courses": "课程",
"community": "社区",
"audios": "音频",
"videos": "视频",
Expand Down Expand Up @@ -632,5 +633,11 @@
"noData": "没有数据",
"selectedFiles": "已选中文件",
"moreOptions": "更多选项",
"lessOptions": "更少选项"
"lessOptions": "更少选项",
"previousChapter": "上一章",
"nextChapter": "下一章",
"examples": "示例",
"continueLearning": "继续练习",
"enrollNow": "加入练习",
"enrollments": "参加的课程"
}
8 changes: 5 additions & 3 deletions enjoy/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import { updateElectronApp, UpdateSourceType } from "update-electron-app";

const logger = log.scope("main");

Sentry.init({
dsn: SENTRY_DSN,
});
if (app.isPackaged) {
Sentry.init({
dsn: SENTRY_DSN,
});
}

app.commandLine.appendSwitch("enable-features", "SharedArrayBuffer");

Expand Down
12 changes: 10 additions & 2 deletions enjoy/src/main/db/handlers/audios-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class AudiosHandler {
],
where,
...options,
group: ["Audio.id"],
});

if (!audios) {
Expand Down Expand Up @@ -116,14 +117,21 @@ class AudiosHandler {
id: string,
params: Attributes<Audio>
) {
const { name, description, metadata, language } = params;
const { name, description, metadata, language, coverUrl, source } = params;

const audio = await Audio.findByPk(id);

if (!audio) {
throw new Error(t("models.audio.notFound"));
}
return await audio.update({ name, description, metadata, language });
return await audio.update({
name,
description,
metadata,
language,
coverUrl,
source,
});
}

private async destroy(_event: IpcMainEvent, id: string) {
Expand Down
14 changes: 14 additions & 0 deletions enjoy/src/main/db/handlers/speeches-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,21 @@ import fs from "fs-extra";
import path from "path";
import settings from "@main/settings";
import { hashFile } from "@main/utils";
import { Attributes, WhereOptions } from "sequelize";

class SpeechesHandler {
private async findOne(
_event: IpcMainEvent,
where: WhereOptions<Attributes<Speech>>
) {
const speech = await Speech.findOne({ where });
if (!speech) {
return null;
}

return speech.toJSON();
}

private async create(
event: IpcMainEvent,
params: {
Expand Down Expand Up @@ -43,6 +56,7 @@ class SpeechesHandler {
}

register() {
ipcMain.handle("speeches-find-one", this.findOne);
ipcMain.handle("speeches-create", this.create);
}
}
Expand Down
5 changes: 3 additions & 2 deletions enjoy/src/main/db/handlers/videos-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class VideosHandler {
],
where,
...options,
group: ["Video.id"],
});
if (!videos) {
return [];
Expand Down Expand Up @@ -106,13 +107,13 @@ class VideosHandler {
id: string,
params: Attributes<Video>
) {
const { name, description, metadata, language } = params;
const { name, description, metadata, language, coverUrl, source } = params;

const video = await Video.findByPk(id);
if (!video) {
throw new Error(t("models.video.notFound"));
}
video.update({ name, description, metadata, language });
video.update({ name, description, metadata, language, coverUrl, source });
}

private async destroy(event: IpcMainEvent, id: string) {
Expand Down
2 changes: 1 addition & 1 deletion enjoy/src/main/db/models/audio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ export class Audio extends Model<Audio> {
},
});
if (existing) {
throw new Error(t("audioAlreadyAddedToLibrary", { file: filePath }));
return existing;
}

// Generate ID
Expand Down
Loading
Loading