Compare commits

..

1809 Commits

Author SHA1 Message Date
joylessorchid 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
Frappe PR Bot 1193776d06 chore(release): Bumped to Version 2.39.2 2025-10-29 12:29:14 +00:00
Jannat Patel 022514a0a7 Merge pull request #1810 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-28 10:56:10 +05:30
Jannat Patel dc7f8a59ed chore: Esperanto translations 2025-10-27 22:34:42 +05:30
Jannat Patel 4e5a76a6c1 chore: Serbian (Latin) translations 2025-10-27 22:34:41 +05:30
Jannat Patel 64c4a25ee8 chore: Bosnian translations 2025-10-27 22:34:39 +05:30
Jannat Patel 47bbdbaa26 chore: Burmese translations 2025-10-27 22:34:38 +05:30
Jannat Patel f8e0c0e19a chore: Thai translations 2025-10-27 22:34:37 +05:30
Jannat Patel 94cdd19224 chore: Tamil translations 2025-10-27 22:34:35 +05:30
Jannat Patel d86d046eb0 chore: Indonesian translations 2025-10-27 22:34:34 +05:30
Jannat Patel 25ec6b5a3f chore: Portuguese, Brazilian translations 2025-10-27 22:34:32 +05:30
Jannat Patel 967453a683 chore: Vietnamese translations 2025-10-27 22:34:30 +05:30
Jannat Patel 4c17305c05 chore: Chinese Simplified translations 2025-10-27 22:34:29 +05:30
Jannat Patel 6092131303 chore: Turkish translations 2025-10-27 22:34:28 +05:30
Jannat Patel 35749834d0 chore: Serbian (Cyrillic) translations 2025-10-27 22:34:26 +05:30
Jannat Patel fe56c7b887 chore: Russian translations 2025-10-27 22:34:25 +05:30
Jannat Patel 2b58a744d2 chore: Portuguese translations 2025-10-27 22:34:24 +05:30
Jannat Patel dfb94d05e4 chore: Polish translations 2025-10-27 22:34:22 +05:30
Jannat Patel 987c1790d8 chore: Dutch translations 2025-10-27 22:34:21 +05:30
Jannat Patel 0d416b17ce chore: Italian translations 2025-10-27 22:34:19 +05:30
Jannat Patel 473e165c89 chore: Hungarian translations 2025-10-27 22:34:18 +05:30
Jannat Patel 3d52d15004 chore: German translations 2025-10-27 22:34:17 +05:30
Jannat Patel 27278e128c chore: Czech translations 2025-10-27 22:34:16 +05:30
Jannat Patel 13cee3c9b3 chore: Arabic translations 2025-10-27 22:34:14 +05:30
Jannat Patel fd95e42e9b chore: Spanish translations 2025-10-27 22:34:13 +05:30
Jannat Patel 65cd2f5d01 chore: French translations 2025-10-27 22:34:11 +05:30
Jannat Patel 70759d1888 chore: Persian translations 2025-10-27 22:34:10 +05:30
Jannat Patel 705d6e2f00 chore: Danish translations 2025-10-27 22:34:09 +05:30
Jannat Patel 088591a335 chore: Norwegian Bokmal translations 2025-10-27 22:34:07 +05:30
Jannat Patel 3f037e0d17 chore: Croatian translations 2025-10-27 22:34:06 +05:30
Jannat Patel e6884b6c93 chore: Swedish translations 2025-10-27 22:34:04 +05:30
Jannat Patel 9943268ca0 Merge pull request #1809 from pateljannat/issues-143
fix: resolved the issue that appeared when adding a chapter
2025-10-27 11:50:25 +05:30
Jannat Patel 620e4d20c2 Merge pull request #1805 from rehanrehman389/dark-mode-fix
fix: multiple fixes for dark mode visibility
2025-10-27 11:39:26 +05:30
Jannat Patel fd03033ac6 Merge pull request #1804 from frappe/pot_develop_2025-10-24
chore: update POT file
2025-10-27 11:37:35 +05:30
Jannat Patel 939099b8c8 Merge pull request #1808 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-27 11:37:19 +05:30
Jannat Patel 75001b494d fix: escape HTML in job form fields 2025-10-27 11:36:46 +05:30
Jannat Patel 8749e21744 fix: only users with moderator and instructor role should have access to quiz form 2025-10-27 11:06:09 +05:30
Jannat Patel 982ac98e27 fix: resolved the issue that appeared when adding a chapter 2025-10-27 10:32:24 +05:30
Jannat Patel f31bf17a41 chore: Polish translations 2025-10-26 21:43:16 +05:30
Rehan Ansari 3425d9118d fix: NotPermitted text visibility in dark mode 2025-10-26 00:19:46 +05:30
Rehan Ansari 6be49ecdf3 fix: multiple fixes for dark mode visibility 2025-10-25 15:38:08 +05:30
frappe-pr-bot ffd6f9578b chore: update POT file 2025-10-24 16:04:25 +00:00
Jannat Patel 41293130ad Merge pull request #1803 from rehanrehman389/brand-setting
fix: handle missing file_url
2025-10-24 10:22:33 +05:30
Rehan Ansari 6cccd28b92 fix: handle missing file_url 2025-10-23 22:50:48 +05:30
Jannat Patel 384f10a722 Merge pull request #1801 from rehanrehman389/streak-fix
fix: improve visibility in dark mode
2025-10-23 18:37:36 +05:30
Jannat Patel a603e299f1 Merge pull request #1800 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-23 18:36:46 +05:30
Rehan Ansari 05822f82da fix: streak number visibility in dark mode 2025-10-22 23:24:02 +05:30
Rehan Ansari 0508e718cb fix: job modal text in dark mode 2025-10-22 22:56:54 +05:30
Rehan Ansari 574913e9e4 fix: improve visibility in billing page 2025-10-22 22:35:01 +05:30
Rehan Ansari 068adb62a7 fix: improve visibility in dark mode 2025-10-22 21:55:03 +05:30
Jannat Patel 73fa1f9cfe chore: Serbian (Latin) translations 2025-10-22 21:17:52 +05:30
Jannat Patel f518882926 chore: Serbian (Cyrillic) translations 2025-10-22 21:17:42 +05:30
Jannat Patel ed566f9eea Merge pull request #1794 from rehanrehman389/setting-scroll-fix
fix: scroll issue in settings
2025-10-22 10:56:40 +05:30
Jannat Patel 8ca32e439a Merge pull request #1795 from rehanrehman389/notes-dark-mode
fix: update font color in dark mode for My Notes
2025-10-22 10:47:35 +05:30
Jannat Patel 35b3b11a3c Merge pull request #1798 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-22 10:46:45 +05:30
Jannat Patel 57d4a53081 chore: Bosnian translations 2025-10-21 21:17:36 +05:30
Jannat Patel 6da05961f2 chore: Polish translations 2025-10-21 21:17:35 +05:30
Jannat Patel 7db3b8c5b8 chore: Danish translations 2025-10-21 21:17:32 +05:30
Jannat Patel 50bafb6fa6 chore: Croatian translations 2025-10-21 21:17:31 +05:30
Jannat Patel 2b3a9072d1 Merge pull request #1793 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-21 21:11:41 +05:30
Rehan Ansari 1c08e57086 fix: update font color in dark mode for My Notes 2025-10-21 13:57:52 +05:30
Rehan Ansari 4290ed2f04 fix: scroll issue in settings 2025-10-20 21:42:41 +05:30
Jannat Patel 342512f3e1 chore: Esperanto translations 2025-10-20 20:49:25 +05:30
Jannat Patel 942c04cb68 chore: Serbian (Latin) translations 2025-10-20 20:49:23 +05:30
Jannat Patel 64bf4ab3f7 chore: Bosnian translations 2025-10-20 20:49:22 +05:30
Jannat Patel 052e69737e chore: Burmese translations 2025-10-20 20:49:21 +05:30
Jannat Patel 02adc4517c chore: Thai translations 2025-10-20 20:49:19 +05:30
Jannat Patel e36fdd6823 chore: Tamil translations 2025-10-20 20:49:18 +05:30
Jannat Patel d10a7ed57f chore: Indonesian translations 2025-10-20 20:49:16 +05:30
Jannat Patel 79adf44dfe chore: Portuguese, Brazilian translations 2025-10-20 20:49:15 +05:30
Jannat Patel 4bc3113f34 chore: Vietnamese translations 2025-10-20 20:49:14 +05:30
Jannat Patel 0826704282 chore: Chinese Simplified translations 2025-10-20 20:49:12 +05:30
Jannat Patel 52aa5e6954 chore: Turkish translations 2025-10-20 20:49:11 +05:30
Jannat Patel fde85607d9 chore: Serbian (Cyrillic) translations 2025-10-20 20:49:09 +05:30
Jannat Patel cc087af012 chore: Russian translations 2025-10-20 20:49:08 +05:30
Jannat Patel 2c7da1e32e chore: Portuguese translations 2025-10-20 20:49:06 +05:30
Jannat Patel 49fe8952ae chore: Polish translations 2025-10-20 20:49:05 +05:30
Jannat Patel b298cd0509 chore: Dutch translations 2025-10-20 20:49:04 +05:30
Jannat Patel a81fc11e73 chore: Italian translations 2025-10-20 20:49:02 +05:30
Jannat Patel 199fb6229d chore: Hungarian translations 2025-10-20 20:49:01 +05:30
Jannat Patel ec6ecee455 chore: German translations 2025-10-20 20:48:59 +05:30
Jannat Patel fa72172b77 chore: Czech translations 2025-10-20 20:48:58 +05:30
Jannat Patel 6789700def chore: Arabic translations 2025-10-20 20:48:56 +05:30
Jannat Patel 752744b3a4 chore: Spanish translations 2025-10-20 20:48:55 +05:30
Jannat Patel c24fa85bf4 chore: French translations 2025-10-20 20:48:54 +05:30
Jannat Patel 4e0b59f6a9 chore: Persian translations 2025-10-20 20:48:52 +05:30
Jannat Patel bd20214552 chore: Danish translations 2025-10-20 20:48:51 +05:30
Jannat Patel 4af0ea9e47 chore: Norwegian Bokmal translations 2025-10-20 20:48:49 +05:30
Jannat Patel 8651679634 chore: Croatian translations 2025-10-20 20:48:48 +05:30
Jannat Patel 99dcac6d12 chore: Swedish translations 2025-10-20 20:48:46 +05:30
Frappe PR Bot 853bf01c9e chore(release): Bumped to Version 2.39.1 2025-10-20 06:28:36 +00:00
Jannat Patel 39c5ad7267 Merge pull request #1788 from frappe/pot_develop_2025-10-17
chore: update POT file
2025-10-20 11:55:24 +05:30
Jannat Patel 8daa2948fa Merge pull request #1787 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-20 11:55:10 +05:30
Jannat Patel f2ba25429e chore: Persian translations 2025-10-19 20:29:28 +05:30
Jannat Patel 1fffb4dc67 chore: Danish translations 2025-10-19 20:29:27 +05:30
frappe-pr-bot 45ce2439fd chore: update POT file 2025-10-17 16:04:25 +00:00
Jannat Patel cb2e77e8f6 chore: Norwegian Bokmal translations 2025-10-17 20:15:15 +05:30
Jannat Patel 800c0b0336 chore: Croatian translations 2025-10-17 20:15:13 +05:30
Jannat Patel 14c23496d5 chore: Swedish translations 2025-10-17 20:15:12 +05:30
Jannat Patel 7756a6d593 fix: increased the rate limit 2025-10-17 15:59:32 +05:30
Jannat Patel ae7791a204 Merge branch 'develop' of https://github.com/frappe/lms into develop 2025-10-15 14:45:14 +05:30
Jannat Patel 44232c44fc fix: activation level doctype name 2025-10-15 14:44:53 +05:30
Jannat Patel 142fc99761 Merge pull request #1783 from pateljannat/issues-140
fix: misc issues
2025-10-15 12:08:39 +05:30
Jannat Patel 5e6dc55c76 fix: added rate limit to all apis that can be accessed by guest 2025-10-15 11:55:58 +05:30
Jannat Patel bb2447e821 fix: misc issues 2025-10-15 11:52:23 +05:30
Frappe PR Bot a88d9cd78e chore(release): Bumped to Version 2.39.0 2025-10-15 05:13:17 +00:00
Jannat Patel dab82db693 Merge pull request #1779 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-15 10:38:52 +05:30
Jannat Patel a1183df72c Merge pull request #1780 from pateljannat/issues-139
fix: moderators should be able to access unpublished courses
2025-10-14 20:46:14 +05:30
Jannat Patel 5cfa4f173a fix: moderators should be able to access unpublished courses 2025-10-14 19:27:45 +05:30
Jannat Patel 451ef49d98 chore: Serbian (Latin) translations 2025-10-14 19:20:20 +05:30
Jannat Patel 36a8ebdc1b chore: Serbian (Cyrillic) translations 2025-10-14 19:20:07 +05:30
Jannat Patel 27577edb16 Merge pull request #1776 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-14 10:35:24 +05:30
Jannat Patel bd69ab314b chore: Burmese translations 2025-10-13 19:07:28 +05:30
Jannat Patel 6abe4ac04a chore: Tamil translations 2025-10-13 19:07:26 +05:30
Jannat Patel 1eeb190653 chore: Esperanto translations 2025-10-13 19:07:24 +05:30
Jannat Patel 23f22d9d9a chore: Serbian (Latin) translations 2025-10-13 19:07:22 +05:30
Jannat Patel b913f33b3f chore: Norwegian Bokmal translations 2025-10-13 19:07:21 +05:30
Jannat Patel 52da1feb91 chore: Bosnian translations 2025-10-13 19:07:18 +05:30
Jannat Patel 0af9f1bfbf chore: Croatian translations 2025-10-13 19:07:16 +05:30
Jannat Patel 3b0e1c3ce7 chore: Thai translations 2025-10-13 19:07:14 +05:30
Jannat Patel 37ea270c56 chore: Persian translations 2025-10-13 19:07:12 +05:30
Jannat Patel 304550dd94 chore: Indonesian translations 2025-10-13 19:07:11 +05:30
Jannat Patel 69cee24ffe chore: Portuguese, Brazilian translations 2025-10-13 19:07:09 +05:30
Jannat Patel 8334c06a9b chore: Vietnamese translations 2025-10-13 19:07:07 +05:30
Jannat Patel 3e739f2877 chore: Chinese Simplified translations 2025-10-13 19:07:05 +05:30
Jannat Patel 5e33ff4a34 chore: Turkish translations 2025-10-13 19:07:03 +05:30
Jannat Patel 2b234e5d64 chore: Swedish translations 2025-10-13 19:07:01 +05:30
Jannat Patel c8b328a1c9 chore: Serbian (Cyrillic) translations 2025-10-13 19:07:00 +05:30
Jannat Patel 5e0ac05f90 chore: Russian translations 2025-10-13 19:06:58 +05:30
Jannat Patel e440097272 chore: Portuguese translations 2025-10-13 19:06:57 +05:30
Jannat Patel 263c858a66 chore: Polish translations 2025-10-13 19:06:55 +05:30
Jannat Patel 82371fb2a8 chore: Dutch translations 2025-10-13 19:06:53 +05:30
Jannat Patel b6336a4096 chore: Italian translations 2025-10-13 19:06:51 +05:30
Jannat Patel 7acfbbaae7 chore: Hungarian translations 2025-10-13 19:06:50 +05:30
Jannat Patel 5a76b4eb2d chore: German translations 2025-10-13 19:06:48 +05:30
Jannat Patel 8aac88b696 chore: Danish translations 2025-10-13 19:06:47 +05:30
Jannat Patel d6e71068be chore: Czech translations 2025-10-13 19:06:45 +05:30
Jannat Patel 6b44951ef0 chore: Arabic translations 2025-10-13 19:06:43 +05:30
Jannat Patel 5289ebb923 chore: Spanish translations 2025-10-13 19:06:42 +05:30
Jannat Patel 263fcda053 chore: French translations 2025-10-13 19:06:40 +05:30
Jannat Patel 2e0d26575e Merge pull request #1775 from pateljannat/issues-138
fix: empty state for profile certificates section
2025-10-13 15:24:22 +05:30
Jannat Patel b9d6670bee fix: timezone for direct evaluation courses 2025-10-13 15:08:29 +05:30
Jannat Patel f20d39a3e7 fix: empty state for profile certificates section 2025-10-13 14:56:08 +05:30
Jannat Patel 09d948b3a0 Merge pull request #1774 from pateljannat/contact-us-mail-to
feat: contact us email modal
2025-10-13 13:22:26 +05:30
Jannat Patel 96941c83f3 fix: improved sidebar for settings 2025-10-13 13:14:13 +05:30
Jannat Patel b8ca0e381a feat: contact us email modal 2025-10-13 11:34:46 +05:30
Jannat Patel 4a2c5d77aa Merge pull request #1770 from frappe/pot_develop_2025-10-10
chore: update POT file
2025-10-13 11:11:39 +05:30
Jannat Patel cf2d29d82e Merge pull request #1771 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-13 11:11:27 +05:30
Jannat Patel fb2ab63550 chore: Polish translations 2025-10-12 18:34:31 +05:30
Jannat Patel 90efc152a8 chore: Burmese translations 2025-10-11 17:41:57 +05:30
frappe-pr-bot de6ba49409 chore: update POT file 2025-10-10 16:04:57 +00:00
Frappe PR Bot 9d4196f15a chore(release): Bumped to Version 2.38.0 2025-10-10 10:59:06 +00:00
Jannat Patel eed7fb970d Merge pull request #1769 from pateljannat/issues-137
fix: private file uploads in assignment text editor
2025-10-10 16:27:00 +05:30
Jannat Patel fe67f1ab61 Merge pull request #1767 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-10 15:55:51 +05:30
Jannat Patel 78640561f5 fix: private file uploads in assignment text editor 2025-10-10 15:52:35 +05:30
Jannat Patel f72631a262 fix: reverted the alternative host change 2025-10-10 12:31:49 +05:30
Jannat Patel 670e5d0202 Merge pull request #1768 from pateljannat/issues-136
fix: misc zoom issues
2025-10-10 11:48:47 +05:30
Jannat Patel ea59d1158a fix: misc zoom issues 2025-10-10 11:40:19 +05:30
Jannat Patel ba23cf9789 fix: misc zoom issues 2025-10-10 11:39:40 +05:30
Jannat Patel de585b90ea chore: Persian translations 2025-10-09 16:56:19 +05:30
Jannat Patel cf40f4e525 Merge pull request #1766 from pateljannat/issues-135
fix: live class issues
2025-10-09 15:50:01 +05:30
Jannat Patel b273e34ac8 fix: live class issues 2025-10-09 15:35:00 +05:30
Jannat Patel 1a00d708e1 Merge pull request #1762 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-08 17:10:46 +05:30
Jannat Patel 583584d8c5 Merge pull request #1763 from pateljannat/issues-134
fix: misc issues
2025-10-07 19:56:47 +05:30
Jannat Patel 09c087dee7 fix: misc issues 2025-10-07 19:24:47 +05:30
Jannat Patel f5cff50674 chore: Burmese translations 2025-10-07 17:03:51 +05:30
Jannat Patel 81c48d5182 chore: Persian translations 2025-10-07 17:03:43 +05:30
Jannat Patel c44414cadb chore: Portuguese, Brazilian translations 2025-10-07 17:03:41 +05:30
Jannat Patel 85db4be514 chore: Arabic translations 2025-10-07 17:03:24 +05:30
Jannat Patel 6526eefaf5 chore: French translations 2025-10-07 17:03:21 +05:30
Jannat Patel bd1fc5d705 Merge pull request #1760 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-07 10:46:27 +05:30
Jannat Patel ca547023b0 chore: Tamil translations 2025-10-06 16:21:31 +05:30
Jannat Patel caf57d355b chore: Esperanto translations 2025-10-06 16:21:30 +05:30
Jannat Patel 7e6da62480 chore: Serbian (Latin) translations 2025-10-06 16:21:28 +05:30
Jannat Patel e14e560415 chore: Norwegian Bokmal translations 2025-10-06 16:21:26 +05:30
Jannat Patel 0a8ac87cee chore: Bosnian translations 2025-10-06 16:21:25 +05:30
Jannat Patel 42441aafd6 chore: Croatian translations 2025-10-06 16:21:23 +05:30
Jannat Patel 9c3ff958e3 chore: Thai translations 2025-10-06 16:21:21 +05:30
Jannat Patel efac7af750 chore: Persian translations 2025-10-06 16:21:20 +05:30
Jannat Patel 314935f68e chore: Indonesian translations 2025-10-06 16:21:18 +05:30
Jannat Patel 1efa857d95 chore: Portuguese, Brazilian translations 2025-10-06 16:21:16 +05:30
Jannat Patel a7409b498e chore: Vietnamese translations 2025-10-06 16:21:13 +05:30
Jannat Patel a9cb0a8c26 chore: Chinese Simplified translations 2025-10-06 16:21:12 +05:30
Jannat Patel 9333affaf1 chore: Turkish translations 2025-10-06 16:21:10 +05:30
Jannat Patel 38a32be503 chore: Swedish translations 2025-10-06 16:21:08 +05:30
Jannat Patel fe5f7daf78 chore: Serbian (Cyrillic) translations 2025-10-06 16:20:58 +05:30
Jannat Patel 3c07c3e1cf chore: Russian translations 2025-10-06 16:20:57 +05:30
Jannat Patel cb87c75ac0 chore: Portuguese translations 2025-10-06 16:20:55 +05:30
Jannat Patel 62ead16817 chore: Polish translations 2025-10-06 16:20:53 +05:30
Jannat Patel 6352e4deb1 chore: Dutch translations 2025-10-06 16:20:52 +05:30
Jannat Patel 0c4b569be6 chore: Italian translations 2025-10-06 16:20:51 +05:30
Jannat Patel fe4d7cfb75 chore: Hungarian translations 2025-10-06 16:20:49 +05:30
Jannat Patel d3e791b017 chore: German translations 2025-10-06 16:20:48 +05:30
Jannat Patel 0849183d26 chore: Danish translations 2025-10-06 16:20:46 +05:30
Jannat Patel 3410af8899 chore: Czech translations 2025-10-06 16:20:45 +05:30
Jannat Patel 81a1e3a4c3 chore: Arabic translations 2025-10-06 16:20:44 +05:30
Jannat Patel c8e18dc445 chore: Spanish translations 2025-10-06 16:20:42 +05:30
Jannat Patel ad21bd6f53 chore: French translations 2025-10-06 16:20:41 +05:30
Jannat Patel 781457fce3 Merge pull request #1759 from pateljannat/contact-us
feat: contact us
2025-10-06 11:11:19 +05:30
Jannat Patel 6662b713f1 Merge pull request #1757 from frappe/pot_develop_2025-10-03
chore: update POT file
2025-10-06 10:57:28 +05:30
Jannat Patel 34c0d16411 refactor: changed Certified Members to Certifications 2025-10-06 10:33:50 +05:30
Jannat Patel f7003ecbbe feat: contact us 2025-10-06 10:15:53 +05:30
frappe-pr-bot 134090df5d chore: update POT file 2025-10-03 16:04:25 +00:00
Jannat Patel efb4feab2e Merge pull request #1755 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-03 10:44:01 +05:30
Jannat Patel 900e959b0b chore: Tamil translations 2025-10-01 14:02:00 +05:30
Jannat Patel 946ffeb3ca chore: Portuguese, Brazilian translations 2025-10-01 14:01:52 +05:30
Jannat Patel 56d32b0674 chore: Vietnamese translations 2025-10-01 14:01:50 +05:30
Jannat Patel 03fc5c084a chore: Chinese Simplified translations 2025-10-01 14:01:48 +05:30
Jannat Patel 2a32355dd8 chore: Polish translations 2025-10-01 14:01:42 +05:30
Jannat Patel d80d0e9d9b chore: Hungarian translations 2025-10-01 14:01:38 +05:30
Jannat Patel be0388ee6e chore: Arabic translations 2025-10-01 14:01:33 +05:30
Jannat Patel 414c41162a chore: French translations 2025-10-01 14:01:31 +05:30
Frappe PR Bot 39106de96c chore(release): Bumped to Version 2.37.0 2025-10-01 07:23:35 +00:00
Jannat Patel 8adb76abfb Merge pull request #1753 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-10-01 12:52:01 +05:30
Jannat Patel 4889b04283 chore: Persian translations 2025-09-30 14:05:54 +05:30
Jannat Patel e9973a242b Merge pull request #1748 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-09-30 10:29:49 +05:30
Jannat Patel d324ad0ac5 Merge pull request #1752 from pateljannat/issues-132
fix: misc issues
2025-09-30 10:29:33 +05:30
Jannat Patel ab6cc2698a fix: assignment should be uploaded as private file 2025-09-29 18:27:50 +05:30
Jannat Patel da076f71a1 fix: when course is unpublished and not coming either, user should not be able to access the course details 2025-09-29 18:09:03 +05:30
Jannat Patel 63c1fe8e75 fix: border when course card has an image 2025-09-29 15:26:14 +05:30
Jannat Patel 31f0833629 chore: removed unused files 2025-09-29 15:13:39 +05:30
Jannat Patel d4dc094049 chore: Serbian (Latin) translations 2025-09-29 13:56:06 +05:30
Jannat Patel 21a84e8032 chore: Serbian (Cyrillic) translations 2025-09-29 13:55:53 +05:30
Jannat Patel 819a1baae0 Merge pull request #1745 from UmakanthKaspa/fix/dark-theme-text-visibility
fix: make text visible in dark theme
2025-09-29 12:17:56 +05:30
Jannat Patel b0ee67faff Merge pull request #1743 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-09-29 12:17:14 +05:30
Jannat Patel 0684bd105a chore: Norwegian Bokmal translations 2025-09-28 13:59:13 +05:30
UmakanthKaspa 5c948862a0 fix: remove extra space in CSS class 2025-09-27 14:15:39 +00:00
UmakanthKaspa 23291b38de fix: add dark theme text colors to Create Program dialog 2025-09-27 13:59:07 +00:00
UmakanthKaspa 9357bd55a6 fix: make text visible in dark theme
- Add text-ink-gray-9 to headings
- Text now shows in both light and dark themes
2025-09-27 13:04:07 +00:00
Jannat Patel e51d668418 chore: Esperanto translations 2025-09-27 13:46:00 +05:30
Jannat Patel a48df70631 chore: Serbian (Latin) translations 2025-09-27 13:45:59 +05:30
Jannat Patel 9853e8311b chore: Norwegian Bokmal translations 2025-09-27 13:45:57 +05:30
Jannat Patel cd8041b048 chore: Bosnian translations 2025-09-27 13:45:56 +05:30
Jannat Patel 00bf5b7ad6 chore: Croatian translations 2025-09-27 13:45:54 +05:30
Jannat Patel 40bcc983c7 chore: Thai translations 2025-09-27 13:45:53 +05:30
Jannat Patel dfb26f31db chore: Persian translations 2025-09-27 13:45:51 +05:30
Jannat Patel a57a0bebef chore: Indonesian translations 2025-09-27 13:45:50 +05:30
Jannat Patel 4853621b1b chore: Portuguese, Brazilian translations 2025-09-27 13:45:49 +05:30
Jannat Patel e3209c6fb3 chore: Vietnamese translations 2025-09-27 13:45:48 +05:30
Jannat Patel 13d25cce1f chore: Chinese Simplified translations 2025-09-27 13:45:47 +05:30
Jannat Patel cb16b0ca64 chore: Turkish translations 2025-09-27 13:45:45 +05:30
Jannat Patel b3ce3159e7 chore: Swedish translations 2025-09-27 13:45:44 +05:30
Jannat Patel 76ffc70892 chore: Serbian (Cyrillic) translations 2025-09-27 13:45:42 +05:30
Jannat Patel 2734587981 chore: Russian translations 2025-09-27 13:45:41 +05:30
Jannat Patel 223e93d654 chore: Portuguese translations 2025-09-27 13:45:39 +05:30
Jannat Patel 26351726a8 chore: Polish translations 2025-09-27 13:45:38 +05:30
Jannat Patel efc84db580 chore: Dutch translations 2025-09-27 13:45:37 +05:30
Jannat Patel 3bf58bb6f0 chore: Italian translations 2025-09-27 13:45:35 +05:30
Jannat Patel a7962d9404 chore: Hungarian translations 2025-09-27 13:45:34 +05:30
Jannat Patel 5ce9bb306d chore: German translations 2025-09-27 13:45:33 +05:30
Jannat Patel 5b5bb38f4f chore: Danish translations 2025-09-27 13:45:32 +05:30
Jannat Patel 419ad311a0 chore: Czech translations 2025-09-27 13:45:30 +05:30
Jannat Patel 0c3af09566 chore: Arabic translations 2025-09-27 13:45:29 +05:30
Jannat Patel c9063625ec chore: Spanish translations 2025-09-27 13:45:28 +05:30
Jannat Patel 205858a41d chore: French translations 2025-09-27 13:45:26 +05:30
Jannat Patel 87edad17c3 Merge pull request #1742 from frappe/pot_develop_2025-09-26
chore: update POT file
2025-09-26 22:45:31 +05:30
frappe-pr-bot 1c54e80951 chore: update POT file 2025-09-26 16:04:27 +00:00
Jannat Patel 6c19cdc729 Merge pull request #1741 from pateljannat/fui-upgrade
chore: upgraded frappe ui and made relevant changes
2025-09-25 18:30:15 +05:30
Jannat Patel 84a703bb50 test: updated tests as per latest frappe ui version 2025-09-25 18:19:03 +05:30
Jannat Patel 27ed95b044 Merge pull request #1739 from KerollesFathy/work-mode-on-job-portal
feat(jobs): Add Work Mode on Job Portal
2025-09-25 17:42:57 +05:30
Jannat Patel 0358dfe790 fix: upgraded evaluator schedule as per latest frappe ui 2025-09-25 17:42:12 +05:30
KerollesFathy 68cee65f22 refactor: make all filters on the same line 2025-09-25 11:59:57 +00:00
Jannat Patel 24b2125b97 chore: upgraded frappe ui and made relevant changes 2025-09-25 16:46:29 +05:30
Jannat Patel eceed12992 Merge pull request #1740 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-09-25 13:02:02 +05:30
Jannat Patel f9028433a0 chore: Serbian (Latin) translations 2025-09-25 12:44:36 +05:30
Jannat Patel 1936e7b212 chore: Bosnian translations 2025-09-25 12:44:33 +05:30
Jannat Patel c04a972be3 chore: Croatian translations 2025-09-25 12:44:32 +05:30
Jannat Patel 9c26b011e4 chore: Swedish translations 2025-09-25 12:44:23 +05:30
Jannat Patel 821f125789 chore: Serbian (Cyrillic) translations 2025-09-25 12:44:22 +05:30
Jannat Patel e0f376880a chore: Dutch translations 2025-09-25 12:44:18 +05:30
Jannat Patel 6da77bb3c7 chore: Hungarian translations 2025-09-25 12:44:15 +05:30
Jannat Patel 2fd660a93f chore: German translations 2025-09-25 12:44:14 +05:30
Jannat Patel f3eefc748a chore: Danish translations 2025-09-25 12:44:12 +05:30
Jannat Patel 4852698d74 chore: Czech translations 2025-09-25 12:44:11 +05:30
Jannat Patel 36b24dc826 chore: Arabic translations 2025-09-25 12:44:09 +05:30
Jannat Patel d60bc1d4b6 chore: Spanish translations 2025-09-25 12:44:08 +05:30
Jannat Patel 06a02c0877 chore: French translations 2025-09-25 12:44:06 +05:30
KerollesFathy 1a53a9f30b feat: Add work mode selection to job form 2025-09-24 14:24:08 +00:00
KerollesFathy 7ee81d4693 feat: Add work mode badge to job detail page 2025-09-24 14:23:45 +00:00
KerollesFathy 0a32d03fda feat: Display work mode badge on job card 2025-09-24 14:22:59 +00:00
KerollesFathy 6c43dfea18 feat: Add work mode filter and selection to job opportunities 2025-09-24 14:22:07 +00:00
KerollesFathy 7d1e226743 feat: Add work mode on job opportunity 2025-09-24 14:21:03 +00:00
Frappe PR Bot 8ea903b81a chore(release): Bumped to Version 2.36.0 2025-09-24 07:17:24 +00:00
Jannat Patel 24b08599b3 Merge pull request #1737 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-09-24 12:46:37 +05:30
Jannat Patel a0f1c1f227 chore: Esperanto translations 2025-09-24 12:46:22 +05:30
Jannat Patel efbb014588 chore: Serbian (Latin) translations 2025-09-24 12:46:20 +05:30
Jannat Patel f881a0e1d5 chore: Norwegian Bokmal translations 2025-09-24 12:46:19 +05:30
Jannat Patel acdb81e8a3 chore: Bosnian translations 2025-09-24 12:46:17 +05:30
Jannat Patel 6559a87323 chore: Croatian translations 2025-09-24 12:46:15 +05:30
Jannat Patel 8301bab768 chore: Thai translations 2025-09-24 12:46:14 +05:30
Jannat Patel eb0b2010f9 chore: Persian translations 2025-09-24 12:46:12 +05:30
Jannat Patel 8158ea164d chore: Indonesian translations 2025-09-24 12:46:10 +05:30
Jannat Patel beb3134af9 chore: Portuguese, Brazilian translations 2025-09-24 12:46:08 +05:30
Jannat Patel 5fdc6a21a5 chore: Vietnamese translations 2025-09-24 12:46:07 +05:30
Jannat Patel e7516c57bc chore: Chinese Simplified translations 2025-09-24 12:46:05 +05:30
Jannat Patel 2169d81b73 chore: Turkish translations 2025-09-24 12:46:04 +05:30
Jannat Patel 1d6bb9f9f6 chore: Swedish translations 2025-09-24 12:46:02 +05:30
Jannat Patel 812bd07d03 chore: Serbian (Cyrillic) translations 2025-09-24 12:46:01 +05:30
Jannat Patel 19bb02f905 chore: Russian translations 2025-09-24 12:45:59 +05:30
Jannat Patel 58d750f726 chore: Portuguese translations 2025-09-24 12:45:58 +05:30
Jannat Patel 7f3bb58ec1 chore: Polish translations 2025-09-24 12:45:56 +05:30
Jannat Patel 08ceaf204f chore: Dutch translations 2025-09-24 12:45:54 +05:30
Jannat Patel eced1221a8 chore: Italian translations 2025-09-24 12:45:52 +05:30
Jannat Patel 3a5bbde0cc chore: Hungarian translations 2025-09-24 12:45:51 +05:30
Jannat Patel eb1a790485 chore: German translations 2025-09-24 12:45:49 +05:30
Jannat Patel 21e9c85bf7 chore: Danish translations 2025-09-24 12:45:47 +05:30
Jannat Patel 632f783d57 chore: Czech translations 2025-09-24 12:45:46 +05:30
Jannat Patel 3ba3908108 chore: Arabic translations 2025-09-24 12:45:44 +05:30
Jannat Patel 903a4e91b0 chore: Spanish translations 2025-09-24 12:45:43 +05:30
Jannat Patel 6496b129ce chore: French translations 2025-09-24 12:45:41 +05:30
Jannat Patel 9fff7a2ea8 Merge pull request #1736 from pateljannat/pwa-customizations
feat: PWA Customizations
2025-09-24 12:26:54 +05:30
Jannat Patel 6d94617e59 feat: PWA Customizations 2025-09-24 12:11:12 +05:30
Jannat Patel b95d07babb Merge pull request #1732 from pateljannat/activation
chore: site data for analytics
2025-09-23 14:54:47 +05:30
Jannat Patel 9748d075fa chore: site data for analytics 2025-09-23 13:00:58 +05:30
Jannat Patel aaeeb84ed3 Merge pull request #1726 from pateljannat/payment-settings-refactor
refactor: payment settings
2025-09-23 11:37:03 +05:30
Jannat Patel c3702ee6d5 feat: transaction list 2025-09-23 11:26:46 +05:30
Jannat Patel f239987043 feat: new payment gateway creation from settings 2025-09-22 14:19:27 +05:30
Jannat Patel 6aa67c3fae Merge pull request #1727 from frappe/pot_develop_2025-09-19
chore: update POT file
2025-09-22 11:16:45 +05:30
frappe-pr-bot 1fc5d75cc0 chore: update POT file 2025-09-19 16:04:26 +00:00
Frappe PR Bot 2e0cd1964c chore(release): Bumped to Version 2.35.0 2025-09-18 13:01:47 +00:00
Jannat Patel bcfd3bb636 refactor: payment settings 2025-09-18 18:29:08 +05:30
Jannat Patel 9b893b56f4 Merge branch 'develop' of https://github.com/frappe/lms into develop 2025-09-17 16:00:52 +05:30
Jannat Patel 733254e2c0 fix: URL in iframe for programming exercises 2025-09-17 15:58:02 +05:30
Jannat Patel 1e351e60a5 Merge pull request #1725 from pateljannat/language-control
feat: switch language from profile
2025-09-17 15:55:37 +05:30
Jannat Patel 90c53e4b46 feat: switch language from profile 2025-09-17 15:46:28 +05:30
Jannat Patel 69f54a00c5 Merge pull request #1263 from FahidLatheef/feat/scorm-progress
feat: SCORM Course Resume Functionality
2025-09-17 12:50:22 +05:30
Jannat Patel 372c4d33f0 Merge pull request #1722 from pateljannat/issues-131
fix: misc issues
2025-09-17 12:48:42 +05:30
Jannat Patel 5ba77aae3d fix: moved lesson navigation buttons to navbar to keep them always visible 2025-09-17 12:15:51 +05:30
Jannat Patel 28f4de1b7f fix: check if question exists in local storage before adding to avoid duplicate 2025-09-17 11:45:09 +05:30
Jannat Patel ed162e2546 fix: don't allow unnecessary attributes in profile bio 2025-09-16 11:34:09 +05:30
Jannat Patel e16cecd149 Merge pull request #1718 from frappe/pot_develop_2025-09-12
chore: update POT file
2025-09-15 11:24:43 +05:30
frappe-pr-bot 3a26a5b4d8 chore: update POT file 2025-09-12 16:04:25 +00:00
Jannat Patel 3848af08fe Merge pull request #1711 from frappe/pot_develop_2025-09-05
chore: update POT file
2025-09-08 10:06:02 +05:30
Fahid Latheef Alungal ae79e52486 fix: add a 300 ms debounce on saveProgress from 'cmi.suspend_data' SCORM API to prevent duplicate entries 2025-09-07 19:04:16 +05:30
Fahid Latheef Alungal 1968f5064d refactor: dropped typehints from whitelisted method to avoid unexpected errors 2025-09-07 17:55:54 +05:30
Fahid Latheef Alungal 9d21bcecbe fix: typehint for SCORMDetails 2025-09-07 17:07:07 +05:30
Fahid Latheef Alungal 7a84933b2f Merge remote-tracking branch 'origin/develop' into feat/scorm-progress 2025-09-07 02:00:32 +05:30
frappe-pr-bot 9a10240fcc chore: update POT file 2025-09-05 16:04:16 +00:00
Jannat Patel 99516421ac Merge pull request #1710 from vishwajeet-13/fix/installprompt-responsive-in-mobile
fix(ui): make install prompt message mobile responsive
2025-09-04 13:55:19 +05:30
vishwajeet 5eecffb75e fix(ui): make install prompt message mobile responsive 2025-09-04 13:35:14 +05:30
Jannat Patel 9d2627849a fix: scorm patch query 2025-09-03 15:44:10 +05:30
Frappe PR Bot 22b8222c3d chore(release): Bumped to Version 2.34.1 2025-09-03 05:39:26 +00:00
Jannat Patel b3d1b14abd Merge pull request #1708 from pateljannat/issues-130
fix: misc issues
2025-09-03 10:41:52 +05:30
Jannat Patel f1cd0d3dd4 fix: misc issues 2025-09-02 19:57:32 +05:30
Jannat Patel 3d7815d65f Merge pull request #1369 from FahidLatheef/fix/continue-learning
fix: fixed issue with Lesson Render for SCORM Chapters
2025-09-02 09:48:25 +05:30
Fahid Latheef Alungal a3e7d1f981 refactor: derive is_scorm_package from Lesson instead of Chapter 2025-09-02 02:29:19 +05:30
Fahid Latheef Alungal 2e79190977 fix: added Patch to update wrong indexes for SCORM Lesson References 2025-09-02 01:36:18 +05:30
Fahid Latheef Alungal ee7debeef7 fix: added missing index for first lesson for SCORM 2025-09-02 00:28:26 +05:30
Fahid Latheef Alungal 61f547733c fix: Continue Learning button not working for SCORM Chapters 2025-09-01 23:51:46 +05:30
Jannat Patel 5129e6d6ac Merge pull request #1707 from frappe/pot_develop_2025-08-29
chore: update POT file
2025-09-01 10:00:25 +05:30
Hussain Nagaria 0a9c14f8b1 Merge pull request #1706 from vishwajeet-13/fix/mobile-view-for-live-class 2025-08-31 19:55:06 +05:30
vishwajeet a1960489e1 chore: ran pre-commit 2025-08-30 11:34:31 +05:30
frappe-pr-bot 66fe1a83c6 chore: update POT file 2025-08-29 16:04:45 +00:00
vishwajeet a88d384ac7 fix: mobile responsive live class card 2025-08-29 19:04:33 +05:30
Jannat Patel 2dc6b68974 Merge branch 'develop' of https://github.com/frappe/lms into develop 2025-08-29 17:44:03 +05:30
Jannat Patel 0988ecc515 fix: misc issues on home page 2025-08-29 17:43:44 +05:30
Frappe PR Bot 5ff100da27 chore(release): Bumped to Version 2.34.0 2025-08-29 11:16:37 +00:00
Jannat Patel f218846f4a Merge pull request #1700 from vishwajeet-13/fix/ui-text-correction
fix(ui): correct mislabeled subtitle in statistics
2025-08-28 12:28:14 +05:30
Jannat Patel fc0aba60b9 Merge pull request #1704 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-28 12:26:29 +05:30
Jannat Patel 82e6a62c54 chore: Norwegian Bokmal translations 2025-08-28 09:48:09 +05:30
Jannat Patel fce8950cc5 chore: Danish translations 2025-08-28 09:48:08 +05:30
Jannat Patel 54247e85e0 Merge pull request #1696 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-27 20:39:35 +05:30
vishwajeet cc3f9cd8a4 fix(ui): correct mislabeled subtitle in statistics 2025-08-27 17:43:09 +05:30
Jannat Patel 6dd79dc5d2 chore: Norwegian Bokmal translations 2025-08-27 09:36:52 +05:30
Jannat Patel 6eb53770c3 chore: Danish translations 2025-08-27 09:36:51 +05:30
Jannat Patel 10faeca121 chore: Serbian (Latin) translations 2025-08-27 09:36:49 +05:30
Jannat Patel 38252d9ffc chore: Thai translations 2025-08-27 09:36:46 +05:30
Jannat Patel 86f62aeb99 chore: Portuguese, Brazilian translations 2025-08-27 09:36:43 +05:30
Jannat Patel e3a6bb8781 chore: Turkish translations 2025-08-27 09:36:40 +05:30
Jannat Patel 8ed94ed12f chore: Serbian (Cyrillic) translations 2025-08-27 09:36:37 +05:30
Jannat Patel 95bcfc2ee0 chore: Russian translations 2025-08-27 09:36:36 +05:30
Jannat Patel 313e4811a1 chore: Polish translations 2025-08-27 09:36:33 +05:30
Jannat Patel 5bb9dfeaf8 chore: Spanish translations 2025-08-27 09:36:27 +05:30
Jannat Patel aabb316c7d Merge pull request #1694 from pateljannat/home-page
feat: home page
2025-08-26 12:30:01 +05:30
Jannat Patel ae40e6f41b fix: batch forms labels to add more clarity 2025-08-26 12:17:26 +05:30
Jannat Patel e644d5d20d fix: lesson progress check issue 2025-08-26 11:35:28 +05:30
Jannat Patel ae9abd08ff chore: French translations 2025-08-26 08:58:40 +05:30
Jannat Patel 965128c802 chore: Esperanto translations 2025-08-26 08:58:38 +05:30
Jannat Patel 26324a63df chore: Serbian (Latin) translations 2025-08-26 08:58:37 +05:30
Jannat Patel b9d9754818 chore: Bosnian translations 2025-08-26 08:58:36 +05:30
Jannat Patel 0fb516a86c chore: Croatian translations 2025-08-26 08:58:34 +05:30
Jannat Patel 4b4c7d8927 chore: Thai translations 2025-08-26 08:58:33 +05:30
Jannat Patel e3cae93bd3 chore: Persian translations 2025-08-26 08:58:31 +05:30
Jannat Patel 324f87dc19 chore: Indonesian translations 2025-08-26 08:58:30 +05:30
Jannat Patel 347b5c9411 chore: Portuguese, Brazilian translations 2025-08-26 08:58:29 +05:30
Jannat Patel 7371f8a29d chore: Vietnamese translations 2025-08-26 08:58:27 +05:30
Jannat Patel fb381a30cf chore: Chinese Simplified translations 2025-08-26 08:58:26 +05:30
Jannat Patel 474e3dae65 chore: Turkish translations 2025-08-26 08:58:24 +05:30
Jannat Patel 738ac3f1c9 chore: Swedish translations 2025-08-26 08:58:23 +05:30
Jannat Patel 2fbe69afc5 chore: Serbian (Cyrillic) translations 2025-08-26 08:58:21 +05:30
Jannat Patel 693448cb42 chore: Russian translations 2025-08-26 08:58:20 +05:30
Jannat Patel 17a416d905 chore: Portuguese translations 2025-08-26 08:58:18 +05:30
Jannat Patel 09a6ede925 chore: Polish translations 2025-08-26 08:58:17 +05:30
Jannat Patel 5fc04ae318 chore: Dutch translations 2025-08-26 08:58:15 +05:30
Jannat Patel 900ea0fb5c chore: Italian translations 2025-08-26 08:58:14 +05:30
Jannat Patel 85a6a1d884 chore: Hungarian translations 2025-08-26 08:58:12 +05:30
Jannat Patel 0572009456 chore: German translations 2025-08-26 08:58:11 +05:30
Jannat Patel 9bcd98cb69 chore: Czech translations 2025-08-26 08:58:10 +05:30
Jannat Patel aefce2a842 chore: Arabic translations 2025-08-26 08:58:08 +05:30
Jannat Patel ee4fe99b08 chore: Spanish translations 2025-08-26 08:58:07 +05:30
Jannat Patel 2cb85d47b8 chore: removed unused files 2025-08-25 15:37:00 +05:30
Jannat Patel 0713b6b419 fix: streak logic 2025-08-25 15:33:05 +05:30
Jannat Patel 8f116fddab Merge pull request #1695 from frappe/pot_develop_2025-08-22
chore: update POT file
2025-08-25 10:08:06 +05:30
Jannat Patel 58838cd806 Merge branch 'develop' into pot_develop_2025-08-22 2025-08-25 10:07:59 +05:30
Jannat Patel 7d5918b320 fix: program list heading 2025-08-25 09:57:00 +05:30
Jannat Patel 7eb4ca0fb4 fix: live class end time 2025-08-25 09:22:59 +05:30
Jannat Patel d575bfa0fb feat: streak details 2025-08-25 09:19:03 +05:30
Jannat Patel b60ea3f153 chore: Indonesian translations 2025-08-25 08:59:48 +05:30
Jannat Patel 6e7bc6cfb4 chore: Italian translations 2025-08-25 08:59:39 +05:30
frappe-pr-bot 9b85a0044c chore: update POT file 2025-08-22 16:04:56 +00:00
Jannat Patel b8708382b1 feat: Admin Home 2025-08-22 16:47:25 +05:30
Jannat Patel e0601c7b38 feat: home page 2025-08-21 21:16:21 +05:30
Jannat Patel 0725714144 Merge pull request #1692 from pateljannat/issues-129
fix: misc issues
2025-08-20 18:31:43 +05:30
Jannat Patel ab501e1c6a fix: filter when getting programming exercise title when adding to lesson 2025-08-20 17:18:47 +05:30
Jannat Patel 7cd401327b fix: misc issues 2025-08-20 17:13:23 +05:30
Jannat Patel e886088dff Merge pull request #1686 from pateljannat/program-refactor
refactor: learning path
2025-08-20 14:09:41 +05:30
Jannat Patel ebe7cc32af fix: misc issues 2025-08-20 13:30:31 +05:30
Jannat Patel 5e607c3b8e refactor: sidebar visibility of programs 2025-08-20 13:11:22 +05:30
Jannat Patel 5ec809e3dd feat: program progress summary 2025-08-20 12:06:52 +05:30
Jannat Patel 9d3b6e0556 feat: program self enrollment 2025-08-19 17:33:20 +05:30
Jannat Patel acd003814a refactor: program list for students 2025-08-18 15:51:07 +05:30
Jannat Patel c4991d09f3 Merge pull request #1688 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-18 11:26:35 +05:30
Jannat Patel ca9b2dada3 chore: Serbian (Latin) translations 2025-08-18 08:04:07 +05:30
Jannat Patel 6a3004d75d chore: Serbian (Cyrillic) translations 2025-08-18 08:03:56 +05:30
Jannat Patel 9bd624f31a chore: Swedish translations 2025-08-17 07:45:41 +05:30
Jannat Patel acb264da20 chore: French translations 2025-08-16 07:25:45 +05:30
Jannat Patel c23b0fbfe7 chore: Esperanto translations 2025-08-16 07:25:44 +05:30
Jannat Patel 0e78b5e289 chore: Serbian (Latin) translations 2025-08-16 07:25:42 +05:30
Jannat Patel 91ab895a1d chore: Bosnian translations 2025-08-16 07:25:41 +05:30
Jannat Patel 5c37238114 chore: Croatian translations 2025-08-16 07:25:39 +05:30
Jannat Patel 3cf40ba504 chore: Thai translations 2025-08-16 07:25:38 +05:30
Jannat Patel 9229961f72 chore: Persian translations 2025-08-16 07:25:36 +05:30
Jannat Patel 0b35b11909 chore: Indonesian translations 2025-08-16 07:25:35 +05:30
Jannat Patel 77a27d8716 chore: Portuguese, Brazilian translations 2025-08-16 07:25:34 +05:30
Jannat Patel be32939029 chore: Vietnamese translations 2025-08-16 07:25:32 +05:30
Jannat Patel 4f046425aa chore: Chinese Simplified translations 2025-08-16 07:25:31 +05:30
Jannat Patel 89bf6b1fd9 chore: Turkish translations 2025-08-16 07:25:30 +05:30
Jannat Patel d81414cca6 chore: Swedish translations 2025-08-16 07:25:28 +05:30
Jannat Patel d8eb96a37a chore: Serbian (Cyrillic) translations 2025-08-16 07:25:27 +05:30
Jannat Patel d1b3b0ba34 chore: Russian translations 2025-08-16 07:25:25 +05:30
Jannat Patel dca207347f chore: Portuguese translations 2025-08-16 07:25:24 +05:30
Jannat Patel 5a7ebf8027 chore: Polish translations 2025-08-16 07:25:23 +05:30
Jannat Patel f6d877715c chore: Dutch translations 2025-08-16 07:25:22 +05:30
Jannat Patel 754eb32db4 chore: Italian translations 2025-08-16 07:25:20 +05:30
Jannat Patel 67c04c7f59 chore: Hungarian translations 2025-08-16 07:25:19 +05:30
Jannat Patel daebb26ffa chore: German translations 2025-08-16 07:25:18 +05:30
Jannat Patel 3e2993d048 chore: Czech translations 2025-08-16 07:25:16 +05:30
Jannat Patel 2745cf4015 chore: Arabic translations 2025-08-16 07:25:15 +05:30
Jannat Patel 4e99e2960c chore: Spanish translations 2025-08-16 07:25:13 +05:30
Jannat Patel 649028307d Merge pull request #1687 from frappe/pot_develop_2025-08-15
chore: update POT file
2025-08-15 21:57:49 +05:30
frappe-pr-bot 24787c32dd chore: update POT file 2025-08-15 16:04:47 +00:00
Jannat Patel 625ddac65a refactor: learning path 2025-08-14 20:26:46 +05:30
Jannat Patel 78ff2e6d07 Merge pull request #1684 from pateljannat/issues-128
fix: misc ui issues
2025-08-12 15:14:35 +05:30
Jannat Patel 837426d3c5 Merge pull request #1683 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-12 15:03:47 +05:30
Jannat Patel 65477a5b2b fix: misc ui issues 2025-08-12 15:03:19 +05:30
Jannat Patel a9fa8be5a2 chore: French translations 2025-08-12 06:48:19 +05:30
Jannat Patel 0bb26150d6 chore: Esperanto translations 2025-08-12 06:48:17 +05:30
Jannat Patel fd8f7ade51 chore: Serbian (Latin) translations 2025-08-12 06:48:16 +05:30
Jannat Patel 3310bc2fed chore: Bosnian translations 2025-08-12 06:48:14 +05:30
Jannat Patel 0cbb640054 chore: Croatian translations 2025-08-12 06:48:13 +05:30
Jannat Patel b4aa88ac33 chore: Thai translations 2025-08-12 06:48:11 +05:30
Jannat Patel f2906e57f0 chore: Persian translations 2025-08-12 06:48:10 +05:30
Jannat Patel 8d381b167e chore: Indonesian translations 2025-08-12 06:48:08 +05:30
Jannat Patel d78e316349 chore: Portuguese, Brazilian translations 2025-08-12 06:48:07 +05:30
Jannat Patel 82d00c6a4a chore: Vietnamese translations 2025-08-12 06:48:05 +05:30
Jannat Patel ba4fd7f1ef chore: Chinese Simplified translations 2025-08-12 06:48:04 +05:30
Jannat Patel 591d265167 chore: Turkish translations 2025-08-12 06:48:02 +05:30
Jannat Patel af9d973a91 chore: Swedish translations 2025-08-12 06:48:01 +05:30
Jannat Patel 15096a3118 chore: Serbian (Cyrillic) translations 2025-08-12 06:47:59 +05:30
Jannat Patel 7c78a9697c chore: Russian translations 2025-08-12 06:47:58 +05:30
Jannat Patel 3f5051f697 chore: Portuguese translations 2025-08-12 06:47:56 +05:30
Jannat Patel 044a66f2e8 chore: Polish translations 2025-08-12 06:47:55 +05:30
Jannat Patel 6fb8775bb7 chore: Dutch translations 2025-08-12 06:47:53 +05:30
Jannat Patel f16d0300ba chore: Italian translations 2025-08-12 06:47:52 +05:30
Jannat Patel 84e12f1eea chore: Hungarian translations 2025-08-12 06:47:50 +05:30
Jannat Patel ba40b7ff15 chore: German translations 2025-08-12 06:47:49 +05:30
Jannat Patel e733326056 chore: Czech translations 2025-08-12 06:47:47 +05:30
Jannat Patel b3d987e933 chore: Arabic translations 2025-08-12 06:47:46 +05:30
Jannat Patel e919874e9e chore: Spanish translations 2025-08-12 06:47:44 +05:30
Jannat Patel a2f51f151a Merge pull request #1681 from pateljannat/pre-commit
chore: formatted files with ruff
2025-08-11 21:30:17 +05:30
Jannat Patel ea288abb27 test: fixed batch overlay test 2025-08-11 20:06:43 +05:30
Jannat Patel b274900ae0 chore: removed profile page renderers 2025-08-11 19:34:22 +05:30
Jannat Patel 10d29d3a3f chore: formatted js with eslint 2025-08-11 17:56:51 +05:30
Jannat Patel a92e04343a chore: formatted files with ruff 2025-08-11 17:48:37 +05:30
Jannat Patel be31c18bfe Merge pull request #1680 from pateljannat/pwa
feat: PWA
2025-08-11 17:26:42 +05:30
Jannat Patel 9d0a5fd8f3 chore: updated pre-commit config 2025-08-11 17:06:35 +05:30
Jannat Patel 5ca577bc0a fix: responsive layout for pages 2025-08-11 17:02:46 +05:30
Jannat Patel 4d25d185c3 feat: PWA 2025-08-11 15:43:34 +05:30
Jannat Patel ea289e02da Merge pull request #1679 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-11 11:22:56 +05:30
Jannat Patel a3f16eb7e8 Merge pull request #1678 from frappe/pot_develop_2025-08-08
chore: update POT file
2025-08-11 11:22:41 +05:30
Jannat Patel ddd29abe99 chore: Italian translations 2025-08-11 06:48:11 +05:30
Jannat Patel decd56f2d2 chore: Italian translations 2025-08-10 06:47:20 +05:30
frappe-pr-bot 387401cb44 chore: update POT file 2025-08-08 16:04:31 +00:00
Jannat Patel 57c1a6b540 Merge pull request #1676 from pateljannat/issues-127
fix: misc issues
2025-08-08 12:08:04 +05:30
Jannat Patel 8dba0e8242 Merge pull request #1677 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-08 12:06:59 +05:30
Jannat Patel ee715f6387 chore: fixed linters 2025-08-08 10:47:21 +05:30
Jannat Patel b770b30334 chore: Italian translations 2025-08-08 06:54:22 +05:30
Jannat Patel d61abac126 fix: validate is uploaded svg is malicious 2025-08-07 17:33:32 +05:30
Jannat Patel ccf28b8012 refactor: bring course title down from the gradient in course cards 2025-08-07 17:23:14 +05:30
Jannat Patel 3762cb06bb Merge pull request #1671 from pateljannat/notes
feat: notes and highlights in lesson
2025-08-07 17:11:46 +05:30
Jannat Patel 15400f2a3e test: open community tab before testing discussions 2025-08-07 17:01:55 +05:30
Jannat Patel 20d1b1fe83 Merge pull request #1675 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-07 16:05:03 +05:30
Jannat Patel 73844f8813 fix: minor changes with visibility and change 2025-08-07 16:04:36 +05:30
Jannat Patel 2187553625 chore: Serbian (Latin) translations 2025-08-07 06:36:14 +05:30
Jannat Patel 984b2a5dea chore: Serbian (Cyrillic) translations 2025-08-07 06:36:13 +05:30
Jannat Patel 9098d9454f Merge pull request #1674 from pateljannat/issues-126
fix: video statistics scroll and time format
2025-08-06 11:28:15 +05:30
Jannat Patel 027dd93fb5 fix: reload notes when moving to another lesson 2025-08-06 11:13:16 +05:30
Jannat Patel a005adc89a Merge pull request #1672 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-06 10:32:09 +05:30
Jannat Patel 866ef04fbf chore: Esperanto translations 2025-08-06 05:34:46 +05:30
Jannat Patel 00b6f97e3a chore: Serbian (Latin) translations 2025-08-06 05:34:45 +05:30
Jannat Patel a1d21b1a2a chore: Bosnian translations 2025-08-06 05:34:43 +05:30
Jannat Patel 7358ea43d8 chore: Croatian translations 2025-08-06 05:34:42 +05:30
Jannat Patel 88c69311eb chore: Thai translations 2025-08-06 05:34:40 +05:30
Jannat Patel c1e45e5d0d chore: Persian translations 2025-08-06 05:34:39 +05:30
Jannat Patel fe78de2417 chore: Indonesian translations 2025-08-06 05:34:37 +05:30
Jannat Patel 4c1fc201e6 chore: Portuguese, Brazilian translations 2025-08-06 05:34:36 +05:30
Jannat Patel 3f5d270915 chore: Vietnamese translations 2025-08-06 05:34:34 +05:30
Jannat Patel a452fbeb07 chore: Chinese Simplified translations 2025-08-06 05:34:33 +05:30
Jannat Patel a6f02c245f chore: Turkish translations 2025-08-06 05:34:31 +05:30
Jannat Patel cb4f9129d6 chore: Swedish translations 2025-08-06 05:34:30 +05:30
Jannat Patel 9c5d64c211 chore: Serbian (Cyrillic) translations 2025-08-06 05:34:28 +05:30
Jannat Patel 41dc0ecc60 chore: Russian translations 2025-08-06 05:34:26 +05:30
Jannat Patel 6b9409b889 chore: Portuguese translations 2025-08-06 05:34:25 +05:30
Jannat Patel ea66eeed6c chore: Polish translations 2025-08-06 05:34:24 +05:30
Jannat Patel a419d28ef1 chore: Dutch translations 2025-08-06 05:34:22 +05:30
Jannat Patel 481dfc24fd chore: Italian translations 2025-08-06 05:34:20 +05:30
Jannat Patel ed686a7d52 chore: Hungarian translations 2025-08-06 05:34:19 +05:30
Jannat Patel b4c5a07800 chore: German translations 2025-08-06 05:34:17 +05:30
Jannat Patel 6ae16f7fef chore: Czech translations 2025-08-06 05:34:16 +05:30
Jannat Patel 4aae2ed3b8 chore: Arabic translations 2025-08-06 05:34:14 +05:30
Jannat Patel 81d4137b20 chore: Spanish translations 2025-08-06 05:34:13 +05:30
Jannat Patel 77ecb02a17 feat: notes in lesson 2025-08-05 20:00:09 +05:30
Jannat Patel 4a375f92ed Merge pull request #1668 from frappe/pot_develop_2025-08-01
chore: update POT file
2025-08-04 20:05:22 +05:30
Jannat Patel 7caf91460a Merge pull request #1669 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-08-04 20:05:12 +05:30
Jannat Patel 0e015c8b97 chore: Indonesian translations 2025-08-03 04:35:30 +05:30
frappe-pr-bot 7b69ddb14d chore: update POT file 2025-08-01 16:04:44 +00:00
Jannat Patel 2271eb270e Merge pull request #1667 from harshpwctech/develop
refactor: Announcement mail being sent to students in BCC
2025-08-01 17:32:41 +05:30
CA Harsh Agrawal 7e5b2e4e79 refactor: Announcement mail being sent to students in BCC 2025-08-01 17:02:48 +05:30
Jannat Patel 124b9d9ea5 fix: video statistics scroll 2025-07-30 17:31:33 +05:30
Jannat Patel 36076068ec fix: text padding on card gradient 2025-07-30 12:30:12 +05:30
Frappe PR Bot c868354b5b chore(release): Bumped to Version 2.33.0 2025-07-30 06:14:36 +00:00
Jannat Patel db91f0b2a0 Merge pull request #1663 from pateljannat/issues-125
fix: show video statistics watch time in minutes
2025-07-30 11:43:01 +05:30
Jannat Patel d7e83bb78e fix: show video statistics watch time in minutes 2025-07-30 11:30:17 +05:30
Jannat Patel feb2a39e05 Merge pull request #1661 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-30 10:53:15 +05:30
Jannat Patel a6cf910d05 chore: Esperanto translations 2025-07-30 04:23:56 +05:30
Jannat Patel b891b44ac6 chore: Spanish translations 2025-07-30 04:23:54 +05:30
Jannat Patel 026a3ebb81 chore: Serbian (Latin) translations 2025-07-30 04:23:53 +05:30
Jannat Patel 71ba246011 chore: Bosnian translations 2025-07-30 04:23:51 +05:30
Jannat Patel a391204fa6 chore: Croatian translations 2025-07-30 04:23:49 +05:30
Jannat Patel 9c773399a8 chore: Thai translations 2025-07-30 04:23:48 +05:30
Jannat Patel 528b85352a chore: Persian translations 2025-07-30 04:23:47 +05:30
Jannat Patel 249c369c14 chore: Indonesian translations 2025-07-30 04:23:45 +05:30
Jannat Patel 9803fc1031 chore: Portuguese, Brazilian translations 2025-07-30 04:23:44 +05:30
Jannat Patel 299fde1c98 chore: Vietnamese translations 2025-07-30 04:23:43 +05:30
Jannat Patel 7f55734fbb chore: Chinese Simplified translations 2025-07-30 04:23:41 +05:30
Jannat Patel efe230865a chore: Turkish translations 2025-07-30 04:23:40 +05:30
Jannat Patel 6e52e684c8 chore: Swedish translations 2025-07-30 04:23:38 +05:30
Jannat Patel 99d880297a chore: Serbian (Cyrillic) translations 2025-07-30 04:23:36 +05:30
Jannat Patel dec706ae72 chore: Russian translations 2025-07-30 04:23:35 +05:30
Jannat Patel 2e60f0a0c2 chore: Portuguese translations 2025-07-30 04:23:34 +05:30
Jannat Patel ef612f86e5 chore: Polish translations 2025-07-30 04:23:32 +05:30
Jannat Patel 9c16e03ea7 chore: Dutch translations 2025-07-30 04:23:31 +05:30
Jannat Patel 7780c0310e chore: Italian translations 2025-07-30 04:23:29 +05:30
Jannat Patel b0a23c0d1a chore: Hungarian translations 2025-07-30 04:23:27 +05:30
Jannat Patel 05c85cea08 chore: German translations 2025-07-30 04:23:26 +05:30
Jannat Patel 1ffae0a1de chore: Czech translations 2025-07-30 04:23:24 +05:30
Jannat Patel 15cbccd15f chore: Arabic translations 2025-07-30 04:23:23 +05:30
Jannat Patel 266b2f2ac8 chore: French translations 2025-07-30 04:23:21 +05:30
Jannat Patel 26f9fb4199 Merge pull request #1658 from frappe/pot_develop_2025-07-25
chore: update POT file
2025-07-29 12:05:37 +05:30
frappe-pr-bot 67887fb6ef chore: update POT file 2025-07-25 16:04:39 +00:00
Jannat Patel 3d102e39ff Merge pull request #1657 from pateljannat/course-card-gradient
feat: course card gradient
2025-07-25 18:56:50 +05:30
Jannat Patel ddd9089130 fix: color swatch input style 2025-07-25 18:31:46 +05:30
Jannat Patel d8ce88ab57 fix: color swatch input style 2025-07-25 18:30:58 +05:30
Jannat Patel 01794a47c6 feat: set a random color is no color or image is present 2025-07-25 17:46:50 +05:30
Jannat Patel 17626dbbdb feat: course card gradient 2025-07-25 17:29:48 +05:30
Jannat Patel e5bd86658d Merge pull request #1655 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-24 10:41:13 +05:30
Jannat Patel e911dc1353 chore: Thai translations 2025-07-24 02:45:56 +05:30
Jannat Patel 27e3e5aa6a chore: Indonesian translations 2025-07-24 02:45:53 +05:30
Jannat Patel 5b65525bf1 chore: Portuguese translations 2025-07-24 02:45:46 +05:30
Jannat Patel 277804f8b1 chore: Hungarian translations 2025-07-24 02:45:42 +05:30
Jannat Patel 4c77802e3c Merge pull request #1653 from pateljannat/issues-124
fix: progress timer in lessons
2025-07-23 11:32:51 +05:30
Jannat Patel aacfea6ea5 fix: progress timer in lessons 2025-07-23 11:31:41 +05:30
Frappe PR Bot 6d55040e43 chore(release): Bumped to Version 2.32.2 2025-07-23 05:31:05 +00:00
Jannat Patel 290f785a47 Merge pull request #1651 from pateljannat/issues-123
fix: vimeo video embed with plyr
2025-07-23 11:00:03 +05:30
Jannat Patel 39ef187f6b fix: vimeo video embed with plyr 2025-07-23 10:44:53 +05:30
Frappe PR Bot a7a475e763 chore(release): Bumped to Version 2.32.1 2025-07-22 13:31:38 +00:00
Jannat Patel 6eb380ea38 Merge pull request #1648 from pateljannat/issues-122
fix: play embed videos on Lesson Form
2025-07-22 14:20:42 +05:30
Jannat Patel 4d150cb323 fix: play embed videos on Lesson Form 2025-07-22 14:11:29 +05:30
Jannat Patel 09d6d99b14 Merge pull request #1647 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-22 10:24:07 +05:30
Jannat Patel 5e7fd8baff chore: Esperanto translations 2025-07-22 02:06:41 +05:30
Jannat Patel 52c159e2e8 chore: French translations 2025-07-22 02:06:40 +05:30
Jannat Patel 67e8feb879 chore: Serbian (Latin) translations 2025-07-22 02:06:38 +05:30
Jannat Patel a5b61d5244 chore: Bosnian translations 2025-07-22 02:06:37 +05:30
Jannat Patel decc3a16ed chore: Croatian translations 2025-07-22 02:06:35 +05:30
Jannat Patel 7f39e9f0cc chore: Thai translations 2025-07-22 02:06:34 +05:30
Jannat Patel 95afa1a6ad chore: Persian translations 2025-07-22 02:06:32 +05:30
Jannat Patel 0d0bb5f9e2 chore: Portuguese, Brazilian translations 2025-07-22 02:06:31 +05:30
Jannat Patel 3dd5ce5035 chore: Vietnamese translations 2025-07-22 02:06:29 +05:30
Jannat Patel 549e56d551 chore: Chinese Simplified translations 2025-07-22 02:06:28 +05:30
Jannat Patel 50b6215d1e chore: Turkish translations 2025-07-22 02:06:27 +05:30
Jannat Patel ff69bfdce7 chore: Swedish translations 2025-07-22 02:06:25 +05:30
Jannat Patel c04cc8ec0f chore: Serbian (Cyrillic) translations 2025-07-22 02:06:24 +05:30
Jannat Patel f324de2254 chore: Russian translations 2025-07-22 02:06:22 +05:30
Jannat Patel 40af4e6f34 chore: Portuguese translations 2025-07-22 02:06:21 +05:30
Jannat Patel 5d9b66b5cb chore: Polish translations 2025-07-22 02:06:20 +05:30
Jannat Patel d2a8277c13 chore: Dutch translations 2025-07-22 02:06:18 +05:30
Jannat Patel ada85fc0f3 chore: Italian translations 2025-07-22 02:06:17 +05:30
Jannat Patel 505345eff7 chore: Hungarian translations 2025-07-22 02:06:15 +05:30
Jannat Patel 2911ade880 chore: German translations 2025-07-22 02:06:14 +05:30
Jannat Patel 8980dc8f9c chore: Czech translations 2025-07-22 02:06:12 +05:30
Jannat Patel d94a1c47c0 chore: Arabic translations 2025-07-22 02:06:11 +05:30
Jannat Patel 99c3e5182d chore: Spanish translations 2025-07-22 02:06:09 +05:30
Jannat Patel 70e39fee40 Merge pull request #1646 from frappe/pot_develop_2025-07-18
chore: update POT file
2025-07-21 19:30:03 +05:30
frappe-pr-bot 26d6bec8a0 chore: update POT file 2025-07-18 16:05:11 +00:00
Jannat Patel c9ac1a1402 Merge pull request #1645 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-18 10:38:18 +05:30
Jannat Patel 6949c1092c chore: Persian translations 2025-07-18 01:39:51 +05:30
Jannat Patel aae8a54481 Merge pull request #1644 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-17 10:26:39 +05:30
Jannat Patel e1d93bf670 chore: Serbian (Latin) translations 2025-07-17 01:24:47 +05:30
Jannat Patel fea0533cb1 chore: Chinese Simplified translations 2025-07-17 01:24:40 +05:30
Jannat Patel 5cd991f02a chore: Swedish translations 2025-07-17 01:24:37 +05:30
Jannat Patel 50a8a605d5 chore: Serbian (Cyrillic) translations 2025-07-17 01:24:36 +05:30
Jannat Patel 9ce7d8f5d6 Merge pull request #1641 from pateljannat/issues-121
chore: upgraded frappe-ui
2025-07-15 15:39:48 +05:30
Jannat Patel eae2587e4c chore: upgraded frappe-ui 2025-07-15 15:08:32 +05:30
Jannat Patel 323097f201 Merge pull request #1639 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-15 09:44:54 +05:30
Jannat Patel 014499888a chore: Esperanto translations 2025-07-15 01:33:53 +05:30
Jannat Patel 5662de21ae chore: Serbian (Latin) translations 2025-07-15 01:33:52 +05:30
Jannat Patel 17c2eba455 chore: Bosnian translations 2025-07-15 01:33:50 +05:30
Jannat Patel 1f2c986e8f chore: Croatian translations 2025-07-15 01:33:49 +05:30
Jannat Patel 12040b5f6d chore: Thai translations 2025-07-15 01:33:47 +05:30
Jannat Patel 20a985848f chore: Portuguese, Brazilian translations 2025-07-15 01:33:46 +05:30
Jannat Patel c06c6169e5 chore: Vietnamese translations 2025-07-15 01:33:44 +05:30
Jannat Patel 917aeb79ef chore: Turkish translations 2025-07-15 01:33:43 +05:30
Jannat Patel c4f36a39fe chore: Swedish translations 2025-07-15 01:33:42 +05:30
Jannat Patel befedc30ad chore: Serbian (Cyrillic) translations 2025-07-15 01:33:40 +05:30
Jannat Patel d3bc67daa2 chore: Russian translations 2025-07-15 01:33:39 +05:30
Jannat Patel 5d7e211367 chore: Polish translations 2025-07-15 01:33:37 +05:30
Jannat Patel fa9daa01ec chore: Dutch translations 2025-07-15 01:33:36 +05:30
Jannat Patel 0ed9dc63b8 chore: Italian translations 2025-07-15 01:33:34 +05:30
Jannat Patel 5dd6b33eb2 chore: Hungarian translations 2025-07-15 01:33:33 +05:30
Jannat Patel 1210b823c7 chore: German translations 2025-07-15 01:33:32 +05:30
Jannat Patel 04240b4b3d chore: Czech translations 2025-07-15 01:33:30 +05:30
Jannat Patel 787f592a1a chore: Arabic translations 2025-07-15 01:33:29 +05:30
Jannat Patel e7363fbd40 chore: Spanish translations 2025-07-15 01:33:27 +05:30
Jannat Patel e2762825e5 chore: French translations 2025-07-15 01:33:25 +05:30
Jannat Patel bbbca70c71 chore: Chinese Simplified translations 2025-07-15 01:33:24 +05:30
Jannat Patel 8dde423866 chore: Persian translations 2025-07-15 01:33:23 +05:30
Jannat Patel fc4c1c2b7e chore: Portuguese translations 2025-07-15 01:33:21 +05:30
Jannat Patel bf02e2de3f Merge pull request #1637 from pateljannat/issues-120
fix: increase pageLength for evaluation schedule
2025-07-14 16:57:09 +05:30
Jannat Patel a26ba4dc6e fix: increase pageLength for evaluation schedule 2025-07-14 16:33:11 +05:30
Frappe PR Bot f187cc9314 chore(release): Bumped to Version 2.32.0 2025-07-14 06:37:43 +00:00
Jannat Patel c15c6374f9 Merge pull request #1635 from pateljannat/issues-119
fix: quiz progress issue
2025-07-14 11:51:51 +05:30
Jannat Patel acec382dfe fix: quiz progress issue 2025-07-14 11:40:55 +05:30
Jannat Patel fbc078c6b6 Merge pull request #1632 from frappe/pot_develop_2025-07-11
chore: update POT file
2025-07-14 09:37:09 +05:30
frappe-pr-bot 170b20185a chore: update POT file 2025-07-11 16:04:39 +00:00
Jannat Patel 3e8489c13b Merge pull request #1631 from pateljannat/issues-118
fix: misc issues
2025-07-11 11:14:36 +05:30
Jannat Patel 18dfc4c23e test: changed CTA labels 2025-07-11 11:06:29 +05:30
Jannat Patel e6bae3dc77 fix: changed CTA labels on lists to Create 2025-07-11 10:44:04 +05:30
Jannat Patel 6f9f27c030 fix: delete batch and pass fields prop to brand settings 2025-07-10 22:21:26 +05:30
Jannat Patel 874bef74c7 Merge pull request #1623 from JoeBrar/feature/reorder-chapters
feat: added chapter re-ordering functionality for courses
2025-07-10 12:20:04 +05:30
Jannat Patel ad483e0916 Merge pull request #1630 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-10 12:19:49 +05:30
Jannat Patel 5b4bbaec20 chore: Portuguese translations 2025-07-10 01:07:19 +05:30
Jannat Patel b8ae0db0bd Merge pull request #1627 from pateljannat/badge-management
feat: badge management from settings
2025-07-09 10:46:58 +05:30
Jannat Patel f2c18fad52 fix: misc improvements to badge flow 2025-07-08 19:41:08 +05:30
Jannat Patel 9716655b94 Merge pull request #1626 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-08 14:16:27 +05:30
Jannat Patel efb317191c feat: badge assignment from settings 2025-07-08 14:12:46 +05:30
Jannat Patel a47b5db40c chore: Serbian (Cyrillic) translations 2025-07-08 01:10:50 +05:30
Jannat Patel ec94796b9c chore: Italian translations 2025-07-08 01:10:48 +05:30
Jannat Patel e3e0cd61a2 chore: Vietnamese translations 2025-07-08 01:10:47 +05:30
Jannat Patel a438473279 chore: Dutch translations 2025-07-08 01:10:46 +05:30
Jannat Patel 12b5b8b509 chore: Czech translations 2025-07-08 01:10:44 +05:30
Jannat Patel 22442b47a8 chore: Esperanto translations 2025-07-08 01:10:43 +05:30
Jannat Patel 30c8b7d64f chore: Chinese Simplified translations 2025-07-08 01:10:41 +05:30
Jannat Patel b643575c4f chore: Serbian (Latin) translations 2025-07-08 01:10:40 +05:30
Jannat Patel 7dd7124fac chore: Bosnian translations 2025-07-08 01:10:38 +05:30
Jannat Patel 4b1eebf5bb chore: Croatian translations 2025-07-08 01:10:37 +05:30
Jannat Patel 3257943926 chore: Thai translations 2025-07-08 01:10:36 +05:30
Jannat Patel 24246c83e0 chore: Persian translations 2025-07-08 01:10:34 +05:30
Jannat Patel a26787f478 chore: Portuguese, Brazilian translations 2025-07-08 01:10:33 +05:30
Jannat Patel ec3b88f890 chore: Turkish translations 2025-07-08 01:10:31 +05:30
Jannat Patel 7f5f1dad92 chore: Swedish translations 2025-07-08 01:10:30 +05:30
Jannat Patel b6db128214 chore: Russian translations 2025-07-08 01:10:29 +05:30
Jannat Patel 8831635db2 chore: Portuguese translations 2025-07-08 01:10:28 +05:30
Jannat Patel e19198b720 chore: Polish translations 2025-07-08 01:10:26 +05:30
Jannat Patel f618d9dc1a chore: Hungarian translations 2025-07-08 01:10:25 +05:30
Jannat Patel 66a667a0a3 chore: German translations 2025-07-08 01:10:23 +05:30
Jannat Patel 8a4c67f712 chore: Arabic translations 2025-07-08 01:10:22 +05:30
Jannat Patel fa6ef2e989 chore: Spanish translations 2025-07-08 01:10:21 +05:30
Jannat Patel 7450b99197 chore: French translations 2025-07-08 01:10:19 +05:30
Jannat Patel 023fd272b1 feat: badge list and form 2025-07-07 16:44:48 +05:30
Jannat Patel 84067cb027 Merge pull request #1621 from JoeBrar/fix/image-upload
fix: Changed image extension validation to MIME type validation
2025-07-07 13:01:18 +05:30
Jannat Patel 3087ef70e7 Merge pull request #1619 from JoeBrar/fix/lms-issues
fix: ensure tags wrap correctly to prevent overflow and breaking of layout
2025-07-07 12:59:26 +05:30
Jannat Patel 387385bb1c Merge pull request #1624 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-07 11:13:27 +05:30
Jannat Patel 6766d0d08c Merge pull request #1622 from frappe/pot_develop_2025-07-04
chore: update POT file
2025-07-07 11:13:03 +05:30
Jannat Patel 371d890793 chore: Persian translations 2025-07-07 01:14:35 +05:30
Joedeep Singh 57046c1b38 feat: added chapter re-ordering functionality for courses 2025-07-06 17:02:27 +00:00
frappe-pr-bot 2a64144e94 chore: update POT file 2025-07-04 16:04:41 +00:00
Joedeep Singh 9b0320ccf1 chore: fixed the linter issues 2025-07-04 14:02:13 +00:00
Joedeep Singh 23f209131e Merge branch 'develop' into fix/image-upload 2025-07-04 18:57:03 +05:30
Joedeep Singh d71f1c7f9a refactor: updated the validateFile function in utils and reused it 2025-07-04 13:22:25 +00:00
Jannat Patel d21ea2c854 Merge pull request #1618 from pateljannat/member-list-refactor
fix: improved members and evaluators list and form
2025-07-04 12:33:44 +05:30
Jannat Patel cd7f3ba820 Merge pull request #1620 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-04 12:28:37 +05:30
Jannat Patel e057d3ed9a fix: improved evaluators list 2025-07-04 12:26:57 +05:30
Joedeep Singh 5f04607a44 fix: Changed image extension validation to MIME type validation 2025-07-03 20:41:23 +00:00
Jannat Patel 9440d13a08 chore: Serbian (Cyrillic) translations 2025-07-04 01:23:16 +05:30
Jannat Patel 85c4f1654e chore: Serbian (Latin) translations 2025-07-04 01:23:15 +05:30
Joedeep Singh eed339cc64 fix: ensure tags wrap correctly to prevent overflow and breaking of layout 2025-07-03 18:25:04 +00:00
Jannat Patel 3d1a23576a fix: repositioned the search bar on members list 2025-07-03 19:40:09 +05:30
Jannat Patel ed0e2e4bb5 fix: issue with roles on profile page 2025-07-03 19:26:07 +05:30
Jannat Patel 954d0a0637 fix: improved members list and form 2025-07-03 18:19:29 +05:30
Jannat Patel f2c8788602 Merge pull request #1613 from Grumbled0rf/patch-1
Update README.md
2025-07-03 13:21:33 +05:30
Jannat Patel 49c63da27c Merge pull request #1614 from mahsem/patch-state
fix: state_translatability
2025-07-03 13:21:06 +05:30
Jannat Patel 24496d1856 Merge pull request #1617 from pateljannat/course-progress-summary
feat: course progress summary report
2025-07-03 13:20:41 +05:30
Jannat Patel 991ebe09a2 chore: linters 2025-07-03 13:09:45 +05:30
Jannat Patel 85da4f6d85 feat: course progress summary report 2025-07-03 13:02:57 +05:30
Jannat Patel 5f065db991 Merge pull request #1616 from pateljannat/issues-117
fix: when logo is updated from brand settings, update the login logo too
2025-07-02 16:56:20 +05:30
Manoj Prabhkaran D ffb40586d7 Merge branch 'develop' into patch-1 2025-07-02 15:10:59 +04:00
Jannat Patel fcfd87fd50 fix: when logo is updated from brand settings, update the login logo too 2025-07-02 16:16:49 +05:30
Jannat Patel eb5b12aa7b Merge pull request #1615 from pateljannat/course-list-fetch
fix: page length issue on course list
2025-07-02 15:41:23 +05:30
Manoj Prabhkaran D f6e2438744 docs(readme): add DNS configuration note to avoid 404 error during self-hosting 2025-07-02 13:43:10 +04:00
Jannat Patel e3c7dc695d fix: page length issue on batch list 2025-07-02 15:01:33 +05:30
Jannat Patel 82d2025e6c fix: page length issue on course list 2025-07-02 15:00:53 +05:30
mahsem 91b82d78b8 fix: state _translatability 2025-07-02 11:03:33 +02:00
Jannat Patel b97e792893 Merge pull request #1609 from pateljannat/track-video-watch-duration
feat: video watch time tracking
2025-07-02 10:53:56 +05:30
Jannat Patel 13ac5ec7dc fix: sidebar settings for programming exercises 2025-07-02 10:47:03 +05:30
Jannat Patel 199f880936 Merge pull request #1612 from addeeandra/fix-sidebar-settings-programming-exercise
feat: sidebar settings to toggle "Programming Exercise" menu
2025-07-02 10:33:47 +05:30
Jannat Patel ed86c207ba Merge pull request #1610 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-07-01 19:18:51 +05:30
Jannat Patel b4cf290f4d fix: allow backward seek but prevent forward seek 2025-07-01 19:16:13 +05:30
Jannat Patel e526a6fd64 fix: moved sirebar settings to settings store 2025-07-01 17:38:15 +05:30
Jannat Patel 94cbbf169a feat: prevent skipping videos 2025-07-01 17:27:43 +05:30
Jannat Patel 2837ed16a7 feat: track watch time for youtube and vimeo 2025-07-01 16:55:55 +05:30
Aditya Chandra 68961deb6b revert: api.py 2025-07-01 12:52:52 +07:00
Aditya Chandra ec54bfee98 fix: programming exercise's sidebar settings 2025-07-01 12:39:50 +07:00
Jannat Patel 385e97b76a chore: Serbian (Cyrillic) translations 2025-07-01 00:39:53 +05:30
Jannat Patel cbd916877f chore: Italian translations 2025-07-01 00:39:51 +05:30
Jannat Patel 38586034cd chore: Vietnamese translations 2025-07-01 00:39:50 +05:30
Jannat Patel 62b3ba2bff chore: Dutch translations 2025-07-01 00:39:49 +05:30
Jannat Patel dd470b61b5 chore: Czech translations 2025-07-01 00:39:47 +05:30
Jannat Patel 4fa92d2327 chore: Esperanto translations 2025-07-01 00:39:46 +05:30
Jannat Patel 6f6c2db66d chore: Chinese Simplified translations 2025-07-01 00:39:44 +05:30
Jannat Patel e6348cfa20 chore: Serbian (Latin) translations 2025-07-01 00:39:43 +05:30
Jannat Patel a006d1000a chore: Bosnian translations 2025-07-01 00:39:42 +05:30
Jannat Patel 4a575e642f chore: Croatian translations 2025-07-01 00:39:40 +05:30
Jannat Patel 93525bc577 chore: Thai translations 2025-07-01 00:39:39 +05:30
Jannat Patel 2cf0e9a723 chore: Persian translations 2025-07-01 00:39:36 +05:30
Jannat Patel c32164bfea chore: Portuguese, Brazilian translations 2025-07-01 00:39:35 +05:30
Jannat Patel 714b0924e7 chore: Turkish translations 2025-07-01 00:39:34 +05:30
Jannat Patel 43079790a8 chore: Swedish translations 2025-07-01 00:39:33 +05:30
Jannat Patel d03e61b625 chore: Russian translations 2025-07-01 00:39:31 +05:30
Jannat Patel 2d760112a3 chore: Portuguese translations 2025-07-01 00:39:30 +05:30
Jannat Patel f46507ec72 chore: Polish translations 2025-07-01 00:39:28 +05:30
Jannat Patel e9e10bdc93 chore: Hungarian translations 2025-07-01 00:39:27 +05:30
Jannat Patel 0386967a32 chore: German translations 2025-07-01 00:39:25 +05:30
Jannat Patel 4900fc8b88 chore: Arabic translations 2025-07-01 00:39:24 +05:30
Jannat Patel 99294b5643 chore: Spanish translations 2025-07-01 00:39:22 +05:30
Jannat Patel eb12bcb83c chore: French translations 2025-07-01 00:39:21 +05:30
Jannat Patel 22a2e57642 fix: fetch stats when lesson is loaded 2025-06-30 20:00:13 +05:30
Jannat Patel 5eaae06ceb feat: video watch time tracking 2025-06-30 19:56:07 +05:30
Jannat Patel ce7fc35349 Merge pull request #1606 from pateljannat/sidebar-toggle-issue
chore: upgraded frappe ui
2025-06-30 11:57:06 +05:30
Jannat Patel 8d4b5c83ae chore: upgraded frappe ui 2025-06-30 11:49:22 +05:30
Jannat Patel cbd3c56ca0 Merge pull request #1605 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-30 11:42:20 +05:30
Jannat Patel be6dad1424 Merge pull request #1603 from frappe/pot_develop_2025-06-27
chore: update POT file
2025-06-30 11:42:07 +05:30
Jannat Patel 298452fa7b Merge pull request #1602 from pateljannat/negative-marking-in-quiz
feat: negative marking in quiz
2025-06-30 11:41:53 +05:30
Jannat Patel 4abbd7c35c chore: Bosnian translations 2025-06-30 00:27:08 +05:30
Jannat Patel c2f51c51ab chore: Croatian translations 2025-06-30 00:27:07 +05:30
Jannat Patel 255cff6664 chore: Turkish translations 2025-06-30 00:27:04 +05:30
Jannat Patel 8a9578bb0a chore: German translations 2025-06-30 00:26:59 +05:30
Jannat Patel 8831f6cecc chore: Arabic translations 2025-06-30 00:26:58 +05:30
Jannat Patel f3daa7e48b chore: Spanish translations 2025-06-30 00:26:56 +05:30
Jannat Patel 6163597958 chore: French translations 2025-06-30 00:26:55 +05:30
frappe-pr-bot f9e1222065 chore: update POT file 2025-06-27 16:04:48 +00:00
Jannat Patel 7d85de7c6c fix: set default marks to cut as 1 2025-06-27 20:00:57 +05:30
Jannat Patel cf452c2300 feat: negative marking in quiz 2025-06-27 19:58:35 +05:30
Jannat Patel 72bd1d548d Merge pull request #1600 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-27 16:51:01 +05:30
Jannat Patel 4556f4dee6 chore: Thai translations 2025-06-26 23:43:56 +05:30
Jannat Patel 3dfbd3165a chore: German translations 2025-06-26 23:43:54 +05:30
Jannat Patel 02b8e02131 Merge pull request #1599 from pateljannat/issues-116
fix: misc issues
2025-06-26 16:53:06 +05:30
Jannat Patel 087ded9f9e chore: removed console 2025-06-26 16:37:05 +05:30
Jannat Patel 21f122ee82 fix: misc issues 2025-06-26 16:35:03 +05:30
Jannat Patel d60a7e8c94 Merge pull request #1593 from pateljannat/programming-exercises
feat: programming exercises
2025-06-26 13:05:22 +05:30
Jannat Patel b8981c249f feat: livecode settings 2025-06-25 19:57:07 +05:30
Jannat Patel e71275a0dc feat: javascript exercises 2025-06-25 12:15:27 +05:30
Jannat Patel 4fb0db7a1e fix: test case with no input issue 2025-06-24 12:22:02 +05:30
Jannat Patel 1e9beedc77 Merge pull request #1591 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-24 09:50:23 +05:30
Jannat Patel 4a4a0653ef chore: Serbian (Cyrillic) translations 2025-06-23 22:25:04 +05:30
Jannat Patel c80a900277 chore: Serbian (Latin) translations 2025-06-23 22:25:02 +05:30
Jannat Patel 6fb0394d96 Merge pull request #1588 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-23 18:55:28 +05:30
Jannat Patel a6a7712039 chore: Serbian (Latin) translations 2025-06-22 22:14:14 +05:30
Jannat Patel dd0687ba29 chore: Serbian (Cyrillic) translations 2025-06-21 22:08:07 +05:30
Jannat Patel 9cb87a5333 chore: Italian translations 2025-06-21 22:08:06 +05:30
Jannat Patel 8ec93d84a0 chore: Vietnamese translations 2025-06-21 22:08:04 +05:30
Jannat Patel 1d38715db9 chore: Dutch translations 2025-06-21 22:08:03 +05:30
Jannat Patel 6225c4eb35 chore: Czech translations 2025-06-21 22:08:02 +05:30
Jannat Patel e58ce2fbe6 chore: Esperanto translations 2025-06-21 22:08:00 +05:30
Jannat Patel 8881d62e78 chore: Chinese Simplified translations 2025-06-21 22:07:59 +05:30
Jannat Patel effb2a1265 chore: Serbian (Latin) translations 2025-06-21 22:07:58 +05:30
Jannat Patel ab387473b5 chore: Bosnian translations 2025-06-21 22:07:56 +05:30
Jannat Patel 3cf6079b70 chore: Croatian translations 2025-06-21 22:07:55 +05:30
Jannat Patel 53c655bb53 chore: Thai translations 2025-06-21 22:07:54 +05:30
Jannat Patel 87952463c2 chore: Persian translations 2025-06-21 22:07:52 +05:30
Jannat Patel 3a8a63a49a chore: Portuguese, Brazilian translations 2025-06-21 22:07:51 +05:30
Jannat Patel debe115044 chore: Turkish translations 2025-06-21 22:07:50 +05:30
Jannat Patel 554d2808fd chore: Swedish translations 2025-06-21 22:07:49 +05:30
Jannat Patel 12b2c89a25 chore: Russian translations 2025-06-21 22:07:47 +05:30
Jannat Patel a66fc3a07e chore: Portuguese translations 2025-06-21 22:07:46 +05:30
Jannat Patel 7b3705cab0 chore: Polish translations 2025-06-21 22:07:45 +05:30
Jannat Patel 8e99e5f5e8 chore: Hungarian translations 2025-06-21 22:07:43 +05:30
Jannat Patel c5ba5370bb chore: German translations 2025-06-21 22:07:42 +05:30
Jannat Patel 464dec9810 chore: Arabic translations 2025-06-21 22:07:41 +05:30
Jannat Patel c2e2ec8803 chore: Spanish translations 2025-06-21 22:07:39 +05:30
Jannat Patel 37378e2360 chore: French translations 2025-06-21 22:07:38 +05:30
Jannat Patel 678385d90c Merge pull request #1586 from frappe/pot_develop_2025-06-20
chore: update POT file
2025-06-20 22:25:10 +05:30
frappe-pr-bot 4c461f087f chore: update POT file 2025-06-20 16:04:51 +00:00
Jannat Patel 88a2b69980 feat: exercise form and submission list 2025-06-20 19:59:10 +05:30
Jannat Patel 1f57792da7 Merge pull request #1582 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-19 22:30:20 +05:30
Jannat Patel 9bb4c45a23 feat: programming exercise submission 2025-06-19 14:47:52 +05:30
Jannat Patel 75fd19f491 chore: Serbian (Cyrillic) translations 2025-06-18 21:10:25 +05:30
Jannat Patel 0ac16bdeb7 chore: Italian translations 2025-06-18 21:10:23 +05:30
Jannat Patel 223ee41e10 Merge pull request #1578 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-18 12:15:27 +05:30
Jannat Patel c126ded82e feat: allow Jammu and Kashmir as state 2025-06-18 11:07:58 +05:30
Jannat Patel 0edf78b7fd feat: programming exercises 2025-06-18 11:06:44 +05:30
Jannat Patel 5af3580987 Merge pull request #1580 from pateljannat/lesson-editor-improvements
fix: lesson editor fixes
2025-06-17 17:04:14 +05:30
Jannat Patel 343cb6f97a fix: removed unused import 2025-06-17 16:46:36 +05:30
Jannat Patel 023c8ac13e fix: lesson editor fixes 2025-06-17 16:38:42 +05:30
Jannat Patel c385eed795 chore: Vietnamese translations 2025-06-16 20:59:31 +05:30
Jannat Patel ee5fdd789f chore: Dutch translations 2025-06-16 20:59:29 +05:30
Jannat Patel df1e400f4e chore: Czech translations 2025-06-16 20:59:28 +05:30
Jannat Patel 6c9c298478 chore: Esperanto translations 2025-06-16 20:59:27 +05:30
Jannat Patel 7106ee150d chore: Chinese Simplified translations 2025-06-16 20:59:26 +05:30
Jannat Patel 03e2287f80 chore: Serbian (Latin) translations 2025-06-16 20:59:24 +05:30
Jannat Patel 2edcd41e24 chore: Bosnian translations 2025-06-16 20:59:23 +05:30
Jannat Patel 0fe043bd99 chore: Croatian translations 2025-06-16 20:59:21 +05:30
Jannat Patel 6686f5240d chore: Thai translations 2025-06-16 20:59:20 +05:30
Jannat Patel 2936facf0f chore: Persian translations 2025-06-16 20:59:18 +05:30
Jannat Patel cc208f2c43 chore: Portuguese, Brazilian translations 2025-06-16 20:59:17 +05:30
Jannat Patel 9a0fc231e5 chore: Turkish translations 2025-06-16 20:59:16 +05:30
Jannat Patel bfc0ae62ec chore: Swedish translations 2025-06-16 20:59:14 +05:30
Jannat Patel 5e7d8d97f2 chore: Russian translations 2025-06-16 20:59:13 +05:30
Jannat Patel 70ceb16ed6 chore: Portuguese translations 2025-06-16 20:59:11 +05:30
Jannat Patel f162fa639f chore: Polish translations 2025-06-16 20:59:10 +05:30
Jannat Patel f000c72546 chore: Hungarian translations 2025-06-16 20:59:08 +05:30
Jannat Patel 32c01f931c chore: German translations 2025-06-16 20:59:07 +05:30
Jannat Patel d0121e2b9d chore: Arabic translations 2025-06-16 20:59:06 +05:30
Jannat Patel 1caab8ce1d chore: Spanish translations 2025-06-16 20:59:04 +05:30
Jannat Patel 878be435a1 chore: French translations 2025-06-16 20:59:02 +05:30
Frappe PR Bot 6a68ae989e chore(release): Bumped to Version 2.31.0 2025-06-16 11:49:38 +00:00
Jannat Patel 00993da781 Merge pull request #1577 from pateljannat/issues-115
fix: misc issues
2025-06-16 17:09:33 +05:30
Jannat Patel e9ef67e402 chore: regenerated yarn lock 2025-06-16 16:55:31 +05:30
Jannat Patel 83ebfececf feat: edit related courses from frontend 2025-06-16 15:13:30 +05:30
Jannat Patel ec8bf6251f Merge branch 'develop' of https://github.com/frappe/lms into issues-115 2025-06-16 13:07:26 +05:30
Jannat Patel 1b2874b3a5 Merge pull request #1565 from OsafAliSayed/related_courses
Feat: Related courses
2025-06-16 13:07:18 +05:30
Jannat Patel 0ac1053a71 Merge pull request #1575 from frappe/pot_develop_2025-06-13
chore: update POT file
2025-06-16 12:55:02 +05:30
Jannat Patel 224d270952 Merge pull request #1572 from harshpwctech/develop
feat: Embedding for Bunny Stream
2025-06-16 12:54:49 +05:30
Jannat Patel c6137545cd ci: verify yarn lock file 2025-06-16 12:53:53 +05:30
Jannat Patel 335417f9f4 fix: persona form role issue 2025-06-16 12:44:29 +05:30
Jannat Patel cb797223ed fix: time markers on video slider for quiz 2025-06-16 12:07:39 +05:30
Jannat Patel 3a2a0313ac fix: show an intermediate dialog informing users of the quiz if its in between video 2025-06-16 11:22:29 +05:30
Jannat Patel e221a5a73a Merge branch 'develop' of https://github.com/frappe/lms into issues-115 2025-06-16 10:47:47 +05:30
frappe-pr-bot 2b7aaf095f chore: update POT file 2025-06-13 16:04:26 +00:00
Jannat Patel 6f01e7b8d8 fix: job count 2025-06-13 20:33:51 +05:30
Jannat Patel d594419200 feat: show live class joining and leaving time in attendance list 2025-06-12 23:18:35 +05:30
Jannat Patel bf50e3f898 Merge pull request #1571 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-11 20:05:43 +05:30
safe user d434f1781f feat: Embedding for Bunny Stream 2025-06-11 06:53:26 +00:00
safe user 3f311a45ef feat: Embedding for Bunny Stream 2025-06-11 06:42:29 +00:00
Jannat Patel 9293b7796e chore: Serbian (Latin) translations 2025-06-11 03:33:13 +05:30
OsafAliSayed b1e7883526 fix(relatedCourses): remove loading component 2025-06-10 18:03:43 +00:00
Frappe PR Bot 7fcf6a253d chore(release): Bumped to Version 2.30.0 2025-06-10 10:24:40 +00:00
Jannat Patel be8d985d15 fix: removed duplicate import 2025-06-10 15:34:19 +05:30
Jannat Patel 974c90dddc Merge branch 'main' into develop 2025-06-10 15:29:39 +05:30
Jannat Patel 4811d395d2 Merge pull request #1568 from pateljannat/issues-114
fix: misc evaluation issues
2025-06-10 11:06:45 +05:30
Jannat Patel 132423d577 Merge pull request #1567 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-10 10:58:22 +05:30
Jannat Patel 10829e2f00 fix: misc evaluation issues 2025-06-10 10:58:03 +05:30
Jannat Patel 47b908c964 chore: Esperanto translations 2025-06-10 03:35:55 +05:30
Jannat Patel 0f8e471d5d chore: Chinese Simplified translations 2025-06-10 03:35:54 +05:30
Jannat Patel 2537119250 chore: Serbian (Latin) translations 2025-06-10 03:35:52 +05:30
Jannat Patel 977066d114 chore: Bosnian translations 2025-06-10 03:35:51 +05:30
Jannat Patel 46e956dc74 chore: Croatian translations 2025-06-10 03:35:50 +05:30
Jannat Patel 7afdd8d44f chore: Thai translations 2025-06-10 03:35:48 +05:30
Jannat Patel 6daf204b4f chore: Persian translations 2025-06-10 03:35:47 +05:30
Jannat Patel 2f4a550a4a chore: Portuguese, Brazilian translations 2025-06-10 03:35:46 +05:30
Jannat Patel fe214f6b41 chore: Turkish translations 2025-06-10 03:35:44 +05:30
Jannat Patel ca7de81888 chore: Swedish translations 2025-06-10 03:35:43 +05:30
Jannat Patel 17ce20355a chore: Russian translations 2025-06-10 03:35:42 +05:30
Jannat Patel 34981b4765 chore: Portuguese translations 2025-06-10 03:35:41 +05:30
Jannat Patel 21151a2e09 chore: Polish translations 2025-06-10 03:35:39 +05:30
Jannat Patel 1abb7f5b8c chore: Hungarian translations 2025-06-10 03:35:38 +05:30
Jannat Patel 05998549a4 chore: German translations 2025-06-10 03:35:37 +05:30
Jannat Patel 96283a3629 chore: Arabic translations 2025-06-10 03:35:35 +05:30
Jannat Patel 2bfc7abe9c chore: Spanish translations 2025-06-10 03:35:34 +05:30
Jannat Patel 4f389eca8d chore: French translations 2025-06-10 03:35:33 +05:30
Jannat Patel 1789479955 Merge pull request #1564 from frappe/pot_develop_2025-06-06
chore: update POT file
2025-06-09 19:44:09 +05:30
OsafAliSayed 212800155b style(linter): apply linting fixes 2025-06-09 06:13:21 +00:00
OsafAliSayed c241bf2104 feat(related-courses): add related courses component 2025-06-09 06:13:21 +00:00
OsafAliSayed bda61f32f3 feat(related-courses): add related courses frontend 2025-06-09 06:11:40 +00:00
frappe-pr-bot 59316dbaf9 chore: update POT file 2025-06-06 16:04:34 +00:00
Jannat Patel b726073a5b Merge pull request #1562 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-06 10:52:56 +05:30
Jannat Patel adf897c812 chore: French translations 2025-06-06 03:03:37 +05:30
Jannat Patel 1fc4c2442c Merge pull request #1561 from pateljannat/evaluator-link-in-batch
fix batch instructor should be linked to evaluator
2025-06-05 15:06:46 +05:30
Jannat Patel 414643ee90 test: link evaluator as batch instructor 2025-06-05 14:46:09 +05:30
Jannat Patel 1a1cbd6ea1 fix: batch instructor should be linked to evaluator 2025-06-05 12:58:12 +05:30
Jannat Patel 9ae809a62f Merge pull request #1559 from pateljannat/issues-113
fix: dont allow enrollment is self learning is disabled from api
2025-06-05 12:53:42 +05:30
Jannat Patel eb9b1c905d Merge pull request #1558 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-05 10:46:03 +05:30
Jannat Patel fe9a8f49c1 fix: dont allow enrollment is self learning is disabled from api 2025-06-05 10:43:25 +05:30
Jannat Patel f912c8fce3 chore: French translations 2025-06-05 02:22:54 +05:30
Jannat Patel 1d1ca43c35 chore: Serbian (Latin) translations 2025-06-04 01:58:16 +05:30
Jannat Patel bce45f44e4 Merge pull request #1557 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-03 13:23:54 +05:30
Jannat Patel 07583fb563 fix: show error in toast when scheduling evaluations 2025-06-03 12:47:57 +05:30
Jannat Patel 775aa23992 chore: Esperanto translations 2025-06-03 02:00:23 +05:30
Jannat Patel 05ed6b7e73 chore: Chinese Simplified translations 2025-06-03 02:00:22 +05:30
Jannat Patel d602694ea7 chore: Serbian (Latin) translations 2025-06-03 02:00:20 +05:30
Jannat Patel 18d71bc0d4 chore: Bosnian translations 2025-06-03 02:00:19 +05:30
Jannat Patel 3fa68643ba chore: Croatian translations 2025-06-03 02:00:18 +05:30
Jannat Patel 8904525c36 chore: Thai translations 2025-06-03 02:00:16 +05:30
Jannat Patel 3ce09a98f3 chore: Persian translations 2025-06-03 02:00:15 +05:30
Jannat Patel b833768e71 chore: Portuguese, Brazilian translations 2025-06-03 02:00:14 +05:30
Jannat Patel b9a6afd993 chore: Turkish translations 2025-06-03 02:00:12 +05:30
Jannat Patel b5a81ea927 chore: Swedish translations 2025-06-03 02:00:11 +05:30
Jannat Patel 750e92cdde chore: Russian translations 2025-06-03 02:00:09 +05:30
Jannat Patel da45f4c011 chore: Portuguese translations 2025-06-03 02:00:08 +05:30
Jannat Patel 544bb5c11c chore: Polish translations 2025-06-03 02:00:07 +05:30
Jannat Patel 1fc6f62f70 chore: Hungarian translations 2025-06-03 02:00:05 +05:30
Jannat Patel 8751ad27ec chore: German translations 2025-06-03 02:00:04 +05:30
Jannat Patel 159d3d5b87 chore: Arabic translations 2025-06-03 02:00:03 +05:30
Jannat Patel 34d6d99d8c chore: Spanish translations 2025-06-03 02:00:01 +05:30
Jannat Patel 6c46931b1a chore: French translations 2025-06-03 02:00:00 +05:30
Jannat Patel 2c3e2d9d08 Merge pull request #1554 from pateljannat/quiz-in-video
feat: show quiz in between videos
2025-06-02 19:35:55 +05:30
Jannat Patel 7be1562fa4 fix: simplified timestamp label 2025-06-02 19:18:27 +05:30
Jannat Patel 294389e7c7 Merge branch 'develop' of https://github.com/frappe/lms into quiz-in-video 2025-06-02 19:16:27 +05:30
Jannat Patel 2c8ce133f7 fix: quiz and time validation before linking to video 2025-06-02 19:12:13 +05:30
Ankush Menat 4f1d4d90d0 fix: remove invasive configs (#1555) 2025-06-02 19:04:55 +05:30
Jannat Patel 7b7484332b feat: quiz in videos 2025-06-02 18:18:13 +05:30
Jannat Patel 50e94b85aa chore: resolved conflicts 2025-06-02 12:24:16 +05:30
Jannat Patel 9b820594ef Merge pull request #1553 from pateljannat/batch-test
test: batch creation flow
2025-06-02 12:22:58 +05:30
Jannat Patel ddcd45d56d test: don't add course to batch 2025-06-02 12:15:34 +05:30
Jannat Patel c4a4c16516 test: batch creation flow 2025-06-02 10:48:54 +05:30
Jannat Patel 5ae9ad0762 Merge pull request #1552 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-06-02 10:38:49 +05:30
Jannat Patel 405f7d498e Merge pull request #1548 from frappe/pot_develop_2025-05-30
chore: update POT file
2025-06-02 10:38:39 +05:30
Jannat Patel bcd6a5b1e7 chore: Persian translations 2025-06-02 01:08:03 +05:30
Jannat Patel e5e5ac994c Merge pull request #1550 from pateljannat/issues-112
fix: misc issues
2025-05-31 12:49:16 +05:30
Jannat Patel e1f8d6ec49 fix: count of jobs and certified members 2025-05-31 12:41:58 +05:30
Jannat Patel 6f50242f5a fix: misc issues 2025-05-31 11:52:25 +05:30
frappe-pr-bot 036f7ece05 chore: update POT file 2025-05-30 16:04:24 +00:00
Jannat Patel 622a2ff072 feat: display quiz when time is reached 2025-05-30 18:55:26 +05:30
Jannat Patel 60334ca04a feat: show quiz in between videos 2025-05-30 13:00:00 +05:30
Jannat Patel ade47b4e83 Merge pull request #1547 from pateljannat/seo-in-forms
feat: seo tags and keywords for courses and batches
2025-05-30 10:19:29 +05:30
Jannat Patel d7e550dfea feat: seo tags and keywords for courses and batches 2025-05-29 20:13:35 +05:30
Jannat Patel c3cc0b9bf7 Merge pull request #1546 from pateljannat/issues-111
fix: misc issues
2025-05-29 16:29:57 +05:30
Jannat Patel 5ad89189c1 fix: changed certified members count based on filters 2025-05-29 16:09:51 +05:30
Jannat Patel f1bbd4eb13 fix: settings ui cleanup 2025-05-29 16:09:14 +05:30
Jannat Patel fba89dfacb feat: show unpushlished courses to admins on frontend 2025-05-29 12:50:25 +05:30
Jannat Patel b93ed41215 fix: course and chapter permissions to moderators 2025-05-29 12:49:30 +05:30
Jannat Patel 13ff6a7304 chore: record sessions while creating courses and lessons 2025-05-29 12:48:58 +05:30
Jannat Patel ad97405e55 Merge pull request #1544 from Rl0007/fix/edit-profile-escape-html
fix: Edit profile escape html
2025-05-28 20:20:53 +05:30
Rahul Agrawal 376e231d7b chore: remove unwanted line profile.bio = profile.bio 2025-05-28 16:00:14 +05:30
Rahul Agrawal e16d76f6dd fix: remove escapeHtml from edit profile bio on save 2025-05-28 15:44:54 +05:30
Jannat Patel ffd0fd92fc Merge pull request #1542 from pateljannat/zoom-refactor
feat: multiple zoom accounts and zoom attendance
2025-05-28 12:06:21 +05:30
Jannat Patel 933613d730 fix: jobs list header issue 2025-05-28 11:22:03 +05:30
Jannat Patel 9b0673bf92 feat: zoom attendance 2025-05-27 23:01:04 +05:30
Jannat Patel 7cba22aa28 Merge pull request #1539 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-27 12:02:06 +05:30
Jannat Patel af05b614a9 feat: delete zoom accounts from settings 2025-05-27 11:40:22 +05:30
Jannat Patel c0fa219a8b chore: Esperanto translations 2025-05-26 23:41:15 +05:30
Jannat Patel 4e3a47b0f4 chore: Chinese Simplified translations 2025-05-26 23:41:14 +05:30
Jannat Patel 161276b58a chore: Serbian (Latin) translations 2025-05-26 23:41:13 +05:30
Jannat Patel 47713019a5 chore: Bosnian translations 2025-05-26 23:41:11 +05:30
Jannat Patel 010632a21d chore: Croatian translations 2025-05-26 23:41:10 +05:30
Jannat Patel e77fe550af chore: Thai translations 2025-05-26 23:41:09 +05:30
Jannat Patel 0a4233da14 chore: Persian translations 2025-05-26 23:41:08 +05:30
Jannat Patel 56fb70ab1e chore: Portuguese, Brazilian translations 2025-05-26 23:41:06 +05:30
Jannat Patel 4a1f2bc01d chore: Turkish translations 2025-05-26 23:41:05 +05:30
Jannat Patel 20292fbf16 chore: Swedish translations 2025-05-26 23:41:04 +05:30
Jannat Patel 1290cf8991 chore: Russian translations 2025-05-26 23:41:02 +05:30
Jannat Patel b8b8af7cf1 chore: Portuguese translations 2025-05-26 23:41:01 +05:30
Jannat Patel 75f4f452d3 chore: Polish translations 2025-05-26 23:41:00 +05:30
Jannat Patel 9de492384f chore: Hungarian translations 2025-05-26 23:40:58 +05:30
Jannat Patel 14c4e161f2 chore: German translations 2025-05-26 23:40:57 +05:30
Jannat Patel c55efbc0ba chore: Arabic translations 2025-05-26 23:40:56 +05:30
Jannat Patel f0610222d9 chore: Spanish translations 2025-05-26 23:40:55 +05:30
Jannat Patel 302ee4a50f chore: French translations 2025-05-26 23:40:53 +05:30
Jannat Patel 2170819159 chore: telemetry fixes 2025-05-26 22:02:46 +05:30
Jannat Patel 0d1fac321a feat: zoom settings on frontend 2025-05-26 21:35:13 +05:30
Jannat Patel dbbc1756dd Merge branch 'develop' of https://github.com/frappe/lms into zoom-refactor 2025-05-26 21:27:18 +05:30
Jannat Patel d5b882d3f8 feat: multiple zoom accounts 2025-05-26 18:08:17 +05:30
Frappe PR Bot 3025ea9a7b chore(release): Bumped to Version 2.29.0 2025-05-26 10:05:36 +00:00
Jannat Patel 5dba4d1384 Merge pull request #1537 from frappe/develop
chore: merge 'develop' into 'main'
2025-05-26 15:33:03 +05:30
Jannat Patel e4f1e7b093 Merge pull request #1536 from pateljannat/telemetry-fixes
chore: fix posthog init condition
2025-05-26 15:21:34 +05:30
Jannat Patel d0a0597087 chore: removed unused imports 2025-05-26 15:08:41 +05:30
Jannat Patel c9ccf9a1b5 chore: fix posthog init condition 2025-05-26 15:02:51 +05:30
Jannat Patel 69107d4441 Merge pull request #1535 from pateljannat/refactor-batch-charts
refactor: use frappe-ui for batch progress charts
2025-05-26 12:43:15 +05:30
Jannat Patel e25afc1ef7 chore: fixed formating 2025-05-26 12:32:34 +05:30
Jannat Patel 9babfd150e fix: course count on batch dashboard 2025-05-26 12:25:16 +05:30
Jannat Patel 532dbbea4a fix: restricted minimum chart interval to 1 2025-05-26 11:34:52 +05:30
Jannat Patel 0d284d05d9 Merge pull request #1534 from pateljannat/issues-110
fix: misc issues
2025-05-26 11:22:16 +05:30
Jannat Patel 28fccae3ac Merge pull request #1532 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-26 11:05:01 +05:30
Jannat Patel 3a4a6da69c Merge pull request #1531 from frappe/pot_develop_2025-05-23
chore: update POT file
2025-05-26 11:04:50 +05:30
Jannat Patel 4ea07a95e7 fix: show batch CTA's on mobile 2025-05-26 11:04:00 +05:30
Jannat Patel 80ceb49358 fix: login menu now works on all browsers and devices 2025-05-26 10:58:17 +05:30
Jannat Patel 589337116a fix: added dependencies for onboarding steps 2025-05-26 09:59:05 +05:30
Jannat Patel cb50067223 chore: Chinese Simplified translations 2025-05-24 23:16:12 +05:30
Jannat Patel 4d63266d88 chore: Serbian (Latin) translations 2025-05-24 23:16:11 +05:30
Jannat Patel 90dd33ce21 chore: Serbian (Latin) translations 2025-05-23 23:13:03 +05:30
frappe-pr-bot 763b849ddf chore: update POT file 2025-05-23 16:04:27 +00:00
Jannat Patel 9c76c54283 Merge pull request #1528 from pateljannat/email-template-list
feat: email template in settings
2025-05-23 15:35:11 +05:30
Md Hussain Nagaria 5cb17b3a36 Merge pull request #1529 from frappe/misc-fixes 2025-05-23 11:01:25 +02:00
Hussain Nagaria 2f7b5d1cbb fix: use unavailabilityMessage if set 2025-05-23 14:28:47 +05:30
Hussain Nagaria 4fe14eb2e9 fix: early return cleanup 2025-05-23 14:26:22 +05:30
Jannat Patel eb089f2b58 fix: return payment fields data after transform 2025-05-23 14:25:29 +05:30
Hussain Nagaria 4f0ac98eea fix: toast used but not imported 2025-05-23 14:02:04 +05:30
Hussain Nagaria af19940fa1 fix: some code semantics 2025-05-23 14:00:11 +05:30
Jannat Patel 5635d2a325 feat: email template update and deletion 2025-05-23 13:28:18 +05:30
Jannat Patel 5e2de35693 refactor: layout of payment fields 2025-05-22 21:39:49 +05:30
Jannat Patel ef7180f23f Merge pull request #1523 from pateljannat/issues-109
refactor: misc enhancements
2025-05-22 12:12:57 +05:30
Jannat Patel f939973d4f fix: don't validate number of students if seat count is 0 in batch 2025-05-22 12:03:07 +05:30
Jannat Patel 63f327733e refactor: category list in settings 2025-05-22 11:54:54 +05:30
Jannat Patel c1fb807fe4 fix: show onboarding banner when redirected from other pages 2025-05-21 17:52:24 +05:30
Jannat Patel b7ddf44267 test: close onboaring popover before creating course 2025-05-21 17:35:48 +05:30
Jannat Patel 6d4c72ea5e fix: rating input style on course details page 2025-05-21 16:28:04 +05:30
Jannat Patel 3db11b9372 refactor: moved batch feedback to sidebar 2025-05-21 16:08:49 +05:30
Jannat Patel b8714f4abe refactor: batch progress chart will now use frappe-ui components 2025-05-21 13:13:42 +05:30
Jannat Patel 7ccbe74bbe chore: fixed conflicts 2025-05-20 19:09:19 +05:30
Jannat Patel ea3ae3516b Merge pull request #1513 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-20 19:05:38 +05:30
Jannat Patel d33af3ca52 chore: Esperanto translations 2025-05-19 21:33:54 +05:30
Jannat Patel 291c3fa908 chore: Serbian (Latin) translations 2025-05-19 21:33:53 +05:30
Jannat Patel a51fa58122 chore: Bosnian translations 2025-05-19 21:33:52 +05:30
Jannat Patel 65a3967abd chore: Croatian translations 2025-05-19 21:33:50 +05:30
Jannat Patel e1e5c94a43 chore: Thai translations 2025-05-19 21:33:49 +05:30
Jannat Patel f15127eceb chore: Chinese Simplified translations 2025-05-19 21:33:47 +05:30
Jannat Patel 071a238b71 chore: Persian translations 2025-05-19 21:33:46 +05:30
Jannat Patel 050b052156 chore: Portuguese, Brazilian translations 2025-05-19 21:33:44 +05:30
Jannat Patel 8f65cca776 chore: Turkish translations 2025-05-19 21:33:43 +05:30
Jannat Patel 66624a8c47 chore: Swedish translations 2025-05-19 21:33:41 +05:30
Jannat Patel c8b9a415e6 chore: Russian translations 2025-05-19 21:33:40 +05:30
Jannat Patel a1dcb4c203 chore: Portuguese translations 2025-05-19 21:33:39 +05:30
Jannat Patel d4edc3e622 chore: Polish translations 2025-05-19 21:33:37 +05:30
Jannat Patel e2b8c3ee0e chore: Hungarian translations 2025-05-19 21:33:35 +05:30
Jannat Patel c37816e90d chore: German translations 2025-05-19 21:33:34 +05:30
Jannat Patel a35cfcdca7 chore: Arabic translations 2025-05-19 21:33:32 +05:30
Jannat Patel d381646226 chore: Spanish translations 2025-05-19 21:33:31 +05:30
Jannat Patel 285e7afec2 chore: French translations 2025-05-19 21:33:30 +05:30
Jannat Patel df7d678c32 Merge pull request #1510 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-19 14:24:21 +05:30
Jannat Patel f36f7e58de Merge pull request #1511 from frappe/pot_develop_2025-05-16
chore: update POT file
2025-05-19 14:24:10 +05:30
Jannat Patel 0e16c834d8 chore: Serbian (Latin) translations 2025-05-18 21:37:27 +05:30
frappe-pr-bot 31a3256128 chore: update POT file 2025-05-16 16:04:20 +00:00
Jannat Patel aa8f70da28 chore: Swedish translations 2025-05-16 21:09:45 +05:30
Frappe PR Bot f375ffb8f8 chore(release): Bumped to Version 2.28.1 2025-05-16 06:36:08 +00:00
Jannat Patel de240e40a5 Merge pull request #1507 from frappe/develop
chore: merge 'develop' into 'main'
2025-05-16 12:01:07 +05:30
Jannat Patel 7d30aea07f Merge pull request #1509 from pateljannat/issues-108
fix: misc issues
2025-05-16 11:55:31 +05:30
Jannat Patel 04a7361d0d fix: verify if score_out_of is not 0 before calculating percentage 2025-05-16 11:40:03 +05:30
Jannat Patel 7b19618eca fix: basic cleanup of quiz submission form 2025-05-16 11:25:43 +05:30
Jannat Patel bd9600cc08 fix: list index error on quiz submission 2025-05-16 11:07:47 +05:30
Jannat Patel 32172bc791 chore: fixed redis issue faced during docker setup 2025-05-16 09:53:45 +05:30
Jannat Patel c92f57fb07 Merge pull request #1508 from pateljannat/issues-107
fix: ask for role in persona form
2025-05-15 21:51:05 +05:30
Jannat Patel 8fbdea7f36 fix: ask for role in persona form 2025-05-15 19:57:43 +05:30
Jannat Patel df15da5145 Merge branch 'develop' of https://github.com/frappe/lms into develop 2025-05-15 09:40:09 +05:30
Jannat Patel 846fe53c0f fix: show persona form after course count has been fetched 2025-05-15 09:38:22 +05:30
Jannat Patel 3bbdc828d9 Merge pull request #1506 from frappe/develop
chore: merge 'develop' into 'main'
2025-05-14 17:48:42 +05:30
Jannat Patel c454c3f0f2 Merge pull request #1505 from pateljannat/issues-106
fix: plyr will now work on all videos of a lesson
2025-05-14 17:33:14 +05:30
Jannat Patel 77b1a546e8 fix: plyr will now work on all videos of a lesson 2025-05-14 17:12:20 +05:30
Jannat Patel 7c7f063204 Merge pull request #1502 from pateljannat/issues-105
fix: misc fixes
2025-05-14 14:10:16 +05:30
Jannat Patel 0a0fcb305c fix: settings modal size 2025-05-14 13:19:03 +05:30
Jannat Patel da8028784d chore: changed cypress config to esm 2025-05-14 11:52:48 +05:30
Jannat Patel 48edd888a6 chore: changed file to esm 2025-05-14 11:30:11 +05:30
Jannat Patel da4f134095 fix: misc ui issues 2025-05-13 20:04:39 +05:30
Jannat Patel 0a71620046 fix: misc ui issues 2025-05-13 20:04:06 +05:30
Jannat Patel 1b5a762578 Merge pull request #1500 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-13 14:10:58 +05:30
Jannat Patel d9d031ed2b refactor: new toast api 2025-05-13 14:08:04 +05:30
Jannat Patel 403e56b4ef fix: misc batch issues 2025-05-13 11:46:00 +05:30
Jannat Patel 499b06e300 chore: Esperanto translations 2025-05-12 20:56:10 +05:30
Jannat Patel cb69540bdd chore: Chinese Simplified translations 2025-05-12 20:56:08 +05:30
Jannat Patel 1f27fa419a chore: Serbian (Latin) translations 2025-05-12 20:56:06 +05:30
Jannat Patel a561b2bd91 chore: Bosnian translations 2025-05-12 20:56:05 +05:30
Jannat Patel eeec85d1de chore: Croatian translations 2025-05-12 20:56:04 +05:30
Jannat Patel e01484f854 chore: Thai translations 2025-05-12 20:56:02 +05:30
Jannat Patel fb996ded88 chore: Persian translations 2025-05-12 20:56:01 +05:30
Jannat Patel a11bfca15a chore: Portuguese, Brazilian translations 2025-05-12 20:55:59 +05:30
Jannat Patel 6262e1c9e6 chore: Turkish translations 2025-05-12 20:55:57 +05:30
Jannat Patel 4e318af7cc chore: Swedish translations 2025-05-12 20:55:55 +05:30
Jannat Patel d587b7867e chore: Russian translations 2025-05-12 20:55:54 +05:30
Jannat Patel bd03ead9c3 chore: Portuguese translations 2025-05-12 20:55:53 +05:30
Jannat Patel c1685b7128 chore: Polish translations 2025-05-12 20:55:51 +05:30
Jannat Patel 7625e79574 chore: Hungarian translations 2025-05-12 20:55:50 +05:30
Jannat Patel c5bf7875b9 chore: German translations 2025-05-12 20:55:48 +05:30
Jannat Patel da026293bc chore: Arabic translations 2025-05-12 20:55:46 +05:30
Jannat Patel 86e5677574 chore: Spanish translations 2025-05-12 20:55:45 +05:30
Jannat Patel a48636604f chore: French translations 2025-05-12 20:55:43 +05:30
Jannat Patel e6945ac076 fix: all empty states now come from a common component 2025-05-12 17:46:23 +05:30
Jannat Patel 9107d76522 fix: batch form cleanup 2025-05-12 15:04:35 +05:30
Jannat Patel 52b925b306 fix: course form cleanup 2025-05-12 13:07:06 +05:30
Jannat Patel 49d3dc0aa0 Merge pull request #1498 from frappe/pot_develop_2025-05-09
chore: update POT file
2025-05-12 10:53:20 +05:30
Jannat Patel 0d41a1ae70 refactor: use frappe-ui for batch progress charts 2025-05-12 10:37:26 +05:30
frappe-pr-bot 49e22d790a chore: update POT file 2025-05-09 16:04:15 +00:00
Jannat Patel 12e5eedd6b Merge pull request #1494 from pateljannat/issues-104
fix: misc issues
2025-05-08 16:01:14 +05:30
Jannat Patel 159b651871 fix: dark mode for upcoming evaluations 2025-05-08 15:29:04 +05:30
Jannat Patel 080be7a885 fix: tooltips for number cards on statistics page 2025-05-08 15:10:51 +05:30
Jannat Patel e526627eb9 fix: only show published certificate on the statistics page 2025-05-08 15:05:07 +05:30
Jannat Patel 67fc37c76c fix: ui of job details 2025-05-08 14:53:34 +05:30
Jannat Patel b2b92aea31 chore: merged upstream 2025-05-07 22:04:53 +05:30
Jannat Patel e0680d9612 chore: merged upstream 2025-05-07 22:03:57 +05:30
Jannat Patel d54ac37403 Merge pull request #1491 from pateljannat/issues-103
fix: only assign lms roles to admin
2025-05-07 21:49:38 +05:30
Jannat Patel eedb3d3dd8 fix: only assign lms roles to admin 2025-05-07 21:40:43 +05:30
Frappe PR Bot 015aff9c4b chore(release): Bumped to Version 2.28.0 2025-05-07 07:48:16 +00:00
Jannat Patel d286df649e Merge pull request #1490 from frappe/develop
chore: merge 'develop' into 'main'
2025-05-07 12:56:56 +05:30
Jannat Patel 567bfc41e0 Merge pull request #1489 from pateljannat/issues-102
fix: misc fixes
2025-05-07 12:51:11 +05:30
Jannat Patel 90d77e9ffb fix: improved question form for quiz 2025-05-07 12:34:38 +05:30
Jannat Patel 2b33ba1984 fix: dark mode issues 2025-05-07 11:50:34 +05:30
Jannat Patel 1918f0c5d5 Merge branch 'develop' of https://github.com/frappe/lms into issues-102 2025-05-07 11:50:07 +05:30
Jannat Patel 91d79de723 fix: submission list access from assignment form 2025-05-06 20:02:34 +05:30
Jannat Patel 62b05f2377 fix: route to course from the course card widget 2025-05-06 19:25:53 +05:30
Jannat Patel b628ec4c57 Merge pull request #1488 from pateljannat/simplify-persona-form
chore: simplified the persona form
2025-05-06 19:23:28 +05:30
Jannat Patel 494394f084 Merge pull request #1487 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-06 19:15:24 +05:30
Jannat Patel e99b4b183c chore: simplified the persona form 2025-05-06 19:14:41 +05:30
Jannat Patel 9186353654 chore: Esperanto translations 2025-05-06 18:24:57 +05:30
Jannat Patel bd2a7b9095 chore: Chinese Simplified translations 2025-05-06 18:24:55 +05:30
Jannat Patel 42b70e7a94 chore: Serbian (Latin) translations 2025-05-06 18:24:54 +05:30
Jannat Patel 7f913203a1 chore: Bosnian translations 2025-05-06 18:24:53 +05:30
Jannat Patel 9b94958840 chore: Croatian translations 2025-05-06 18:24:51 +05:30
Jannat Patel 2070e93379 chore: Thai translations 2025-05-06 18:24:50 +05:30
Jannat Patel 772f4d938f chore: Persian translations 2025-05-06 18:24:48 +05:30
Jannat Patel 531f3af203 chore: Portuguese, Brazilian translations 2025-05-06 18:24:47 +05:30
Jannat Patel ed522341c1 chore: Turkish translations 2025-05-06 18:24:46 +05:30
Jannat Patel ee59c5068e chore: Swedish translations 2025-05-06 18:24:44 +05:30
Jannat Patel ebe3abd05b chore: Russian translations 2025-05-06 18:24:43 +05:30
Jannat Patel 358dd4dddc chore: Portuguese translations 2025-05-06 18:24:41 +05:30
Jannat Patel 3d924d3631 chore: Polish translations 2025-05-06 18:24:40 +05:30
Jannat Patel 0bed316a40 chore: Hungarian translations 2025-05-06 18:24:39 +05:30
Jannat Patel 24b5937793 chore: German translations 2025-05-06 18:24:37 +05:30
Jannat Patel c5b5876700 chore: Arabic translations 2025-05-06 18:24:36 +05:30
Jannat Patel 0f969e952d chore: Spanish translations 2025-05-06 18:24:34 +05:30
Jannat Patel 43ba512fd5 chore: French translations 2025-05-06 18:24:33 +05:30
Jannat Patel e0cbc247b2 Merge pull request #1485 from pateljannat/release-conflicts
chore: merge to 'main'
2025-05-06 13:10:08 +05:30
Jannat Patel a2c8a82559 chore: merged conflicts 2025-05-06 12:59:22 +05:30
Jannat Patel 8aadbffe8c Merge pull request #1483 from pateljannat/issues-101
fix: misc fixes
2025-05-06 10:49:47 +05:30
Jannat Patel be7e7bc6fd refactor: extracted function that enables plyr as a utility 2025-05-06 10:35:05 +05:30
Jannat Patel 3a10d4bdc0 fix: alignment of information on batch details 2025-05-06 10:17:07 +05:30
Jannat Patel fc03ecd1b3 fix: made programs breadcrumb translatable 2025-05-06 09:27:48 +05:30
Jannat Patel c7b10f0e83 Merge pull request #1482 from frappe/pot_develop_2025-05-02
chore: update POT file
2025-05-06 08:50:56 +05:30
Jannat Patel 6a94ce5e1c Merge pull request #1480 from pateljannat/evaluator-list-issue
fix: evaluator list in settings
2025-05-06 08:50:44 +05:30
frappe-pr-bot 59859a8e2f chore: update POT file 2025-05-02 16:04:11 +00:00
Jannat Patel f51a8aae39 fix: evaluator list in settings 2025-05-02 15:03:54 +05:30
Jannat Patel bd5b8c5e0e Merge pull request #1478 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-05-02 15:02:35 +05:30
Jannat Patel 67e7744566 Merge pull request #1479 from pateljannat/read-only
feat: read only mode
2025-04-30 18:33:22 +05:30
Jannat Patel 65a6663c31 fix: when moving between lessons in zen mode, ensure discussions remain hidden 2025-04-30 18:19:45 +05:30
Jannat Patel 603e80fd26 feat: read only mode 2025-04-30 18:03:00 +05:30
Jannat Patel de4ee6bbe6 chore: Persian translations 2025-04-30 15:28:31 +05:30
Jannat Patel a8aa242280 chore: Portuguese, Brazilian translations 2025-04-30 15:28:30 +05:30
Jannat Patel 0d32c2a9d9 Merge branch 'develop' of https://github.com/frappe/lms into read-only 2025-04-29 18:40:42 +05:30
Jannat Patel 6d5a02e2a8 feat: read only mode 2025-04-29 18:39:22 +05:30
Jannat Patel 67f3cbaaa8 Merge pull request #1475 from pateljannat/issues-100
fix: hide start learning button if self enrollment is disabled
2025-04-29 16:23:51 +05:30
Jannat Patel f17504e1a0 fix: hide start learning button if self enrollment is disabled 2025-04-29 15:51:03 +05:30
Jannat Patel b1a9af5de8 Merge pull request #1474 from pateljannat/issues-99
fix: check parenttype when fetching instructors
2025-04-29 11:27:56 +05:30
Jannat Patel 913bf553ae refactor: simplified the condition to check is user is instructor 2025-04-29 11:03:58 +05:30
Jannat Patel 356dcc42bf fix: check parenttype when fetching instructors 2025-04-29 10:48:52 +05:30
Jannat Patel 8c006f24ce Merge pull request #1465 from nextchamp-saqib/refactor-charts
refactor: use charts from `frappe-ui`
2025-04-28 18:19:16 +05:30
Jannat Patel 6f2f0092f0 refactor: dynamic data for statistics charts 2025-04-28 18:05:43 +05:30
Jannat Patel 56afc4c614 Merge pull request #1471 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-28 15:34:43 +05:30
Jannat Patel 0a3b9f8f9a chore: Esperanto translations 2025-04-28 14:01:56 +05:30
Jannat Patel 9b0623f4a4 chore: Bosnian translations 2025-04-28 14:01:55 +05:30
Jannat Patel c13ef17a86 chore: Croatian translations 2025-04-28 14:01:54 +05:30
Jannat Patel d5ac2f521f chore: Thai translations 2025-04-28 14:01:52 +05:30
Jannat Patel 037af18114 chore: Persian translations 2025-04-28 14:01:51 +05:30
Jannat Patel 92299458f5 chore: Portuguese, Brazilian translations 2025-04-28 14:01:49 +05:30
Jannat Patel 3272f2a4cf chore: Turkish translations 2025-04-28 14:01:48 +05:30
Jannat Patel 6a6dfdd82c chore: Swedish translations 2025-04-28 14:01:46 +05:30
Jannat Patel fa27452983 chore: Russian translations 2025-04-28 14:01:45 +05:30
Jannat Patel 8df5ec41d5 chore: Portuguese translations 2025-04-28 14:01:43 +05:30
Jannat Patel 55aad3a742 chore: Polish translations 2025-04-28 14:01:42 +05:30
Jannat Patel e46890d87e chore: Hungarian translations 2025-04-28 14:01:41 +05:30
Jannat Patel 3a36e10fce chore: German translations 2025-04-28 14:01:39 +05:30
Jannat Patel cc30c6d271 chore: Arabic translations 2025-04-28 14:01:38 +05:30
Jannat Patel 5e75ff7fb7 chore: Spanish translations 2025-04-28 14:01:36 +05:30
Jannat Patel 80681a1f8b chore: French translations 2025-04-28 14:01:34 +05:30
Jannat Patel 5954e10155 chore: Serbian (Latin) translations 2025-04-28 14:01:32 +05:30
Jannat Patel 78c43b7a10 chore: Chinese Simplified translations 2025-04-28 14:01:31 +05:30
Jannat Patel 8c6f8bf97b Merge pull request #1470 from pateljannat/issues-98
fix: don't allow billing page access if batch has started
2025-04-28 12:38:13 +05:30
Jannat Patel f220438257 fix: remove borders for iframe on lesson form 2025-04-28 11:16:04 +05:30
Jannat Patel bbd06752d3 Merge pull request #1468 from frappe/pot_develop_2025-04-25
chore: update POT file
2025-04-28 10:36:31 +05:30
Jannat Patel e34df2ce95 fix: don't allow billing page access if batch has started 2025-04-28 10:35:14 +05:30
frappe-pr-bot b197c08716 chore: update POT file 2025-04-25 16:04:29 +00:00
Jannat Patel aeb6c0f433 Merge branch 'develop' of https://github.com/frappe/lms into refactor-charts 2025-04-25 18:27:50 +05:30
Jannat Patel 8f32767267 Merge pull request #1461 from frappe/zen-mode
feat: Zen Mode
2025-04-25 18:21:31 +05:30
Jannat Patel afd43b9a9a Merge branch 'develop' of https://github.com/frappe/lms into zen-mode 2025-04-25 17:49:13 +05:30
Jannat Patel 5893e02c48 fix: reduced the size of play button in video block 2025-04-25 17:49:07 +05:30
Jannat Patel 66d3325e3c Merge pull request #1467 from harshpwctech/develop
feat: Embedding for CloudflareStream
2025-04-25 17:29:35 +05:30
Jannat Patel e513993a0d feat: show and hide discussions in zen mode 2025-04-25 17:28:54 +05:30
safe user ddbdf42265 feat: Embedding Cloudflare Stream 2025-04-25 09:28:44 +00:00
safe user badaa33ddb feat: Embedding for CloudflareStream 2025-04-25 08:38:00 +00:00
safe user befa3d7a6d feat: Added embedding for CloudflareStream 2025-04-25 08:38:00 +00:00
Jannat Patel 513f1e8b86 fix: improved lesson locked state 2025-04-25 08:38:00 +00:00
Jannat Patel 4128f0fb73 chore: fixed settings 2025-04-25 08:38:00 +00:00
Jannat Patel 3d81a63410 ci: skip persona form for ui tests 2025-04-25 08:38:00 +00:00
Jannat Patel c0ba44cacc fix: check persona_captured after details get saved 2025-04-25 08:38:00 +00:00
Jannat Patel deba027457 chore: identify user persona 2025-04-25 08:38:00 +00:00
Jannat Patel 47089d286e chore: Serbian (Latin) translations 2025-04-25 08:38:00 +00:00
Jannat Patel 6c50292a66 fix: tags spacing on course cards 2025-04-25 08:38:00 +00:00
Jannat Patel 1f23f06926 fix: allow fullscreen on vimeo and adjust video height on mobile devices 2025-04-25 08:38:00 +00:00
Jannat Patel 63319d32e8 fix: detect editor change to enable plyr on newly added videos 2025-04-25 11:18:19 +05:30
Jannat Patel 66f28ef7a6 Merge branch 'develop' of https://github.com/frappe/lms into zen-mode 2025-04-25 10:20:38 +05:30
Jannat Patel 4e4eccd909 Merge pull request #1466 from pateljannat/issues-97
fix: country details in job page and form
2025-04-25 10:19:32 +05:30
Jannat Patel c21fe99368 fix: country details in job page and form 2025-04-25 10:13:17 +05:30
Jannat Patel 53ea91e945 feat: plyr for vimeo 2025-04-25 10:05:32 +05:30
Jannat Patel 7cde05b58a Merge branch 'develop' of https://github.com/frappe/lms into zen-mode 2025-04-24 18:42:44 +05:30
Jannat Patel 0fc9b35307 Merge pull request #1464 from pateljannat/issues-96
feat: redesigned job list
2025-04-24 18:35:20 +05:30
Jannat Patel 4a36826af0 fix: if student applied for a job show that on the details page 2025-04-24 18:28:06 +05:30
Jannat Patel 26a278c5f4 feat: country filter in job list 2025-04-24 18:22:00 +05:30
Saqib Ansari 66a4d79730 refactor: use charts from frappe-ui 2025-04-24 16:19:12 +05:30
Jannat Patel 097d541391 feat: redesigned job list 2025-04-24 14:20:51 +05:30
Jannat Patel 788ef9b106 Merge pull request #1463 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-24 14:12:16 +05:30
Jannat Patel a38e1163af chore: Chinese Simplified translations 2025-04-24 13:37:52 +05:30
Jannat Patel a633ff5174 fix: check if youtube or vimeo video exists before enabling plyr 2025-04-24 12:06:57 +05:30
Jannat Patel 6b412106de feat: redesigned video block 2025-04-23 17:06:29 +05:30
Jannat Patel 93b5cb6161 feat: zen mode 2025-04-23 11:44:39 +05:30
Jannat Patel 4b80fbe5eb Merge pull request #1460 from pateljannat/issues-95
fix: improved lesson locked state
2025-04-22 18:13:01 +05:30
Jannat Patel 52775aae60 fix: improved lesson locked state 2025-04-22 18:05:07 +05:30
Jannat Patel 0430178b3e Merge pull request #1459 from pateljannat/user-persona
chore: identify user persona
2025-04-22 17:47:20 +05:30
Jannat Patel 470123c77a chore: fixed settings 2025-04-22 16:17:29 +05:30
Jannat Patel 66d4798db3 Merge branch 'develop' of https://github.com/frappe/lms into user-persona 2025-04-22 15:54:55 +05:30
Jannat Patel cc39395a12 Merge pull request #1458 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-22 15:54:42 +05:30
Jannat Patel 3aeb9cf0b1 ci: skip persona form for ui tests 2025-04-22 15:32:01 +05:30
Jannat Patel f1b383f0b7 fix: check persona_captured after details get saved 2025-04-22 15:02:21 +05:30
Jannat Patel e2896b7bf0 chore: Serbian (Latin) translations 2025-04-22 12:52:49 +05:30
Jannat Patel 780dfb8966 Merge branch 'develop' of https://github.com/frappe/lms into user-persona 2025-04-21 18:07:12 +05:30
Jannat Patel 8b91323705 Merge pull request #1457 from pateljannat/vimeo
fix: allow fullscreen on vimeo
2025-04-21 17:32:12 +05:30
Jannat Patel 89fdbf5660 test: find the course image label and attach course image to its sibling input 2025-04-21 17:10:33 +05:30
Jannat Patel ac47ab3f8a Merge pull request #1456 from pateljannat/issues-94
fix: allow fullscreen on vimeo and adjust video height on mobile devices
2025-04-21 16:36:06 +05:30
Jannat Patel 7ed5dfdb8f fix: allow fullscreen on video and adjust video height on mobile devices 2025-04-21 16:34:34 +05:30
Jannat Patel bfc1488860 fix: tags spacing on course cards 2025-04-21 16:16:54 +05:30
Jannat Patel 726f733434 fix: allow fullscreen on vimeo and adjust video height on mobile devices 2025-04-21 15:41:51 +05:30
Jannat Patel 0c97e31101 Merge pull request #1455 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-21 15:07:47 +05:30
Jannat Patel ec2b0718e6 chore: Portuguese translations 2025-04-21 12:09:04 +05:30
Jannat Patel 720056268c chore: Serbian (Latin) translations 2025-04-21 12:09:03 +05:30
Jannat Patel 345992eda4 chore: Esperanto translations 2025-04-21 12:09:02 +05:30
Jannat Patel e3e6b35eb7 chore: Croatian translations 2025-04-21 12:09:00 +05:30
Jannat Patel 701ea950de chore: Thai translations 2025-04-21 12:08:59 +05:30
Jannat Patel 4b78865823 chore: Portuguese, Brazilian translations 2025-04-21 12:08:58 +05:30
Jannat Patel 5b2bdf4cf6 chore: Bosnian translations 2025-04-21 12:08:57 +05:30
Jannat Patel a677b7fd3a chore: Persian translations 2025-04-21 12:08:55 +05:30
Jannat Patel 9cbd3db022 chore: Chinese Simplified translations 2025-04-21 12:08:54 +05:30
Jannat Patel 5f52d2c2c7 chore: Turkish translations 2025-04-21 12:08:53 +05:30
Jannat Patel b8c403aa5d chore: Swedish translations 2025-04-21 12:08:52 +05:30
Jannat Patel 2c6863e18e chore: Russian translations 2025-04-21 12:08:50 +05:30
Jannat Patel e7a462c685 chore: Polish translations 2025-04-21 12:08:49 +05:30
Jannat Patel 0cf671ae3b chore: Hungarian translations 2025-04-21 12:08:48 +05:30
Jannat Patel dfc6f5bfb4 chore: German translations 2025-04-21 12:08:47 +05:30
Jannat Patel 64b9be7e42 chore: Arabic translations 2025-04-21 12:08:45 +05:30
Jannat Patel 7412a8761c chore: Spanish translations 2025-04-21 12:08:44 +05:30
Jannat Patel 65cdeabc77 chore: French translations 2025-04-21 12:08:42 +05:30
Jannat Patel a507d4464d Merge pull request #1454 from pateljannat/issues-93
feat: meta image and keywords from settings
2025-04-21 11:05:39 +05:30
Jannat Patel 9143cc39d9 test: find the course image label and attach course image to its sibling input 2025-04-21 10:53:22 +05:30
Jannat Patel e821755721 test: attach course image if selector is hidden 2025-04-21 10:33:24 +05:30
Jannat Patel d081688fc9 Merge pull request #1453 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-21 10:16:30 +05:30
Jannat Patel cdc7ee698c Merge pull request #1452 from frappe/pot_develop_2025-04-18
chore: update POT file
2025-04-21 09:55:00 +05:30
Jannat Patel 0d0a9c872c chore: Chinese Simplified translations 2025-04-20 11:58:27 +05:30
Jannat Patel 30953cce66 chore: German translations 2025-04-20 11:58:22 +05:30
Jannat Patel f6008cf46a fix: don't show course count on batch details if there are no courses 2025-04-19 12:46:31 +05:30
Jannat Patel eb0587f726 feat: meta image and keywords from settings 2025-04-19 12:37:24 +05:30
frappe-pr-bot ba56ac87c5 chore: update POT file 2025-04-18 16:04:27 +00:00
Jannat Patel 5800ac67c4 chore: identify user persona 2025-04-18 18:05:57 +05:30
Jannat Patel 73941a159a Merge pull request #1451 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-18 16:16:35 +05:30
Jannat Patel d1fe8b203a chore: Thai translations 2025-04-18 11:52:30 +05:30
Jannat Patel 8b8dbc1053 chore: Chinese Simplified translations 2025-04-18 11:52:28 +05:30
Jannat Patel 57e477b17c Merge pull request #1450 from pateljannat/issues-92
fix: moved powered by learning to the bottom of sidebar
2025-04-17 22:41:59 +05:30
Jannat Patel 1a1924de3e fix: removed styles on attachments as they were overriding the styles on webform 2025-04-17 22:32:25 +05:30
Jannat Patel 3bea19c8ad fix: moved powered by learning to the bottom of sidebar 2025-04-17 22:31:47 +05:30
Jannat Patel cd47b62765 Merge pull request #1449 from pateljannat/assignment-issues
refactor: enhanced assignment form
2025-04-17 22:09:01 +05:30
Jannat Patel ffeaad324e fix: removed assignment submission email notification 2025-04-17 22:03:07 +05:30
Jannat Patel 4504dd810d fix: make assignment modal scrollable if the questions is very long 2025-04-17 21:52:55 +05:30
Jannat Patel 60ad86f79c refactor: enhanced assignment form 2025-04-17 21:42:43 +05:30
Jannat Patel f63294699a Merge pull request #1446 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-17 17:37:12 +05:30
Jannat Patel 650594d9ea Merge pull request #1447 from pateljannat/certification-redesign
fix: improved UI of certified participants page
2025-04-17 12:48:27 +05:30
Jannat Patel 7c22d5c774 chore: changed release workflow to run on the 15th of every month 2025-04-17 12:38:24 +05:30
Jannat Patel 73a501908d fix: mobile view for certified members page 2025-04-17 12:34:38 +05:30
Jannat Patel 31836e5c9e chore: Persian translations 2025-04-17 11:49:28 +05:30
Jannat Patel 31adab94b3 chore: merged conflicts 2025-04-16 21:38:00 +05:30
Jannat Patel 824c65eb38 Merge pull request #1440 from frappe/develop
chore: merge 'develop' into 'main'
2025-04-16 18:55:21 +05:30
Jannat Patel 4e02044eb4 Merge pull request #1441 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-16 18:47:37 +05:30
Jannat Patel f245cf2c5d fix: meta title for pages that don't have a default title 2025-04-16 17:09:09 +05:30
Jannat Patel 1b49cc1408 fix: meta title for pages that don't have a title 2025-04-16 17:02:52 +05:30
Jannat Patel bd384a9b59 chore: Portuguese translations 2025-04-16 11:50:58 +05:30
Jannat Patel 48eb2ff405 fix: registration button should be visible if batch starts today but a few hours are left 2025-04-16 11:18:17 +05:30
Jannat Patel dcacda984f fix: mobile view for certified member list 2025-04-16 10:59:06 +05:30
Jannat Patel 8186e9e1d2 Merge pull request #1438 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-15 20:14:15 +05:30
Jannat Patel b5b93917d1 chore: Croatian translations 2025-04-15 11:50:27 +05:30
Jannat Patel 1ffdadbde3 chore: Bosnian translations 2025-04-15 11:50:25 +05:30
Jannat Patel 4506603ea1 chore: Swedish translations 2025-04-15 11:50:23 +05:30
Jannat Patel fdf8b85f88 Merge branch 'develop' of https://github.com/frappe/lms into certification-redesign 2025-04-14 22:50:47 +05:30
Jannat Patel 340264ce41 Merge pull request #1436 from pateljannat/issues-91
fix: misc issues
2025-04-14 22:49:25 +05:30
Jannat Patel d6187b3d63 fix: corrected grammar in payments app error message 2025-04-14 22:39:07 +05:30
Jannat Patel b6577133a9 fix: misc issues 2025-04-14 22:28:06 +05:30
Jannat Patel 2d410eac37 Merge pull request #1430 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-14 16:24:43 +05:30
Jannat Patel e63e71f2bf chore: Portuguese translations 2025-04-14 11:31:24 +05:30
Jannat Patel ba743e0480 chore: Serbian (Latin) translations 2025-04-14 11:31:23 +05:30
Jannat Patel 2f26b15524 chore: Esperanto translations 2025-04-14 11:31:21 +05:30
Jannat Patel 5841ed0e70 chore: Croatian translations 2025-04-14 11:31:20 +05:30
Jannat Patel d217dff4b9 chore: Thai translations 2025-04-14 11:31:18 +05:30
Jannat Patel 2746606db1 chore: Portuguese, Brazilian translations 2025-04-14 11:31:17 +05:30
Jannat Patel 2d321780d0 chore: Bosnian translations 2025-04-14 11:31:16 +05:30
Jannat Patel c26108586f chore: Persian translations 2025-04-14 11:31:14 +05:30
Jannat Patel 7f30d9c3dc chore: Chinese Simplified translations 2025-04-14 11:31:12 +05:30
Jannat Patel 816b40bdc6 chore: Turkish translations 2025-04-14 11:31:11 +05:30
Jannat Patel 09688315cb chore: Swedish translations 2025-04-14 11:31:10 +05:30
Jannat Patel c709535442 chore: Russian translations 2025-04-14 11:31:08 +05:30
Jannat Patel 08e2d804fa chore: Polish translations 2025-04-14 11:31:07 +05:30
Jannat Patel b4fb07b435 chore: Hungarian translations 2025-04-14 11:31:06 +05:30
Jannat Patel d119ae6409 chore: German translations 2025-04-14 11:31:04 +05:30
Jannat Patel cf26fc4530 chore: Arabic translations 2025-04-14 11:31:03 +05:30
Jannat Patel f50a7704c9 chore: Spanish translations 2025-04-14 11:31:02 +05:30
Jannat Patel facec8393c chore: French translations 2025-04-14 11:31:00 +05:30
Jannat Patel 172e8872ef Merge pull request #1428 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-14 10:57:06 +05:30
Jannat Patel b7755b844a Merge pull request #1427 from frappe/pot_develop_2025-04-11
chore: update POT file
2025-04-14 10:56:54 +05:30
Jannat Patel 7e77d29edb chore: Portuguese translations 2025-04-13 11:08:49 +05:30
Jannat Patel 3b84ef6968 fix: seo description for job openings 2025-04-13 10:26:59 +05:30
Jannat Patel 2dd8192dcb feat: list of certified participants 2025-04-13 10:14:00 +05:30
Jannat Patel cafb499a79 chore: Portuguese translations 2025-04-12 10:51:50 +05:30
Jannat Patel f952267396 chore: Arabic translations 2025-04-12 10:51:38 +05:30
frappe-pr-bot 6913b71c69 chore: update POT file 2025-04-11 16:04:23 +00:00
Jannat Patel c485b03b83 chore: merged conflicts 2025-04-11 19:01:46 +05:30
Jannat Patel e1f35c86db fix: empty meta info issue 2025-04-11 18:43:34 +05:30
Jannat Patel cfbe60b731 fix: improved UI of certified participants page 2025-04-11 18:36:12 +05:30
Jannat Patel a21020e226 Merge pull request #1425 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-11 13:21:11 +05:30
Jannat Patel 28d18102f0 chore: Serbian (Latin) translations 2025-04-11 10:37:08 +05:30
Jannat Patel f5e78b7fdb chore: Persian translations 2025-04-11 10:37:04 +05:30
Jannat Patel d420b2dae5 chore: Turkish translations 2025-04-11 10:37:01 +05:30
Jannat Patel 3cce9107d0 chore: Polish translations 2025-04-11 10:36:59 +05:30
Jannat Patel a5248eb92b chore: Hungarian translations 2025-04-11 10:36:57 +05:30
Jannat Patel 1acf734229 chore: German translations 2025-04-11 10:36:56 +05:30
Jannat Patel cc170ecb20 chore: French translations 2025-04-11 10:36:53 +05:30
Jannat Patel b7f40d16a4 Merge pull request #1424 from pateljannat/seo-description
feat: SEO Meta Description
2025-04-10 17:42:58 +05:30
Jannat Patel 7e6cb727bd feat: seo description field 2025-04-10 17:19:38 +05:30
Jannat Patel eeaa835bef fix: redirect to course list from course from if user is not moderator and instructor 2025-04-10 16:36:22 +05:30
Frappe PR Bot 04aff8d149 chore(release): Bumped to Version 2.27.0 2025-04-10 10:38:37 +00:00
Jannat Patel e43eeeba4a Merge pull request #1423 from frappe/develop
chore: merge 'develop' into 'main'
2025-04-10 16:01:54 +05:30
Jannat Patel e88bdd818d Merge pull request #1422 from pateljannat/issues-89
fix: don't update onboarding status if user is not system manager
2025-04-10 15:55:32 +05:30
Jannat Patel 1a5d8ce07e fix: don't update onboarding status if user is not system manager 2025-04-10 15:37:59 +05:30
Jannat Patel 9e2c7cc145 Merge pull request #1417 from frappe/develop
chore: merge 'develop' into 'main'
2025-04-09 15:17:25 +05:30
Jannat Patel 8e405bc8eb Merge pull request #1416 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-09 15:01:24 +05:30
Jannat Patel 23e2a153c9 chore: German translations 2025-04-09 10:03:41 +05:30
Jannat Patel 85a0949488 Merge pull request #1415 from pateljannat/jobs-improvements
fix: new ui for job list
2025-04-08 22:53:30 +05:30
Jannat Patel 57b6433dc0 fix: new ui for job list 2025-04-08 22:39:42 +05:30
Jannat Patel 1b43e1be44 fix: added back csrf_token 2025-04-08 21:33:52 +05:30
Jannat Patel d6738b86c9 Merge pull request #1414 from pateljannat/seo-improvements
fix: seo improvements
2025-04-08 21:09:54 +05:30
Jannat Patel a5325cef44 chore: renamed lint jobs 2025-04-08 21:03:30 +05:30
Jannat Patel cc917f3d83 chore: bumped up pre commit action version to 3.0. 2025-04-08 21:00:50 +05:30
Jannat Patel 492917ea40 chore: added commit lint rules 2025-04-08 20:53:44 +05:30
Jannat Patel 78263185a1 chore: cached pip for linters 2025-04-08 20:31:42 +05:30
Jannat Patel ee7aa9d58b feat: fetch meta tags from website route meta 2025-04-08 19:37:16 +05:30
Jannat Patel a7112937de fix: changed course and batch meta description 2025-04-08 18:21:28 +05:30
Jannat Patel a8d4572aef fix: add app_name as document title 2025-04-08 18:12:21 +05:30
Jannat Patel 45c530e53a Merge pull request #1413 from pateljannat/improve-page-meta
fix: persistent favicon for all pages
2025-04-08 11:52:23 +05:30
Jannat Patel e0bcce5e6e fix: show learning logo as favicon if its missing in website settings 2025-04-08 11:45:51 +05:30
Jannat Patel 8346ec8525 fix: import usePageMeta for QuizSubmission 2025-04-08 11:13:46 +05:30
Jannat Patel 5d1673bad8 fix: persistent favicon for all pages 2025-04-08 10:57:02 +05:30
Jannat Patel a33328e11d Merge pull request #1412 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-08 10:27:35 +05:30
Jannat Patel 3efa326684 chore: Esperanto translations 2025-04-08 09:28:34 +05:30
Jannat Patel 196fead1e0 chore: Croatian translations 2025-04-08 09:28:33 +05:30
Jannat Patel b8ce04e9fe chore: Thai translations 2025-04-08 09:28:31 +05:30
Jannat Patel 6369dfd65c chore: Portuguese, Brazilian translations 2025-04-08 09:28:30 +05:30
Jannat Patel f4da56adf9 chore: Bosnian translations 2025-04-08 09:28:29 +05:30
Jannat Patel 0987a91bfc chore: Persian translations 2025-04-08 09:28:27 +05:30
Jannat Patel 9f23a56cf4 chore: Chinese Simplified translations 2025-04-08 09:28:26 +05:30
Jannat Patel 34a4754767 chore: Turkish translations 2025-04-08 09:28:25 +05:30
Jannat Patel b88de74552 chore: Swedish translations 2025-04-08 09:28:24 +05:30
Jannat Patel 45ac682c7f chore: Russian translations 2025-04-08 09:28:22 +05:30
Jannat Patel b753d366bf chore: Polish translations 2025-04-08 09:28:21 +05:30
Jannat Patel 06c598886e chore: Hungarian translations 2025-04-08 09:28:20 +05:30
Jannat Patel 52b0b7f8dc chore: German translations 2025-04-08 09:28:18 +05:30
Jannat Patel 656b3b2ebe chore: Arabic translations 2025-04-08 09:28:17 +05:30
Jannat Patel 6bdfbde23f chore: Spanish translations 2025-04-08 09:28:16 +05:30
Jannat Patel 1b9f5eebc0 chore: French translations 2025-04-08 09:28:15 +05:30
Jannat Patel 1f37da08b4 Merge pull request #1411 from pateljannat/disable-signup-settings
feat: signups can now be enabled/disabled from portal settings
2025-04-07 18:22:57 +05:30
Jannat Patel 5bc44e6fe5 feat: signups can now be enabled/disabled from portal settings 2025-04-07 18:15:30 +05:30
Jannat Patel c70da08078 Merge pull request #1410 from pateljannat/quiz-issue
fix: save lesson details in quiz
2025-04-07 15:19:15 +05:30
Jannat Patel 7600fb14e1 Merge pull request #1409 from frappe/pot_develop_2025-04-04
chore: update POT file
2025-04-07 15:10:55 +05:30
Jannat Patel e2fdf2042e Merge pull request #1406 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-04-07 15:10:38 +05:30
Jannat Patel 8477d6b9ed fix: save lesson details in quiz 2025-04-07 15:09:31 +05:30
Jannat Patel 241df63334 chore: Persian translations 2025-04-07 09:31:08 +05:30
Jannat Patel 7131de8a2a chore: Persian translations 2025-04-06 09:34:34 +05:30
frappe-pr-bot 473a799f58 chore: update POT file 2025-04-04 16:04:26 +00:00
Jannat Patel 6c9fe85170 chore: Portuguese, Brazilian translations 2025-04-01 09:07:24 +05:30
Jannat Patel 2c5d2db340 chore: Chinese Simplified translations 2025-03-29 08:33:34 +05:30
Jannat Patel 6cd2e6e7fb Merge pull request #1403 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-28 10:11:02 +05:30
Jannat Patel a6b094cff9 chore: Chinese Simplified translations 2025-03-28 08:29:45 +05:30
Jannat Patel 989598b9cd Merge pull request #1398 from frappe/develop
chore: merge 'develop' into 'main'
2025-03-27 09:44:00 +05:30
Jannat Patel b024a4546c Merge pull request #1401 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-27 09:42:07 +05:30
Jannat Patel 519715f8ee chore: Chinese Simplified translations 2025-03-27 08:19:36 +05:30
Jannat Patel 522de390a7 Merge pull request #1399 from pateljannat/onboarding-ui
feat: onboarding
2025-03-26 22:45:52 +05:30
Jannat Patel 2ffe19cea1 chore: removed frappe-ui from workspaces 2025-03-26 22:36:13 +05:30
Jannat Patel 124dc10cc3 chore: fixed linters 2025-03-26 22:15:47 +05:30
Jannat Patel a41338c3a2 fix: onboarding step improvements 2025-03-26 22:13:08 +05:30
Jannat Patel aa979b96f2 feat: onboarding 2025-03-26 13:08:06 +05:30
Jannat Patel f9b2471b32 Merge pull request #1397 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-25 13:55:56 +05:30
Jannat Patel d594f3ac88 chore: Chinese Simplified translations 2025-03-25 07:52:09 +05:30
Jannat Patel e5190d4409 Merge pull request #1394 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-24 15:13:10 +05:30
Jannat Patel 4f876c2bbc Merge pull request #1396 from pateljannat/assignment-in-course-issue
fix: assignment and quiz rendering issue in courses
2025-03-24 15:10:19 +05:30
Jannat Patel 4d031ae55e fix: dark mode issues for assignment 2025-03-24 14:57:46 +05:30
Jannat Patel 89a348b154 fix: assignment and quiz rendering issue in courses 2025-03-24 13:42:24 +05:30
Jannat Patel db62d40c50 chore: Croatian translations 2025-03-23 07:01:35 +05:30
Jannat Patel eff2ae8a73 chore: Thai translations 2025-03-23 07:01:33 +05:30
Jannat Patel b23d29767f chore: Portuguese, Brazilian translations 2025-03-23 07:01:32 +05:30
Jannat Patel 7d5a3c3421 chore: Esperanto translations 2025-03-23 07:01:31 +05:30
Jannat Patel 1054623d9d chore: Bosnian translations 2025-03-23 07:01:30 +05:30
Jannat Patel 4eba93f47b chore: Persian translations 2025-03-23 07:01:28 +05:30
Jannat Patel 13bcc84e8f chore: Chinese Simplified translations 2025-03-23 07:01:27 +05:30
Jannat Patel c726ad3467 chore: Turkish translations 2025-03-23 07:01:26 +05:30
Jannat Patel 5e95ff963c chore: Swedish translations 2025-03-23 07:01:24 +05:30
Jannat Patel 1ef232e45b chore: Russian translations 2025-03-23 07:01:23 +05:30
Jannat Patel 034654193f chore: Polish translations 2025-03-23 07:01:22 +05:30
Jannat Patel bddaa26d5a chore: Hungarian translations 2025-03-23 07:01:19 +05:30
Jannat Patel b42648fecb chore: German translations 2025-03-23 07:01:18 +05:30
Jannat Patel aa800bf96b chore: Arabic translations 2025-03-23 07:01:17 +05:30
Jannat Patel 6575e139b5 chore: Spanish translations 2025-03-23 07:01:15 +05:30
Jannat Patel c5b3460006 chore: French translations 2025-03-23 07:01:14 +05:30
Jannat Patel b1e490765b Merge pull request #1393 from frappe/pot_develop_2025-03-21
chore: update POT file
2025-03-22 13:22:38 +05:30
Jannat Patel c0f4a09e22 fix: removed page_renderer for courses 2025-03-22 11:18:03 +05:30
frappe-pr-bot 8fb5311844 chore: update POT file 2025-03-21 16:04:11 +00:00
Jannat Patel 12122f1eaf Merge pull request #1391 from pateljannat/issues-88
fix: removed user info from assignment block
2025-03-21 12:46:51 +05:30
Jannat Patel e83312289b fix: removed user info from assignment block 2025-03-21 12:34:49 +05:30
Jannat Patel d59f4113c1 Merge pull request #1389 from pateljannat/issues-87
fix: course tags issue when getting course details
2025-03-21 06:00:06 +05:30
Jannat Patel 8e3b70e7c8 fix: course tags issue when getting course details 2025-03-21 05:53:24 +05:30
Jannat Patel 6a41942de6 Merge pull request #1384 from frappe/develop
chore: merge 'develop' into 'main'
2025-03-20 13:04:16 +05:30
Jannat Patel c25d95b3b6 Merge pull request #1386 from pateljannat/issues-85
fix: misc issues
2025-03-20 12:29:25 +05:30
Jannat Patel edde95edeb chore: fixed linters 2025-03-20 12:22:13 +05:30
Jannat Patel 066eaea45d fix: redirection to FC site without checking payment method 2025-03-20 11:57:08 +05:30
Jannat Patel 7ae3cf5d95 fix: check seats of a batch at the time of billing 2025-03-20 11:03:08 +05:30
Jannat Patel 2fa728d45c Merge pull request #1383 from NihalRoshanCK/develop
change the text color according to the theme
2025-03-19 22:42:47 +05:30
Jannat Patel 04cbd6a1d8 chore: use vite plugins from frappe-ui 2025-03-19 22:26:58 +05:30
Jannat Patel c6e658e26b fix: show tabs and featured courses on list for guest users 2025-03-19 11:04:29 +05:30
Jannat Patel 0692aceda4 fix: don't allow billing page access if batch is sold out 2025-03-19 10:45:47 +05:30
Nihal Roshan 072bef5847 change the text color according to the theme 2025-03-18 10:15:52 +00:00
Jannat Patel e94a689f83 Merge pull request #1382 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-17 15:55:35 +05:30
Jannat Patel c71a980f78 chore: Chinese Simplified translations 2025-03-17 05:54:46 +05:30
Jannat Patel ef7d850dd4 chore: Persian translations 2025-03-16 05:49:18 +05:30
Jannat Patel 1e6a71f36b chore: Croatian translations 2025-03-15 05:16:33 +05:30
Jannat Patel f5ae4120cd chore: Thai translations 2025-03-15 05:16:32 +05:30
Jannat Patel 82331364b7 chore: Portuguese, Brazilian translations 2025-03-15 05:16:31 +05:30
Jannat Patel ef3879e419 chore: Esperanto translations 2025-03-15 05:16:30 +05:30
Jannat Patel 403dbf13e8 chore: Bosnian translations 2025-03-15 05:16:28 +05:30
Jannat Patel c8193c0009 chore: Persian translations 2025-03-15 05:16:27 +05:30
Jannat Patel 9c0c69a728 chore: Chinese Simplified translations 2025-03-15 05:16:26 +05:30
Jannat Patel 4606fc3e2a chore: Turkish translations 2025-03-15 05:16:24 +05:30
Jannat Patel c9bb3ab368 chore: Swedish translations 2025-03-15 05:16:23 +05:30
Jannat Patel 99e4b406a4 chore: Russian translations 2025-03-15 05:16:22 +05:30
Jannat Patel 67b9424b9e chore: Polish translations 2025-03-15 05:16:20 +05:30
Jannat Patel 5b60be5f51 chore: Hungarian translations 2025-03-15 05:16:19 +05:30
Jannat Patel d88927a6fb chore: German translations 2025-03-15 05:16:18 +05:30
Jannat Patel 6616ee3607 chore: Arabic translations 2025-03-15 05:16:16 +05:30
Jannat Patel 0dbd8de335 chore: Spanish translations 2025-03-15 05:16:15 +05:30
Jannat Patel 9b406e368b chore: French translations 2025-03-15 05:16:14 +05:30
Jannat Patel 4449dc43a0 Merge pull request #1381 from frappe/pot_develop_2025-03-14
chore: update POT file
2025-03-14 21:43:26 +05:30
frappe-pr-bot 554093ab3e chore: update POT file 2025-03-14 16:04:06 +00:00
Jannat Patel ac3ed22ae9 Merge pull request #1380 from pateljannat/issues-84
fix: moved evaluation cancel button in a menu
2025-03-13 22:17:39 +05:30
Jannat Patel 2ca7b09d1e fix: made address amount and currency mandatory in LMS Payment 2025-03-13 22:01:26 +05:30
Jannat Patel f29c2da9ce fix: moved evaluation cancel button in a menu 2025-03-13 22:00:39 +05:30
Jannat Patel e23f6ae0fa Merge pull request #1378 from pateljannat/issues-83
fix: batch reminder email subject and content
2025-03-13 08:27:49 +05:30
Jannat Patel 51061273bc fix: show view certificate link on course page, if already certified 2025-03-13 06:08:39 +05:30
Jannat Patel 4a0812dfe9 fix: batch reminder email subject and content 2025-03-13 06:08:00 +05:30
Md Hussain Nagaria efb694a6e6 Merge pull request #1377 from frappe/state-enhancement
fix: misc
2025-03-12 14:48:54 +05:30
Hussain Nagaria 1dbe2f31d0 fix: linter 2025-03-12 14:40:45 +05:30
Hussain Nagaria be9525dbf2 fix: empty query string with trailing ?
Fixes #1376
2025-03-12 14:37:50 +05:30
Hussain Nagaria a24afad641 chore: more dead code 2025-03-12 14:36:07 +05:30
Hussain Nagaria abd14aa33c chore: remove dead code 2025-03-12 14:31:53 +05:30
Hussain Nagaria 5b3c0685ac feat: track current tab in batches and courses page 2025-03-12 14:08:25 +05:30
Jannat Patel d263072aca Merge pull request #1373 from frappe/develop
chore: merge 'develop' into 'main'
2025-03-12 11:10:48 +05:30
Jannat Patel 2a59d9ff04 Merge pull request #1374 from pateljannat/issues-82
fix: check enrollment on course certification page
2025-03-12 11:03:20 +05:30
Jannat Patel 619dc73bcb fix: show created tab to users with moderator or instructor role 2025-03-12 10:50:20 +05:30
Jannat Patel 02edefc158 fix: check enrollment on course certification page 2025-03-12 10:49:44 +05:30
Jannat Patel 572f5ae585 Merge pull request #1370 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-11 10:39:34 +05:30
Jannat Patel a326866cc9 chore: Croatian translations 2025-03-11 04:16:36 +05:30
Jannat Patel 17decf7b71 chore: Thai translations 2025-03-11 04:16:34 +05:30
Jannat Patel b9784e22ff chore: Portuguese, Brazilian translations 2025-03-11 04:16:33 +05:30
Jannat Patel 0f600c5b70 chore: Esperanto translations 2025-03-11 04:16:32 +05:30
Jannat Patel a606e9c974 chore: Bosnian translations 2025-03-11 04:16:30 +05:30
Jannat Patel 9e1938095c chore: Persian translations 2025-03-11 04:16:29 +05:30
Jannat Patel 3491eb3881 chore: Chinese Simplified translations 2025-03-11 04:16:28 +05:30
Jannat Patel 6277340d6b chore: Turkish translations 2025-03-11 04:16:26 +05:30
Jannat Patel 0c12ee4452 chore: Swedish translations 2025-03-11 04:16:25 +05:30
Jannat Patel 4ec245a119 chore: Russian translations 2025-03-11 04:16:23 +05:30
Jannat Patel 24fa6d17de chore: Polish translations 2025-03-11 04:16:22 +05:30
Jannat Patel 2eedc1032c chore: Hungarian translations 2025-03-11 04:16:20 +05:30
Jannat Patel 8c3b1b433f chore: German translations 2025-03-11 04:16:19 +05:30
Jannat Patel ae3f0f9a4e chore: Arabic translations 2025-03-11 04:16:18 +05:30
Jannat Patel f4ae601f0d chore: Spanish translations 2025-03-11 04:16:16 +05:30
Jannat Patel 2104b86080 chore: French translations 2025-03-11 04:16:15 +05:30
Jannat Patel 9724dceb73 Merge pull request #1368 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-10 11:24:09 +05:30
Jannat Patel 4c07a4f35d Merge pull request #1366 from frappe/pot_develop_2025-03-07
chore: update POT file
2025-03-10 11:23:56 +05:30
Jannat Patel 6a15697957 chore: Croatian translations 2025-03-10 03:59:01 +05:30
frappe-pr-bot 47f880d8dc chore: update POT file 2025-03-07 16:04:14 +00:00
Jannat Patel d5814f5680 Merge pull request #1365 from pateljannat/issues-81
fix: youtube embed issue
2025-03-07 12:32:26 +05:30
Jannat Patel 345a444d73 fix: youtube embed issue 2025-03-07 12:18:52 +05:30
Jannat Patel 0053ce5602 Merge pull request #1364 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-06 16:14:45 +05:30
Jannat Patel 9851757a4e chore: Croatian translations 2025-03-06 03:44:37 +05:30
Jannat Patel 55fe25b8cb chore: Thai translations 2025-03-06 03:44:36 +05:30
Jannat Patel 714f8a17c3 chore: Portuguese, Brazilian translations 2025-03-06 03:44:35 +05:30
Jannat Patel 732e9db9af chore: Bosnian translations 2025-03-06 03:44:33 +05:30
Jannat Patel 6fbc448a52 chore: Persian translations 2025-03-06 03:44:32 +05:30
Jannat Patel 76fc241778 chore: Polish translations 2025-03-06 03:44:27 +05:30
Jannat Patel 51cbbfdc45 chore: German translations 2025-03-06 03:44:25 +05:30
Jannat Patel 279f2f503e chore: Arabic translations 2025-03-06 03:44:24 +05:30
Frappe PR Bot 795d95b482 chore(release): Bumped to Version 2.26.0 2025-03-05 13:04:57 +00:00
Jannat Patel 78c8467bf6 Merge pull request #1361 from frappe/develop
chore: merge 'develop' into 'main'
2025-03-05 18:33:33 +05:30
Jannat Patel 5b5b95c85c Merge pull request #1363 from pateljannat/scorm-issue-js-files
fix: scorm files getting wrong path
2025-03-05 17:03:40 +05:30
Jannat Patel 8490b07c90 fix: scorm files getting wrong path 2025-03-05 16:31:14 +05:30
Jannat Patel dee2c51c60 Merge pull request #1359 from pateljannat/evaluation-validation-issue
fix: allow scheduling evals if future eval has been cancelled
2025-03-04 17:47:42 +05:30
Jannat Patel 4149fa6ce4 fix: renamed evaluation and certification buttons 2025-03-04 17:38:43 +05:30
Jannat Patel 7a69611f09 Merge pull request #1358 from pateljannat/payment-reminder-issue
fix: don't send payment reminder if member has already paid later
2025-03-04 17:34:30 +05:30
Jannat Patel 6692252df9 fix: allow scheduling evals if furture eval has been calcelled 2025-03-04 17:33:39 +05:30
Jannat Patel 486ce1bdb0 Merge pull request #1357 from pateljannat/course-certification-filter
refactor: course list fetching and filters
2025-03-04 17:27:01 +05:30
Jannat Patel cceff77bc2 fix: don't send payment reminder if member has already paid later 2025-03-04 17:24:03 +05:30
Jannat Patel 22a9169f87 fix: show progress bar for enrolled courses 2025-03-04 17:14:01 +05:30
Jannat Patel 47a30763a0 refactor: course list fetching and filters 2025-03-04 17:02:47 +05:30
Jannat Patel 73379a1bd8 Merge pull request #1354 from pateljannat/dont-override-user
fix: reverting user doctype override
2025-03-04 13:08:12 +05:30
Jannat Patel 7cc46629b4 test: increased login request timeout in ui tests 2025-03-04 12:53:33 +05:30
Jannat Patel 67304245ba test: increased login request timeout in ui tests 2025-03-04 12:39:22 +05:30
Jannat Patel 8edd3a1a34 chore: upgrading actions/cache to v4 for ui tests 2025-03-04 11:43:07 +05:30
Jannat Patel e4bc7c8d78 Merge pull request #1356 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-04 10:22:56 +05:30
Jannat Patel a8af78d400 chore: Esperanto translations 2025-03-04 02:59:49 +05:30
Jannat Patel 0afe3de818 chore: Bosnian translations 2025-03-04 02:59:48 +05:30
Jannat Patel 3c81aadec6 chore: Persian translations 2025-03-04 02:59:47 +05:30
Jannat Patel 1dfcb035da chore: Chinese Simplified translations 2025-03-04 02:59:45 +05:30
Jannat Patel 77b24882a9 chore: Turkish translations 2025-03-04 02:59:44 +05:30
Jannat Patel 1fd0673257 chore: Swedish translations 2025-03-04 02:59:42 +05:30
Jannat Patel dbda76e0ce chore: Russian translations 2025-03-04 02:59:40 +05:30
Jannat Patel a9d22521ce chore: Polish translations 2025-03-04 02:59:39 +05:30
Jannat Patel 6da1d9629f chore: Hungarian translations 2025-03-04 02:59:37 +05:30
Jannat Patel 37b61a7087 chore: German translations 2025-03-04 02:59:35 +05:30
Jannat Patel 9b484e6ee9 chore: Arabic translations 2025-03-04 02:59:34 +05:30
Jannat Patel 5ef67ef21c chore: Spanish translations 2025-03-04 02:59:32 +05:30
Jannat Patel f902166643 chore: French translations 2025-03-04 02:59:31 +05:30
Md Hussain Nagaria 8f91466b3d Merge pull request #1355 from frappe/enhance-timezone
feat: autofill timezone based on user timezone
2025-03-03 22:43:24 +05:30
Hussain Nagaria fa1621c3d1 feat: autofill client timezone based on user timezone 2025-03-03 22:42:43 +05:30
Jannat Patel 2acd45feae fix: reverting user doctype override 2025-03-03 19:54:41 +05:30
Jannat Patel f19e974b9d Merge pull request #1353 from pateljannat/mark-eval-request-complete
feat: mark evaluation requests as complete
2025-03-03 17:14:42 +05:30
Jannat Patel 01598ac002 feat: mark evaluation requests as complete 2025-03-03 17:01:10 +05:30
Frappe PR Bot 9b3906359b chore(release): Bumped to Version 2.25.0 2025-03-03 10:20:45 +00:00
Jannat Patel 084908bd04 Merge pull request #1352 from frappe/develop
chore: merge 'develop' into 'main'
2025-03-03 15:38:08 +05:30
Jannat Patel 4224580d6f Merge pull request #1351 from pateljannat/billing-flow-changes
fix: redirect to FC dashboard when login to FC
2025-03-03 14:59:21 +05:30
Jannat Patel 07d30647d8 chore: upgrading actions/cache to v4 for ci tests 2025-03-03 13:58:39 +05:30
Jannat Patel 263096fc77 fix: changed frappe cloud login flow 2025-03-03 13:53:16 +05:30
Jannat Patel b510cbce7f Merge pull request #1347 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-03-03 10:13:26 +05:30
Jannat Patel 0b84dc3266 Merge pull request #1346 from frappe/pot_develop_2025-02-28
chore: update POT file
2025-03-03 10:13:13 +05:30
Md Hussain Nagaria 7ee7b95eb5 Merge pull request #1350 from frappe/tz-autocomplete
feat: timezone autocomplete in live class & misc fixes
2025-03-03 06:35:07 +05:30
Hussain Nagaria 83b8bdde45 fix: transform tabIndex query param to number 2025-03-03 06:22:19 +05:30
Hussain Nagaria 1b5dd15b90 feat(LiveClass): timezone autocomplete field 2025-03-03 06:19:06 +05:30
Hussain Nagaria 47c224fcad chore: remove unused imports 2025-03-03 06:01:02 +05:30
Fahid Latheef A 39cc83c1b8 Merge branch 'frappe:develop' into feat/scorm-progress 2025-03-02 14:17:26 +05:30
Jannat Patel 1c866f40eb chore: Persian translations 2025-03-01 02:00:07 +05:30
frappe-pr-bot 1861aabaca chore: update POT file 2025-02-28 16:04:26 +00:00
Jannat Patel cd8fb6eb38 Merge pull request #1342 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-28 10:42:18 +05:30
Jannat Patel 21d05d3731 chore: Bosnian translations 2025-02-28 01:36:22 +05:30
Jannat Patel 7c953925f9 chore: Bosnian translations 2025-02-27 01:40:12 +05:30
Jannat Patel 33a4bbbe47 chore: Persian translations 2025-02-27 01:40:10 +05:30
Frappe PR Bot dfb82570ea chore(release): Bumped to Version 2.24.0 2025-02-26 04:50:44 +00:00
Jannat Patel 039a775ce4 Merge pull request #1340 from frappe/develop
chore: merge 'develop' into 'main'
2025-02-26 10:18:26 +05:30
Jannat Patel e712d6ae42 Merge pull request #1334 from pateljannat/paid-certificate-on-courses
feat: paid certifications on courses
2025-02-25 14:47:07 +05:30
Jannat Patel 6ffc953370 test: removed course expiry from test 2025-02-25 14:33:53 +05:30
Jannat Patel 63bf6a5574 fix: polished the course certification flow 2025-02-25 12:46:35 +05:30
Jannat Patel 1e73fc5751 Merge pull request #1338 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-25 10:50:30 +05:30
Jannat Patel 65604a0b88 chore: Esperanto translations 2025-02-25 01:05:38 +05:30
Jannat Patel 5a1a39f5f5 chore: Bosnian translations 2025-02-25 01:05:36 +05:30
Jannat Patel d22576c85c chore: Persian translations 2025-02-25 01:05:35 +05:30
Jannat Patel b7e5332c38 chore: Chinese Simplified translations 2025-02-25 01:05:33 +05:30
Jannat Patel ed8570fb88 chore: Turkish translations 2025-02-25 01:05:32 +05:30
Jannat Patel ce69e6634d chore: Swedish translations 2025-02-25 01:05:31 +05:30
Jannat Patel 274db20c60 chore: Russian translations 2025-02-25 01:05:29 +05:30
Jannat Patel 3d72072f1f chore: Polish translations 2025-02-25 01:05:28 +05:30
Jannat Patel ed156c09d7 chore: Hungarian translations 2025-02-25 01:05:27 +05:30
Jannat Patel fda3a1a468 chore: German translations 2025-02-25 01:05:25 +05:30
Jannat Patel c261387635 chore: Arabic translations 2025-02-25 01:05:24 +05:30
Jannat Patel 7a2fa4dae8 chore: Spanish translations 2025-02-25 01:05:22 +05:30
Jannat Patel b0c41958d9 chore: French translations 2025-02-25 01:05:21 +05:30
Jannat Patel 4f1dcbfb78 feat: eval and certification flow with purchased certificate 2025-02-24 19:15:26 +05:30
Jannat Patel dc9ed099d0 Merge pull request #1335 from frappe/pot_develop_2025-02-21
chore: update POT file
2025-02-24 10:38:54 +05:30
Md Hussain Nagaria 95255d44a9 feat(batch): track active tab in URL/route (#1337)
* chore: remove defineModel imports

* it is a compiler macro now, so no longer needs to be imported

* feat(batch): track active tab in URL/route

Fixes #1336

* style: lint
2025-02-22 22:30:14 +05:30
Hussain Nagaria 5a94e8df75 style: lint 2025-02-22 22:23:40 +05:30
Hussain Nagaria 015e3f8490 feat(batch): track active tab in URL/route
Fixes #1336
2025-02-22 22:21:26 +05:30
Hussain Nagaria 558601f02b chore: remove defineModel imports
* it is a compiler macro now, so no longer needs to be imported
2025-02-22 21:58:50 +05:30
frappe-pr-bot 461d96a079 chore: update POT file 2025-02-21 16:04:10 +00:00
Jannat Patel bacfaf4a71 feat: paid certifications on courses 2025-02-21 19:12:20 +05:30
Jannat Patel 0678def698 Merge pull request #1330 from pateljannat/markdown-links
fix: link issue in lesson
2025-02-20 16:37:33 +05:30
Jannat Patel 07b0a0af51 test: fixed lesson content test 2025-02-20 16:31:09 +05:30
Jannat Patel f12f6cb720 fix: link issue in lesson 2025-02-20 15:08:14 +05:30
Jannat Patel 4e6c1478f9 Merge pull request #1328 from pateljannat/reschedule-evals
feat: cancel evaluations
2025-02-20 10:34:08 +05:30
Jannat Patel f9fd36f77e feat: cancel evaluations 2025-02-19 22:29:24 +05:30
Jannat Patel db4c7424b3 Merge pull request #1327 from pateljannat/issues-79
fix: misc batch issues
2025-02-19 16:51:42 +05:30
Jannat Patel 9311043190 fix: misc batch issues 2025-02-19 16:40:11 +05:30
Jannat Patel 03915ccfbd fix: only system managers should login to FC 2025-02-19 15:39:13 +05:30
Jannat Patel c6d59216fd fix: redirect to FC dashboard when login to FC 2025-02-19 15:35:34 +05:30
Jannat Patel dd9e80f067 Merge pull request #1326 from frappe/develop
chore: merge 'develop' into 'main'
2025-02-19 11:06:43 +05:30
Frappe PR Bot a8690e41e6 chore(release): Bumped to Version 2.23.0 2025-02-19 05:29:30 +00:00
Jannat Patel cda42b9ec5 Merge pull request #1325 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-19 08:49:19 +05:30
Jannat Patel 21a75fdd6d chore: Bosnian translations 2025-02-18 23:05:44 +05:30
Jannat Patel a90a1e9855 chore: Persian translations 2025-02-18 23:05:43 +05:30
Jannat Patel 2a046e2e8b chore: German translations 2025-02-18 23:05:40 +05:30
Jannat Patel bb41656d81 Merge branch 'develop' of https://github.com/frappe/lms into develop 2025-02-18 19:12:23 +05:30
Jannat Patel a88a107718 fix: batch confirmation email template 2025-02-18 19:12:04 +05:30
Jannat Patel 2d21469f91 Merge pull request #1324 from pateljannat/issues-78
fix: redirect users to the batch page after login
2025-02-18 18:29:51 +05:30
Jannat Patel 960ebe4a79 fix: redirect users to the batch page after login 2025-02-18 18:10:33 +05:30
Jannat Patel 46dba0c394 Merge pull request #1323 from pateljannat/batch-reminders
feat: batch start and live class reminder
2025-02-18 17:34:44 +05:30
Jannat Patel ba27e8ca95 fix: send live class reminder on the day of the class 2025-02-18 17:26:40 +05:30
Jannat Patel 30574ea0fd feat: batch start and live class reminder 2025-02-18 17:22:52 +05:30
Jannat Patel c3c985c4a1 Merge pull request #1322 from pateljannat/certification-batches
feat: filter certification batches
2025-02-18 17:05:16 +05:30
Jannat Patel 7b3d2d8812 feat: filter certification batches 2025-02-18 15:57:55 +05:30
Jannat Patel d573a9f008 Merge pull request #1320 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-18 12:41:05 +05:30
Fahid Latheef A 5dd1bb949c Merge branch 'develop' into feat/scorm-progress 2025-02-17 23:07:10 +05:30
Jannat Patel 85a05f56b2 chore: Esperanto translations 2025-02-17 22:33:51 +05:30
Jannat Patel 904adfb905 chore: Bosnian translations 2025-02-17 22:33:50 +05:30
Jannat Patel b2201c29fd chore: Persian translations 2025-02-17 22:33:48 +05:30
Jannat Patel fe01f68623 chore: Chinese Simplified translations 2025-02-17 22:33:47 +05:30
Jannat Patel 531c8ebe94 chore: Turkish translations 2025-02-17 22:33:45 +05:30
Jannat Patel 52dfb5a360 chore: Swedish translations 2025-02-17 22:33:44 +05:30
Jannat Patel 7e04e7e461 chore: Russian translations 2025-02-17 22:33:42 +05:30
Jannat Patel bce47f606d chore: Polish translations 2025-02-17 22:33:41 +05:30
Jannat Patel 4dc1fdfdd8 chore: Hungarian translations 2025-02-17 22:33:40 +05:30
Jannat Patel 9a852b52bc chore: German translations 2025-02-17 22:33:38 +05:30
Jannat Patel 71a57b1fc0 chore: Arabic translations 2025-02-17 22:33:37 +05:30
Jannat Patel d634598db1 chore: Spanish translations 2025-02-17 22:33:35 +05:30
Jannat Patel 6377d682a4 chore: French translations 2025-02-17 22:33:33 +05:30
Jannat Patel 6e1acfdc24 Merge pull request #1316 from FahidLatheef/fix/quiz-maximum-attempts
fix: fixed bug in which user can submit quiz over the maximum limit allowed
2025-02-17 19:59:57 +05:30
Jannat Patel 30ec1dfd7c Merge pull request #1319 from pateljannat/assignment-grading-comment-field
feat: assignment comments is now text editor
2025-02-17 19:56:22 +05:30
Jannat Patel 3d209024dd fix: height of batch page 2025-02-17 19:45:45 +05:30
Jannat Patel 9ce64a037d fix: increased column width for grading 2025-02-17 19:41:24 +05:30
Jannat Patel 43117bc035 feat:assignment comments is now text editor 2025-02-17 19:28:50 +05:30
Jannat Patel 2af704043e Merge pull request #1318 from pateljannat/batch-email-template
feat: batch specific email templates
2025-02-17 18:36:05 +05:30
Jannat Patel fa14ffdcba feat: batch specific email templates 2025-02-17 18:17:50 +05:30
Jannat Patel 492b715ea0 Merge pull request #1317 from pateljannat/trial-signup
feat: billing banner for FC trial sites
2025-02-17 16:00:46 +05:30
Jannat Patel d452e20b8a feat: show trial banner only if fc site 2025-02-17 15:39:15 +05:30
Jannat Patel 6b634c15d9 feat: billing banner for FC trial sites 2025-02-17 15:07:31 +05:30
Jannat Patel eeaec3369f Merge pull request #1313 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-17 11:10:39 +05:30
Jannat Patel ce1eece90d Merge pull request #1312 from frappe/pot_develop_2025-02-14
chore: update POT file
2025-02-17 11:05:48 +05:30
Jannat Patel 030bff6592 chore: Bosnian translations 2025-02-16 22:32:22 +05:30
Jannat Patel 65de46a59e chore: Swedish translations 2025-02-16 22:32:18 +05:30
Fahid Latheef Alungal b76486e4dc fix: changed filters in calculation of completed LMS Course Progress count 2025-02-16 21:08:58 +05:30
Fahid Latheef Alungal 974f67aefe fix: validate if submission exceeds the allowed limit in backend 2025-02-16 19:29:03 +05:30
Fahid Latheef Alungal e374ae3229 fix: fixed spelling nextQuetion -> nextQuestion 2025-02-16 18:28:48 +05:30
Fahid Latheef Alungal 8b1058e577 fix: fixed issue in which submissions are not reflected gracefully until page reload
ListView throws error if initialized without emptyState which was causing the component to not reload when number of submissions was 0.
2025-02-16 18:27:38 +05:30
Fahid Latheef Alungal aaa2eea5e6 fix: fixed incomplete router initialization in Quiz.vue which was allowing user to submit quiz multiple times 2025-02-16 18:19:14 +05:30
Fahid Latheef Alungal 54047e3c2c fix: fix spelling typo Maximun Attempts -> Maximum Attempts 2025-02-16 16:10:14 +05:30
Fahid Latheef Alungal 50fe94e47b fix: fix yarn dev not working due to const variable re-assignment
It was causing this error

  ✘ [ERROR] Cannot assign to "isLoggedIn" because it is a constant

    src/router.js:230:2:
      230 │     isLoggedIn = false
          ╵     ~~~~~~~~~~

  The symbol "isLoggedIn" was declared a constant here:

    src/router.js:222:7:
      222 │   const { isLoggedIn } = sessionStore()
          ╵         ^
2025-02-16 16:08:35 +05:30
Jannat Patel 6999f6641a chore: Bosnian translations 2025-02-15 22:29:52 +05:30
frappe-pr-bot c2b12aa65f chore: update POT file 2025-02-14 16:04:13 +00:00
Jannat Patel 1a731b6908 Merge pull request #1311 from pateljannat/issues-77
fix: students should have access private batch if enrolled
2025-02-14 20:21:54 +05:30
Jannat Patel 837d050628 fix: students should be able to access private batch if they are enrolled 2025-02-14 20:10:32 +05:30
Jannat Patel 8b00bec49c fix: students should be able to access private batch if they are enrolled 2025-02-14 20:04:37 +05:30
Jannat Patel a3a2af948e Merge pull request #1303 from frappe/develop
chore: merge 'develop' into 'main'
2025-02-14 18:07:10 +05:30
Jannat Patel 9ade643af0 Merge pull request #1310 from frappe/l10n_develop2
chore: sync translations from crowdin
2025-02-14 17:06:53 +05:30
Jannat Patel a29b92a886 chore: Bosnian translations 2025-02-13 22:17:06 +05:30
Jannat Patel e2c28e211f Merge pull request #1309 from pateljannat/issues-76
fix: misc batch issues
2025-02-13 21:26:17 +05:30
Jannat Patel 65f5b6a0a4 fix: delete unused custom fields from web form 2025-02-13 17:23:57 +05:30
Jannat Patel 75cea1ab78 fix: delete unused custom fields from web form 2025-02-13 17:21:14 +05:30
Jannat Patel 5ab9131629 fix: misc batch issues 2025-02-13 16:57:21 +05:30
FahidLatheef 2ce2df6390 style: change height of SCORM iframe so that user don't have to scroll 2025-01-22 15:25:39 +05:30
FahidLatheef 19e5136d64 feat: added logic to handle failure cases on SCORM courses failure (Whether to allow retake of final quiz or Reset the whole Course) 2025-01-22 15:25:39 +05:30
FahidLatheef 281e155480 feat: set cmi.launch_data from scorm_content for resumability
- Replaced already_completed with progress_already_exists variable
- Added scorm_details parameter to save_progress whitelisted function
- Added Separate logic for SCORM chapter progress in save_progress
2025-01-22 15:25:39 +05:30
FahidLatheef 70b2a11cb7 feat: added is_scorm_chapter and scorm_details fields used for tracking SCORM Data Model
feat: added is_scorm_chapter and scorm_content to track cmi.suspend_data for resuming scorm chapter
2025-01-22 15:25:39 +05:30
Jannat Patel 0bedf3ea59 Merge pull request #1264 from frappe/develop
chore: merge 'develop' into 'main'
2025-01-22 12:59:34 +05:30
Jannat Patel 1775ac4803 Merge pull request #1247 from frappe/develop
chore: merge 'develop' into 'main'
2025-01-15 11:24:49 +05:30
Jannat Patel ae1a615863 Merge pull request #1237 from frappe/develop
chore: merge 'develop' into 'main'
2025-01-09 11:01:37 +05:30
Jannat Patel a6ef1b8902 Merge pull request #1220 from frappe/develop
chore: merge 'develop' into 'main'
2025-01-02 20:24:58 +05:30
Jannat Patel 94d17b81d4 Merge pull request #1197 from frappe/develop
chore: merge 'develop' into 'main'
2024-12-18 20:30:52 +05:30
Jannat Patel 44a63d9cec Merge pull request #1180 from frappe/develop
chore: merge 'develop' into 'main'
2024-12-13 12:27:07 +05:30
Jannat Patel e2b4b5a57e Merge pull request #1164 from frappe/develop
chore: merge 'develop' into 'main'
2024-12-06 11:05:49 +05:30
Jannat Patel ec30aa323e Merge pull request #1155 from frappe/develop
chore: merge 'develop' into 'main'
2024-11-29 17:05:30 +05:30
Jannat Patel 95e9087c6e Merge pull request #1151 from frappe/develop
chore: merge 'develop' into 'main'
2024-11-25 15:06:00 +05:30
Jannat Patel db38099557 Merge pull request #1143 from frappe/develop
chore: merge 'develop' into 'main'
2024-11-20 13:30:06 +05:30
Jannat Patel 164d5cdec9 Merge pull request #1130 from frappe/develop
chore: merge 'develop' into 'main'
2024-11-13 11:53:57 +05:30
Jannat Patel c6b1076092 Merge pull request #1099 from frappe/develop
chore: merge 'develop' into 'main'
2024-11-07 09:51:07 +05:30
Jannat Patel 6aebe856da Merge pull request #1087 from frappe/develop
chore: merge 'develop' into 'main'
2024-10-31 12:15:12 +05:30
Jannat Patel 4737551918 Merge pull request #1075 from frappe/develop
chore: merge 'develop' into 'main'
2024-10-23 13:00:37 +05:30
Jannat Patel c2cb79f700 Merge pull request #1067 from frappe/develop
chore: merge 'develop' into 'main'
2024-10-17 12:33:35 +05:30
Jannat Patel d7c05984be Merge pull request #1048 from frappe/develop
chore: merge 'develop' into 'main'
2024-10-09 22:11:23 +05:30
Jannat Patel 55429e2f03 Merge pull request #1036 from frappe/develop
chore: merge 'develop' into 'main'
2024-10-02 12:30:46 +05:30
Jannat Patel 25ffe8b0e4 Merge pull request #1029 from frappe/develop
chore: merge 'develop' into 'main'
2024-09-25 11:47:14 +05:30
Jannat Patel 303a9d1110 Merge pull request #1020 from frappe/develop
chore: merge 'develop' into 'main'
2024-09-18 10:21:11 +05:30
Jannat Patel de8c907c51 Merge pull request #1013 from frappe/develop
chore: merge 'develop' into 'main'
2024-09-11 11:09:55 +05:30
Jannat Patel 0fd1cabd60 Merge pull request #1003 from frappe/develop
chore: merge 'develop' into 'main'
2024-09-04 10:36:05 +05:30
Jannat Patel 8dd480735c Merge pull request #996 from frappe/develop
chore: merge 'develop' into 'main'
2024-08-28 11:24:59 +05:30
Jannat Patel 676f1a1f0e Merge pull request #984 from frappe/develop
chore: merge 'develop' into 'main'
2024-08-21 10:48:23 +05:30
Jannat Patel ce75422126 Merge pull request #966 from frappe/develop
chore: merge 'develop' into 'main'
2024-08-14 11:24:10 +05:30
Jannat Patel 3a097d6b15 Merge pull request #956 from frappe/develop
chore: Merge develop into main
2024-08-06 11:27:00 +05:30
Jannat Patel 9de1bf1020 Merge pull request #954 from frappe/develop
chore: Merge develop into main
2024-08-05 14:47:45 +05:30
Jannat Patel 93e5cf1c25 Merge pull request #952 from frappe/develop
chore: Merge develop to main
2024-08-05 12:22:05 +05:30
Jannat Patel 6e2376570b Merge pull request #949 from frappe/develop
chore: Merge develop to main
2024-08-01 17:16:22 +05:30
Jannat Patel b20c4bf197 Merge pull request #948 from frappe/develop
chore: Merge develop to main
2024-07-31 16:33:43 +05:30
Jannat Patel 6ae1d92033 Merge pull request #925 from frappe/develop
chore: merge `develop` into `main`
2024-07-11 09:11:50 +05:30
488 changed files with 192436 additions and 43090 deletions
+124
View File
@@ -0,0 +1,124 @@
{
"env": {
"browser": true,
"node": true,
"es2022": true
},
"parserOptions": {
"sourceType": "module"
},
"extends": "eslint:recommended",
"rules": {
"indent": "off",
"brace-style": "off",
"no-mixed-spaces-and-tabs": "off",
"no-useless-escape": "off",
"space-unary-ops": ["error", { "words": true }],
"linebreak-style": "off",
"quotes": ["off"],
"semi": "off",
"camelcase": "off",
"no-unused-vars": "off",
"no-console": ["warn"],
"no-extra-boolean-cast": ["off"],
"no-control-regex": ["off"],
},
"root": true,
"globals": {
"frappe": true,
"Vue": true,
"SetVueGlobals": true,
"__": true,
"repl": true,
"Class": true,
"locals": true,
"cint": true,
"cstr": true,
"cur_frm": true,
"cur_dialog": true,
"cur_page": true,
"cur_list": true,
"cur_tree": true,
"msg_dialog": true,
"is_null": true,
"in_list": true,
"has_common": true,
"posthog": true,
"has_words": true,
"validate_email": true,
"open_web_template_values_editor": true,
"validate_name": true,
"validate_phone": true,
"validate_url": true,
"get_number_format": true,
"format_number": true,
"format_currency": true,
"comment_when": true,
"open_url_post": true,
"toTitle": true,
"lstrip": true,
"rstrip": true,
"strip": true,
"strip_html": true,
"replace_all": true,
"flt": true,
"precision": true,
"CREATE": true,
"AMEND": true,
"CANCEL": true,
"copy_dict": true,
"get_number_format_info": true,
"strip_number_groups": true,
"print_table": true,
"Layout": true,
"web_form_settings": true,
"$c": true,
"$a": true,
"$i": true,
"$bg": true,
"$y": true,
"$c_obj": true,
"refresh_many": true,
"refresh_field": true,
"toggle_field": true,
"get_field_obj": true,
"get_query_params": true,
"unhide_field": true,
"hide_field": true,
"set_field_options": true,
"getCookie": true,
"getCookies": true,
"get_url_arg": true,
"md5": true,
"$": true,
"jQuery": true,
"moment": true,
"hljs": true,
"Awesomplete": true,
"Sortable": true,
"Showdown": true,
"Taggle": true,
"Gantt": true,
"Slick": true,
"Webcam": true,
"PhotoSwipe": true,
"PhotoSwipeUI_Default": true,
"io": true,
"JsBarcode": true,
"L": true,
"Chart": true,
"DataTable": true,
"Cypress": true,
"cy": true,
"it": true,
"describe": true,
"expect": true,
"context": true,
"before": true,
"beforeEach": true,
"after": true,
"qz": true,
"localforage": true,
"extend_cscript": true
}
}
+1 -1
View File
@@ -5,7 +5,7 @@ echo "Setting Up System Dependencies..."
sudo apt update
sudo apt remove mysql-server mysql-client
sudo apt-get install libcups2-dev redis-server mariadb-client
sudo apt-get install libcups2-dev redis-server mariadb-client libmariadb-dev
install_wkhtmltopdf() {
wget -q https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox_0.12.6-1.focal_amd64.deb
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
node-version: '18'
check-latest: true
- name: setup cache for bench
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: ~/bench-cache
key: ${{ runner.os }}
+30 -2
View File
@@ -7,8 +7,27 @@ on:
branches: [ main ]
jobs:
commit-lint:
name: 'Semantic Commits'
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 200
- uses: actions/setup-node@v4
with:
node-version: 20
check-latest: true
- name: Check commit titles
run: |
npm install @commitlint/cli @commitlint/config-conventional
npx commitlint --verbose --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }}
linters:
name: Semantic Commits
name: Semgrep Rules
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
@@ -20,8 +39,17 @@ jobs:
with:
python-version: '3.10'
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: Install and Run Pre-commit
uses: pre-commit/action@v2.0.3
uses: pre-commit/action@v3.0.1
- name: Download Semgrep rules
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
+1 -2
View File
@@ -1,8 +1,7 @@
name: Create weekly release
on:
schedule:
# 13:00 UTC -> 7pm IST on every Wednesday
- cron: '30 4 * * 3'
- cron: '30 3 * * 3'
workflow_dispatch:
jobs:
+5 -4
View File
@@ -58,7 +58,7 @@ jobs:
echo "127.0.0.1 lms.test" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml', '**/setup.py') }}
@@ -70,7 +70,7 @@ jobs:
id: yarn-cache-dir-path
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
@@ -79,7 +79,7 @@ jobs:
${{ runner.os }}-yarn-ui-
- name: Cache cypress binary
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-cypress
@@ -100,11 +100,12 @@ jobs:
bench --site lms.test execute frappe.utils.install.complete_setup_wizard
bench --site lms.test execute frappe.tests.ui_test_helpers.create_test_user
bench --site lms.test set-password frappe@example.com admin
bench --site lms.test execute lms.lms.utils.persona_captured
- name: cypress pre-requisites
run: |
cd ~/frappe-bench/apps/lms
yarn add cypress@^10 --no-lockfile
yarn add cypress@^10 --no-lockfile -W
- name: UI Tests
run: cd ~/frappe-bench/ && bench --site lms.test run-ui-tests lms --headless
+26 -17
View File
@@ -1,10 +1,10 @@
exclude: 'node_modules|.git'
default_stages: [commit]
default_stages: [pre-commit]
fail_fast: false
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v5.0.0
hooks:
- id: trailing-whitespace
files: "lms.*"
@@ -16,17 +16,16 @@ repos:
- id: check-toml
- id: debug-statements
- repo: https://github.com/asottile/pyupgrade
rev: v2.34.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.1
hooks:
- id: pyupgrade
args: ['--py310-plus']
- repo: https://github.com/adityahase/black
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
hooks:
- id: black
additional_dependencies: ['click==8.0.4']
- id: ruff
name: "Run ruff import sorter"
args: ["--select=I", "--fix"]
- id: ruff
name: "Run ruff linter"
- id: ruff-format
name: "Run ruff formatter"
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.7.1
@@ -44,12 +43,22 @@ repos:
lms/public/js/lib/.*
)$
- repo: https://github.com/PyCQA/flake8
rev: 5.0.4
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v8.44.0
hooks:
- id: flake8
additional_dependencies: ['flake8-bugbear',]
args: ['--config', '.github/helper/flake8.conf']
- id: eslint
types_or: [javascript]
args: ['--quiet']
exclude: |
(?x)^(
lms/public/dist/.*|
cypress/.*|
.*node_modules.*|
.*boilerplate.*|
lms/www/website_script.js|
lms/templates/includes/.*|
lms/public/js/lib/.*
)$
ci:
autoupdate_schedule: weekly
-174
View File
@@ -1,174 +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.
## 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>
+26
View File
@@ -0,0 +1,26 @@
export default {
parserPreset: "conventional-changelog-conventionalcommits",
rules: {
"subject-empty": [2, "never"],
"type-case": [2, "always", "lower-case"],
"type-empty": [2, "never"],
"type-enum": [
2,
"always",
[
"build",
"chore",
"ci",
"docs",
"feat",
"fix",
"perf",
"refactor",
"revert",
"style",
"test",
"deprecate", // deprecation decision
],
],
},
};
+3 -3
View File
@@ -1,6 +1,6 @@
const { defineConfig } = require("cypress");
import { defineConfig } from "cypress";
module.exports = defineConfig({
export default defineConfig({
projectId: "vandxn",
adminPassword: "admin",
testUser: "frappe@example.com",
@@ -13,6 +13,6 @@ module.exports = defineConfig({
openMode: 0,
},
e2e: {
baseUrl: "http://lms1:8000",
baseUrl: "http://pertest:8000",
},
});
+168
View File
@@ -0,0 +1,168 @@
describe("Batch Creation", () => {
it("creates a new batch", () => {
cy.login();
cy.wait(500);
cy.visit("/lms/batches");
cy.closeOnboardingModal();
// Open Settings
cy.get("span").contains("Learning").click();
cy.get("span").contains("Settings").click();
// Add a new member
cy.get("[data-dismissable-layer]")
.find("span")
.contains(/^Members$/)
.click();
cy.get("[data-dismissable-layer]")
.find("button")
.contains("New")
.click();
const dateNow = Date.now();
const randomEmail = `testuser_${dateNow}@example.com`;
const randomName = `Test User ${dateNow}`;
cy.get("input[placeholder='jane@doe.com']").type(randomEmail);
cy.get("input[placeholder='Jane']").type(randomName);
cy.get("button").contains("Add").click();
// Add evaluator
cy.get("[data-dismissable-layer]")
.find("span")
.contains(/^Evaluators$/)
.click();
cy.get("[data-dismissable-layer]")
.find("button")
.contains("New")
.click();
const randomEvaluator = `evaluator${dateNow}@example.com`;
cy.get("input[placeholder='jane@doe.com']").type(randomEvaluator);
cy.get("button").contains("Add").click();
cy.get("div").contains(randomEvaluator).should("be.visible").click();
cy.visit("/lms/batches");
cy.closeOnboardingModal();
// Create a batch
cy.get("button").contains("Create").click();
cy.wait(500);
cy.url().should("include", "/batches/new/edit");
cy.get("label").contains("Title").type("Test Batch");
cy.get("label").contains("Start Date").type("2030-10-01");
cy.get("label").contains("End Date").type("2030-10-31");
cy.get("label").contains("Start Time").type("10:00");
cy.get("label").contains("End Time").type("11:00");
cy.get("label").contains("Timezone").type("IST");
cy.get("label").contains("Seat Count").type("10");
cy.get("label").contains("Published").click();
cy.get("label")
.contains("Short Description")
.type("Test Batch Short Description to test the UI");
cy.get("div[contenteditable=true").invoke(
"text",
"Test Batch Description. I need a very big description to test the UI. This is a very big description. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
);
/* Instructor */
cy.get("label")
.contains("Instructors")
.parent()
.within(() => {
cy.get("input").click().type("evaluator");
cy.get("input")
.invoke("attr", "aria-controls")
.as("instructor_list_id");
});
cy.get("@instructor_list_id").then((instructor_list_id) => {
cy.get(`[id^=${instructor_list_id}`)
.should("be.visible")
.within(() => {
cy.get("[id^=headlessui-combobox-option-").first().click();
});
});
cy.button("Save").click();
cy.wait(1000);
let batchName;
cy.url().then((url) => {
console.log(url);
batchName = url.split("/").pop();
cy.wrap(batchName).as("batchName");
});
cy.wait(500);
// View Batch
cy.wait(1000);
cy.visit("/lms/batches");
cy.closeOnboardingModal();
cy.url().should("include", "/lms/batches");
cy.get('[id^="headlessui-radiogroup-v-"]')
.find("span")
.contains("Upcoming")
.should("be.visible")
.click();
cy.get("@batchName").then((batchName) => {
cy.get(`a[href='/lms/batches/details/${batchName}'`).within(() => {
cy.get("div").contains("Test Batch").should("be.visible");
cy.get("div")
.contains("Test Batch Short Description to test the UI")
.should("be.visible");
cy.get("span")
.contains("01 Oct 2030 - 31 Oct 2030")
.should("be.visible");
cy.get("span")
.contains("10:00 AM - 11:00 AM")
.should("be.visible");
cy.get("span").contains("IST").should("be.visible");
cy.get("a").contains("Evaluator").should("be.visible");
cy.get("div")
.contains("10")
.should("be.visible")
.get("span")
.contains("Seats Left")
.should("be.visible");
});
cy.get(`a[href='/lms/batches/details/${batchName}'`).click();
});
cy.get("div").contains("Test Batch").should("be.visible");
cy.get("div")
.contains("Test Batch Short Description to test the UI")
.should("be.visible");
cy.get("a").contains("Evaluator").should("be.visible");
cy.get("span:visible")
.contains("01 Oct 2030 - 31 Oct 2030")
.should("be.visible");
cy.get("span:visible")
.contains("10:00 AM - 11:00 AM")
.should("be.visible");
cy.get("span:visible").contains("IST").should("be.visible");
cy.contains("div:visible", "10 Seats Left").should("be.visible");
cy.get("p")
.contains(
"Test Batch Description. I need a very big description to test the UI. This is a very big description. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
)
.should("be.visible");
cy.get("button:visible").contains("Manage Batch").click();
/* Add student to batch */
cy.get("button").contains("Add").click();
cy.get('div[role="dialog"]').first().find("button").eq(1).click();
cy.get("input[id^='headlessui-combobox-input-v-']").type(randomEmail);
cy.get("div").contains(randomEmail).click();
cy.get("button").contains("Submit").click();
// Verify Seat Count
cy.get("span").contains("Details").click();
cy.contains("div:visible", "9 Seats Left").should("be.visible");
});
});
+24 -16
View File
@@ -1,12 +1,15 @@
describe("Course Creation", () => {
it("creates a new course", () => {
cy.login();
cy.wait(1000);
cy.wait(500);
cy.visit("/lms/courses");
// Close onboarding modal
cy.closeOnboardingModal();
// Create a course
cy.get("header").children().last().children().last().click();
cy.wait(1000);
cy.get("button").contains("Create").click();
cy.wait(500);
cy.url().should("include", "/courses/new/edit");
cy.get("label").contains("Title").type("Test Course");
@@ -19,12 +22,16 @@ describe("Course Creation", () => {
);
cy.fixture("profile.png", "base64").then((fileContent) => {
cy.get('input[type="file"]').attachFile({
fileContent,
fileName: "profile.png",
mimeType: "image/png",
encoding: "base64",
});
cy.get("div")
.contains("Course Image")
.siblings("div")
.children('input[type="file"]')
.attachFile({
fileContent,
fileName: "profile.png",
mimeType: "image/png",
encoding: "base64",
});
});
cy.get("label")
@@ -69,7 +76,7 @@ describe("Course Creation", () => {
cy.button("Add Chapter").click();
cy.wait(1000);
cy.get("[id^=headlessui-dialog-panel-")
cy.get("[data-dismissable-layer]")
.should("be.visible")
.within(() => {
cy.get("label").contains("Title").type("Test Chapter");
@@ -84,23 +91,23 @@ describe("Course Creation", () => {
cy.wait(1000);
cy.get("label").contains("Title").type("Test Lesson");
cy.get("#content .ce-block").type(
"This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
"{enter}This is an extremely big paragraph that is meant to test the UI. This is a very long paragraph. It contains more than once sentence. Its meant to be this long as this is a UI test. Its unbearably long and I'm not sure why I'm typing this much. I'm just going to keep typing until I feel like its long enough. I think its long enough now. I'm going to stop typing now."
);
cy.button("Save").click();
// View Course
cy.wait(1000);
cy.visit("/lms");
cy.wait(500);
cy.visit("/lms/courses");
cy.closeOnboardingModal();
cy.url().should("include", "/lms/courses");
cy.get(".grid a:first").within(() => {
cy.get("div").contains("Test Course");
cy.get("div").contains(
"Test Course Short Introduction to test the UI"
);
cy.get(".course-image")
cy.get(".bg-cover")
.invoke("css", "background-image")
.should("include", "/files/profile");
});
@@ -133,9 +140,10 @@ describe("Course Creation", () => {
);
// Add Discussion
cy.get("span").contains("Community").click();
cy.button("New Question").click();
cy.wait(500);
cy.get("[id^=headlessui-dialog-panel-").within(() => {
cy.get("[data-dismissable-layer]").within(() => {
cy.get("label").contains("Title").type("Test Discussion");
cy.get("div[contenteditable=true]").invoke(
"text",
+19
View File
@@ -25,6 +25,7 @@
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
import "cypress-file-upload";
import "cypress-real-events";
Cypress.Commands.add("login", (email, password) => {
if (!email) {
@@ -37,6 +38,9 @@ Cypress.Commands.add("login", (email, password) => {
url: "/api/method/login",
method: "POST",
body: { usr: email, pwd: password },
timeout: 60000,
retryOnStatusCodeFailure: true,
retryOnNetworkFailure: true,
});
});
@@ -65,3 +69,18 @@ Cypress.Commands.add("paste", { prevSubject: true }, (subject, text) => {
element.dispatchEvent(event);
});
});
Cypress.Commands.add("closeOnboardingModal", () => {
cy.wait(500);
cy.get("body").then(($body) => {
// Check if any element with class including 'z-50' exists
if ($body.find('[class*="z-50"]').length > 0) {
cy.get('[class*="z-50"]')
.find('button:has(svg[class*="feather-x"])')
.realClick();
cy.wait(1000);
} else {
cy.log("Onboarding modal not found, skipping close.");
}
});
});
+3 -3
View File
@@ -16,9 +16,9 @@ cd frappe-bench
# Use containers instead of localhost
bench set-mariadb-host mariadb
bench set-redis-cache-host redis:6379
bench set-redis-queue-host redis:6379
bench set-redis-socketio-host redis:6379
bench set-redis-cache-host redis://redis:6379
bench set-redis-queue-host redis://redis:6379
bench set-redis-socketio-host redis://redis:6379
# Remove redis, watch from Procfile
sed -i '/redis/d' ./Procfile
+1
View File
@@ -2,4 +2,5 @@ node_modules
.DS_Store
dist
dist-ssr
dev-dist
*.local
+10
View File
@@ -0,0 +1,10 @@
/* eslint-disable */
/* prettier-ignore */
// @ts-nocheck
// noinspection JSUnusedGlobalSymbols
// Generated by unplugin-auto-import
// biome-ignore lint: disable
export {}
declare global {
}
+125
View File
@@ -0,0 +1,125 @@
/* eslint-disable */
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
// biome-ignore lint: disable
export {}
/* prettier-ignore */
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']
AssessmentPlugin: typeof import('./src/components/AssessmentPlugin.vue')['default']
Assessments: typeof import('./src/components/Assessments.vue')['default']
Assignment: typeof import('./src/components/Assignment.vue')['default']
AssignmentForm: typeof import('./src/components/Modals/AssignmentForm.vue')['default']
AudioBlock: typeof import('./src/components/AudioBlock.vue')['default']
Autocomplete: typeof import('./src/components/Controls/Autocomplete.vue')['default']
BadgeAssignmentForm: typeof import('./src/components/Settings/BadgeAssignmentForm.vue')['default']
BadgeAssignments: typeof import('./src/components/Settings/BadgeAssignments.vue')['default']
BadgeForm: typeof import('./src/components/Settings/BadgeForm.vue')['default']
Badges: typeof import('./src/components/Settings/Badges.vue')['default']
BatchCard: typeof import('./src/components/BatchCard.vue')['default']
BatchCourseModal: typeof import('./src/components/Modals/BatchCourseModal.vue')['default']
BatchCourses: typeof import('./src/components/BatchCourses.vue')['default']
BatchDashboard: typeof import('./src/components/BatchDashboard.vue')['default']
BatchFeedback: typeof import('./src/components/BatchFeedback.vue')['default']
BatchOverlay: typeof import('./src/components/BatchOverlay.vue')['default']
BatchStudentProgress: typeof import('./src/components/Modals/BatchStudentProgress.vue')['default']
BatchStudents: typeof import('./src/components/BatchStudents.vue')['default']
BrandSettings: typeof import('./src/components/Settings/BrandSettings.vue')['default']
BulkCertificates: typeof import('./src/components/Modals/BulkCertificates.vue')['default']
Categories: typeof import('./src/components/Settings/Categories.vue')['default']
CertificationLinks: typeof import('./src/components/CertificationLinks.vue')['default']
ChapterModal: typeof import('./src/components/Modals/ChapterModal.vue')['default']
ChildTable: typeof import('./src/components/Controls/ChildTable.vue')['default']
Code: typeof import('./src/components/Controls/Code.vue')['default']
CodeEditor: typeof import('./src/components/Controls/CodeEditor.vue')['default']
CollapseSidebar: typeof import('./src/components/Icons/CollapseSidebar.vue')['default']
ColorSwatches: typeof import('./src/components/Controls/ColorSwatches.vue')['default']
ContactUsEmail: typeof import('./src/components/ContactUsEmail.vue')['default']
CourseCard: typeof import('./src/components/CourseCard.vue')['default']
CourseCardOverlay: typeof import('./src/components/CourseCardOverlay.vue')['default']
CourseInstructors: typeof import('./src/components/CourseInstructors.vue')['default']
CourseOutline: typeof import('./src/components/CourseOutline.vue')['default']
CourseProgressSummary: typeof import('./src/components/Modals/CourseProgressSummary.vue')['default']
CourseReviews: typeof import('./src/components/CourseReviews.vue')['default']
CreateOutline: typeof import('./src/components/CreateOutline.vue')['default']
DateRange: typeof import('./src/components/Common/DateRange.vue')['default']
DesktopLayout: typeof import('./src/components/DesktopLayout.vue')['default']
DiscussionModal: typeof import('./src/components/Modals/DiscussionModal.vue')['default']
DiscussionReplies: typeof import('./src/components/DiscussionReplies.vue')['default']
Discussions: typeof import('./src/components/Discussions.vue')['default']
EditCoverImage: typeof import('./src/components/Modals/EditCoverImage.vue')['default']
EditProfile: typeof import('./src/components/Modals/EditProfile.vue')['default']
EmailTemplateModal: typeof import('./src/components/Modals/EmailTemplateModal.vue')['default']
EmailTemplates: typeof import('./src/components/Settings/EmailTemplates.vue')['default']
EmptyState: typeof import('./src/components/EmptyState.vue')['default']
EvaluationModal: typeof import('./src/components/Modals/EvaluationModal.vue')['default']
Evaluators: typeof import('./src/components/Settings/Evaluators.vue')['default']
Event: typeof import('./src/components/Modals/Event.vue')['default']
ExplanationVideos: typeof import('./src/components/Modals/ExplanationVideos.vue')['default']
FeedbackModal: typeof import('./src/components/Modals/FeedbackModal.vue')['default']
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
IconPicker: typeof import('./src/components/Controls/IconPicker.vue')['default']
IndicatorIcon: typeof import('./src/components/Icons/IndicatorIcon.vue')['default']
InlineLessonMenu: typeof import('./src/components/Notes/InlineLessonMenu.vue')['default']
InstallPrompt: typeof import('./src/components/InstallPrompt.vue')['default']
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']
LiveClass: typeof import('./src/components/LiveClass.vue')['default']
LiveClassAttendance: typeof import('./src/components/Modals/LiveClassAttendance.vue')['default']
LiveClassModal: typeof import('./src/components/Modals/LiveClassModal.vue')['default']
LMSLogo: typeof import('./src/components/Icons/LMSLogo.vue')['default']
Members: typeof import('./src/components/Settings/Members.vue')['default']
MobileLayout: typeof import('./src/components/MobileLayout.vue')['default']
MultiSelect: typeof import('./src/components/Controls/MultiSelect.vue')['default']
NoPermission: typeof import('./src/components/NoPermission.vue')['default']
NoSidebarLayout: typeof import('./src/components/NoSidebarLayout.vue')['default']
Notes: typeof import('./src/components/Notes/Notes.vue')['default']
NotPermitted: typeof import('./src/components/NotPermitted.vue')['default']
PageModal: typeof import('./src/components/Modals/PageModal.vue')['default']
PaymentGatewayDetails: typeof import('./src/components/Settings/PaymentGatewayDetails.vue')['default']
PaymentGateways: typeof import('./src/components/Settings/PaymentGateways.vue')['default']
Play: typeof import('./src/components/Icons/Play.vue')['default']
ProgressBar: typeof import('./src/components/ProgressBar.vue')['default']
Question: typeof import('./src/components/Modals/Question.vue')['default']
Quiz: typeof import('./src/components/Quiz.vue')['default']
QuizBlock: typeof import('./src/components/QuizBlock.vue')['default']
QuizInVideo: typeof import('./src/components/Modals/QuizInVideo.vue')['default']
Rating: typeof import('./src/components/Controls/Rating.vue')['default']
RelatedCourses: typeof import('./src/components/RelatedCourses.vue')['default']
ReviewModal: typeof import('./src/components/Modals/ReviewModal.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SettingDetails: typeof import('./src/components/Settings/SettingDetails.vue')['default']
SettingFields: typeof import('./src/components/Settings/SettingFields.vue')['default']
Settings: typeof import('./src/components/Settings/Settings.vue')['default']
SidebarLink: typeof import('./src/components/SidebarLink.vue')['default']
StudentHeatmap: typeof import('./src/components/StudentHeatmap.vue')['default']
StudentModal: typeof import('./src/components/Modals/StudentModal.vue')['default']
Tags: typeof import('./src/components/Tags.vue')['default']
TransactionDetails: typeof import('./src/components/Settings/TransactionDetails.vue')['default']
Transactions: typeof import('./src/components/Settings/Transactions.vue')['default']
UnsplashImageBrowser: typeof import('./src/components/UnsplashImageBrowser.vue')['default']
UpcomingEvaluations: typeof import('./src/components/UpcomingEvaluations.vue')['default']
Uploader: typeof import('./src/components/Controls/Uploader.vue')['default']
UploadPlugin: typeof import('./src/components/UploadPlugin.vue')['default']
UserAvatar: typeof import('./src/components/UserAvatar.vue')['default']
UserDropdown: typeof import('./src/components/UserDropdown.vue')['default']
VideoBlock: typeof import('./src/components/VideoBlock.vue')['default']
VideoStatistics: typeof import('./src/components/Modals/VideoStatistics.vue')['default']
ZoomAccountModal: typeof import('./src/components/Modals/ZoomAccountModal.vue')['default']
ZoomSettings: typeof import('./src/components/Settings/ZoomSettings.vue')['default']
}
}
+200 -18
View File
@@ -2,9 +2,206 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="{{ favicon or '/assets/lms/frontend/favicon.png' }}" />
<link rel="icon" href="{{ favicon }}" />
<link rel="manifest" href="/api/method/lms.lms.api.get_pwa_manifest" />
<link rel="apple-touch-icon" href="public/manifest/apple-icon-180.png" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="theme-color" content="#FFFFFF" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#0F0F0F" media="(prefers-color-scheme: dark)" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="msapplication-navbutton-color" content="#ffffff" />
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2048-2732.jpg"
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2732-2048.jpg"
media="(device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1668-2388.jpg"
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2388-1668.jpg"
media="(device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1536-2048.jpg"
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2048-1536.jpg"
media="(device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1640-2360.jpg"
media="(device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2360-1640.jpg"
media="(device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1668-2224.jpg"
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2224-1668.jpg"
media="(device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1620-2160.jpg"
media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2160-1620.jpg"
media="(device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1488-2266.jpg"
media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2266-1488.jpg"
media="(device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1320-2868.jpg"
media="(device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2868-1320.jpg"
media="(device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1206-2622.jpg"
media="(device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2622-1206.jpg"
media="(device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1290-2796.jpg"
media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2796-1290.jpg"
media="(device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1179-2556.jpg"
media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2556-1179.jpg"
media="(device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1170-2532.jpg"
media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2532-1170.jpg"
media="(device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1284-2778.jpg"
media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2778-1284.jpg"
media="(device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1125-2436.jpg"
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2436-1125.jpg"
media="(device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1242-2688.jpg"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2688-1242.jpg"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-828-1792.jpg"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1792-828.jpg"
media="(device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1242-2208.jpg"
media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-2208-1242.jpg"
media="(device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-750-1334.jpg"
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1334-750.jpg"
media="(device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-640-1136.jpg"
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
/>
<link
rel="apple-touch-startup-image"
href="public/manifest/apple-splash-1136-640.jpg"
media="(device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Frappe Learning</title>
<title>{{ title }}</title>
<meta name="title" content="{{ meta.title }}" />
<meta name="image" content="{{ meta.image }}" />
<meta name="description" content="{{ meta.description }}" />
@@ -16,32 +213,17 @@
<meta name="twitter:image" content="{{ meta.image }}" />
<meta name="twitter:description" content="{{ meta.description }}" />
</head>
<body>
<body class="sm:overscroll-y-none no-scrollbar">
<div id="app">
<div id="seo-content">
<h1>{{ meta.title }}</h1>
<p>
{{ meta.description }}
</p>
<p>
The content here is just for seo purposes. The actual content will be loaded in a few seconds.
</p>
<p>
Seo checks if a page has more than 300 words. So, here are some more words to make it more than 300 words.
Page descriptions are the HTML meta tags that provide a brief summary of a web page.
Search engines use meta descriptions to help identify the page's topic - they don't use them to rank the page, but they do use them to determine whether or not to display the page in search results.
Meta descriptions are important because they're often the first thing people see when they're deciding which search result to click on.
They're also important because they can help improve your click-through rate (CTR) from search results.
A good meta description can entice people to click on your page instead of someone else's.
</p>
<a href="{{ meta.link }}">Know More</a>
</div>
</div>
<div id="modals"></div>
<div id="popovers"></div>
<script>
window.csrf_token = '{{ csrf_token }}'
document.getElementById('seo-content').style.display = 'none';
</script>
<script type="module" src="/src/main.js"></script>
+16 -4
View File
@@ -2,6 +2,7 @@
"name": "frappe-ui-frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"serve": "vite preview",
@@ -9,6 +10,10 @@
"copy-html-entry": "cp ../lms/public/frontend/index.html ../lms/www/lms.html"
},
"dependencies": {
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.4",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-python": "^6.2.1",
"@editorjs/checklist": "^1.6.0",
"@editorjs/code": "^2.9.0",
"@editorjs/editorjs": "^2.29.0",
@@ -19,21 +24,27 @@
"@editorjs/paragraph": "^2.11.3",
"@editorjs/simple-image": "^1.6.0",
"@editorjs/table": "^2.4.2",
"@vueuse/router": "^12.7.0",
"ace-builds": "^1.36.2",
"apexcharts": "^4.3.0",
"chart.js": "^4.4.1",
"codemirror-editor-vue3": "^2.8.0",
"codemirror": "^6.0.1",
"dayjs": "^1.11.6",
"dompurify": "^3.2.6",
"feather-icons": "^4.28.0",
"frappe-ui": "^0.1.109",
"frappe-ui": "^0.1.201",
"highlight.js": "^11.11.1",
"lucide-vue-next": "^0.383.0",
"markdown-it": "^14.0.0",
"pinia": "^2.0.33",
"plyr": "^3.7.8",
"socket.io-client": "^4.7.2",
"tailwindcss": "^3.3.3",
"tailwindcss": "3.4.15",
"thememirror": "^2.0.1",
"typescript": "^5.7.2",
"vue": "^3.4.23",
"vue-chartjs": "^5.3.0",
"vue-codemirror": "^6.1.1",
"vue-draggable-next": "^2.2.1",
"vue-router": "^4.0.12",
"vue3-apexcharts": "^1.8.0",
@@ -43,6 +54,7 @@
"@vitejs/plugin-vue": "^5.0.3",
"autoprefixer": "^10.4.2",
"postcss": "^8.4.5",
"vite": "^5.0.11"
"vite": "^5.0.11",
"vite-plugin-pwa": "^1.0.2"
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
module.exports = {
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

@@ -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

+2
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

+4
View File
@@ -0,0 +1,4 @@
<svg width="80" height="79" viewBox="0 0 80 79" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M57.1285 0.580383H22.8514C10.2309 0.580383 0 10.5649 0 22.8815V56.3332C0 68.6497 10.2309 78.6343 22.8514 78.6343H57.1285C69.749 78.6343 79.9799 68.6497 79.9799 56.3332V22.8815C79.9799 10.5649 69.749 0.580383 57.1285 0.580383Z" fill="#0E7159"/>
<path d="M62.8434 23.6906L60.7869 23.1052C53.6744 21.0702 45.9048 22.4641 39.992 26.8128C35.8502 23.7742 30.7943 22.1854 25.7099 22.2133H17.1406V27.8163H25.7099C29.6232 27.8163 33.508 29.015 36.6787 31.3845L39.992 33.8377L43.3056 31.3845C47.2475 28.4575 52.3032 27.2588 57.1306 28.0393V50.647C51.1035 49.9223 44.9051 51.4834 39.992 55.0795C35.8502 52.0688 30.8515 50.4798 25.7671 50.4798C24.7959 50.4798 23.8247 50.5355 22.8535 50.647V35.0642H17.1406V57.0588H62.8434V23.7185V23.6906Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+38 -20
View File
@@ -1,38 +1,56 @@
<template>
<Layout>
<router-view />
</Layout>
<Dialogs />
<Toasts />
<FrappeUIProvider>
<Layout class="isolate text-base">
<router-view />
</Layout>
<!--<InstallPrompt v-if="isMobile" />-->
<Dialogs />
</FrappeUIProvider>
</template>
<script setup>
import { Toasts } from 'frappe-ui'
import { FrappeUIProvider } from 'frappe-ui'
import { Dialogs } from '@/utils/dialogs'
import { computed, onMounted, onUnmounted } from 'vue'
import { computed, onUnmounted, ref, watch } from 'vue'
import { useScreenSize } from './utils/composables'
import { usersStore } from '@/stores/user'
import { useRouter } from 'vue-router'
import { posthogSettings } from '@/telemetry'
import DesktopLayout from './components/DesktopLayout.vue'
import MobileLayout from './components/MobileLayout.vue'
import { stopSession } from '@/telemetry'
import { init as initTelemetry } from '@/telemetry'
import { usersStore } from '@/stores/user'
import NoSidebarLayout from './components/NoSidebarLayout.vue'
import InstallPrompt from './components/InstallPrompt.vue'
const screenSize = useScreenSize()
let { userResource } = usersStore()
const { isMobile } = useScreenSize()
const router = useRouter()
const noSidebar = ref(false)
const { userResource } = usersStore()
const Layout = computed(() => {
if (screenSize.width < 640) {
return MobileLayout
router.beforeEach((to, from, next) => {
if (to.query.fromLesson || to.path === '/persona') {
noSidebar.value = true
} else {
return DesktopLayout
noSidebar.value = false
}
next()
})
onMounted(async () => {
if (!userResource.data) return
await initTelemetry()
const Layout = computed(() => {
if (noSidebar.value) {
return NoSidebarLayout
}
if (isMobile.value) {
return MobileLayout
}
return DesktopLayout
})
onUnmounted(() => {
stopSession()
noSidebar.value = false
})
watch(userResource, () => {
if (userResource.data) {
posthogSettings.reload()
}
})
</script>
+587 -81
View File
@@ -9,12 +9,12 @@
>
<UserDropdown :isCollapsed="sidebarStore.isSidebarCollapsed" />
<div class="flex flex-col" v-if="sidebarSettings.data">
<SidebarLink
v-for="link in sidebarLinks"
:link="link"
:isCollapsed="sidebarStore.isSidebarCollapsed"
class="mx-2 my-0.5"
/>
<div v-for="link in sidebarLinks" class="mx-2 my-0.5">
<SidebarLink
:link="link"
:isCollapsed="sidebarStore.isSidebarCollapsed"
/>
</div>
</div>
<div
v-if="sidebarSettings.data?.web_pages?.length || isModerator"
@@ -39,7 +39,11 @@
{{ __('More') }}
</span>
</div>
<Button v-if="isModerator" variant="ghost" @click="openPageModal()">
<Button
v-if="isModerator && !readOnlyMode"
variant="ghost"
@click="openPageModal()"
>
<template #icon>
<Plus class="h-4 w-4 text-ink-gray-7 stroke-1.5" />
</template>
@@ -50,37 +54,124 @@
class="flex flex-col transition-all duration-300 ease-in-out"
:class="!sidebarStore.isWebpagesCollapsed ? 'block' : 'hidden'"
>
<SidebarLink
<div
v-for="link in sidebarSettings.data.web_pages"
:link="link"
:isCollapsed="sidebarStore.isSidebarCollapsed"
class="mx-2 my-0.5"
:showControls="isModerator ? true : false"
@openModal="openPageModal"
@deletePage="deletePage"
/>
>
<SidebarLink
:link="link"
:isCollapsed="sidebarStore.isSidebarCollapsed"
:showControls="isModerator ? true : false"
@openModal="openPageModal"
@deletePage="deletePage"
/>
</div>
</div>
</div>
</div>
<SidebarLink
:link="{
label: sidebarStore.isSidebarCollapsed ? 'Expand' : 'Collapse',
}"
:isCollapsed="sidebarStore.isSidebarCollapsed"
@click="toggleSidebar()"
class="m-2"
>
<template #icon>
<span class="grid h-5 w-6 flex-shrink-0 place-items-center">
<div class="m-2 flex flex-col gap-1">
<div
v-if="readOnlyMode && !sidebarStore.isSidebarCollapsed"
class="z-10 m-2 bg-surface-modal py-2.5 px-3 text-xs text-ink-gray-7 leading-5 rounded-md"
>
{{
__(
'This site is being updated. You will not be able to make any changes. Full access will be restored shortly.'
)
}}
</div>
<TrialBanner
v-if="
userResource.data?.is_system_manager && userResource.data?.is_fc_site
"
:isSidebarCollapsed="sidebarStore.isSidebarCollapsed"
/>
<GettingStartedBanner
v-if="showOnboarding && !isOnboardingStepsCompleted"
:isSidebarCollapsed="sidebarStore.isSidebarCollapsed"
appName="learning"
/>
<div
class="flex items-center mt-4"
:class="
sidebarStore.isSidebarCollapsed ? 'flex-col space-y-3' : 'flex-row'
"
>
<div
class="flex items-center flex-1"
:class="
sidebarStore.isSidebarCollapsed
? 'flex-col space-y-3'
: 'flex-row space-x-3'
"
>
<Tooltip v-if="readOnlyMode && sidebarStore.isSidebarCollapsed">
<CircleAlert
class="size-4 stroke-1.5 text-ink-gray-7 cursor-pointer"
/>
<template #body>
<div
class="max-w-[30ch] rounded bg-surface-gray-7 px-2 py-1 text-center text-p-xs text-ink-white shadow-xl"
>
{{
__(
'This site is being updated. You will not be able to make any changes. Full access will be restored shortly.'
)
}}
</div>
</template>
</Tooltip>
<Tooltip :text="__('Powered by Learning')">
<Zap
class="size-4 stroke-1.5 text-ink-gray-7 cursor-pointer"
@click="redirectToWebsite()"
/>
</Tooltip>
<Tooltip v-if="showOnboarding" :text="__('Help')">
<CircleHelp
class="size-4 stroke-1.5 text-ink-gray-7 cursor-pointer"
@click="
() => {
showHelpModal = minimize ? true : !showHelpModal
minimize = !showHelpModal
}
"
/>
</Tooltip>
</div>
<Tooltip
:text="
sidebarStore.isSidebarCollapsed ? __('Expand') : __('Collapse')
"
>
<CollapseSidebar
class="h-4.5 w-4.5 text-ink-gray-7 duration-300 ease-in-out"
class="size-4 text-ink-gray-7 duration-300 stroke-1.5 ease-in-out cursor-pointer"
:class="{
'[transform:rotateY(180deg)]': sidebarStore.isSidebarCollapsed,
}"
@click="toggleSidebar()"
/>
</span>
</template>
</SidebarLink>
</Tooltip>
</div>
</div>
<HelpModal
v-if="showOnboarding && showHelpModal"
v-model="showHelpModal"
v-model:articles="articles"
appName="learning"
title="Frappe Learning"
:logo="LMSLogo"
:afterSkip="(step) => capture('onboarding_step_skipped_' + step)"
:afterSkipAll="() => capture('onboarding_steps_skipped')"
:afterReset="(step) => capture('onboarding_step_reset_' + step)"
:afterResetAll="() => capture('onboarding_steps_reset')"
docsLink="https://docs.frappe.io/learning"
/>
<IntermediateStepModal
v-model="showIntermediateModal"
:currentStep="currentStep"
/>
</div>
<PageModal
v-model="showPageModal"
@@ -93,18 +184,52 @@
import UserDropdown from '@/components/UserDropdown.vue'
import CollapseSidebar from '@/components/Icons/CollapseSidebar.vue'
import SidebarLink from '@/components/SidebarLink.vue'
import { useStorage } from '@vueuse/core'
import { ref, onMounted, inject, watch } from 'vue'
import { getSidebarLinks } from '../utils'
import {
ref,
onMounted,
inject,
watch,
reactive,
markRaw,
h,
onUnmounted,
} from 'vue'
import { getSidebarLinks } from '@/utils'
import { usersStore } from '@/stores/user'
import { sessionStore } from '@/stores/session'
import { useSidebar } from '@/stores/sidebar'
import { useSettings } from '@/stores/settings'
import { ChevronRight, Plus } from 'lucide-vue-next'
import { createResource, Button } from 'frappe-ui'
import { Button, call, createResource, Tooltip } from 'frappe-ui'
import PageModal from '@/components/Modals/PageModal.vue'
import { capture } from '@/telemetry'
import LMSLogo from '@/components/Icons/LMSLogo.vue'
import { useRouter } from 'vue-router'
import InviteIcon from './Icons/InviteIcon.vue'
import {
BookOpen,
CircleAlert,
ChevronRight,
Plus,
CircleHelp,
FolderTree,
FileText,
UserPlus,
Users,
BookText,
Zap,
Check,
} from 'lucide-vue-next'
import {
TrialBanner,
HelpModal,
GettingStartedBanner,
useOnboarding,
showHelpModal,
minimize,
IntermediateStepModal,
} from 'frappe-ui/frappe'
const { user, sidebarSettings } = sessionStore()
const { user } = sessionStore()
const { userResource } = usersStore()
let sidebarStore = useSidebar()
const socket = inject('$socket')
@@ -115,12 +240,30 @@ const isModerator = ref(false)
const isInstructor = ref(false)
const pageToEdit = ref(null)
const settingsStore = useSettings()
const { sidebarSettings } = settingsStore
const showOnboarding = ref(false)
const showIntermediateModal = ref(false)
const currentStep = ref({})
const router = useRouter()
let onboardingDetails
let isOnboardingStepsCompleted = false
const readOnlyMode = window.read_only_mode
const iconProps = {
strokeWidth: 1.5,
width: 16,
height: 16,
}
onMounted(() => {
addNotifications()
setSidebarLinks()
setUpOnboarding()
socket.on('publish_lms_notifications', (data) => {
unreadNotifications.reload()
})
addNotifications()
})
const setSidebarLinks = () => {
sidebarSettings.reload(
{},
{
@@ -135,7 +278,7 @@ onMounted(() => {
},
}
)
})
}
const unreadNotifications = createResource({
cache: 'Unread Notifications Count',
@@ -175,57 +318,95 @@ const addNotifications = () => {
const addQuizzes = () => {
if (isInstructor.value || isModerator.value) {
sidebarLinks.value.push({
sidebarLinks.value.splice(4, 0, {
label: 'Quizzes',
icon: 'CircleHelp',
to: 'Quizzes',
activeFor: ['Quizzes', 'QuizForm'],
activeFor: [
'Quizzes',
'QuizForm',
'QuizSubmissionList',
'QuizSubmission',
],
})
}
}
const addAssignments = () => {
if (isInstructor.value || isModerator.value) {
sidebarLinks.value.push({
sidebarLinks.value.splice(5, 0, {
label: 'Assignments',
icon: 'Pencil',
to: 'Assignments',
activeFor: ['Assignments', 'AssignmentForm'],
activeFor: [
'Assignments',
'AssignmentForm',
'AssignmentSubmissionList',
'AssignmentSubmission',
],
})
}
}
const addPrograms = () => {
let activeFor = ['Programs', 'ProgramForm']
let index = 1
let canAddProgram = false
if (
!isInstructor.value &&
!isModerator.value &&
settingsStore.learningPaths.data
) {
sidebarLinks.value = sidebarLinks.value.filter(
(link) => link.label !== 'Courses'
)
activeFor.push('CourseDetail')
activeFor.push('Lesson')
index = 0
canAddProgram = true
} else if (isInstructor.value || isModerator.value) {
canAddProgram = true
}
if (canAddProgram) {
sidebarLinks.value.splice(index, 0, {
label: 'Programs',
icon: 'Route',
to: 'Programs',
activeFor: activeFor,
const addProgrammingExercises = () => {
if (isInstructor.value || isModerator.value) {
sidebarLinks.value.splice(3, 0, {
label: 'Programming Exercises',
icon: 'Code',
to: 'ProgrammingExercises',
activeFor: [
'ProgrammingExercises',
'ProgrammingExerciseForm',
'ProgrammingExerciseSubmissions',
'ProgrammingExerciseSubmission',
],
})
}
}
const addPrograms = async () => {
let canAddProgram = await checkIfCanAddProgram()
if (!canAddProgram) return
let activeFor = ['Programs', 'ProgramDetail']
let index = 2
sidebarLinks.value.splice(index, 0, {
label: 'Programs',
icon: 'Route',
to: 'Programs',
activeFor: activeFor,
})
}
const addContactUsDetails = () => {
if (settingsStore.contactUsEmail?.data || settingsStore.contactUsURL?.data) {
sidebarLinks.value.push({
label: 'Contact Us',
icon: settingsStore.contactUsURL?.data ? 'Headset' : 'Mail',
to: settingsStore.contactUsURL?.data
? settingsStore.contactUsURL.data
: settingsStore.contactUsEmail?.data,
})
}
}
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
}
const addHome = () => {
sidebarLinks.value.unshift({
label: 'Home',
icon: 'Home',
to: 'Home',
activeFor: ['Home'],
})
}
const openPageModal = (link) => {
showPageModal.value = true
pageToEdit.value = link
@@ -249,20 +430,6 @@ const deletePage = (link) => {
)
}
const getSidebarFromStorage = () => {
return useStorage('sidebar_is_collapsed', false)
}
watch(userResource, () => {
if (userResource.data) {
isModerator.value = userResource.data.is_moderator
isInstructor.value = userResource.data.is_instructor
addPrograms()
addQuizzes()
addAssignments()
}
})
const toggleSidebar = () => {
sidebarStore.isSidebarCollapsed = !sidebarStore.isSidebarCollapsed
localStorage.setItem(
@@ -278,4 +445,343 @@ const toggleWebPages = () => {
JSON.stringify(sidebarStore.isWebpagesCollapsed)
)
}
const getFirstCourse = async () => {
let firstCourse = localStorage.getItem('firstCourse')
if (firstCourse) return firstCourse
return await call('lms.lms.onboarding.get_first_course')
}
const getFirstBatch = async () => {
let firstBatch = localStorage.getItem('firstBatch')
if (firstBatch) return firstBatch
return await call('lms.lms.onboarding.get_first_batch')
}
const steps = reactive([
{
name: 'create_first_course',
title: __('Create your first course'),
icon: markRaw(h(BookOpen, iconProps)),
completed: false,
onClick: () => {
minimize.value = true
router.push({
name: 'Courses',
})
},
},
{
name: 'create_first_chapter',
title: __('Add your first chapter'),
icon: markRaw(h(FolderTree, iconProps)),
completed: false,
dependsOn: 'create_first_course',
onClick: async () => {
minimize.value = true
let course = await getFirstCourse()
if (course) {
router.push({ name: 'CourseForm', params: { courseName: course } })
} else {
router.push({ name: 'CourseForm' })
}
},
},
{
name: 'create_first_lesson',
title: __('Add your first lesson'),
icon: markRaw(h(FileText, iconProps)),
completed: false,
dependsOn: 'create_first_chapter',
onClick: async () => {
minimize.value = true
let course = await getFirstCourse()
if (course) {
router.push({
name: 'CourseForm',
params: { courseName: course },
})
} else {
router.push({ name: 'Courses' })
}
},
},
{
name: 'create_first_quiz',
title: __('Create your first quiz'),
icon: markRaw(h(CircleHelp, iconProps)),
completed: false,
dependsOn: 'create_first_course',
onClick: () => {
minimize.value = true
router.push({ name: 'Quizzes' })
},
},
{
name: 'invite_students',
title: __('Invite your team and students'),
icon: markRaw(h(InviteIcon, iconProps)),
completed: false,
onClick: () => {
minimize.value = true
settingsStore.activeTab = 'Members'
settingsStore.isSettingsOpen = true
},
},
{
name: 'create_first_batch',
title: __('Create your first batch'),
icon: markRaw(h(Users, iconProps)),
completed: false,
onClick: () => {
minimize.value = true
router.push({ name: 'Batches' })
},
},
{
name: 'add_batch_student',
title: __('Add students to your batch'),
icon: markRaw(h(UserPlus, iconProps)),
completed: false,
dependsOn: 'create_first_batch',
onClick: async () => {
minimize.value = true
let batch = await getFirstBatch()
if (batch) {
router.push({
name: 'Batch',
params: {
batchName: batch,
},
})
} else {
router.push({ name: 'Batch' })
}
},
},
{
name: 'add_batch_course',
title: __('Add courses to your batch'),
icon: markRaw(h(BookText, iconProps)),
completed: false,
dependsOn: 'create_first_batch',
onClick: async () => {
minimize.value = true
let batch = await getFirstBatch()
if (batch) {
router.push({
name: 'Batch',
params: {
batchName: batch,
},
hash: '#courses',
})
} else {
router.push({ name: 'Batch' })
}
},
},
])
const articles = ref([
{
title: __('Introduction'),
opened: false,
subArticles: [
{ name: 'introduction', title: __('Introduction') },
{ name: 'setting-up', title: __('Setting up') },
],
},
{
title: __('Creating a course'),
opened: false,
subArticles: [
{ name: 'create-a-course', title: __('Create a course') },
{ name: 'add-a-chapter', title: __('Add a chapter') },
{ name: 'add-a-lesson', title: __('Add a lesson') },
],
},
{
title: __('Creating a batch'),
opened: false,
subArticles: [
{ name: 'create-a-batch', title: __('Create a batch') },
{ name: 'create-a-live-class', title: __('Create a live class') },
],
},
{
title: __('Learning Paths'),
opened: false,
subArticles: [{ name: 'add-a-program', title: __('Add a program') }],
},
{
title: __('Assessments'),
opened: false,
subArticles: [
{ name: 'quizzes', title: __('Quizzes') },
{ name: 'assignments', title: __('Assignments') },
],
},
{
title: __('Certification'),
opened: false,
subArticles: [
{ name: 'issue-a-certificate', title: __('Issue a Certificate') },
{
name: 'custom-certificate-templates',
title: __('Custom Certificate Templates'),
},
],
},
{
title: __('Monetization'),
opened: false,
subArticles: [
{
name: 'setting-up-payment-gateway',
title: __('Setting up payment gateway'),
},
],
},
{
title: __('Settings'),
opened: false,
subArticles: [{ name: 'roles', title: __('Roles') }],
},
])
const setUpOnboarding = () => {
if (userResource.data?.is_system_manager) {
onboardingDetails = useOnboarding('learning')
onboardingDetails.setUp(steps)
isOnboardingStepsCompleted = onboardingDetails.isOnboardingStepsCompleted
showOnboarding.value = true
}
}
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) {
isModerator.value = userResource.data.is_moderator
isInstructor.value = userResource.data.is_instructor
addHome()
addPrograms()
addProgrammingExercises()
addQuizzes()
addAssignments()
setUpOnboarding()
addMyPoints()
addLeaderBoard()
addChatGPT()
addMyChild()
addProfile()
}
})
const redirectToWebsite = () => {
window.open('https://frappe.io/learning', '_blank')
}
onUnmounted(() => {
socket.off('publish_lms_notifications')
})
</script>
+1 -1
View File
@@ -3,7 +3,7 @@
<template #target="{ togglePopover }">
<button
:class="[
'group w-full flex h-7 items-center justify-between rounded px-2 text-base text-ink-gray-8 hover:bg-surface-gray-2',
'group w-full flex h-7 items-center justify-between rounded px-2 text-base text-ink-gray-7 hover:bg-surface-gray-2',
]"
@click.prevent="togglePopover()"
>
+16 -14
View File
@@ -2,17 +2,24 @@
<Dialog
v-model="show"
:options="{
title:
type == 'quiz'
? __('Add a quiz to your lesson')
: __('Add an assignment to your lesson'),
size: 'xl',
actions: [
{
label: __('Save'),
variant: 'solid',
onClick: () => {
addAssessment()
},
},
],
}"
>
<template #body>
<div class="p-5 space-y-4">
<div v-if="type == 'quiz'" class="text-lg font-semibold">
{{ __('Add a quiz to your lesson') }}
</div>
<div v-else class="text-lg font-semibold">
{{ __('Add an assignment to your lesson') }}
</div>
<template #body-content>
<div class="">
<div>
<Link
v-if="type == 'quiz'"
@@ -29,17 +36,12 @@
:onCreate="(value, close) => redirectToForm()"
/>
</div>
<div class="flex justify-end space-x-2">
<Button variant="solid" @click="addAssessment()">
{{ __('Save') }}
</Button>
</div>
</div>
</template>
</Dialog>
</template>
<script setup>
import { Dialog, Button } from 'frappe-ui'
import { Dialog } from 'frappe-ui'
import { onMounted, ref, nextTick } from 'vue'
import Link from '@/components/Controls/Link.vue'
+34 -4
View File
@@ -4,7 +4,7 @@
<div class="text-lg font-semibold text-ink-gray-9">
{{ __('Assessments') }}
</div>
<Button v-if="canSeeAddButton()" @click="showModal = true">
<Button v-if="canAddAssessments()" @click="showModal = true">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
@@ -40,7 +40,7 @@
<template #default="{ column, item }">
<ListRowItem :item="row[column.key]" :align="column.align">
<div v-if="column.key == 'assessment_type'">
{{ row[column.key] == 'LMS Quiz' ? 'Quiz' : 'Assignment' }}
{{ getAssessmentTypeLabel(row[column.key]) }}
</div>
<div v-else-if="column.key == 'title'">
{{ row[column.key] }}
@@ -100,6 +100,7 @@ import { Plus, Trash2 } from 'lucide-vue-next'
const user = inject('$user')
const showModal = ref(false)
const readOnlyMode = window.read_only_mode
const props = defineProps({
batch: {
@@ -171,6 +172,24 @@ const getRowRoute = (row) => {
},
}
}
} else if (row.assessment_type == 'LMS Programming Exercise') {
if (row.submission) {
return {
name: 'ProgrammingExerciseSubmission',
params: {
exerciseID: row.assessment_name,
submissionID: row.submission.name,
},
}
} else {
return {
name: 'ProgrammingExerciseSubmission',
params: {
exerciseID: row.assessment_name,
submissionID: 'new',
},
}
}
} else {
return {
name: 'QuizPage',
@@ -181,7 +200,8 @@ const getRowRoute = (row) => {
}
}
const canSeeAddButton = () => {
const canAddAssessments = () => {
if (readOnlyMode) return false
return user.data?.is_moderator || user.data?.is_evaluator
}
@@ -211,7 +231,7 @@ const getAssessmentColumns = () => {
}
const getStatusTheme = (status) => {
if (status === 'Pass') {
if (status === 'Pass' || status === 'Passed') {
return 'green'
} else if (status === 'Not Graded') {
return 'orange'
@@ -219,4 +239,14 @@ const getStatusTheme = (status) => {
return 'red'
}
}
const getAssessmentTypeLabel = (type) => {
if (type == 'LMS Assignment') {
return __('Assignment')
} else if (type == 'LMS Quiz') {
return __('Quiz')
} else if (type == 'LMS Programming Exercise') {
return __('Programming Exercise')
}
}
</script>
+56 -23
View File
@@ -1,10 +1,13 @@
<template>
<div
v-if="assignment.data"
class="grid grid-cols-[68%,32%] h-full"
:class="{ 'border rounded-lg': !showTitle }"
class="grid grid-cols-2 h-full"
:class="{ 'border rounded-lg overflow-auto': !showTitle }"
>
<div class="border-r p-5 overflow-y-auto h-[calc(100vh-3.2rem)]">
<div
class="border-r p-5 overflow-y-auto h-[calc(100vh-3.2rem)]"
:class="{ 'h-full': !showTitle }"
>
<div v-if="showTitle" class="text-lg font-semibold mb-5 text-ink-gray-9">
<div v-if="submissionName === 'new'">
{{ __('Submission by') }} {{ user.data?.full_name }}
@@ -50,7 +53,7 @@
!['Pass', 'Fail'].includes(submissionResource.doc?.status) &&
submissionResource.doc?.owner == user.data?.name
"
class="bg-surface-blue-2 p-3 rounded-md leading-5 text-sm mb-4"
class="bg-surface-blue-2 text-ink-blue-2 p-3 rounded-md leading-5 text-sm mb-4"
>
{{ __("You've successfully submitted the assignment.") }}
{{
@@ -67,6 +70,9 @@
<FileUploader
v-if="!submissionFile"
:fileTypes="getType()"
:uploadArgs="{
private: true,
}"
:validateFile="validateFile"
@success="(file) => saveSubmission(file)"
>
@@ -81,8 +87,8 @@
</template>
</FileUploader>
<div v-else>
<div class="flex items-center text-ink-gray-7">
<div class="border rounded-md p-2 mr-2">
<div class="flex text-ink-gray-7">
<div class="border self-start rounded-md p-2 mr-2">
<FileText class="h-5 w-5 stroke-1.5" />
</div>
<a
@@ -90,7 +96,7 @@
target="_blank"
class="flex flex-col cursor-pointer !no-underline"
>
<span>
<span class="text-sm leading-5">
{{ submissionFile.file_name }}
</span>
<span class="text-sm text-ink-gray-5 mt-1">
@@ -116,7 +122,7 @@
/>
</div>
<div v-else>
<div class="text-sm mb-4">
<div class="text-sm mb-2 text-ink-gray-7">
{{ __('Write your answer here') }}
</div>
<TextEditor
@@ -124,6 +130,9 @@
@change="(val) => (answer = val)"
:editable="true"
:fixedMenu="true"
:uploadArgs="{
private: true,
}"
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
/>
</div>
@@ -138,9 +147,10 @@
<div class="text-sm text-ink-gray-5 font-medium mb-2">
{{ __('Comments by Evaluator') }}:
</div>
<div class="leading-5">
{{ submissionResource.doc.comments }}
</div>
<div
class="leading-5 text-ink-gray-9"
v-html="submissionResource.doc.comments"
></div>
</div>
<!-- Grading -->
@@ -155,12 +165,23 @@
type="select"
:options="submissionStatusOptions"
/>
<FormControl
v-if="submissionResource.doc"
v-model="submissionResource.doc.comments"
:label="__('Comments')"
type="textarea"
/>
<div>
<div class="text-sm text-ink-gray-5 mb-1">
{{ __('Comments') }}
</div>
<TextEditor
:content="comments"
@change="
(val) => {
comments = val
isDirty = true
}
"
:editable="true"
:fixedMenu="true"
editorClass="prose-sm max-w-none border-b border-x bg-surface-gray-2 rounded-b-md py-1 px-2 min-h-[7rem]"
/>
</div>
</div>
</div>
</div>
@@ -176,17 +197,18 @@ import {
FileUploader,
FormControl,
TextEditor,
toast,
} from 'frappe-ui'
import { computed, inject, onMounted, onBeforeUnmount, ref, watch } from 'vue'
import { FileText, X } from 'lucide-vue-next'
import { showToast, getFileSize } from '@/utils'
import { getFileSize } from '@/utils'
import { useRouter } from 'vue-router'
const submissionFile = ref(null)
const answer = ref(null)
const comments = ref(null)
const router = useRouter()
const user = inject('$user')
const showTitle = router.currentRoute.value.name == 'AssignmentSubmission'
const isDirty = ref(false)
const props = defineProps({
@@ -198,6 +220,10 @@ const props = defineProps({
type: String,
default: 'new',
},
showTitle: {
type: Boolean,
default: true,
},
})
onMounted(() => {
@@ -265,7 +291,7 @@ const submissionResource = createDocumentResource({
doctype: 'LMS Assignment Submission',
name: props.submissionName,
onError(err) {
showToast(__('Error'), __(err.messages?.[0] || err), 'x')
toast.error(err.messages?.[0] || err)
},
auto: false,
cache: [user.data?.name, props.assignmentID],
@@ -281,6 +307,9 @@ watch(submissionResource, () => {
if (submissionResource.doc.answer) {
answer.value = submissionResource.doc.answer
}
if (submissionResource.doc.comments) {
comments.value = submissionResource.doc.comments
}
if (submissionResource.isDirty) {
isDirty.value = true
} else if (showUploader() && !submissionFile.value) {
@@ -305,15 +334,18 @@ const submitAssignment = () => {
submissionResource.doc && submissionResource.doc.owner != user.data?.name
? user.data?.name
: null
submissionResource.setValue.submit(
{
...submissionResource.doc,
assignment_attachment: submissionFile.value?.file_url,
evaluator: evaluator,
comments: comments.value,
answer: answer.value,
},
{
onSuccess(data) {
showToast(__('Success'), __('Changes saved successfully'), 'check')
toast.success(__('Changes saved successfully'))
},
}
)
@@ -327,7 +359,7 @@ const addNewSubmission = () => {
{},
{
onSuccess(data) {
showToast('Success', 'Assignment submitted successfully.', 'check')
toast.success(__('Assignment submitted successfully'))
if (router.currentRoute.value.name == 'AssignmentSubmission') {
router.push({
name: 'AssignmentSubmission',
@@ -335,6 +367,7 @@ const addNewSubmission = () => {
assignmentID: props.assignmentID,
submissionName: data.name,
},
query: { fromLesson: router.currentRoute.value.query.fromLesson },
})
} else {
markLessonProgress()
@@ -344,7 +377,7 @@ const addNewSubmission = () => {
submissionResource.reload()
},
onError(err) {
showToast('Error', err.messages?.[0] || err, 'x')
toast.error(err.messages?.[0] || err)
},
}
)
@@ -1,46 +0,0 @@
<template>
<Assignment
v-if="user.data && submission.data"
:assignmentID="assignmentID"
:submissionName="submission.data?.name || 'new'"
/>
<div v-else class="border rounded-md text-center py-20">
<div>
{{ __('Please login to access the assignment.') }}
</div>
<Button @click="redirectToLogin()" class="mt-2">
<span>
{{ __('Login') }}
</span>
</Button>
</div>
</template>
<script setup>
import { inject, watch } from 'vue'
import { Button, createResource } from 'frappe-ui'
import Assignment from '@/components/Assignment.vue'
const user = inject('$user')
const props = defineProps({
assignmentID: {
type: String,
required: true,
},
})
const submission = createResource({
url: 'frappe.client.get_value',
makeParams(values) {
return {
doctype: 'LMS Assignment Submission',
fieldname: 'name',
filters: {
assignment: props.assignmentID,
member: user.data?.name,
},
}
},
auto: true,
})
</script>
+3 -4
View File
@@ -1,6 +1,6 @@
<template>
<div
class="flex flex-col border-2 hover:bg-surface-gray-2 rounded-md p-4 h-full"
class="flex flex-col border hover:border-outline-gray-3 rounded-md p-4 h-full"
style="min-height: 150px"
>
<div class="text-lg leading-5 font-semibold mb-2 text-ink-gray-9">
@@ -70,9 +70,8 @@
</div>
</template>
<script setup>
import { Badge } from 'frappe-ui'
import { formatTime } from '../utils'
import { Clock, BookOpen, Globe } from 'lucide-vue-next'
import { formatTime } from '@/utils'
import { Clock, Globe } from 'lucide-vue-next'
import DateRange from '@/components/Common/DateRange.vue'
import CourseInstructors from '@/components/CourseInstructors.vue'
import UserAvatar from '@/components/UserAvatar.vue'
+9 -3
View File
@@ -63,6 +63,9 @@
</ListSelectBanner>
</ListView>
</div>
<div v-else class="text-sm italic text-ink-gray-5">
{{ __('No courses added') }}
</div>
<BatchCourseModal
v-model="showCourseModal"
:batch="batch"
@@ -83,9 +86,10 @@ import {
ListRows,
ListView,
ListRowItem,
toast,
} from 'frappe-ui'
import { Plus, Trash2 } from 'lucide-vue-next'
import { showToast } from '@/utils'
const readOnlyMode = window.read_only_mode
const showCourseModal = ref(false)
const user = inject('$user')
@@ -102,7 +106,6 @@ const courses = createResource({
params: {
batch: props.batch,
},
cache: ['batchCourses', props.batchName],
auto: true,
})
@@ -148,7 +151,7 @@ const removeCourses = (selections, unselectAll) => {
{
onSuccess(data) {
courses.reload()
showToast(__('Success'), __('Courses deleted successfully'), 'check')
toast.success(__('Courses deleted successfully'))
unselectAll()
},
}
@@ -156,6 +159,9 @@ const removeCourses = (selections, unselectAll) => {
}
const canSeeAddButton = () => {
if (readOnlyMode) {
return false
}
return user.data?.is_moderator || user.data?.is_evaluator
}
</script>
+1 -2
View File
@@ -6,13 +6,12 @@
:courses="batch.data.courses"
/>
<Assessments :batch="batch.data.name" />
<StudentHeatmap />
<!-- <StudentHeatmap /> -->
</div>
</template>
<script setup>
import UpcomingEvaluations from '@/components/UpcomingEvaluations.vue'
import Assessments from '@/components/Assessments.vue'
import StudentHeatmap from '@/components/StudentHeatmap.vue'
const props = defineProps({
batch: {
+51 -124
View File
@@ -1,44 +1,49 @@
<template>
<div v-if="user.data?.is_student">
<div
v-if="feedbackList.data?.length"
class="bg-surface-blue-2 text-blue-700 p-2 rounded-md mb-5"
>
{{ __('Thank you for providing your feedback!') }}
</div>
<div v-else class="flex justify-between items-center mb-5">
<div class="text-lg font-semibold">
{{ __('Help Us Improve') }}
<div>
<div class="leading-5 mb-4">
<div v-if="readOnly">
{{ __('Thank you for providing your feedback.') }}
<span
@click="showFeedbackForm = !showFeedbackForm"
class="underline cursor-pointer"
>{{ __('Click here') }}</span
>
{{ __('to view your feedback.') }}
</div>
<div v-else>
{{ __('Help us improve by providing your feedback.') }}
</div>
</div>
<Button @click="submitFeedback()">
{{ __('Submit') }}
</Button>
</div>
<div class="space-y-8">
<div class="flex items-center justify-between">
<Rating
v-for="key in ratingKeys"
v-model="feedback[key]"
:label="__(convertToTitleCase(key))"
<div class="space-y-4" :class="showFeedbackForm ? 'block' : 'hidden'">
<div class="space-y-4">
<Rating
v-for="key in ratingKeys"
v-model="feedback[key]"
:label="__(convertToTitleCase(key))"
:readonly="readOnly"
/>
</div>
<FormControl
v-model="feedback.feedback"
type="textarea"
:label="__('Feedback')"
:rows="9"
:readonly="readOnly"
/>
<Button v-if="!readOnly" @click="submitFeedback">
{{ __('Submit Feedback') }}
</Button>
</div>
<FormControl
v-model="feedback.feedback"
type="textarea"
:label="__('Feedback')"
:rows="7"
:readonly="readOnly"
/>
</div>
</div>
<div v-else-if="feedbackList.data?.length">
<div class="text-lg font-semibold mb-5">
{{ __('Average of Feedback Received') }}
<div class="leading-5 text-sm mb-2 mt-5">
{{ __('Average Feedback Received') }}
</div>
<div class="flex items-center justify-between mb-10">
<div class="space-y-4">
<Rating
v-for="key in ratingKeys"
v-model="average[key]"
@@ -47,82 +52,32 @@
/>
</div>
<div class="text-lg font-semibold mb-5">
{{ __('All Feedback') }}
</div>
<ListView
:columns="feedbackColumns"
:rows="feedbackList.data"
row-key="name"
:options="{
showTooltip: false,
rowHeight: 'h-16',
selectable: false,
}"
>
<ListHeader
class="mb-2 grid items-center space-x-4 rounded bg-surface-gray-2 p-2"
></ListHeader>
<ListRows>
<ListRow
:row="row"
v-for="row in feedbackList.data"
class="group cursor-pointer feedback-list"
>
<template #default="{ column, item }">
<ListRowItem
:item="row[column.key]"
:align="column.align"
class="text-sm"
>
<template #prefix>
<div v-if="column.key == 'member_name'">
<Avatar
class="flex items-center"
:image="row['member_image']"
:label="item"
size="sm"
/>
</div>
</template>
<div v-if="ratingKeys.includes(column.key)">
<Rating v-model="row[column.key]" :readonly="true" />
</div>
<div v-else class="leading-5">
{{ row[column.key] }}
</div>
</ListRowItem>
</template>
</ListRow>
</ListRows>
</ListView>
<Button variant="outline" class="mt-5" @click="showAllFeedback = true">
{{ __('View all feedback') }}
</Button>
</div>
<div v-else class="text-sm italic text-center text-ink-gray-7 mt-5">
<div v-else class="text-ink-gray-7 mt-5 leading-5">
{{ __('No feedback received yet.') }}
</div>
<FeedbackModal
v-if="feedbackList.data?.length"
v-model="showAllFeedback"
:feedbackList="feedbackList.data"
/>
</template>
<script setup>
import { computed, inject, onMounted, reactive, ref, watch } from 'vue'
import { inject, onMounted, reactive, ref, watch } from 'vue'
import { convertToTitleCase } from '@/utils'
import {
Avatar,
Button,
createListResource,
FormControl,
ListView,
ListHeader,
ListHeaderItem,
ListRows,
ListRow,
ListRowItem,
Rating,
} from 'frappe-ui'
import { Button, createListResource, FormControl, Rating } from 'frappe-ui'
import FeedbackModal from '@/components/Modals/FeedbackModal.vue'
const user = inject('$user')
const ratingKeys = ['content', 'instructors', 'value']
const readOnly = ref(false)
const average = reactive({})
const feedback = reactive({})
const showFeedbackForm = ref(true)
const showAllFeedback = ref(false)
const props = defineProps({
batch: {
@@ -168,6 +123,7 @@ watch(
if (feedbackList.data.length) {
let data = feedbackList.data
readOnly.value = true
showFeedbackForm.value = false
ratingKeys.forEach((key) => {
average[key] = 0
@@ -202,44 +158,15 @@ const submitFeedback = () => {
{
onSuccess: () => {
feedbackList.reload()
showFeedbackForm.value = false
},
}
)
}
const feedbackColumns = computed(() => {
return [
{
label: 'Member',
key: 'member_name',
width: '10rem',
},
{
label: 'Feedback',
key: 'feedback',
width: '15rem',
},
{
label: 'Content',
key: 'content',
width: '9rem',
},
{
label: 'Instructors',
key: 'instructors',
width: '9rem',
},
{
label: 'Value',
key: 'value',
width: '9rem',
},
]
})
</script>
<style>
.feedback-list > button > div {
align-items: start;
padding: 0.25rem 0;
padding: 0.15rem 0;
}
</style>
+109 -64
View File
@@ -2,7 +2,12 @@
<div v-if="batch.data" class="border-2 rounded-md p-5 lg:w-72">
<div
v-if="batch.data.seat_count && seats_left > 0"
class="text-xs bg-green-200 text-green-800 float-right px-2 py-0.5 rounded-md"
class="text-sm bg-green-100 text-green-700 px-2 py-1 rounded-md"
:class="
batch.data.amount || batch.data.courses.length
? 'float-right'
: 'w-fit mb-4'
"
>
{{ seats_left }}
<span v-if="seats_left > 1">
@@ -14,7 +19,7 @@
</div>
<div
v-else-if="batch.data.seat_count && seats_left <= 0"
class="text-xs bg-red-200 text-red-900 float-right px-2 py-0.5 rounded-md"
class="text-xs bg-red-100 text-red-700 float-right px-2 py-0.5 rounded-md"
>
{{ __('Sold Out') }}
</div>
@@ -24,7 +29,10 @@
>
{{ formatNumberIntoCurrency(batch.data.amount, batch.data.currency) }}
</div>
<div class="flex items-center mb-3 text-ink-gray-7">
<div
v-if="batch.data.courses.length"
class="flex items-center mb-3 text-ink-gray-7"
>
<BookOpen class="h-4 w-4 stroke-1.5 mr-2" />
<span> {{ batch.data.courses.length }} {{ __('Courses') }} </span>
</div>
@@ -46,72 +54,105 @@
{{ batch.data.timezone }}
</span>
</div>
<router-link
v-if="isModerator || isStudent"
:to="{
name: 'Batch',
params: {
batchName: batch.data.name,
},
}"
>
<Button variant="solid" class="w-full mt-4">
<span>
{{ isModerator ? __('Manage Batch') : __('Visit Batch') }}
</span>
<div v-if="!readOnlyMode">
<router-link
v-if="canAccessBatch"
:to="{
name: 'Batch',
params: {
batchName: batch.data.name,
},
}"
>
<Button variant="solid" class="w-full mt-4">
<template #prefix>
<LogIn v-if="isStudent" class="size-4 stroke-1.5" />
<Settings v-else class="size-4 stroke-1.5" />
</template>
<span>
{{ isStudent ? __('Visit Batch') : __('Manage Batch') }}
</span>
</Button>
</router-link>
<router-link
:to="{
name: 'Billing',
params: {
type: 'batch',
name: batch.data.name,
},
}"
v-else-if="
batch.data.paid_batch &&
batch.data.seats_left > 0 &&
batch.data.accept_enrollments
"
>
<Button v-if="!isStudent" class="w-full mt-4" variant="solid">
<template #prefix>
<CreditCard class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Register Now') }}
</span>
</Button>
</router-link>
<Button
variant="solid"
class="w-full mt-2"
v-else-if="
batch.data.allow_self_enrollment &&
batch.data.seats_left &&
batch.data.accept_enrollments
"
@click="enrollInBatch()"
>
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('Enroll Now') }}
</Button>
</router-link>
<router-link
:to="{
name: 'Billing',
params: {
type: 'batch',
name: batch.data.name,
},
}"
v-else-if="batch.data.paid_batch && batch.data.seats_left"
>
<Button v-if="!isStudent" class="w-full mt-4" variant="solid">
<span>
{{ __('Register Now') }}
</span>
</Button>
</router-link>
<Button
variant="solid"
class="w-full mt-2"
v-else-if="batch.data.allow_self_enrollment && batch.data.seats_left"
@click="enrollInBatch()"
>
{{ __('Enroll Now') }}
</Button>
<router-link
v-if="isModerator"
:to="{
name: 'BatchForm',
params: {
batchName: batch.data.name,
},
}"
>
<Button class="w-full mt-2">
<span>
{{ __('Edit') }}
</span>
</Button>
</router-link>
<router-link
v-if="isModerator"
:to="{
name: 'BatchForm',
params: {
batchName: batch.data.name,
},
}"
>
<Button class="w-full mt-2">
<template #prefix>
<Pencil class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Edit') }}
</span>
</Button>
</router-link>
</div>
</div>
</template>
<script setup>
import { inject, computed } from 'vue'
import { Badge, Button, createResource } from 'frappe-ui'
import { BookOpen, Clock, Globe } from 'lucide-vue-next'
import { formatNumberIntoCurrency, formatTime, showToast } from '@/utils'
import { Button, createResource, toast } from 'frappe-ui'
import {
BookOpen,
Clock,
CreditCard,
Globe,
GraduationCap,
LogIn,
Pencil,
Settings,
} from 'lucide-vue-next'
import { formatNumberIntoCurrency, formatTime } from '@/utils'
import DateRange from '@/components/Common/DateRange.vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const user = inject('$user')
const readOnlyMode = window.read_only_mode
const props = defineProps({
batch: {
@@ -137,11 +178,7 @@ const enrollInBatch = () => {
{},
{
onSuccess(data) {
showToast(
__('Success'),
__('You have been enrolled in this batch'),
'check'
)
toast.success(__('You have been enrolled in this batch'))
router.push({
name: 'Batch',
params: {
@@ -167,4 +204,12 @@ const isStudent = computed(() => {
const isModerator = computed(() => {
return user.data?.is_moderator
})
const isEvaluator = computed(() => {
return user.data?.is_evaluator
})
const canAccessBatch = computed(() => {
return isModerator.value || isStudent.value || isEvaluator.value
})
</script>
+102 -193
View File
@@ -1,108 +1,64 @@
<template>
<div class="">
<div v-if="batch.data" class="">
<div class="w-full flex items-center justify-between pb-4">
<div class="font-medium text-ink-gray-7">
{{ __('Statistics') }}
</div>
</div>
<div class="grid grid-cols-4 gap-5 mb-8">
<div
class="flex items-center border py-2 px-3 rounded-md text-ink-gray-7"
>
<div class="p-2 rounded-md bg-surface-gray-2 mr-3">
<User class="w-5 h-5 stroke-1.5" />
</div>
<div class="flex items-center space-x-2">
<span class="font-semibold">
{{ students.data?.length }}
</span>
<span class="">
{{ __('Students') }}
</span>
</div>
</div>
<div
class="flex items-center border py-2 px-3 rounded-md text-ink-gray-7"
>
<div class="p-2 rounded-md bg-surface-gray-2 mr-3">
<GraduationCap class="w-5 h-5 stroke-1.5" />
</div>
<div class="flex items-center space-x-2">
<span class="font-semibold">
{{ certificationCount.data }}
</span>
<span class="">
{{ __('Certified') }}
</span>
</div>
</div>
<div
class="flex items-center border py-2 px-3 rounded-md text-ink-gray-7"
>
<div class="p-2 rounded-md bg-surface-gray-2 mr-3">
<BookOpen class="w-5 h-5 stroke-1.5" />
</div>
<div class="flex items-center space-x-2">
<span class="font-semibold">
{{ batch.courses?.length }}
</span>
<span>
{{ __('Courses') }}
</span>
</div>
</div>
<div
class="flex items-center border py-2 px-3 rounded-md text-ink-gray-7"
>
<div class="p-2 rounded-md bg-surface-gray-2 mr-3">
<ShieldCheck class="w-5 h-5 stroke-1.5" />
</div>
<div class="flex items-center space-x-2">
<span class="font-semibold">
{{ assessmentCount }}
</span>
<span>
{{ __('Assessments') }}
</span>
</div>
</div>
</div>
<div v-if="showProgressChart" class="mb-8">
<div class="text-ink-gray-7 font-medium">
{{ __('Progress') }}
</div>
<ApexChart
:options="chartOptions"
:series="chartData"
type="bar"
height="200"
<div class="grid grid-cols-2 md:grid-cols-4 gap-5 mb-8">
<NumberChart
class="border rounded-md"
:config="{ title: __('Students'), value: students.data?.length || 0 }"
/>
<NumberChart
class="border rounded-md"
:config="{
title: __('Certified'),
value: certificationCount.data || 0,
}"
/>
<NumberChart
class="border rounded-md"
:config="{
title: __('Courses'),
value: batch.data.courses?.length || 0,
}"
/>
<NumberChart
class="border rounded-md"
:config="{ title: __('Assessments'), value: assessmentCount || 0 }"
/>
<div
class="flex items-center justify-center text-sm text-ink-gray-7 space-x-4"
>
<div class="flex items-center space-x-2">
<div
class="w-3 h-3 rounded-sm"
:style="{ 'background-color': theme.colors.green[600] }"
></div>
<div>
{{ __('Courses') }}
</div>
</div>
<div class="flex items-center space-x-2">
<div
class="w-3 h-3 rounded-sm"
:style="{ 'background-color': theme.colors.blue[600] }"
></div>
<div>
{{ __('Assessments') }}
</div>
</div>
</div>
</div>
<AxisChart
v-if="showProgressChart"
:config="{
data: chartData,
title: __('Batch Summary'),
subtitle: __('Progress of students in courses and assessments'),
xAxis: {
key: 'task',
title: 'Tasks',
type: 'category',
},
yAxis: {
title: __('Number of Students'),
echartOptions: {
minInterval: 1,
},
},
swapXY: true,
series: [
{
name: 'value',
type: 'bar',
},
],
}"
/>
</div>
<div>
@@ -110,7 +66,7 @@
<div class="text-ink-gray-7 font-medium">
{{ __('Students') }}
</div>
<Button @click="openStudentModal()">
<Button v-if="!readOnlyMode" @click="openStudentModal()">
<template #prefix>
<Plus class="h-4 w-4" />
</template>
@@ -201,9 +157,10 @@
</div>
<StudentModal
:batch="props.batch.name"
:batch="props.batch.data.name"
v-model="showStudentModal"
v-model:reloadStudents="students"
v-model:batchModal="props.batch"
/>
<BatchStudentProgress
:student="selectedStudent"
@@ -213,6 +170,7 @@
<script setup>
import {
Avatar,
AxisChart,
Button,
createResource,
FeatherIcon,
@@ -223,6 +181,8 @@ import {
ListRows,
ListView,
ListRowItem,
NumberChart,
toast,
} from 'frappe-ui'
import {
BookOpen,
@@ -234,7 +194,6 @@ import {
} from 'lucide-vue-next'
import { ref, watch } from 'vue'
import StudentModal from '@/components/Modals/StudentModal.vue'
import { showToast } from '@/utils'
import ProgressBar from '@/components/ProgressBar.vue'
import BatchStudentProgress from '@/components/Modals/BatchStudentProgress.vue'
import ApexChart from 'vue3-apexcharts'
@@ -244,9 +203,9 @@ const showStudentModal = ref(false)
const showStudentProgressModal = ref(false)
const selectedStudent = ref(null)
const chartData = ref(null)
const chartOptions = ref(null)
const showProgressChart = ref(false)
const assessmentCount = ref(0)
const readOnlyMode = window.read_only_mode
const props = defineProps({
batch: {
@@ -257,14 +216,15 @@ const props = defineProps({
const students = createResource({
url: 'lms.lms.utils.get_batch_students',
cache: ['students', props.batch.name],
params: {
batch: props.batch?.name,
batch: props.batch?.data?.name,
},
auto: true,
onSuccess(data) {
chartData.value = getChartData()
showProgressChart.value = data.length && true
showProgressChart.value =
data.length &&
(props.batch?.data?.courses?.length || assessmentCount.value)
},
})
@@ -321,7 +281,8 @@ const removeStudents = (selections, unselectAll) => {
{
onSuccess(data) {
students.reload()
showToast(__('Success'), __('Students deleted successfully'), 'check')
props.batch.reload()
toast.success(__('Students deleted successfully'))
unselectAll()
},
}
@@ -329,96 +290,49 @@ const removeStudents = (selections, unselectAll) => {
}
const getChartData = () => {
let categories = {}
let tasks = []
let data = []
if (!students.data?.length) return []
Object.keys(students.data[0].courses).forEach((course) => {
categories[course] = {
value: 0,
type: 'course',
label: course,
}
students.data.forEach((row) => {
tasks = countAssessments(row, tasks)
tasks = countCourses(row, tasks)
})
Object.keys(students.data?.[0].assessments).forEach((assessment) => {
categories[assessment] = {
value: 0,
type: 'assessment',
label: assessment,
}
})
students.data.forEach((student) => {
Object.keys(student.courses).forEach((course) => {
if (student.courses[course] === 100) {
categories[course].value += 1
}
})
Object.keys(student.assessments).forEach((assessment) => {
if (student.assessments[assessment].result === 'Passed') {
categories[assessment].value += 1
}
tasks.forEach((task) => {
data.push({
task: task.label,
value: task.value,
})
})
chartOptions.value = getChartOptions(categories)
return [
{
name: __('Completed by Students'),
data: Object.values(categories).map((item) => item.value),
},
]
return data
}
const getChartOptions = (categories) => {
const courseColor = theme.colors.green[700]
const assessmentColor = theme.colors.blue[700]
const maxY =
students.data?.length % 5
? students.data?.length + (5 - (students.data?.length % 5))
: students.data?.length
const countAssessments = (row, tasks) => {
Object.keys(row.assessments).forEach((assessment) => {
if (row.assessments[assessment].result === 'Pass') {
tasks.filter((task) => task.label === assessment).length
? tasks.filter((task) => task.label === assessment)[0].value++
: tasks.push({
value: 1,
label: assessment,
})
}
})
return tasks
}
return {
chart: {
type: 'bar',
toolbar: {
show: false,
},
},
plotOptions: {
bar: {
distributed: true,
borderRadius: 3,
borderRadiusApplication: 'end',
horizontal: true,
barHeight: '40%',
},
},
colors: Object.values(categories).map((item) =>
item.type === 'course' ? courseColor : assessmentColor
),
xaxis: {
categories: Object.values(categories).map((item) => item.label),
labels: {
style: {
fontSize: '10px',
},
rotate: 0,
formatter: function (value) {
return value.length > 30 ? `${value.substring(0, 30)}...` : value
},
},
},
yaxis: {
max: maxY,
min: 0,
stepSize: 10,
tickAmount: maxY / 5,
/* reversed: true */
},
}
const countCourses = (row, tasks) => {
Object.keys(row.courses).forEach((course) => {
if (row.courses[course] === 100) {
tasks.filter((task) => task.label === course).length
? tasks.filter((task) => task.label === course)[0].value++
: tasks.push({
value: 1,
label: course,
})
}
})
return tasks
}
watch(students, () => {
@@ -432,14 +346,9 @@ const certificationCount = createResource({
params: {
doctype: 'LMS Certificate',
filters: {
batch_name: props.batch.name,
batch_name: props.batch?.data?.name,
},
},
auto: true,
})
</script>
<style>
.apexcharts-legend {
display: none !important;
}
</style>
-92
View File
@@ -1,92 +0,0 @@
<template>
<div class="flex flex-col justify-between min-h-0">
<div>
<div class="flex items-center justify-between">
<div class="font-semibold mb-1 text-ink-gray-9">
{{ __(label) }}
</div>
<Badge
v-if="isDirty"
:label="__('Not Saved')"
variant="subtle"
theme="orange"
/>
</div>
<div class="text-xs text-ink-gray-5">
{{ __(description) }}
</div>
</div>
<div class="overflow-y-auto">
<SettingFields :fields="fields" :data="data.data" />
<div class="flex flex-row-reverse mt-auto">
<Button variant="solid" :loading="saveSettings.loading" @click="update">
{{ __('Update') }}
</Button>
</div>
</div>
</div>
</template>
<script setup>
import { createResource, Button, Badge } from 'frappe-ui'
import SettingFields from '@/components/SettingFields.vue'
import { watch, ref } from 'vue'
const isDirty = ref(false)
const props = defineProps({
fields: {
type: Array,
required: true,
},
data: {
type: Object,
required: true,
},
label: {
type: String,
required: true,
},
description: {
type: String,
},
})
const saveSettings = createResource({
url: 'frappe.client.set_value',
makeParams(values) {
return {
doctype: 'Website Settings',
name: 'Website Settings',
fieldname: values.fields,
}
},
})
const update = () => {
let fieldsToSave = {}
let imageFields = ['favicon', 'banner_image', 'footer_logo']
props.fields.forEach((f) => {
if (imageFields.includes(f.name)) {
fieldsToSave[f.name] = f.value ? f.value.file_url : null
} else {
fieldsToSave[f.name] = f.value
}
})
saveSettings.submit(
{
fields: fieldsToSave,
},
{
onSuccess(data) {
isDirty.value = false
},
}
)
}
watch(props.data, (newData) => {
if (newData && !isDirty.value) {
isDirty.value = true
}
})
</script>
-130
View File
@@ -1,130 +0,0 @@
<template>
<div class="flex flex-col min-h-0">
<div class="flex items-center justify-between">
<div class="text-xl font-semibold mb-5 text-ink-gray-9">
{{ label }}
</div>
<Button @click="() => showCategoryForm()">
<template #icon>
<Plus v-if="!showForm" class="h-3 w-3 stroke-1.5" />
<X v-else class="h-3 w-3 stroke-1.5" />
</template>
</Button>
</div>
<div
v-if="showForm"
class="flex items-center justify-between my-4 space-x-2"
>
<FormControl
ref="categoryInput"
v-model="category"
:placeholder="__('Category Name')"
class="flex-1"
/>
<Button @click="addCategory()" variant="subtle">
{{ __('Add') }}
</Button>
</div>
<div class="overflow-y-scroll">
<div class="text-base divide-y space-y-2">
<FormControl
:value="cat.category"
type="text"
v-for="cat in categories.data"
class=""
@change.stop="(e) => update(cat.name, e.target.value)"
/>
</div>
</div>
</div>
</template>
<script setup>
import {
Button,
FormControl,
createListResource,
createResource,
debounce,
} from 'frappe-ui'
import { Plus, X } from 'lucide-vue-next'
import { ref } from 'vue'
const showForm = ref(false)
const category = ref(null)
const categoryInput = ref(null)
const props = defineProps({
label: {
type: String,
required: true,
},
description: {
type: String,
default: '',
},
})
const categories = createListResource({
doctype: 'LMS Category',
fields: ['name', 'category'],
auto: true,
})
const newCategory = createResource({
url: 'frappe.client.insert',
makeParams(values) {
return {
doc: {
doctype: 'LMS Category',
category: category.value,
},
}
},
})
const addCategory = () => {
newCategory.submit(
{},
{
onSuccess(data) {
categories.reload()
category.value = null
},
}
)
}
const showCategoryForm = () => {
showForm.value = !showForm.value
setTimeout(() => {
categoryInput.value.$el.querySelector('input').focus()
}, 0)
}
const updateCategory = createResource({
url: 'frappe.client.rename_doc',
makeParams(values) {
return {
doctype: 'LMS Category',
old_name: values.name,
new_name: values.category,
}
},
})
const update = (name, value) => {
updateCategory.submit(
{
name: name,
category: value,
},
{
onSuccess() {
categories.reload()
},
}
)
}
</script>
@@ -0,0 +1,85 @@
<template>
<Button
v-if="certification.data && certification.data.certificate"
@click="downloadCertificate"
class=""
>
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('View Certificate') }}
</Button>
<div
v-else-if="
certification.data &&
certification.data.membership &&
certification.data.paid_certificate &&
user.data?.is_student
"
>
<router-link
v-if="!certification.data.membership.purchased_certificate"
:to="{
name: 'Billing',
params: {
type: 'certificate',
name: courseName,
},
}"
>
<Button class="w-full">
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('Get Certified') }}
</Button>
</router-link>
<router-link
v-else-if="!certification.data.membership.certificate"
:to="{
name: 'CourseCertification',
params: {
courseName: courseName,
},
}"
>
<Button class="w-full">
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('Get Certified') }}
</Button>
</router-link>
</div>
</template>
<script setup>
import { Button, createResource } from 'frappe-ui'
import { inject } from 'vue'
import { GraduationCap } from 'lucide-vue-next'
const user = inject('$user')
const props = defineProps({
courseName: {
type: String,
required: true,
},
})
const certification = createResource({
url: 'lms.lms.api.get_certification_details',
params: {
course: props.courseName,
},
auto: user.data ? true : false,
cache: ['certificationData', user.data?.name],
})
const downloadCertificate = () => {
window.open(
`/api/method/frappe.utils.print_format.download_pdf?doctype=LMS+Certificate&name=${
certification.data.certificate.name
}&format=${encodeURIComponent(certification.data.certificate.template)}`
)
}
</script>
@@ -0,0 +1,67 @@
<template>
<Dialog
v-model="show"
:options="{
title: __('Contact Us'),
size: 'md',
}"
>
<template #body-content>
<div class="flex flex-col gap-4">
<FormControl
v-model="subject"
:label="__('Subject')"
type="text"
:required="true"
/>
<div>
<div class="mb-1.5 text-sm text-ink-gray-5">
{{ __('Message') }}
<span class="text-ink-red-3">*</span>
</div>
<TextEditor
:fixedMenu="true"
@change="(val) => (message = val)"
editorClass="prose-sm py-2 px-2 min-h-[200px] border-outline-gray-2 hover:border-outline-gray-3 rounded-b-md bg-surface-gray-3"
/>
</div>
</div>
</template>
<template #actions="{ close }">
<div class="pb-5 float-right">
<Button variant="solid" @click="sendMail(close)">
{{ __('Send') }}
</Button>
</div>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { Button, call, Dialog, FormControl, TextEditor, toast } from 'frappe-ui'
import { ref } from 'vue'
import { useSettings } from '@/stores/settings'
const show = defineModel<boolean>({ required: true, default: false })
const subject = ref('')
const message = ref('')
const settingsStore = useSettings()
const sendMail = (close: Function) => {
call('frappe.core.doctype.communication.email.make', {
recipients: settingsStore.contactUsEmail?.data,
subject: subject.value,
content: message.value,
send_email: true,
})
.then(() => {
toast.success(__('Email sent successfully'))
close()
subject.value = ''
message.value = ''
})
.catch(() => {
toast.error(__('Failed to send email'))
close()
})
}
</script>
+127 -109
View File
@@ -1,126 +1,140 @@
<template>
<Combobox v-model="selectedValue" nullable v-slot="{ open: isComboboxOpen }">
<Popover class="w-full" v-model:show="showOptions">
<template #target="{ open: openPopover, togglePopover }">
<slot name="target" v-bind="{ open: openPopover, togglePopover }">
<div class="w-full">
<button
class="flex w-full items-center justify-between focus:outline-none"
:class="inputClasses"
@click="() => togglePopover()"
>
<div class="flex items-center">
<slot name="prefix" />
<span
class="overflow-hidden text-ellipsis whitespace-nowrap text-base leading-5"
v-if="selectedValue"
>
{{ displayValue(selectedValue) }}
</span>
<span class="text-base leading-5 text-ink-gray-4" v-else>
{{ placeholder || '' }}
</span>
</div>
<ChevronDown class="h-4 w-4 stroke-1.5" />
</button>
</div>
</slot>
</template>
<template #body="{ isOpen }">
<div v-show="isOpen">
<div
class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl"
>
<div class="relative px-1.5 pt-0.5">
<ComboboxInput
ref="search"
class="form-input w-full"
type="text"
@change="
(e) => {
query = e.target.value
}
"
:value="query"
autocomplete="off"
placeholder="Search"
/>
<div>
<div v-if="label" class="text-xs text-ink-gray-5 mb-1">
{{ __(label) }}
<span class="text-ink-red-3" v-if="attrs.required">*</span>
</div>
<Combobox
v-model="selectedValue"
nullable
v-slot="{ open: isComboboxOpen }"
>
<Popover class="w-full" v-model:show="showOptions">
<template #target="{ open: openPopover, togglePopover }">
<slot name="target" v-bind="{ open: openPopover, togglePopover }">
<div class="w-full">
<button
class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center"
@click="selectedValue = null"
class="flex w-full items-center justify-between focus:outline-none"
:class="inputClasses"
@click="() => togglePopover()"
:disabled="attrs.readonly"
>
<X class="h-4 w-4 stroke-1.5" />
<div class="flex items-center">
<slot name="prefix" />
<span
class="overflow-hidden text-ellipsis whitespace-nowrap text-base leading-5"
v-if="selectedValue"
>
{{ displayValue(selectedValue) }}
</span>
<span class="text-base leading-5 text-ink-gray-4" v-else>
{{ placeholder || '' }}
</span>
</div>
<ChevronDown class="h-4 w-4 stroke-1.5" />
</button>
</div>
<ComboboxOptions
class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
static
</slot>
</template>
<template #body="{ isOpen }">
<div v-show="isOpen" class="">
<div
class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2"
>
<div
class="mt-1.5"
v-for="group in groups"
:key="group.key"
v-show="group.items.length > 0"
<div class="relative px-1.5 pt-0.5">
<ComboboxInput
ref="search"
class="form-input w-full"
type="text"
@change="
(e) => {
query = e.target.value
}
"
:value="query"
autocomplete="off"
placeholder="Search"
/>
<button
class="absolute right-1.5 inline-flex h-7 w-7 items-center justify-center"
@click="selectedValue = null"
>
<X class="h-4 w-4 stroke-1.5 text-ink-gray-7" />
</button>
</div>
<ComboboxOptions
class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
static
>
<div
v-if="group.group && !group.hideLabel"
class="px-2.5 py-1.5 text-sm font-medium text-ink-gray-4"
class="mt-1.5"
v-for="group in groups"
:key="group.key"
v-show="group.items.length > 0"
>
{{ group.group }}
</div>
<ComboboxOption
as="template"
v-for="option in group.items"
:key="option.value"
:value="option"
v-slot="{ active, selected }"
>
<li
:class="[
'flex items-center rounded px-2.5 py-2 text-base',
{ 'bg-surface-gray-2': active },
]"
<div
v-if="group.group && !group.hideLabel"
class="px-2.5 py-1.5 text-sm font-medium text-ink-gray-4"
>
<slot
name="item-prefix"
v-bind="{ active, selected, option }"
/>
<slot
name="item-label"
v-bind="{ active, selected, option }"
{{ group.group }}
</div>
<ComboboxOption
as="template"
v-for="option in group.items"
:key="option.value"
:value="option"
v-slot="{ active, selected }"
>
<li
:class="[
'flex items-center rounded px-2.5 py-2 text-base',
{ 'bg-surface-gray-2': active },
]"
>
<div class="flex flex-col space-y-1">
<div>
{{ option.label }}
<slot
name="item-prefix"
v-bind="{ active, selected, option }"
/>
<slot
name="item-label"
v-bind="{ active, selected, option }"
>
<div class="flex flex-col space-y-1 text-ink-gray-8">
<div>
{{ option.label }}
</div>
<div
v-if="
option.description &&
option.description != option.label
"
class="text-xs text-ink-gray-7"
v-html="option.description"
></div>
</div>
<div
v-if="option.description"
class="text-xs text-ink-gray-7"
v-html="option.description"
></div>
</div>
</slot>
</li>
</ComboboxOption>
</slot>
</li>
</ComboboxOption>
</div>
<li
v-if="groups.length == 0"
class="mt-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
>
No results found
</li>
</ComboboxOptions>
<div v-if="slots.footer" class="border-t p-1.5 pb-0.5">
<slot
name="footer"
v-bind="{ value: search?.el._value, close }"
></slot>
</div>
<li
v-if="groups.length == 0"
class="mt-1.5 rounded-md px-2.5 py-1.5 text-base text-ink-gray-5"
>
No results found
</li>
</ComboboxOptions>
<div v-if="slots.footer" class="border-t p-1.5 pb-0.5">
<slot
name="footer"
v-bind="{ value: search?.el._value, close }"
></slot>
</div>
</div>
</div>
</template>
</Popover>
</Combobox>
</template>
</Popover>
</Combobox>
</div>
</template>
<script setup>
@@ -130,7 +144,7 @@ import {
ComboboxOptions,
ComboboxOption,
} from '@headlessui/vue'
import { Popover, Button } from 'frappe-ui'
import { Popover } from 'frappe-ui'
import { ChevronDown, X } from 'lucide-vue-next'
import { ref, computed, useAttrs, useSlots, watch, nextTick } from 'vue'
@@ -147,6 +161,10 @@ const props = defineProps({
type: String,
default: 'md',
},
label: {
type: String,
default: '',
},
variant: {
type: String,
default: 'subtle',
@@ -0,0 +1,149 @@
<template>
<div>
<div class="text-xs text-ink-gray-5 mb-2">
{{ label }}
</div>
<div class="overflow-x-auto border rounded-md">
<div
class="grid items-center space-x-4 p-2 border-b"
:style="{ gridTemplateColumns: getGridTemplateColumns() }"
>
<div
v-for="(column, index) in columns"
:key="index"
class="text-sm text-ink-gray-5"
>
{{ column }}
</div>
<div></div>
</div>
<div
v-for="(row, rowIndex) in rows"
:key="rowIndex"
class="grid items-center space-x-4 p-2"
:style="{ gridTemplateColumns: getGridTemplateColumns() }"
>
<template v-for="key in Object.keys(row)" :key="key">
<input
v-if="showKey(key)"
v-model="row[key]"
class="py-1.5 px-2 border-none focus:ring-0 focus:border focus:border-gray-300 focus:bg-surface-gray-2 rounded-sm text-sm focus:outline-none"
/>
</template>
<div class="relative" ref="menuRef">
<Button
variant="ghost"
@click="(event: MouseEvent) => toggleMenu(rowIndex, event)"
>
<template #icon>
<Ellipsis
class="size-4 text-ink-gray-7 stroke-1.5 cursor-pointer"
/>
</template>
</Button>
<div
v-if="menuOpenIndex === rowIndex"
class="absolute right-[30px] top-5 mt-1 w-32 bg-surface-white border border-outline-gray-1 rounded-md shadow-sm"
>
<button
@click="deleteRow(rowIndex)"
class="flex items-center space-x-2 w-full text-left px-3 py-2 text-sm text-ink-red-3"
>
<Trash2 class="size-4 stroke-1.5" />
<span>
{{ __('Delete') }}
</span>
</button>
</div>
</div>
</div>
</div>
<div class="mt-2">
<Button @click="addRow">
<template #prefix>
<Plus class="size-4 text-ink-gray-7" />
</template>
{{ __('Add Row') }}
</Button>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { Button } from 'frappe-ui'
import { Ellipsis, Plus, Trash2 } from 'lucide-vue-next'
import { onClickOutside } from '@vueuse/core'
const rows = defineModel<Cell[][]>()
const menuRef = ref(null)
const menuOpenIndex = ref<number | null>(null)
const menuTopPosition = ref<string>('')
const emit = defineEmits<{
(e: 'update:modelValue', value: Cell[][]): void
}>()
type Cell = {
value: string
editable?: boolean
}
const props = withDefaults(
defineProps<{
modelValue?: Cell[][]
columns?: string[]
label?: string
}>(),
{
columns: [],
}
)
const columns = ref(props.columns)
watch(rows, () => {
if (rows.value?.length < 1) {
addRow()
}
})
const addRow = () => {
if (!rows.value) {
rows.value = []
}
let newRow: { [key: string]: string } = {}
columns.value.forEach((column: any) => {
newRow[column.toLowerCase().split(' ').join('_')] = ''
})
rows.value.push(newRow)
emit('update:modelValue', rows.value)
}
const deleteRow = (index: number) => {
rows.value.splice(index, 1)
emit('update:modelValue', rows.value)
}
const getGridTemplateColumns = () => {
return [...Array(columns.value.length).fill('1fr'), '0.25fr'].join(' ')
}
const toggleMenu = (index: number, event: MouseEvent) => {
menuOpenIndex.value = menuOpenIndex.value === index ? null : index
menuTopPosition.value = `${event.clientY + 10}px`
}
onClickOutside(menuRef, () => {
menuOpenIndex.value = null
})
const showKey = (key: string) => {
let columnsLower = columns.value.map((col) =>
col.toLowerCase().split(' ').join('_')
)
return columnsLower.includes(key)
}
</script>
+162
View File
@@ -0,0 +1,162 @@
<template>
<div class="flex w-full flex-col gap-1.5">
<div v-if="label" class="text-xs text-ink-gray-5">
{{ __(label) }}
</div>
<codemirror
v-model="code"
:extensions="extensions"
:tab-size="2"
:autofocus="autofocus"
:indent-with-tab="true"
:style="{ height: height, maxHeight: maxHeight }"
:disabled="readonly"
@blur="emitEditorValue"
:class="{
'border border-outline-gray-1': showBorder,
}"
/>
<Button
v-if="showSaveButton"
@click="emit('save', code)"
class="mt-3 w-full text-base"
>
{{ __('Save') }}
</Button>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, computed, watch } from 'vue'
import { Button } from 'frappe-ui'
import { Codemirror } from 'vue-codemirror'
import { autocompletion, closeBrackets } from '@codemirror/autocomplete'
import { LanguageSupport } from '@codemirror/language'
import { EditorView } from '@codemirror/view'
import { tomorrow } from 'thememirror'
const props = withDefaults(
defineProps<{
language: 'json' | 'javascript' | 'html' | 'css' | 'python'
modelValue: string | object | Array<string | object> | null
height?: string
maxHeight?: string
autofocus?: boolean
showSaveButton?: boolean
showLineNumbers?: boolean
completions?: Function | null
label?: string
showBorder?: boolean
required?: boolean
readonly?: boolean
}>(),
{
language: 'javascript',
modelValue: null,
height: 'auto',
maxHeight: '250px',
showLineNumbers: true,
completions: null,
}
)
const emit = defineEmits(['update:modelValue', 'save'])
const code = ref<string>('')
watch(
() => props.modelValue,
(newVal) => {
code.value =
typeof newVal === 'string' ? newVal : JSON.stringify(newVal, null, 2)
},
{ immediate: true }
)
watch(code, (val) => {
emit('update:modelValue', val)
})
const errorMessage = ref('')
const emitEditorValue = () => {
try {
errorMessage.value = ''
let value = code.value || ''
if (!props.showSaveButton && !props.readonly) {
emit('update:modelValue', value)
}
} catch (e) {
console.error('Error while parsing JSON for editor', e)
errorMessage.value = `Invalid object/JSON: ${e.message}`
}
}
const languageExtension = ref<LanguageSupport>()
const autocompleteExtension = ref()
async function setLanguageExtension() {
const importMap = {
json: () => import('@codemirror/lang-json'),
javascript: () => import('@codemirror/lang-javascript'),
html: () => import('@codemirror/lang-html'),
css: () => import('@codemirror/lang-css'),
python: () => import('@codemirror/lang-python'),
}
const languageImport = importMap[props.language]
if (!languageImport) return
const module = await languageImport()
languageExtension.value = (module as any)[props.language]()
if (props.completions) {
const languageData = (module as any)[`${props.language}Language`]
autocompleteExtension.value = languageData.data.of({
autocomplete: props.completions,
})
}
}
onMounted(async () => {
await setLanguageExtension()
})
watch(
() => props.language,
async () => {
await setLanguageExtension()
},
{ immediate: true }
)
const extensions = computed(() => {
const baseExtensions = [
closeBrackets(),
tomorrow,
EditorView.theme({
'&': {
fontFamily: 'monospace',
fontSize: '12px',
},
'.cm-gutters': {
display: props.showLineNumbers ? 'flex' : 'none',
},
}),
]
if (languageExtension.value) {
baseExtensions.push(languageExtension.value)
}
if (autocompleteExtension.value) {
baseExtensions.push(autocompleteExtension.value)
}
const autocompletionOptions = {
activateOnTyping: true,
maxRenderedOptions: 10,
closeOnBlur: false,
icons: false,
optionClass: () => 'flex h-7 !px-2 items-center rounded !text-gray-600',
}
baseExtensions.push(autocompletion(autocompletionOptions))
return baseExtensions
})
</script>
@@ -5,7 +5,7 @@
height: height,
}"
>
<span class="text-xs text-ink-gray-7" v-if="label">
<span class="text-xs text-ink-gray-7 mb-1" v-if="label">
{{ label }}
</span>
<div
@@ -146,7 +146,6 @@ function resetEditor(value: string, resetHistory = false) {
value = getModelValue()
aceEditor?.setValue(value)
aceEditor?.clearSelection()
console.log(isDark.value)
aceEditor?.setTheme(isDark.value ? 'ace/theme/twilight' : 'ace/theme/chrome')
props.autofocus && aceEditor?.focus()
if (resetHistory) {
@@ -0,0 +1,108 @@
<template>
<div>
<div class="text-xs text-ink-gray-5 mb-1">
{{ __(label) }}
</div>
<Popover placement="bottom" class="!block">
<template #target="{ togglePopover, isOpen }">
<div class="space-y-2">
<FormControl
type="text"
autocomplete="off"
class="w-full"
:placeholder="__('Set Color')"
@focus="togglePopover"
:modelValue="modelValue"
@update:modelValue="(val: string) => emit('update:modelValue', val)"
>
<template #prefix>
<div
class="size-4 rounded-full"
:style="
modelValue
? {
backgroundColor:
theme.backgroundColor[modelValue.toLowerCase()][400],
}
: {}
"
>
<Palette
v-if="!modelValue"
class="size-4 stroke-1.5 text-ink-gray-5"
/>
</div>
</template>
<template #suffix>
<Button variant="ghost">
<X
class="size-3 text-ink-gray-5"
@click="emit('update:modelValue', null)"
/>
</Button>
</template>
</FormControl>
</div>
</template>
<template #body="{ close }">
<div class="rounded-lg bg-surface-white p-3 border w-fit mt-2">
<div class="text-xs text-ink-gray-5 mb-1.5">
{{ __('Swatches') }}
</div>
<div class="grid grid-cols-7 gap-2">
<div
v-for="color in colors"
:key="color"
class="size-5 rounded-full cursor-pointer"
:style="{
backgroundColor:
theme.backgroundColor[color.toLowerCase()][400],
}"
@click="
(e) => {
emit('update:modelValue', color)
close()
emit('change', color)
}
"
></div>
</div>
</div>
</template>
</Popover>
<div class="text-sm text-ink-gray-5 mt-2">
{{ description }}
</div>
</div>
</template>
<script setup lang="ts">
import { Button, FormControl, Popover } from 'frappe-ui'
import { computed } from 'vue'
import { Palette, X } from 'lucide-vue-next'
import { theme } from '@/utils/theme'
const emit = defineEmits(['update:modelValue', 'change'])
const props = defineProps<{
modelValue: string
label: string
description?: string
}>()
const colors = computed(() => {
return [
'Red',
'Blue',
'Green',
'Amber',
'Purple',
'Cyan',
'Orange',
'Violet',
'Pink',
'Teal',
'Gray',
'Yellow',
]
})
</script>
+2 -1
View File
@@ -12,6 +12,7 @@
:variant="attrs.variant"
:placeholder="attrs.placeholder"
:filterable="false"
:readonly="attrs.readonly"
>
<template #target="{ open, togglePopover }">
<slot name="target" v-bind="{ open, togglePopover }" />
@@ -34,7 +35,7 @@
<Button
variant="ghost"
class="w-full !justify-start"
label="Create New"
:label="__('Create New')"
@click="attrs.onCreate(value, close)"
>
<template #prefix>
@@ -4,78 +4,92 @@
{{ label }}
<span class="text-ink-red-3" v-if="required">*</span>
</label>
<div class="grid grid-cols-3 gap-1">
<Button
ref="emails"
v-for="value in values"
:key="value"
:label="value"
theme="gray"
variant="subtle"
class="rounded-md"
@keydown.delete.capture.stop="removeLastValue"
>
<template #suffix>
<X @click="removeValue(value)" class="h-4 w-4 stroke-1.5" />
</template>
</Button>
<div class="">
<Combobox v-model="selectedValue" nullable>
<Popover class="w-full" v-model:show="showOptions">
<template #target="{ togglePopover }">
<ComboboxInput
ref="search"
class="search-input form-input w-full focus-visible:!ring-0"
type="text"
:value="query"
@change="
(e) => {
query = e.target.value
showOptions = true
}
"
autocomplete="off"
@focus="() => togglePopover()"
@keydown.delete.capture.stop="removeLastValue"
/>
</template>
<template #body="{ isOpen }">
<div v-show="isOpen">
<div
class="mt-1 rounded-lg bg-surface-white py-1 text-base shadow-2xl"
<div class="w-full">
<Combobox v-model="selectedValue" nullable>
<Popover class="w-full" v-model:show="showOptions">
<template #target="{ togglePopover }">
<ComboboxInput
ref="search"
class="search-input form-input w-full focus-visible:!ring-0"
type="text"
:value="query"
@change="
(e) => {
query = e.target.value
showOptions = true
}
"
autocomplete="off"
@focus="() => togglePopover()"
@keydown.delete.capture.stop="removeLastValue"
/>
</template>
<template #body="{ isOpen, close }">
<div v-show="isOpen">
<div
class="mt-1 rounded-lg bg-surface-white py-1 text-base border-2"
>
<ComboboxOptions
class="my-1 min-h-[6rem] max-h-[12rem] overflow-y-auto px-1.5"
static
>
<ComboboxOptions
class="my-1 max-h-[12rem] overflow-y-auto px-1.5"
static
<ComboboxOption
v-for="option in options"
:key="option.value"
:value="option"
v-slot="{ active }"
>
<ComboboxOption
v-for="option in options"
:key="option.value"
:value="option"
v-slot="{ active }"
<li
:class="[
'flex cursor-pointer items-center rounded px-2 py-1 text-base',
{ 'bg-surface-gray-2': active },
]"
>
<li
:class="[
'flex cursor-pointer items-center rounded px-2 py-1 text-base',
{ 'bg-surface-gray-2': active },
]"
>
<div class="flex flex-col gap-1 p-1">
<div class="text-base font-medium">
{{ option.description }}
</div>
<div class="text-sm text-ink-gray-5">
{{ option.value }}
</div>
<div class="flex flex-col gap-1 p-1">
<div class="text-base font-medium text-ink-gray-8">
{{ option.description }}
</div>
</li>
</ComboboxOption>
</ComboboxOptions>
</div>
<div class="text-sm text-ink-gray-5">
{{ option.value }}
</div>
</div>
</li>
</ComboboxOption>
<div class="h-10"></div>
<div
v-if="attrs.onCreate"
class="absolute bottom-2 left-1 w-[99%] pt-2 bg-white border-t"
>
<Button
variant="ghost"
class="w-full !justify-start"
:label="__('Create New')"
@click="attrs.onCreate(close)"
>
<template #prefix>
<Plus class="h-4 w-4 stroke-1.5" />
</template>
</Button>
</div>
</ComboboxOptions>
</div>
</template>
</Popover>
</Combobox>
</div>
</template>
</Popover>
</Combobox>
</div>
<div v-if="values.length" class="grid grid-cols-2 gap-2 mt-1">
<div
v-for="value in values"
class="flex items-center justify-between break-all bg-surface-gray-2 text-ink-gray-7 word-wrap p-2 rounded-md mr-2"
>
<span class="break-all">
{{ value }}
</span>
<X
class="size-4 stroke-1.5 cursor-pointer"
@click="removeValue(value)"
/>
</div>
</div>
<!-- <ErrorMessage class="mt-2 pl-2" v-if="error" :message="error" /> -->
@@ -90,9 +104,9 @@ import {
ComboboxOption,
} from '@headlessui/vue'
import { createResource, Popover, Button } from 'frappe-ui'
import { ref, computed, nextTick } from 'vue'
import { ref, computed, nextTick, useAttrs } from 'vue'
import { watchDebounced } from '@vueuse/core'
import { X } from 'lucide-vue-next'
import { X, Plus } from 'lucide-vue-next'
const props = defineProps({
label: {
@@ -124,7 +138,7 @@ const props = defineProps({
})
const values = defineModel()
const attrs = useAttrs()
const emails = ref([])
const search = ref(null)
const error = ref(null)
@@ -0,0 +1,76 @@
<template>
<div class="mb-4">
<div v-if="label" class="text-xs text-ink-gray-5 mb-2">
{{ __(label) }}
<span class="text-ink-red-3">*</span>
</div>
<FileUploader
v-if="!modelValue"
:fileTypes="['image/*']"
:validateFile="validateFile"
@success="(file: File) => saveImage(file)"
>
<template v-slot="{ file, progress, uploading, openFileSelector }">
<div class="flex items-center">
<div class="border rounded-md w-fit py-7 px-20">
<Image class="size-5 stroke-1 text-ink-gray-7" />
</div>
<div class="ml-4">
<Button @click="openFileSelector">
{{ __('Upload') }}
</Button>
<div class="mt-1 text-ink-gray-5 text-sm leading-5">
{{ __(description) }}
</div>
</div>
</div>
</template>
</FileUploader>
<div v-else class="mb-4">
<div class="flex items-center">
<img :src="modelValue" class="border rounded-md w-44 h-auto" />
<div class="ml-4">
<Button @click="removeImage()">
{{ __('Remove') }}
</Button>
<div
v-if="description"
class="mt-2 text-ink-gray-5 text-sm leading-5"
>
{{ __(description) }}
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { validateFile } from '@/utils'
import { Button, FileUploader } from 'frappe-ui'
import { Image } from 'lucide-vue-next'
const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
}>()
const props = withDefaults(
defineProps<{
modelValue: string
label?: string
description?: string
}>(),
{
modelValue: '',
label: '',
description: '',
}
)
const saveImage = (file: any) => {
emit('update:modelValue', file.file_url)
}
const removeImage = () => {
emit('update:modelValue', '')
}
</script>
+86 -66
View File
@@ -1,36 +1,57 @@
<template>
<div
v-if="course.title"
class="flex flex-col h-full rounded-md border-2 overflow-auto"
class="flex flex-col h-full rounded-md overflow-auto text-ink-gray-9"
style="min-height: 350px"
>
<div
class="course-image"
:class="{ 'default-image': !course.image }"
:style="{ backgroundImage: 'url(\'' + encodeURI(course.image) + '\')' }"
class="w-[100%] h-[168px] bg-cover bg-center bg-no-repeat border-t border-x rounded-t-md"
:style="
course.image
? { backgroundImage: `url('${encodeURI(course.image)}')` }
: {
backgroundImage: getGradientColor(),
backgroundBlendMode: 'screen',
}
"
>
<div
class="flex items-center flex-wrap space-x-1 relative top-4 px-2 w-fit"
>
<Badge v-if="course.featured" variant="subtle" theme="green" size="md">
{{ __('Featured') }}
</Badge>
<!-- <div class="flex items-center flex-wrap relative top-4 px-2 w-fit">
<div
v-for="tag in course.tags"
class="text-xs bg-white text-gray-800 px-2 py-0.5 rounded-md"
v-if="course.featured"
class="flex items-center space-x-1 text-xs text-ink-amber-3 bg-surface-white border border-outline-amber-1 px-2 py-0.5 rounded-md mr-1 mb-1"
>
<Star class="size-3 stroke-2" />
<span>
{{ __('Featured') }}
</span>
</div>
<div
v-if="course.tags"
v-for="tag in course.tags?.split(', ')"
class="text-xs border bg-surface-white text-ink-gray-9 px-2 py-0.5 rounded-md mb-1 mr-1"
>
{{ tag }}
</div>
</div>
<div v-if="!course.image" class="image-placeholder">
{{ course.title[0] }}
</div> -->
<div
v-if="!course.image"
class="flex items-center justify-center text-white flex-1 font-extrabold my-auto px-5 text-center leading-6 h-full"
:class="
course.title.length > 32
? 'text-lg'
: course.title.length > 20
? 'text-xl'
: 'text-2xl'
"
>
{{ course.title }}
</div>
</div>
<div class="flex flex-col flex-auto p-4">
<div class="flex flex-col flex-auto p-4 border-x-2 border-b-2 rounded-b-md">
<div class="flex items-center justify-between mb-2">
<div v-if="course.lessons">
<Tooltip :text="__('Lessons')">
<span class="flex items-center text-ink-gray-7">
<span class="flex items-center">
<BookOpen class="h-4 w-4 stroke-1.5 mr-1" />
{{ course.lessons }}
</span>
@@ -39,38 +60,36 @@
<div v-if="course.enrollments">
<Tooltip :text="__('Enrolled Students')">
<span class="flex items-center text-ink-gray-7">
<Users class="h-4 w-4 stroke-1. mr-1" />
{{ course.enrollments }}
<span class="flex items-center">
<Users class="h-4 w-4 stroke-1.5 mr-1" />
{{ formatAmount(course.enrollments) }}
</span>
</Tooltip>
</div>
<div v-if="course.rating">
<Tooltip :text="__('Average Rating')">
<span class="flex items-center text-ink-gray-7">
<span class="flex items-center">
<Star class="h-4 w-4 stroke-1.5 mr-1" />
{{ course.rating }}
</span>
</Tooltip>
</div>
<div v-if="course.status != 'Approved'">
<Badge
variant="subtle"
:theme="course.status === 'Under Review' ? 'orange' : 'blue'"
size="sm"
>
{{ course.status }}
</Badge>
</div>
<Tooltip v-if="course.featured" :text="__('Featured')">
<Award class="size-4 stroke-2 text-ink-amber-3" />
</Tooltip>
</div>
<div class="text-xl font-semibold leading-6 text-ink-gray-9">
<div
v-if="course.image"
class="font-semibold leading-6"
:class="course.title.length > 32 ? 'text-lg' : 'text-xl'"
>
{{ course.title }}
</div>
<div class="short-introduction text-ink-gray-7 text-sm">
<div class="short-introduction text-sm">
{{ course.short_introduction }}
</div>
@@ -79,11 +98,8 @@
:progress="course.membership.progress"
/>
<div
v-if="user && course.membership"
class="text-sm text-ink-gray-7 mt-2 mb-4"
>
{{ Math.ceil(course.membership.progress) }}% completed
<div v-if="user && course.membership" class="text-sm mt-2 mb-4">
{{ Math.ceil(course.membership.progress) }}% {{ __('completed') }}
</div>
<div class="flex items-center justify-between mt-auto">
@@ -100,19 +116,30 @@
<CourseInstructors :instructors="course.instructors" />
</div>
<div class="font-semibold">
{{ course.price }}
<div class="flex items-center space-x-2">
<div v-if="course.paid_course" class="font-semibold">
{{ course.price }}
</div>
<Tooltip
v-if="course.paid_certificate || course.enable_certification"
:text="__('Get Certified')"
>
<GraduationCap class="size-5 stroke-1.5 text-ink-gray-7" />
</Tooltip>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { BookOpen, Users, Star } from 'lucide-vue-next'
import UserAvatar from '@/components/UserAvatar.vue'
import { Award, BookOpen, GraduationCap, Star, Users } from 'lucide-vue-next'
import { sessionStore } from '@/stores/session'
import { Badge, Tooltip } from 'frappe-ui'
import { Tooltip } from 'frappe-ui'
import { theme } from '@/utils/theme'
import { formatAmount } from '@/utils'
import CourseInstructors from '@/components/CourseInstructors.vue'
import UserAvatar from '@/components/UserAvatar.vue'
import ProgressBar from '@/components/ProgressBar.vue'
const { user } = sessionStore()
@@ -123,16 +150,24 @@ const props = defineProps({
default: null,
},
})
const getGradientColor = () => {
let color = props.course.card_gradient?.toLowerCase() || 'blue'
let colorMap = theme.backgroundColor[color]
return `linear-gradient(to top right, black, ${colorMap[400]})`
/* return `bg-gradient-to-br from-${color}-100 via-${color}-200 to-${color}-400` */
/* return `linear-gradient(to bottom right, ${colorMap[100]}, ${colorMap[400]})` */
/* return `radial-gradient(ellipse at 80% 20%, black 20%, ${colorMap[500]} 100%)` */
/* return `radial-gradient(ellipse at 30% 70%, black 50%, ${colorMap[500]} 100%)` */
/* return `radial-gradient(ellipse at 80% 20%, ${colorMap[100]} 0%, ${colorMap[300]} 50%, ${colorMap[500]} 100%)` */
/* return `conic-gradient(from 180deg at 50% 50%, ${colorMap[100]} 0%, ${colorMap[200]} 50%, ${colorMap[400]} 100%)` */
/* return `linear-gradient(135deg, ${colorMap[100]}, ${colorMap[300]}), linear-gradient(120deg, rgba(255,255,255,0.4) 0%, transparent 60%) ` */
/* return `radial-gradient(circle at 20% 30%, ${colorMap[100]} 0%, transparent 40%),
radial-gradient(circle at 80% 40%, ${colorMap[200]} 0%, transparent 50%),
linear-gradient(135deg, ${colorMap[300]} 0%, ${colorMap[400]} 100%);` */
}
</script>
<style>
.course-image {
height: 168px;
width: 100%;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.course-card-pills {
background: #ffffff;
margin-left: 0;
@@ -146,14 +181,6 @@ const props = defineProps({
width: fit-content;
}
.default-image {
display: flex;
flex-direction: column;
align-items: center;
background-color: theme('colors.green.100');
color: theme('colors.green.600');
}
.avatar-group {
display: inline-flex;
align-items: center;
@@ -162,14 +189,7 @@ const props = defineProps({
.avatar-group .avatar {
transition: margin 0.1s ease-in-out;
}
.image-placeholder {
display: flex;
align-items: center;
flex: 1;
font-size: 5rem;
color: theme('colors.gray.700');
font-weight: 600;
}
.avatar-group.overlap .avatar + .avatar {
margin-left: calc(-8px);
}
+166 -99
View File
@@ -1,94 +1,128 @@
<template>
<div class="border-2 rounded-md min-w-80">
<div class="border-2 rounded-md min-w-80 max-w-sm">
<iframe
v-if="course.data.video_link"
:src="video_link"
class="rounded-t-md min-h-56 w-full"
/>
<div class="p-5">
<div v-if="course.data.price" class="text-2xl font-semibold mb-3">
<div v-if="course.data.paid_course" class="text-2xl font-semibold mb-3">
{{ course.data.price }}
</div>
<router-link
v-if="course.data.membership"
:to="{
name: 'Lesson',
params: {
courseName: course.name,
chapterNumber: course.data.current_lesson
? course.data.current_lesson.split('-')[0]
: 1,
lessonNumber: course.data.current_lesson
? course.data.current_lesson.split('-')[1]
: 1,
},
}"
>
<Button variant="solid" size="md" class="w-full">
<div v-if="!readOnlyMode">
<div v-if="course.data.membership" class="space-y-2">
<router-link
:to="{
name: 'Lesson',
params: {
courseName: course.name,
chapterNumber: course.data.current_lesson
? course.data.current_lesson.split('-')[0]
: 1,
lessonNumber: course.data.current_lesson
? course.data.current_lesson.split('-')[1]
: 1,
},
}"
>
<Button variant="solid" size="md" class="w-full">
<template #prefix>
<BookText class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Continue Learning') }}
</span>
</Button>
</router-link>
<CertificationLinks :courseName="course.data.name" class="w-full" />
</div>
<router-link
v-else-if="course.data.paid_course"
:to="{
name: 'Billing',
params: {
type: 'course',
name: course.data.name,
},
}"
>
<Button variant="solid" size="md" class="w-full">
<template #prefix>
<CreditCard class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Buy this course') }}
</span>
</Button>
</router-link>
<Badge
v-else-if="course.data.disable_self_learning"
theme="blue"
size="lg"
>
{{ __('Contact the Administrator to enroll for this course.') }}
</Badge>
<Button
v-else-if="!user.data?.is_moderator && !is_instructor()"
@click="enrollStudent()"
variant="solid"
class="w-full"
size="md"
>
<template #prefix>
<BookText class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Continue Learning') }}
{{ __('Start Learning') }}
</span>
</Button>
</router-link>
<router-link
v-else-if="course.data.paid_course"
:to="{
name: 'Billing',
params: {
type: 'course',
name: course.data.name,
},
}"
>
<Button variant="solid" size="md" class="w-full">
<span>
{{ __('Buy this course') }}
</span>
<Button
v-if="canGetCertificate"
@click="fetchCertificate()"
variant="subtle"
class="w-full mt-2"
size="md"
>
<template #prefix>
<GraduationCap class="size-4 stroke-1.5" />
</template>
{{ __('Get Certificate') }}
</Button>
</router-link>
<div
v-else-if="course.data.disable_self_learning"
class="bg-surface-blue-2 text-blue-900 text-sm rounded-md py-1 px-3"
>
{{ __('Contact the Administrator to enroll for this course.') }}
<Button
v-if="user.data?.is_moderator || is_instructor()"
class="w-full mt-2"
size="md"
@click="showProgressSummary"
>
<template #prefix>
<TrendingUp class="size-4 stroke-1.5" />
{{ __('Progress Summary') }}
</template>
</Button>
<router-link
v-if="user?.data?.is_moderator || is_instructor()"
:to="{
name: 'CourseForm',
params: {
courseName: course.data.name,
},
}"
>
<Button variant="subtle" class="w-full mt-2" size="md">
<template #prefix>
<Pencil class="size-4 stroke-1.5" />
</template>
<span>
{{ __('Edit') }}
</span>
</Button>
</router-link>
</div>
<Button
v-else
@click="enrollStudent()"
variant="solid"
class="w-full"
size="md"
>
<span>
{{ __('Start Learning') }}
</span>
</Button>
<Button
v-if="canGetCertificate"
@click="fetchCertificate()"
variant="subtle"
class="w-full mt-2"
size="md"
>
{{ __('Get Certificate') }}
</Button>
<router-link
v-if="user?.data?.is_moderator || is_instructor()"
:to="{
name: 'CourseForm',
params: {
courseName: course.data.name,
},
}"
>
<Button variant="subtle" class="w-full mt-2" size="md">
<span>
{{ __('Edit') }}
</span>
</Button>
</router-link>
<div class="space-y-4">
<div class="mt-8 font-medium text-ink-gray-9">
<div
class="font-medium text-ink-gray-9"
:class="{ 'mt-8': !readOnlyMode }"
>
{{ __('This course has:') }}
</div>
<div class="flex items-center text-ink-gray-9">
@@ -108,25 +142,62 @@
v-if="parseInt(course.data.rating) > 0"
class="flex items-center text-ink-gray-9"
>
<Star class="h-4 w-4 stroke-1.5 fill-orange-500 text-gray-50" />
<Star class="size-4 stroke-1.5 fill-yellow-500 text-transparent" />
<span class="ml-2">
{{ course.data.rating }} {{ __('Rating') }}
</span>
</div>
<div
v-if="course.data.enable_certification"
class="flex items-center font-semibold text-ink-gray-9"
>
<GraduationCap class="h-4 w-4 stroke-2" />
<span class="ml-2">
{{ __('Certificate of Completion') }}
</span>
</div>
<div
v-if="course.data.paid_certificate"
class="flex items-center font-semibold text-ink-gray-9"
>
<GraduationCap class="h-4 w-4 stroke-2" />
<span class="ml-2">
{{ __('Paid Certificate after Evaluation') }}
</span>
</div>
</div>
</div>
</div>
<CourseProgressSummary
v-if="user.data?.is_moderator || is_instructor()"
v-model="showProgressModal"
:courseName="course.data.name"
:enrollments="course.data.enrollments"
/>
</template>
<script setup>
import { BookOpen, Users, Star } from 'lucide-vue-next'
import { computed, inject } from 'vue'
import { Button, createResource } from 'frappe-ui'
import { showToast, formatAmount } from '@/utils/'
import {
BookOpen,
BookText,
CreditCard,
GraduationCap,
Pencil,
Star,
TrendingUp,
Users,
} from 'lucide-vue-next'
import { computed, inject, ref } from 'vue'
import { Badge, Button, call, createResource, toast } from 'frappe-ui'
import { formatAmount } from '@/utils/'
import { capture } from '@/telemetry'
import { useRouter } from 'vue-router'
import CertificationLinks from '@/components/CertificationLinks.vue'
import CourseProgressSummary from '@/components/Modals/CourseProgressSummary.vue'
const router = useRouter()
const user = inject('$user')
const showProgressModal = ref(false)
const readOnlyMode = window.read_only_mode
const props = defineProps({
course: {
@@ -144,31 +215,19 @@ const video_link = computed(() => {
function enrollStudent() {
if (!user.data) {
showToast(
__('Please Login'),
__('You need to login first to enroll for this course'),
'alert-circle'
)
toast.success(__('You need to login first to enroll for this course'))
setTimeout(() => {
window.location.href = `/login?redirect-to=${window.location.pathname}`
}, 2000)
}, 500)
} else {
const enrollStudentResource = createResource({
url: 'lms.lms.doctype.lms_enrollment.lms_enrollment.create_membership',
call('lms.lms.doctype.lms_enrollment.lms_enrollment.create_membership', {
course: props.course.data.name,
})
enrollStudentResource
.submit({
course: props.course.data.name,
})
.then(() => {
capture('enrolled_in_course', {
course: props.course.data.name,
})
showToast(
__('Success'),
__('You have been enrolled in this course'),
'check'
)
toast.success(__('You have been enrolled in this course'))
setTimeout(() => {
router.push({
name: 'Lesson',
@@ -178,7 +237,11 @@ function enrollStudent() {
lessonNumber: 1,
},
})
}, 2000)
}, 1000)
})
.catch((err) => {
toast.warning(__(err.messages?.[0] || err))
console.error(err)
})
}
}
@@ -226,4 +289,8 @@ const fetchCertificate = () => {
member: user.data?.name,
})
}
const showProgressSummary = () => {
showProgressModal.value = true
}
</script>
@@ -6,6 +6,7 @@
name: 'Profile',
params: { username: instructors[0].username },
}"
class="text-ink-gray-7 hover:text-ink-gray-9"
>
{{ instructors[0].full_name }}
</router-link>
@@ -16,15 +17,17 @@
name: 'Profile',
params: { username: instructors[0].username },
}"
class="text-ink-gray-7 hover:text-ink-gray-9"
>
{{ instructors[0].first_name }}
</router-link>
and
{{ __('and') }}
<router-link
:to="{
name: 'Profile',
params: { username: instructors[1].username },
}"
class="text-ink-gray-7 hover:text-ink-gray-9"
>
{{ instructors[1].first_name }}
</router-link>
@@ -35,10 +38,11 @@
name: 'Profile',
params: { username: instructors[0].username },
}"
class="text-ink-gray-7 hover:text-ink-gray-9"
>
{{ instructors[0].first_name }}
</router-link>
and {{ instructors?.length - 1 }} others
{{ __('and') }} {{ instructors?.length - 1 }} {{ __('others') }}
</span>
</div>
</template>
+182 -124
View File
@@ -1,140 +1,161 @@
<template>
<div class="text-base">
<div class="">
<div
v-if="title && (outline.data?.length || allowEdit)"
class="grid grid-cols-[70%,30%] mb-4 px-2"
class="flex items-center justify-between space-x-2 mb-4 px-2"
:class="{
'sticky top-0 z-10 bg-surface-white border-b px-3 py-2.5 sm:px-5':
allowEdit,
}"
>
<div class="font-semibold text-lg leading-5 text-ink-gray-9">
<div
class="font-semibold text-lg leading-5 text-ink-gray-9"
:class="{ 'font-medium text-p-base': allowEdit }"
>
{{ __(title) }}
</div>
<Button size="sm" v-if="allowEdit" @click="openChapterModal()">
{{ __('Add Chapter') }}
</Button>
<!-- <span class="font-medium cursor-pointer" @click="expandAllChapters()">
{{ expandAll ? __("Collapse all chapters") : __("Expand all chapters") }}
</span> -->
</div>
<div
:class="{
'border-2 rounded-md py-2 px-2': showOutline && outline.data?.length,
}"
>
<Disclosure
v-slot="{ open }"
v-for="(chapter, index) in outline.data"
:key="chapter.name"
:defaultOpen="openChapterDetail(chapter.idx)"
<Draggable
:list="outline.data"
:disabled="!allowEdit"
item-key="name"
group="chapters"
@end="updateChapterOrder"
>
<DisclosureButton ref="" class="flex items-center w-full p-2 group">
<ChevronRight
:class="{
'rotate-90 transform duration-200': open,
'duration-200': !open,
hidden: chapter.is_scorm_package,
open: index == 1,
}"
class="h-4 w-4 text-ink-gray-9 stroke-1"
/>
<div
class="text-base text-left text-ink-gray-9 font-medium leading-5 ml-2"
@click="redirectToChapter(chapter)"
>
{{ chapter.title }}
</div>
<div class="flex ml-auto space-x-4">
<Tooltip :text="__('Edit Chapter')" placement="bottom">
<FilePenLine
v-if="allowEdit"
@click.prevent="openChapterModal(chapter)"
class="h-4 w-4 text-ink-gray-9 invisible group-hover:visible"
/>
</Tooltip>
<Tooltip :text="__('Delete Chapter')" placement="bottom">
<Trash2
v-if="allowEdit"
@click.prevent="trashChapter(chapter.name)"
class="h-4 w-4 text-ink-red-3 invisible group-hover:visible"
/>
</Tooltip>
</div>
</DisclosureButton>
<DisclosurePanel v-if="!chapter.is_scorm_package">
<Draggable
v-if="!chapter.is_scorm_package"
:list="chapter.lessons"
:disabled="!allowEdit"
item-key="name"
group="items"
@end="updateOutline"
:data-chapter="chapter.name"
>
<template #item="{ element: lesson }">
<div
class="outline-lesson pl-8 py-2 pr-4 text-ink-gray-9"
:class="
isActiveLesson(lesson.number) ? 'bg-surface-selected' : ''
"
<template #item="{ element: chapter, index }">
<div class="chapter-item">
<Disclosure
v-slot="{ open }"
:key="chapter.name"
:defaultOpen="openChapterDetail(chapter.idx)"
>
<DisclosureButton
ref=""
class="flex items-center w-full p-2 group"
>
<router-link
:to="{
name: allowEdit ? 'LessonForm' : 'Lesson',
params: {
courseName: courseName,
chapterNumber: lesson.number.split('.')[0],
lessonNumber: lesson.number.split('.')[1],
},
<ChevronRight
:class="{
'rotate-90 transform duration-200': open,
'duration-200': !open,
hidden: chapter.is_scorm_package,
open: index == 1,
}"
class="h-4 w-4 text-ink-gray-9 stroke-1"
/>
<div
class="text-base text-left text-ink-gray-9 font-medium leading-5 ml-2"
@click="redirectToChapter(chapter)"
>
<div class="flex items-center text-sm leading-5 group">
<MonitorPlay
v-if="lesson.icon === 'icon-youtube'"
class="h-4 w-4 stroke-1 mr-2"
{{ chapter.title }}
</div>
<div class="flex ml-auto space-x-4">
<Tooltip :text="__('Edit Chapter')" placement="bottom">
<FilePenLine
v-if="allowEdit"
@click.prevent="openChapterModal(chapter)"
class="h-4 w-4 text-ink-gray-9 invisible group-hover:visible"
/>
<HelpCircle
v-else-if="lesson.icon === 'icon-quiz'"
class="h-4 w-4 stroke-1 mr-2"
/>
<FileText
v-else-if="lesson.icon === 'icon-list'"
class="h-4 w-4 text-ink-gray-9 stroke-1 mr-2"
/>
{{ lesson.title }}
</Tooltip>
<Tooltip :text="__('Delete Chapter')" placement="bottom">
<Trash2
v-if="allowEdit"
@click.prevent="trashLesson(lesson.name, chapter.name)"
class="h-4 w-4 text-ink-red-3 ml-auto invisible group-hover:visible"
@click.prevent="trashChapter(chapter.name)"
class="h-4 w-4 text-ink-red-3 invisible group-hover:visible"
/>
<Check
v-if="lesson.is_complete"
class="h-4 w-4 text-green-700 ml-2"
/>
</div>
</router-link>
</div>
</template>
</Draggable>
<div v-if="allowEdit" class="flex mt-2 mb-4 pl-8">
<router-link
v-if="!chapter.is_scorm_package"
:to="{
name: 'LessonForm',
params: {
courseName: courseName,
chapterNumber: chapter.idx,
lessonNumber: chapter.lessons.length + 1,
},
}"
>
<Button>
{{ __('Add Lesson') }}
</Button>
</router-link>
</Tooltip>
</div>
</DisclosureButton>
<DisclosurePanel v-if="!chapter.is_scorm_package">
<Draggable
v-if="!chapter.is_scorm_package"
:list="chapter.lessons"
:disabled="!allowEdit"
item-key="name"
group="items"
@end="updateOutline"
:data-chapter="chapter.name"
>
<template #item="{ element: lesson }">
<div
class="outline-lesson pl-8 py-2 pr-4 text-ink-gray-9"
:class="
isActiveLesson(lesson.number) ? 'bg-surface-gray-3' : ''
"
>
<router-link
:to="{
name: allowEdit ? 'LessonForm' : 'Lesson',
params: {
courseName: courseName,
chapterNumber: lesson.number.split('.')[0],
lessonNumber: lesson.number.split('.')[1],
},
}"
>
<div class="flex items-center text-sm leading-5 group">
<MonitorPlay
v-if="lesson.icon === 'icon-youtube'"
class="h-4 w-4 stroke-1 mr-2"
/>
<HelpCircle
v-else-if="lesson.icon === 'icon-quiz'"
class="h-4 w-4 stroke-1 mr-2"
/>
<FileText
v-else-if="lesson.icon === 'icon-list'"
class="h-4 w-4 text-ink-gray-9 stroke-1 mr-2"
/>
{{ lesson.title }}
<Trash2
v-if="allowEdit"
@click.prevent="
trashLesson(lesson.name, chapter.name)
"
class="h-4 w-4 text-ink-red-3 ml-auto invisible group-hover:visible"
/>
<Check
v-if="lesson.is_complete"
class="h-4 w-4 text-green-700 ml-2"
/>
</div>
</router-link>
</div>
</template>
</Draggable>
<div v-if="allowEdit" class="flex mt-2 mb-4 pl-8">
<router-link
v-if="!chapter.is_scorm_package"
:to="{
name: 'LessonForm',
params: {
courseName: courseName,
chapterNumber: chapter.idx,
lessonNumber: chapter.lessons.length + 1,
},
}"
>
<Button>
{{ __('Add Lesson') }}
</Button>
</router-link>
</div>
</DisclosurePanel>
</Disclosure>
</div>
</DisclosurePanel>
</Disclosure>
</template>
</Draggable>
</div>
</div>
<ChapterModal
v-if="user.data"
v-model="showChapterModal"
v-model:outline="outline"
:course="courseName"
@@ -142,8 +163,8 @@
/>
</template>
<script setup>
import { Button, createResource, Tooltip } from 'frappe-ui'
import { getCurrentInstance, inject, ref } from 'vue'
import { Button, createResource, Tooltip, toast } from 'frappe-ui'
import { getCurrentInstance, inject, ref, watch } from 'vue'
import Draggable from 'vuedraggable'
import { Disclosure, DisclosureButton, DisclosurePanel } from '@headlessui/vue'
import {
@@ -157,7 +178,6 @@ import {
} from 'lucide-vue-next'
import { useRoute, useRouter } from 'vue-router'
import ChapterModal from '@/components/Modals/ChapterModal.vue'
import { showToast } from '@/utils'
const route = useRoute()
const router = useRouter()
@@ -188,18 +208,38 @@ const props = defineProps({
type: Boolean,
default: false,
},
lessonProgress: {
type: Number,
default: 0,
},
})
const outline = createResource({
url: 'lms.lms.utils.get_course_outline',
cache: ['course_outline', props.courseName],
params: {
course: props.courseName,
progress: props.getProgress,
makeParams() {
return {
course: props.courseName,
progress: props.getProgress,
}
},
auto: true,
})
watch(
() => props.courseName,
() => {
outline.reload()
}
)
watch(
() => props.lessonProgress,
() => {
outline.reload()
}
)
const deleteLesson = createResource({
url: 'lms.lms.api.delete_lesson',
makeParams(values) {
@@ -210,7 +250,7 @@ const deleteLesson = createResource({
},
onSuccess() {
outline.reload()
showToast('Success', 'Lesson deleted successfully', 'check')
toast.success(__('Lesson deleted successfully'))
},
})
@@ -225,7 +265,21 @@ const updateLessonIndex = createResource({
}
},
onSuccess() {
showToast('Success', 'Lesson moved successfully', 'check')
toast.success(__('Lesson moved successfully'))
},
})
const updateChapterIndex = createResource({
url: 'lms.lms.api.update_chapter_index',
makeParams(values) {
return {
chapter: values.chapter,
course: values.course,
idx: values.idx,
}
},
onSuccess() {
toast.success(__('Chapter moved successfully'))
},
})
@@ -274,6 +328,14 @@ const updateOutline = (e) => {
})
}
const updateChapterOrder = (e) => {
updateChapterIndex.submit({
chapter: e.item.__draggable_context.element.name,
course: props.courseName,
idx: e.newIndex,
})
}
const deleteChapter = createResource({
url: 'lms.lms.api.delete_chapter',
makeParams(values) {
@@ -283,7 +345,7 @@ const deleteChapter = createResource({
},
onSuccess() {
outline.reload()
showToast('Success', 'Chapter deleted successfully', 'check')
toast.success(__('Chapter deleted successfully'))
},
})
@@ -312,11 +374,7 @@ const redirectToChapter = (chapter) => {
event.preventDefault()
if (props.allowEdit) return
if (!user.data) {
showToast(
__('You are not enrolled'),
__('Please enroll for this course to view this lesson'),
'alert-circle'
)
toast.success(__('Please enroll for this course to view this lesson'))
return
}
+16 -7
View File
@@ -35,14 +35,14 @@
<span class="text-ink-gray-7">
{{ review.creation }}
</span>
<div class="flex mt-2">
<div class="flex mt-2 space-x-1">
<Star
v-for="index in 5"
class="h-5 w-5 text-ink-gray-2 rounded-sm mr-2"
class="size-4 text-transparent rounded-sm"
:class="
index <= Math.ceil(review.rating)
? 'fill-orange-500'
: 'fill-gray-600'
? 'fill-yellow-500'
: 'fill-gray-300'
"
/>
</div>
@@ -64,7 +64,7 @@
<script setup>
import { Star } from 'lucide-vue-next'
import { createResource, Button } from 'frappe-ui'
import { computed, ref, inject } from 'vue'
import { watch, ref, inject } from 'vue'
import UserAvatar from '@/components/UserAvatar.vue'
import ReviewModal from '@/components/Modals/ReviewModal.vue'
@@ -101,12 +101,21 @@ const hasReviewed = createResource({
const reviews = createResource({
url: 'lms.lms.utils.get_reviews',
cache: ['course_reviews', props.courseName],
params: {
course: props.courseName,
makeParams() {
return {
course: props.courseName,
}
},
auto: true,
})
watch(
() => props.courseName,
() => {
reviews.reload()
}
)
const showReviewModal = ref(false)
function openReviewModal() {
+6 -12
View File
@@ -1,16 +1,10 @@
<template>
<div class="relative flex h-full flex-col">
<div class="h-full flex-1">
<div class="flex h-screen text-base bg-surface-white">
<div
class="relative block min-h-0 flex-shrink-0 overflow-hidden hover:overflow-auto"
>
<AppSidebar />
</div>
<div class="w-full overflow-auto" id="scrollContainer">
<slot />
</div>
</div>
<div class="flex h-screen w-screen">
<div class="h-full border-r bg-surface-menu-bar">
<AppSidebar />
</div>
<div class="flex-1 flex flex-col h-full overflow-auto bg-surface-white">
<slot />
</div>
</div>
</template>

Some files were not shown because too many files have changed in this diff Show More