Compare commits
617 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f01e634445 | ||
|
|
1564de346d | ||
|
|
a5268af269 | ||
|
|
565d9e093c | ||
|
|
cb75606b05 | ||
|
|
7c36294359 | ||
|
|
ad084389cc | ||
|
|
aa8c65a00a | ||
|
|
95ec31e238 | ||
|
|
b5f3a0fa98 | ||
|
|
36bf0d7fb9 | ||
|
|
1719887ac4 | ||
|
|
7f149bf3b1 | ||
|
|
f592e6655f | ||
|
|
46399c7b13 | ||
|
|
0ec66f0f2d | ||
|
|
96c8b64e26 | ||
|
|
bd0b7a8286 | ||
|
|
263b3ec476 | ||
|
|
46075130ab | ||
|
|
0f314bc4e3 | ||
|
|
2b45e7d77c | ||
|
|
987c3e5fe2 | ||
|
|
1e1580d58a | ||
|
|
da9667e1f7 | ||
|
|
9e42fdd786 | ||
|
|
de19abbc5e | ||
|
|
5448a99177 | ||
|
|
f93d7b0193 | ||
|
|
d3bda1b5d0 | ||
|
|
1c49e78b13 | ||
|
|
9d373d4091 | ||
|
|
26edfc7bb9 | ||
|
|
b527c9b160 | ||
|
|
0356b8e2d2 | ||
|
|
1bf093d1b9 | ||
|
|
a78d127702 | ||
|
|
028c0725c3 | ||
|
|
424d35bf42 | ||
|
|
1effdd8482 | ||
|
|
a780b7520f | ||
|
|
233bf36ef6 | ||
|
|
616a45ebc5 | ||
|
|
136f16c9cc | ||
|
|
609628b9cf | ||
|
|
1e0d2e0f2a | ||
|
|
da7e52f85f | ||
|
|
4640ce82f6 | ||
|
|
03ff9e0521 | ||
|
|
f566211d82 | ||
|
|
66ddea2031 | ||
|
|
8b5a9e1639 | ||
|
|
9a183d2ef1 | ||
|
|
807f77755e | ||
|
|
c0a851e045 | ||
|
|
96849afcba | ||
|
|
91e71091ef | ||
|
|
f691ebd146 | ||
|
|
f620c431a1 | ||
|
|
019743b245 | ||
|
|
1d8e3de136 | ||
|
|
0f46f6a1c1 | ||
|
|
b5078c1f1f | ||
|
|
88f9114dd6 | ||
|
|
cfcc1b3162 | ||
|
|
ed2fababff | ||
|
|
74210245cf | ||
|
|
a4ec058a81 | ||
|
|
ae2c15fe8c | ||
|
|
d9e44e0f91 | ||
|
|
3e1f29af48 | ||
|
|
7ac3f6d8ef | ||
|
|
e0f2b9c1ab | ||
|
|
3785e7066e | ||
|
|
157f6b45e9 | ||
|
|
c8dbc18179 | ||
|
|
1d5d86ef6c | ||
|
|
f1746978b2 | ||
|
|
e1f4dae832 | ||
|
|
94e7f6a1f4 | ||
|
|
d3ea923da7 | ||
|
|
dc27dd5d7e | ||
|
|
26f76acdd2 | ||
|
|
719a32e4a5 | ||
|
|
cdf004cdec | ||
|
|
9d5f495842 | ||
|
|
8204fa8ee7 | ||
|
|
9f9dd25f91 | ||
|
|
bd929bfa3f | ||
|
|
5916695d30 | ||
|
|
cca42dca49 | ||
|
|
33065c0ed3 | ||
|
|
603eddf878 | ||
|
|
cda26ab248 | ||
|
|
e73d59d538 | ||
|
|
893fac348d | ||
|
|
642b28bad9 | ||
|
|
b9db14ad44 | ||
|
|
0c23ead398 | ||
|
|
e9009dcb9c | ||
|
|
0d0e64f930 | ||
|
|
b1bdf6516e | ||
|
|
eca4f89d8b | ||
|
|
199cbcf33f | ||
|
|
1f4c7fcb0f | ||
|
|
59b8c781e3 | ||
|
|
9133a3f50b | ||
|
|
b9f4ba6527 | ||
|
|
7b5fe82de9 | ||
|
|
d74db85b82 | ||
|
|
915bbdf247 | ||
|
|
b3412b42b7 | ||
|
|
c6b917fa83 | ||
|
|
c286afa45f | ||
|
|
c74faa3340 | ||
|
|
fa4e8a1ea6 | ||
|
|
42c664a379 | ||
|
|
b84a955ee1 | ||
|
|
211ca3111f | ||
|
|
935e2a976e | ||
|
|
5d38b4dfa0 | ||
|
|
cbf852828c | ||
|
|
7d8b366a73 | ||
|
|
4ad457d568 | ||
|
|
2ab0cb2787 | ||
|
|
4feab27c59 | ||
|
|
3c1449c898 | ||
|
|
7d029c5305 | ||
|
|
13274c01d7 | ||
|
|
f37229c202 | ||
|
|
61f9ff6892 | ||
|
|
3df08b99b3 | ||
|
|
f9748cb723 | ||
|
|
437f637be9 | ||
|
|
7d2b86c548 | ||
|
|
c10ff68ee7 | ||
|
|
b2a8dd13f6 | ||
|
|
fb8ab132e9 | ||
|
|
7ce2e45719 | ||
|
|
c6d15d2605 | ||
|
|
8d57ea4216 | ||
|
|
fdf1bbd1e2 | ||
|
|
662813b378 | ||
|
|
8709ae7113 | ||
|
|
ac22b71171 | ||
|
|
328d1d6546 | ||
|
|
11277d2ef3 | ||
|
|
54dc6102a6 | ||
|
|
c0c9b50a5f | ||
|
|
e780a6fc7c | ||
|
|
fd89b288e5 | ||
|
|
a05c3a5e94 | ||
|
|
43e91c9275 | ||
|
|
26dd2935d7 | ||
|
|
f653871e3a | ||
|
|
89b91a081c | ||
|
|
246b26079b | ||
|
|
41a9e422d5 | ||
|
|
0704d7f4a4 | ||
|
|
1e66742d02 | ||
|
|
d55f827d93 | ||
|
|
40c68d4d63 | ||
|
|
5c58ddc800 | ||
|
|
94171cbc0e | ||
|
|
cf8549bb28 | ||
|
|
a291d73828 | ||
|
|
a6156ec863 | ||
|
|
be583cc86d | ||
|
|
00c55f5e82 | ||
|
|
c9fd1f5252 | ||
|
|
992d1065ac | ||
|
|
247017d19a | ||
|
|
b9fe05c27f | ||
|
|
b01a2cfd79 | ||
|
|
37f2e7eeda | ||
|
|
4ba6ea9190 | ||
|
|
7c1c061681 | ||
|
|
47e4175c9a | ||
|
|
023fd73b86 | ||
|
|
f7ba72217b | ||
|
|
47b9b1dcd6 | ||
|
|
f3adbfef55 | ||
|
|
bc9225f8ed | ||
|
|
62ac0089c9 | ||
|
|
af059141f0 | ||
|
|
efe73a21d9 | ||
|
|
adad299724 | ||
|
|
15b832eefb | ||
|
|
434b6fdc8f | ||
|
|
99c886a9cb | ||
|
|
7d18215bc9 | ||
|
|
7d7f674d9e | ||
|
|
46861486c9 | ||
|
|
d959cacd15 | ||
|
|
d8d0ce5b45 | ||
|
|
b94a4ef9d6 | ||
|
|
212ed8e428 | ||
|
|
6d14bc2f54 | ||
|
|
9dc10c3756 | ||
|
|
316e7be51e | ||
|
|
14842a6d56 | ||
|
|
ce7f3ffca9 | ||
|
|
4c969420f3 | ||
|
|
36aca1e664 | ||
|
|
3a08f57fb1 | ||
|
|
8f86a8aba6 | ||
|
|
e84e02ff07 | ||
|
|
7ef625c598 | ||
|
|
2819e55a61 | ||
|
|
25d9b08dd5 | ||
|
|
6a760c3019 | ||
|
|
8088a464ad | ||
|
|
e41c83a68c | ||
|
|
2d5b8430bd | ||
|
|
eabbe3e3ed | ||
|
|
c37cdbdc5f | ||
|
|
8a0df559c3 | ||
|
|
dfc1c9c228 | ||
|
|
ad20c1cbf1 | ||
|
|
6f4677b36b | ||
|
|
b3a9274cd3 | ||
|
|
7a7bc3e0db | ||
|
|
425bb54057 | ||
|
|
d82df84cf6 | ||
|
|
7d697f068f | ||
|
|
4499b34b51 | ||
|
|
9c6cc8ecd4 | ||
|
|
668130d443 | ||
|
|
5aba690318 | ||
|
|
7397bf389e | ||
|
|
e1b16e9ae3 | ||
|
|
eb50f6fd8f | ||
|
|
5d6dc16a19 | ||
|
|
64dc76d616 | ||
|
|
301664ce93 | ||
|
|
a4534d8f3e | ||
|
|
f161173cb6 | ||
|
|
c58f5efcdd | ||
|
|
65edd2ce22 | ||
|
|
0723f3091c | ||
|
|
a95204f02e | ||
|
|
6dd12e111d | ||
|
|
6e741bd800 | ||
|
|
d37e53bd8e | ||
|
|
fd3585697b | ||
|
|
e92e6ec1c6 | ||
|
|
f0c89cbbba | ||
|
|
d20f932316 | ||
|
|
e011ef469f | ||
|
|
384850b452 | ||
|
|
e467aba32f | ||
|
|
56c51b73b0 | ||
|
|
1aa82dd03e | ||
|
|
a3b7c67ef9 | ||
|
|
de0200f352 | ||
|
|
999c267dfe | ||
|
|
c9a6c2948e | ||
|
|
041157a85f | ||
|
|
cd009936e2 | ||
|
|
f43dfd47d0 | ||
|
|
7082467352 | ||
|
|
f05d3581c1 | ||
|
|
02e560cb18 | ||
|
|
b2d38ad9d6 | ||
|
|
2743f1adc9 | ||
|
|
5e875b6d71 | ||
|
|
6ccb5e8dbf | ||
|
|
ad42a3d41c | ||
|
|
b40e0068ab | ||
|
|
f8dbbc1d11 | ||
|
|
951070757c | ||
|
|
c2a93c6c02 | ||
|
|
9dc82963c4 | ||
|
|
148fce42ba | ||
|
|
92f1263314 | ||
|
|
5fad44369c | ||
|
|
eb3d7c9615 | ||
|
|
5437a98539 | ||
|
|
d9b26f31f8 | ||
|
|
9916ec132b | ||
|
|
1f3806a7bd | ||
|
|
55a770f129 | ||
|
|
d742d595b2 | ||
|
|
9f575902b0 | ||
|
|
6e49cf14fa | ||
|
|
4d96abb786 | ||
|
|
b6d9470a4e | ||
|
|
6ef86dce8c | ||
|
|
5a33f4c707 | ||
|
|
119c1cbb35 | ||
|
|
2be2646d95 | ||
|
|
0609174a14 | ||
|
|
227ca0ed41 | ||
|
|
cc90ccece2 | ||
|
|
9ab92165c8 | ||
|
|
e1fc0d08b7 | ||
|
|
21dad2d72e | ||
|
|
87fe3e72a2 | ||
|
|
c92220f1e5 | ||
|
|
eabeb612b4 | ||
|
|
900e61291a | ||
|
|
51d9f1943b | ||
|
|
282b07dffc | ||
|
|
6521415ae0 | ||
|
|
2819be4508 | ||
|
|
a60805a971 | ||
|
|
af21d33165 | ||
|
|
e465ad58ca | ||
|
|
cd56fc6179 | ||
|
|
1ef70dd4e4 | ||
|
|
a460ea5194 | ||
|
|
5ebf7b7992 | ||
|
|
c9b50e7db6 | ||
|
|
b9993796a0 | ||
|
|
4fb2241621 | ||
|
|
fa49dc08a3 | ||
|
|
3d939f18df | ||
|
|
0d38b9aab1 | ||
|
|
28207f45cd | ||
|
|
72a5e9eb05 | ||
|
|
91dc99d8ef | ||
|
|
305a34b26d | ||
|
|
67349bbce6 | ||
|
|
242ba89b95 | ||
|
|
295280f8cf | ||
|
|
eb0f4728c4 | ||
|
|
8017715bc7 | ||
|
|
503c74c488 | ||
|
|
32cdaa8baa | ||
|
|
83176a0293 | ||
|
|
5db3d14b17 | ||
|
|
bc6ae25aa6 | ||
|
|
8e3900fab7 | ||
|
|
51b3d59094 | ||
|
|
3585645580 | ||
|
|
1e3c20d118 | ||
|
|
f83f13af59 | ||
|
|
54d0bc56a4 | ||
|
|
c722673dbd | ||
|
|
88d34a9daf | ||
|
|
e91237ec05 | ||
|
|
430a2bc08d | ||
|
|
3bbe5d33d3 | ||
|
|
674c6a1684 | ||
|
|
f34519e3ff | ||
|
|
f047be816a | ||
|
|
593c20d62b | ||
|
|
a4bfad6138 | ||
|
|
89de3c5f7a | ||
|
|
81fb664ad9 | ||
|
|
b65597b884 | ||
|
|
d5423947f3 | ||
|
|
f80db23642 | ||
|
|
935906e328 | ||
|
|
3ed7f68054 | ||
|
|
c894b75f4b | ||
|
|
ef43d6905f | ||
|
|
ab7ebedcd5 | ||
|
|
8ca19afd87 | ||
|
|
70e1e550e3 | ||
|
|
cb0087c433 | ||
|
|
d867f86c08 | ||
|
|
1891029eed | ||
|
|
157090a122 | ||
|
|
0ddf2aad79 | ||
|
|
4f47a5032c | ||
|
|
ae957ab642 | ||
|
|
b69a7022b5 | ||
|
|
c19bd88a8e | ||
|
|
4967b70e7c | ||
|
|
cdfad8cc67 | ||
|
|
dcaccaca35 | ||
|
|
d954262184 | ||
|
|
208720545e | ||
|
|
2cbadc6946 | ||
|
|
ebfa49ed8e | ||
|
|
e70c3ef939 | ||
|
|
0523f701c2 | ||
|
|
c6b46295bc | ||
|
|
16ddfb2a20 | ||
|
|
ca5ea6032c | ||
|
|
b4eda0e7cd | ||
|
|
9d2a9bbd9c | ||
|
|
ef13c8fe8d | ||
|
|
aa6932f547 | ||
|
|
5d3c132e83 | ||
|
|
56f4f6c977 | ||
|
|
77df068fea | ||
|
|
b9a1bf9f24 | ||
|
|
2b348916f4 | ||
|
|
70bc5ea2ec | ||
|
|
eff9e553a1 | ||
|
|
e1bfca1883 | ||
|
|
190dbab3d0 | ||
|
|
a1895b1f78 | ||
|
|
1091774003 | ||
|
|
ae29eb35fd | ||
|
|
5ca0a89789 | ||
|
|
6c6e836f0d | ||
|
|
c971d34d67 | ||
|
|
1b04615bff | ||
|
|
40eb8dec68 | ||
|
|
2556e98c26 | ||
|
|
2204da25ed | ||
|
|
ab1eb6de6b | ||
|
|
16278a72e9 | ||
|
|
573a1f22dc | ||
|
|
da370a7dd2 | ||
|
|
6567660639 | ||
|
|
984054f00f | ||
|
|
9351edebe0 | ||
|
|
36465f0859 | ||
|
|
ef5cf4bd96 | ||
|
|
27e1aec001 | ||
|
|
aa9ef65375 | ||
|
|
c8af6d3672 | ||
|
|
ffe5370264 | ||
|
|
ef0156c068 | ||
|
|
00883170f3 | ||
|
|
fb72704a33 | ||
|
|
8f9cd72975 | ||
|
|
913e87c4f5 | ||
|
|
3bdf6df70d | ||
|
|
5e973b21ae | ||
|
|
23e2611725 | ||
|
|
f8784afd72 | ||
|
|
46a73c8ef1 | ||
|
|
bcd80b616d | ||
|
|
b5d870d885 | ||
|
|
f9ac77606e | ||
|
|
ce554ed53f | ||
|
|
27d48f85a9 | ||
|
|
059ff14e6d | ||
|
|
8cfb3569fe | ||
|
|
1ac3e9b364 | ||
|
|
22c6a3da4f | ||
|
|
737405d449 | ||
|
|
e805ae7757 | ||
|
|
d5cf0fee64 | ||
|
|
48e2ae6e52 | ||
|
|
351e784733 | ||
|
|
6c64181bf4 | ||
|
|
d64e6a12a7 | ||
|
|
ccddc9a404 | ||
|
|
aee35aa66d | ||
|
|
0cf953b3eb | ||
|
|
eb073ebe87 | ||
|
|
c3fac64280 | ||
|
|
28ef8e7db7 | ||
|
|
e3eda95b35 | ||
|
|
894a68823f | ||
|
|
dc3843087e | ||
|
|
aaae9fe8bc | ||
|
|
3dc9fc52a7 | ||
|
|
2d373ba509 | ||
|
|
f200e79dc8 | ||
|
|
ae9518a006 | ||
|
|
96c24e8e5f | ||
|
|
cc0c1cc320 | ||
|
|
9834c83126 | ||
|
|
4b8cb5a4e4 | ||
|
|
7e2f473e22 | ||
|
|
ee9f858933 | ||
|
|
69f322d34c | ||
|
|
91099188f2 | ||
|
|
1e7209bafa | ||
|
|
a23a356bf6 | ||
|
|
5218e134a9 | ||
|
|
55a87999e4 | ||
|
|
6cd7861b2c | ||
|
|
6dfaeddc0a | ||
|
|
4846549a90 | ||
|
|
942837b4d9 | ||
|
|
259b4aabcc | ||
|
|
6200b6a4b0 | ||
|
|
6ee1413996 | ||
|
|
08fff1700f | ||
|
|
fd5b7976e7 | ||
|
|
e17637d27b | ||
|
|
57c69a7d6c | ||
|
|
bf3a496ea3 | ||
|
|
3e46db9c11 | ||
|
|
50c624e305 | ||
|
|
6d4e64059a | ||
|
|
ec879b12b3 | ||
|
|
5ace8f5570 | ||
|
|
2fe5a6b248 | ||
|
|
19f5251736 | ||
|
|
a87e3d66a6 | ||
|
|
62acdde68f | ||
|
|
e214573cd1 | ||
|
|
8fff1cd817 | ||
|
|
20eb0c4d64 | ||
|
|
ff05292bdb | ||
|
|
326bc88f19 | ||
|
|
f0a7612369 | ||
|
|
515be5de33 | ||
|
|
e1e7354d85 | ||
|
|
2ec6a06204 | ||
|
|
9150def93e | ||
|
|
730f1a6c47 | ||
|
|
7c12d094c5 | ||
|
|
8aceaf0595 | ||
|
|
5a1bdc156d | ||
|
|
aa81426189 | ||
|
|
7a5d39cc94 | ||
|
|
b1b8f202c9 | ||
|
|
fcfda68d88 | ||
|
|
e966e4c7ed | ||
|
|
42455c72f9 | ||
|
|
ef5f49016e | ||
|
|
6417dfb4a1 | ||
|
|
40985da9ca | ||
|
|
e07c26c17d | ||
|
|
9f2cba49ee | ||
|
|
6e3de21f6e | ||
|
|
a6bdbd7cf1 | ||
|
|
b822428d52 | ||
|
|
03a7df1c98 | ||
|
|
08b7290070 | ||
|
|
6188c698e3 | ||
|
|
7d9b60c16a | ||
|
|
df3c5060e9 | ||
|
|
ff702c9d14 | ||
|
|
ea06fe8cf8 | ||
|
|
f8b0d9b180 | ||
|
|
d3a3e7066d | ||
|
|
45e3964285 | ||
|
|
4edf4936c1 | ||
|
|
067be4973d | ||
|
|
6a3442d058 | ||
|
|
0b83307f7d | ||
|
|
f36042f537 | ||
|
|
668a5d6334 | ||
|
|
eb59713b65 | ||
|
|
fbc6187062 | ||
|
|
274ecaa222 | ||
|
|
051196179d | ||
|
|
cddfc4550d | ||
|
|
465bc3b24a | ||
|
|
38087f0b02 | ||
|
|
3237a539f7 | ||
|
|
828d5764d0 | ||
|
|
15fc3742d2 | ||
|
|
8489b1d943 | ||
|
|
682188540c | ||
|
|
8f740d70e0 | ||
|
|
bc80c2200d | ||
|
|
fd524f627e | ||
|
|
59b3b68bde | ||
|
|
943c8eabbf | ||
|
|
b83918c2aa | ||
|
|
5b4db8fd54 | ||
|
|
c8d7ac48ea | ||
|
|
3cd4e64957 | ||
|
|
2f994628c3 | ||
|
|
f68fc02e57 | ||
|
|
0637b9c8f8 | ||
|
|
7001ddc96f | ||
|
|
fe31a64175 | ||
|
|
cd0cc2b501 | ||
|
|
ebcb3c5466 | ||
|
|
a1d0f3948a | ||
|
|
22f5508bea | ||
|
|
63c4f708c3 | ||
|
|
52fd891370 | ||
|
|
fb447a30e4 | ||
|
|
e0c73e26ee | ||
|
|
d5da5bd8aa | ||
|
|
d84302682e | ||
|
|
c963e93b52 | ||
|
|
c96e3ee2f9 | ||
|
|
a78019ccbc | ||
|
|
e014c94446 | ||
|
|
6c747ff8b4 | ||
|
|
ffd9e9d48e | ||
|
|
3328359ba4 | ||
|
|
66f6c1fd46 | ||
|
|
aaa845a0f8 | ||
|
|
f1157895db | ||
|
|
1277cfed64 | ||
|
|
102fa9c0a8 | ||
|
|
7cd57cadb2 | ||
|
|
2a56b7ade2 | ||
|
|
cf8be3ca21 | ||
|
|
715a1b5df5 | ||
|
|
0a374a0e78 | ||
|
|
36996a54a5 | ||
|
|
3f687e4c4a | ||
|
|
315d373d2d | ||
|
|
6ae346df44 | ||
|
|
9582a27dc6 | ||
|
|
6195d72c3c | ||
|
|
3f0309c36a | ||
|
|
08ea7401cc | ||
|
|
f3d7f09476 | ||
|
|
36150d5b09 | ||
|
|
e5deb2ddd7 | ||
|
|
d60aa54903 | ||
|
|
2627cee938 | ||
|
|
e7f47a4485 | ||
|
|
5bfe56c091 | ||
|
|
f08586ee12 | ||
|
|
af17270c52 | ||
|
|
06b4062003 | ||
|
|
6cba6972bc | ||
|
|
f7a23e629c | ||
|
|
e67b37be28 | ||
|
|
1fa7dfe41f | ||
|
|
e781071ebf | ||
|
|
1697c5d5b5 | ||
|
|
091fefb601 | ||
|
|
7939e6c619 | ||
|
|
f8788dc32c | ||
|
|
4db51bff79 | ||
|
|
6f96da74c7 | ||
|
|
f1692763d3 |
@@ -9,7 +9,7 @@ root = true
|
|||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = tab
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
@@ -26,4 +26,4 @@ indent_style = tab
|
|||||||
|
|
||||||
# HTML, CSS, javascript, JSON and YAML
|
# HTML, CSS, javascript, JSON and YAML
|
||||||
[*.{html,css,js,json,yml,yaml}]
|
[*.{html,css,js,json,yml,yaml}]
|
||||||
indent_size = 2
|
indent_size = 4
|
||||||
|
|||||||
37
.flake8
Normal file
37
.flake8
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
[flake8]
|
||||||
|
ignore =
|
||||||
|
E121,
|
||||||
|
E126,
|
||||||
|
E127,
|
||||||
|
E128,
|
||||||
|
E203,
|
||||||
|
E225,
|
||||||
|
E226,
|
||||||
|
E231,
|
||||||
|
E241,
|
||||||
|
E251,
|
||||||
|
E261,
|
||||||
|
E265,
|
||||||
|
E302,
|
||||||
|
E303,
|
||||||
|
E305,
|
||||||
|
E402,
|
||||||
|
E501,
|
||||||
|
E741,
|
||||||
|
W291,
|
||||||
|
W292,
|
||||||
|
W293,
|
||||||
|
W391,
|
||||||
|
W503,
|
||||||
|
W504,
|
||||||
|
F403,
|
||||||
|
B007,
|
||||||
|
B950,
|
||||||
|
W191,
|
||||||
|
E124, # closing bracket, irritating while writing QB code
|
||||||
|
E131, # continuation line unaligned for hanging indent
|
||||||
|
E123, # closing bracket does not match indentation of opening bracket's line
|
||||||
|
E101, # ensured by use of black
|
||||||
|
|
||||||
|
max-line-length = 200
|
||||||
|
exclude=.github/helper/semgrep_rules
|
||||||
74
.github/helper/flake8.conf
vendored
Normal file
74
.github/helper/flake8.conf
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
[flake8]
|
||||||
|
ignore =
|
||||||
|
B001,
|
||||||
|
B007,
|
||||||
|
B009,
|
||||||
|
B010,
|
||||||
|
B950,
|
||||||
|
E101,
|
||||||
|
E111,
|
||||||
|
E114,
|
||||||
|
E116,
|
||||||
|
E117,
|
||||||
|
E121,
|
||||||
|
E122,
|
||||||
|
E123,
|
||||||
|
E124,
|
||||||
|
E125,
|
||||||
|
E126,
|
||||||
|
E127,
|
||||||
|
E128,
|
||||||
|
E131,
|
||||||
|
E201,
|
||||||
|
E202,
|
||||||
|
E203,
|
||||||
|
E211,
|
||||||
|
E221,
|
||||||
|
E222,
|
||||||
|
E223,
|
||||||
|
E224,
|
||||||
|
E225,
|
||||||
|
E226,
|
||||||
|
E228,
|
||||||
|
E231,
|
||||||
|
E241,
|
||||||
|
E242,
|
||||||
|
E251,
|
||||||
|
E261,
|
||||||
|
E262,
|
||||||
|
E265,
|
||||||
|
E266,
|
||||||
|
E271,
|
||||||
|
E272,
|
||||||
|
E273,
|
||||||
|
E274,
|
||||||
|
E301,
|
||||||
|
E302,
|
||||||
|
E303,
|
||||||
|
E305,
|
||||||
|
E306,
|
||||||
|
E402,
|
||||||
|
E501,
|
||||||
|
E502,
|
||||||
|
E701,
|
||||||
|
E702,
|
||||||
|
E703,
|
||||||
|
E741,
|
||||||
|
F401,
|
||||||
|
F403,
|
||||||
|
F405,
|
||||||
|
W191,
|
||||||
|
W291,
|
||||||
|
W292,
|
||||||
|
W293,
|
||||||
|
W391,
|
||||||
|
W503,
|
||||||
|
W504,
|
||||||
|
E711,
|
||||||
|
E129,
|
||||||
|
F841,
|
||||||
|
E713,
|
||||||
|
E712,
|
||||||
|
|
||||||
|
|
||||||
|
max-line-length = 200
|
||||||
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
- name: setup python
|
- name: setup python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
python-version: '3.9'
|
python-version: '3.10'
|
||||||
- name: setup node
|
- name: setup node
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
@@ -57,15 +57,15 @@ jobs:
|
|||||||
mkdir -p ~/bench-cache
|
mkdir -p ~/bench-cache
|
||||||
(cd && tar czf ~/bench-cache/bench.tgz frappe-bench)
|
(cd && tar czf ~/bench-cache/bench.tgz frappe-bench)
|
||||||
fi
|
fi
|
||||||
- name: add school app to bench
|
- name: add lms app to bench
|
||||||
working-directory: /home/runner/frappe-bench
|
working-directory: /home/runner/frappe-bench
|
||||||
run: bench get-app school $GITHUB_WORKSPACE
|
run: bench get-app lms $GITHUB_WORKSPACE
|
||||||
- name: create bench site
|
- name: create bench site
|
||||||
working-directory: /home/runner/frappe-bench
|
working-directory: /home/runner/frappe-bench
|
||||||
run: bench new-site --mariadb-root-password root --admin-password admin frappe.local
|
run: bench new-site --mariadb-root-password root --admin-password admin frappe.local
|
||||||
- name: install school app
|
- name: install lms app
|
||||||
working-directory: /home/runner/frappe-bench
|
working-directory: /home/runner/frappe-bench
|
||||||
run: bench --verbose --site frappe.local install-app school
|
run: bench --site frappe.local install-app lms
|
||||||
- name: setup requirements
|
- name: setup requirements
|
||||||
working-directory: /home/runner/frappe-bench
|
working-directory: /home/runner/frappe-bench
|
||||||
run: bench setup requirements --dev
|
run: bench setup requirements --dev
|
||||||
@@ -77,5 +77,5 @@ jobs:
|
|||||||
run: bench --site frappe.local build
|
run: bench --site frappe.local build
|
||||||
- name: run tests
|
- name: run tests
|
||||||
working-directory: /home/runner/frappe-bench
|
working-directory: /home/runner/frappe-bench
|
||||||
run: bench --site frappe.local run-tests --app school
|
run: bench --site frappe.local run-tests --app lms
|
||||||
|
|
||||||
|
|||||||
33
.github/workflows/linters.yml
vendored
Normal file
33
.github/workflows/linters.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Linters
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
linters:
|
||||||
|
name: Semantic Commits
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.10'
|
||||||
|
|
||||||
|
- name: Install and Run Pre-commit
|
||||||
|
uses: pre-commit/action@v2.0.3
|
||||||
|
|
||||||
|
- name: Download Semgrep rules
|
||||||
|
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||||
|
|
||||||
|
- name: Download semgrep
|
||||||
|
run: pip install semgrep
|
||||||
|
|
||||||
|
- name: Run Semgrep rules
|
||||||
|
run: semgrep ci --config ./frappe-semgrep-rules/rules
|
||||||
19
.github/workflows/semantic.yml
vendored
Normal file
19
.github/workflows/semantic.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: Semantic Pull Request
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request: {}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# This workflow contains a single job called "build"
|
||||||
|
semantic:
|
||||||
|
name: Validate PR title
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
|
steps:
|
||||||
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- uses: zeke/semantic-pull-requests@main
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,8 +3,8 @@
|
|||||||
*.egg-info
|
*.egg-info
|
||||||
*.swp
|
*.swp
|
||||||
tags
|
tags
|
||||||
school/docs/current
|
lms/docs/current
|
||||||
school/public/dist
|
lms/public/dist
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
|||||||
59
.pre-commit-config.yaml
Normal file
59
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
exclude: 'node_modules|.git'
|
||||||
|
default_stages: [commit]
|
||||||
|
fail_fast: false
|
||||||
|
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.3.0
|
||||||
|
hooks:
|
||||||
|
- id: trailing-whitespace
|
||||||
|
files: "frappe.*"
|
||||||
|
exclude: ".*json$|.*txt$|.*csv|.*md|.*svg"
|
||||||
|
- id: check-yaml
|
||||||
|
- id: no-commit-to-branch
|
||||||
|
args: ['--branch', 'main']
|
||||||
|
- id: check-merge-conflict
|
||||||
|
- id: check-ast
|
||||||
|
- id: check-json
|
||||||
|
- id: check-toml
|
||||||
|
- id: debug-statements
|
||||||
|
|
||||||
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
|
rev: v2.34.0
|
||||||
|
hooks:
|
||||||
|
- id: pyupgrade
|
||||||
|
args: ['--py310-plus']
|
||||||
|
|
||||||
|
- repo: https://github.com/adityahase/black
|
||||||
|
rev: 9cb0a69f4d0030cdf687eddf314468b39ed54119
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
|
additional_dependencies: ['click==8.0.4']
|
||||||
|
|
||||||
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
|
rev: v2.7.1
|
||||||
|
hooks:
|
||||||
|
- id: prettier
|
||||||
|
types_or: [javascript]
|
||||||
|
# Ignore any files that might contain jinja / bundles
|
||||||
|
exclude: |
|
||||||
|
(?x)^(
|
||||||
|
lms/public/dist/.*|
|
||||||
|
.*node_modules.*|
|
||||||
|
.*boilerplate.*|
|
||||||
|
lms/www/website_script.js|
|
||||||
|
lms/templates/includes/.*|
|
||||||
|
lms/public/js/lib/.*
|
||||||
|
)$
|
||||||
|
|
||||||
|
- repo: https://github.com/PyCQA/flake8
|
||||||
|
rev: 5.0.4
|
||||||
|
hooks:
|
||||||
|
- id: flake8
|
||||||
|
additional_dependencies: ['flake8-bugbear',]
|
||||||
|
args: ['--config', '.github/helper/flake8.conf']
|
||||||
|
|
||||||
|
ci:
|
||||||
|
autoupdate_schedule: weekly
|
||||||
|
skip: []
|
||||||
|
submodules: false
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
1. Go to the apps/school directory of your installation and execute git pull --unshallow to ensure that you have the full git repository. Also fork the frappe/school repository on GitHub.
|
1. Go to the apps/lms directory of your installation and execute git pull --unshallow to ensure that you have the full git repository. Also fork the frappe/lms repository on GitHub.
|
||||||
1. Check out a working branch in git (e.g. git checkout -b my-new-branch).
|
1. Check out a working branch in git (e.g. git checkout -b my-new-branch).
|
||||||
1. Make your proposed changes to the source
|
1. Make your proposed changes to the source
|
||||||
1. Run your local version (e.g. bench start in your bench installation). Make sure that your changes work the way you want them to.
|
1. Run your local version (e.g. bench start in your bench installation). Make sure that your changes work the way you want them to.
|
||||||
|
|||||||
24
MANIFEST.in
24
MANIFEST.in
@@ -4,15 +4,15 @@ include *.json
|
|||||||
include *.md
|
include *.md
|
||||||
include *.py
|
include *.py
|
||||||
include *.txt
|
include *.txt
|
||||||
recursive-include school *.css
|
recursive-include lms *.css
|
||||||
recursive-include school *.csv
|
recursive-include lms *.csv
|
||||||
recursive-include school *.html
|
recursive-include lms *.html
|
||||||
recursive-include school *.ico
|
recursive-include lms *.ico
|
||||||
recursive-include school *.js
|
recursive-include lms *.js
|
||||||
recursive-include school *.json
|
recursive-include lms *.json
|
||||||
recursive-include school *.md
|
recursive-include lms *.md
|
||||||
recursive-include school *.png
|
recursive-include lms *.png
|
||||||
recursive-include school *.py
|
recursive-include lms *.py
|
||||||
recursive-include school *.svg
|
recursive-include lms *.svg
|
||||||
recursive-include school *.txt
|
recursive-include lms *.txt
|
||||||
recursive-exclude school *.pyc
|
recursive-exclude lms *.pyc
|
||||||
|
|||||||
91
README.md
91
README.md
@@ -1,25 +1,90 @@
|
|||||||
## School
|
<p align="center">
|
||||||
|
<a href="https://www.frappelms.com/">
|
||||||
|
<img src="https://www.frappelms.com/files/flms.svg" alt="Frappe LMS" width="100" height="100">
|
||||||
|
</a>
|
||||||
|
<p align="center">Easy to use, open source, learning management system.</p>
|
||||||
|
</p>
|
||||||
|
|
||||||
Create online courses without much hassle.
|
<p align="center">
|
||||||
|
<a href="https://github.com/frappe/lms/blob/main/LICENSE">
|
||||||
|
<img alt="license" src="https://img.shields.io/badge/license-AGPLv3-blue">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||

|
<img width="1402" alt="Lesson" src="https://frappelms.com/files/fs-banner71f330.png">
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Show more screenshots</summary>
|
||||||
|
<img width="1520" alt="ss1" src="https://user-images.githubusercontent.com/31363128/210056046-584bc8aa-d28c-4514-b031-73817012837d.png">
|
||||||
|
<img width="830" alt="ss2" src="https://user-images.githubusercontent.com/31363128/210056097-36849182-6db0-43a2-8c62-5333cd2aedf4.png">
|
||||||
|
<img width="941" alt="ss3" src="https://user-images.githubusercontent.com/31363128/210056134-01a7c429-1ef4-434e-9d43-128dda35d7e5.png">
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Frappe LMS is an easy-to-use, open-source learning management system. You can use it to create and share online courses. The app has a clear UI that helps students focus only on what's important and assists in distraction-free learning.
|
||||||
|
|
||||||
|
You can create courses and lessons through simple forms. Lessons can be in the form of text, videos, quizzes or a combination of all these. You can keep your students engaged with quizzes to help revise and test the concepts learned. Course Instructors and Students can reach out to each other through the discussions section available for each lesson and get queries resolved.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
- Create online courses. 📚
|
||||||
|
- Add detailed descriptions and preview videos to the course. 🎬
|
||||||
|
- Add videos, quizzes, and assignments to your lessons and make them interesting and interactive 📝
|
||||||
|
- Discussions section below each lesson where instructors and students can interact with each other. 💬
|
||||||
|
- Create classes to group your students based on courses and track their progress 🏛
|
||||||
|
- Statistics dashboard that provides all important numbers at a glimpse. 📈
|
||||||
|
- Job Board where users can post and look for jobs. 💼
|
||||||
|
- People directory with each person's profile page 👨👩👧👦
|
||||||
|
- Set cover image, profile photo, short bio, and other professional information. 🦹🏼♀️
|
||||||
|
- Simple layout that optimizes readability 🤓
|
||||||
|
- Delightful user experience in overall usage ✨
|
||||||
|
|
||||||
1. Simple Backend Forms.
|
## Tech Stack
|
||||||
1. The UI is clean and minimal.
|
|
||||||
1. Lessons can be in the form of texts, videos, quizzes or a combination of all of these.
|
|
||||||
|
|
||||||
## Development Setup
|
Frappe LMS is built on [Frappe Framework](https://frappeframework.com) which is a batteries-included python web framework.
|
||||||
|
These are some of the tools it's built on:
|
||||||
|
- [Python](https://www.python.org)
|
||||||
|
- [Redis](https://redis.io/)
|
||||||
|
- [MariaDB](https://mariadb.org/)
|
||||||
|
- [Socket.io](https://socket.io/)
|
||||||
|
|
||||||
1. [Through Docker](docker-installation.md)
|
## Local Setup
|
||||||
1. [Direct install through bench](bench-installation.md)
|
|
||||||
|
### Docker
|
||||||
|
You need Docker, docker-compose, and git setup on your machine. Refer to [Docker documentation](https://docs.docker.com/). After that, run the following commands:
|
||||||
|
```
|
||||||
|
git clone https://github.com/frappe/lms
|
||||||
|
cd lms/docker
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
Wait for some time until the setup script creates a site. After that, you can access `http://localhost:8000` in your browser and the app's login screen should show up.
|
||||||
|
|
||||||
|
### Frappe Bench
|
||||||
|
|
||||||
|
Currently, this app depends on the `develop` branch of [frappe](https://github.com/frappe/frappe).
|
||||||
|
|
||||||
|
1. Setup frappe-bench by following [this guide](https://frappeframework.com/docs/v14/user/en/installation)
|
||||||
|
1. In the frappe-bench directory, run `bench start` and keep it running. Open a new terminal session and cd into the `frappe-bench` directory.
|
||||||
|
1. Run the following commands:
|
||||||
|
```sh
|
||||||
|
bench new-site lms.test
|
||||||
|
bench get-app lms
|
||||||
|
bench --site lms.test install-app lms
|
||||||
|
bench --site lms.test add-to-hosts
|
||||||
|
|
||||||
|
1. Now, you can access the site at `http://gameplan.test:8080`
|
||||||
|
|
||||||
|
|
||||||
### Contributing
|
## Deployment
|
||||||
|
Frappe LMS is an app built on top of the Frappe Framework. So, you can follow any deployment guide for hosting a Frappe Framework-based site.
|
||||||
|
|
||||||
1. [Contribution Guidelines](Contribution.md)
|
### Managed Hosting
|
||||||
|
Frappe LMS can be deployed in a few clicks on [Frappe Cloud](https://frappecloud.com/marketplace/apps/lms).
|
||||||
|
|
||||||
|
### Self-hosting
|
||||||
|
If you want to self-host, you can follow official [Frappe Bench Installation](https://github.com/frappe/bench#installation) instructions.
|
||||||
|
|
||||||
|
## Bugs and Feature Requests
|
||||||
|
If you find any bugs or have a feature idea for the app, feel free to report them here on [GitHub Issues](https://github.com/frappe/lms/issues). Make sure you share enough information (app screenshots, browser console screenshots, stack traces, etc) for project maintainers.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
Distributed under [GNU AFFERO GENERAL PUBLIC LICENSE](license.txt)
|
||||||
[GNU AFFERO GENERAL PUBLIC LICENSE](license.txt)
|
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ 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. 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. Start the server by running bench start.
|
||||||
1. In a separate terminal window, create a new site by running bench new-site school.test.
|
1. In a separate terminal window, create a new site by running bench new-site lms.test.
|
||||||
1. Fork the school app
|
1. Fork the LMS app
|
||||||
1. Run bench get-app <url-of-your-form>.
|
1. Run bench get-app <url-of-your-form>.
|
||||||
1. Run bench --site school.test install-app school.
|
1. Run bench --site lms.test install-app lms.
|
||||||
1. Map your site to localhost with the command ```bench --site school.test add-to-hosts```
|
1. Map your site to localhost with the command ```bench --site lms.test add-to-hosts```
|
||||||
1. Now open the URL http://school.test:8000/ in your browser, you should see the app running.
|
1. Now open the URL http://lms.test:8000/ in your browser, you should see the app running.
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
version: "3"
|
|
||||||
|
|
||||||
services:
|
|
||||||
mariadb:
|
|
||||||
image: mariadb
|
|
||||||
volumes:
|
|
||||||
- mariadb-storage:/var/lib/mysql
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=root
|
|
||||||
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
|
|
||||||
bench:
|
|
||||||
image: anandology/frappe-bench:2021.10
|
|
||||||
volumes:
|
|
||||||
- .:/opt/frappe-bench/apps/school
|
|
||||||
environment:
|
|
||||||
- FRAPPE_APPS=school
|
|
||||||
- FRAPPE_ALLOW_TESTS=true
|
|
||||||
- FRAPPE_SITE_NAME=frappe.localhost
|
|
||||||
depends_on:
|
|
||||||
- mariadb
|
|
||||||
ports:
|
|
||||||
- 8000:8000
|
|
||||||
- 9000:9000
|
|
||||||
volumes:
|
|
||||||
mariadb-storage: {}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
**Step 1:** Clone the repo
|
**Step 1:** Clone the repo
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone https://github.com/frappe/school.git
|
$ git clone https://github.com/frappe/lms.git
|
||||||
|
|
||||||
$ cd school
|
$ cd lms
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 2:** Run docker-compose
|
**Step 2:** Run docker-compose
|
||||||
|
|||||||
32
docker/docker-compose.yml
Normal file
32
docker/docker-compose.yml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
version: "3.7"
|
||||||
|
name: lms
|
||||||
|
services:
|
||||||
|
mariadb:
|
||||||
|
image: mariadb:10.6
|
||||||
|
command:
|
||||||
|
- --character-set-server=utf8mb4
|
||||||
|
- --collation-server=utf8mb4_unicode_ci
|
||||||
|
- --skip-character-set-client-handshake
|
||||||
|
- --skip-innodb-read-only-compressed # Temporary fix for MariaDB 10.6
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: 123
|
||||||
|
volumes:
|
||||||
|
- mariadb-data:/var/lib/mysql
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:alpine
|
||||||
|
|
||||||
|
frappe:
|
||||||
|
image: frappe/bench:latest
|
||||||
|
command: bash /workspace/init.sh
|
||||||
|
environment:
|
||||||
|
- SHELL=/bin/bash
|
||||||
|
working_dir: /home/frappe
|
||||||
|
volumes:
|
||||||
|
- .:/workspace
|
||||||
|
ports:
|
||||||
|
- 8000:8000
|
||||||
|
- 9000:9000
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
mariadb-data:
|
||||||
39
docker/init.sh
Normal file
39
docker/init.sh
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#!bin/bash
|
||||||
|
|
||||||
|
if [ -d "/home/frappe/frappe-bench/apps/frappe" ]; then
|
||||||
|
echo "Bench already exists, skipping init"
|
||||||
|
cd frappe-bench
|
||||||
|
bench start
|
||||||
|
else
|
||||||
|
echo "Creating new bench..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
bench init --skip-redis-config-generation frappe-bench
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# Remove redis, watch from Procfile
|
||||||
|
sed -i '/redis/d' ./Procfile
|
||||||
|
sed -i '/watch/d' ./Procfile
|
||||||
|
|
||||||
|
bench get-app lms
|
||||||
|
|
||||||
|
bench new-site lms.localhost \
|
||||||
|
--force \
|
||||||
|
--mariadb-root-password 123 \
|
||||||
|
--admin-password admin \
|
||||||
|
--no-mariadb-socket
|
||||||
|
|
||||||
|
bench --site lms.localhost install-app lms
|
||||||
|
bench --site lms.localhost set-config developer_mode 1
|
||||||
|
bench --site lms.localhost clear-cache
|
||||||
|
bench --site lms.localhost set-config mute_emails 1
|
||||||
|
bench use lms.localhost
|
||||||
|
|
||||||
|
bench start
|
||||||
1
lms/__init__.py
Normal file
1
lms/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__version__ = "0.0.1"
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
from frappe import _
|
from frappe import _
|
||||||
|
|
||||||
|
|
||||||
def get_data():
|
def get_data():
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -9,6 +8,6 @@ def get_data():
|
|||||||
"color": "grey",
|
"color": "grey",
|
||||||
"icon": "octicon octicon-file-directory",
|
"icon": "octicon octicon-file-directory",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"label": _("Community")
|
"label": _("Community"),
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -7,5 +7,6 @@ Configuration for docs
|
|||||||
# headline = "App that does everything"
|
# headline = "App that does everything"
|
||||||
# sub_heading = "Yes, you got that right the first time, everything"
|
# sub_heading = "Yes, you got that right the first time, everything"
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
context.brand_html = "Community"
|
context.brand_html = "Community"
|
||||||
2016
lms/fixtures/custom_field.json
Normal file
2016
lms/fixtures/custom_field.json
Normal file
File diff suppressed because it is too large
Load Diff
114
lms/fixtures/function.json
Normal file
114
lms/fixtures/function.json
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Consulting",
|
||||||
|
"modified": "2021-12-14 15:16:26.189604",
|
||||||
|
"name": "Consulting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Data & Analytics",
|
||||||
|
"modified": "2021-12-14 15:16:26.341051",
|
||||||
|
"name": "Data & Analytics"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Design & Creative",
|
||||||
|
"modified": "2021-12-14 15:16:26.343820",
|
||||||
|
"name": "Design & Creative"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Engineering (Non Software)",
|
||||||
|
"modified": "2021-12-14 15:16:26.346329",
|
||||||
|
"name": "Engineering (Non Software)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Finance, Investment & Accounting",
|
||||||
|
"modified": "2021-12-14 15:16:26.351518",
|
||||||
|
"name": "Finance, Investment & Accounting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Human Resource & Recruiting",
|
||||||
|
"modified": "2021-12-14 15:16:26.354310",
|
||||||
|
"name": "Human Resource & Recruiting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Legal",
|
||||||
|
"modified": "2021-12-14 15:16:26.356844",
|
||||||
|
"name": "Legal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Marketing, Advertising & PR",
|
||||||
|
"modified": "2021-12-14 15:16:26.359511",
|
||||||
|
"name": "Marketing, Advertising & PR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Operations & Admin",
|
||||||
|
"modified": "2021-12-14 15:16:26.362571",
|
||||||
|
"name": "Operations & Admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Project Management",
|
||||||
|
"modified": "2021-12-14 15:16:26.365033",
|
||||||
|
"name": "Project Management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Product",
|
||||||
|
"modified": "2021-12-14 15:16:26.367804",
|
||||||
|
"name": "Product"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Research, Training & Education",
|
||||||
|
"modified": "2021-12-14 15:16:26.370085",
|
||||||
|
"name": "Research, Training & Education"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Sales & Customer Service",
|
||||||
|
"modified": "2021-12-14 15:16:26.372635",
|
||||||
|
"name": "Sales & Customer Service"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Supply Chain, Logistics Strategy & Management",
|
||||||
|
"modified": "2021-12-14 15:16:26.375091",
|
||||||
|
"name": "Supply Chain, Logistics Strategy & Management"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Other",
|
||||||
|
"modified": "2021-12-14 15:16:26.377761",
|
||||||
|
"name": "Other"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Function",
|
||||||
|
"function": "Engineering (Software & IT)",
|
||||||
|
"modified": "2021-12-14 15:16:26.348864",
|
||||||
|
"name": "Engineering (Software & IT)"
|
||||||
|
}
|
||||||
|
]
|
||||||
170
lms/fixtures/industry.json
Normal file
170
lms/fixtures/industry.json
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Accounting",
|
||||||
|
"modified": "2021-12-14 15:21:18.044741",
|
||||||
|
"name": "Accounting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Ads, Marketing, PR & Events",
|
||||||
|
"modified": "2021-12-14 15:21:18.069794",
|
||||||
|
"name": "Ads, Marketing, PR & Events"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Agriculture, Fishing & Forestry",
|
||||||
|
"modified": "2021-12-14 15:21:18.074148",
|
||||||
|
"name": "Agriculture, Fishing & Forestry"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Architecture",
|
||||||
|
"modified": "2021-12-14 15:21:18.078250",
|
||||||
|
"name": "Architecture"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Aviation & Aerospace",
|
||||||
|
"modified": "2021-12-14 15:21:18.082127",
|
||||||
|
"name": "Aviation & Aerospace"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Banking, Financial Services & Insurance",
|
||||||
|
"modified": "2021-12-14 15:21:18.087499",
|
||||||
|
"name": "Banking, Financial Services & Insurance"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Biotech & Pharmaceuticals",
|
||||||
|
"modified": "2021-12-14 15:21:18.092094",
|
||||||
|
"name": "Biotech & Pharmaceuticals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Construction & Real Estate",
|
||||||
|
"modified": "2021-12-14 15:21:18.095728",
|
||||||
|
"name": "Construction & Real Estate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Consulting & Professional Services",
|
||||||
|
"modified": "2021-12-14 15:21:18.099171",
|
||||||
|
"name": "Consulting & Professional Services"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Energy & Utilities",
|
||||||
|
"modified": "2021-12-14 15:21:18.114022",
|
||||||
|
"name": "Energy & Utilities"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Food & Beverages",
|
||||||
|
"modified": "2021-12-14 15:21:18.124655",
|
||||||
|
"name": "Food & Beverages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Health & Medical",
|
||||||
|
"modified": "2021-12-14 15:21:18.127914",
|
||||||
|
"name": "Health & Medical"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Hospitality & Tourism",
|
||||||
|
"modified": "2021-12-14 15:21:18.130783",
|
||||||
|
"name": "Hospitality & Tourism"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "IT / Ecommerce / Internet",
|
||||||
|
"modified": "2021-12-14 15:21:18.134069",
|
||||||
|
"name": "IT / Ecommerce / Internet"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Manufacturing & Production",
|
||||||
|
"modified": "2021-12-14 15:21:18.137362",
|
||||||
|
"name": "Manufacturing & Production"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Media & Entertainment",
|
||||||
|
"modified": "2021-12-14 15:21:18.140180",
|
||||||
|
"name": "Media & Entertainment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Public Service & NGOs",
|
||||||
|
"modified": "2021-12-14 15:21:18.143125",
|
||||||
|
"name": "Public Service & NGOs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Retail, Fashion & FMCG",
|
||||||
|
"modified": "2021-12-14 15:21:18.146020",
|
||||||
|
"name": "Retail, Fashion & FMCG"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Staffing & Recruiting",
|
||||||
|
"modified": "2021-12-14 15:21:18.149084",
|
||||||
|
"name": "Staffing & Recruiting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Transportation & Logistics",
|
||||||
|
"modified": "2021-12-14 15:21:18.151952",
|
||||||
|
"name": "Transportation & Logistics"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Security & Law Enforcement",
|
||||||
|
"modified": "2021-12-14 15:21:18.154929",
|
||||||
|
"name": "Security & Law Enforcement"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Other",
|
||||||
|
"modified": "2021-12-14 15:21:18.157766",
|
||||||
|
"name": "Other"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Education & Training",
|
||||||
|
"modified": "2021-12-14 15:21:18.105864",
|
||||||
|
"name": "Education & Training"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Industry",
|
||||||
|
"industry": "Engineering",
|
||||||
|
"modified": "2021-12-14 15:21:18.119149",
|
||||||
|
"name": "Engineering"
|
||||||
|
}
|
||||||
|
]
|
||||||
292
lms/hooks.py
Normal file
292
lms/hooks.py
Normal file
@@ -0,0 +1,292 @@
|
|||||||
|
from . import __version__ as app_version
|
||||||
|
|
||||||
|
app_name = "frappe_lms"
|
||||||
|
app_title = "Frappe LMS"
|
||||||
|
app_publisher = "Frappe"
|
||||||
|
app_description = "Frappe LMS App"
|
||||||
|
app_icon = "octicon octicon-file-directory"
|
||||||
|
app_color = "grey"
|
||||||
|
app_email = "school@frappe.io"
|
||||||
|
app_license = "AGPL"
|
||||||
|
|
||||||
|
# Includes in <head>
|
||||||
|
# ------------------
|
||||||
|
|
||||||
|
# include js, css files in header of desk.html
|
||||||
|
# app_include_css = "/assets/lms/css/lms.css"
|
||||||
|
# app_include_js = "/assets/lms/js/lms.js"
|
||||||
|
|
||||||
|
# include js, css files in header of web template
|
||||||
|
web_include_css = "lms.bundle.css"
|
||||||
|
# web_include_css = "/assets/lms/css/lms.css"
|
||||||
|
web_include_js = ["website.bundle.js"]
|
||||||
|
|
||||||
|
# include custom scss in every website theme (without file extension ".scss")
|
||||||
|
# website_theme_scss = "lms/public/scss/website"
|
||||||
|
|
||||||
|
# include js, css files in header of web form
|
||||||
|
# webform_include_js = {"doctype": "public/js/doctype.js"}
|
||||||
|
# webform_include_css = {"doctype": "public/css/doctype.css"}
|
||||||
|
|
||||||
|
# include js in page
|
||||||
|
# page_js = {"page" : "public/js/file.js"}
|
||||||
|
|
||||||
|
# include js in doctype views
|
||||||
|
# doctype_js = {"doctype" : "public/js/doctype.js"}
|
||||||
|
# doctype_list_js = {"doctype" : "public/js/doctype_list.js"}
|
||||||
|
# doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"}
|
||||||
|
# doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"}
|
||||||
|
|
||||||
|
# Home Pages
|
||||||
|
# ----------
|
||||||
|
|
||||||
|
# application home page (will override Website Settings)
|
||||||
|
# home_page = "login"
|
||||||
|
|
||||||
|
# website user home page (by Role)
|
||||||
|
# role_home_page = {
|
||||||
|
# "Role": "home_page"
|
||||||
|
# }
|
||||||
|
|
||||||
|
# Generators
|
||||||
|
# ----------
|
||||||
|
|
||||||
|
# automatically create page for each record of this doctype
|
||||||
|
# website_generators = ["Web Page"]
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
# ------------
|
||||||
|
|
||||||
|
# before_install = "lms.install.before_install"
|
||||||
|
after_install = "lms.install.after_install"
|
||||||
|
after_sync = "lms.install.after_sync"
|
||||||
|
after_uninstall = "lms.install.after_uninstall"
|
||||||
|
|
||||||
|
|
||||||
|
setup_wizard_requires = "assets/lms/js/setup_wizard.js"
|
||||||
|
|
||||||
|
# Desk Notifications
|
||||||
|
# ------------------
|
||||||
|
# See frappe.core.notifications.get_notification_config
|
||||||
|
|
||||||
|
# notification_config = "lms.notifications.get_notification_config"
|
||||||
|
|
||||||
|
# Permissions
|
||||||
|
# -----------
|
||||||
|
# Permissions evaluated in scripted ways
|
||||||
|
|
||||||
|
# permission_query_conditions = {
|
||||||
|
# "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions",
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# has_permission = {
|
||||||
|
# "Event": "frappe.desk.doctype.event.event.has_permission",
|
||||||
|
# }
|
||||||
|
|
||||||
|
# DocType Class
|
||||||
|
# ---------------
|
||||||
|
# Override standard doctype classes
|
||||||
|
|
||||||
|
override_doctype_class = {
|
||||||
|
"User": "lms.overrides.user.CustomUser",
|
||||||
|
"Web Template": "lms.overrides.web_template.CustomWebTemplate",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Document Events
|
||||||
|
# ---------------
|
||||||
|
# Hook on document methods and events
|
||||||
|
|
||||||
|
doc_events = {
|
||||||
|
"Discussion Reply": {"after_insert": "lms.lms.utils.create_notification_log"},
|
||||||
|
"Course Lesson": {"on_update": "lms.lms.doctype.lms_quiz.lms_quiz.update_lesson_info"},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Scheduled Tasks
|
||||||
|
# ---------------
|
||||||
|
# scheduler_events = {
|
||||||
|
# "daily": [
|
||||||
|
# "erpnext.stock.reorder_item.reorder_item"
|
||||||
|
# ]
|
||||||
|
# }
|
||||||
|
|
||||||
|
fixtures = ["Custom Field", "Function", "Industry"]
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
# -------
|
||||||
|
|
||||||
|
# before_tests = "lms.install.before_tests"
|
||||||
|
|
||||||
|
# Overriding Methods
|
||||||
|
# ------------------------------
|
||||||
|
#
|
||||||
|
# override_whitelisted_methods = {
|
||||||
|
# "frappe.desk.doctype.event.event.get_events": "lms.event.get_events"
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# each overriding function accepts a `data` argument;
|
||||||
|
# generated from the base implementation of the doctype dashboard,
|
||||||
|
# along with any modifications made in other Frappe apps
|
||||||
|
# override_doctype_dashboards = {
|
||||||
|
# "Task": "lms.task.get_dashboard_data"
|
||||||
|
# }
|
||||||
|
|
||||||
|
# exempt linked doctypes from being automatically cancelled
|
||||||
|
#
|
||||||
|
# auto_cancel_exempted_doctypes = ["Auto Repeat"]
|
||||||
|
|
||||||
|
# Add all simple route rules here
|
||||||
|
website_route_rules = [
|
||||||
|
{"from_route": "/sketches/<sketch>", "to_route": "sketches/sketch"},
|
||||||
|
{"from_route": "/courses/<course>", "to_route": "courses/course"},
|
||||||
|
{"from_route": "/courses/<course>/<certificate>", "to_route": "courses/certificate"},
|
||||||
|
{"from_route": "/courses/<course>/learn", "to_route": "batch/learn"},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/learn/<int:chapter>.<int:lesson>",
|
||||||
|
"to_route": "batch/learn",
|
||||||
|
},
|
||||||
|
{"from_route": "/quizzes", "to_route": "batch/quiz_list"},
|
||||||
|
{"from_route": "/quizzes/<quizname>", "to_route": "batch/quiz"},
|
||||||
|
{"from_route": "/classes/<classname>", "to_route": "classes/class"},
|
||||||
|
{"from_route": "/courses/<course>/progress", "to_route": "batch/progress"},
|
||||||
|
{"from_route": "/courses/<course>/join", "to_route": "batch/join"},
|
||||||
|
{"from_route": "/courses/<course>/manage", "to_route": "cohorts"},
|
||||||
|
{"from_route": "/courses/<course>/cohorts/<cohort>", "to_route": "cohorts/cohort"},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/cohorts/<cohort>/<page>",
|
||||||
|
"to_route": "cohorts/cohort",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>",
|
||||||
|
"to_route": "cohorts/subgroup",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/subgroups/<cohort>/<subgroup>/<page>",
|
||||||
|
"to_route": "cohorts/subgroup",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"from_route": "/courses/<course>/join/<cohort>/<subgroup>/<invite_code>",
|
||||||
|
"to_route": "cohorts/join",
|
||||||
|
},
|
||||||
|
{"from_route": "/users", "to_route": "profiles/profile"},
|
||||||
|
{"from_route": "/jobs/<job>", "to_route": "jobs/job"},
|
||||||
|
{
|
||||||
|
"from_route": "/classes/<classname>/students/<username>",
|
||||||
|
"to_route": "/classes/progress",
|
||||||
|
},
|
||||||
|
{"from_route": "/assignments/<assignment>", "to_route": "assignments/assignment"},
|
||||||
|
]
|
||||||
|
|
||||||
|
website_redirects = [
|
||||||
|
{"source": "/update-profile", "target": "/edit-profile"},
|
||||||
|
{"source": "/dashboard", "target": "/courses"},
|
||||||
|
]
|
||||||
|
|
||||||
|
update_website_context = [
|
||||||
|
"lms.widgets.update_website_context",
|
||||||
|
]
|
||||||
|
|
||||||
|
jinja = {
|
||||||
|
"methods": [
|
||||||
|
"lms.page_renderers.get_profile_url",
|
||||||
|
"lms.overrides.user.get_enrolled_courses",
|
||||||
|
"lms.overrides.user.get_course_membership",
|
||||||
|
"lms.overrides.user.get_authored_courses",
|
||||||
|
"lms.overrides.user.get_palette",
|
||||||
|
"lms.lms.utils.get_membership",
|
||||||
|
"lms.lms.utils.get_lessons",
|
||||||
|
"lms.lms.utils.get_tags",
|
||||||
|
"lms.lms.utils.get_instructors",
|
||||||
|
"lms.lms.utils.get_students",
|
||||||
|
"lms.lms.utils.get_average_rating",
|
||||||
|
"lms.lms.utils.is_certified",
|
||||||
|
"lms.lms.utils.get_lesson_index",
|
||||||
|
"lms.lms.utils.get_lesson_url",
|
||||||
|
"lms.lms.utils.get_chapters",
|
||||||
|
"lms.lms.utils.get_slugified_chapter_title",
|
||||||
|
"lms.lms.utils.get_progress",
|
||||||
|
"lms.lms.utils.render_html",
|
||||||
|
"lms.lms.utils.is_mentor",
|
||||||
|
"lms.lms.utils.is_cohort_staff",
|
||||||
|
"lms.lms.utils.get_mentors",
|
||||||
|
"lms.lms.utils.get_reviews",
|
||||||
|
"lms.lms.utils.is_eligible_to_review",
|
||||||
|
"lms.lms.utils.get_initial_members",
|
||||||
|
"lms.lms.utils.get_sorted_reviews",
|
||||||
|
"lms.lms.utils.is_instructor",
|
||||||
|
"lms.lms.utils.convert_number_to_character",
|
||||||
|
"lms.lms.utils.get_signup_optin_checks",
|
||||||
|
"lms.lms.utils.get_popular_courses",
|
||||||
|
"lms.lms.utils.format_amount",
|
||||||
|
"lms.lms.utils.first_lesson_exists",
|
||||||
|
"lms.lms.utils.get_courses_under_review",
|
||||||
|
"lms.lms.utils.has_course_instructor_role",
|
||||||
|
"lms.lms.utils.has_course_moderator_role",
|
||||||
|
"lms.lms.utils.get_certificates",
|
||||||
|
"lms.lms.utils.format_number",
|
||||||
|
"lms.lms.utils.get_lesson_count",
|
||||||
|
"lms.lms.utils.get_all_memberships",
|
||||||
|
"lms.lms.utils.get_filtered_membership",
|
||||||
|
"lms.lms.utils.show_start_learing_cta",
|
||||||
|
"lms.lms.utils.can_create_courses",
|
||||||
|
],
|
||||||
|
"filters": [],
|
||||||
|
}
|
||||||
|
## Specify the additional tabs to be included in the user profile page.
|
||||||
|
## Each entry must be a subclass of lms.lms.plugins.ProfileTab
|
||||||
|
# profile_tabs = []
|
||||||
|
|
||||||
|
## Specify the extension to be used to control what scripts and stylesheets
|
||||||
|
## to be included in lesson pages. The specified value must be be a
|
||||||
|
## subclass of lms.plugins.PageExtension
|
||||||
|
# lms_lesson_page_extension = None
|
||||||
|
|
||||||
|
# lms_lesson_page_extensions = [
|
||||||
|
# "lms.plugins.LiveCodeExtension"
|
||||||
|
# ]
|
||||||
|
|
||||||
|
has_website_permission = {
|
||||||
|
"LMS Certificate Evaluation": "lms.lms.doctype.lms_certificate_evaluation.lms_certificate_evaluation.has_website_permission"
|
||||||
|
}
|
||||||
|
|
||||||
|
profile_mandatory_fields = [
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"user_image",
|
||||||
|
"bio",
|
||||||
|
"linkedin",
|
||||||
|
"education",
|
||||||
|
"skill",
|
||||||
|
"preferred_functions",
|
||||||
|
"preferred_industries",
|
||||||
|
"dream_companies",
|
||||||
|
"attire",
|
||||||
|
"collaboration",
|
||||||
|
"role",
|
||||||
|
"location_preference",
|
||||||
|
"time",
|
||||||
|
"company_type",
|
||||||
|
]
|
||||||
|
|
||||||
|
## Markdown Macros for Lessons
|
||||||
|
lms_markdown_macro_renderers = {
|
||||||
|
"Exercise": "lms.plugins.exercise_renderer",
|
||||||
|
"Quiz": "lms.plugins.quiz_renderer",
|
||||||
|
"YouTubeVideo": "lms.plugins.youtube_video_renderer",
|
||||||
|
"Video": "lms.plugins.video_renderer",
|
||||||
|
"Assignment": "lms.plugins.assignment_renderer",
|
||||||
|
}
|
||||||
|
|
||||||
|
# page_renderer to manage profile pages
|
||||||
|
page_renderer = [
|
||||||
|
"lms.page_renderers.ProfileRedirectPage",
|
||||||
|
"lms.page_renderers.ProfilePage",
|
||||||
|
]
|
||||||
|
|
||||||
|
# set this to "/" to have profiles on the top-level
|
||||||
|
profile_url_prefix = "/users/"
|
||||||
|
|
||||||
|
signup_form_template = "lms.plugins.show_custom_signup"
|
||||||
|
|
||||||
|
on_login = "lms.overrides.user.on_login"
|
||||||
|
|
||||||
|
on_session_creation = "lms.overrides.user.on_session_creation"
|
||||||
129
lms/install.py
Normal file
129
lms/install.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
import frappe
|
||||||
|
from frappe.desk.page.setup_wizard.setup_wizard import add_all_roles_to
|
||||||
|
|
||||||
|
|
||||||
|
def after_install():
|
||||||
|
add_pages_to_nav()
|
||||||
|
|
||||||
|
|
||||||
|
def after_sync():
|
||||||
|
create_lms_roles()
|
||||||
|
set_default_home()
|
||||||
|
add_all_roles_to("Administrator")
|
||||||
|
|
||||||
|
|
||||||
|
def add_pages_to_nav():
|
||||||
|
pages = [
|
||||||
|
{"label": "Explore", "idx": 1},
|
||||||
|
{"label": "Courses", "url": "/courses", "parent": "Explore", "idx": 2},
|
||||||
|
{"label": "Classes", "url": "/classes", "parent": "Explore", "idx": 3},
|
||||||
|
{"label": "Statistics", "url": "/statistics", "parent": "Explore", "idx": 4},
|
||||||
|
{"label": "Jobs", "url": "/jobs", "parent": "Explore", "idx": 5},
|
||||||
|
{"label": "People", "url": "/community", "parent": "Explore", "idx": 6},
|
||||||
|
]
|
||||||
|
|
||||||
|
for page in pages:
|
||||||
|
filters = frappe._dict()
|
||||||
|
if page.get("url"):
|
||||||
|
filters["url"] = ["like", "%" + page.get("url") + "%"]
|
||||||
|
else:
|
||||||
|
filters["label"] = page.get("label")
|
||||||
|
|
||||||
|
if not frappe.db.exists("Top Bar Item", filters):
|
||||||
|
frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Top Bar Item",
|
||||||
|
"label": page.get("label"),
|
||||||
|
"url": page.get("url"),
|
||||||
|
"parent_label": page.get("parent"),
|
||||||
|
"idx": page.get("idx"),
|
||||||
|
"parent": "Website Settings",
|
||||||
|
"parenttype": "Website Settings",
|
||||||
|
"parentfield": "top_bar_items",
|
||||||
|
}
|
||||||
|
).save()
|
||||||
|
|
||||||
|
|
||||||
|
def after_uninstall():
|
||||||
|
delete_custom_fields()
|
||||||
|
|
||||||
|
|
||||||
|
def create_lms_roles():
|
||||||
|
create_course_creator_role()
|
||||||
|
create_moderator_role()
|
||||||
|
|
||||||
|
|
||||||
|
def set_default_home():
|
||||||
|
frappe.db.set_value("Portal Settings", None, "default_portal_home", "/courses")
|
||||||
|
|
||||||
|
|
||||||
|
def create_course_creator_role():
|
||||||
|
if not frappe.db.exists("Role", "Course Creator"):
|
||||||
|
role = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Role",
|
||||||
|
"role_name": "Course Creator",
|
||||||
|
"home_page": "",
|
||||||
|
"desk_access": 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
role.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
|
def create_moderator_role():
|
||||||
|
if not frappe.db.exists("Role", "Moderator"):
|
||||||
|
role = frappe.get_doc(
|
||||||
|
{
|
||||||
|
"doctype": "Role",
|
||||||
|
"role_name": "Moderator",
|
||||||
|
"home_page": "",
|
||||||
|
"desk_access": 0,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
role.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_custom_fields():
|
||||||
|
fields = [
|
||||||
|
"user_category",
|
||||||
|
"headline",
|
||||||
|
"college",
|
||||||
|
"city",
|
||||||
|
"verify_terms",
|
||||||
|
"country",
|
||||||
|
"preferred_location",
|
||||||
|
"preferred_functions",
|
||||||
|
"preferred_industries",
|
||||||
|
"work_environment_column",
|
||||||
|
"time",
|
||||||
|
"role",
|
||||||
|
"carrer_preference_details",
|
||||||
|
"skill",
|
||||||
|
"certification_details",
|
||||||
|
"internship",
|
||||||
|
"branch",
|
||||||
|
"github",
|
||||||
|
"medium",
|
||||||
|
"linkedin",
|
||||||
|
"profession",
|
||||||
|
"looking_for_job",
|
||||||
|
"cover_image" "work_environment",
|
||||||
|
"dream_companies",
|
||||||
|
"career_preference_column",
|
||||||
|
"attire",
|
||||||
|
"collaboration",
|
||||||
|
"location_preference",
|
||||||
|
"company_type",
|
||||||
|
"skill_details",
|
||||||
|
"certification",
|
||||||
|
"education",
|
||||||
|
"work_experience",
|
||||||
|
"education_details",
|
||||||
|
"hide_private",
|
||||||
|
"work_experience_details",
|
||||||
|
"profile_complete",
|
||||||
|
]
|
||||||
|
|
||||||
|
for field in fields:
|
||||||
|
frappe.db.delete("Custom Field", {"fieldname": field})
|
||||||
|
frappe.db.commit()
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, Frappe and contributors
|
// Copyright (c) 2021, Frappe and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Community Talk', {
|
frappe.ui.form.on("Job Opportunity", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
157
lms/job/doctype/job_opportunity/job_opportunity.json
Normal file
157
lms/job/doctype/job_opportunity/job_opportunity.json
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_import": 1,
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "format: JOB-{#####}",
|
||||||
|
"creation": "2022-02-07 12:01:41.074418",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"job_title",
|
||||||
|
"location",
|
||||||
|
"disabled",
|
||||||
|
"column_break_5",
|
||||||
|
"type",
|
||||||
|
"status",
|
||||||
|
"section_break_6",
|
||||||
|
"description",
|
||||||
|
"company_details_section",
|
||||||
|
"company_name",
|
||||||
|
"company_website",
|
||||||
|
"column_break_11",
|
||||||
|
"company_logo",
|
||||||
|
"application_link"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "job_title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Job Title",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "location",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Location",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_5",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Full Time",
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Type",
|
||||||
|
"options": "Full Time\nPart Time\nFreelance\nContract",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Open",
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Status",
|
||||||
|
"options": "Open\nClosed"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_6",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Text Editor",
|
||||||
|
"label": "Description",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company_details_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Company Details"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Company Name",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company_website",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Company Website",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_11",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company_logo",
|
||||||
|
"fieldtype": "Attach Image",
|
||||||
|
"label": "Company Logo",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "application_link",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Application Form Link",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Disabled"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [],
|
||||||
|
"make_attachments_public": 1,
|
||||||
|
"modified": "2022-09-15 17:22:21.662675",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Job",
|
||||||
|
"name": "Job Opportunity",
|
||||||
|
"naming_rule": "Expression",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"select": 1,
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "All",
|
||||||
|
"select": 1,
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "job_title"
|
||||||
|
}
|
||||||
41
lms/job/doctype/job_opportunity/job_opportunity.py
Normal file
41
lms/job/doctype/job_opportunity/job_opportunity.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# Copyright (c) 2021, Frappe and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import get_link_to_form
|
||||||
|
from frappe.utils.user import get_system_managers
|
||||||
|
|
||||||
|
from lms.lms.utils import validate_image
|
||||||
|
|
||||||
|
|
||||||
|
class JobOpportunity(Document):
|
||||||
|
def validate(self):
|
||||||
|
self.validate_urls()
|
||||||
|
self.company_logo = validate_image(self.company_logo)
|
||||||
|
|
||||||
|
def validate_urls(self):
|
||||||
|
frappe.utils.validate_url(self.company_website, True)
|
||||||
|
frappe.utils.validate_url(self.application_link, True)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def report(job, reason):
|
||||||
|
system_managers = get_system_managers(only_name=True)
|
||||||
|
user = frappe.db.get_value("User", frappe.session.user, "full_name")
|
||||||
|
subject = _("User {0} has reported the job post {1}").format(user, job)
|
||||||
|
args = {
|
||||||
|
"job": job,
|
||||||
|
"job_url": get_link_to_form("Job Opportunity", job),
|
||||||
|
"user": user,
|
||||||
|
"reason": reason,
|
||||||
|
}
|
||||||
|
frappe.sendmail(
|
||||||
|
recipients=system_managers,
|
||||||
|
subject=subject,
|
||||||
|
header=[subject, "green"],
|
||||||
|
template="job_report",
|
||||||
|
args=args,
|
||||||
|
now=True,
|
||||||
|
)
|
||||||
9
lms/job/doctype/job_opportunity/test_job_opportunity.py
Normal file
9
lms/job/doctype/job_opportunity/test_job_opportunity.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestJobOpportunity(unittest.TestCase):
|
||||||
|
pass
|
||||||
7
lms/job/doctype/job_settings/job_settings.js
Normal file
7
lms/job/doctype/job_settings/job_settings.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) 2022, Frappe and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on("Job Settings", {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
// }
|
||||||
|
});
|
||||||
@@ -1,50 +1,48 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2021-08-11 10:51:47.234690",
|
"allow_rename": 1,
|
||||||
|
"creation": "2022-02-07 12:01:41.422955",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"event",
|
"allow_posting",
|
||||||
"user",
|
"title",
|
||||||
"full_name"
|
"subtitle"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "event",
|
"default": "0",
|
||||||
"fieldtype": "Link",
|
"fieldname": "allow_posting",
|
||||||
"label": "Event",
|
"fieldtype": "Check",
|
||||||
"options": "Event Details"
|
"label": "Allow Job Posting From Website"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "full_name",
|
"fieldname": "title",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"label": "Job Board Title"
|
||||||
"label": "Full Name",
|
|
||||||
"unique": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "user",
|
"fieldname": "subtitle",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "User"
|
"label": "Job Board Subtitle"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-20 17:03:26.733195",
|
"modified": "2022-02-11 15:56:38.958317",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Event Management",
|
"module": "Job",
|
||||||
"name": "Host",
|
"name": "Job Settings",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
@@ -52,6 +50,5 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "user",
|
"states": []
|
||||||
"track_changes": 1
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
# Copyright (c) 2021, FOSS United and contributors
|
# Copyright (c) 2022, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Host(Document):
|
|
||||||
|
class JobSettings(Document):
|
||||||
pass
|
pass
|
||||||
9
lms/job/doctype/job_settings/test_job_settings.py
Normal file
9
lms/job/doctype/job_settings/test_job_settings.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2022, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestJobSettings(unittest.TestCase):
|
||||||
|
pass
|
||||||
28
lms/job/notification/new_job_alert/new_job_alert.json
Normal file
28
lms/job/notification/new_job_alert/new_job_alert.json
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"attach_print": 0,
|
||||||
|
"channel": "Email",
|
||||||
|
"creation": "2021-12-30 12:29:56.533903",
|
||||||
|
"days_in_advance": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Notification",
|
||||||
|
"document_type": "Job Opportunity",
|
||||||
|
"enabled": 1,
|
||||||
|
"event": "New",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": 1,
|
||||||
|
"message": "Hey,\n\nA new Job Opportunity has been created. \n\n<p>Company Name: {{ doc.company_name}}</p>\n<p>Job Title: {{ doc.job_title}}</p>\n<p>Job Location: {{ doc.location}}</p><br>\n<p>Job Description: {{ doc.description}}</p><br>\n\n<p>Find all the posted jobs <a href=\"{{ frappe.utils.get_url() }}/app/job-opportunity\">here</a>.</p><br>\n",
|
||||||
|
"modified": "2021-12-30 12:54:13.382512",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Job",
|
||||||
|
"name": "New job alert",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"recipients": [
|
||||||
|
{
|
||||||
|
"receiver_by_role": "System Manager"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"send_system_notification": 0,
|
||||||
|
"send_to_all_assignees": 0,
|
||||||
|
"sender_email": "",
|
||||||
|
"subject": "New job added by {{ doc.company_name}}"
|
||||||
|
}
|
||||||
10
lms/job/notification/new_job_alert/new_job_alert.md
Normal file
10
lms/job/notification/new_job_alert/new_job_alert.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Hey,
|
||||||
|
|
||||||
|
A new Job Opportunity has been created.
|
||||||
|
|
||||||
|
<p>Company Name: {{ doc.company_name}}</p>
|
||||||
|
<p>Job Title: {{ doc.job_title}}</p>
|
||||||
|
<p>Job Location: {{ doc.location}}</p><br>
|
||||||
|
<p>Job Description: {{ doc.description}}</p><br>
|
||||||
|
|
||||||
|
<p>Find all the posted jobs <a href="{{ frappe.utils.get_url() }}/app/job-opportunity">here</a>.</p><br>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
# do your magic here
|
# do your magic here
|
||||||
pass
|
pass
|
||||||
7
lms/job/web_form/job_opportunity/job_opportunity.js
Normal file
7
lms/job/web_form/job_opportunity/job_opportunity.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
frappe.ready(function () {
|
||||||
|
frappe.web_form.after_save = () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
window.location.href = `/jobs`;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
});
|
||||||
151
lms/job/web_form/job_opportunity/job_opportunity.json
Normal file
151
lms/job/web_form/job_opportunity/job_opportunity.json
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
{
|
||||||
|
"accept_payment": 0,
|
||||||
|
"allow_comments": 0,
|
||||||
|
"allow_delete": 0,
|
||||||
|
"allow_edit": 1,
|
||||||
|
"allow_incomplete": 0,
|
||||||
|
"allow_multiple": 1,
|
||||||
|
"allow_print": 0,
|
||||||
|
"amount": 0.0,
|
||||||
|
"amount_based_on_field": 0,
|
||||||
|
"apply_document_permissions": 1,
|
||||||
|
"button_label": "Save",
|
||||||
|
"creation": "2021-12-27 17:02:12.461145",
|
||||||
|
"custom_css": "[data-doctype=\"Web Form\"] {\n max-width: 720px;\n margin: 6rem auto;\n}",
|
||||||
|
"doc_type": "Job Opportunity",
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Web Form",
|
||||||
|
"idx": 0,
|
||||||
|
"is_standard": 1,
|
||||||
|
"list_columns": [],
|
||||||
|
"login_required": 1,
|
||||||
|
"max_attachment_size": 0,
|
||||||
|
"modified": "2022-09-15 17:22:43.957184",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Job",
|
||||||
|
"name": "job-opportunity",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"payment_button_label": "Buy Now",
|
||||||
|
"published": 1,
|
||||||
|
"route": "job-opportunity",
|
||||||
|
"show_attachments": 0,
|
||||||
|
"show_list": 1,
|
||||||
|
"show_sidebar": 0,
|
||||||
|
"success_message": "",
|
||||||
|
"success_url": "/jobs",
|
||||||
|
"title": "Job Opportunity",
|
||||||
|
"web_form_fields": [
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "job_title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Job Title",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "location",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Location",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"default": "Full Time",
|
||||||
|
"fieldname": "type",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Type",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"options": "Full Time\nPart Time\nFreelance\nContract",
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"default": "Open",
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Status",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"options": "Open\nClosed",
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "company_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Company Name",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "company_website",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Company Website",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "company_logo",
|
||||||
|
"fieldtype": "Attach Image",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Company Logo",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "application_link",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Application Form Link",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_read_on_all_link_options": 0,
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Text Editor",
|
||||||
|
"hidden": 0,
|
||||||
|
"label": "Description",
|
||||||
|
"max_length": 0,
|
||||||
|
"max_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"show_in_filter": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
def get_context(context):
|
def get_context(context):
|
||||||
# do your magic here
|
# do your magic here
|
||||||
pass
|
pass
|
||||||
141
lms/lms/api.py
Normal file
141
lms/lms/api.py
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
"""API methods for the LMS.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def autosave_section(section, code):
|
||||||
|
"""Saves the code edited in one of the sections."""
|
||||||
|
doc = frappe.get_doc(
|
||||||
|
doctype="Code Revision", section=section, code=code, author=frappe.session.user
|
||||||
|
)
|
||||||
|
doc.insert()
|
||||||
|
return {"name": doc.name}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def submit_solution(exercise, code):
|
||||||
|
"""Submits a solution.
|
||||||
|
|
||||||
|
@exerecise: name of the exercise to submit
|
||||||
|
@code: solution to the exercise
|
||||||
|
"""
|
||||||
|
ex = frappe.get_doc("Exercise", exercise)
|
||||||
|
if not ex:
|
||||||
|
return
|
||||||
|
doc = ex.submit(code)
|
||||||
|
return {"name": doc.name, "creation": doc.creation}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def save_current_lesson(course_name, lesson_name):
|
||||||
|
"""Saves the current lesson for a student/mentor."""
|
||||||
|
name = frappe.get_value(
|
||||||
|
doctype="LMS Batch Membership",
|
||||||
|
filters={"course": course_name, "member": frappe.session.user},
|
||||||
|
fieldname="name",
|
||||||
|
)
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
doc = frappe.get_doc("LMS Batch Membership", name)
|
||||||
|
doc.current_lesson = lesson_name
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
return {"current_lesson": doc.current_lesson}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def join_cohort(course, cohort, subgroup, invite_code):
|
||||||
|
"""Creates a Cohort Join Request for given user."""
|
||||||
|
course_doc = frappe.get_doc("LMS Course", course)
|
||||||
|
cohort_doc = course_doc and course_doc.get_cohort(cohort)
|
||||||
|
subgroup_doc = cohort_doc and cohort_doc.get_subgroup(subgroup)
|
||||||
|
|
||||||
|
if not subgroup_doc or subgroup_doc.invite_code != invite_code:
|
||||||
|
return {"ok": False, "error": "Invalid join link"}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"doctype": "Cohort Join Request",
|
||||||
|
"cohort": cohort_doc.name,
|
||||||
|
"subgroup": subgroup_doc.name,
|
||||||
|
"email": frappe.session.user,
|
||||||
|
"status": "Pending",
|
||||||
|
}
|
||||||
|
# Don't insert duplicate records
|
||||||
|
if frappe.db.exists(data):
|
||||||
|
return {"ok": True, "status": "record found"}
|
||||||
|
else:
|
||||||
|
doc = frappe.get_doc(data)
|
||||||
|
doc.insert(ignore_permissions=True)
|
||||||
|
return {"ok": True, "status": "record created"}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def approve_cohort_join_request(join_request):
|
||||||
|
r = frappe.get_doc("Cohort Join Request", join_request)
|
||||||
|
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
|
||||||
|
if not sg or r.status not in ["Pending", "Accepted"]:
|
||||||
|
return {"ok": False, "error": "Invalid Join Request"}
|
||||||
|
if (
|
||||||
|
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
|
||||||
|
):
|
||||||
|
return {"ok": False, "error": "Permission Deined"}
|
||||||
|
|
||||||
|
r.status = "Accepted"
|
||||||
|
r.save(ignore_permissions=True)
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def reject_cohort_join_request(join_request):
|
||||||
|
r = frappe.get_doc("Cohort Join Request", join_request)
|
||||||
|
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
|
||||||
|
if not sg or r.status not in ["Pending", "Rejected"]:
|
||||||
|
return {"ok": False, "error": "Invalid Join Request"}
|
||||||
|
if (
|
||||||
|
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
|
||||||
|
):
|
||||||
|
return {"ok": False, "error": "Permission Deined"}
|
||||||
|
|
||||||
|
r.status = "Rejected"
|
||||||
|
r.save(ignore_permissions=True)
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def undo_reject_cohort_join_request(join_request):
|
||||||
|
r = frappe.get_doc("Cohort Join Request", join_request)
|
||||||
|
sg = r and frappe.get_doc("Cohort Subgroup", r.subgroup)
|
||||||
|
# keeping Pending as well to consider the case of duplicate requests
|
||||||
|
if not sg or r.status not in ["Pending", "Rejected"]:
|
||||||
|
return {"ok": False, "error": "Invalid Join Request"}
|
||||||
|
if (
|
||||||
|
not sg.is_manager(frappe.session.user) and "System Manager" not in frappe.get_roles()
|
||||||
|
):
|
||||||
|
return {"ok": False, "error": "Permission Deined"}
|
||||||
|
|
||||||
|
r.status = "Pending"
|
||||||
|
r.save(ignore_permissions=True)
|
||||||
|
return {"ok": True}
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def add_mentor_to_subgroup(subgroup, email):
|
||||||
|
try:
|
||||||
|
sg = frappe.get_doc("Cohort Subgroup", subgroup)
|
||||||
|
except frappe.DoesNotExistError:
|
||||||
|
return {"ok": False, "error": f"Invalid subgroup: {subgroup}"}
|
||||||
|
|
||||||
|
if (
|
||||||
|
not sg.get_cohort().is_admin(frappe.session.user)
|
||||||
|
and "System Manager" not in frappe.get_roles()
|
||||||
|
):
|
||||||
|
return {"ok": False, "error": "Permission Deined"}
|
||||||
|
|
||||||
|
try:
|
||||||
|
user = frappe.get_doc("User", email)
|
||||||
|
except frappe.DoesNotExistError:
|
||||||
|
return {"ok": False, "error": f"Invalid user: {email}"}
|
||||||
|
|
||||||
|
sg.add_mentor(email)
|
||||||
|
return {"ok": True}
|
||||||
@@ -2,23 +2,26 @@
|
|||||||
"based_on": "creation",
|
"based_on": "creation",
|
||||||
"chart_name": "Course Enrollments",
|
"chart_name": "Course Enrollments",
|
||||||
"chart_type": "Count",
|
"chart_type": "Count",
|
||||||
|
"color": "#4463F0",
|
||||||
"creation": "2021-09-30 12:23:09.414853",
|
"creation": "2021-09-30 12:23:09.414853",
|
||||||
|
"custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}",
|
||||||
"docstatus": 0,
|
"docstatus": 0,
|
||||||
"doctype": "Dashboard Chart",
|
"doctype": "Dashboard Chart",
|
||||||
"document_type": "LMS Batch Membership",
|
"document_type": "LMS Batch Membership",
|
||||||
"dynamic_filters_json": "[]",
|
"dynamic_filters_json": "[]",
|
||||||
"filters_json": "[]",
|
"filters_json": "[]",
|
||||||
"group_by_type": "Count",
|
"group_by_type": "Count",
|
||||||
"idx": 0,
|
"idx": 1,
|
||||||
"is_public": 1,
|
"is_public": 1,
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
"last_synced_on": "2021-10-17 13:32:21.745498",
|
"last_synced_on": "2022-10-20 10:46:56.859520",
|
||||||
"modified": "2021-10-21 17:31:06.997133",
|
"modified": "2022-10-20 11:30:26.863008",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Enrollments",
|
"name": "Course Enrollments",
|
||||||
"number_of_groups": 0,
|
"number_of_groups": 0,
|
||||||
"owner": "basawaraj@erpnext.com",
|
"owner": "basawaraj@erpnext.com",
|
||||||
|
"roles": [],
|
||||||
"source": "",
|
"source": "",
|
||||||
"time_interval": "Daily",
|
"time_interval": "Daily",
|
||||||
"timeseries": 1,
|
"timeseries": 1,
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"based_on": "creation",
|
||||||
|
"chart_name": "Lesson Completion",
|
||||||
|
"chart_type": "Count",
|
||||||
|
"color": "#4463F0",
|
||||||
|
"creation": "2022-11-09 16:52:19.021695",
|
||||||
|
"custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}",
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Dashboard Chart",
|
||||||
|
"document_type": "LMS Course Progress",
|
||||||
|
"dynamic_filters_json": "[]",
|
||||||
|
"filters_json": "[]",
|
||||||
|
"group_by_type": "Count",
|
||||||
|
"idx": 0,
|
||||||
|
"is_public": 1,
|
||||||
|
"is_standard": 1,
|
||||||
|
"modified": "2022-11-09 16:52:52.241756",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Lesson Completion",
|
||||||
|
"number_of_groups": 0,
|
||||||
|
"owner": "Administrator",
|
||||||
|
"parent_document_type": "",
|
||||||
|
"roles": [],
|
||||||
|
"source": "",
|
||||||
|
"time_interval": "Daily",
|
||||||
|
"timeseries": 1,
|
||||||
|
"timespan": "Last Month",
|
||||||
|
"type": "Line",
|
||||||
|
"use_report_chart": 0,
|
||||||
|
"value_based_on": "",
|
||||||
|
"y_axis": []
|
||||||
|
}
|
||||||
33
lms/lms/dashboard_chart/new_signups/new_signups.json
Normal file
33
lms/lms/dashboard_chart/new_signups/new_signups.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"based_on": "creation",
|
||||||
|
"chart_name": "New Signups",
|
||||||
|
"chart_type": "Count",
|
||||||
|
"color": "#4463F0",
|
||||||
|
"creation": "2021-09-28 18:57:50.047656",
|
||||||
|
"custom_options": "{\"type\": \"line\", \"axisOptions\": {\"xIsSeries\": 1}, \"lineOptions\": {\"regionFill\": 1}}",
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "Dashboard Chart",
|
||||||
|
"document_type": "User",
|
||||||
|
"dynamic_filters_json": "[]",
|
||||||
|
"filters_json": "[]",
|
||||||
|
"group_by_type": "Count",
|
||||||
|
"idx": 1,
|
||||||
|
"is_public": 1,
|
||||||
|
"is_standard": 1,
|
||||||
|
"last_synced_on": "2022-10-20 10:46:56.849265",
|
||||||
|
"modified": "2022-10-20 11:31:17.184897",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "New Signups",
|
||||||
|
"number_of_groups": 0,
|
||||||
|
"owner": "basawaraj@erpnext.com",
|
||||||
|
"roles": [],
|
||||||
|
"source": "",
|
||||||
|
"time_interval": "Daily",
|
||||||
|
"timeseries": 1,
|
||||||
|
"timespan": "Last Quarter",
|
||||||
|
"type": "Line",
|
||||||
|
"use_report_chart": 0,
|
||||||
|
"value_based_on": "",
|
||||||
|
"y_axis": []
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, Frappe and contributors
|
// Copyright (c) 2021, Frappe and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('TShirt Sizes', {
|
frappe.ui.form.on("Certification", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
74
lms/lms/doctype/certification/certification.json
Normal file
74
lms/lms/doctype/certification/certification.json
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "hash",
|
||||||
|
"creation": "2021-12-07 12:20:37.143096",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"certification_name",
|
||||||
|
"organization",
|
||||||
|
"description",
|
||||||
|
"column_break_4",
|
||||||
|
"expire",
|
||||||
|
"issue_date",
|
||||||
|
"expiration_date"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "certification_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Certification Name",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "organization",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Organization",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "issue_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Issue Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Small Text",
|
||||||
|
"label": "Description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval: !doc.expire",
|
||||||
|
"fieldname": "expiration_date",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Expiration Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "expire",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "This certificate does no expire"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-12-21 10:05:43.377876",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Certification",
|
||||||
|
"naming_rule": "Random",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2021, Frappe and contributors
|
# Copyright (c) 2021, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class TShirtSizes(Document):
|
|
||||||
|
class Certification(Document):
|
||||||
pass
|
pass
|
||||||
9
lms/lms/doctype/certification/test_certification.py
Normal file
9
lms/lms/doctype/certification/test_certification.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestCertification(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
|
"autoname": "hash",
|
||||||
"creation": "2021-07-27 16:25:02.903245",
|
"creation": "2021-07-27 16:25:02.903245",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -20,13 +21,15 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-30 10:35:30.014950",
|
"modified": "2022-03-15 09:39:41.937565",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Chapter Reference",
|
"name": "Chapter Reference",
|
||||||
|
"naming_rule": "Random",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
class ChapterReference(Document):
|
class ChapterReference(Document):
|
||||||
pass
|
pass
|
||||||
43
lms/lms/doctype/class_course/class_course.json
Normal file
43
lms/lms/doctype/class_course/class_course.json
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"autoname": "autoincrement",
|
||||||
|
"creation": "2022-11-09 16:23:26.454527",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"course",
|
||||||
|
"title"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "course.title",
|
||||||
|
"fieldname": "title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Title",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2022-11-11 15:51:45.560864",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Class Course",
|
||||||
|
"naming_rule": "Autoincrement",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
# Copyright (c) 2021, FOSS United and contributors
|
# Copyright (c) 2022, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Speaker(Document):
|
|
||||||
|
class ClassCourse(Document):
|
||||||
pass
|
pass
|
||||||
7
lms/lms/doctype/class_student/class_student.js
Normal file
7
lms/lms/doctype/class_student/class_student.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) 2022, Frappe and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on("Class Student", {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
// }
|
||||||
|
});
|
||||||
51
lms/lms/doctype/class_student/class_student.json
Normal file
51
lms/lms/doctype/class_student/class_student.json
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2022-11-09 16:20:44.602545",
|
||||||
|
"default_view": "List",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"student",
|
||||||
|
"student_name",
|
||||||
|
"username"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "student",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Student",
|
||||||
|
"options": "User",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "student.full_name",
|
||||||
|
"fieldname": "student_name",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Student Name",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "student.username",
|
||||||
|
"fieldname": "username",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Username",
|
||||||
|
"read_only": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2022-11-15 11:13:39.410578",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Class Student",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
# Copyright (c) 2021, FOSS United and contributors
|
# Copyright (c) 2022, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class Attendee(Document):
|
|
||||||
|
class ClassStudent(Document):
|
||||||
pass
|
pass
|
||||||
9
lms/lms/doctype/class_student/test_class_student.py
Normal file
9
lms/lms/doctype/class_student/test_class_student.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2022, Frappe and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestClassStudent(FrappeTestCase):
|
||||||
|
pass
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Talk', {
|
frappe.ui.form.on("Cohort", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
133
lms/lms/doctype/cohort/cohort.json
Normal file
133
lms/lms/doctype/cohort/cohort.json
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"autoname": "format:{course}/{slug}",
|
||||||
|
"creation": "2021-11-19 11:45:31.016097",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"course",
|
||||||
|
"title",
|
||||||
|
"slug",
|
||||||
|
"section_break_2",
|
||||||
|
"instructor",
|
||||||
|
"status",
|
||||||
|
"column_break_4",
|
||||||
|
"begin_date",
|
||||||
|
"end_date",
|
||||||
|
"duration",
|
||||||
|
"section_break_8",
|
||||||
|
"description",
|
||||||
|
"pages"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Markdown Editor",
|
||||||
|
"label": "Description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "instructor",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Instructor",
|
||||||
|
"options": "User",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Status",
|
||||||
|
"options": "Upcoming\nLive\nCompleted\nCancelled",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "begin_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "Begin Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "end_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "End Date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "duration",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Duration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "slug",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Slug",
|
||||||
|
"reqd": 1,
|
||||||
|
"unique": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_8",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_2",
|
||||||
|
"fieldtype": "Section Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Title",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "pages",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Pages",
|
||||||
|
"options": "Cohort Web Page"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"group": "Links",
|
||||||
|
"link_doctype": "Cohort Subgroup",
|
||||||
|
"link_fieldname": "cohort"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2022-10-13 15:46:32.322926",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Cohort",
|
||||||
|
"naming_rule": "Expression",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"track_changes": 1
|
||||||
|
}
|
||||||
79
lms/lms/doctype/cohort/cohort.py
Normal file
79
lms/lms/doctype/cohort/cohort.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class Cohort(Document):
|
||||||
|
def get_url(self):
|
||||||
|
return f"{frappe.utils.get_url()}/courses/{self.course}/cohorts/{self.slug}"
|
||||||
|
|
||||||
|
def get_subgroups(self, include_counts=False, sort_by=None):
|
||||||
|
names = frappe.get_all("Cohort Subgroup", filters={"cohort": self.name}, pluck="name")
|
||||||
|
subgroups = [frappe.get_cached_doc("Cohort Subgroup", name) for name in names]
|
||||||
|
subgroups = sorted(subgroups, key=lambda sg: sg.title)
|
||||||
|
|
||||||
|
if include_counts:
|
||||||
|
mentors = self._get_subgroup_counts("Cohort Mentor")
|
||||||
|
students = self._get_subgroup_counts("LMS Batch Membership")
|
||||||
|
join_requests = self._get_subgroup_counts("Cohort Join Request", status="Pending")
|
||||||
|
for s in subgroups:
|
||||||
|
s.num_mentors = mentors.get(s.name, 0)
|
||||||
|
s.num_students = students.get(s.name, 0)
|
||||||
|
s.num_join_requests = join_requests.get(s.name, 0)
|
||||||
|
|
||||||
|
if sort_by:
|
||||||
|
subgroups.sort(key=lambda sg: getattr(sg, sort_by), reverse=True)
|
||||||
|
return subgroups
|
||||||
|
|
||||||
|
def _get_subgroup_counts(self, doctype, **kw):
|
||||||
|
rows = frappe.get_all(
|
||||||
|
doctype,
|
||||||
|
filters={"cohort": self.name, **kw},
|
||||||
|
fields=["subgroup", "count(*) as count"],
|
||||||
|
group_by="subgroup",
|
||||||
|
)
|
||||||
|
return {row["subgroup"]: row["count"] for row in rows}
|
||||||
|
|
||||||
|
def _get_count(self, doctype, **kw):
|
||||||
|
filters = {"cohort": self.name, **kw}
|
||||||
|
return frappe.db.count(doctype, filters=filters)
|
||||||
|
|
||||||
|
def get_page_template(self, slug, scope=None):
|
||||||
|
p = self.get_page(slug, scope=scope)
|
||||||
|
return p and p.get_template_html()
|
||||||
|
|
||||||
|
def get_page(self, slug, scope=None):
|
||||||
|
for p in self.pages:
|
||||||
|
if p.slug == slug and scope in [p.scope, None]:
|
||||||
|
return p
|
||||||
|
|
||||||
|
def get_pages(self, scope=None):
|
||||||
|
return [p for p in self.pages if scope in [p.scope, None]]
|
||||||
|
|
||||||
|
def get_stats(self):
|
||||||
|
return {
|
||||||
|
"subgroups": self._get_count("Cohort Subgroup"),
|
||||||
|
"mentors": self._get_count("Cohort Mentor"),
|
||||||
|
"students": self._get_count("LMS Batch Membership"),
|
||||||
|
"join_requests": self._get_count("Cohort Join Request", status="Pending"),
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_subgroup(self, slug):
|
||||||
|
q = dict(cohort=self.name, slug=slug)
|
||||||
|
name = frappe.db.get_value("Cohort Subgroup", q, "name")
|
||||||
|
return name and frappe.get_doc("Cohort Subgroup", name)
|
||||||
|
|
||||||
|
def get_mentor(self, email):
|
||||||
|
q = dict(cohort=self.name, email=email)
|
||||||
|
name = frappe.db.get_value("Cohort Mentor", q, "name")
|
||||||
|
return name and frappe.get_doc("Cohort Mentor", name)
|
||||||
|
|
||||||
|
def is_mentor(self, email):
|
||||||
|
q = {"doctype": "Cohort Mentor", "cohort": self.name, "email": email}
|
||||||
|
return frappe.db.exists(q)
|
||||||
|
|
||||||
|
def is_admin(self, email):
|
||||||
|
q = {"doctype": "Cohort Staff", "cohort": self.name, "email": email, "role": "Admin"}
|
||||||
|
return frappe.db.exists(q)
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
# import frappe
|
# import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestTalk(unittest.TestCase):
|
|
||||||
|
class TestCohort(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on("Cohort Join Request", {
|
||||||
|
// refresh: function(frm) {
|
||||||
|
// }
|
||||||
|
});
|
||||||
@@ -1,51 +1,60 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2021-02-12 18:36:08.324156",
|
"allow_rename": 1,
|
||||||
|
"creation": "2021-11-19 16:27:41.716509",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"project",
|
"cohort",
|
||||||
"intro",
|
"email",
|
||||||
"status",
|
"column_break_3",
|
||||||
"project_owner"
|
"subgroup",
|
||||||
|
"status"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "project",
|
"fieldname": "cohort",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"label": "Cohort",
|
||||||
"label": "Project",
|
"options": "Cohort",
|
||||||
"options": "Community Project",
|
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "intro",
|
"fieldname": "subgroup",
|
||||||
"fieldtype": "Small Text",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Intro",
|
"label": "Subgroup",
|
||||||
|
"options": "Cohort Subgroup",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "email",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "E-Mail",
|
||||||
|
"options": "User",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "Pending",
|
"default": "Pending",
|
||||||
"fieldname": "status",
|
"fieldname": "status",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
|
"in_list_view": 1,
|
||||||
"label": "Status",
|
"label": "Status",
|
||||||
"options": "Pending\nAccepted\nRejected"
|
"options": "Pending\nAccepted\nRejected"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "project_owner",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Column Break"
|
||||||
"label": "Project Owner",
|
|
||||||
"options": "Email"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-03-04 19:44:09.832170",
|
"modified": "2021-12-16 15:06:03.985221",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Hackathon",
|
"module": "LMS",
|
||||||
"name": "Community Project Member",
|
"name": "Cohort Join Request",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -59,18 +68,8 @@
|
|||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
|
||||||
{
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Participant",
|
|
||||||
"share": 1
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
52
lms/lms/doctype/cohort_join_request/cohort_join_request.py
Normal file
52
lms/lms/doctype/cohort_join_request/cohort_join_request.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class CohortJoinRequest(Document):
|
||||||
|
def on_update(self):
|
||||||
|
if self.status == "Accepted":
|
||||||
|
self.ensure_student()
|
||||||
|
|
||||||
|
def ensure_student(self):
|
||||||
|
# case 1 - user is already a member
|
||||||
|
q = {
|
||||||
|
"doctype": "LMS Batch Membership",
|
||||||
|
"cohort": self.cohort,
|
||||||
|
"subgroup": self.subgroup,
|
||||||
|
"member": self.email,
|
||||||
|
"member_type": "Student",
|
||||||
|
}
|
||||||
|
if frappe.db.exists(q):
|
||||||
|
return
|
||||||
|
|
||||||
|
# case 2 - user has signed up for this course, possibly not this cohort
|
||||||
|
cohort = frappe.get_doc("Cohort", self.cohort)
|
||||||
|
|
||||||
|
q = {
|
||||||
|
"doctype": "LMS Batch Membership",
|
||||||
|
"course": cohort.course,
|
||||||
|
"member": self.email,
|
||||||
|
"member_type": "Student",
|
||||||
|
}
|
||||||
|
name = frappe.db.exists(q)
|
||||||
|
if name:
|
||||||
|
doc = frappe.get_doc("LMS Batch Membership", name)
|
||||||
|
doc.cohort = self.cohort
|
||||||
|
doc.subgroup = self.subgroup
|
||||||
|
doc.save(ignore_permissions=True)
|
||||||
|
else:
|
||||||
|
# case 3 - user has not signed up for this course yet
|
||||||
|
data = {
|
||||||
|
"doctype": "LMS Batch Membership",
|
||||||
|
"course": cohort.course,
|
||||||
|
"cohort": self.cohort,
|
||||||
|
"subgroup": self.subgroup,
|
||||||
|
"member": self.email,
|
||||||
|
"member_type": "Student",
|
||||||
|
"role": "Member",
|
||||||
|
}
|
||||||
|
doc = frappe.get_doc(data)
|
||||||
|
doc.insert(ignore_permissions=True)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestCohortJoinRequest(unittest.TestCase):
|
||||||
|
pass
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Host', {
|
frappe.ui.form.on("Cohort Mentor", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
@@ -1,57 +1,57 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2021-02-15 11:04:02.748879",
|
"allow_rename": 1,
|
||||||
|
"creation": "2021-11-19 15:31:47.129156",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"first_name",
|
"cohort",
|
||||||
"last_name",
|
|
||||||
"email",
|
"email",
|
||||||
"student",
|
"subgroup",
|
||||||
"organization_college"
|
"course"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "first_name",
|
"fieldname": "cohort",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "First Name",
|
"in_standard_filter": 1,
|
||||||
"reqd": 1
|
"label": "Cohort",
|
||||||
},
|
"options": "Cohort",
|
||||||
{
|
|
||||||
"fieldname": "last_name",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Last Name",
|
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "email",
|
"fieldname": "email",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Email",
|
"label": "E-mail",
|
||||||
"options": "Email",
|
"options": "User",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"fieldname": "subgroup",
|
||||||
"fieldname": "student",
|
"fieldtype": "Link",
|
||||||
"fieldtype": "Check",
|
"in_list_view": 1,
|
||||||
"label": "Student"
|
"label": "Primary Subgroup",
|
||||||
|
"options": "Cohort Subgroup",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "organization_college",
|
"fetch_from": "cohort.course",
|
||||||
"fieldtype": "Data",
|
"fieldname": "course",
|
||||||
"label": "Organization/College"
|
"fieldtype": "Link",
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-02-15 11:04:02.748879",
|
"modified": "2021-11-29 16:32:33.235281",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Community",
|
"module": "LMS",
|
||||||
"name": "Community Participant",
|
"name": "Cohort Mentor",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,6 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 1,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
13
lms/lms/doctype/cohort_mentor/cohort_mentor.py
Normal file
13
lms/lms/doctype/cohort_mentor/cohort_mentor.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class CohortMentor(Document):
|
||||||
|
def get_subgroup(self):
|
||||||
|
return frappe.get_doc("Cohort Subgroup", self.subgroup)
|
||||||
|
|
||||||
|
def get_user(self):
|
||||||
|
return frappe.get_doc("User", self.email)
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
# import frappe
|
# import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestEventDetails(unittest.TestCase):
|
|
||||||
|
class TestCohortMentor(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Exhibitor', {
|
frappe.ui.form.on("Cohort Staff", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
@@ -1,55 +1,61 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2021-08-11 10:37:32.124651",
|
"allow_rename": 1,
|
||||||
|
"creation": "2021-11-19 15:35:00.551949",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"event",
|
"cohort",
|
||||||
"company",
|
"course",
|
||||||
"column_break_8",
|
"column_break_3",
|
||||||
"user",
|
"email",
|
||||||
"full_name"
|
"role"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "user",
|
"fieldname": "cohort",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Cohort",
|
||||||
|
"options": "Cohort",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "email",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "User",
|
"label": "User",
|
||||||
"options": "User"
|
"options": "User",
|
||||||
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fetch_from": "user.full_name",
|
"fieldname": "role",
|
||||||
"fieldname": "full_name",
|
"fieldtype": "Select",
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Full Name",
|
"label": "Role",
|
||||||
|
"options": "Admin\nManager\nStaff",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "cohort.course",
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Company"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_8",
|
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "event",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Event",
|
|
||||||
"options": "Event Details"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-20 16:53:43.968260",
|
"modified": "2021-12-16 15:16:04.042372",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Event Management",
|
"module": "LMS",
|
||||||
"name": "Speaker",
|
"name": "Cohort Staff",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -67,6 +73,5 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"title_field": "user",
|
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
# import frappe
|
# import frappe
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class EventDetails(Document):
|
|
||||||
|
class CohortStaff(Document):
|
||||||
pass
|
pass
|
||||||
@@ -4,5 +4,6 @@
|
|||||||
# import frappe
|
# import frappe
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
class TestExhibitor(unittest.TestCase):
|
|
||||||
|
class TestCohortStaff(unittest.TestCase):
|
||||||
pass
|
pass
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('Event Details', {
|
frappe.ui.form.on("Cohort Subgroup", {
|
||||||
// refresh: function(frm) {
|
// refresh: function(frm) {
|
||||||
|
|
||||||
// }
|
// }
|
||||||
});
|
});
|
||||||
@@ -1,82 +1,87 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_import": 1,
|
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "format:{####} {title}",
|
"autoname": "format:{title} ({cohort})",
|
||||||
"creation": "2021-05-03 06:21:12.995984",
|
"creation": "2021-11-19 11:50:27.312434",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"chapter",
|
"cohort",
|
||||||
"include_in_preview",
|
"slug",
|
||||||
"column_break_4",
|
|
||||||
"title",
|
"title",
|
||||||
"index_label",
|
"column_break_4",
|
||||||
"section_break_6",
|
"invite_code",
|
||||||
"body",
|
"course",
|
||||||
"help_section",
|
"section_break_7",
|
||||||
"help"
|
"description"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "chapter",
|
"fieldname": "cohort",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Course Chapter",
|
"in_preview": 1,
|
||||||
"options": "Course Chapter",
|
"in_standard_filter": 1,
|
||||||
|
"label": "Cohort",
|
||||||
|
"options": "Cohort",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"fieldname": "title",
|
||||||
"fieldname": "include_in_preview",
|
"fieldtype": "Data",
|
||||||
"fieldtype": "Check",
|
"in_list_view": 1,
|
||||||
"label": "Include In Preview"
|
"in_preview": 1,
|
||||||
|
"in_standard_filter": 1,
|
||||||
|
"label": "Title",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "description",
|
||||||
|
"fieldtype": "Markdown Editor",
|
||||||
|
"label": "Description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "invite_code",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Invite Code",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "slug",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"label": "Slug",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "cohort.course",
|
||||||
|
"fieldname": "course",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Course",
|
||||||
|
"options": "LMS Course",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "column_break_4",
|
"fieldname": "column_break_4",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "title",
|
"fieldname": "section_break_7",
|
||||||
"fieldtype": "Data",
|
|
||||||
"in_list_view": 1,
|
|
||||||
"label": "Title",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "index_label",
|
|
||||||
"fieldtype": "Data",
|
|
||||||
"label": "Index Label",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_6",
|
|
||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "body",
|
|
||||||
"fieldtype": "Markdown Editor",
|
|
||||||
"ignore_xss_filter": 1,
|
|
||||||
"label": "Body",
|
|
||||||
"reqd": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "help_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Help"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "help",
|
|
||||||
"fieldtype": "HTML"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [
|
||||||
"modified": "2021-10-11 15:07:38.134808",
|
{
|
||||||
|
"group": "Links",
|
||||||
|
"link_doctype": "Cohort Join Request",
|
||||||
|
"link_fieldname": "subgroup"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"modified": "2021-12-16 15:12:42.504883",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Lesson",
|
"name": "Cohort Subgroup",
|
||||||
"naming_rule": "Expression",
|
"naming_rule": "Expression",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
88
lms/lms/doctype/cohort_subgroup/cohort_subgroup.py
Normal file
88
lms/lms/doctype/cohort_subgroup/cohort_subgroup.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.utils import random_string
|
||||||
|
|
||||||
|
|
||||||
|
class CohortSubgroup(Document):
|
||||||
|
def before_save(self):
|
||||||
|
if not self.invite_code:
|
||||||
|
self.invite_code = random_string(8)
|
||||||
|
|
||||||
|
def get_url(self):
|
||||||
|
cohort = frappe.get_doc("Cohort", self.cohort)
|
||||||
|
return (
|
||||||
|
f"{frappe.utils.get_url()}/courses/{self.course}/subgroups/{cohort.slug}/{self.slug}"
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_invite_link(self):
|
||||||
|
cohort = frappe.get_doc("Cohort", self.cohort)
|
||||||
|
return f"{frappe.utils.get_url()}/courses/{self.course}/join/{cohort.slug}/{self.slug}/{self.invite_code}"
|
||||||
|
|
||||||
|
def has_student(self, email):
|
||||||
|
"""Check if given user is a student of this subgroup."""
|
||||||
|
q = {"doctype": "LMS Batch Membership", "subgroup": self.name, "member": email}
|
||||||
|
return frappe.db.exists(q)
|
||||||
|
|
||||||
|
def has_join_request(self, email):
|
||||||
|
"""Check if given user is a student of this subgroup."""
|
||||||
|
q = {"doctype": "Cohort Join Request", "subgroup": self.name, "email": email}
|
||||||
|
return frappe.db.exists(q)
|
||||||
|
|
||||||
|
def get_join_requests(self, status="Pending"):
|
||||||
|
q = {"subgroup": self.name, "status": status}
|
||||||
|
return frappe.get_all(
|
||||||
|
"Cohort Join Request", filters=q, fields=["*"], order_by="creation desc"
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_mentors(self):
|
||||||
|
emails = frappe.get_all(
|
||||||
|
"Cohort Mentor", filters={"subgroup": self.name}, fields=["email"], pluck="email"
|
||||||
|
)
|
||||||
|
return self._get_users(emails)
|
||||||
|
|
||||||
|
def get_students(self):
|
||||||
|
emails = frappe.get_all(
|
||||||
|
"LMS Batch Membership",
|
||||||
|
filters={"subgroup": self.name},
|
||||||
|
fields=["member"],
|
||||||
|
pluck="member",
|
||||||
|
page_length=1000,
|
||||||
|
)
|
||||||
|
return self._get_users(emails)
|
||||||
|
|
||||||
|
def _get_users(self, emails):
|
||||||
|
users = [frappe.get_cached_doc("User", email) for email in emails]
|
||||||
|
return sorted(users, key=lambda user: user.full_name)
|
||||||
|
|
||||||
|
def is_mentor(self, email):
|
||||||
|
q = {"doctype": "Cohort Mentor", "subgroup": self.name, "email": email}
|
||||||
|
return frappe.db.exists(q)
|
||||||
|
|
||||||
|
def is_manager(self, email):
|
||||||
|
"""Returns True if the given user is a manager of this subgroup.
|
||||||
|
|
||||||
|
Mentors of the subgroup, admins of the Cohort are considered as managers.
|
||||||
|
"""
|
||||||
|
return self.is_mentor(email) or self.get_cohort().is_admin(email)
|
||||||
|
|
||||||
|
def get_cohort(self):
|
||||||
|
return frappe.get_doc("Cohort", self.cohort)
|
||||||
|
|
||||||
|
def add_mentor(self, email):
|
||||||
|
d = {
|
||||||
|
"doctype": "Cohort Mentor",
|
||||||
|
"subgroup": self.name,
|
||||||
|
"cohort": self.cohort,
|
||||||
|
"email": email,
|
||||||
|
}
|
||||||
|
if frappe.db.exists(d):
|
||||||
|
return
|
||||||
|
doc = frappe.get_doc(d)
|
||||||
|
doc.insert(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
|
# def after_doctype_insert():
|
||||||
|
# frappe.db.add_unique("Cohort Subgroup", ("cohort", "slug"))
|
||||||
9
lms/lms/doctype/cohort_subgroup/test_cohort_subgroup.py
Normal file
9
lms/lms/doctype/cohort_subgroup/test_cohort_subgroup.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2021, FOSS United and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
|
||||||
|
class TestCohortSubgroup(unittest.TestCase):
|
||||||
|
pass
|
||||||
64
lms/lms/doctype/cohort_web_page/cohort_web_page.json
Normal file
64
lms/lms/doctype/cohort_web_page/cohort_web_page.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2021-12-04 23:28:40.429867",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"slug",
|
||||||
|
"title",
|
||||||
|
"template",
|
||||||
|
"scope",
|
||||||
|
"required_role"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "title",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Title",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "template",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Template",
|
||||||
|
"options": "Web Template",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Cohort",
|
||||||
|
"fieldname": "scope",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Scope",
|
||||||
|
"options": "Cohort\nSubgroup"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "Public",
|
||||||
|
"fieldname": "required_role",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Required Role",
|
||||||
|
"options": "Public\nStudent\nMentor\nAdmin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "slug",
|
||||||
|
"fieldtype": "Data",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Slug",
|
||||||
|
"reqd": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2021-12-04 23:33:03.954128",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "LMS",
|
||||||
|
"name": "Cohort Web Page",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2021, Frappe and contributors
|
# Copyright (c) 2021, Frappe and contributors
|
||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
import frappe
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
|
||||||
class CommunityEventVolunteer(Document):
|
|
||||||
pass
|
class CohortWebPage(Document):
|
||||||
|
def get_template_html(self):
|
||||||
|
return frappe.get_doc("Web Template", self.template).template
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright (c) 2021, FOSS United and contributors
|
// Copyright (c) 2021, FOSS United and contributors
|
||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on('LMS Course Mentor Mapping', {
|
frappe.ui.form.on("Course Chapter", {
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
frm.set_query('mentor', function(doc) {
|
frm.set_query("lesson", "lessons", function () {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
"ignore_user_type": 1,
|
chapter: frm.doc.name,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"link_fieldname": "chapter"
|
"link_fieldname": "chapter"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2021-09-29 15:33:44.611229",
|
"modified": "2022-03-14 17:57:00.707416",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "LMS",
|
"module": "LMS",
|
||||||
"name": "Course Chapter",
|
"name": "Course Chapter",
|
||||||
@@ -77,11 +77,26 @@
|
|||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"if_owner": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "All",
|
||||||
|
"select": 1,
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search_fields": "title",
|
"search_fields": "title",
|
||||||
|
"show_title_field_in_link": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"title_field": "title",
|
"title_field": "title",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user