Compare commits

...

131 Commits

Author SHA1 Message Date
37d408f762 Merge branch 'develop' of https://git.nefor.net/MIDNIGHT/enlight-lms into develop 2026-03-09 11:00:49 +00:00
6d7c91ceeb Before update v2.46.0 2026-03-09 10:54:44 +00:00
9041101505 Обновить README.md 2026-03-09 02:10:09 +03:00
Nicolai
d3fda0be37 StudentProfile new design 2026-03-08 23:31:54 +03:00
Nicolai
41de21201e LaderBoard design update 2026-03-08 12:48:34 +03:00
Alexandrina-Kuzeleva
005f85c34f UPD 7
- add links in Mobile
- switch off InstalPromt
2026-01-28 11:06:55 +03:00
Alexandrina-Kuzeleva
6bb6125e81 Update ParentProfile.vue 2025-12-05 16:45:49 +03:00
Alexandrina-Kuzeleva
4da2b844e8 Update ParentProfile.vue 2025-12-05 16:44:39 +03:00
Alexandrina-Kuzeleva
eba1923b7c Update ParentProfile.vue 2025-12-05 16:41:05 +03:00
Alexandrina-Kuzeleva
f28823dbe9 TEST UPD
-add parentprofile
2025-12-05 16:33:32 +03:00
Alexandrina-Kuzeleva
5d122bca7d upd 2025-12-05 16:22:23 +03:00
Alexandrina-Kuzeleva
ef4321586c TEST UPD 2025-12-05 16:13:38 +03:00
Alexandrina-Kuzeleva
336511dcd5 TEST UPD
- add traslation
- bug of doesntexist
2025-12-05 13:17:01 +03:00
Alexandrina-Kuzeleva
d73b6f9026 TEST UPD
- /api/method/frappe.client.get DoesNotExistError
2025-12-05 12:51:37 +03:00
Alexandrina-Kuzeleva
e959c0172d TEST UPD
-schoolchildprofile bug of learn_subjects
-front
2025-12-05 11:59:43 +03:00
Alexandrina-Kuzeleva
a15767c14f TEST UPD
-some traslation
-trest schoolchildrenprofile
-frontworks
2025-12-04 18:57:34 +03:00
Alexandrina-Kuzeleva
20b1743223 TEST UPD
- course creator front
- tg icon
2025-12-04 16:06:39 +03:00
Alexandrina-Kuzeleva
a89930fae6 TEST UPD
-translation
-front works
2025-12-04 15:29:50 +03:00
Alexandrina-Kuzeleva
60e81a921e TEST UPD
- translate leader board
2025-12-04 15:13:11 +03:00
Alexandrina-Kuzeleva
36f75beea9 TEST UPD
-test bio
2025-12-04 15:10:29 +03:00
Alexandrina-Kuzeleva
01a9eab73d TEST UPD
- front works
2025-12-04 14:17:57 +03:00
Alexandrina-Kuzeleva
a4eff5ae38 TEST UPD 2025-12-03 22:52:16 +03:00
Alexandrina-Kuzeleva
46b5495167 TEST UPD
- tranlation My Points
- front works
2025-12-03 22:44:25 +03:00
Alexandrina-Kuzeleva
7c9ef2a702 TEST UPD
-front works for student profile
2025-12-03 22:10:43 +03:00
Alexandrina-Kuzeleva
ee9aed6bbc Update Test.vue 2025-11-28 11:00:45 +03:00
Alexandrina-Kuzeleva
eb4cf6e2db Update Test.vue 2025-11-28 10:57:54 +03:00
Alexandrina-Kuzeleva
c6ad6b495c Update api.py 2025-11-28 10:50:48 +03:00
Alexandrina-Kuzeleva
5499a86854 Update Test.vue 2025-11-28 10:46:51 +03:00
Alexandrina-Kuzeleva
627ccd8214 Update Test.vue 2025-11-28 10:42:35 +03:00
Alexandrina-Kuzeleva
e760d59d9f Update Test.vue
-front works
- fix bonus points
2025-11-28 10:39:04 +03:00
Alexandrina-Kuzeleva
e76858121f TEST UPD
- front works
2025-11-28 10:27:03 +03:00
Alexandrina-Kuzeleva
34f1d02803 TEST UPD
- add roles permision in api method
2025-11-28 10:11:30 +03:00
Alexandrina-Kuzeleva
64610050ca TEST UPD
- current user card
2025-11-27 16:50:33 +03:00
Alexandrina-Kuzeleva
f5bd52a94d Update Test.vue 2025-11-26 18:17:17 +03:00
Alexandrina-Kuzeleva
ce603cac1e Update Test.vue 2025-11-26 18:09:45 +03:00
Alexandrina-Kuzeleva
3108235521 TEST UPD 2025-11-26 17:51:42 +03:00
Alexandrina-Kuzeleva
280aaecf76 Update Test.vue 2025-11-26 17:41:18 +03:00
Alexandrina-Kuzeleva
ba0bb1eabc Update Test.vue 2025-11-26 17:36:32 +03:00
Alexandrina-Kuzeleva
73d0755249 Update Test.vue 2025-11-26 17:27:33 +03:00
Alexandrina-Kuzeleva
4d93dcb9b4 TEST 2025-11-26 17:21:35 +03:00
Alexandrina-Kuzeleva
1fc9b8e279 TEST 2025-11-26 17:15:09 +03:00
Alexandrina-Kuzeleva
c6d05111cc Update LeaderBoard.vue 2025-11-25 15:34:35 +03:00
Alexandrina-Kuzeleva
8fa3d8ba4a Update LeaderBoard.vue 2025-11-25 15:30:22 +03:00
Alexandrina-Kuzeleva
c5317beb3f TEST UPD 2025-11-25 15:28:23 +03:00
Alexandrina-Kuzeleva
7d82e36790 Update Test.vue 2025-11-25 15:18:58 +03:00
Alexandrina-Kuzeleva
f39867b0e2 Update Test.vue 2025-11-25 15:12:07 +03:00
Alexandrina-Kuzeleva
54cef503ad TEST UPD
- add test page
2025-11-25 15:08:07 +03:00
Alexandrina-Kuzeleva
ce51371e62 TEST UPD
- roles
2025-11-25 13:14:13 +03:00
Alexandrina-Kuzeleva
7aabbbd497 Update LeaderBoard.vue 2025-11-25 13:07:26 +03:00
Alexandrina-Kuzeleva
02b89ea137 TEST UPD
- debug
- user role
2025-11-25 13:00:10 +03:00
Alexandrina-Kuzeleva
119a48f3a3 Update LeaderBoard.vue 2025-11-25 12:37:50 +03:00
Alexandrina-Kuzeleva
3146a0354c Update LeaderBoard.vue 2025-11-25 12:34:06 +03:00
Alexandrina-Kuzeleva
8e895a9890 TEST UPD
- debug
2025-11-25 11:55:43 +03:00
Alexandrina-Kuzeleva
ac436cbf79 TEST UPD
- roles
2025-11-25 11:23:15 +03:00
Alexandrina-Kuzeleva
4363aa7734 TEST UPD
- дурацкие названия файлов ненавижу
2025-11-25 11:10:29 +03:00
Alexandrina-Kuzeleva
a65cb073b5 TEST UPD
- try to add imgs
2025-11-25 10:58:57 +03:00
Alexandrina-Kuzeleva
a3b9e4f7b2 TEST UPD
- add front
2025-11-25 10:51:18 +03:00
Alexandrina-Kuzeleva
ebde8a0171 TEST UPD
- try to do anthore logic of script
2025-11-25 10:26:39 +03:00
Alexandrina-Kuzeleva
684299ac3b Update LeaderBoard.vue 2025-11-21 16:47:34 +03:00
Alexandrina-Kuzeleva
c449aef7ae Update LeaderBoard.vue 2025-11-21 16:41:05 +03:00
Alexandrina-Kuzeleva
879a27ed0a TEST UPD
- debug
2025-11-21 16:37:03 +03:00
Alexandrina-Kuzeleva
107e7a4e31 TEST UPD
- test leader board
2025-11-21 16:28:33 +03:00
Alexandrina-Kuzeleva
fa0325106a Update MyPoints.vue 2025-11-21 15:57:41 +03:00
Alexandrina-Kuzeleva
bbfce9363f TEST UPD
- font works
2025-11-21 15:47:58 +03:00
Alexandrina-Kuzeleva
10a6280b78 TEST UPD
- change weekly sum
2025-11-21 15:37:08 +03:00
Alexandrina-Kuzeleva
08e8724b4c UPD 6.1
- delete func
2025-11-21 15:29:07 +03:00
Alexandrina-Kuzeleva
555c7e4e2d TEST UPD
- add today weekly points
2025-11-21 15:18:41 +03:00
Alexandrina-Kuzeleva
3673026a33 TEST UPD
- add load more
2025-11-21 14:50:00 +03:00
Alexandrina-Kuzeleva
cd565ec160 Update MyPoints.vue 2025-11-20 16:44:05 +03:00
Alexandrina-Kuzeleva
bdcbae03ef TEST UPD
- front
2025-11-20 16:40:42 +03:00
Alexandrina-Kuzeleva
296234a093 TEST UPD
- remove upd
2025-11-20 16:36:39 +03:00
Alexandrina-Kuzeleva
10c0955c6c TEST UPD
- add load more
- add front
2025-11-20 16:28:21 +03:00
Alexandrina-Kuzeleva
8ba2bfda63 TEXT UPD
- front
2025-11-20 16:17:10 +03:00
Alexandrina-Kuzeleva
cb06cc53c2 TEST UPD
- front works
2025-11-20 15:53:36 +03:00
Alexandrina-Kuzeleva
826828ba30 TEST UPD
- text-white remove
2025-11-20 15:34:24 +03:00
Alexandrina-Kuzeleva
22de38c72b TEST UPD
- try to fix bug of sum points
2025-11-20 15:23:59 +03:00
Alexandrina-Kuzeleva
0037c01beb TEST UPD
- problem of date
2025-11-20 13:35:11 +03:00
Alexandrina-Kuzeleva
fb17c666a9 TEST UPD
- add my points
2025-11-20 13:29:09 +03:00
Alexandrina-Kuzeleva
2c32fac1f2 TEST UPD
- try to get resource
2025-11-20 13:17:23 +03:00
Alexandrina-Kuzeleva
3f0b00decd TEST UPD
- another logic of download user and data
2025-11-20 13:06:55 +03:00
Alexandrina-Kuzeleva
160c7863f0 TEST UPD
- My points page
2025-11-20 12:56:28 +03:00
Alexandrina-Kuzeleva
c4d185f2d6 UPD 6
- add locale file, ru
- AI in Quizes, now it is off
- bug of translation in Courses
- fronted of tags in Course Detail in Mobile ver
- another locale bugs
2025-11-20 12:44:53 +03:00
Alexandrina-Kuzeleva
6b13b1231a UPD 5
- add Profiles for Student, Schoolchildren, Parent, Course Creator
2025-11-12 17:18:03 +03:00
Alexandrina-Kuzeleva
661137d500 UPD 4.1
- error
2025-11-11 17:38:06 +03:00
Alexandrina-Kuzeleva
962dcc1ce9 UPD 4
- add MobileLayout changes
2025-11-11 17:27:09 +03:00
Alexandrina-Kuzeleva
655df62d6c UPD 3.1
- add imports in ProfileAbout
2025-11-10 17:34:30 +03:00
Alexandrina-Kuzeleva
d827a10c84 UPD 3
- checked and fixed problems: timer in lesson, sing-up, page length in courses
- add Points and Courses in ProfileAbout
NEW:
- add icon for RuTube
2025-11-10 17:28:26 +03:00
Alexandrina-Kuzeleva
25c640fabb UPD 2
- add RuTube servise
2025-11-10 17:00:10 +03:00
Alexandrina-Kuzeleva
0cb8d21290 UPD 1
- add all AppSidebar links that used
- add singup form
2025-11-10 12:27:28 +03:00
Jannat Patel
7a47591967 Merge pull request #1819 from rehanrehman389/misc-fix
fix: UI improvements
2025-11-06 16:43:28 +05:30
Jannat Patel
6931ca27c3 Merge pull request #1824 from pateljannat/issues-145
fix: roles, permission and access on profile page
2025-11-06 12:51:45 +05:30
Jannat Patel
d00d2de1cc fix: export livecodeURL from settings store 2025-11-06 12:28:27 +05:30
Jannat Patel
b1be568991 fix: removed uncalled function 2025-11-06 12:23:18 +05:30
Jannat Patel
28be3891d2 fix: roles, permission and access on profile page 2025-11-06 12:21:12 +05:30
Jannat Patel
27d2297e2b Merge pull request #1823 from pateljannat/issues-144
fix: misc improvements
2025-11-05 12:50:21 +05:30
Jannat Patel
7212ddd5c5 fix: evaluators and modetators can now see schedule of other evaluators 2025-11-05 12:34:40 +05:30
Jannat Patel
f4e9ac5bf1 fix: IPhone PWA install prompt 2025-11-05 11:59:45 +05:30
Jannat Patel
8fec484d66 Merge pull request #1818 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-11-04 13:14:49 +05:30
Jannat Patel
bcf781c37b chore: Serbian (Latin) translations 2025-11-03 00:37:46 +05:30
Jannat Patel
d8a8e689d0 chore: Bosnian translations 2025-11-03 00:37:45 +05:30
Jannat Patel
a844b95de3 chore: Burmese translations 2025-11-03 00:37:44 +05:30
Jannat Patel
ece885f973 chore: Thai translations 2025-11-03 00:37:42 +05:30
Jannat Patel
66dd30604b chore: Tamil translations 2025-11-03 00:37:41 +05:30
Jannat Patel
d0f0f4905c chore: Indonesian translations 2025-11-03 00:37:40 +05:30
Jannat Patel
c9cb6702b6 chore: Portuguese, Brazilian translations 2025-11-03 00:37:39 +05:30
Jannat Patel
1ddb980242 chore: Vietnamese translations 2025-11-03 00:37:37 +05:30
Jannat Patel
94b626a4d2 chore: Chinese Simplified translations 2025-11-03 00:37:36 +05:30
Jannat Patel
d2a011462d chore: Turkish translations 2025-11-03 00:37:35 +05:30
Jannat Patel
4c34926af0 chore: Serbian (Cyrillic) translations 2025-11-03 00:37:34 +05:30
Jannat Patel
ce35cd1009 chore: Russian translations 2025-11-03 00:37:32 +05:30
Jannat Patel
56d072bd06 chore: Portuguese translations 2025-11-03 00:37:31 +05:30
Jannat Patel
5d336ef669 chore: Polish translations 2025-11-03 00:37:30 +05:30
Jannat Patel
b47c59eac1 chore: Dutch translations 2025-11-03 00:37:29 +05:30
Jannat Patel
87285db361 chore: Italian translations 2025-11-03 00:37:27 +05:30
Jannat Patel
84312e498c chore: Hungarian translations 2025-11-03 00:37:26 +05:30
Jannat Patel
bd763d9462 chore: German translations 2025-11-03 00:37:25 +05:30
Jannat Patel
a00e66f786 chore: Czech translations 2025-11-03 00:37:24 +05:30
Jannat Patel
78c7b52088 chore: Arabic translations 2025-11-03 00:37:23 +05:30
Jannat Patel
c3a5bee993 chore: Spanish translations 2025-11-03 00:37:21 +05:30
Jannat Patel
c2b5b7c3e2 chore: French translations 2025-11-03 00:37:20 +05:30
Jannat Patel
3992f00353 chore: Persian translations 2025-11-03 00:37:19 +05:30
Jannat Patel
97d853e0d3 chore: Danish translations 2025-11-03 00:37:18 +05:30
Jannat Patel
f786cec75f chore: Norwegian Bokmal translations 2025-11-03 00:37:16 +05:30
Jannat Patel
07cd08b55e chore: Croatian translations 2025-11-03 00:37:15 +05:30
Jannat Patel
ca42faf14a chore: Swedish translations 2025-11-03 00:37:14 +05:30
Rehan Ansari
87f5b68279 fix: UI improvements 2025-11-02 13:43:25 +05:30
Jannat Patel
6b31edb687 chore: Esperanto translations 2025-10-31 23:03:40 +05:30
Jannat Patel
6a64048bb6 Merge pull request #1817 from frappe/pot_develop_2025-10-31
chore: update POT file
2025-10-31 22:03:56 +05:30
frappe-pr-bot
6cf069ee6a chore: update POT file 2025-10-31 16:04:36 +00:00
Jannat Patel
3b74bba6ab Merge pull request #1813 from rehanrehman389/missing-type-fix
fix: add missing type prop
2025-10-30 11:13:31 +05:30
Rehan Ansari
8689788523 fix: add missing type prop 2025-10-29 21:41:48 +05:30
86 changed files with 11101 additions and 4298 deletions

178
README.md
View File

@@ -1,178 +0,0 @@
<div align="center" markdown="1">
<img src=".github/lms-logo.png" alt="Frappe Learning logo" width="80" height="80"/>
<h1>Frappe Learning</h1>
**Easy to use, open source, Learning Management System**
![Tests](https://img.shields.io/endpoint?url=https://dashboard.cypress.io/badge/simple/vandxn/main&style=flat&logo=cypress)
</div>
<div align="center">
<img src=".github/hero.png?v=5" alt="Hero Image" width="72%" />
</div>
<br />
<div align="center">
<a href="https://frappe.io/learning">Website</a>
-
<a href="https://docs.frappe.io/learning">Documentation</a>
</div>
## Frappe Learning
Frappe Learning is an easy-to-use learning system that helps you bring structure to your content.
### Motivation
In 2021, we were looking for a Learning Management System to launch [Mon.School](https://mon.school) for FOSS United. We checked out Moodle, but it didnt feel right. The forms were unnecessarily lengthy and the UI was confusing. It shouldn't be this hard to create a course right? So I started making a learning system for Mon.School which soon became a product in itself. The aim is to have a simple platform that anyone can use to launch a course of their own and make knowledge sharing easier.
### Key Features
- **Structured Learning**: Design a course with a 3-level hierarchy, where your courses have chapters and you can group your lessons within these chapters. This ensures that the context of the lesson is set by the chapter.
- **Live Classes**: Group learners into batches based on courses and duration. You can then create Zoom live class for these batches right from the app. Learners get to see the list of live classes they have to take as a part of this batch.
- **Quizzes and Assignments**: Create quizzes where questions can have single-choice, multiple-choice options, or can be open ended. Instructors can also add assignments which learners can submit as PDF's or Documents.
- **Getting Certified**: Once a learner has completed the course or batch, you can grant them a certificate. The app provides an inbuilt certificate template. You can use this or else create a template of your own and use that instead.
<details>
<summary>View Screenshots</summary>
![Batch](.github/batch.png)
<div align="center">
<sub>
Create batches to group your learners
</sub>
</div>
<br>
![Quiz](.github/quiz.png)
<div align="center">
<sub>
Evaluate their knowledge by quizzes
</sub>
</div>
<br>
![Cerficicate](.github/certificate.png)
<div align="center">
<sub>
Autenticate their work with certification
</sub>
</div>
</details>
### Under the Hood
- [**Frappe Framework**](https://github.com/frappe/frappe): A full-stack web application framework.
- [**Frappe UI**](https://github.com/frappe/frappe-ui): A Vue-based UI library, to provide a modern user interface.
## Production Setup
### Managed Hosting
You can try [Frappe Cloud](https://frappecloud.com), a simple, user-friendly and sophisticated [open-source](https://github.com/frappe/press) platform to host Frappe applications with peace of mind.
It takes care of installation, setup, upgrades, monitoring, maintenance and support of your Frappe deployments. It is a fully featured developer platform with an ability to manage and control multiple Frappe deployments.
<div>
<a href="https://frappecloud.com/lms/signup" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/try-on-fc-white.png">
<img src="https://frappe.io/files/try-on-fc-black.png" alt="Try on Frappe Cloud" height="28" />
</picture>
</a>
</div>
### Self Hosting
Follow these steps to set up Frappe Learning in production:
**Step 1**: Download the easy install script
```bash
wget https://frappe.io/easy-install.py
```
**Step 2**: Run the deployment command
```bash
python3 ./easy-install.py deploy \
--project=learning_prod_setup \
--email=your_email.example.com \
--image=ghcr.io/frappe/lms \
--version=stable \
--app=lms \
--sitename subdomain.domain.tld
```
Replace the following parameters with your values:
- `your_email.example.com`: Your email address
- `subdomain.domain.tld`: Your domain name where Learning will be hosted
The script will set up a production-ready instance of Frappe Learning with all the necessary configurations in about 5 minutes.
**Note:** To avoid a `404 Page Not Found` error:
- If hosting on a **public server**, make sure your DNS **A record** points to your server's IP.
- If hosting **locally**, map your domain to `127.0.0.1` in your `/etc/hosts` file:
## Development Setup
### Docker
You need Docker, docker-compose and git setup on your machine. Refer [Docker documentation](https://docs.docker.com/). After that, follow below steps:
**Step 1**: Setup folder and download the required files
mkdir frappe-learning
cd frappe-learning
# Download the docker-compose file
wget -O docker-compose.yml https://raw.githubusercontent.com/frappe/lms/develop/docker/docker-compose.yml
# Download the setup script
wget -O init.sh https://raw.githubusercontent.com/frappe/lms/develop/docker/init.sh
**Step 2**: Run the container and daemonize it
docker compose up -d
**Step 3**: The site [http://lms.localhost:8000/lms](http://lms.localhost:8000/lms) should now be available. The default credentials are:
- Username: Administrator
- Password: admin
### Local
To setup the repository locally follow the steps mentioned below:
1. Install bench and setup a `frappe-bench` directory by following the [Installation Steps](https://frappeframework.com/docs/user/en/installation)
1. Start the server by running `bench start`
1. In a separate terminal window, create a new site by running `bench new-site learning.test`
1. Map your site to localhost with the command `bench --site learning.test add-to-hosts`
1. Get the Learning app. Run `bench get-app https://github.com/frappe/lms`
1. Run `bench --site learning.test install-app lms`.
1. Now open the URL `http://learning.test:8000/lms` in your browser, you should see the app running
## Learn and connect
- [Telegram Public Group](https://t.me/frappelms)
- [Discuss Forum](https://discuss.frappe.io/c/lms/70)
- [Documentation](https://docs.frappe.io/learning)
- [YouTube](https://www.youtube.com/channel/UCn3bV5kx77HsVwtnlCeEi_A)
<br>
<br>
<div align="center" style="padding-top: 0.75rem;">
<a href="https://frappe.io" target="_blank">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://frappe.io/files/Frappe-white.png">
<img src="https://frappe.io/files/Frappe-black.png" alt="Frappe Technologies" height="28"/>
</picture>
</a>
</div>

View File

@@ -10,7 +10,6 @@ declare module 'vue' {
export interface GlobalComponents {
Annoucements: typeof import('./src/components/Annoucements.vue')['default']
AnnouncementModal: typeof import('./src/components/Modals/AnnouncementModal.vue')['default']
AppHeader: typeof import('./src/components/AppHeader.vue')['default']
Apps: typeof import('./src/components/Apps.vue')['default']
AppSidebar: typeof import('./src/components/AppSidebar.vue')['default']
AssessmentModal: typeof import('./src/components/Modals/AssessmentModal.vue')['default']
@@ -73,7 +72,6 @@ declare module 'vue' {
InviteIcon: typeof import('./src/components/Icons/InviteIcon.vue')['default']
JobApplicationModal: typeof import('./src/components/Modals/JobApplicationModal.vue')['default']
JobCard: typeof import('./src/components/JobCard.vue')['default']
LayoutHeader: typeof import('./src/components/LayoutHeader.vue')['default']
LessonContent: typeof import('./src/components/LessonContent.vue')['default']
LessonHelp: typeof import('./src/components/LessonHelp.vue')['default']
Link: typeof import('./src/components/Controls/Link.vue')['default']

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 512.001 512.001" xml:space="preserve">
<g>
<path style="fill:#A67C52;" d="M84.096,436.178l-49.312,37.686c-7.54,5.762-8.981,16.547-3.219,24.087
c3.383,4.425,8.494,6.751,13.666,6.751c3.638,0,7.306-1.151,10.421-3.532l49.312-37.686c7.54-5.762,8.981-16.547,3.219-24.087
C102.421,431.858,91.637,430.416,84.096,436.178z"/>
<path style="fill:#A67C52;" d="M441.194,473.864l-49.312-37.686c-7.541-5.762-18.325-4.32-24.087,3.219
c-5.762,7.541-4.321,18.325,3.219,24.087l49.312,37.686c3.115,2.38,6.782,3.532,10.421,3.532c5.171,0,10.284-2.326,13.665-6.751
C450.175,490.411,448.734,479.627,441.194,473.864z"/>
</g>
<path style="fill:#DBAD75;" d="M237.989,36.024c-131.227,0-237.989,106.761-237.989,237.989s106.761,237.989,237.989,237.989
S475.978,405.24,475.978,274.012S369.216,36.024,237.989,36.024z"/>
<path style="fill:#EABD81;" d="M237.989,36.024c-131.227,0-237.989,106.761-237.989,237.989s106.761,237.989,237.989,237.989V36.024
z"/>
<path style="fill:#BC2A46;" d="M237.989,80.411c-106.752,0-193.601,86.849-193.601,193.601s86.849,193.601,193.601,193.601
s193.601-86.849,193.601-193.601S344.742,80.411,237.989,80.411z"/>
<path style="fill:#D62D46;" d="M237.989,80.411c-106.752,0-193.601,86.849-193.601,193.601s86.849,193.601,193.601,193.601V80.411z"
/>
<path style="fill:#DBAD75;" d="M237.989,142.771c-72.367,0-131.241,58.874-131.241,131.241s58.874,131.241,131.241,131.241
S369.23,346.379,369.23,274.012S310.355,142.771,237.989,142.771z"/>
<path style="fill:#EABD81;" d="M237.989,142.771c-72.367,0-131.241,58.874-131.241,131.241s58.874,131.241,131.241,131.241V142.771z
"/>
<path style="fill:#BC2A46;" d="M237.989,209.763c-35.427,0-64.248,28.821-64.248,64.248s28.821,64.248,64.248,64.248
s64.248-28.821,64.248-64.248S273.416,209.763,237.989,209.763z"/>
<path style="fill:#D62D46;" d="M237.989,209.763c-35.427,0-64.248,28.821-64.248,64.248s28.821,64.248,64.248,64.248V209.763z"/>
<path style="fill:#CFCDD6;" d="M237.989,291.196c-4.398,0-8.796-1.677-12.15-5.034c-6.711-6.711-6.711-17.59,0-24.301
L448.687,39.014c6.71-6.711,17.59-6.711,24.301,0s6.711,17.59,0,24.301L250.14,286.162
C246.784,289.519,242.386,291.196,237.989,291.196z"/>
<path style="fill:#DEE1E7;" d="M237.989,291.196c-4.398,0-8.796-1.677-12.15-5.034c-6.711-6.711-6.711-17.59,0-24.301
l106.576-106.576l24.301,24.301L250.14,286.162C246.784,289.519,242.386,291.196,237.989,291.196z"/>
<path style="fill:#39B7B6;" d="M457.533,105.266h-33.615c-9.49,0-17.184-7.694-17.184-17.184V54.467
c0-9.49,7.694-17.184,17.184-17.184s17.184,7.694,17.184,17.184v16.432h16.431c9.49,0,17.184,7.694,17.184,17.184
S467.023,105.266,457.533,105.266z"/>
<path style="fill:#FBB03B;" d="M476.175,86.623h-33.614c-9.49,0-17.184-7.694-17.184-17.184V35.825
c0-9.49,7.694-17.184,17.184-17.184s17.184,7.694,17.184,17.184v16.431h16.431c9.49,0,17.184,7.694,17.184,17.184
S485.665,86.623,476.175,86.623z"/>
<path style="fill:#39B7B6;" d="M494.817,67.982h-33.614c-9.49,0-17.184-7.694-17.184-17.184V17.184
c0-9.49,7.694-17.184,17.184-17.184s17.184,7.694,17.184,17.184v16.431h16.431c9.49,0,17.184,7.694,17.184,17.184
S504.308,67.982,494.817,67.982z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--noto" preserveAspectRatio="xMidYMid meet"><path d="M68.05 7.23l13.46 30.7a7.047 7.047 0 0 0 5.82 4.19l32.79 2.94c3.71.54 5.19 5.09 2.5 7.71l-24.7 20.75c-2 1.68-2.91 4.32-2.36 6.87l7.18 33.61c.63 3.69-3.24 6.51-6.56 4.76L67.56 102a7.033 7.033 0 0 0-7.12 0l-28.62 16.75c-3.31 1.74-7.19-1.07-6.56-4.76l7.18-33.61c.54-2.55-.36-5.19-2.36-6.87L5.37 52.78c-2.68-2.61-1.2-7.17 2.5-7.71l32.79-2.94a7.047 7.047 0 0 0 5.82-4.19l13.46-30.7c1.67-3.36 6.45-3.36 8.11-.01z" fill="#fdd835"></path><path d="M67.07 39.77l-2.28-22.62c-.09-1.26-.35-3.42 1.67-3.42c1.6 0 2.47 3.33 2.47 3.33l6.84 18.16c2.58 6.91 1.52 9.28-.97 10.68c-2.86 1.6-7.08.35-7.73-6.13z" fill="#ffff8d"></path><path d="M95.28 71.51L114.9 56.2c.97-.81 2.72-2.1 1.32-3.57c-1.11-1.16-4.11.51-4.11.51l-17.17 6.71c-5.12 1.77-8.52 4.39-8.82 7.69c-.39 4.4 3.56 7.79 9.16 3.97z" fill="#f4b400"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -3,7 +3,7 @@
<Layout class="isolate text-base">
<router-view />
</Layout>
<InstallPrompt v-if="isMobile" />
<!--<InstallPrompt v-if="isMobile" />-->
<Dialogs />
</FrappeUIProvider>
</template>

View File

@@ -659,6 +659,104 @@ const setUpOnboarding = () => {
}
}
const addMyPoints = () => {
const roles = userResource.data?.roles || []
if (roles.includes('LMS Student') || roles.includes('LMS Schoolchild')) {
sidebarLinks.value.push({
label: __('My points'),
icon: 'Award',
to: 'MyPoints',
activeFor: [],
})
}
}
const addLeaderBoard = () => {
if (user) {
sidebarLinks.value.push({
label: __('Leader Board'),
icon: 'Trophy',
to: 'LeaderBoard',
activeFor: [],
})
}
}
const addChatGPT = () => {
const roles = userResource.data?.roles || []
let URL = ''
let nameLabel = ''
if (roles.includes('LMS Schoolchild') || roles.includes('LMS Student') || roles.includes('Course Creator')) {
if (roles.includes('LMS Schoolchild')) {
URL = 'chatgpt-schoolchild'
nameLabel = __('ChatGPT for Schoolers')
} else if (roles.includes('LMS Student')) {
URL = 'chatgpt-schoolchild'
nameLabel = __('ChatGPT for Students')
} else if (roles.includes('Course Creator')) {
URL = 'ai-teachers'
nameLabel = __('ChatGPT for Teachers')
}
sidebarLinks.value.push({
label: nameLabel,
icon: 'Cpu',
to: URL,
external: true,
activeFor: [],
})
}
}
const addMyChild = () => {
const roles = userResource.data?.roles || []
if (roles.includes('Parent')) {
sidebarLinks.value.push({
label: __('My Child'),
icon: 'User',
to: 'my-child',
activeFor: [],
external: true,
})
}
}
//test of new page
const addProfile = () => {
const roles = userResource.data?.roles || []
if (roles.includes('LMS Student')) {
sidebarLinks.value.push({
label: __('Student Profile'),
icon: 'Home',
to: 'StudentProfile',
activeFor: [],
})
} else if (roles.includes('LMS Schoolchild')) {
sidebarLinks.value.push({
label: __('Schoolchildren Profile'),
icon: 'Home',
to: 'SchoolchildrenProfile',
activeFor: [],
})
} else if (roles.includes('Course Creator')) {
sidebarLinks.value.push({
label: __('Course Creator Profile'),
icon: 'Home',
to: 'CourseCreatorProfile',
activeFor: [],
})
} else {
sidebarLinks.value.push({
label: __('Parent Profile'),
icon: 'Home',
to: 'ParentProfile',
activeFor: [],
})
}
}
watch(userResource, () => {
addContactUsDetails()
if (userResource.data) {
@@ -670,6 +768,12 @@ watch(userResource, () => {
addQuizzes()
addAssignments()
setUpOnboarding()
addMyPoints()
addLeaderBoard()
addChatGPT()
addMyChild()
addProfile()
}
})

View File

@@ -20,10 +20,10 @@
</template>
</Dialog>
<Popover :show="iosInstallMessage" placement="top">
<Popover :show="iosInstallMessage" placement="top-start">
<template #body>
<div
class="fixed bottom-[4rem] left-1/2 -translate-x-1/2 z-20 w-[90%] flex flex-col gap-3 rounded bg-blue-100 py-5 drop-shadow-xl"
class="fixed top-[20rem] translate-x-1/3 z-20 flex flex-col gap-3 rounded bg-surface-white py-5 drop-shadow-xl"
>
<div
class="mb-1 flex flex-row items-center justify-between px-3 text-center"
@@ -41,7 +41,7 @@
</div>
<div class="px-3 text-xs text-gray-800">
<span class="flex flex-col gap-2">
<span>
<span class="leading-5">
{{
__(
'Get the app on your iPhone for easy access & a better experience'

View File

@@ -9,6 +9,16 @@
allowfullscreen
></iframe>
</div>
<div v-if="rutube">
<iframe
class="rutube-video"
:src="getRutubeVideoSource(rutube.split('/').pop())"
width="100%"
:height="screenSize.width < 640 ? 200 : 400"
frameborder="0"
allowfullscreen
></iframe>
</div>
<div v-for="block in content?.split('\n\n')">
<div v-if="block.includes('{{ YouTubeVideo')">
<iframe
@@ -20,6 +30,16 @@
allowfullscreen
></iframe>
</div>
<div v-else-if="block.includes('{{ RutubeVideo')">
<iframe
class="rutube-video"
:src="getRutubeVideoSource(block)"
width="100%"
:height="screenSize.width < 640 ? 200 : 400"
frameborder="0"
allowfullscreen
></iframe>
</div>
<div v-else-if="block.includes('{{ Quiz')">
<Quiz :quiz="getId(block)" />
</div>
@@ -97,6 +117,13 @@ const getYouTubeVideoSource = (block) => {
return `https://www.youtube.com/embed/${block}`
}
const getRutubeVideoSource = (block) => {
if (block.includes('{{')) {
block = getId(block)
}
return `https://rutube.ru/play/embed/${block}`
}
const getPDFSource = (block) => {
return `${getId(block)}#toolbar=0`
}
@@ -105,3 +132,11 @@ const getId = (block) => {
return block.match(/\(["']([^"']+?)["']\)/)[1]
}
</script>
<style scoped>
.youtube-video,
.rutube-video {
display: block;
margin: 0 auto;
}
</style>

View File

@@ -52,9 +52,9 @@ const contentMap = {
'To upload Image, Video, Audio or PDF from your system, click on the add icon and select upload from the menu. Then choose the file you want to add to the lesson and it gets added to your lesson.',
},
youtube: {
title: 'How to add a YouTube Video?',
title: 'How to add a YouTube Video/RuTube?',
description:
'Copy the URL of the video from YouTube and paste it in the editor.',
'Copy the URL of the video from YouTube/RuTube and paste it in the editor.',
},
remove: {
title: 'How to remove an embed?',

View File

@@ -76,15 +76,12 @@ const isModerator = ref(false)
const isInstructor = ref(false)
onMounted(() => {
sidebarSettings.reload(
{},
{
onSuccess(data) {
filterLinksToShow(data)
addOtherLinks()
},
}
)
// Вызываем addSideBar только если userResource уже загружен
if (userResource.data) {
addSideBar()
}
addOtherLinks()
filterLinksToShow(data)
})
const handleOutsideClick = (e) => {
@@ -113,24 +110,184 @@ const filterLinksToShow = (data) => {
})
}
const addSideBar = () => {
sidebarLinks.value = [] // Очищаем, чтобы избежать дублирования
// Проверяем роли пользователя
const roles = userResource.data?.roles || []
sidebarLinks.value.push({
label: __('Courses'),
icon: 'BookOpen',
to: 'Courses',
activeFor: [
'Courses',
'CourseDetail',
'Lesson',
'CourseForm',
'LessonForm',
],
})
sidebarLinks.value.push({
label: __('Leader Board'),
icon: 'Trophy',
to: 'LeaderBoard',
activeFor: [],
})
if (roles.includes('LMS Student') || roles.includes('LMS Schoolchild')) {
otherLinks.value.push({
label: __('My points'),
icon: 'Award',
to: 'MyPoints',
activeFor: [],
})
}
if (roles.includes('Parent')) {
otherLinks.value.push({
label: __('My Child'),
icon: 'User',
to: 'my-child',
external: true,
activeFor: [],
})
}
let chatGPTURL = ''
let chatGPTLabel = ''
if (roles.includes('LMS Schoolchild')) {
chatGPTURL = 'chatgpt-schoolchild'
chatGPTLabel = __('ChatGPT for Schoolers')
} else if (roles.includes('LMS Student')) {
chatGPTURL = 'chatgpt-schoolchild'
chatGPTLabel = __('ChatGPT for Students')
} else if (roles.includes('Course Creator')) {
chatGPTURL = 'ai-teachers'
chatGPTLabel = __('ChatGPT for Teachers')
}
if (chatGPTURL) {
sidebarLinks.value.push({
label: chatGPTLabel,
icon: 'Cpu',
to: chatGPTURL,
external: true,
activeFor: [],
})
}
}
const addOtherLinks = () => {
otherLinks.value = []
if (user) {
const roles = userResource.data?.roles || []
if (!userResource.data?.is_instructor && !userResource.data?.is_moderator) {
otherLinks.value.push({
label: __('Programs'),
icon: 'Route',
to: 'Programs',
activeFor: ['Programs', 'ProgramForm', 'CourseDetail', 'Lesson'],
})
} else if (userResource.data?.is_instructor || userResource.data?.is_moderator) {
otherLinks.value.push({
label: __('Programs'),
icon: 'Route',
to: 'Programs',
activeFor: ['Programs', 'ProgramForm'],
})
}
if (userResource.data?.is_moderator || userResource.data?.is_instructor) {
otherLinks.value.push({
label: __('Quizzes'),
icon: 'CircleHelp',
to: 'Quizzes',
activeFor: [
'Quizzes',
'QuizForm',
'QuizSubmissionList',
'QuizSubmission',
],
})
otherLinks.value.push({
label: __('Assignments'),
icon: 'Pencil',
to: 'Assignments',
activeFor: [
'Assignments',
'AssignmentForm',
'AssignmentSubmissionList',
'AssignmentSubmission',
],
}),
otherLinks.value.push({
label: 'Programming Exercises',
icon: 'Code',
to: 'ProgrammingExercises',
})
}
if (roles.includes('LMS Student') || roles.includes('LMS Schoolchild')) {
otherLinks.value.push({
label: __('My points'),
icon: 'Award',
to: 'my_points',
external: true,
activeFor: [],
})
}
let chatGPTURL = ''
let chatGPTLabel = ''
if (roles.includes('LMS Schoolchild')) {
chatGPTURL = 'chatgpt-schoolchild'
chatGPTLabel = __('ChatGPT for Schoolers')
} else if (roles.includes('LMS Student')) {
chatGPTURL = 'chatgpt-schoolchild'
chatGPTLabel = __('ChatGPT for Students')
} else if (roles.includes('Course Creator')) {
chatGPTURL = 'ai-teachers'
chatGPTLabel = __('ChatGPT for Teachers')
}
if (chatGPTURL) {
otherLinks.value.push({
label: chatGPTLabel,
icon: 'Cpu',
to: chatGPTURL,
external: true,
activeFor: [],
})
}
otherLinks.value.push({
label: 'Notifications',
icon: 'Bell',
to: 'Notifications',
label: __('Leader Board'),
icon: 'Trophy',
to: 'leaderboardsample',
external: true,
activeFor: [],
})
otherLinks.value.push({
label: 'Profile',
label: __('Profile'),
icon: 'UserRound',
to: 'Profile',
params: { username: userResource.data?.username },
})
otherLinks.value.push({
label: 'Log out',
label: __('Log out'),
icon: 'LogOut',
})
} else {
otherLinks.value.push({
label: 'Log in',
label: __('Log in'),
icon: 'LogIn',
})
}
@@ -138,63 +295,11 @@ const addOtherLinks = () => {
watch(userResource, () => {
if (userResource.data) {
isModerator.value = userResource.data.is_moderator
isInstructor.value = userResource.data.is_instructor
addPrograms()
if (isModerator.value || isInstructor.value) {
addProgrammingExercises()
addQuizzes()
addAssignments()
}
addSideBar() // Обновляем sidebarLinks при изменении userResource
addOtherLinks() // Обновляем otherLinks
}
})
const addQuizzes = () => {
otherLinks.value.push({
label: 'Quizzes',
icon: 'CircleHelp',
to: 'Quizzes',
})
}
const addAssignments = () => {
otherLinks.value.push({
label: 'Assignments',
icon: 'Pencil',
to: 'Assignments',
})
}
const addProgrammingExercises = () => {
otherLinks.value.push({
label: 'Programming Exercises',
icon: 'Code',
to: 'ProgrammingExercises',
})
}
const addPrograms = async () => {
let canAddProgram = await checkIfCanAddProgram()
if (!canAddProgram) return
let activeFor = ['Programs', 'ProgramDetail']
let index = 1
sidebarLinks.value.splice(index, 0, {
label: 'Programs',
icon: 'Route',
to: 'Programs',
activeFor: activeFor,
})
}
const checkIfCanAddProgram = async () => {
if (isModerator.value || isInstructor.value) {
return true
}
const programs = await call('lms.lms.utils.get_programs')
return programs.enrolled.length > 0 || programs.published.length > 0
}
let isActive = (tab) => {
return tab.activeFor?.includes(router.currentRoute.value.name)
}
@@ -212,6 +317,7 @@ const handleClick = (tab) => {
username: userResource.data?.username,
},
})
else if (tab.external) window.location.href = `/${tab.to}`
else router.push({ name: tab.to })
}

View File

@@ -113,6 +113,14 @@ watch(
{ flush: 'post' }
)
watch(show, (newVal) => {
if (newVal && props.assignmentID === 'new') {
assignment.title = ''
assignment.type = ''
assignment.question = ''
}
})
const saveAssignment = () => {
if (props.assignmentID == 'new') {
assignments.value.insert.submit(

View File

@@ -11,7 +11,7 @@
<Avatar :image="student.user_image" size="3xl" />
<div class="space-y-1">
<div class="flex items-center space-x-2">
<div class="text-xl font-semibold">
<div class="text-xl font-semibold text-ink-gray-9">
{{ student.full_name }}
</div>
<Badge
@@ -36,7 +36,9 @@
v-if="Object.keys(student.assessments).length"
class="space-y-2 text-sm"
>
<div class="flex items-center border-b pb-1 font-medium">
<div
class="flex items-center border-b pb-1 font-medium text-ink-gray-9"
>
<span class="flex-1">
{{ __('Assessment') }}
</span>
@@ -86,7 +88,9 @@
v-if="Object.keys(student.courses).length"
class="space-y-2 text-sm"
>
<div class="flex items-center border-b pb-1 font-medium">
<div
class="flex items-center border-b pb-1 font-medium text-ink-gray-9"
>
<span class="flex-1">
{{ __('Courses') }}
</span>

View File

@@ -1,11 +1,11 @@
<template>
<Dialog
:options="{
title: 'Edit your profile',
title: __('Edit your profile'),
size: '3xl',
actions: [
{
label: 'Save',
label: __('Save'),
variant: 'solid',
onClick: (close) => saveProfile(close),
},

View File

@@ -66,7 +66,11 @@
</template>
{{ __('View Certificate') }}
</Button>
<Button v-else @click="openCallLink(event.venue)" class="w-full">
<Button
v-else-if="userIsEvaluator()"
@click="openCallLink(event.venue)"
class="w-full"
>
<template #prefix>
<Video class="h-4 w-4 stroke-1.5" />
</template>
@@ -83,21 +87,31 @@
class="flex flex-col space-y-4 p-5"
>
<div class="flex items-center justify-between">
<Rating v-model="evaluation.rating" :label="__('Rating')" />
<Rating
v-model="evaluation.rating"
:label="__('Rating')"
:disabled="!userIsEvaluator()"
/>
<FormControl
type="select"
:options="statusOptions"
v-model="evaluation.status"
:label="__('Status')"
class="w-1/2"
:disabled="!userIsEvaluator()"
/>
</div>
<Textarea
v-model="evaluation.summary"
:label="__('Summary')"
:rows="7"
:disabled="!userIsEvaluator()"
/>
<Button variant="solid" @click="saveEvaluation()">
<Button
v-if="userIsEvaluator()"
variant="solid"
@click="saveEvaluation()"
>
{{ __('Save') }}
</Button>
</div>
@@ -106,11 +120,13 @@
type="checkbox"
v-model="certificate.published"
:label="__('Published')"
:disabled="!userIsEvaluator()"
/>
<Link
v-model="certificate.template"
:label="__('Template')"
doctype="Print Format"
:disabled="!userIsEvaluator()"
:filters="{
doc_type: 'LMS Certificate',
}"
@@ -118,14 +134,20 @@
<FormControl
type="date"
v-model="certificate.issue_date"
:disabled="!userIsEvaluator()"
:label="__('Issue Date')"
/>
<FormControl
type="date"
v-model="certificate.expiry_date"
:disabled="!userIsEvaluator()"
:label="__('Expiry Date')"
/>
<Button variant="solid" @click="saveCertificate()">
<Button
v-if="userIsEvaluator()"
variant="solid"
@click="saveCertificate()"
>
{{ __('Save') }}
</Button>
</div>
@@ -163,6 +185,7 @@ import Rating from '@/components/Controls/Rating.vue'
import Link from '@/components/Controls/Link.vue'
const show = defineModel()
const user = inject('$user')
const dayjs = inject('$dayjs')
const tabIndex = ref(0)
const showCertification = ref(false)
@@ -175,9 +198,18 @@ const props = defineProps({
})
const evaluation = reactive({})
const certificate = reactive({})
watch(user, () => {
if (userIsEvaluator()) {
defaultTemplate.reload()
}
})
const userIsEvaluator = () => {
return user.data && user.data.name == props.event.evaluator
}
const defaultTemplate = createResource({
url: 'frappe.client.get_value',
makeParams(values) {
@@ -190,7 +222,6 @@ const defaultTemplate = createResource({
},
}
},
auto: true,
onSuccess(data) {
certificate.template = data.value
},

View File

@@ -1,13 +1,13 @@
<template>
<div class="border rounded-md w-1/3 mx-auto my-32">
<div class="border-b px-5 py-3 font-medium">
<div class="border-b px-5 py-3 font-medium text-ink-gray-9">
<span
class="inline-flex items-center before:bg-surface-red-5 before:w-2 before:h-2 before:rounded-md before:mr-2"
></span>
{{ __('Not Permitted') }}
</div>
<div v-if="user.data" class="px-5 py-3">
<div>
<div class="text-ink-gray-7">
{{ __('You do not have permission to access this page.') }}
</div>
<router-link
@@ -21,7 +21,7 @@
</router-link>
</div>
<div class="px-5 py-3">
<div>
<div class="text-ink-gray-7">
{{ __('Please login to access this page.') }}
</div>
<Button @click="redirectToLogin()" class="mt-4">

View File

@@ -55,8 +55,8 @@
<div v-if="quiz.data.duration" class="flex flex-col space-x-1 my-4">
<div class="mb-2">
<span class=""> {{ __('Time') }}: </span>
<span class="font-semibold">
<span class="text-ink-gray-9"> {{ __('Time') }}: </span>
<span class="font-semibold text-ink-gray-9">
{{ formatTimer(timer) }}
</span>
</div>
@@ -165,14 +165,14 @@
</div>
</div>
<span
class="ml-2"
class="ml-2 text-ink-gray-9"
v-html="questionDetails.data[`option_${index}`]"
>
</span>
</label>
<div
v-if="questionDetails.data[`explanation_${index}`]"
class="mt-2 text-xs"
class="mt-2 text-xs text-ink-gray-7"
v-show="showAnswers.length"
>
{{ questionDetails.data[`explanation_${index}`] }}
@@ -260,7 +260,7 @@
)
}}
</div>
<div v-else>
<div v-else class="text-ink-gray-7">
{{
__(
'You got {0}% correct answers with a score of {1} out of {2}'

View File

@@ -1,6 +1,6 @@
<template>
<div v-if="heatmap.data">
<div class="text-lg font-semibold mb-2">
<div class="text-lg font-semibold mb-2 text-ink-gray-9">
{{ heatmap.data.total_activities }}
{{
heatmap.data.total_activities > 1 ? __('activities') : __('activity')

View File

@@ -40,7 +40,7 @@
</div>
<div v-if="batch.data.courses.length">
<div class="flex items-center mt-10">
<div class="text-2xl font-semibold">
<div class="text-2xl font-semibold text-ink-gray-9">
{{ __('Courses') }}
</div>
</div>

View File

@@ -0,0 +1,918 @@
<template>
<div class="min-h-screen bg-white">
<NoPermission v-if="!$user.data" />
<div v-else-if="profile.error" class="p-6">
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-sm p-6 border border-red-200">
<p class="text-red-500 text-lg font-medium">Ошибка загрузки профиля: {{ profile.error.message }}</p>
</div>
</div>
<div v-else-if="profile.data">
<header class="sticky top-0 z-10 flex items-center justify-between bg-white px-6 py-4">
<Breadcrumbs class="h-7" :items="breadcrumbs" />
</header>
<div class="mx-auto max-w-6xl px-4 py-6">
<!-- Profile Header -->
<div v-if="!schoolProfileNotFound" class="bg-gradient-to-r from-teal-100 to-teal-600 rounded-2xl shadow-sm border border-gray-200 p-6 -mt-4 relative">
<div class="flex flex-col md:flex-row md:items-center gap-6">
<div class="flex-1">
<h2 class="text-3xl font-bold text-gray-900">{{ displayName }}</h2>
<div
v-if="profile.data.bio"
v-html="
DOMPurify.sanitize(decodeEntities(profile.data.bio), {
ALLOWED_TAGS: [
'b',
'i',
'em',
'strong',
'a',
'p',
'br',
'ul',
'ol',
'li',
'img',
],
ALLOWED_ATTR: ['href', 'target', 'rel', 'src'],
})
"
class="ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-outline-gray-2 prose-th:border-outline-gray-2 prose-td:relative prose-th:relative prose-th:bg-surface-gray-2 prose-sm max-w-none !whitespace-normal mt-2 text-gray-700"
></div>
</div>
<div v-if="$user.data && isSessionUser() && !schoolProfileNotFound" class="md:ml-auto">
<Button @click="toggleEdit()" class="bg-white hover:bg-gray-100 px-5 py-2.5 rounded-lg transition-colors duration-200">
<template #prefix>
<Edit class="w-4 h-4 stroke-1.5" />
</template>
{{ editMode ? 'Отменить редактирование' : 'Редактировать профиль' }}
</Button>
</div>
</div>
</div>
<!-- VIEW MODE -->
<div v-if="!editMode" class="mt-6">
<!-- Пустой профиль -->
<div v-if="schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="p-8 text-center">
<div class="max-w-md mx-auto">
<div class="mx-auto w-20 h-20 bg-teal-100 rounded-full flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-teal-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</div>
<h3 class="text-2xl font-bold text-gray-900 mb-3">Профиль преподавателя еще не заполнен</h3>
<p class="text-gray-600 mb-6">
Чтобы начать создавать и проводить курсы, заполните информацию о себе.
Это поможет студентам лучше узнать вас как преподавателя.
</p>
<div class="bg-teal-50 border border-teal-100 rounded-lg p-5 mb-6 text-left">
<h4 class="font-semibold text-teal-800 mb-3 flex items-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Заполнив профиль, вы сможете:
</h4>
<ul class="space-y-2 text-sm text-gray-700">
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Создавать и проводить собственные курсы</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Привлекать студентов с помощью подробного профиля</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Показать свою экспертизу и опыт</span>
</li>
</ul>
</div>
<Button
@click="toggleEdit()"
class="bg-teal-600 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 shadow-sm hover:shadow-md"
>
<template #prefix>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</svg>
</template>
Заполнить профиль создателя курса
</Button>
</div>
</div>
</div>
<!-- Загружающийся профиль -->
<div v-else-if="schoolProfile.loading" class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="flex items-center justify-center py-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div>
</div>
</div>
<!-- Ошибка загрузки (кроме DoesNotExistError) -->
<div v-else-if="schoolProfile.error && !schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-red-200 p-6">
<p class="text-red-500 text-lg font-medium">{{__('Error loading course creator data:')}} {{ schoolProfile.error.message }}</p>
</div>
<!-- Загруженный профиль -->
<div v-else-if="schoolProfile.data && !schoolProfileNotFound" class="space-y-6">
<!-- Основная информация -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Основная информация</h3>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Last name:')}}:</span>
<span class="text-gray-900">{{ schoolProfile.data.last_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Name:')}}:</span>
<span class="text-gray-900">{{ schoolProfile.data.first_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Middle name:')}}</span>
<span class="text-gray-900">{{ schoolProfile.data.middle_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Date of birth:')}}</span>
<span class="text-gray-900">{{ formattedDate(schoolProfile.data.birth_date) || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Phone:')}}</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.phone) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Email:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.email_private) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Telegram:</span>
<div class="flex-1">
<a v-if="schoolProfile.data.telegram"
:href="formatTelegram(schoolProfile.data.telegram)"
target="_blank"
class="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 font-medium transition-colors">
<span>{{ schoolProfile.data.telegram.replace('@', '') }}</span>
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69.01-.03.01-.14-.06-.2-.07-.06-.17-.04-.24-.02-.1.02-1.69 1.09-4.78 3.2-.45.31-.86.46-1.23.45-.41-.01-1.2-.23-1.79-.42-.72-.23-1.29-.36-1.24-.76.03-.24.37-.48 1.01-.74 3.97-1.67 6.62-2.77 7.94-3.31 3.26-1.33 3.94-1.56 4.38-1.56.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z"/>
</svg>
</a>
<span v-else class="text-gray-500">—</span>
</div>
</div>
</div>
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('University:')}}</span>
<span class="text-gray-900">{{ schoolProfile.data.school || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Education level:')}}</span>
<span class="text-gray-900">{{ schoolProfile.data.education_level || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('The direction of training:')}}</span>
<span class="text-gray-900">{{ schoolProfile.data.major || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-40 text-gray-700 font-medium">{{__('Educational program:')}}</span>
<span class="text-gray-900">{{ schoolProfile.data.program || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Год окончания:</span>
<span class="text-gray-900">{{ schoolProfile.data.graduation_year || '—' }}</span>
</div>
</div>
</div>
</div>
</div>
<!-- О себе, опыте и достижениях -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Коротко о себе</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.about_me || 'Информация не указана' }}</p>
</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Опыт работы</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.experience || 'Информация не указана' }}</p>
</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Достижения</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.achievement || 'Информация не указана' }}</p>
</div>
</div>
</div>
</div>
<div v-else class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="text-center py-12">
<div class="mx-auto w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
</div>
<h3 class="text-xl font-semibold text-gray-900 mb-2">Данные профиля не найдены</h3>
<p class="text-gray-600">Информация о репетиторе/эксперте отсутствует</p>
</div>
</div>
</div>
<!-- EDIT MODE -->
<div v-else class="mt-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">{{__('Profile Editing')}}</h3>
<p class="text-sm text-gray-200 mt-1">{{__('Fill in the information about yourself')}}</p>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Левая колонка -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">{{__('Personal information')}}</h4>
<Input
v-model="form.last_name"
:label="__('Last name:')"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.first_name"
:label="__('Name:')"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.middle_name"
:label="__('Middle name:')"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">{{__('Date of birth:')}}</label>
<DatePicker
v-model="form.birth_date"
class="w-full bg-gray-50 border-gray-300 rounded-lg focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<Input
v-model="form.phone"
:label="__('Phone:')"
placeholder="+7 (XXX) XXX-XX-XX"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.email_private"
label="Email"
type="email"
placeholder="example@email.com"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.telegram"
label="Telegram"
placeholder="username или t.me/username"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<!-- Правая колонка -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Образование</h4>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Университет</label>
<input
type="text"
v-model="schoolQuery"
@input="debouncedSearchSchool"
class="w-full bg-gray-50 border border-gray-300 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-colors"
placeholder="Начните вводить название университета"
/>
<div v-if="schoolResults.length" class="mt-2 border border-gray-300 rounded-lg overflow-hidden shadow-lg bg-white">
<div
v-for="s in schoolResults"
:key="s.school"
class="p-3 cursor-pointer hover:bg-primary-50 border-b border-gray-100 last:border-b-0 transition-colors"
@click="selectSchool(s)"
>
<div class="font-medium text-gray-900">{{ s.school }}</div>
<div class="text-xs text-gray-500 mt-1">{{ s.adress }}</div>
</div>
</div>
<div v-if="form.school_name && !schoolResults.length" class="mt-2 text-sm text-gray-600">
<span class="font-medium">Выбрана:</span> {{ form.school }}
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Уровень образования</label>
<Select
v-model="form.education_level"
:options="['Бакалавриат','Магистратура','Аспирантура','Базовое высшее образование','Специализированное высшее образование','Профессиональная переподготовка','Повышение квалификации']"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Направление подготовки</label>
<input
type="text"
v-model="majorQuery"
@input="debouncedSearchMajor"
class="w-full bg-gray-50 border border-gray-300 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-colors"
placeholder="Начните вводить название направления"
/>
<div v-if="majorResults.length" class="mt-2 border border-gray-300 rounded-lg overflow-hidden shadow-lg bg-white">
<div
v-for="m in majorResults"
:key="m.major"
class="p-3 cursor-pointer hover:bg-primary-50 border-b border-gray-100 last:border-b-0 transition-colors"
@click="selectMajor(m)"
>
<div class="font-medium text-gray-900">{{ m.major_name }}</div>
</div>
</div>
<div v-if="form.major_name && !majorResults.length" class="mt-2 text-sm text-gray-600">
<span class="font-medium">Выбрано:</span> {{ form.major_name }}
</div>
</div>
<Input
v-model="form.program"
label="Образовательная программа"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.graduation_year"
label="Год окончания"
placeholder="например, 2025"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
</div>
<!-- Текстовые поля -->
<div class="mt-8 space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Дополнительная информация</h4>
<Textarea
v-model="form.about_me"
label="Коротко о себе"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Textarea
v-model="form.experience"
label="Опыт работы"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Textarea
v-model="form.achievement"
label="Достижения"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<!-- Кнопки действий -->
<div class="mt-8 pt-6 border-t border-gray-200 flex gap-3">
<Button
@click="saveProfile"
:loading="saving"
class="bg-teal-400 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 flex items-center gap-2"
>
{{ saving ? 'Сохранение...' : 'Сохранить изменения' }}
</Button>
<Button
variant="outline"
@click="toggleEdit()"
class="border-gray-300 text-gray-700 hover:bg-gray-50 px-6 py-3 rounded-lg font-medium transition-colors duration-200"
>
Отмена
</Button>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="flex items-center justify-center min-h-screen">
<div class="text-center">
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-primary-600 mx-auto"></div>
<p class="mt-4 text-lg text-gray-600">Загрузка профиля...</p>
</div>
</div>
</div>
</template>
<style scoped>
/* Плавные переходы для интерактивных элементов */
.border-gray-300 {
transition: border-color 0.2s ease;
}
.bg-primary-50 {
background-color: rgba(59, 130, 246, 0.05);
}
/* Стилизация скроллбара для выпадающих списков */
.overflow-auto::-webkit-scrollbar {
width: 6px;
}
.overflow-auto::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.overflow-auto::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.overflow-auto::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
</style>
<script setup>
import { ref, computed, inject, watch, onMounted } from 'vue';
import { Breadcrumbs, createResource, Button, Input, DatePicker, Select, Textarea } from 'frappe-ui';
import { sessionStore } from '@/stores/session';
import NoPermission from '@/components/NoPermission.vue';
import { Edit } from 'lucide-vue-next';
import { convertToTitleCase, updateDocumentTitle } from '@/utils';
import debounce from 'lodash/debounce';
import { decodeEntities } from '@/utils'
import DOMPurify from 'dompurify'
const { user } = sessionStore();
const $user = inject('$user');
const schoolProfileNotFound = ref(false);
// Логирование инициализации
console.log('[DEBUG] Инициализация компонента:', {
user: user,
$user: $user.data,
username: $user.data?.username,
});
const props = defineProps({
username: {
type: String,
required: false,
default: '',
},
});
const effectiveUsername = computed(() => {
const username = props.username || $user.data?.username || '';
console.log('[DEBUG] Вычисление effectiveUsername:', { propsUsername: props.username, sessionUsername: $user.data?.username, result: username });
return username;
});
const editMode = ref(false);
const saving = ref(false);
const profile = createResource({
url: 'frappe.client.get',
makeParams(values) {
const username = effectiveUsername.value;
console.log('[DEBUG] Запрос profile:', { doctype: 'User', filters: { username } });
return {
doctype: 'User',
filters: { username },
};
},
onSuccess(data) {
console.log('[DEBUG] Профиль загружен:', data);
},
onError(error) {
console.error('[DEBUG] Ошибка загрузки профиля:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль пользователя: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
},
});
const schoolProfile = createResource({
url: 'frappe.client.get',
params: {
doctype: 'Schoolchildren Profile',
filters: { user:user },
},
auto: false,
onSuccess(data) {
console.log('[DEBUG] Профиль школьника загружен:', data);
},
onError(error) {
// Проверяем, является ли ошибка "не найдено"
if (error.exc_type === 'DoesNotExistError' || error.message?.includes('DoesNotExist')) {
console.log('[DEBUG] Профиль школьника не найден, создаем новый');
schoolProfileNotFound.value = true;
} else {
console.error('[DEBUG] Ошибка загрузки профиля школьника:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль школьника: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
}
},
});
const form = ref({
first_name: '',
last_name: '',
middle_name: '',
birth_date: '',
phone: '',
email_private: '',
telegram: '',
school: '',
education_level: '',
major: '',
program: '',
graduation_year: '',
experience: '',
achievement: '',
about_me: ''
});
const breadcrumbs = computed(() => {
const username = effectiveUsername.value;
const crumbs = [
{
label: 'People',
route: { name: 'People' },
},
{
label: profile.data?.full_name || 'Профиль',
route: username ? {
name: 'Profile',
params: { username },
} : undefined,
},
];
console.log('[DEBUG] Хлебные крошки:', crumbs);
return crumbs;
});
const pageMeta = computed(() => {
const meta = {
title: profile.data?.full_name || 'Профиль',
description: profile.data?.headline || '',
};
console.log('[DEBUG] Мета-данные страницы:', meta);
return meta;
});
const displayName = computed(() => {
if (!profile.data) {
console.log('[DEBUG] displayName: profile.data не загружен');
return 'Загрузка...';
}
const name = profile.data?.full_name || `${form.value.first_name || ''} ${form.value.last_name || ''}`.trim();
console.log('[DEBUG] Отображаемое имя:', name);
return name;
});
const isSessionUser = () => {
const sessionUser = $user.data?.username;
const profileUser = effectiveUsername.value;
const isSession = sessionUser === profileUser;
console.log('[DEBUG] Проверка isSessionUser:', { sessionUser, profileUser, isSession });
return isSession;
};
function formattedDate(d) {
if (!d) return '';
try {
return new Date(d).toLocaleDateString('ru-RU');
} catch (e) {
console.error('[DEBUG] Ошибка форматирования даты:', e, { date: d });
return d;
}
}
function maskPrivate(val) {
if (!val) return '-';
if (val.includes('@')) {
const parts = val.split('@');
return parts[0].slice(0, 1) + '***@' + parts[1];
}
return val.slice(0, 3) + '***' + val.slice(-2);
}
function formatTelegram(t) {
if (!t) return '';
if (t.startsWith('t.me/') || t.startsWith('https://t.me/')) return (t.startsWith('http') ? t : 'https://' + t);
return 'https://t.me/' + t.replace(/^@/, '');
}
function fillFormFromProfile() {
console.log('[DEBUG] Заполнение формы:', {
schoolProfile: schoolProfile.data,
profile: profile.data,
currentForm: JSON.stringify(form.value, null, 2),
});
form.value.first_name = schoolProfile.data?.first_name || profile.data?.first_name || '';
form.value.last_name = schoolProfile.data?.last_name || profile.data?.last_name || '';
form.value.middle_name = schoolProfile.data?.middle_name || '';
form.value.birth_date = schoolProfile.data?.birth_date || '';
form.value.phone = schoolProfile.data?.phone || '';
form.value.email_private = schoolProfile.data?.email_private || '';
form.value.telegram = schoolProfile.data?.telegram || '';
form.value.school = schoolProfile.data?.school || '';
form.value.education_level = schoolProfile.data?.education_level || '';
form.value.major = schoolProfile.data?.major || '';
form.value.program = schoolProfile.data?.program || '';
form.value.graduation_year = schoolProfile.data?.graduation_year || '';
form.value.experience = schoolProfile.data?.experience || '';
form.value.achievement = schoolProfile.data?.achievement || '';
form.value.about_me = schoolProfile.data?.about_me || '';
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
function toggleEdit() {
editMode.value = !editMode.value;
if (editMode.value) fillFormFromProfile();
console.log('[DEBUG] Переключение режима редактирования:', { editMode: editMode.value });
}
function validateExams(exams) {
console.log('[DEBUG] Валидация exams:', { exams, validOptions: examOptions });
return exams.every(exam => examOptions.includes(exam));
}
function validateLearnSubjects(subjects) {
console.log('[DEBUG] Валидация learn_subjects:', { subjects, validOptions: learnOptions });
return subjects.every(subject => learnOptions.includes(subject));
}
async function saveProfile() {
console.log('[DEBUG] Сохранение профиля:', { form: form.value });
saving.value = true;
try {
// Создаём копию данных формы
const formData = { ...form.value };
console.log('[DEBUG] Копия formData:', JSON.stringify(formData, null, 2));
// Обновление full_name в User, если нужно
if (formData.first_name || formData.last_name) {
const fullName = `${formData.first_name || ''} ${formData.last_name || ''}`.trim();
console.log('[DEBUG] Обновление User.full_name:', { name: profile.data?.name, fullName });
await createResource({
url: 'frappe.client.set_value',
params: {
doctype: 'User',
name: profile.data?.name,
fieldname: 'full_name',
value: fullName,
},
}).submit();
}
// Получаем docname
let docname = '';
try {
await schoolProfile.reload();
console.log('[DEBUG] Schoolprofile:', { schoolProfile });
docname = schoolProfile?.data?.name;
console.log('[DEBUG] Выбранное имя документа:', docname);
} catch (error) {
console.log('[DEBUG] Ошибка загрузки schoolProfile, продолжаем с profile:', error.message);
}
// Формируем payload из копии данных формы
let payload = {
doctype: 'Schoolchildren Profile',
user: profile.data?.name,
first_name: formData.first_name,
last_name: formData.last_name,
middle_name: formData.middle_name,
birth_date: formData.birth_date,
phone: formData.phone,
email_private: formData.email_private,
telegram: formData.telegram,
school: formData.school || '',
education_level: formData.education_level,
major: formData.major || '',
program: formData.program,
graduation_year: formData.graduation_year,
experience: formData.experience,
achievement: formData.achievement,
about_me: formData.about_me,
last_updated: new Date().toISOString(),
};
console.log('[DEBUG] Сохранение Schoolchildren Profile (payload):', { docname, payload });
// Сохранение или создание документа
if (docname) {
await createResource({
url: 'frappe.client.save',
params: { doc: { ...schoolProfile.data, ...payload } },
}).submit();
} else {
await createResource({
url: 'frappe.client.insert',
params: { doc: payload },
}).submit();
}
editMode.value = false;
schoolProfileNotFound.value = false;
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint('Профиль сохранён');
console.log('[DEBUG] Профиль успешно сохранён');
} catch (e) {
console.error('[DEBUG] Ошибка при сохранении профиля:', e);
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint({
title: 'Ошибка',
message: (e && e.message) || 'Ошибка при сохранении',
indicator: 'red',
});
} finally {
saving.value = false;
}
await schoolProfile.reload();
}
const schoolQuery = ref('');
const schoolResults = ref([]);
async function searchSchool(q) {
if (!q) {
schoolResults.value = [];
return;
}
try {
console.log('[DEBUG] Поиск школы:', { query: q });
const res = await createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'Schools',
fields: ['school', 'address'],
filters: [['school', 'like', '%' + q + '%']],
limit_page_length: 20,
},
}).submit();
schoolResults.value = res || [];
console.log('[DEBUG] Результаты поиска школы:', schoolResults.value);
} catch (e) {
schoolResults.value = [];
console.error('[DEBUG] Ошибка поиска школы:', e);
}
}
const debouncedSearchSchool = debounce(() => searchSchool(schoolQuery.value), 300);
function selectSchool(s) {
form.value.school = s.school;
//form.value.school_name = s.school_name;
schoolResults.value = [];
schoolQuery.value = s.school;
console.log('[DEBUG] Выбрана школа:', { school: s });
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
const majorQuery = ref('');
const majorResults = ref([]);
async function searchMajor(q) {
if (!q) {
majorResults.value = [];
return;
}
try {
console.log('[DEBUG] Поиск направления:', { query: q });
const res = await createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'Majors',
fields: ['code', 'major_name'],
filters: [['major_name', 'like', '%' + q + '%']],
limit_page_length: 20,
},
}).submit();
majorResults.value = res || [];
console.log('[DEBUG] Результаты поиска направления:', majorResults.value);
} catch (e) {
majorResults.value = [];
console.error('[DEBUG] Ошибка поиска направления:', e);
}
}
const debouncedSearchMajor = debounce(() => searchMajor(majorQuery.value), 300);
function selectMajor(m) {
form.value.major = m.major_name;
//form.value.school_name = s.school_name;
majorResults.value = [];
majorQuery.value = m.major_name;
console.log('[DEBUG] Выбрана школа:', { major: m });
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
onMounted(() => {
console.log('[DEBUG] Компонент смонтирован:', {
propsUsername: props.username,
sessionUsername: $user.data?.username,
user: user,
$user: $user.data,
});
if ($user.data) {
console.log('[DEBUG] Запуск profile.reload()');
profile.reload();
}
});
watch(
() => props.username,
(newUsername, oldUsername) => {
console.log('[DEBUG] Изменение props.username:', { old: oldUsername, new: newUsername });
profile.reload();
}
);
watch(
() => profile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение profile.data:', { old: oldData, new: newData });
if (newData) {
console.log('[DEBUG] Запуск schoolProfile.reload()');
schoolProfile.reload();
}
}
);
watch(
() => schoolProfile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение schoolProfile.data:', { old: oldData, new: newData });
if (newData && !editMode.value && !schoolProfileNotFound.value) {
console.log('[DEBUG] Заполнение формы из schoolProfile');
fillFormFromProfile();
}
}
);
watch(
() => effectiveUsername.value,
(newUsername) => {
console.log('[DEBUG] Изменение effectiveUsername для schoolProfile:', newUsername);
schoolProfile.update({
params: {
doctype: 'Schoolchildren Profile',
filters: { user: newUsername },
},
});
}
);
</script>

View File

@@ -56,7 +56,7 @@
<CourseInstructors :instructors="course.data.instructors" />
</div>
</div>
<div v-if="course.data.tags" class="flex my-4 w-fit">
<div v-if="course.data.tags" class="flex flex-wrap gap-2 mt-3 mb-3 max-w-full">
<Badge
theme="gray"
size="lg"

View File

@@ -134,7 +134,7 @@ const courses = createListResource({
doctype: 'LMS Course',
url: 'lms.lms.utils.get_courses',
cache: ['courses', user.data?.name],
pageLength: pageLength.value,
//pageLength: pageLength.value,
start: start.value,
onSuccess(data) {
setCategories(data)
@@ -229,7 +229,7 @@ const updateTabFilter = () => {
delete filters.value['published_on']
delete filters.value['upcoming']
if (currentTab.value == 'Enrolled' && user.data?.is_student) {
if ((currentTab.value == 'Enrolled' && user.data?.is_student) || (currentTab.value == 'Зачислен' && user.data?.is_student)) {
filters.value['enrolled'] = 1
delete filters.value['published']
} else {
@@ -240,24 +240,25 @@ const updateTabFilter = () => {
filters.value['published'] = 1
filters.value['upcoming'] = 0
filters.value['live'] = 1
} else if (currentTab.value == 'Upcoming') {
} else if (currentTab.value == 'Upcoming' || currentTab.value == 'Предстоящие') {
filters.value['upcoming'] = 1
} else if (currentTab.value == 'New') {
filters.value['published'] = 1
} else if (currentTab.value == 'New' || currentTab.value == 'Новый') {
filters.value['published'] = 1
filters.value['published_on'] = [
'>=',
dayjs().add(-3, 'month').format('YYYY-MM-DD'),
]
} else if (currentTab.value == 'Created') {
} else if (currentTab.value == 'Created' || currentTab.value == 'Создано') {
filters.value['created'] = 1
} else if (currentTab.value == 'Unpublished') {
} else if (currentTab.value == 'Unpublished' || currentTab.value == 'Неопубликовано') {
filters.value['published'] = 0
}
}
}
const updateStudentFilter = () => {
if (!user.data || (user.data?.is_student && currentTab.value != 'Enrolled')) {
if (!user.data || (user.data?.is_student && currentTab.value != 'Enrolled') || (currentTab.value != 'Зачислен' && user.data?.is_student)) {
filters.value['published'] = 1
}
}

View File

@@ -10,7 +10,7 @@
</header>
<div class="py-5">
<div class="container border-b mb-4 pb-5">
<div class="text-lg font-semibold mb-4">
<div class="text-lg font-semibold mb-4 text-ink-gray-9">
{{ __('Job Details') }}
</div>
<div class="grid grid-cols-2 gap-5">
@@ -59,7 +59,7 @@
</div>
</div>
<div class="container border-b mb-4 pb-5">
<div class="text-lg font-semibold mb-4">
<div class="text-lg font-semibold mb-4 text-ink-gray-9">
{{ __('Company Details') }}
</div>
<div class="grid grid-cols-2 gap-5">

View File

@@ -0,0 +1,718 @@
<template>
<div class="lms-page-container">
<!-- HEADER & TABS -->
<div class="lms-page-header">
<h1 class="page-title">{{ __('Таблица лидеров') }}</h1>
<!-- Сегментированные вкладки (Apple / Frappe style) -->
<div class="lms-tabs-container">
<button
v-for="group in roleGroups"
:key="group.role"
@click="activeGroup = group.role"
class="lms-tab-btn"
:class="{ 'active': activeGroup === group.role }"
>
{{ group.label }}
</button>
</div>
</div>
<!-- MAIN GRID LAYOUT -->
<div class="lms-layout-grid">
<!-- LEFT COLUMN: SUMMARY CARDS -->
<div class="lms-sidebar">
<!-- Карточка: Ваш результат -->
<div class="lms-card my-result-card">
<div class="lms-card-body">
<div class="card-header">
<span class="card-subtitle">{{ __('Ваш результат') }}</span>
<div v-if="currentUserPosition === 1" class="icon-gold"><i class="fas fa-crown"></i></div>
<div v-else-if="currentUserPosition === 2" class="icon-silver"><i class="fas fa-medal"></i></div>
<div v-else-if="currentUserPosition === 3" class="icon-bronze"><i class="fas fa-medal"></i></div>
<div v-else class="icon-gray"><i class="fas fa-user"></i></div>
</div>
<h2 class="card-title truncate-text" :title="currentUser.full_name">{{ currentUser.full_name || __('Вы') }}</h2>
<div class="card-stats">
<div class="stat-block">
<span class="stat-value">{{ currentUserPosition !== '-' ? currentUserPosition : '-' }}</span>
<span class="stat-label">{{ __('Место') }}</span>
</div>
<div class="stat-block">
<span class="stat-value text-primary">{{ currentUserPoints }}</span>
<span class="stat-label">{{ __('Очки') }}</span>
</div>
</div>
<div class="card-footer">
<p v-if="pointsToNext > 0 && currentUserPosition !== '-'" class="text-muted">
{{ __('До') }} {{ nextPosition }}-{{ __('го места не хватает') }} <strong style="color: #111827;">{{ pointsToNext }}</strong> {{ __('очков') }}
</p>
<p v-else-if="currentUserPosition === 1" class="text-success">
<i class="fas fa-check-circle"></i> {{ __('Вы на первом месте!') }}
</p>
<p v-else class="text-muted">{{ __('Выполняйте задания, чтобы попасть в топ') }}</p>
</div>
</div>
</div>
<!-- Карточка: Лидер группы -->
<div class="lms-card leader-card">
<div class="lms-card-body">
<div class="card-header">
<span class="card-subtitle">{{ __('Лидер группы') }}</span>
<div class="icon-gold"><i class="fas fa-trophy"></i></div>
</div>
<template v-if="topUserInGroup">
<h2 class="card-title truncate-text" :title="topUserInGroup.full_name">
<a :href="`/lms/user/${topUserInGroup.username}`" class="card-link">
{{ topUserInGroup.full_name }}
</a>
</h2>
<div class="card-stats">
<div class="stat-block">
<span class="stat-value">1</span>
<span class="stat-label">{{ __('Место') }}</span>
</div>
<div class="stat-block">
<span class="stat-value text-gold">{{ topUserInGroup.points }}</span>
<span class="stat-label">{{ __('Очки') }}</span>
</div>
</div>
<div class="card-footer">
<p class="text-muted">{{ __('Лучший результат среди категории') }} «{{ activeGroupLabel }}»</p>
</div>
</template>
<template v-else>
<h2 class="card-title text-muted mt-2">{{ __('Пока нет лидера') }}</h2>
</template>
</div>
</div>
</div>
<!-- RIGHT COLUMN: LEADERBOARD TABLE -->
<div class="lms-main-content">
<div class="lms-card table-card">
<div class="lms-table-header">
<h3>{{ activeGroupLabel }} <span class="count-badge">{{ currentLeaderboard.length }}</span></h3>
</div>
<div class="table-responsive">
<table v-if="currentLeaderboard.length > 0" class="lms-table">
<!-- FIX: Fixed table layout to prevent jumping when tabs change -->
<colgroup>
<col style="width: 70px;">
<col style="width: auto;">
<col style="width: 130px;">
<col style="width: 130px;">
<col v-if="activeGroup === 'LMS Schoolchild'" style="width: 150px;">
</colgroup>
<thead>
<tr>
<th style="text-align: center;">#</th>
<th>{{ __('Пользователь') }}</th>
<th style="text-align: center;">{{ __('Активность') }}</th>
<th style="text-align: center;">{{ __('Всего') }}</th>
<th v-if="activeGroup === 'LMS Schoolchild'" style="text-align: center;">{{ __('Баллы МПГУ') }}</th>
</tr>
</thead>
<tbody>
<tr
v-for="(user, index) in currentLeaderboard"
:key="user.user"
:class="{'is-current-user': user.user === currentUser.name}"
>
<!-- Ранг -->
<td style="text-align: center; font-weight: 600; color: #4b5563;">
<span v-if="index === 0" title="1 Место" class="medal-emoji">🥇</span>
<span v-else-if="index === 1" title="2 Место" class="medal-emoji">🥈</span>
<span v-else-if="index === 2" title="3 Место" class="medal-emoji">🥉</span>
<span v-else>{{ index + 1 }}</span>
</td>
<!-- Пользователь -->
<td>
<div class="user-cell">
<div class="user-avatar">{{ getUserInitial(user) }}</div>
<a :href="`/lms/user/${user.username}`" class="user-link truncate-text" :title="user.full_name">
{{ user.full_name }}
</a>
</div>
</td>
<!-- Очки -->
<td style="text-align: center; font-weight: 600; color: #111827;">
{{ user.points }}
</td>
<td style="text-align: center; font-weight: 600; color: #111827;">
{{ user.points }}
</td>
<!-- Бонусы МПГУ -->
<td v-if="activeGroup === 'LMS Schoolchild'" style="text-align: center;">
<span v-if="user.bonus > 0" class="bonus-badge">
+{{ user.bonus }}
</span>
<span v-else class="text-muted">-</span>
</td>
</tr>
</tbody>
</table>
<div v-else class="lms-empty-state">
<i class="fas fa-ghost empty-icon"></i>
<p>{{ __('В этой категории пока нет участников.') }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed, onMounted, ref, watch } from 'vue'
import { usersStore } from '@/stores/user'
import { createResource } from 'frappe-ui'
const store = usersStore()
const { userResource, allUsers } = store
const roleGroups = [
{ role: 'LMS Student', label: __('Студенты') },
{ role: 'Course Creator', label: __('Преподаватели') },
{ role: 'LMS Schoolchild', label: __('Школьники') }
]
function getUserRoleGroup(userRoles) {
if (!userRoles) return 'LMS Student'
const validRole = userRoles.find(role =>
roleGroups.some(group => group.role === role)
)
return validRole || 'LMS Student'
}
const activeGroup = ref('LMS Student')
const usersList = computed(() => allUsers.data || [])
const logsResource = createResource({
url: "frappe.client.get_list",
params: {
doctype: "Energy Point Log",
fields: ["user", "points"],
limit_page_length: 10000
},
auto: false,
onError: (err) => console.error("Error loading Energy Point Log:", err)
})
const leaderboard = ref([])
const currentUser = computed(() => {
return userResource.data || {}
})
const currentUserInitial = computed(() => {
if (currentUser.value.full_name) {
return currentUser.value.full_name.charAt(0).toUpperCase()
}
return currentUser.value.name?.charAt(0).toUpperCase() || 'U'
})
function getUserInitial(user) {
return user.full_name?.charAt(0).toUpperCase() || user.username?.charAt(0).toUpperCase() || 'U'
}
watch(
[() => logsResource.data, () => allUsers.data],
() => {
if (logsResource.data && allUsers.data) {
calculateLeaderboard()
}
},
{ deep: true }
)
watch([currentUser, usersList], () => {
if (currentUser.value.roles && usersList.value.length > 0) {
const userGroup = getUserRoleGroup(currentUser.value.roles)
activeGroup.value = userGroup
}
})
const activeGroupLabel = computed(() => {
const group = roleGroups.find(g => g.role === activeGroup.value)
return group ? group.label : ''
})
const currentLeaderboard = computed(() => {
return leaderboard.value
.filter(user => user.roles.includes(activeGroup.value))
.slice(0, 50)
})
const topUserInGroup = computed(() => {
return currentLeaderboard.value[0]
})
const currentUserPosition = computed(() => {
const userInLeaderboard = currentLeaderboard.value.findIndex(
user => user.user === currentUser.value.name
)
return userInLeaderboard !== -1 ? userInLeaderboard + 1 : '-'
})
const currentUserPoints = computed(() => {
const userEntry = leaderboard.value.find(user => user.user === currentUser.value.name)
return userEntry ? userEntry.points : 0
})
const pointsToNext = computed(() => {
const userIndex = currentLeaderboard.value.findIndex(
user => user.user === currentUser.value.name
)
if (userIndex === -1 || userIndex === 0) return 0
const currentPoints = currentLeaderboard.value[userIndex].points
const nextUserPoints = currentLeaderboard.value[userIndex - 1].points
return nextUserPoints - currentPoints + 1
})
const nextPosition = computed(() => {
const userIndex = currentLeaderboard.value.findIndex(
user => user.user === currentUser.value.name
)
return userIndex > 0 ? userIndex : 1
})
function calculateLeaderboard() {
if (!logsResource.data || !usersList.value) return
const pointsMap = {}
logsResource.data.forEach(log => {
if (!pointsMap[log.user]) pointsMap[log.user] = 0
pointsMap[log.user] += log.points
})
leaderboard.value = Object.keys(pointsMap)
.map(user => {
const u = usersList.value.find(x => x.name === user)
if (!u) return null
const hasValidRole = u.roles && u.roles.some(role =>
roleGroups.some(group => group.role === role)
)
if (!hasValidRole) return null
if (pointsMap[user] < 0) return null
const isSchoolchild = u.roles.includes('LMS Schoolchild')
const bonus = isSchoolchild ? Math.min(Math.floor(pointsMap[user] / 100), 10) : 0
return {
user,
points: pointsMap[user],
full_name: u.full_name,
username: u.username,
roles: u.roles || [],
bonus: bonus,
isSchoolchild: isSchoolchild
}
})
.filter(user => user !== null)
.sort((a, b) => b.points - a.points)
}
onMounted(async () => {
await allUsers.reload()
await logsResource.reload()
calculateLeaderboard()
})
</script>
<style scoped>
/* ============================================
ДИЗАЙН В СТИЛЕ FRAPPE LMS
============================================ */
.lms-page-container {
padding: 32px;
max-width: 1400px;
margin: 0 auto;
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #111827;
}
/* === HEADER & TABS === */
.lms-page-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 32px;
flex-wrap: wrap;
gap: 20px;
}
.page-title {
font-size: 28px;
font-weight: 700;
margin: 0;
color: #111827;
letter-spacing: -0.02em;
}
.lms-tabs-container {
display: inline-flex;
background-color: #f3f4f6;
padding: 4px;
border-radius: 8px;
border: 1px solid #e5e7eb;
}
.lms-tab-btn {
background: transparent;
border: none;
color: #6b7280;
font-size: 14px;
font-weight: 500;
padding: 8px 20px;
border-radius: 6px;
cursor: pointer;
transition: all 0.2s ease;
}
.lms-tab-btn:hover {
color: #374151;
}
.lms-tab-btn.active {
background: #ffffff;
color: #111827;
font-weight: 600;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
/* === MAIN GRID LAYOUT === */
.lms-layout-grid {
display: grid;
grid-template-columns: 340px 1fr;
gap: 24px;
align-items: start;
}
.lms-sidebar {
display: flex;
flex-direction: column;
gap: 24px;
}
/* === CARDS === */
.lms-card {
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
overflow: hidden;
}
.lms-card-body {
padding: 24px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16px;
}
.card-subtitle {
font-size: 13px;
font-weight: 600;
color: #6b7280;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.icon-gold { color: #f59e0b; font-size: 1.4rem; }
.icon-silver { color: #9ca3af; font-size: 1.4rem; }
.icon-bronze { color: #b45309; font-size: 1.4rem; }
.icon-gray { color: #d1d5db; font-size: 1.4rem; }
.card-title {
font-size: 20px;
font-weight: 700;
margin: 0 0 24px 0;
color: #111827;
line-height: 1.3;
}
.card-link {
text-decoration: none;
color: #111827;
transition: color 0.2s;
}
.card-link:hover { color: #00a9a6; }
.card-stats {
display: flex;
gap: 32px;
margin-bottom: 20px;
border-bottom: 1px solid #f3f4f6;
padding-bottom: 20px;
}
.stat-block {
display: flex;
flex-direction: column;
}
.stat-value {
font-size: 28px;
font-weight: 800;
line-height: 1;
color: #111827;
}
.stat-label {
font-size: 12px;
color: #6b7280;
margin-top: 8px;
font-weight: 500;
}
.text-primary { color: #00a9a6; }
.text-gold { color: #f59e0b; }
.text-muted { color: #6b7280; font-size: 13px; margin: 0; line-height: 1.5; }
.text-success { color: #059669; font-size: 13px; margin: 0; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.card-footer {
min-height: 20px;
}
/* === TABLE === */
.table-card {
min-height: 500px;
}
.lms-table-header {
padding: 20px 24px;
background: #ffffff;
border-bottom: 1px solid #e5e7eb;
}
.lms-table-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #111827;
display: flex;
align-items: center;
gap: 12px;
}
.count-badge {
background: #f3f4f6;
color: #4b5563;
padding: 2px 10px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
}
/* --- FIX: Настройки скролла для длинной таблицы --- */
.table-responsive {
overflow-x: auto;
overflow-y: auto;
max-height: 650px; /* Ограничиваем высоту, чтобы таблица не уезжала вниз */
}
/* Кастомный красивый скроллбар */
.table-responsive::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.table-responsive::-webkit-scrollbar-track {
background: transparent;
}
.table-responsive::-webkit-scrollbar-thumb {
background-color: #d1d5db;
border-radius: 10px;
}
.table-responsive::-webkit-scrollbar-thumb:hover {
background-color: #9ca3af;
}
.lms-table {
width: 100%;
border-collapse: collapse;
text-align: left;
font-size: 14px;
table-layout: fixed;
}
.lms-table th {
background: #f9fafb;
color: #4b5563;
font-weight: 500;
font-size: 13px;
padding: 14px 24px;
/* Заменяем border-bottom на box-shadow для sticky, чтобы не было просветов */
box-shadow: inset 0 -1px 0 #e5e7eb;
white-space: nowrap;
/* Делаем шапку прилипающей */
position: sticky;
top: 0;
z-index: 10;
}
.lms-table td {
padding: 16px 24px;
border-bottom: 1px solid #e5e7eb;
color: #374151;
vertical-align: middle;
}
.lms-table tr:last-child td {
border-bottom: none;
}
.lms-table tr:hover {
background-color: #f9fafb;
}
.lms-table tr.is-current-user {
background-color: #f0fdfa;
}
.lms-table tr.is-current-user td {
border-bottom-color: #ccfbf1;
}
.medal-emoji {
font-size: 18px;
}
.user-cell {
display: flex;
align-items: center;
gap: 14px;
}
.user-avatar {
width: 36px;
height: 36px;
background: #e5e7eb;
color: #4b5563;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 600;
font-size: 13px;
flex-shrink: 0;
}
.is-current-user .user-avatar {
background: #00a9a6;
color: #ffffff;
}
.user-link {
color: #111827;
text-decoration: none;
font-weight: 600;
}
.user-link:hover {
color: #00a9a6;
text-decoration: underline;
}
.truncate-text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.bonus-badge {
display: inline-flex;
align-items: center;
background: #ecfdf5;
color: #059669;
padding: 4px 10px;
border-radius: 6px;
font-weight: 600;
font-size: 13px;
}
.lms-empty-state {
padding: 60px 20px;
text-align: center;
color: #6b7280;
font-size: 15px;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
.empty-icon {
font-size: 32px;
color: #d1d5db;
}
/* === RESPONSIVE === */
@media (max-width: 1024px) {
.lms-layout-grid {
grid-template-columns: 1fr;
}
.lms-sidebar {
flex-direction: row;
}
.lms-card {
flex: 1;
}
}
@media (max-width: 768px) {
.lms-page-container {
padding: 16px;
}
.lms-sidebar {
flex-direction: column;
}
.lms-tabs-container {
width: 100%;
display: flex;
}
.lms-tab-btn {
flex: 1;
text-align: center;
padding: 8px 12px;
}
.lms-table th, .lms-table td {
padding: 12px 16px;
}
/* Немного уменьшим высоту на мобилках */
.table-responsive {
max-height: 500px;
}
}
</style>

View File

@@ -258,6 +258,7 @@
v-if="lesson.data?.body"
:content="lesson.data.body"
:youtube="lesson.data.youtube"
:rutube="lesson.data.rutube"
:quizId="lesson.data.quiz_id"
/>
</div>
@@ -733,7 +734,7 @@ const updateVideoTime = (video) => {
const startTimer = () => {
let timerInterval = setInterval(() => {
timer.value++
if (timer.value == 30) {
if (timer.value == 5) {
clearInterval(timerInterval)
markProgress()
}

View File

@@ -18,14 +18,14 @@
<div class="w-5/6 mx-auto">
<FormControl
v-model="lesson.title"
label="Title"
:label="__('Title')"
class="mb-4"
:required="true"
/>
<FormControl
v-model="lesson.include_in_preview"
type="checkbox"
label="Include in Preview"
:label="__('Include in Preview')"
/>
</div>
<div class="border-t mt-4">
@@ -272,6 +272,7 @@ const lessonReference = createResource({
const convertToJSON = (lessonData) => {
let blocks = []
if (lessonData.youtube) {
let youtubeID = lessonData.youtube.split('/').pop()
blocks.push({
@@ -282,6 +283,20 @@ const convertToJSON = (lessonData) => {
},
})
}
if (lessonData.rutube) {
let rutubeID = lessonData.rutube.includes('rutube.ru')
? lessonData.rutube.split('/').pop()
: lessonData.rutube;
blocks.push({
type: 'embed',
data: {
service: 'rutube',
embed: `https://rutube.ru/play/embed/${rutubeID}`,
},
});
}
lessonData.body.split('\n').forEach((block) => {
if (block.includes('{{ YouTubeVideo')) {
let youtubeID = block.match(/\(["']([^"']+?)["']\)/)[1]
@@ -294,6 +309,18 @@ const convertToJSON = (lessonData) => {
embed: youtubeID,
},
})
} else if (block.includes('{{ RutubeVideo')) {
let rutubeID = block.match(/\(["']([^"']+?)["']\)/)[1];
if (rutubeID.includes('rutube.ru')) {
rutubeID = rutubeID.split('/').pop();
}
blocks.push({
type: 'embed',
data: {
service: 'rutube',
embed: `https://rutube.ru/play/embed/${rutubeID}`,
},
});
} else if (block.includes('{{ Quiz')) {
let quiz = block.match(/\(["']([^"']+?)["']\)/)[1]
blocks.push({
@@ -458,17 +485,17 @@ const editCurrentLesson = () => {
const validateLesson = () => {
if (!lesson.title) {
return 'Title is required'
return __('Title is required')
}
if (!lesson.content) {
return 'Content is required'
return __('Content is required')
}
}
const breadcrumbs = computed(() => {
let crumbs = [
{
label: 'Courses',
label: __('Courses'),
route: { name: 'Courses' },
},
{
@@ -479,7 +506,7 @@ const breadcrumbs = computed(() => {
if (lessonDetails?.data?.lesson) {
crumbs.push({
label: lessonDetails.data.lesson.title,
label: __(lessonDetails.data.lesson.title),
route: {
name: 'Lesson',
params: {
@@ -491,7 +518,7 @@ const breadcrumbs = computed(() => {
})
}
crumbs.push({
label: lessonDetails?.data?.lesson ? 'Edit Lesson' : 'Create Lesson',
label: lessonDetails?.data?.lesson ? __('Edit Lesson') : __('Create Lesson'),
route: {
name: 'LessonForm',
params: {
@@ -507,8 +534,8 @@ const breadcrumbs = computed(() => {
usePageMeta(() => {
return {
title: lessonDetails?.data?.lesson
? lessonDetails.data.lesson.title
: 'New Lesson',
? __(lessonDetails.data.lesson.title)
: __('New Lesson'),
icon: brand.favicon,
}
})

View File

@@ -0,0 +1,183 @@
<template>
<div v-if="!$user.data">
<NoPermission />
</div>
<div v-else class="min-h-screen bg-50">
<header class="sticky top-0 z-10 flex items-center justify-between border-b bg-surface-white px-5 py-3">
<Breadcrumbs :items="breadcrumbs" />
</header>
<div class="p-5 pb-10">
<h2 class="text-lg text-ink-gray-9 font-semibold">{{__('My points')}}</h2>
<!-- Загрузка -->
<div v-if="energyPoints.loading" class="text-center py-16 text-gray-600">
{{__('Loading points...')}}
</div>
<!-- Нет баллов -->
<div v-else-if="!energyPoints.data?.length" class="bg-white rounded-xl shadow-xl mt-4 p-12 text-center">
<p class="text-xl text-gray-800">{{__('You don`t have any points yet')}}</p>
<p class="text-sm text-gray-700 mt-2">{{__('Participate in the activities — the points will appear!')}}</p>
</div>
<!-- Есть баллы -->
<div v-else>
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
<!-- ЛЕВАЯ КОЛОНКА список баллов -->
<div class="bg-white rounded-xl shadow-xl mt-4">
<ul class="divide-y divide-gray-200">
<li v-for="item in visibleItems" :key="item.name" class="p-6 hover:bg-gray-50">
<div class="flex items-center justify-between">
<div class="flex items-center gap-5">
<div class="text-2xl font-bold"
:class="item.points > 0 ? 'text-green-600' : 'text-red-600'">
{{ item.points > 0 ? '+' : '' }}{{ item.points }}
</div>
<div>
<p class="font-medium text-gray-900">
{{__( item.rule || 'Accrual of points' )}}
</p>
<p class="text-sm text-gray-500">
{{ dayjs(item.creation).format('DD MMMM YYYY в HH:mm') }}
</p>
</div>
</div>
</div>
</li>
</ul>
<div v-if="!showAll && energyPoints.data.length > 5" class="p-6 text-center">
<button
@click="showAll = true"
class="px-4 py-2 bg-gray-2 text-gray rounded-lg shadow-xl hover:bg-gray-3 transition">
{{__('Load more')}}
</button>
</div>
</div>
<!-- ПРАВАЯ КОЛОНКА итоги -->
<div class="space-y-6 text-teal-900">
<!-- БЛОК "Ты сегодня получил баллы" -->
<div class="bg-teal-600/20 rounded-xl p-6 shadow-xl mt-4">
<p class="text-lg opacity-80">{{__('Your stats')}}</p>
<p class="text-sm opacity-80 mt-1">
{{__('You`ve earned a lot today:')}}<strong>{{ todayPoints }}</strong>
</p>
<p class="text-sm opacity-80 mt-3">
{{ todayPoints > 0 ? __('Keep it up !') : __('You need to work out a little!') }}
</p>
<p class="text-sm opacity-80 mt-3">
{{ differencePoints > 0 ? `${__('This is')} ${differencePoints} ${__('more than yesterday')}`
: differencePoints < 0 ? `${__('This is')} ${Math.abs(differencePoints)} ${__('less than yesterday')}`
: __('This is the same as yesterday') }}
</p>
<p class="text-sm opacity-80 mt-3">
{{__('You`ve earned a lot in the last week:')}}<strong>{{ weeklyPoints }}</strong>
</p>
</div>
<div class="bg-teal-600/30 rounded-xl p-6 shadow-xl mt-4">
<p class="text-lg opacity-80">{{__('Total points')}}</p>
<p class="text-5xl font-bold mt-3">{{ totalPoints }}</p>
</div>
<div class="bg-teal-600/40 rounded-xl p-6 shadow-xl mt-4">
<p class="text-lg font-semibold opacity-90">{{__('Additionally, upon admission to the MPSU')}}</p>
<p class="text-5xl font-bold mt-3">+{{ additionalPoints }}</p>
<p class="text-sm opacity-70 mt-3">{{__('maximum of 10 points')}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { inject, computed, onMounted, ref } from 'vue'
import { createResource, Breadcrumbs } from 'frappe-ui'
import NoPermission from '@/components/NoPermission.vue'
const $user = inject('$user')
const dayjs = inject('$dayjs')
// Главное — фильтруем по email, как в LMS!
const energyPoints = createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'Energy Point Log',
fields: ['name', 'points', 'rule', 'creation'],
filters: {
user: $user.data.email // ← вот так, как в LMS — по email!
},
order_by: 'creation desc',
limit_page_length: 1000
},
auto: false,
onSuccess(data) {
console.log('Баллы загружены:', data.length, 'записей')
}
})
const totalPoints = computed(() => {
const list = Array.isArray(energyPoints.data) ? energyPoints.data : []
return list.reduce((sum, item) => sum + (item.points || 0), 0)
})
const additionalPoints = computed(() => {
const bonus = Math.floor(totalPoints.value / 100)
return bonus < 10 ? bonus : 10
})
const breadcrumbs = computed(() => [
{ label: __('Home'), route: '/' },
{ label: __('My Points') }
])
const showAll = ref(false)
const visibleItems = computed(() => {
if (!Array.isArray(energyPoints.data)) return []
return showAll.value
? energyPoints.data // показать все
: energyPoints.data.slice(0, 5) // первые 5
})
function getPointsByDate(dateString) {
if (!Array.isArray(energyPoints.data)) return 0
return energyPoints.data
.filter(item => dayjs(item.creation).format('YYYY-MM-DD') === dateString)
.reduce((sum, item) => sum + (item.points || 0), 0)
}
const today = dayjs().format('YYYY-MM-DD')
const yesterday = dayjs().subtract(1, 'day').format('YYYY-MM-DD')
const todayPoints = computed(() => getPointsByDate(today))
const yesterdayPoints = computed(() => getPointsByDate(yesterday))
const differencePoints = computed(() =>
todayPoints.value - yesterdayPoints.value
)
const weeklyPoints = computed(() => {
if (!Array.isArray(energyPoints.data)) return 0
const weekAgo = dayjs().subtract(7, 'day').startOf('day')
return energyPoints.data
.filter(item => dayjs(item.creation).isAfter(weekAgo))
.reduce((sum, item) => sum + (item.points || 0), 0)
})
onMounted(() => {
if ($user.data) {
energyPoints.fetch()
}
})
</script>

View File

@@ -0,0 +1,762 @@
<template>
<div class="min-h-screen bg-white">
<NoPermission v-if="!$user.data" />
<div v-else-if="profile.error" class="p-6">
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-sm p-6 border border-red-200">
<p class="text-red-500 text-lg font-medium">Ошибка загрузки профиля: {{ profile.error.message }}</p>
</div>
</div>
<div v-else-if="profile.data">
<header class="sticky top-0 z-10 flex items-center justify-between bg-white px-6 py-4">
<Breadcrumbs class="h-7" :items="breadcrumbs" />
</header>
<div class="mx-auto max-w-6xl px-4 py-6">
<!-- Profile Header -->
<div v-if="!schoolProfileNotFound" class="bg-gradient-to-r from-teal-100 to-teal-600 rounded-2xl shadow-sm border border-gray-200 p-6 -mt-4 relative">
<div class="flex flex-col md:flex-row md:items-center gap-6">
<div class="flex-1">
<h2 class="text-3xl font-bold text-gray-900">{{ displayName }}</h2>
<div
v-if="profile.data.headline"
v-html="
DOMPurify.sanitize(decodeEntities(profile.data.headline), {
ALLOWED_TAGS: [
'b',
'i',
'em',
'strong',
'a',
'p',
'br',
'ul',
'ol',
'li',
'img',
],
ALLOWED_ATTR: ['href', 'target', 'rel', 'src'],
})
"
class="ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-outline-gray-2 prose-th:border-outline-gray-2 prose-td:relative prose-th:relative prose-th:bg-surface-gray-2 prose-sm max-w-none !whitespace-normal mt-2 text-gray-700"
></div>
</div>
<div v-if="$user.data && isSessionUser()" class="md:ml-auto">
<Button @click="toggleEdit()" class="bg-white hover:bg-gray-100 px-5 py-2.5 rounded-lg transition-colors duration-200">
<template #prefix>
<Edit class="w-4 h-4 stroke-1.5" />
</template>
{{ editMode ? 'Отменить редактирование' : 'Редактировать профиль' }}
</Button>
</div>
</div>
</div>
<!-- VIEW MODE -->
<div v-if="!editMode" class="mt-6">
<!-- Пустой профиль родителя -->
<div v-if="schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="p-8 text-center">
<div class="max-w-md mx-auto">
<div class="mx-auto w-20 h-20 bg-teal-100 rounded-full flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-teal-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</div>
<h3 class="text-2xl font-bold text-gray-900 mb-3">Профиль родителя еще не заполнен</h3>
<p class="text-gray-600 mb-6">
Чтобы лучше понимать потребности вашего ребёнка и получать персонализированные рекомендации,
заполните информацию о себе и своём ребёнке.
</p>
<div class="bg-teal-50 border border-teal-100 rounded-lg p-5 mb-6 text-left">
<h4 class="font-semibold text-teal-800 mb-3 flex items-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Заполнив профиль, вы сможете:
</h4>
<ul class="space-y-2 text-sm text-gray-700">
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Получать персонализированные рекомендации для развития ребёнка</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Находить подходящих наставников для вашего ребёнка</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Быть в курсе успехов и прогресса вашего ребёнка</span>
</li>
</ul>
</div>
<Button
@click="toggleEdit()"
class="bg-teal-600 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 shadow-sm hover:shadow-md"
>
<template #prefix>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</svg>
</template>
Заполнить профиль родителя
</Button>
</div>
</div>
</div>
<!-- Загружающийся профиль -->
<div v-else-if="schoolProfile.loading" class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="flex items-center justify-center py-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div>
</div>
</div>
<!-- Ошибка загрузки (кроме DoesNotExistError) -->
<div v-else-if="schoolProfile.error && !schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-red-200 p-6">
<p class="text-red-500 text-lg font-medium">Ошибка загрузки данных родителя: {{ schoolProfile.error.message }}</p>
</div>
<!-- Загруженный профиль родителя -->
<div v-else-if="schoolProfile.data && !schoolProfileNotFound" class="space-y-6">
<!-- Основная информация -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Личная информация</h3>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Фамилия:</span>
<span class="text-gray-900">{{ schoolProfile.data.last_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Имя:</span>
<span class="text-gray-900">{{ schoolProfile.data.first_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Отчество:</span>
<span class="text-gray-900">{{ schoolProfile.data.middle_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Дата рождения:</span>
<span class="text-gray-900">{{ formattedDate(schoolProfile.data.birth_date) || '—' }}</span>
</div>
</div>
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Телефон:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.phone) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Email:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.email_private) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Telegram:</span>
<div class="flex-1">
<a v-if="schoolProfile.data.telegram"
:href="formatTelegram(schoolProfile.data.telegram)"
target="_blank"
class="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 font-medium transition-colors">
<span>{{ schoolProfile.data.telegram.replace('@', '') }}</span>
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69.01-.03.01-.14-.06-.2-.07-.06-.17-.04-.24-.02-.1.02-1.69 1.09-4.78 3.2-.45.31-.86.46-1.23.45-.41-.01-1.2-.23-1.79-.42-.72-.23-1.29-.36-1.24-.76.03-.24.37-.48 1.01-.74 3.97-1.67 6.62-2.77 7.94-3.31 3.26-1.33 3.94-1.56 4.38-1.56.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z"/>
</svg>
</a>
<span v-else class="text-gray-500">—</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Информация о ребенке -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Информация о ребёнке</h3>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">ФИО ребёнка:</span>
<span class="text-gray-900">{{ schoolProfile.data.child_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Телефон ребёнка:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.child_phone) || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Email ребёнка:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.child_email) || '—' }}</span>
</div>
</div>
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Цели для ребёнка:</span>
<div class="flex-1">
<div class="p-4 bg-teal-50 rounded-lg border border-teal-100">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.goals || 'Цели не указаны' }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="text-center py-12">
<div class="mx-auto w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197m13.5 6.197h-6"/>
</svg>
</div>
<h3 class="text-xl font-semibold text-gray-900 mb-2">Данные профиля не найдены</h3>
<p class="text-gray-600">Информация о родителе отсутствует</p>
</div>
</div>
</div>
<!-- EDIT MODE -->
<div v-else class="mt-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Редактирование профиля родителя</h3>
<p class="text-sm text-gray-200 mt-1">Заполните информацию о себе и своём ребёнке</p>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Левая колонка - Личная информация -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Личная информация</h4>
<Input
v-model="form.last_name"
label="Фамилия"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.first_name"
label="Имя"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.middle_name"
label="Отчество"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Дата рождения</label>
<DatePicker
v-model="form.birth_date"
class="w-full bg-gray-50 border-gray-300 rounded-lg focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<Input
v-model="form.phone"
label="Телефон (не публиковать)"
placeholder="+7 (XXX) XXX-XX-XX"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.email_private"
label="Email (не публиковать)"
type="email"
placeholder="example@email.com"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.telegram"
label="Telegram"
placeholder="username или t.me/username"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<!-- Правая колонка - Информация о ребенке -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Информация о ребёнке</h4>
<Input
v-model="form.child_name"
label="ФИО ребёнка"
placeholder="Иванов Иван Иванович"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.child_phone"
label="Телефон ребёнка"
placeholder="+7 (XXX) XXX-XX-XX"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.child_email"
label="Email ребёнка"
type="email"
placeholder="child@email.com"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Textarea
v-model="form.goals"
label="Какие цели Вы ставите своему ребёнку?"
rows="6"
placeholder="Опишите ваши ожидания и цели для развития вашего ребёнка..."
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
</div>
<!-- Кнопки действий -->
<div class="mt-8 pt-6 border-t border-gray-200 flex gap-3">
<Button
@click="saveProfile"
:loading="saving"
class="bg-teal-400 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 flex items-center gap-2"
>
{{ saving ? 'Сохранение...' : 'Сохранить изменения' }}
</Button>
<Button
variant="outline"
@click="toggleEdit()"
class="border-gray-300 text-gray-700 hover:bg-gray-50 px-6 py-3 rounded-lg font-medium transition-colors duration-200"
>
Отмена
</Button>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="flex items-center justify-center min-h-screen">
<div class="text-center">
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-primary-600 mx-auto"></div>
<p class="mt-4 text-lg text-gray-600">Загрузка профиля...</p>
</div>
</div>
</div>
</template>
<style scoped>
/* Плавные переходы для интерактивных элементов */
.border-gray-300 {
transition: border-color 0.2s ease;
}
.bg-primary-50 {
background-color: rgba(59, 130, 246, 0.05);
}
/* Стилизация скроллбара для выпадающих списков */
.overflow-y-auto::-webkit-scrollbar {
width: 6px;
}
.overflow-y-auto::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.overflow-y-auto::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
/* Анимация для кнопок */
.transition-colors {
transition-property: background-color, border-color, color, fill, stroke;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
}
</style>
<!-- Скрипт остается без изменений, только нужно добавить импорты -->
<script setup>
import { ref, computed, inject, watch, onMounted } from 'vue';
import { Breadcrumbs, createResource, Button, Input, DatePicker, Select, Textarea } from 'frappe-ui';
import { sessionStore } from '@/stores/session';
import NoPermission from '@/components/NoPermission.vue';
import { Edit } from 'lucide-vue-next';
import { convertToTitleCase, updateDocumentTitle } from '@/utils';
import debounce from 'lodash/debounce';
import { decodeEntities } from '@/utils'
import DOMPurify from 'dompurify'
const { user } = sessionStore();
const $user = inject('$user');
const schoolProfileNotFound = ref(false);
// Логирование инициализации
console.log('[DEBUG] Инициализация компонента:', {
user: user,
$user: $user.data,
username: $user.data?.username,
});
const props = defineProps({
username: {
type: String,
required: false,
default: '',
},
});
const effectiveUsername = computed(() => {
const username = props.username || $user.data?.username || '';
console.log('[DEBUG] Вычисление effectiveUsername:', { propsUsername: props.username, sessionUsername: $user.data?.username, result: username });
return username;
});
const editMode = ref(false);
const saving = ref(false);
const profile = createResource({
url: 'frappe.client.get',
makeParams(values) {
const username = effectiveUsername.value;
console.log('[DEBUG] Запрос profile:', { doctype: 'User', filters: { username } });
return {
doctype: 'User',
filters: { username },
};
},
onSuccess(data) {
console.log('[DEBUG] Профиль загружен:', data);
},
onError(error) {
console.error('[DEBUG] Ошибка загрузки профиля:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль пользователя: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
},
});
const schoolProfile = createResource({
url: 'frappe.client.get',
params: {
doctype: 'Schoolchildren Profile',
filters: { user:user },
},
auto: false,
onSuccess(data) {
console.log('[DEBUG] Профиль школьника загружен:', data);
},
onError(error) {
// Проверяем, является ли ошибка "не найдено"
if (error.exc_type === 'DoesNotExistError' || error.message?.includes('DoesNotExist')) {
console.log('[DEBUG] Профиль родителя не найден, создаем новый');
schoolProfileNotFound.value = true;
} else {
console.error('[DEBUG] Ошибка загрузки профиля родителя:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль родителя: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
}
},
});
const form = ref({
first_name: '',
last_name: '',
middle_name: '',
birth_date: '',
phone: '',
email_private: '',
telegram: '',
child_name: '',
child_phone: '',
child_email: '',
goals: '',
});
const breadcrumbs = computed(() => {
const username = effectiveUsername.value;
const crumbs = [
{
label: 'People',
route: { name: 'People' },
},
{
label: profile.data?.full_name || 'Профиль',
route: username ? {
name: 'Profile',
params: { username },
} : undefined,
},
];
console.log('[DEBUG] Хлебные крошки:', crumbs);
return crumbs;
});
const pageMeta = computed(() => {
const meta = {
title: profile.data?.full_name || 'Профиль',
description: profile.data?.headline || '',
};
console.log('[DEBUG] Мета-данные страницы:', meta);
return meta;
});
const displayName = computed(() => {
if (!profile.data) {
console.log('[DEBUG] displayName: profile.data не загружен');
return 'Загрузка...';
}
const name = profile.data?.full_name || `${form.value.first_name || ''} ${form.value.last_name || ''}`.trim();
console.log('[DEBUG] Отображаемое имя:', name);
return name;
});
const isSessionUser = () => {
const sessionUser = $user.data?.username;
const profileUser = effectiveUsername.value;
const isSession = sessionUser === profileUser;
console.log('[DEBUG] Проверка isSessionUser:', { sessionUser, profileUser, isSession });
return isSession;
};
function formattedDate(d) {
if (!d) return '';
try {
return new Date(d).toLocaleDateString('ru-RU');
} catch (e) {
console.error('[DEBUG] Ошибка форматирования даты:', e, { date: d });
return d;
}
}
function maskPrivate(val) {
if (!val) return '-';
if (val.includes('@')) {
const parts = val.split('@');
return parts[0].slice(0, 1) + '***@' + parts[1];
}
return val.slice(0, 3) + '***' + val.slice(-2);
}
function formatTelegram(t) {
if (!t) return '';
if (t.startsWith('t.me/') || t.startsWith('https://t.me/')) return (t.startsWith('http') ? t : 'https://' + t);
return 'https://t.me/' + t.replace(/^@/, '');
}
function fillFormFromProfile() {
console.log('[DEBUG] Заполнение формы:', {
schoolProfile: schoolProfile.data,
profile: profile.data,
currentForm: JSON.stringify(form.value, null, 2),
});
form.value.first_name = schoolProfile.data?.first_name || profile.data?.first_name || '';
form.value.last_name = schoolProfile.data?.last_name || profile.data?.last_name || '';
form.value.middle_name = schoolProfile.data?.middle_name || '';
form.value.birth_date = schoolProfile.data?.birth_date || '';
form.value.phone = schoolProfile.data?.phone || '';
form.value.email_private = schoolProfile.data?.email_private || '';
form.value.telegram = schoolProfile.data?.telegram || '';
form.value.child_name = schoolProfile.data?.child_name || '';
form.value.child_phone = schoolProfile.data?.child_phone || '';
form.value.child_email = schoolProfile.data?.child_email || '';
form.value.goals = schoolProfile.data?.goals || '';
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
function toggleEdit() {
editMode.value = !editMode.value;
if (editMode.value) fillFormFromProfile();
console.log('[DEBUG] Переключение режима редактирования:', { editMode: editMode.value });
}
function validateExams(exams) {
console.log('[DEBUG] Валидация exams:', { exams, validOptions: examOptions });
return exams.every(exam => examOptions.includes(exam));
}
function validateLearnSubjects(subjects) {
console.log('[DEBUG] Валидация learn_subjects:', { subjects, validOptions: learnOptions });
return subjects.every(subject => learnOptions.includes(subject));
}
async function saveProfile() {
console.log('[DEBUG] Сохранение профиля:', { form: form.value });
saving.value = true;
try {
// Создаём копию данных формы
const formData = { ...form.value };
console.log('[DEBUG] Копия formData:', JSON.stringify(formData, null, 2));
// Обновление full_name в User, если нужно
if (formData.first_name || formData.last_name) {
const fullName = `${formData.first_name || ''} ${formData.last_name || ''}`.trim();
console.log('[DEBUG] Обновление User.full_name:', { name: profile.data?.name, fullName });
await createResource({
url: 'frappe.client.set_value',
params: {
doctype: 'User',
name: profile.data?.name,
fieldname: 'full_name',
value: fullName,
},
}).submit();
}
// Получаем docname
let docname = '';
try {
await schoolProfile.reload();
console.log('[DEBUG] Schoolprofile:', { schoolProfile });
docname = schoolProfile?.data?.name;
console.log('[DEBUG] Выбранное имя документа:', docname);
} catch (error) {
console.log('[DEBUG] Ошибка загрузки schoolProfile, продолжаем с profile:', error.message);
}
// Формируем payload из копии данных формы
let payload = {
doctype: 'Schoolchildren Profile',
user: profile.data?.name,
first_name: formData.first_name,
last_name: formData.last_name,
middle_name: formData.middle_name,
birth_date: formData.birth_date,
phone: formData.phone,
email_private: formData.email_private,
telegram: formData.telegram,
child_name: formData.child_name,
child_phone: formData.child_phone,
child_email: formData.child_email,
goals: formData.goals,
last_updated: new Date().toISOString(),
};
console.log('[DEBUG] Сохранение Schoolchildren Profile (payload):', { docname, payload });
// Сохранение или создание документа
if (docname) {
await createResource({
url: 'frappe.client.save',
params: { doc: { ...schoolProfile.data, ...payload } },
}).submit();
} else {
await createResource({
url: 'frappe.client.insert',
params: { doc: payload },
}).submit();
}
editMode.value = false;
// После успешного сохранения в конце функции saveProfile
schoolProfileNotFound.value = false;
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint('Профиль сохранён');
console.log('[DEBUG] Профиль успешно сохранён');
} catch (e) {
console.error('[DEBUG] Ошибка при сохранении профиля:', e);
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint({
title: 'Ошибка',
message: (e && e.message) || 'Ошибка при сохранении',
indicator: 'red',
});
} finally {
saving.value = false;
}
await schoolProfile.reload();
}
onMounted(() => {
console.log('[DEBUG] Компонент смонтирован:', {
propsUsername: props.username,
sessionUsername: $user.data?.username,
user: user,
$user: $user.data,
});
if ($user.data) {
console.log('[DEBUG] Запуск profile.reload()');
profile.reload();
}
});
watch(
() => props.username,
(newUsername, oldUsername) => {
console.log('[DEBUG] Изменение props.username:', { old: oldUsername, new: newUsername });
profile.reload();
}
);
watch(
() => profile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение profile.data:', { old: oldData, new: newData });
if (newData) {
console.log('[DEBUG] Запуск schoolProfile.reload()');
schoolProfile.reload();
}
}
);
watch(
() => schoolProfile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение schoolProfile.data:', { old: oldData, new: newData });
if (newData && !editMode.value) {
console.log('[DEBUG] Заполнение формы из schoolProfile');
fillFormFromProfile();
}
}
);
watch(
() => effectiveUsername.value,
(newUsername) => {
console.log('[DEBUG] Изменение effectiveUsername для schoolProfile:', newUsername);
schoolProfile.update({
params: {
doctype: 'Schoolchildren Profile',
filters: { user: newUsername },
},
});
}
);
</script>

View File

@@ -124,19 +124,13 @@ const props = defineProps({
onMounted(() => {
if ($user.data) profile.reload()
setActiveTab()
})
const profile = createResource({
url: 'frappe.client.get',
makeParams(values) {
return {
doctype: 'User',
filters: {
username: props.username,
},
}
url: 'lms.lms.api.get_profile_details',
params: {
username: props.username,
},
})
@@ -194,24 +188,25 @@ const isSessionUser = () => {
return $user.data?.email === profile.data?.email
}
const hasHigherAccess = () => {
return $user.data?.is_evaluator || $user.data?.is_moderator
}
const getTabButtons = () => {
let buttons = [{ label: 'About' }, { label: 'Certificates' }]
if ($user.data?.is_moderator) buttons.push({ label: 'Roles' })
if (
isSessionUser() &&
($user.data?.is_evaluator || $user.data?.is_moderator)
) {
if (hasHigherAccess()) {
buttons.push({ label: 'Slots' })
buttons.push({ label: 'Schedule' })
}
return buttons
}
const breadcrumbs = computed(() => {
let crumbs = [
{
label: 'People',
label: __('People'),
},
{
label: profile.data?.full_name,

View File

@@ -29,6 +29,62 @@
{{ __('No introduction') }}
</div>
</div>
<!-- Points Section -->
<div class="mt-7 mb-10" v-if="energyPoints.data?.length">
<h2 class="mb-3 text-lg font-semibold text-ink-gray-9">
{{ __('Points') }}
</h2>
<h2 class="mb-3 text-lg font-semibold text-ink-gray-9">
{{ __('The last 10 score records have been uploaded') }}
</h2>
<ul class="space-y-4">
<li v-for="item in energyPoints.data.slice(0, 10)" :key="item.name" class="text-sm text-gray-700">
<div class="flex justify-between">
<span>{{ __('Points') }}: {{ item.points }}</span>
<span>{{ dayjs(item.creation).format('DD-MM-YYYY') }}</span>
</div>
<div v-if="item.rule" class="text-ink-gray-7">
{{ __('Reason') }}: {{ item.rule }}
</div>
</li>
</ul>
<div class="mt-4 text-sm">
<div class="font-semibold">
{{ __('Total Points') }}: {{ totalPoints }}
</div>
<div class="font-semibold">
{{ __('Additional Points for MPGU Admission') }}: {{ additionalPoints }}
</div>
</div>
</div>
<div v-else class="mt-7 text-ink-gray-7 text-sm italic">
{{ __('No points yet') }}
</div>
<!-- Courses Section -->
<div class="mt-7 mb-10" v-if="coursesWithTitles.length">
<h2 class="mb-3 text-lg font-semibold text-ink-gray-9">
{{ __('Completed Courses') }}
</h2>
<div class="grid grid-cols-1 gap-4">
<div v-for="course in coursesWithTitles" :key="course.name">
<a
:href="`/lms/courses/${course.course}`"
class="text-base text-ink-gray-9 hover:text-blue-600"
>
{{ course.title || course.course }} <!-- Отображаем title, если есть, иначе course -->
</a>
<div class="text-sm text-ink-gray-7">
{{ __('Completed on') }}: {{ dayjs(course.creation).format('DD MMM YYYY') }}
</div>
</div>
</div>
</div>
<div v-else class="mt-7 text-ink-gray-7 text-sm italic">
{{ __('No completed courses yet') }}
</div>
<div class="mt-7 mb-10" v-if="badges.data?.length">
<h2 class="mb-3 text-lg font-semibold text-ink-gray-9">
{{ __('Achievements') }}
@@ -114,7 +170,7 @@
</div>
</template>
<script setup>
import { inject } from 'vue'
import { inject, computed, ref, watch } from 'vue'
import { createResource, Popover, Button } from 'frappe-ui'
import { X, LinkedinIcon, Twitter } from 'lucide-vue-next'
import { sessionStore } from '@/stores/session'
@@ -153,6 +209,96 @@ const badges = createResource({
},
})
const courses = createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'LMS Course Progress',
fields: ['name', 'member', 'course', 'status', 'creation'],
filters: {
member: props.profile.data.email,
status: 'Complete',
},
},
auto: true,
onSuccess(data) {
console.log('LMS Course Progress data:', data) // Отладка
},
})
const courseTitles = ref({})
const coursesWithTitles = computed(() => {
if (!courses.data) return []
const result = courses.data.map(course => ({
...course,
title: courseTitles.value[course.course] || null,
}))
console.log('Courses with titles:', result) // Отладка
return result
})
// Запрашиваем title для каждого курса
watch(
() => courses.data,
(newCourses) => {
if (newCourses && newCourses.length) {
const courseIds = newCourses.map(course => course.course)
console.log('Course IDs:', courseIds) // Отладка
createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'LMS Course',
fields: ['name', 'title'],
filters: {
name: ['in', courseIds],
},
},
auto: true,
onSuccess(data) {
console.log('Raw course titles data:', data) // Отладка сырых данных
const titles = {}
data.forEach(course => {
titles[course.name] = course.title
})
courseTitles.value = titles
console.log('Processed course titles:', titles) // Отладка обработанных titles
},
onError(error) {
console.error('Error fetching course titles:', error) // Отладка ошибок
},
})
}
},
{ immediate: true }
)
const energyPoints = createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'Energy Point Log',
fields: ['name', 'user', 'points', 'rule', 'creation'],
filters: {
user: props.profile.data.email,
},
limit_page_length: 1000,
},
auto: true,
onSuccess(data) {
console.log('Energy Points data:', data) // Отладка
data.forEach(item => {
console.log('Points for', item.name, ':', item.points, typeof item.points)
})
},
})
const totalPoints = computed(() => {
return energyPoints.data?.reduce((sum, item) => sum + (item.points || 0), 0) || 0
})
const additionalPoints = computed(() => {
const points = Math.floor(totalPoints.value / 100)
return points < 10 ? points : 10
})
const shareOnSocial = (badge, medium) => {
let shareUrl
const url = encodeURIComponent(

View File

@@ -36,7 +36,7 @@
</Calendar>
</div>
</div>
<Event v-model="showEvent" :event="currentEvent" />
<Event v-if="showEvent" v-model="showEvent" :event="currentEvent" />
</template>
<script setup>
import { Calendar, createListResource, Button } from 'frappe-ui'
@@ -57,7 +57,7 @@ const props = defineProps({
const evaluations = createListResource({
doctype: 'LMS Certificate Request',
filters: {
evaluator: user.data?.name,
evaluator: props.profile.data?.name,
status: ['!=', 'Cancelled'],
},
fields: [

View File

@@ -43,18 +43,22 @@
:options="days"
v-model="slot.day"
@focusout.stop="update(slot.name, 'day', slot.day)"
:disabled="!isSessionUser()"
/>
<FormControl
type="time"
v-model="slot.start_time"
@focusout.stop="update(slot.name, 'start_time', slot.start_time)"
:disabled="!isSessionUser()"
/>
<FormControl
type="time"
v-model="slot.end_time"
@focusout.stop="update(slot.name, 'end_time', slot.end_time)"
:disabled="!isSessionUser()"
/>
<X
v-if="isSessionUser()"
@click="deleteRow(slot.name)"
class="w-6 h-auto stroke-1.5 text-red-900 rounded-md cursor-pointer p-1 bg-surface-red-2 hidden group-hover:block"
/>
@@ -69,20 +73,23 @@
:options="days"
v-model="newSlot.day"
@focusout.stop="add()"
:disabled="!isSessionUser()"
/>
<FormControl
type="time"
v-model="newSlot.start_time"
@focusout.stop="add()"
:disabled="!isSessionUser()"
/>
<FormControl
type="time"
v-model="newSlot.end_time"
@focusout.stop="add()"
:disabled="!isSessionUser()"
/>
</div>
<Button @click="showSlotsTemplate = 1">
<Button v-if="isSessionUser()" @click="showSlotsTemplate = 1">
<template #prefix>
<Plus class="w-4 h-4 stroke-1.5 text-ink-gray-7" />
</template>
@@ -98,6 +105,7 @@
type="date"
:label="__('From')"
v-model="from"
:disabled="!isSessionUser()"
@blur="
() => {
updateUnavailability.submit({
@@ -111,6 +119,7 @@
type="date"
:label="__('To')"
v-model="to"
:disabled="!isSessionUser()"
@blur="
() => {
updateUnavailability.submit({
@@ -122,7 +131,7 @@
/>
</div>
</div>
<div>
<div v-if="isSessionUser()">
<h2 class="mb-4 text-lg font-semibold text-ink-gray-9">
{{ __('My calendar') }}
</h2>
@@ -157,11 +166,19 @@ const props = defineProps({
})
onMounted(() => {
if (user.data?.name !== props.profile.data?.name) {
if (user.data?.name !== props.profile.data?.name && !hasHigherAccess()) {
window.location.href = `/user/${props.profile.data?.username}`
}
})
const hasHigherAccess = () => {
return user.data?.is_evaluator || user.data?.is_moderator
}
const isSessionUser = () => {
return user.data?.email === props.profile.data?.email
}
const showSlotsTemplate = ref(0)
const from = ref(null)
const to = ref(null)

View File

@@ -21,7 +21,7 @@
</div>
<div class="grid grid-cols-2 h-[calc(100vh_-_3rem)]">
<div class="border-r py-5 px-8 h-full">
<div class="font-semibold mb-2">
<div class="font-semibold mb-2 text-ink-gray-9">
{{ __('Problem Statement') }}
</div>
<div
@@ -31,7 +31,7 @@
</div>
<div>
<div class="flex items-center justify-between p-2 bg-surface-gray-2">
<div class="font-semibold">
<div class="font-semibold text-ink-gray-9">
{{ exercise.doc?.language }}
</div>
<div class="space-x-2">
@@ -89,7 +89,9 @@
class="py-3"
>
<div class="flex items-center mb-3">
<span class=""> {{ __('Test {0}').format(index + 1) }} - </span>
<span class="text-ink-gray-9">
{{ __('Test {0}').format(index + 1) }} -
</span>
<span
class="font-semibold ml-2 mr-1"
:class="
@@ -112,13 +114,13 @@
<div class="text-xs text-ink-gray-7">
{{ __('Input') }}
</div>
<div>{{ testCase.input }}</div>
<div class="text-ink-gray-9">{{ testCase.input }}</div>
</div>
<div class="space-y-2">
<div class="text-xs text-ink-gray-7">
{{ __('Your Output') }}
</div>
<div>
<div class="text-ink-gray-9">
{{ testCase.output }}
</div>
</div>
@@ -126,7 +128,9 @@
<div class="text-xs text-ink-gray-7">
{{ __('Expected Output') }}
</div>
<div>{{ testCase.expected_output }}</div>
<div class="text-ink-gray-9">
{{ testCase.expected_output }}
</div>
</div>
</div>
</div>
@@ -153,6 +157,7 @@ import { Play, X, Check, Settings } from 'lucide-vue-next'
import { sessionStore } from '@/stores/session'
import { useRouter } from 'vue-router'
import { openSettings } from '@/utils'
import { useSettings } from '@/stores/settings'
const user = inject<any>('$user')
const code = ref<string | null>('')
@@ -162,7 +167,8 @@ const errorMessage = ref<string | null>(null)
const testCaseSection = ref<HTMLElement | null>(null)
const testCases = ref<TestCase[]>([])
const boilerplate = ref<string>('')
const { brand, livecodeURL } = sessionStore()
const { brand } = sessionStore()
const { livecodeURL } = useSettings()
const router = useRouter()
const fromLesson = ref(false)
const falconURL = ref<string>('https://falcon.frappe.io/')

View File

@@ -3,7 +3,7 @@
class="sticky top-0 z-10 flex items-center justify-between border-b bg-surface-white px-3 py-2.5 sm:px-5"
>
<Breadcrumbs :items="breadcrumbs" />
<div v-if="!readOnlyMode" class="space-x-2">
<div v-if="!readOnlyMode" class="flex items-center space-x-2">
<Badge v-if="quizDetails.isDirty" theme="orange">
{{ __('Not Saved') }}
</Badge>

View File

@@ -11,6 +11,32 @@
>
<Quiz :quizName="quizID" />
</div>
<div>
<!--<button @click="toggleChatGPT" class="btn btn-primary">Решить с ChatGPT</button>-->
</div>
<div v-if="showChat" class="chat-container mt-4">
<h2>AI-тьютор</h2>
<div class="chat-window">
<div id="chat-box" class="chat-box">
<div v-for="(message, index) in chatHistory" :key="index" class="message">
<span :class="{ 'user-message': message.isUser, 'ai-message': !message.isUser }">
{{ message.text }}
</span>
</div>
<div v-if="chatHistory.length === 0" class="placeholder-text">Загрузка ответа...</div>
</div>
</div>
<div class="chat-input mt-4">
<input
v-model="userInput"
type="text"
placeholder="Введите ваше сообщение..."
class="w-full p-2 border rounded-md"
@keyup.enter="sendMessage"
/>
<button @click="sendMessage" class="btn btn-primary ml-2">Отправить</button>
</div>
</div>
</template>
<script setup>
import Quiz from '@/components/Quiz.vue'
@@ -24,6 +50,12 @@ const user = inject('$user')
const router = useRouter()
const fromLesson = ref(false)
const showChat = ref(false)
const chatResponse = ref(null) // Временная переменная для текущего ответа
const currentQuestionIndex = ref(0) // Индекс текущего вопроса
const userInput = ref('') // Поле для ввода сообщения
const chatHistory = ref([]) // История сообщений
onMounted(() => {
if (!user.data) {
router.push({ name: 'Courses' })
@@ -41,6 +73,21 @@ const props = defineProps({
},
})
const quizData = createResource({
url: 'frappe.client.get',
params: {
doctype: 'LMS Quiz',
name: props.quizID,
},
auto: true,
onSuccess: (data) => {
console.log('[DEBUG] quizData onSuccess:', data)
},
onError: (err) => {
console.error('[DEBUG] quizData onError:', err)
},
})
const title = createResource({
url: 'frappe.client.get_value',
params: {
@@ -63,4 +110,283 @@ usePageMeta(() => {
icon: brand.favicon,
}
})
const handleCurrentQuestion = (index) => {
currentQuestionIndex.value = index
console.log('[DEBUG] Текущий индекс вопроса из Quiz.vue:', index)
}
const sendMessage = async () => {
if (!userInput.value.trim()) return;
// Добавляем сообщение пользователя в историю
chatHistory.value.push({ text: userInput.value, isUser: true });
console.log('[DEBUG] Пользовательское сообщение:', userInput.value);
// Сбрасываем поле ввода
const userMessage = userInput.value;
userInput.value = '';
try {
console.log('[DEBUG] Отправка запроса к прокси с пользовательским сообщением...');
const res = await fetch('https://openai.enlightrussia.ru/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'a38ed6248c82e31f014b7459479d4c75154e41a331f8a4d9b4afc4b10cbc884a'
},
body: JSON.stringify({
prompt: generatePrompt(userMessage),
model: 'gpt-4o',
system_prompt: `Ты — опытный, доброжелательный и очень терпеливый учитель. Твоя задача — сопровождать ученика в самостоятельном разборе задачи, не раскрывая ему готовое решение и не выдавая правильного ответа напрямую.
Ни при каких условиях нельзя выдавать готовый ответ. Ученик должен сам дойти до него. Обязательно нужно разбирать процесс решений по шагам, задавая ученику по одному вопросу за один шаг и ожидая от него ответа.
Говори и отвечай на русском языке, простыми и понятными формулировками. Будь вежлив, отзывчив и дружелюбен. Показывай искреннее желание помочь. Подбадривай ученика, если он ошибается или затрудняется.`
})
});
console.log('[DEBUG] Ответ от прокси:', res.status, res.statusText);
if (!res.ok) {
const errorText = await res.text();
console.log('[DEBUG] Ошибка ответа от прокси:', errorText);
throw new Error(`Ошибка API: ${res.status} ${errorText}`);
}
const data = await res.json();
console.log('[DEBUG] Получен ответ от GPT:', data);
chatHistory.value.push({ text: data.answer, isUser: false });
} catch (err) {
console.error('[DEBUG] Ошибка в sendMessage:', err);
chatHistory.value.push({ text: `Ошибка: ${err.message}`, isUser: false });
}
};
const toggleChatGPT = async () => {
console.log('[DEBUG] toggleChatGPT вызван, showChat:', showChat.value);
showChat.value = !showChat.value;
if (!showChat.value) {
chatResponse.value = null;
chatHistory.value = [];
console.log('[DEBUG] Чат закрыт, chatResponse и история сброшены');
return;
}
try {
console.log('[DEBUG] Начало обработки, quizData:', quizData);
if (quizData.loading) {
chatHistory.value.push({ text: 'Загрузка данных квиза...', isUser: false });
console.log('[DEBUG] Данные квиза загружаются');
return;
}
if (quizData.error) {
throw new Error(`Ошибка загрузки квиза: ${quizData.error.message}`);
}
const quiz = quizData.data;
if (!quiz) {
chatHistory.value.push({ text: 'Данные квиза не загружены', isUser: false });
console.log('[DEBUG] quizData.data отсутствует');
return;
}
const quiz_title = quiz.title || 'Без названия';
console.log('[DEBUG] Получен quiz:', quiz, quiz_title);
if (!quiz.questions || quiz.questions.length === 0) {
chatHistory.value.push({ text: 'Вопросы не найдены', isUser: false });
console.log('[DEBUG] Вопросы не найдены в quiz:', quiz);
return;
}
// Используем текущий индекс
const currentQuestion = quiz.questions[currentQuestionIndex.value];
if (!currentQuestion?.question_detail) {
chatHistory.value.push({ text: 'Детали вопроса не найдены', isUser: false });
console.log('[DEBUG] Текущий вопрос отсутствует:', currentQuestion);
return;
}
// Создаём и ждём загрузки данных вопроса
const questionData = await new Promise((resolve) => {
const resource = createResource({
url: 'frappe.client.get',
params: {
doctype: 'LMS Question',
name: currentQuestion.question,
},
auto: true,
onSuccess: (data) => {
console.log('[DEBUG] questionData onSuccess:', data);
resolve(data);
},
onError: (err) => {
console.error('[DEBUG] questionData onError:', err);
resolve(null);
},
});
});
if (!questionData) {
chatHistory.value.push({ text: 'Данные вопроса не загружены', isUser: false });
console.log('[DEBUG] Данные вопроса отсутствуют');
return;
}
let questionDataPrompt, question, prompt, correct_answer, options = [], possibilitys = [];
if (questionData.type === "Choices") {
question = currentQuestion.question_detail;
options = [
questionData.option_1 || '',
questionData.option_2 || '',
questionData.option_3 || '',
questionData.option_4 || '',
].filter(Boolean);
correct_answer = null;
for (let i = 1; i <= 4; i++) {
if (questionData[`is_correct_${i}`] === 1) {
correct_answer = questionData[`option_${i}`];
console.log(`Правильный ответ ${i}:`, correct_answer);
break;
}
}
console.log('[DEBUG] Получен вопрос, варианты и ответ:', { question, options, correct_answer });
questionDataPrompt = `Это вопрос типа: ${questionData.type} из квиза под названием ${quiz_title}.\n${question}\nВарианты ответа: ${options.join(', ')}\равильный ответ: ${correct_answer}`;
console.log('[DEBUG] Данные для промта:', questionDataPrompt)
prompt = generatePrompt(questionDataPrompt);
} else if (questionData.type === "User Input") {
question = currentQuestion.question_detail;
possibilitys = [
questionData.possibility_1 || '',
questionData.possibility_2 || '',
questionData.possibility_3 || '',
questionData.possibility_4 || '',
].filter(Boolean);
console.log('[DEBUG] Получен вопрос и возможные варианты:', { question, possibilitys });
questionDataPrompt = `Это вопрос типа: ${questionData.type} из квиза под названием ${quiz_title}.\n${question}\nВозможные варианты ответа: ${possibilitys.join(', ')}`;
console.log('[DEBUG] Данные для промта:', questionDataPrompt)
prompt = generatePrompt(questionDataPrompt);
} else {
question = currentQuestion.question_detail;
console.log('[DEBUG] Получен вопрос:', { question });
questionDataPrompt = `Это вопрос типа: ${questionData.type} из квиза под названием ${quiz_title}.\n${question}`;
console.log('[DEBUG] Данные для промта:', questionDataPrompt)
prompt = generatePrompt(questionDataPrompt);
}
if (!question) {
chatHistory.value.push({ text: 'Текст вопроса не найден', isUser: false });
console.log('[DEBUG] Текст вопроса отсутствует в currentQuestion:', currentQuestion);
return;
}
console.log('[DEBUG] Сформирован промпт:', prompt);
console.log('[DEBUG] Отправка запроса к прокси...');
const res = await fetch('https://openai.enlightrussia.ru/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-KEY': 'a38ed6248c82e31f014b7459479d4c75154e41a331f8a4d9b4afc4b10cbc884a'
},
body: JSON.stringify({
prompt: prompt,
model: 'gpt-4o',
system_prompt: `1. Роль
Ты — опытный, доброжелательный и очень терпеливый учитель. Твоя задача — сопровождать ученика в самостоятельном разборе задачи, не раскрывая ему готовое решение и не выдавая правильного ответа напрямую.
Ни при каких условиях нельзя выдавать готовый ответ. Ученик должен сам дойти до него. Обязательно нужно разбирать процесс решений по шагам, задавая ученику по одному вопросу за один шаг и ожидая от него ответа.
2. Стиль общения
Говори и отвечай на русском языке, простыми и понятными формулировками.
Будь вежлив, отзывчив и дружелюбен.
Показывай искреннее желание помочь.
Подбадривай ученика, если он ошибается или затрудняется.
3. Пошаговый подход
Начинай с запроса к ученику: попроси его показать или описать задание. Если возможно, пусть он загрузит скриншот, документ или текст задания.
Не говори финальный ответ сразу. Вместо этого:
1. Спроси, что ученик уже знает или какие идеи у него есть.
2. Дай наводящие вопросы, чтобы понять, в каком месте он испытывает затруднение.
3. Подсказывай принципы или формулы, которые могут помочь, но не окончательный результат.
4. Делай это пошагово, пока ученик не найдёт решение самостоятельно (или не выскажет версию, близкую к правильной).
При необходимости:
Повтори ключевые определения и формулы.
Предложи разобрать аналогичный, но более простой пример. Обязательно нужно разбирать процесс решений по шагам, задавая ученику по одному вопросу за один шаг и ожидая от него ответа. Ни в коем случае не давай сразу решение.`
})
});
console.log('[DEBUG] Ответ от прокси:', res.status, res.statusText);
if (!res.ok) {
const errorText = await res.text();
console.log('[DEBUG] Ошибка ответа от прокси:', errorText);
throw new Error(`Ошибка API: ${res.status} ${errorText}`);
}
const data = await res.json();
console.log('[DEBUG] Получен ответ от GPT:', data);
chatHistory.value.push({ text: data.answer, isUser: false });
chatResponse.value = null; // Сбрасываем chatResponse после добавления в историю
} catch (err) {
console.error('[DEBUG] Ошибка в toggleChatGPT:', err);
chatHistory.value.push({ text: `Ошибка: ${err.message}`, isUser: false });
chatResponse.value = null;
}
};
// Функция для генерации промпта с историей
const generatePrompt = (userMsg) => {
let prompt = `Текущая задача: "${userMsg}".\n`;
prompt += 'История диалога:\n';
chatHistory.value.forEach(msg => {
prompt += `${msg.isUser ? 'Ученик' : 'Учитель'}: ${msg.text}\n`;
});
prompt += `\nНовое сообщение от ученика: ${userMsg}`;
return prompt;
};
//updateDocumentTitle(pageMeta)
</script>
<style scoped>
.chat-container {
max-width: 700px;
margin: 0 auto;
padding: 20px;
border: 1px solid #e5e7eb;
border-radius: 8px;
background: #fff;
}
.chat-window {
max-height: 400px;
overflow-y: auto;
padding: 10px;
border: 1px solid #e5e7eb;
border-radius: 4px;
}
.chat-box {
min-height: 100px;
}
.placeholder-text {
color: #94a3b8;
text-align: center;
}
.message {
margin: 5px 0;
}
.user-message {
background-color: #e3f2fd;
padding: 5px 10px;
border-radius: 5px;
display: inline-block;
}
.ai-message {
background-color: #f0f0f0;
padding: 5px 10px;
border-radius: 5px;
display: inline-block;
}
.chat-input input {
border: 1px solid #e5e7eb;
}
.btn-primary {
background-color: #2563eb;
color: white;
padding: 8px 16px;
border-radius: 4px;
}
</style>

View File

@@ -56,8 +56,8 @@
<span class="font-semibold"> {{ __('Question') }}: </span>
<span class="leading-5" v-html="row.question"> </span>
</div>
<div class="">
<span class="font-semibold"> {{ __('Answer') }} </span>
<div class="text-ink-gray-9">
<span class="font-semibold"> {{ __('Answer') }}: </span>
<span class="leading-5" v-html="row.answer"></span>
</div>
<div class="grid grid-cols-2 gap-5">

View File

@@ -5,7 +5,7 @@
<Breadcrumbs :items="breadcrumbs" />
</header>
<div v-if="submissions.data?.length" class="md:w-3/4 md:mx-auto py-5 mx-5">
<div class="text-xl font-semibold mb-5">
<div class="text-xl font-semibold mb-5 text-ink-gray-9">
{{ submissions.data[0].quiz_title }}
</div>
<ListView
@@ -40,7 +40,7 @@
</Button>
</div>
</div>
<EmptyState v-else />
<EmptyState v-else type="Quiz Submissions" />
</template>
<script setup>
import {

View File

@@ -0,0 +1,923 @@
<template>
<div class="min-h-screen bg-white">
<NoPermission v-if="!$user.data" />
<div v-else-if="profile.error" class="p-6">
<div class="max-w-4xl mx-auto bg-white rounded-xl shadow-sm p-6 border border-red-200">
<p class="text-red-500 text-lg font-medium">Ошибка загрузки профиля: {{ profile.error.message }}</p>
</div>
</div>
<div v-else-if="profile.data">
<header class="sticky top-0 z-10 flex items-center justify-between bg-white px-6 py-4">
<Breadcrumbs class="h-7" :items="breadcrumbs" />
</header>
<div class="mx-auto max-w-6xl px-4 py-6">
<!-- Profile Header -->
<div v-if="!schoolProfileNotFound" class="bg-gradient-to-r from-teal-100 to-teal-600 rounded-2xl shadow-sm border border-gray-200 p-6 -mt-4 relative">
<div class="flex flex-col md:flex-row md:items-center gap-6">
<div class="flex-1">
<h2 class="text-3xl font-bold text-gray-900">{{ displayName }}</h2>
<div
v-if="profile.data.bio"
v-html="
DOMPurify.sanitize(decodeEntities(profile.data.bio), {
ALLOWED_TAGS: [
'b',
'i',
'em',
'strong',
'a',
'p',
'br',
'ul',
'ol',
'li',
'img',
],
ALLOWED_ATTR: ['href', 'target', 'rel', 'src'],
})
"
class="ProseMirror prose prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-outline-gray-2 prose-th:border-outline-gray-2 prose-td:relative prose-th:relative prose-th:bg-surface-gray-2 prose-sm max-w-none !whitespace-normal mt-2 text-gray-700"
></div>
</div>
<div v-if="$user.data && isSessionUser() && !schoolProfileNotFound" class="md:ml-auto">
<Button @click="toggleEdit()" class="bg-white hover:bg-gray-100 px-5 py-2.5 rounded-lg transition-colors duration-200">
<template #prefix>
<Edit class="w-4 h-4 stroke-1.5" />
</template>
{{ editMode ? 'Отменить редактирование' : 'Редактировать профиль' }}
</Button>
</div>
</div>
</div>
<!-- VIEW MODE -->
<div v-if="!editMode" class="mt-6">
<!-- Пустой профиль -->
<div v-if="schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="p-8 text-center">
<div class="max-w-md mx-auto">
<div class="mx-auto w-20 h-20 bg-teal-100 rounded-full flex items-center justify-center mb-6">
<svg class="w-10 h-10 text-teal-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
</svg>
</div>
<h3 class="text-2xl font-bold text-gray-900 mb-3">Профиль школьника еще не заполнен</h3>
<p class="text-gray-600 mb-6">
Чтобы получить доступ ко всем возможностям платформы, заполните информацию о себе.
Это поможет наставникам лучше понять ваши интересы и цели.
</p>
<div class="bg-teal-50 border border-teal-100 rounded-lg p-5 mb-6 text-left">
<h4 class="font-semibold text-teal-800 mb-3 flex items-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd" />
</svg>
Заполнив профиль, вы получите:
</h4>
<ul class="space-y-2 text-sm text-gray-700">
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Персонализированные рекомендации по обучению</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Подбор наставников по вашим интересам</span>
</li>
<li class="flex items-start gap-2">
<svg class="w-4 h-4 text-teal-500 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd" />
</svg>
<span>Доступ к закрытым мероприятиям и курсам</span>
</li>
</ul>
</div>
<Button
@click="toggleEdit()"
class="bg-teal-600 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 shadow-sm hover:shadow-md"
>
<template #prefix>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" />
</svg>
</template>
Заполнить профиль школьника
</Button>
</div>
</div>
</div>
<!-- Загружающийся профиль -->
<div v-else-if="schoolProfile.loading" class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="flex items-center justify-center py-12">
<div class="animate-spin rounded-full h-12 w-12 border-b-2 border-primary-600"></div>
</div>
</div>
<!-- Ошибка загрузки (кроме DoesNotExistError) -->
<div v-else-if="schoolProfile.error && !schoolProfileNotFound" class="bg-white rounded-2xl shadow-sm border border-red-200 p-6">
<p class="text-red-500 text-lg font-medium">Ошибка загрузки данных школьника: {{ schoolProfile.error.message }}</p>
</div>
<!-- Загруженный профиль -->
<div v-else-if="schoolProfile.data && !schoolProfileNotFound" class="space-y-6">
<!-- Основная информация -->
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Основная информация</h3>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Фамилия:</span>
<span class="text-gray-900">{{ schoolProfile.data.last_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Имя:</span>
<span class="text-gray-900">{{ schoolProfile.data.first_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Отчество:</span>
<span class="text-gray-900">{{ schoolProfile.data.middle_name || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Дата рождения:</span>
<span class="text-gray-900">{{ formattedDate(schoolProfile.data.birth_date) || '—' }}</span>
</div>
</div>
<div class="space-y-4">
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Школа:</span>
<span class="text-gray-900">{{ schoolProfile.data.school || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Класс:</span>
<span class="text-gray-900">{{ schoolProfile.data.grade || '—' }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Телефон:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.phone) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Email:</span>
<span class="text-gray-900 font-mono">{{ maskPrivate(schoolProfile.data.email_private) }}</span>
</div>
<div class="flex items-start">
<span class="inline-block w-48 text-gray-700 font-medium">Telegram:</span>
<div class="flex-1">
<a v-if="schoolProfile.data.telegram"
:href="formatTelegram(schoolProfile.data.telegram)"
target="_blank"
class="inline-flex items-center gap-2 text-primary-600 hover:text-primary-700 font-medium transition-colors">
<span>{{ schoolProfile.data.telegram.replace('@', '') }}</span>
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.19-.14.75-.42 1-.68 1.03-.58.05-1.02-.38-1.58-.75-.88-.58-1.38-.94-2.23-1.5-.99-.65-.35-1.01.22-1.59.15-.15 2.71-2.48 2.76-2.69.01-.03.01-.14-.06-.2-.07-.06-.17-.04-.24-.02-.1.02-1.69 1.09-4.78 3.2-.45.31-.86.46-1.23.45-.41-.01-1.2-.23-1.79-.42-.72-.23-1.29-.36-1.24-.76.03-.24.37-.48 1.01-.74 3.97-1.67 6.62-2.77 7.94-3.31 3.26-1.33 3.94-1.56 4.38-1.56.08 0 .27.02.39.12.1.08.13.19.14.27-.01.06.01.24 0 .38z"/>
</svg>
</a>
<span v-else class="text-gray-500">—</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ЕГЭ и Предметы для обучения -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">ЕГЭ (планируется)</h3>
</div>
<div class="p-6">
<div v-if="schoolProfile.data.exams && schoolProfile.data.exams.length > 0" class="flex flex-wrap gap-2">
<span v-for="exam in schoolProfile.data.exams" :key="exam"
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-teal-100">
{{ exam }}
</span>
</div>
<p v-else class="text-gray-500 italic">Не указано</p>
</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Чему хочется научиться</h3>
</div>
<div class="p-6">
<div v-if="schoolProfile.data.learn_subjects && schoolProfile.data.learn_subjects.length > 0" class="flex flex-wrap gap-2">
<span v-for="subject in schoolProfile.data.learn_subjects" :key="subject"
class="inline-flex items-center px-3 py-1 rounded-full text-sm font-medium bg-teal-100">
{{ subject }}
</span>
</div>
<p v-else class="text-gray-500 italic">Не указано</p>
</div>
</div>
</div>
<!-- О себе, интересах и мечтах -->
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Коротко о своих интересах</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.interests || 'Информация не указана' }}</p>
</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Коротко о себе</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.about_me || 'Информация не указана' }}</p>
</div>
</div>
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Коротко о мечтах</h3>
</div>
<div class="p-6">
<p class="text-gray-700 leading-relaxed whitespace-pre-line">{{ schoolProfile.data.dreams || 'Информация не указана' }}</p>
</div>
</div>
</div>
</div>
<div v-else class="bg-white rounded-2xl shadow-sm border border-gray-200 p-8">
<div class="text-center py-12">
<div class="mx-auto w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/>
</svg>
</div>
<h3 class="text-xl font-semibold text-gray-900 mb-2">Данные профиля не найдены</h3>
<p class="text-gray-600">Информация о школьнике отсутствует</p>
</div>
</div>
</div>
<!-- EDIT MODE -->
<div v-else class="mt-6">
<div class="bg-white rounded-2xl shadow-sm border border-gray-200 overflow-hidden">
<div class="px-6 py-4 border-b border-gray-100 bg-teal-400">
<h3 class="text-xl font-semibold text-white">Редактирование профиля школьника</h3>
<p class="text-sm text-gray-200 mt-1">Заполните информацию о себе</p>
</div>
<div class="p-6">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Левая колонка -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Личная информация</h4>
<Input
v-model="form.last_name"
label="Фамилия"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.first_name"
label="Имя"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.middle_name"
label="Отчество"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Дата рождения</label>
<DatePicker
v-model="form.birth_date"
class="w-full bg-gray-50 border-gray-300 rounded-lg focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<Input
v-model="form.phone"
label="Телефон (не публиковать)"
placeholder="+7 (XXX) XXX-XX-XX"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.email_private"
label="Email (не публиковать)"
type="email"
placeholder="example@email.com"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Input
v-model="form.telegram"
label="Telegram"
placeholder="username или t.me/username"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<!-- Правая колонка -->
<div class="space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Образование</h4>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Школа</label>
<input
type="text"
v-model="schoolQuery"
@input="debouncedSearchSchool"
class="w-full bg-gray-50 border border-gray-300 rounded-lg px-4 py-2.5 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent transition-colors"
placeholder="Начните вводить название школы"
/>
<div v-if="schoolResults.length" class="mt-2 border border-gray-300 rounded-lg overflow-hidden shadow-lg bg-white">
<div
v-for="s in schoolResults"
:key="s.school"
class="p-3 cursor-pointer hover:bg-primary-50 border-b border-gray-100 last:border-b-0 transition-colors"
@click="selectSchool(s)"
>
<div class="font-medium text-gray-900">{{ s.school }}</div>
<div class="text-xs text-gray-500 mt-1">{{ s.adress }}</div>
</div>
</div>
<div v-if="form.school_name && !schoolResults.length" class="mt-2 text-sm text-gray-600">
<span class="font-medium">Выбрана:</span> {{ form.school_name }}
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Класс</label>
<Select
v-model="form.grade"
:options="['10', '11']"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
<div>
<label class="block mb-3 font-medium text-gray-700">ЕГЭ (отметьте):</label>
<div class="grid grid-cols-2 gap-3 max-h-48 overflow-y-auto p-3 border border-gray-200 rounded-lg bg-gray-50">
<label v-for="e in examOptions" :key="e" class="flex items-center space-x-3 p-2 hover:bg-white rounded-md transition-colors cursor-pointer">
<input type="checkbox" :value="e" v-model="form.exams"
class="h-4 w-4 text-teal-600 focus:ring-teal-500 border-gray-300 rounded" />
<span class="text-sm text-gray-700">{{ e }}</span>
</label>
</div>
<p v-if="form.exams.length > 0" class="mt-2 text-sm text-gray-600">
Выбрано: {{ form.exams.length }} предмет(ов)
</p>
</div>
<div>
<label class="block mb-3 font-medium text-gray-700">Чему хочется научиться:</label>
<div class="grid grid-cols-2 gap-3 max-h-48 overflow-y-auto p-3 border border-gray-200 rounded-lg bg-gray-50">
<label v-for="s in learnOptions" :key="s" class="flex items-center space-x-3 p-2 hover:bg-white rounded-md transition-colors cursor-pointer">
<input type="checkbox" :value="s" v-model="form.learn_subjects"
class="h-4 w-4 text-teal-600 focus:ring-teal-500 border-gray-300 rounded" />
<span class="text-sm text-gray-700">{{ s }}</span>
</label>
</div>
<p v-if="form.learn_subjects.length > 0" class="mt-2 text-sm text-gray-600">
Выбрано: {{ form.learn_subjects.length }} направлений
</p>
</div>
</div>
</div>
<!-- Текстовые поля -->
<div class="mt-8 space-y-6">
<h4 class="text-lg font-semibold text-gray-900 border-b pb-2">Дополнительная информация</h4>
<Textarea
v-model="form.interests"
label="Коротко о своих интересах (2-3 предложения)"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<Textarea
v-model="form.about_me"
label="Коротко о себе"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
<Textarea
v-model="form.dreams"
label="Коротко о своих мечтах"
rows="4"
class="bg-gray-50 border-gray-300 focus:border-primary-500 focus:ring-primary-500"
/>
</div>
</div>
<!-- Кнопки действий -->
<div class="mt-8 pt-6 border-t border-gray-200 flex gap-3">
<Button
@click="saveProfile"
:loading="saving"
class="bg-teal-400 hover:bg-teal-700 text-white px-8 py-3 rounded-lg font-medium transition-colors duration-200 flex items-center gap-2"
>
{{ saving ? 'Сохранение...' : 'Сохранить изменения' }}
</Button>
<Button
variant="outline"
@click="toggleEdit()"
class="border-gray-300 text-gray-700 hover:bg-gray-50 px-6 py-3 rounded-lg font-medium transition-colors duration-200"
>
Отмена
</Button>
</div>
</div>
</div>
</div>
</div>
</div>
<div v-else class="flex items-center justify-center min-h-screen">
<div class="text-center">
<div class="animate-spin rounded-full h-16 w-16 border-b-2 border-primary-600 mx-auto"></div>
<p class="mt-4 text-lg text-gray-600">Загрузка профиля...</p>
</div>
</div>
</div>
</template>
<style scoped>
/* Плавные переходы для интерактивных элементов */
.border-gray-300 {
transition: border-color 0.2s ease;
}
.bg-primary-50 {
background-color: rgba(59, 130, 246, 0.05);
}
/* Стилизация скроллбара для выпадающих списков */
.overflow-y-auto::-webkit-scrollbar {
width: 6px;
}
.overflow-y-auto::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 3px;
}
.overflow-y-auto::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 3px;
}
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
background: #a1a1a1;
}
</style>
<!-- Скрипт остается без изменений -->
<script setup>
import { ref, computed, inject, watch, onMounted } from 'vue';
import { Breadcrumbs, createResource, Button, Input, DatePicker, Select, Textarea } from 'frappe-ui';
import { sessionStore } from '@/stores/session';
import NoPermission from '@/components/NoPermission.vue';
import { Edit } from 'lucide-vue-next';
import { convertToTitleCase, updateDocumentTitle } from '@/utils';
import debounce from 'lodash/debounce';
import { decodeEntities } from '@/utils'
import DOMPurify from 'dompurify'
const { user } = sessionStore();
const $user = inject('$user');
const schoolProfileNotFound = ref(false);
// Логирование инициализации
console.log('[DEBUG] Инициализация компонента:', {
user: user,
$user: $user.data,
username: $user.data?.username,
});
const props = defineProps({
username: {
type: String,
required: false,
default: '',
},
});
const effectiveUsername = computed(() => {
const username = props.username || $user.data?.username || '';
console.log('[DEBUG] Вычисление effectiveUsername:', { propsUsername: props.username, sessionUsername: $user.data?.username, result: username });
return username;
});
const editMode = ref(false);
const saving = ref(false);
const examOptions = [
'Русский язык', 'Математика(базовый)', 'Математика(профильный)', 'Физика', 'Химия', 'Информатика',
'Биология', 'История', 'География', 'Английский язык', 'Немецкий язык', 'Французский язык', 'Испанский язык',
'Китайский язык', 'Обществознание', 'Литература'
];
const learnOptions = [
'Программирование', 'Дизайн', 'Актерское мастерство', 'Риторика', 'Робототехника', 'Иностранные языки',
'Математика углубленно', 'Физика углубленно'
];
const profile = createResource({
url: 'frappe.client.get',
makeParams(values) {
const username = effectiveUsername.value;
console.log('[DEBUG] Запрос profile:', { doctype: 'User', filters: { username } });
return {
doctype: 'User',
filters: { username },
};
},
onSuccess(data) {
console.log('[DEBUG] Профиль загружен:', data);
},
onError(error) {
console.error('[DEBUG] Ошибка загрузки профиля:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль пользователя: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
},
});
const schoolProfile = createResource({
url: 'frappe.client.get',
params: {
doctype: 'Schoolchildren Profile',
filters: { user:user },
},
auto: false,
transform(data) {
if (!data) {
schoolProfileNotFound.value = true;
return null;
}
let doc = data || {};
console.log('[DEBUG] Данные schoolProfile до трансформации:', doc);
try {
doc.exams = doc.exams ? doc.exams.map(e => e.exam_subject) : [];
doc.learn_subjects = doc.learn_subjects ? doc.learn_subjects.map(s => s.learn_subject) : [];
} catch (e) {
console.error('[DEBUG] Ошибка трансформации данных:', e);
doc.exams = [];
doc.learn_subjects = [];
}
console.log('[DEBUG] Данные schoolProfile после трансформации:', doc);
return doc;
},
onSuccess(data) {
console.log('[DEBUG] Профиль школьника загружен:', data);
},
onError(error) {
// Проверяем, является ли ошибка "не найдено"
if (error.exc_type === 'DoesNotExistError' || error.message?.includes('DoesNotExist')) {
console.log('[DEBUG] Профиль школьника не найден, создаем новый');
schoolProfileNotFound.value = true;
} else {
console.error('[DEBUG] Ошибка загрузки профиля школьника:', error);
window.frappe?.msgprint({
title: 'Ошибка',
message: 'Не удалось загрузить профиль школьника: ' + (error.message || 'Неизвестная ошибка'),
indicator: 'red',
});
}
},
});
const form = ref({
first_name: '',
last_name: '',
middle_name: '',
birth_date: '',
school: '',
//school_name: '',
grade: '',
phone: '',
email_private: '',
telegram: '',
exams: [],
learn_subjects: [],
interests: '',
about_me: '',
dreams: ''
});
const breadcrumbs = computed(() => {
const username = effectiveUsername.value;
const crumbs = [
{
label: 'People',
route: { name: 'People' },
},
{
label: profile.data?.full_name || 'Профиль',
route: username ? {
name: 'Profile',
params: { username },
} : undefined,
},
];
console.log('[DEBUG] Хлебные крошки:', crumbs);
return crumbs;
});
const pageMeta = computed(() => {
const meta = {
title: profile.data?.full_name || 'Профиль',
description: profile.data?.headline || '',
};
console.log('[DEBUG] Мета-данные страницы:', meta);
return meta;
});
const displayName = computed(() => {
if (!profile.data) {
console.log('[DEBUG] displayName: profile.data не загружен');
return 'Загрузка...';
}
const name = profile.data?.full_name || `${form.value.first_name || ''} ${form.value.last_name || ''}`.trim();
console.log('[DEBUG] Отображаемое имя:', name);
return name;
});
const isSessionUser = () => {
const sessionUser = $user.data?.username;
const profileUser = effectiveUsername.value;
const isSession = sessionUser === profileUser;
console.log('[DEBUG] Проверка isSessionUser:', { sessionUser, profileUser, isSession });
return isSession;
};
function formattedDate(d) {
if (!d) return '';
try {
return new Date(d).toLocaleDateString('ru-RU');
} catch (e) {
console.error('[DEBUG] Ошибка форматирования даты:', e, { date: d });
return d;
}
}
function maskPrivate(val) {
if (!val) return '-';
if (val.includes('@')) {
const parts = val.split('@');
return parts[0].slice(0, 1) + '***@' + parts[1];
}
return val.slice(0, 3) + '***' + val.slice(-2);
}
function formatTelegram(t) {
if (!t) return '';
if (t.startsWith('t.me/') || t.startsWith('https://t.me/')) return (t.startsWith('http') ? t : 'https://' + t);
return 'https://t.me/' + t.replace(/^@/, '');
}
function fillFormFromProfile() {
console.log('[DEBUG] Заполнение формы:', {
schoolProfile: schoolProfile.data,
profile: profile.data,
currentForm: JSON.stringify(form.value, null, 2),
});
form.value.first_name = schoolProfile.data?.first_name || profile.data?.first_name || '';
form.value.last_name = schoolProfile.data?.last_name || profile.data?.last_name || '';
form.value.middle_name = schoolProfile.data?.middle_name || '';
form.value.birth_date = schoolProfile.data?.birth_date || '';
form.value.school = schoolProfile.data?.school || '';
form.value.grade = schoolProfile.data?.grade || '';
form.value.phone = schoolProfile.data?.phone || '';
form.value.email_private = schoolProfile.data?.email_private || '';
form.value.telegram = schoolProfile.data?.telegram || '';
form.value.exams = schoolProfile.data?.exams ? schoolProfile.data.exams : [];
form.value.learn_subjects = schoolProfile.data?.learn_subjects ? schoolProfile.data.learn_subjects : [];
form.value.interests = schoolProfile.data?.interests || '';
form.value.about_me = schoolProfile.data?.about_me || '';
form.value.dreams = schoolProfile.data?.dreams || '';
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
function toggleEdit() {
editMode.value = !editMode.value;
if (editMode.value) fillFormFromProfile();
console.log('[DEBUG] Переключение режима редактирования:', { editMode: editMode.value });
}
function validateExams(exams) {
console.log('[DEBUG] Валидация exams:', { exams, validOptions: examOptions });
return exams.every(exam => examOptions.includes(exam));
}
function validateLearnSubjects(subjects) {
console.log('[DEBUG] Валидация learn_subjects:', { subjects, validOptions: learnOptions });
return subjects.every(subject => learnOptions.includes(subject));
}
async function saveProfile() {
console.log('[DEBUG] Сохранение профиля:', { form: form.value });
saving.value = true;
try {
// Создаём копию данных формы
const formData = { ...form.value };
console.log('[DEBUG] Копия formData:', JSON.stringify(formData, null, 2));
// Обновление full_name в User, если нужно
if (formData.first_name || formData.last_name) {
const fullName = `${formData.first_name || ''} ${formData.last_name || ''}`.trim();
console.log('[DEBUG] Обновление User.full_name:', { name: profile.data?.name, fullName });
await createResource({
url: 'frappe.client.set_value',
params: {
doctype: 'User',
name: profile.data?.name,
fieldname: 'full_name',
value: fullName,
},
}).submit();
}
// Получаем docname
let docname = '';
try {
await schoolProfile.reload();
console.log('[DEBUG] Schoolprofile:', { schoolProfile });
docname = schoolProfile?.data?.name;
console.log('[DEBUG] Выбранное имя документа:', docname);
} catch (error) {
console.log('[DEBUG] Ошибка загрузки schoolProfile, продолжаем с profile:', error.message);
}
// Формируем payload из копии данных формы
let payload = {
doctype: 'Schoolchildren Profile',
user: profile.data?.name,
first_name: formData.first_name,
last_name: formData.last_name,
middle_name: formData.middle_name,
birth_date: formData.birth_date,
school: formData.school || '',
grade: formData.grade,
phone: formData.phone,
email_private: formData.email_private,
telegram: formData.telegram,
exams: Array.isArray(formData.exams) ? formData.exams.map(exam => ({ exam_subject: exam })) : [],
learn_subjects: Array.isArray(formData.learn_subjects) ? formData.learn_subjects.map(subject => ({ learn_subject: subject })) : [],
interests: formData.interests,
about_me: formData.about_me,
dreams: formData.dreams,
last_updated: new Date().toISOString(),
};
console.log('[DEBUG] Сохранение Schoolchildren Profile (payload):', { docname, payload });
// Сохранение или создание документа
if (docname) {
await createResource({
url: 'frappe.client.save',
params: { doc: { ...schoolProfile.data, ...payload } },
}).submit();
} else {
await createResource({
url: 'frappe.client.insert',
params: { doc: payload },
}).submit();
}
editMode.value = false;
schoolProfileNotFound.value = false;
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint('Профиль сохранён');
console.log('[DEBUG] Профиль успешно сохранён');
} catch (e) {
console.error('[DEBUG] Ошибка при сохранении профиля:', e);
if (window.frappe && window.frappe.msgprint) window.frappe.msgprint({
title: 'Ошибка',
message: (e && e.message) || 'Ошибка при сохранении',
indicator: 'red',
});
} finally {
saving.value = false;
}
await schoolProfile.reload();
}
const schoolQuery = ref('');
const schoolResults = ref([]);
async function searchSchool(q) {
if (!q) {
schoolResults.value = [];
return;
}
try {
console.log('[DEBUG] Поиск школы:', { query: q });
const res = await createResource({
url: 'frappe.client.get_list',
params: {
doctype: 'Schools',
fields: ['school', 'address'],
filters: [['school', 'like', '%' + q + '%']],
limit_page_length: 20,
},
}).submit();
schoolResults.value = res || [];
console.log('[DEBUG] Результаты поиска школы:', schoolResults.value);
} catch (e) {
schoolResults.value = [];
console.error('[DEBUG] Ошибка поиска школы:', e);
}
}
const debouncedSearchSchool = debounce(() => searchSchool(schoolQuery.value), 300);
function selectSchool(s) {
form.value.school = s.school;
//form.value.school_name = s.school_name;
schoolResults.value = [];
schoolQuery.value = s.school;
console.log('[DEBUG] Выбрана школа:', { school: s });
console.log('[DEBUG] Форма после заполнения:', JSON.stringify(form.value, null, 2));
}
onMounted(() => {
console.log('[DEBUG] Компонент смонтирован:', {
propsUsername: props.username,
sessionUsername: $user.data?.username,
user: user,
$user: $user.data,
});
if ($user.data) {
console.log('[DEBUG] Запуск profile.reload()');
profile.reload();
}
});
watch(
() => props.username,
(newUsername, oldUsername) => {
console.log('[DEBUG] Изменение props.username:', { old: oldUsername, new: newUsername });
profile.reload();
}
);
watch(
() => profile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение profile.data:', { old: oldData, new: newData });
if (newData) {
console.log('[DEBUG] Запуск schoolProfile.reload()');
schoolProfile.reload();
}
}
);
watch(
() => schoolProfile.data,
(newData, oldData) => {
console.log('[DEBUG] Изменение schoolProfile.data:', { old: oldData, new: newData });
if (newData && !editMode.value && !schoolProfileNotFound.value) {
console.log('[DEBUG] Заполнение формы из schoolProfile');
fillFormFromProfile();
}
}
);
watch(
() => effectiveUsername.value,
(newUsername) => {
console.log('[DEBUG] Изменение effectiveUsername для schoolProfile:', newUsername);
schoolProfile.update({
params: {
doctype: 'Schoolchildren Profile',
filters: { user: newUsername },
},
});
}
);
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
<template>
<div class="min-h-screen p-6">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Тестовая страница</h1>
</div>
</div>
</template>

View File

@@ -9,6 +9,43 @@ const routes = [
name: 'Home',
component: () => import('@/pages/Home/Home.vue'),
},
//Test of page
{
path: '/test',
name: 'Test',
component: () => import('@/pages/Test.vue'),
},
{
path: '/schoolchildren',
name: 'SchoolchildrenProfile',
component: () => import('@/pages/SchoolchildrenProfile.vue'),
},
{
path: '/student',
name: 'StudentProfile',
component: () => import('@/pages/StudentProfile.vue'),
},
{
path: '/coursecreator',
name: 'CourseCreatorProfile',
component: () => import('@/pages/CourseCreatorProfile.vue'),
},
{
path: '/parent',
name: 'ParentProfile',
component: () => import('@/pages/ParentProfile.vue'),
},
{
path: '/mypoints',
name: 'MyPoints',
component: () => import('@/pages/MyPoints.vue'),
},
{
path: '/leaderboard',
name: 'LeaderBoard',
component: () => import('@/pages/LeaderBoard.vue'),
},
// End of test of page
{
path: '/courses',
name: 'Courses',

View File

@@ -54,16 +54,6 @@ export const sessionStore = defineStore('lms-session', () => {
},
})
const livecodeURL = createResource({
url: 'frappe.client.get_single_value',
params: {
doctype: 'LMS Settings',
field: 'livecode_url',
},
cache: 'livecodeURL',
auto: user.value ? true : false,
})
return {
user,
isLoggedIn,
@@ -71,6 +61,5 @@ export const sessionStore = defineStore('lms-session', () => {
logout,
brand,
branding,
livecodeURL,
}
})

View File

@@ -41,6 +41,13 @@ export const useSettings = defineStore('settings', () => {
auto: false,
})
const livecodeURL = createResource({
url: 'lms.lms.api.get_lms_setting',
params: { field: 'livecode_url' },
auto: true,
cache: ['livecodeURL'],
})
return {
isSettingsOpen,
activeTab,
@@ -49,5 +56,6 @@ export const useSettings = defineStore('settings', () => {
contactUsEmail,
contactUsURL,
sidebarSettings,
livecodeURL,
}
})

View File

@@ -239,6 +239,15 @@ export function getEditorTools() {
'https://codesandbox.io/embed/<%= remote_id %>?view=editor+%2B+preview&module=%2Findex.html',
html: "<iframe style='width: 100%; height: 500px; border: 0; border-radius: 4px; overflow: hidden;' sandbox='allow-mods allow-forms allow-popups allow-scripts allow-same-origin' frameborder='0' allowfullscreen='true'></iframe>",
},
rutube: {
regex: /(?:https?:\/\/)?(?:www\.)?rutube\.ru\/(?:video\/|play\/embed\/)([^#&?=]*)/,
embedUrl:
'https://rutube.ru/play/embed/<%= remote_id %>',
html: '<iframe style="width:100%; height: 30rem;" frameborder="0" allowfullscreen></iframe>',
height: 320,
width: 580,
id: ([id]) => id,
},
},
},
},

View File

@@ -105,7 +105,7 @@ doc_events = {
"Notification Log": {"on_change": "lms.lms.utils.publish_notifications"},
"User": {
"validate": "lms.lms.user.validate_username_duplicates",
"after_insert": "lms.lms.user.after_insert",
#"after_insert": "lms.lms.user.after_insert",
},
}
@@ -222,6 +222,7 @@ lms_markdown_macro_renderers = {
"Exercise": "lms.plugins.exercise_renderer",
"Quiz": "lms.plugins.quiz_renderer",
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
"RuTubeVideo": "lms.plugins.rutube_video_renderer",
"Video": "lms.plugins.video_renderer",
"Assignment": "lms.plugins.assignment_renderer",
"Embed": "lms.plugins.embed_renderer",

View File

@@ -470,16 +470,22 @@ def get_assigned_badges(member):
@frappe.whitelist()
def get_all_users():
frappe.only_for(["Moderator", "Course Creator", "Batch Evaluator"])
users = frappe.get_all(
"User",
{
"enabled": 1,
},
["name", "full_name", "user_image"],
)
frappe.only_for(["Moderator", "Course Creator", "Batch Evaluator", "LMS Student", "LMS Schoolchild", "Parent"])
users = frappe.get_all(
"User",
{"enabled": 1},
["name", "full_name", "user_image", "email", "username"]
)
return {user.name: user for user in users}
for user in users:
roles = frappe.get_all(
"Has Role",
filters={"parent": user.name},
fields=["role"]
)
user["roles"] = [role["role"] for role in roles]
return users
@frappe.whitelist()
@@ -1672,3 +1678,13 @@ def get_pwa_manifest():
}
return Response(json.dumps(manifest), status=200, content_type="application/manifest+json")
@frappe.whitelist()
def get_profile_details(username):
return frappe.db.get_value(
"User",
{"username": username},
["full_name", "name", "username", "user_image", "bio", "headline", "cover_image"],
as_dict=True,
)

View File

@@ -22,6 +22,7 @@
"instructor_notes",
"section_break_6",
"youtube",
"rutube",
"column_break_9",
"quiz_id",
"section_break_16",
@@ -104,6 +105,12 @@
"fieldtype": "Data",
"label": "YouTube Video URL"
},
{
"description": "RuTube Video will appear at the top of the lesson.",
"fieldname": "rutube",
"fieldtype": "Data",
"label": "RuTube Video URL"
},
{
"fieldname": "section_break_16",
"fieldtype": "Section Break",

View File

@@ -84,7 +84,7 @@
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2025-07-07 20:37:22.449149",
"modified": "2025-11-06 11:38:35.903520",
"modified_by": "sayali@frappe.io",
"module": "LMS",
"name": "LMS Badge Assignment",
@@ -135,6 +135,30 @@
"report": 1,
"role": "LMS Student",
"share": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Batch Evaluator",
"share": 1,
"write": 1
},
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Course Creator",
"share": 1,
"write": 1
}
],
"row_format": "Dynamic",

View File

@@ -35,6 +35,7 @@ def find_macros(text):
>>> find_macros(text)
[
('YouTubeVideo': 'abcd1234')
('RuTubeVideo': 'abcd1234')
('Exercise', 'two-circles'),
('Exercise', 'four-circles')
]
@@ -119,5 +120,7 @@ def sanitize_html(html, macro):
classname = ""
if macro == "YouTubeVideo":
classname = "lesson-video"
elif macro == "RutubeVideo": # Добавлено
classname = "rutube-video"
return "<div class='" + classname + "'>" + "\n".join(str(node) for node in nodes) + "</div>"

View File

@@ -1,9 +1,9 @@
import frappe
from frappe import _
from frappe.model.naming import append_number_if_name_exists
from frappe.utils import escape_html, random_string
from frappe.website.utils import cleanup_page_name, is_signup_disabled
from frappe.website.utils import cleanup_page_name
from frappe.website.utils import is_signup_disabled
from frappe.utils import random_string, escape_html
from lms.lms.utils import get_country_code
@@ -19,12 +19,12 @@ def validate_username_duplicates(doc, method):
doc.username = doc.email.replace("@", "").replace(".", "")
def after_insert(doc, method):
doc.add_roles("LMS Student")
'''def after_insert(doc, method):
doc.add_roles("LMS Student")'''
@frappe.whitelist(allow_guest=True)
def sign_up(email, full_name, verify_terms, user_category):
def sign_up(email, full_name, verify_terms, user_category, user_role, phone):
if is_signup_disabled():
frappe.throw(_("Sign Up is disabled"), _("Not Allowed"))
@@ -48,6 +48,7 @@ def sign_up(email, full_name, verify_terms, user_category):
{
"doctype": "User",
"email": email,
"phone": escape_html(phone),
"first_name": escape_html(full_name),
"verify_terms": verify_terms,
"user_category": user_category,
@@ -62,11 +63,15 @@ def sign_up(email, full_name, verify_terms, user_category):
user.insert()
# set default signup role as per Portal Settings
default_role = frappe.db.get_single_value("Portal Settings", "default_role")
default_role = frappe.db.get_value("Portal Settings", None, "default_role")
if default_role:
user.add_roles(default_role)
elif user_role: # set Role
user.add_roles(user_role) # Если роль передана, добавляем её
else:
user.add_roles("LMS Student") # Иначе добавляем роль по умолчанию
user.add_roles("LMS Student")
#user.add_roles("LMS Student")
set_country_from_ip(None, user.name)
if user.flags.email_sent:
@@ -79,8 +84,8 @@ def set_country_from_ip(login_manager=None, user=None):
if not user and login_manager:
user = login_manager.user
user_country = frappe.db.get_value("User", user, "country")
if user_country:
return
# if user_country:
# return
frappe.db.set_value("User", user, "country", get_country_code())
return

View File

@@ -145,6 +145,7 @@ def get_lesson_details(chapter, progress=False):
"body",
"creation",
"youtube",
"rutube",
"quiz_id",
"question",
"file_type",
@@ -179,6 +180,7 @@ def get_lesson_icon(body, content):
if block.get("type") == "embed" and block.get("data").get("service") in [
"youtube",
"rutube",
"vimeo",
"cloudflareStream",
"bunnyStream",
@@ -192,7 +194,7 @@ def get_lesson_icon(body, content):
macros = find_macros(body)
for macro in macros:
if macro[0] == "YouTubeVideo" or macro[0] == "Video":
if macro[0] == "YouTubeVideo" or macro[0] == "Video" or macro[0] == "RuTubeVideo" :
return "icon-youtube"
elif macro[0] == "Quiz":
return "icon-quiz"
@@ -334,12 +336,17 @@ def render_html(lesson):
youtube = lesson.youtube
quiz_id = lesson.quiz_id
body = lesson.body
rutube = lesson.get("rutube")
if youtube and "/" in youtube:
youtube = youtube.split("/")[-1]
if rutube and "/" in rutube:
rutube = rutube.split("/")[-1]
quiz_id = "{{ Quiz('" + quiz_id + "') }}" if quiz_id else ""
youtube = "{{ YouTubeVideo('" + youtube + "') }}" if youtube else ""
rutube = "{{ RutubeVideo('" + rutube + "') }}" if rutube else ""
text = youtube + body + quiz_id
if lesson.question:
@@ -1276,6 +1283,7 @@ def get_lesson(course, chapter, lesson):
"body",
"creation",
"youtube",
"rutube",
"quiz_id",
"question",
"file_type",
@@ -1815,6 +1823,7 @@ def get_lesson_creation_details(course, chapter, lesson):
"instructor_notes",
"instructor_content",
"youtube",
"rutube",
"quiz_id",
],
as_dict=1,

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Arabic\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "حذف"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "هوية شخصية"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "جديد"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "أنشطة"
msgid "activity"
msgstr "نشاط"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "و"
@@ -7643,11 +7643,11 @@ msgstr "الطلاب"
msgid "minutes"
msgstr "الدقائق"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "بدلات أخرى"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Bosnian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Dodaj Lekciju"
msgid "Add a new member"
msgstr "Dodaj novog člana"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Dodaj novo pitanje"
@@ -1734,15 +1734,15 @@ msgstr "Naziv Kursa"
msgid "Course added to program successfully"
msgstr "Kurs je uspješno dodan u program"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "Kurs je uspješno kreiran"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Kurs uspješno izbrisan"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "Kurs je uspješno ažuriran"
@@ -1999,7 +1999,7 @@ msgstr "Tip Stepena"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Izbriši"
msgid "Delete Chapter"
msgstr "Izbriši Poglavlje"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Izbriši Kurs"
@@ -2021,7 +2021,7 @@ msgstr "Izbriši ovo Poglavlje?"
msgid "Delete this lesson?"
msgstr "Izbriši ovu Lekciju?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Brisanjem kursa izbrisat će se i sva njegova poglavlja i lekcije. Jeste li sigurni da želite izbrisati ovaj kurs?"
@@ -3023,7 +3023,7 @@ msgstr "Tražim posao"
msgid "I am unavailable"
msgstr "Ja sam nedostupan/nedostupna"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr "Referenca Lekcije"
msgid "Lesson Title"
msgstr "Naziv Lekcije"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "Lekcija je uspješno kreirana"
@@ -3768,7 +3768,7 @@ msgstr "Lekcija je uspješno izbrisana"
msgid "Lesson moved successfully"
msgstr "Lekcija je uspješno premještena"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "Lekcija je uspješno ažurirana"
@@ -3948,7 +3948,7 @@ msgstr "Označi sve kao pročitano"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Novi"
msgid "New Batch"
msgstr "Nova Grupa"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Novi Kurs"
@@ -4402,7 +4402,7 @@ msgstr "Novi Sistem Plaćanja"
msgid "New Question"
msgstr "Novo Pitanje"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Novi Kviz"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Detalj Pitanja"
msgid "Question Name"
msgstr "Naziv Pitanja"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Pitanje je uspješno dodano"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Pitanje je uspješno ažurirano"
@@ -5492,7 +5492,7 @@ msgstr "Pitanje {0} od {1}"
msgid "Questions"
msgstr "Pitanja"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Pitanja su uspješno izbrisana"
@@ -5542,7 +5542,7 @@ msgstr "Kviz je uspješno kreiran"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Kviz nije dostupan gostima. Prijavi se da nastaviš."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Kviz je uspješno ažuriran"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Kviz će se pojaviti na dnu lekcije."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Kvizovi"
@@ -7529,8 +7529,8 @@ msgstr "aktivnosti"
msgid "activity"
msgstr "aktivnost"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "i"
@@ -7643,11 +7643,11 @@ msgstr "članovi"
msgid "minutes"
msgstr "minuta"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "ostalo"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "pitanje_detalj"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Czech\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "a"
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "ostatní"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Danish\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr "Kurstitel"
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr "Abschlussart"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Löschen"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr "Ich bin nicht verfügbar"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr "Titel der Unterrichtseinheit"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Alle als gelesen markieren"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Neu"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Neuer Kurs"
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr "Name der Frage"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr "Frage {0} von {1}"
msgid "Questions"
msgstr "Fragen"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Das Quiz ist für Gastbenutzer nicht verfügbar. Bitte melden Sie sich an, um fortzufahren."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Das Quiz wird am Ende der Lektion angezeigt."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "aktivitäten"
msgid "activity"
msgstr "aktivität"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "und"
@@ -7643,11 +7643,11 @@ msgstr "mitglieder"
msgid "minutes"
msgstr "Minuten"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "andere"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-10-31 17:33\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Esperanto\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "crwdns151728:0crwdne151728:0"
msgid "Add a new member"
msgstr "crwdns155798:0crwdne155798:0"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "crwdns149228:0crwdne149228:0"
@@ -1734,15 +1734,15 @@ msgstr "crwdns149590:0crwdne149590:0"
msgid "Course added to program successfully"
msgstr "crwdns158496:0crwdne158496:0"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "crwdns155084:0crwdne155084:0"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "crwdns151586:0crwdne151586:0"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "crwdns155086:0crwdne155086:0"
@@ -1999,7 +1999,7 @@ msgstr "crwdns149644:0crwdne149644:0"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "crwdns149646:0crwdne149646:0"
msgid "Delete Chapter"
msgstr "crwdns151626:0crwdne151626:0"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "crwdns151588:0crwdne151588:0"
@@ -2021,7 +2021,7 @@ msgstr "crwdns151628:0crwdne151628:0"
msgid "Delete this lesson?"
msgstr "crwdns151630:0crwdne151630:0"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "crwdns151590:0crwdne151590:0"
@@ -3023,7 +3023,7 @@ msgstr "crwdns149892:0crwdne149892:0"
msgid "I am unavailable"
msgstr "crwdns149894:0crwdne149894:0"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "crwdns149896:0crwdne149896:0"
@@ -3756,7 +3756,7 @@ msgstr "crwdns150082:0crwdne150082:0"
msgid "Lesson Title"
msgstr "crwdns150084:0crwdne150084:0"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "crwdns155092:0crwdne155092:0"
@@ -3768,7 +3768,7 @@ msgstr "crwdns155094:0crwdne155094:0"
msgid "Lesson moved successfully"
msgstr "crwdns155096:0crwdne155096:0"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "crwdns155098:0crwdne155098:0"
@@ -3948,7 +3948,7 @@ msgstr "crwdns150140:0crwdne150140:0"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "crwdns150214:0crwdne150214:0"
msgid "New Batch"
msgstr "crwdns150218:0crwdne150218:0"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "crwdns150220:0crwdne150220:0"
@@ -4402,7 +4402,7 @@ msgstr "crwdns159762:0crwdne159762:0"
msgid "New Question"
msgstr "crwdns150226:0crwdne150226:0"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "crwdns150228:0crwdne150228:0"
@@ -5451,7 +5451,7 @@ msgstr "crwdns155756:0crwdne155756:0"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "crwdns150506:0crwdne150506:0"
msgid "Question Name"
msgstr "crwdns150508:0crwdne150508:0"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "crwdns150510:0crwdne150510:0"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "crwdns150512:0crwdne150512:0"
@@ -5492,7 +5492,7 @@ msgstr "crwdns150516:0{0}crwdnd150516:0{1}crwdne150516:0"
msgid "Questions"
msgstr "crwdns150518:0crwdne150518:0"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "crwdns150520:0crwdne150520:0"
@@ -5542,7 +5542,7 @@ msgstr "crwdns150534:0crwdne150534:0"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "crwdns150536:0crwdne150536:0"
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "crwdns150538:0crwdne150538:0"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "crwdns150540:0crwdne150540:0"
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "crwdns150542:0crwdne150542:0"
@@ -7529,8 +7529,8 @@ msgstr "crwdns152176:0crwdne152176:0"
msgid "activity"
msgstr "crwdns152178:0crwdne152178:0"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "crwdns157186:0crwdne157186:0"
@@ -7643,11 +7643,11 @@ msgstr "crwdns151800:0crwdne151800:0"
msgid "minutes"
msgstr "crwdns155280:0crwdne155280:0"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "crwdns157188:0crwdne157188:0"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "crwdns151070:0crwdne151070:0"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Añadir una lección"
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Añadir una nueva pregunta"
@@ -1734,15 +1734,15 @@ msgstr "Título del curso"
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr "Tipo de Grado"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Eliminar"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr "Estoy buscando un trabajo"
msgid "I am unavailable"
msgstr "No estoy disponible"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "Identificador"
@@ -3756,7 +3756,7 @@ msgstr "Referencia de la lección"
msgid "Lesson Title"
msgstr "Título de la lección"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Marcar todo como leídas"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Nuevo"
msgid "New Batch"
msgstr "Nuevo lote"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Nuevo curso"
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr "Nueva pregunta"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Nuevo cuestionario"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Detalle de la pregunta"
msgid "Question Name"
msgstr "Nombre de la Pregunta"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Pregunta añadida correctamente"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Pregunta actualizada correctamente"
@@ -5492,7 +5492,7 @@ msgstr "Pregunta {0} de {1}"
msgid "Questions"
msgstr "Preguntas"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Preguntas eliminadas correctamente"
@@ -5542,7 +5542,7 @@ msgstr "Cuestionario creado correctamente"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "El cuestionario no está disponible para usuarios invitados. Por favor inicie sesión para continuar."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Cuestionario actualizado correctamente"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "El cuestionario aparecerá al final de la lección."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Cuestionarios"
@@ -7529,8 +7529,8 @@ msgstr "actividades"
msgid "activity"
msgstr "actividad"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "y"
@@ -7643,11 +7643,11 @@ msgstr "miembros"
msgid "minutes"
msgstr "minutos"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "otros"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "pregunta_detalle"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Persian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr "عنوان دوره"
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "دوره با موفقیت ایجاد شد"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "دوره با موفقیت حذف شد"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "دوره با موفقیت به‌روزرسانی شد"
@@ -1999,7 +1999,7 @@ msgstr "نوع مدرک"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "حذف"
msgid "Delete Chapter"
msgstr "حذف فصل"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "حذف دوره"
@@ -2021,7 +2021,7 @@ msgstr "این فصل حذف شود؟"
msgid "Delete this lesson?"
msgstr "این درس حذف شود؟"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr "من در دسترس نیستم"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "شناسه"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr "عنوان درس"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "درس با موفقیت ایجاد شد"
@@ -3768,7 +3768,7 @@ msgstr "درس با موفقیت حذف شد"
msgid "Lesson moved successfully"
msgstr "درس با موفقیت منتقل شد"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "درس با موفقیت به‌روزرسانی شد"
@@ -3948,7 +3948,7 @@ msgstr "همه را به عنوان خوانده شده علامت بزن"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "جدید"
msgid "New Batch"
msgstr "دسته جدید"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "دوره جدید"
@@ -4402,7 +4402,7 @@ msgstr "درگاه پرداخت جدید"
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr "پایتون"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr "سوال {0} از {1}"
msgid "Questions"
msgstr "سوالات"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "آزمون برای کاربران مهمان در دسترس نیست. لطفا برای ادامه وارد شوید."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "تکلیف زیر درس نشان داده می‌شود."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "فعالیت ها"
msgid "activity"
msgstr "فعالیت"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "و"
@@ -7643,11 +7643,11 @@ msgstr "اعضا"
msgid "minutes"
msgstr "دقایق"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "سایر"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: French\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr "Titre du cours"
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr "Type de diplôme"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Supprimer"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "Identifiant"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Marquer tout comme lu"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Nouveau"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "activités"
msgid "activity"
msgstr "historique"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "et"
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr "procès-verbal"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "autres"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Croatian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Dodaj Lekciju"
msgid "Add a new member"
msgstr "Dodaj novog člana"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Dodaj novo pitanje"
@@ -1734,15 +1734,15 @@ msgstr "Naziv Kursa"
msgid "Course added to program successfully"
msgstr "Tečaj je uspješno dodan u program"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "Tečaj je uspješno kreiran"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Kurs uspješno izbrisan"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "Tečaj je uspješno ažuriran"
@@ -1999,7 +1999,7 @@ msgstr "Tip Stepena"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Izbriši"
msgid "Delete Chapter"
msgstr "Izbriši Poglavlje"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Izbriši Kurs"
@@ -2021,7 +2021,7 @@ msgstr "Izbriši ovo Poglavlje?"
msgid "Delete this lesson?"
msgstr "Izbriši ovu Lekciju?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Brisanjem kursa izbrisat će se i sva njegova poglavlja i lekcije. Jeste li sigurni da želite izbrisati ovaj kurs?"
@@ -3023,7 +3023,7 @@ msgstr "Tražim posao"
msgid "I am unavailable"
msgstr "Ja sam nedostupan/nedostupna"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr "Referenca Lekcije"
msgid "Lesson Title"
msgstr "Naziv Lekcije"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "Lekcija je uspješno kreirana"
@@ -3768,7 +3768,7 @@ msgstr "Lekcija je uspješno izbrisana"
msgid "Lesson moved successfully"
msgstr "Lekcija je uspješno premještena"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "Lekcija je uspješno ažurirana"
@@ -3948,7 +3948,7 @@ msgstr "Označi sve kao pročitano"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Novi"
msgid "New Batch"
msgstr "Nova Grupa"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Novi Kurs"
@@ -4402,7 +4402,7 @@ msgstr "Novi Sustav Plaćanja"
msgid "New Question"
msgstr "Novo Pitanje"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Novi Kviz"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Detalj Pitanja"
msgid "Question Name"
msgstr "Naziv Pitanja"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Pitanje je uspješno dodano"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Pitanje je uspješno ažurirano"
@@ -5492,7 +5492,7 @@ msgstr "Pitanje {0} od {1}"
msgid "Questions"
msgstr "Pitanja"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Pitanja su uspješno izbrisana"
@@ -5542,7 +5542,7 @@ msgstr "Kviz je uspješno kreiran"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Kviz nije dostupan gostima. Prijavi se da nastaviš."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Kviz je uspješno ažuriran"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Kviz će se pojaviti na dnu lekcije."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Kvizovi"
@@ -7529,8 +7529,8 @@ msgstr "aktivnosti"
msgid "activity"
msgstr "aktivnost"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "i"
@@ -7643,11 +7643,11 @@ msgstr "članovi"
msgid "minutes"
msgstr "minuta"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "ostalo"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "pitanje_detalj"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Hungarian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Mindegyik megjelölése olvasottként"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "tevékenységek"
msgid "activity"
msgstr "tevékenység"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr "tagok"
msgid "minutes"
msgstr "percek"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Indonesian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Hapus"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Baru"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "dan"
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "lainnya"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Italian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Elimina"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "altri"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Frappe LMS VERSION\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-24 16:04+0000\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-10-31 16:04+0000\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: jannat@frappe.io\n"
"MIME-Version: 1.0\n"
@@ -214,7 +214,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1732,15 +1732,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1997,7 +1997,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2007,7 +2007,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2019,7 +2019,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3021,7 +3021,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3754,7 +3754,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3766,7 +3766,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3946,7 +3946,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4376,7 +4376,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4400,7 +4400,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5449,7 +5449,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5469,11 +5469,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5490,7 +5490,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5540,7 +5540,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5550,7 +5550,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7527,8 +7527,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7641,11 +7641,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Burmese\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Norwegian Bokmal\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Merk alle som lest"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Dutch\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "anderen"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Polish\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Oznacz wszystko jako przeczytane"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr "aktywności"
msgid "activity"
msgstr "aktywność"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr "minut"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Portuguese\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Eliminar"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Novo"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "outros"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Portuguese, Brazilian\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Excluir"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Novo"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "e"
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr "minutos"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "outros"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Serbian (Cyrillic)\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Додај лекцију"
msgid "Add a new member"
msgstr "Додај новог члана"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Додај ново питање"
@@ -1734,15 +1734,15 @@ msgstr "Наслов обуке"
msgid "Course added to program successfully"
msgstr "Обука је успешно додата у програм"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "Обука је успешно креирана"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Обука је успешно обрисана"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "Обука је успешно ажурирана"
@@ -1999,7 +1999,7 @@ msgstr "Врста дипломе"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Обриши"
msgid "Delete Chapter"
msgstr "Обриши поглавље"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Обриши обуку"
@@ -2021,7 +2021,7 @@ msgstr "Обриши ово поглавље?"
msgid "Delete this lesson?"
msgstr "Обришите ову лекцију?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Брисањем обуке такође ће се обрисати сва поглавља и лекције. Да ли сте сигурни да желите да обришете ову обуку?"
@@ -3023,7 +3023,7 @@ msgstr "Тренутно сам у потрази за послом"
msgid "I am unavailable"
msgstr "Нисам доступан"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ИД"
@@ -3756,7 +3756,7 @@ msgstr "Референца лекције"
msgid "Lesson Title"
msgstr "Наслов лекције"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "Лекција је успешно креирана"
@@ -3768,7 +3768,7 @@ msgstr "Лекција је успешно обрисана"
msgid "Lesson moved successfully"
msgstr "Лекција је успешно премештена"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "Лекција је успешно ажурирана"
@@ -3948,7 +3948,7 @@ msgstr "Означи све као прочитано"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Нови"
msgid "New Batch"
msgstr "Нова група"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Нова обука"
@@ -4402,7 +4402,7 @@ msgstr "Нови платни портал"
msgid "New Question"
msgstr "Ново питање"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Нови квиз"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Детаљи питања"
msgid "Question Name"
msgstr "Назив питања"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Питање је успешно додато"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Питање је успешно ажурирано"
@@ -5492,7 +5492,7 @@ msgstr "Питање {0} од {1}"
msgid "Questions"
msgstr "Питања"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Питања су успешно обрисана"
@@ -5542,7 +5542,7 @@ msgstr "Квиз је успешно креиран"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Квиз није доступан гостујућим корисницима. Молимо Вас да се пријавите да бисте наставили."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Квиз је успешно ажуриран"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Квиз ће бити приказиван на дну лекције."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Квизови"
@@ -7529,8 +7529,8 @@ msgstr "активности"
msgid "activity"
msgstr "активност"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "и"
@@ -7643,11 +7643,11 @@ msgstr "чланови"
msgid "minutes"
msgstr "минуте"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "остало"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "question_detail"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Serbian (Latin)\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Dodaj lekciju"
msgid "Add a new member"
msgstr "Dodaj novog člana"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Dodaj novo pitanje"
@@ -1734,15 +1734,15 @@ msgstr "Naslov obuke"
msgid "Course added to program successfully"
msgstr "Obuka je uspešno dodata u program"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "Obuka je uspešno kreirana"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Obuka je uspešno obrisana"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "Obuka je uspešno ažurirana"
@@ -1999,7 +1999,7 @@ msgstr "Vrsta diplome"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Obriši"
msgid "Delete Chapter"
msgstr "Obriši poglavlje"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Obriši obuku"
@@ -2021,7 +2021,7 @@ msgstr "Obriši ovo poglavlje?"
msgid "Delete this lesson?"
msgstr "Obrišite ovu lekciju?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Brisanjem obuke takođe će se obrisati sva poglavlja i lekcije. Da li ste sigurni da želite da obrišete ovu obuku?"
@@ -3023,7 +3023,7 @@ msgstr "Trenutno sam u potrazi za poslom"
msgid "I am unavailable"
msgstr "Nisam dostupan"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr "Referenca lekcije"
msgid "Lesson Title"
msgstr "Naslov lekcije"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "Lekcija je uspešno kreirana"
@@ -3768,7 +3768,7 @@ msgstr "Lekcija je uspešno obrisana"
msgid "Lesson moved successfully"
msgstr "Lekcija je uspešno premeštena"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "Lekcija je uspešno ažurirana"
@@ -3948,7 +3948,7 @@ msgstr "Označi sve kao pročitano"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Novi"
msgid "New Batch"
msgstr "Nova grupa"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Nova obuka"
@@ -4402,7 +4402,7 @@ msgstr "Novi platni portal"
msgid "New Question"
msgstr "Novo pitanje"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Novi kviz"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Detalji pitanja"
msgid "Question Name"
msgstr "Naziv pitanja"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Pitanje je uspešno dodato"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Pitanje je uspešno ažurirano"
@@ -5492,7 +5492,7 @@ msgstr "Pitanje {0} od {1}"
msgid "Questions"
msgstr "Pitanja"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Pitanja su uspešno obrisana"
@@ -5542,7 +5542,7 @@ msgstr "Kviz je uspešno kreiran"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Kviz nije dostupan gostujućim korisnicima. Molimo Vas da se prijavite da biste nastavili."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Kviz je uspešno ažuriran"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Kviz će biti prikazivan na dnu lekcije."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Kvizovi"
@@ -7529,8 +7529,8 @@ msgstr "aktivnosti"
msgid "activity"
msgstr "aktivnost"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "i"
@@ -7643,11 +7643,11 @@ msgstr "članovi"
msgid "minutes"
msgstr "minute"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "ostalo"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "question_detail"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Swedish\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Lägg till Lektion"
msgid "Add a new member"
msgstr "Lägg till ny medlem"
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Lägg till ny fråga"
@@ -1734,15 +1734,15 @@ msgstr "Kurs Benämning"
msgid "Course added to program successfully"
msgstr "Kurs tillagd till Program"
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr "Kurs skapad"
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Kurs är borttagen"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr "Kurs uppdaterad"
@@ -1999,7 +1999,7 @@ msgstr "Examen Typ"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Ta bort"
msgid "Delete Chapter"
msgstr "Ta bort Kapitel"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Ta bort kurs"
@@ -2021,7 +2021,7 @@ msgstr "Ta bort detta kapitel?"
msgid "Delete this lesson?"
msgstr "Ta bort denna lektion?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Om du tar bort kurs raderas också alla dess kapitel och lektioner. Är du säker på att du vill ta bort denna kurs?"
@@ -3023,7 +3023,7 @@ msgstr "Jag söker jobb"
msgid "I am unavailable"
msgstr "Jag är inte tillgänglig"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr "Lektion Referens"
msgid "Lesson Title"
msgstr "Lektion Benämning"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr "Lektion skapad"
@@ -3768,7 +3768,7 @@ msgstr "Lektion raderad"
msgid "Lesson moved successfully"
msgstr "Lektion flyttad"
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr "Lektion uppdaterad"
@@ -3948,7 +3948,7 @@ msgstr "Markera alla som lästa"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Ny"
msgid "New Batch"
msgstr "Ny Grupp"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Ny Kurs"
@@ -4402,7 +4402,7 @@ msgstr "Ny Betalning Portal"
msgid "New Question"
msgstr "Ny Fråga"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Nytt Frågesport"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Fråga Detalj"
msgid "Question Name"
msgstr "Fråga Namn"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Fråga tillagd"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Fråga uppdaterad"
@@ -5492,7 +5492,7 @@ msgstr "Fråga {0} av {1}"
msgid "Questions"
msgstr "Frågor"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Frågor är borttagna"
@@ -5542,7 +5542,7 @@ msgstr "Frågesport skapad"
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr "Frågesport är inte tillgänglig för gästanvändare. Logga in för att fortsätta."
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Frågesport uppdaterad"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr "Frågesport kommer att visas längst ner i lektionen."
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Frågesporter"
@@ -7529,8 +7529,8 @@ msgstr "aktiviteter"
msgid "activity"
msgstr "aktivitet"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "och"
@@ -7643,11 +7643,11 @@ msgstr "medlemmar"
msgid "minutes"
msgstr "minuter"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "övriga"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr "fråga_detalj"

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Tamil\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr ""
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Thai\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -2002,7 +2002,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2012,7 +2012,7 @@ msgstr "ลบ"
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2024,7 +2024,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3026,7 +3026,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "รหัส"
@@ -3759,7 +3759,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3771,7 +3771,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3951,7 +3951,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4381,7 +4381,7 @@ msgstr "ใหม่"
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4405,7 +4405,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5454,7 +5454,7 @@ msgstr "ไพธอน"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5474,11 +5474,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5495,7 +5495,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5545,7 +5545,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5555,7 +5555,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7532,8 +7532,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "และ"
@@ -7646,11 +7646,11 @@ msgstr ""
msgid "minutes"
msgstr "นาที"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "อื่นๆ"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Turkish\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr "Bir ders ekle"
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr "Yeni Soru Ekle"
@@ -1734,15 +1734,15 @@ msgstr "Kurs Başlığı"
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr "Kurs başarıyla silindi"
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr "Derece Türü"
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr "Sil"
msgid "Delete Chapter"
msgstr "Bölümü Sil"
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr "Kursu Sil"
@@ -2021,7 +2021,7 @@ msgstr "Bu bölümü silmek istiyor musunuz?"
msgid "Delete this lesson?"
msgstr "Bu dersi silmek istiyor musunuz?"
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr "Kursu silmek, tüm bölümlerini ve derslerini de silecektir. Bu kursu silmek istediğinizden emin misiniz?"
@@ -3023,7 +3023,7 @@ msgstr "Bir iş arıyorum"
msgid "I am unavailable"
msgstr "Müsait değilim"
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr "ID"
@@ -3756,7 +3756,7 @@ msgstr "Ders Referansı"
msgid "Lesson Title"
msgstr "Ders Başlığı"
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr "Hepsini Okundu İşaretle"
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr "Yeni"
msgid "New Batch"
msgstr "Yeni Parti"
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr "Yeni Kurs"
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr "Yeni Soru"
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr "Yeni Test"
@@ -5451,7 +5451,7 @@ msgstr "Python"
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr "Soru Detayı"
msgid "Question Name"
msgstr "Soru Adı"
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr "Soru başarıyla eklendi"
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr "Soru başarıyla güncellendi"
@@ -5492,7 +5492,7 @@ msgstr "Soru {0} / {1}"
msgid "Questions"
msgstr "Sorular"
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr "Sorular başarıyla silindi"
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr "Sınav başarıyla güncellendi"
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr "Sınavlar"
@@ -7529,8 +7529,8 @@ msgstr "aktiviteler"
msgid "activity"
msgstr "aktivite"
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr "ve"
@@ -7643,11 +7643,11 @@ msgstr "üyeler"
msgid "minutes"
msgstr "süreler"
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "diğer"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

View File

@@ -2,8 +2,8 @@ msgid ""
msgstr ""
"Project-Id-Version: frappe\n"
"Report-Msgid-Bugs-To: jannat@frappe.io\n"
"POT-Creation-Date: 2025-10-24 16:04+0000\n"
"PO-Revision-Date: 2025-10-27 17:04\n"
"POT-Creation-Date: 2025-10-31 16:04+0000\n"
"PO-Revision-Date: 2025-11-02 19:07\n"
"Last-Translator: jannat@frappe.io\n"
"Language-Team: Vietnamese\n"
"MIME-Version: 1.0\n"
@@ -216,7 +216,7 @@ msgstr ""
msgid "Add a new member"
msgstr ""
#: frontend/src/components/Modals/Question.vue:166
#: frontend/src/components/Modals/Question.vue:167
#: frontend/src/pages/QuizForm.vue:200
msgid "Add a new question"
msgstr ""
@@ -1734,15 +1734,15 @@ msgstr ""
msgid "Course added to program successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:560
#: frontend/src/pages/CourseForm.vue:559
msgid "Course created successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:597
#: frontend/src/pages/CourseForm.vue:596
msgid "Course deleted successfully"
msgstr ""
#: frontend/src/pages/CourseForm.vue:580
#: frontend/src/pages/CourseForm.vue:579
msgid "Course updated successfully"
msgstr ""
@@ -1999,7 +1999,7 @@ msgstr ""
#: frontend/src/components/CourseOutline.vue:360
#: frontend/src/components/DiscussionReplies.vue:41
#: frontend/src/components/Settings/Badges.vue:171
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:610
#: frontend/src/pages/BatchForm.vue:565 frontend/src/pages/CourseForm.vue:609
#: frontend/src/pages/ProgrammingExercises/ProgrammingExerciseForm.vue:67
#: frontend/src/pages/Programs/ProgramForm.vue:231
msgid "Delete"
@@ -2009,7 +2009,7 @@ msgstr ""
msgid "Delete Chapter"
msgstr ""
#: frontend/src/pages/CourseForm.vue:604
#: frontend/src/pages/CourseForm.vue:603
msgid "Delete Course"
msgstr ""
@@ -2021,7 +2021,7 @@ msgstr ""
msgid "Delete this lesson?"
msgstr ""
#: frontend/src/pages/CourseForm.vue:605
#: frontend/src/pages/CourseForm.vue:604
msgid "Deleting the course will also delete all its chapters and lessons. Are you sure you want to delete this course?"
msgstr ""
@@ -3023,7 +3023,7 @@ msgstr ""
msgid "I am unavailable"
msgstr ""
#: frontend/src/pages/QuizForm.vue:338
#: frontend/src/pages/QuizForm.vue:334
msgid "ID"
msgstr ""
@@ -3756,7 +3756,7 @@ msgstr ""
msgid "Lesson Title"
msgstr ""
#: frontend/src/pages/LessonForm.vue:426
#: frontend/src/pages/LessonForm.vue:425
msgid "Lesson created successfully"
msgstr ""
@@ -3768,7 +3768,7 @@ msgstr ""
msgid "Lesson moved successfully"
msgstr ""
#: frontend/src/pages/LessonForm.vue:450
#: frontend/src/pages/LessonForm.vue:449
msgid "Lesson updated successfully"
msgstr ""
@@ -3948,7 +3948,7 @@ msgstr ""
#. Label of the marks (Int) field in DocType 'LMS Quiz Result'
#: frontend/src/components/Modals/Question.vue:40
#: frontend/src/components/Modals/Question.vue:106
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:348
#: frontend/src/components/Quiz.vue:120 frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizSubmission.vue:64
#: lms/lms/doctype/lms_quiz_question/lms_quiz_question.json
#: lms/lms/doctype/lms_quiz_result/lms_quiz_result.json
@@ -4378,7 +4378,7 @@ msgstr ""
msgid "New Batch"
msgstr ""
#: frontend/src/pages/CourseForm.vue:691 lms/www/lms.py:93
#: frontend/src/pages/CourseForm.vue:690 lms/www/lms.py:93
msgid "New Course"
msgstr ""
@@ -4402,7 +4402,7 @@ msgstr ""
msgid "New Question"
msgstr ""
#: frontend/src/pages/QuizForm.vue:404 frontend/src/pages/QuizForm.vue:412
#: frontend/src/pages/QuizForm.vue:400 frontend/src/pages/QuizForm.vue:408
msgid "New Quiz"
msgstr ""
@@ -5451,7 +5451,7 @@ msgstr ""
#: frontend/src/components/Assignment.vue:20
#: frontend/src/components/Modals/AssignmentForm.vue:32
#: frontend/src/components/Modals/Question.vue:27
#: frontend/src/pages/QuizForm.vue:343 frontend/src/pages/QuizSubmission.vue:56
#: frontend/src/pages/QuizForm.vue:339 frontend/src/pages/QuizSubmission.vue:56
#: lms/lms/doctype/course_lesson/course_lesson.json
#: lms/lms/doctype/lms_assignment/lms_assignment.json
#: lms/lms/doctype/lms_assignment_submission/lms_assignment_submission.json
@@ -5471,11 +5471,11 @@ msgstr ""
msgid "Question Name"
msgstr ""
#: frontend/src/components/Modals/Question.vue:284
#: frontend/src/components/Modals/Question.vue:285
msgid "Question added successfully"
msgstr ""
#: frontend/src/components/Modals/Question.vue:334
#: frontend/src/components/Modals/Question.vue:335
msgid "Question updated successfully"
msgstr ""
@@ -5492,7 +5492,7 @@ msgstr ""
msgid "Questions"
msgstr ""
#: frontend/src/pages/QuizForm.vue:385
#: frontend/src/pages/QuizForm.vue:381
msgid "Questions deleted successfully"
msgstr ""
@@ -5542,7 +5542,7 @@ msgstr ""
msgid "Quiz is not available to Guest users. Please login to continue."
msgstr ""
#: frontend/src/pages/QuizForm.vue:310
#: frontend/src/pages/QuizForm.vue:306
msgid "Quiz updated successfully"
msgstr ""
@@ -5552,7 +5552,7 @@ msgid "Quiz will appear at the bottom of the lesson."
msgstr ""
#: frontend/src/components/AppSidebar.vue:621
#: frontend/src/pages/QuizForm.vue:396 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/QuizForm.vue:392 frontend/src/pages/Quizzes.vue:275
#: frontend/src/pages/Quizzes.vue:285 lms/www/lms.py:249
msgid "Quizzes"
msgstr ""
@@ -7529,8 +7529,8 @@ msgstr ""
msgid "activity"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:22
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:24
#: frontend/src/components/CourseInstructors.vue:45
msgid "and"
msgstr ""
@@ -7643,11 +7643,11 @@ msgstr ""
msgid "minutes"
msgstr ""
#: frontend/src/components/CourseInstructors.vue:41
#: frontend/src/components/CourseInstructors.vue:45
msgid "others"
msgstr "các thông tin khác"
#: frontend/src/pages/QuizForm.vue:344
#: frontend/src/pages/QuizForm.vue:340
msgid "question_detail"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -174,6 +174,17 @@ def youtube_video_renderer(video_id):
</iframe>
"""
def rutube_video_renderer(video_id):
return f"""
<iframe width="100%" height="400"
src="https://rutube.ru/play/embed/{video_id}"
title="Rutube video player"
frameborder="0"
class="rutube-video"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
"""
def embed_renderer(details):
type = details.split("|||")[0]

View File

@@ -11,21 +11,24 @@
<input type="email" id="signup_email" class="form-control"
placeholder="{{ _('jane@example.com') }}" required>
</div>
<div class="form-group">
<label class="form-label sr-only" for="signup_phone"> {{ _("Phone") }} </label>
<input type="phone" id="signup_phone" class="form-control"
placeholder="{{ _('+79990009900') }}" required>
</div>
{% if frappe.db.get_single_value("LMS Settings", "user_category") %}
<div class="form-group">
<label class="form-label sr-only"> {{ _("User Category") }} </label>
<label class="form-label sr-only"> {{ _("Role") }} </label>
<div class="control-input-wrapper">
<div class="control-input flex align-center">
<select type="text" id="user_category" data-fieldname="user_category" style="color: var(--text-light)"
<select type="text" id="user_role" data-fieldname="user_role" style="color: var(--text-muted)"
class="input-with-feedback form-control ellipsis" data-fieldtype="Select" required>
<option value=""> {{ _("Category") }} </option>
<option value="Business Owner"> {{ _("Business Owner") }} </option>
<option value="Manager (Sales/Marketing/Customer)"> {{ _("Manager (Sales/Marketing/Customer)") }} </option>
<option value="Employee"> {{ _("Employee") }} </option>
<option value="Student"> {{ _("Student") }} </option>
<option value="Freelancer/Just looking"> {{ _("Freelancer/Just looking") }} </option>
<option value="Others"> {{ _("Others") }} </option>
<option value=""> {{ _("Role") }} </option>
<option value="LMS Student"> {{ _("Student") }} </option>
<option value="LMS Schoolchild"> {{ _("Ученик 11 класса") }} </option>
<option value="Course Creator"> {{ _("Учитель/Репетитор") }} </option>
<option value="Parent"> {{ _("Parent") }} </option>
</select>
</div>
</div>
@@ -48,6 +51,9 @@
</div>
{% endif %}
</div>
<p style="font-size: 12px;">
{{ _("Проверьте почту — там письмо для подтверждения регистрации. Если его нет во «Входящих», проверьте «Спам».") }}
</p>
<div class="page-card-actions">
<button class="btn btn-sm btn-primary btn-block btn-signup"
type="submit">{{ _("Sign up") }}</button>
@@ -78,22 +84,30 @@
e.preventDefault();
const email = ($("#signup_email").val() || "").trim();
const full_name = frappe.utils.xss_sanitise(($("#signup_fullname").val() || "").trim());
const phone = ($("#signup_phone").val() || "").trim();
if (!email || !validate_email(email) || !full_name) {
login.set_status('{{ _("Valid email and name required") }}', 'red');
if (!email || !validate_email(email) || !full_name || !validate_phone(phone)) {
login.set_status('{{ _("Valid email, name, and phone required") }}', 'red');
return false;
}
frappe.call({
method: "lms.lms.user.sign_up",
method: "lms.overrides.user.sign_up",
args: {
"email": email,
"full_name": full_name,
"phone": phone,
"verify_terms": $("#signup-terms").prop("checked") ? 1 : 0,
"user_category": $("#user_category").length ? $("#user_category").val() : ""
"user_category": $("#user_category").length ? $("#user_category").val() : "",
"user_role": $("#user_role").length ? $("#user_role").val() : ""
},
statusCode: login.login_handlers
})
return false;
}
const validate_phone = (phone) => {
const phone_regex = /^[0-9\-\+\s]{10,15}$/;
return phone_regex.test(phone);
}
</script>

1374
yarn.lock Normal file

File diff suppressed because it is too large Load Diff