From 2c516b24e865f4df53870057f953b52321f4e0d5 Mon Sep 17 00:00:00 2001 From: s457957 Date: Sun, 20 Dec 2020 23:10:49 +0100 Subject: [PATCH] more ajax --- .idea/timefall.iml | 1 + __pycache__/manage.cpython-38.pyc | Bin 0 -> 824 bytes db.sqlite3 | Bin 131072 -> 176128 bytes hr_module/__pycache__/admin.cpython-38.pyc | Bin 0 -> 359 bytes hr_module/__pycache__/apps.cpython-38.pyc | Bin 0 -> 374 bytes hr_module/__pycache__/forms.cpython-38.pyc | Bin 0 -> 987 bytes hr_module/__pycache__/models.cpython-38.pyc | Bin 0 -> 1798 bytes hr_module/__pycache__/urls.cpython-38.pyc | Bin 280 -> 493 bytes hr_module/__pycache__/views.cpython-38.pyc | Bin 391 -> 5215 bytes hr_module/admin.py | 6 + hr_module/forms.py | 19 ++ .../__pycache__/__init__.cpython-38.pyc | Bin 0 -> 168 bytes .../data_import_functions.cpython-38.pyc | Bin 0 -> 1710 bytes .../monthly_planning_functions.cpython-38.pyc | Bin 0 -> 1447 bytes .../sqlalchemy_tables.cpython-38.pyc | Bin 0 -> 1609 bytes .../data_import_functions.py | 37 +-- .../monthly_planning_functions.py | 46 ++++ .../handling_functions/sqlalchemy_tables.py | 47 ++++ hr_module/models.py | 53 +++- hr_module/static/css/hr_import_validation.css | 23 ++ hr_module/static/css/hr_module_base.css | 30 +++ hr_module/static/css/hr_module_import.css | 95 +++++++ hr_module/static/css/hr_module_schedule.css | 38 +++ hr_module/static/js/hr_module_schedule.js | 244 ++++++++++++++++++ hr_module/templates/hr_import_validation.html | 27 +- hr_module/templates/hr_module_base.html | 42 ++- hr_module/templates/hr_module_import.html | 104 +++++++- hr_module/templates/hr_module_schedule.html | 67 ++++- hr_module/urls.py | 7 + hr_module/views.py | 147 ++++++++++- static/css/base.css | 20 +- temp/import_file.csv | 29 +-- templates/base.html | 20 +- timefall/__pycache__/settings.cpython-38.pyc | Bin 2298 -> 2554 bytes timefall/settings.py | 17 +- 35 files changed, 1000 insertions(+), 119 deletions(-) create mode 100644 __pycache__/manage.cpython-38.pyc create mode 100644 hr_module/__pycache__/admin.cpython-38.pyc create mode 100644 hr_module/__pycache__/apps.cpython-38.pyc create mode 100644 hr_module/__pycache__/forms.cpython-38.pyc create mode 100644 hr_module/__pycache__/models.cpython-38.pyc create mode 100644 hr_module/handling_functions/__pycache__/__init__.cpython-38.pyc create mode 100644 hr_module/handling_functions/__pycache__/data_import_functions.cpython-38.pyc create mode 100644 hr_module/handling_functions/__pycache__/monthly_planning_functions.cpython-38.pyc create mode 100644 hr_module/handling_functions/__pycache__/sqlalchemy_tables.cpython-38.pyc diff --git a/.idea/timefall.iml b/.idea/timefall.iml index 6dd7f5e..04c03b9 100644 --- a/.idea/timefall.iml +++ b/.idea/timefall.iml @@ -22,6 +22,7 @@ diff --git a/__pycache__/manage.cpython-38.pyc b/__pycache__/manage.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ea454f83a3de78968db9b96c0044a3979d315e7 GIT binary patch literal 824 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 L!DF|<7q;;aaXr2b diff --git a/hr_module/__pycache__/admin.cpython-38.pyc b/hr_module/__pycache__/admin.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..43bb924affd90145356d0d53598ff1ede48246e5 GIT binary patch literal 359 zcmYjNJ5Izf5Vd3Hv#^UOxk8$CgG7T64IQABSR~|T72+Wu*>U6qq}&Ed?!ZahQmwcF z6&|3-So8ee%y>MS`_<}z1Uo(c*nNfj6UE$E5SPJ+hX9Hws)?bJQlcWobYz%hhD&Z@ z8Jk2VlmKnh*9_QOsQKr7#^V`JkSl&i@^~M*lbrgvP^Rhj6czW`mFcye0Q_Rx7`U+t zwC5XLbUwwvwXJURg*;Mi(N%U`+HQ2sql?08pBStj91p_92nj-pIX*Na_{>4o3?sOA z;tnx~@O>s~Ye4kH3uv*K%DQl7<7^A%IEXQP`c!BwYPSphpEZczf!F=yv-7{m1r9&p LR+sD~T2eeeTv}O; literal 0 HcmV?d00001 diff --git a/hr_module/__pycache__/apps.cpython-38.pyc b/hr_module/__pycache__/apps.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a00467e9007440573f7a7fa180009fe91fa8da60 GIT binary patch literal 374 zcmYjNy-ve05I)C2N=l1(1lBC|)~P~840NHYgjgaZ%ZlBml^q+qMd}PM!z(cH99fxo z1t!i(1wHA0zWeUaejJSkfHMF5;7{nkA~=;4!3;HAp^+eo2180h;0|OW=^IF@$SW-q znLa>q_Kj6gkT$<@?$$P|&AN)2Qy~ausNoWgf|5wUZcBKUd#(EZGOs;1 zU1CwBZN_;cjN-f<@M9X|A?MF~p^r=&{X6&!7j))l!fI<2bK*s5wmej|@Mh`lR#m&e zb{nHsLTmQ7hzaMy*d08@3GoL)f+iy!Uf_-Aax0p(9mhH!xsLf?*he`MZ8q(XzmD(j H<_zgC!YEd! literal 0 HcmV?d00001 diff --git a/hr_module/__pycache__/forms.cpython-38.pyc b/hr_module/__pycache__/forms.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03e027dbde68b7a70c9c4cd614ca5b8bdb532f5f GIT binary patch literal 987 zcmZuvyN=W_6t(l(Og6KRLE;N&rr9ZJ5L#GRw9RTIG))@IjGY+|b`l)VJ|sG5_aC6- zJ7{S50k>593sl^jWS5b^k#EjDzH`syT+hejjKF&J;wSqa5b_I??G-_C47&p1r>p!BD|#{x}`-TV(6auy?LW+E>4w}ry$@1C5l63 zn%X*60@&-T8FKr;JtHNXC4|n5o4^BhDH7u;IEtv0xGLqprV_ zTKLI{mfZ4ppa<>Gs%GPSgi7Ct-GkaL{C+xH)ke-5ekt|r;%2ep)?C<;gIc#pU0_qOmpoF72_;ZQdbAq*h$yXW$1-b#z^-~E990~Tk7Uo$PMrCXg(AK4UG zJHmiBZ*cSkEII8Q%}Qlk*GOKrTgMoBKG;qx`sJaJ(;SOwT_pi z9|7VEr!J+>k=!)WVjrIg*>LNOteihEyy8n~*@HrURyhew-)@Wp!pTU@l<@g|d8zsG z?~Hr2k6&~E0Y9>RjDY6DlTv&zgF#{q-nm4qd9|#27k2yPXi-@ZvUhv~p}Gc;RfbJnDVvh_3K|a)d9*qWz;wJFxUb087wV zy0G*`2us*ld{_n|f+cD!J+X1*#KRk$>cqr!(p*SYK=NJ|QpYXoUF7DibiaZEU|hPi*XZ3#LIcQsfZ{Gf(YtKXfpo8;pB=g(0$j9j z{JnIk^0k!4U*U!sPvs=`OfSzEZZ1pM%bcAiQVG)&Cv2LlRhpUpQYR_bYj!5rH@_ml z{n#}@%D>0uvROGdUba%ov`-Yz&aR2>V~Ocal2ksoh{Do=aIch= zL&m;aaaGUgmfbygk;zF8vTuXYuC;Y{wvTqUclUI=^1n0Zx|*edkbt{P0XQ9|JmWK| z+3f{Qu%Bz0%(AcK+H}X?yqN6mOlVLdIvashCj27Lk(I1=7T!8IReW~s=tnrLBELTw z&GS@_mdK|Xjn`A0pN@6DkkhglS%0TosnJ|F7aP^(w6$DoTi_u^@ji%80@AYoA04k_ z`JWv(BtufI`d4AR>5Wrty;~TzAdvF9JgVM6!ciPo9ukfcxaxtUAS&K(c-U}T7J1z=iHYuk-`EgtY*yk{opq7SlCm(7kWyb7xst}c zkOIVo4oEL+tVF`_d2Ta?>8>2n+5YBD{h>k!GuQ%?)OuuIrSlqR(n5N)&d0DrE z@dU)W!Bc^;?JF{APR_E8);W1k-Wj)dTjmaR#E0hdhioO1>P2;@Koc|hkd z50OKJK^?&mM#q3CCK^KAQ$jR?aZf2x43nOwLXG>v^_W=?m%@^zh+t-?%;J<4o-*p$MkwP|bIbT;cMg-=4t?9zeE bn_B6Ei*L>?x%CF^f@H!cgD{x!et!P|(SwUD delta 169 zcmaFMJcCI)l$V!_0SHzd+!db-q#uJg$bc2daRB0Cy@}e=5~++SEUC;{EGeuhY`x6s zj8Uv9?7Y~=8Qxhgm&;Gd@~3PEAPTsFT9-0X13A<-0>oC6)>U0AzAWOhYtB$yc|Yix zrM|E{6mpRE5THRXJ>(z(y*TJ!=%46uE0kYBp;Yejoky@7;^bmh}&+%>Qgu-oc~(f`nU~MOMsw7TdnfEN=5sREizniOYT& zb&ETZ8&~{F?D?Llm!qm*Lwh-@`*nX@p=C|$~9hpZuu8@gEx_1{NlUqE7O z#n!GA2^Ug(Qt(iUUiJkmI$Dp0Q5x{IFcNF2jCFlo>^xFJQU&wQNfGdFknrv>kV0F-JFkrqX0qt5Dy~ z8#ghl)=QHFa)oKqBhjWmI{Olyck!qe63)gfvvMnE2R3$SukT+R$ZnkSQ6##mHxN|l z46-;{VUlKJ7ZoXTZKXbC6ifvE^ChCw9<8Lj{l7!Edm)+}gq} zp4xw4vc+xG*i%>TW~PK%>A=Pgotzz(kE{d6uv03@UFzedWov9_Zf+m2aValxXPMqt z;m$1!wK94gUe2A6jmz8}yP1cRa`W;*X~W``$y%Rh)x%mbYuP$t<4RV~D`qA0rrTE5 z;NAhljA}6hl73j&U)H3S19sRtvhG5;ns@at3K5 zZ{+oy@hhK|u*a*X_GrN--dNYpgI{iZ;J3nfn8HqnQjpHH(}$V+72bz6X9GBT6qIe4Lfb>`gCW6qJ+&=8dIc#G2ZNIb+QA-5 zmxk%kuik|LtVtY)Bt5J&d7WPVLrRFS=8U2`(>&RT`ZW@ZHCTpCHPX1V3HE>7G8k+N~&51)_eAF^0npp3JI!k--y0(Hx{^ z!%rLlNkm3K%x|!6Bw8Xjm9gI$M|Hp^a*_I0Y0w5+r!h^cSu@#$qho&3aXwV5xhrLfPBfGZjMOL%jFXdg7 zPwa+vLb!PskNOM=2;aCX`KOE>l9MXIWzcEcEQPz zjZfhEIZ=Ic-5_1Jln5j_e_&2TTrbS(Dg*8}<(t^a{$nM;(^>nNmdMC@fjP|Ur<%bM zBT<;-G1(9rDb8tc%5*erKiQj`q$?8!3$RyfvQ#k22AyL@ZRdIWnxfQn%;@!m9JEMh z%7#PeGzvm@u%kR;t zfBwH7#Z2PYa0F({vlrej)G({ByOpiC$ zb7=zS=My;3=6q8?&z&0~H~8(hLKKB7*H5V!HZ)cDD-4&AHbr0YhAi%IggkrQK?>J& zy^VUDCMM5DSON7N!HfD}Wb(cYO|F7$T7M;%ye{C*VgH!1D9AD~7NjH&FaS6ad9`oT z22M8Z41^SO+=emNlzb1WkUu4TeEffX{C6UK?fRHn<BrJYeq<&0lp?h2+6wrQDVOL zD3EIwOfTTGR&zl!moVQQVospskFl~O!Ew!_Yon4?RPar$kffJNA?Z^dg5;uQfbUDP zPP51{OZpU}tCK$dr10Vtwwqf`;las|n$tD=oYS5;8WU1`w~EhAcj(O3RV0hJNfmdi U27L87)+l+d_qOMGSG;Tg2Amqej{pDw literal 391 zcmYjMJ5Iwu5Z(1J5jYY@aDhOUkX_OsghZ1nia->&i7fAc9j(1)cAXGfI0;>j04=w0 zOT`tam^CRf(tP*Lytj9g$pIsK|N2~fQ2w^fzB$xfk?Ug$f(b5J%`?tz?MSC~GnZ;t zcyBE8gn!H8;D?Yb=6!(B2*54x!>KXt4d_-i8VYXTcV=r#aZRqr6bw$0n@5%CQlTk2 kqtOET!`--~Z=y$&VPR0Q7e*F3zW8Umv_IDt8}iWo19ehdg#Z8m diff --git a/hr_module/admin.py b/hr_module/admin.py index 8c38f3f..e7dde83 100644 --- a/hr_module/admin.py +++ b/hr_module/admin.py @@ -1,3 +1,9 @@ from django.contrib import admin # Register your models here. +from .models import Employee, TimeModel, Plan, TimeLog + +admin.site.register(Employee) +admin.site.register(TimeModel) +admin.site.register(Plan) +admin.site.register(TimeLog) diff --git a/hr_module/forms.py b/hr_module/forms.py index e69de29..bd15122 100644 --- a/hr_module/forms.py +++ b/hr_module/forms.py @@ -0,0 +1,19 @@ +from django import forms +from django.conf import settings + +class UploadFileForm(forms.Form): + file = forms.FileField(widget=forms.ClearableFileInput(attrs={'id': 'import_filepicker'})) + + +class NewUserForm(forms.Form): + first_name = forms.CharField(max_length=200) + last_name = forms.CharField(max_length=200) + username = forms.CharField(max_length=200) + email = forms.EmailField(max_length=200) + is_staff = forms.BooleanField() + is_active = forms.BooleanField() + is_superuser = forms.BooleanField() + department = forms.CharField(max_length=200) + manager_username = forms.CharField(max_length=200) + time_model_id = forms.IntegerField() + manager_flag = forms.BooleanField() \ No newline at end of file diff --git a/hr_module/handling_functions/__pycache__/__init__.cpython-38.pyc b/hr_module/handling_functions/__pycache__/__init__.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d4e91f0e44c75377d25734bcb9a5ab42b97edca6 GIT binary patch literal 168 zcmWIL<>g`k0%P;D@gVv!h(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6vPKO;XkRlgvy zEHy_zpfWilu_!m7C_gJTxujUXBr`WPEiorYKcgrg8h7`7cJlgZ9>r={#NaLIM{&_P06s%k~qZ4uJ$P-xLExkT>RnaPl^wLN90 zO1Ttq+ke2J6(|0ZIdbA3078h@Nxv2x`6F-Myng+>&*QKA{QyCG^y9DbpB_TL*_XSG zz{@Al)l(Qa;y6PQhM8m}cOnP3HX2c|IhmV#kq0))-5*fY;U4e6>~o)YVeWE#h(^Kh z5D862*!W6lofb0%>;6;bVFHzkHTzapMt$S4~x7nkK2>;qj_*l z(>as*fh=tnYOK>-BrMCua~bC)UuI%FX9drofN`=c8j#f3A{VE5RZ4wp-Kth*{i?vX zh<0o}2QVOyVuE|vhd#jXW4Q*lweOPF8fopULM9^g6)M!C3T#hd>CqwiQ zm}p5+;|s4Qmr(K=FFKZ!+4G1{lJVsA~hqTI7|X_G43$cIeyKo6Tl`cnoAxpcK39d+(4PQ0VctJQGf{uqEAwbcw2wsAqxU&QLh1uP)Z=hhSULNp! z+~Ga$&bmX3Em?THUt_+;@AJVM5Ln~8&Nuiwd~@c458wYn_Wi zn?cSBHWRY>y-A^O6=9_yvN+|YckPg5Y!+?Ys3eApX5~tVQKunx%arcZ-J{)4cMtat zjc<={V;O2!#?>WftA;F~bx3dsxkw*|XaGb6?${Hw8%Jxc<$90*lBSmy;Hz7*gb+e) z!+`Jx5XC1}c5gj@c!6gvi2UQxo3DR+-nCVJ1b>eL<5fUJrsO8PLj4x3n3Y=qVbYvV xehB8s-c&4`&PBdzuBi6(mYq$MJE_{sM>Zt)ciOAvv6Yjuc6%v6C;qzc{|hh{%@Y6s literal 0 HcmV?d00001 diff --git a/hr_module/handling_functions/__pycache__/monthly_planning_functions.cpython-38.pyc b/hr_module/handling_functions/__pycache__/monthly_planning_functions.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02aa54ec82dad3a626c10d103ad20004bcfcbc0f GIT binary patch literal 1447 zcmY*ZJC7qp5bmCym&cEN+;WcykPtd2Yci4(LgENntpp?^A#2XvyB_a6eBJF^SsIh< zrTY&E)*=6aA9Ct|1PJ^CNKOdxRa-1ekE&GF&#JG!n(v3hjA6X{^WF5QUFv^&+ZR+AmY52pL zR)tkl)m)a1!bED6wPkZ@b^)CbF8#V*R_$6T*ZZ!l)i8AcKxAI3(Cco1hCi{)BBrC+@_SAvAGT{*H4yjw9pHr4r#-JmkW8yV5SM z%VuTa(cC!HLu_+BauA0tTx4vatrMz|KQn!V)%VlMysgz_S-erzb9}-YCT;d&E|hgr^~e)(IwOS7158W>?EC5>oHpy@KCbGhN z(IS)q{MbfayojYZVK;n}*rXFSUG%y{hPV7C*rZs^AbrRHGK7pE2arP<{giBaRD`E& zakRKy)8gOwuav`CDW~Pqwyv;q`(S0({JW4(z{Rs~FM03w{51oFF z$vpMDX#Wvedr+5!wLp6xhrr|bPtX&#ofcBMkXYxLF z5b_7#`#8<`fFD9K%m@4LuQ<}56fpH_GP literal 0 HcmV?d00001 diff --git a/hr_module/handling_functions/__pycache__/sqlalchemy_tables.cpython-38.pyc b/hr_module/handling_functions/__pycache__/sqlalchemy_tables.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40fd9ca75e3056d3d101fe8498b09d28d5bf1fbc GIT binary patch literal 1609 zcmcIkO>f&c5S1)hl4Z$pvgqfbmj(rViT^-R6m1v90^1-!(jIsr7;|E)B_)@V(yEsp zve*8Q{Gi1G++$Du3q5s4mSZ21_EZ^q!$;EO@Xe!Mr)liq^ZEb(_`km6d?m8|V4w38 z-|`cJbfl{s?K0P;c2D)R$2{#bU-wyG2Q1Jb3w6XIJzxXZ0r$dT@k>W~(*MViKExLu z8zS$^0C~{z1bHYU)eKa;;Fp(qTR6 zG7o&{%bxVU^jJXc3zvmmj4%$6#~6ng6X|2NeH;C$m#Sz0?B2p~UC3GihpzAB(zU~- z$+R#He+SLsB()LexzND5jrn>$w+ZL(YoWT4l=DiQDp*nDVVb6oV57POL%lYZuoR}! zkXLrBMJ`Ydz8*DnLYr22c-jIK&!h>cFIi7LQ(}JUm^-vI!S^@QMWJE36z8C(N6l;@ zj6O2OTbNbllvX+uN=>iMI9-TbD%75z)%mQ-ioBeb@0C!q1?Xm#etEEL4B0Nkw@eTs z*Y726)c)F$n`yRyBZG2C9g;)_Q%x$ zIi0x`@5E5*hm$=s!f18~#ss?rZE;9%bBiECutO;_)$m18o6-(H0K7vcMN_Vd;OQc_ zUR8tjK7hp5qPE_d$*fn33Zc$7by>CU($e=3Xy5WS!nTqtJqg=6H*5L}zppi2`^>~Q?et_@VS?-myXymu55Rzm5F6L}^BLw+H74uFDvyVAkoAv|;9$lL@jT}yP z*!|5#I)IPW!Pb}1^l*-iHxst}*Gf#cyp_0hVyiIopW)}Ty>6{P49R0?v+MG+(c{%u V?1_srT5S_|-wS% { + return response.json(); + }).then((data) => { + console.log(data); + appendFoundFilterOptions(data); + }); +} + + +function appendFoundFilterOptions(data){ + console.log(data) + var parent = document.getElementById('schedule_filter_search'); + parent.innerHTML = ''; + for (var i = 0; i < data.length; i++) { + + var caption = data[i]['caption']; + var value = data[i]['value']; + console.log(caption) + console.log(value) + + innerHTML = '' + + var wrapper = document.createElement('div'); + wrapper.innerHTML = innerHTML; + var htmlNode = wrapper.firstChild; + + parent.appendChild(htmlNode); + } +} + +function fetchEmployees() { + var host = 'http://' + window.location.host; + var fetch_url = host + '/hr_module/loeademployees' + + var searched_field = document.getElementById('schedule_filter_category').value + var searched_string = document.getElementById('searched_string').value + + fetch(fetch_url, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrftoken + }, + body: JSON.stringify({ + "searched_field": searched_field, + "searched_string": searched_string + }), + }).then((response) => { + return response.json(); + }).then((data) => { + console.log(data); + appendFoundEmployees(data); + }); +} + +function appendFoundEmployees(data){ + console.log(data) + var parentTable = document.getElementById('scheduling_list'); + parent.innerHTML = ''; + for (var i = 0; i < data.length; i++) { + + var name = data[i]['name']; + var username = data[i]['username']; + var manager_name = data[i]['manager_name']; + var daily_hours = data[i]['daily_hours']; + + + var newRow = parentTable.insertRow(-1) + newRow.className = 'employee_row' + newRow.id = 'employee_row_' + username + newRow.setAttribute('data-username', username) + addCell(newRow, username, 0) + addCell(newRow, name, 1) + addCell(newRow, manager_name, 2) + addCell(newRow, daily_hours, 3) + var cellDays = addCell(newRow, '', 4) + workingDays(cellDays, data[i]) + + addCell(newRow, addActivityType(), 5) + + addCell(newRow,'', 6) + var cellButton = addCell(newRow, addDeleteButton(username),7) + cellButton.firstChild.addEventListener('click', function(){ + deleteRow(username) + }) + } +} + +function addDeleteButton(username){ + var cell = document.createElement('td') + var submit = document.createElement('button') + submit.innerHTML = 'Delete' + cell.appendChild(submit) + return cell.outerHTML +} + +function addActivityType(){ + var cell = document.createElement('td') + var options = {'work': 'Work', + 'vacation': 'Vacation', + 'sickness': 'Sickness', + 'parental_leave': 'Parental leave'} + var select = document.createElement('select') + select.id = 'activity_type' + + for (const [key, value] of Object.entries(options)) { + var option = document.createElement('option'); + option.value = key; + option.text = value; + select.appendChild(option) + } + + cell.appendChild(select) + return cell.outerHTML +} + +function addCell(row, innerhtml, index){ + var cell = row.insertCell(index); + cell.innerHTML = innerhtml; + return cell +} + +function workingDays(parent, data){ + var days = ['mon', + 'tue', + 'wed', + 'thu', + 'fri', + 'sat', + 'sun',] + days.forEach(function (item) { + if (data[item] === true) { + var tag = '' + + } else { + var tag = '' + } + var wrapper = document.createElement('div'); + wrapper.className = 'day_of_week_checkbox' + wrapper.innerHTML = tag; + parent.appendChild(wrapper) + }); +} + +function deleteRow(username){ + var row = document.getElementById('employee_row_' + username) + row.outerHTML = '' +} + +function buildPlanJson(){ + var listJsons = [] + var employees = document.getElementsByClassName('employee_row') + var lowerBoundary = document.getElementById('planning_lower_boundary').value + var upperBoundary = document.getElementById('planning_upper_boundary').value + for (var i = 0; i < employees.length; i++) { + var planJson = {} + row = employees[0] + var username = row.getAttribute('data-username') + var startTime = row.getElementsByClassName('schedule_time_input')[0].value + var days = row.getElementsByClassName('working_days') + var daysOfWeek = {} + for (var k = 0; k < days.length; k++){ + day = days[k] + daysOfWeek[day.value] = day.checked + } + planJson['username'] = username + planJson['start_time'] = startTime + planJson['timemodel_pattern'] = daysOfWeek + planJson['date_start'] = lowerBoundary + planJson['date_end'] = upperBoundary + listJsons.push(planJson) + } + return listJsons +} + +function postPlanToDb(){ + var host = 'http://' + window.location.host; + var fetch_url = host + '/hr_module/plan_api' + var json = buildPlanJson() + + fetch(fetch_url, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-CSRFToken': csrftoken + }, + body: JSON.stringify({ + json + }), + }).then((response) => { + return true; + }).then((data) => { + console.log(data); + }); +} + + + +function getCookie(name) { + let cookieValue = null; + if (document.cookie && document.cookie !== '') { + let cookies = document.cookie.split(';'); + for (let i = 0; i < cookies.length; i++) { + let cookie = cookies[i].trim(); + + if (cookie.substring(0, name.length + 1) === (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} \ No newline at end of file diff --git a/hr_module/templates/hr_import_validation.html b/hr_module/templates/hr_import_validation.html index 4bdcfcb..2117b41 100644 --- a/hr_module/templates/hr_import_validation.html +++ b/hr_module/templates/hr_import_validation.html @@ -1,10 +1,17 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends 'hr_module_base.html' %} + +{% load static %} + +{% block action_panel %} + +
The following data will be imported: +
+
+ {{ df_html|safe }} +
+
+ {% csrf_token %} + +
+ +{% endblock %} diff --git a/hr_module/templates/hr_module_base.html b/hr_module/templates/hr_module_base.html index 4bdcfcb..24716d6 100644 --- a/hr_module/templates/hr_module_base.html +++ b/hr_module/templates/hr_module_base.html @@ -1,10 +1,32 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends 'base.html' %} +{% load static %} + +{% block stylesheet_hr_module_base %} + +{% endblock %} + + + +{% block core_content %} + + + +
+{% block action_panel %} +{% endblock %} +
+ +{% endblock %} \ No newline at end of file diff --git a/hr_module/templates/hr_module_import.html b/hr_module/templates/hr_module_import.html index 4bdcfcb..7ffb83c 100644 --- a/hr_module/templates/hr_module_import.html +++ b/hr_module/templates/hr_module_import.html @@ -1,10 +1,94 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends 'hr_module_base.html' %} + +{% load static %} + +{% block action_panel %} + +
+
+ Add employee manually +
+
+ +
+ + {{ userform.first_name }} +
+
+ + {{ userform.last_name }} +
+
+ + {{ userform.username }} +
+
+ + {{ userform.email }} +
+
+ + {{ userform.is_staff }} +
+
+ + {{ userform.is_active }} +
+
+ + {{ userform.is_superuser }} +
+
+ + {{ userform.manager_flag }} +
+
+ + {{ userform.department }} +
+
+ + {{ userform.manager_username }} +
+
+ + {{ userform.time_model_id }} +
+ {% csrf_token %} + +
+
+ +
+
+
+
or
+
+
+ +
+
+ Import employees from Excel file +
+ + + + + + {% for item in columns %} + + + + + {% endfor %} +
Column nameData type
{{ item }}
+
+ {% csrf_token %} +
+ {{ fileform.file }} +
+ +
+
+ +{% endblock %} diff --git a/hr_module/templates/hr_module_schedule.html b/hr_module/templates/hr_module_schedule.html index 4bdcfcb..695dd2b 100644 --- a/hr_module/templates/hr_module_schedule.html +++ b/hr_module/templates/hr_module_schedule.html @@ -1,10 +1,57 @@ - - - - - $Title$ - - -$END$ - - \ No newline at end of file +{% extends 'hr_module_base.html' %} + +{% load static %} + +{% block action_panel %} + + +
+
Select filter type: + +
+ +
+ + + +
+
+ +
+
+ + + + + + + + + + + + + +
UsernameNameName of the ManagerDaily working hoursDefault scheduleActivity typeStart time
+ +
+
+ +
+ +
+ +
+ +
+ +
+
+ + + +{% endblock %} diff --git a/hr_module/urls.py b/hr_module/urls.py index 91f65b2..c3c69c3 100644 --- a/hr_module/urls.py +++ b/hr_module/urls.py @@ -2,6 +2,13 @@ from django.urls import path from . import views +app_name = 'hr_module' + urlpatterns = [ path('', views.index, name='index'), + path('import_data', views.hr_import, name='import_data'), + path('search', views.search_users_api, name='search_users_api'), + path('loeademployees', views.load_employees_api, name='load_employees'), + path('plan_api', views.plan_api, name='plan_api'), + ] \ No newline at end of file diff --git a/hr_module/views.py b/hr_module/views.py index a189121..38f8eac 100644 --- a/hr_module/views.py +++ b/hr_module/views.py @@ -1,6 +1,147 @@ -from django.shortcuts import render -from django.http import HttpResponse +from django.shortcuts import render, redirect +from .forms import UploadFileForm, NewUserForm +from hr_module.handling_functions.data_import_functions import read_and_parse_excel, insert_excel +import pandas as pd +import json +from .models import Employee +from django.core import serializers +from django.http import HttpResponse, JsonResponse, Http404 +from django.db import connection # Create your views here. def index(request): - return HttpResponse("Hello, world. You're at the app index.") \ No newline at end of file + template_name = 'hr_module_schedule.html' + + return render(request, template_name) + + +def hr_import(request): + if request.method == 'POST': + if 'import_preview' in request.POST: + fileform = UploadFileForm(request.POST, request.FILES) + print(fileform.is_valid()) + if fileform.is_valid(): + uploaded_file = request.FILES['file'] + df_dict = read_and_parse_excel(uploaded_file) + + request.session['df_path'] = df_dict['df_path'] + df_html = df_dict['df_html'] + context = {'df_html': df_html} + template = 'hr_import_validation.html' + return render(request, template, context) + + if 'import_insert' in request.POST: + df = pd.read_csv(request.session['df_path']) + insert_excel(df) + del request.session['df_path'] + return redirect('import_data') + + + if 'import_single' in request.POST: + df_dict = {k: v[0] for k, v in dict(request.POST).items()} + for i in ('csrfmiddlewaretoken','import_single'): + df_dict.pop(i, None) + df = pd.DataFrame(df_dict, index=[0]) + insert_excel(df) + print('done') + return redirect('import_data') + + else: + columns_user = ['first_name', + 'last_name', + 'username', + 'email', + 'is_staff', + 'is_active', + 'is_superuser'] + columns_empl = ['department', + 'manager_username', + 'time_model_id', + 'manager_flag'] + columns = columns_user + columns_empl + + fileform = UploadFileForm() + userform = NewUserForm() + context = {'userform': userform, + 'columns': columns, + 'fileform': fileform + } + template = 'hr_module_import.html' + return render(request, template, context) + + +def dictfetchall(cursor): + "Return all rows from a cursor as a dict" + columns = [col[0] for col in cursor.description] + return [ + dict(zip(columns, row)) + for row in cursor.fetchall() + ] + +def search_users_api(request): + if request.method == 'POST': + body = json.loads(request.body) + searched_field = body['searched_field'] + searched_string = body['searched_string'] + print(searched_field, searched_string) + cursor = connection.cursor() + + + if searched_field == 'department': + cursor.execute('select department as caption, department as value from hr_module_employee ' + 'group by department') + elif searched_field == 'manager': + cursor.execute('select auth.first_name || %s || auth.last_name as caption, empl.manager_username as value ' + 'from hr_module_employee empl inner join auth_user auth on auth.username = empl.manager_username ' + 'group by auth.first_name || %s || auth.last_name, empl.manager_username', [' ', ' '] + ) + elif searched_field == 'username': + cursor.execute('select auth.first_name || %s || auth.last_name as caption, empl.username as value from hr_module_employee empl ' + 'inner join auth_user auth on empl.username = auth.username ', [' ',] + ) + + response = dictfetchall(cursor) + print(response) + return JsonResponse(response, safe=False) + + +def load_employees_api(request): + if request.method == 'POST': + body = json.loads(request.body) + searched_field = body['searched_field'] + searched_string = body['searched_string'] + print(searched_field, searched_string) + cursor = connection.cursor() + + + if searched_field == 'department': + cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, ' + 'empl.manager_username as manager_name, tm.daily_hours, ' + 'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.fri ' + 'from hr_module_employee empl inner join auth_user auth on auth.username = empl.manager_username ' + 'inner join hr_module_timemodel tm on empl.time_model_id = tm.time_model_id ' + 'where department = %s', [' ', searched_string]) + elif searched_field == 'manager': + cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, ' + 'empl.manager_username as manager_name, tm.daily_hours, ' + 'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.fri ' + 'from hr_module_employee empl inner join auth_user auth on auth.username = empl.manager_username ' + 'inner join hr_module_timemodel tm on empl.time_model_id = tm.time_model_id ' + 'where manager_username = %s', [' ', searched_string]) + + elif searched_field == 'username': + cursor.execute('select auth.first_name || %s || auth.last_name as name, auth.username as username, ' + 'empl.manager_username as manager_name, tm.daily_hours, ' + 'tm.mon, tm.tue, tm.wed, tm.thu, tm.fri, tm.sat, tm.sun ' + 'from hr_module_employee empl inner join auth_user auth on auth.username = empl.manager_username ' + 'inner join hr_module_timemodel tm on empl.time_model_id = tm.time_model_id ' + 'where auth.username = %s ', [' ', searched_string]) + + response = dictfetchall(cursor) + print(response) + return JsonResponse(response, safe=False) + + +def plan_api(request): + + print(json.loads(request.body)) \ No newline at end of file diff --git a/static/css/base.css b/static/css/base.css index b248c23..14408a9 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -1,8 +1,16 @@ - -.top-bar { - height: 150; - background: #C0C0C0; - margin-left: auto; - margin-right: auto; +html, body { + width: 100%; + height: 100%; + font-family: sans-serif; +} +.navbar { + height: 50px; + background-color: #D3D3D3; + width: 100%; +} +.main_container { + background-color: whitesmoke; + width: 100%; + height: 100%; } \ No newline at end of file diff --git a/temp/import_file.csv b/temp/import_file.csv index eebff6f..f85f523 100644 --- a/temp/import_file.csv +++ b/temp/import_file.csv @@ -1,23 +1,6 @@ -,first_name,last_name,email,is_staff,is_active,is_superuser,department,manager_username,time_model_id,manager_flag -0,test,test2,testtest2@fff.com,False,True,False,test department,93099,10,0 -1,test,sf,testsf@fff.com,False,True,False,test department,123555,5,0 -2,test,fsdc,testfsdc@fff.com,False,True,False,dfdfdv,58347,14,0 -3,test,sdvcds,testsdvcds@fff.com,False,True,False,fsdfgfg,21411,11,0 -4,test,vsd,testvsd@fff.com,False,True,False,fg,100670,14,0 -5,gf,ddsf,gfddsf@fff.com,False,True,False,fsdfgfg,56776,1,1 -6,fg,bg,fgbg@fff.com,False,True,False,fg,1012,7,1 -7,gf,gb,gfgb@fff.com,False,True,False,fsdfgfg,24615,6,1 -8,fg,gb,fggb@fff.com,False,True,False,dfgdfgffgs,131029,10,1 -9,fg,gf,fggf@fff.com,False,True,False,fsdfgfg,150186,6,1 -10,gf,bfg,gfbfg@fff.com,False,True,False,sfgdfsgdfg,127720,7,0 -11,dfg,bvdf,dfgbvdf@fff.com,False,True,False,test department,21584,13,1 -12,fg,test2,fgtest2@fff.com,False,True,False,test department,106721,6,0 -13,first_name,bfg,first_namebfg@fff.com,False,True,False,test department,151398,10,0 -14,dfg,test2,dfgtest2@fff.com,False,True,False,test department,18196,1,0 -15,gf,gbb,gfgbb@fff.com,False,True,False,fsdfgfg,23266,11,0 -16,dfg,fd,dfgfd@fff.com,False,True,False,fsdfgfg,109517,15,0 -17,gf,bsdgbdf,gfbsdgbdf@fff.com,False,True,False,fsdfgfg,56302,13,1 -18,gf,fd,gffd@fff.com,False,True,False,fsdfgfg,149169,11,1 -19,dfg,gdf,dfggdf@fff.com,False,True,False,fsdfgfg,83458,3,0 -20,dfg,gb,dfggb@fff.com,False,True,False,fsdfgfg,12670,6,0 -21,test,test2,testtest2@fff.com,False,True,False,test department,49135,3,1 +,first_name,last_name,username,email,is_staff,is_active,is_superuser,department,manager_username,time_model_id,manager_flag +0,Jan,Kowalski,kowalskija,kowalskija@company.com,0,1,0,test department,hitlerad,1,0 +1,Janina,Kowalska,kowalskaja,kowalskaja@company.com,0,1,0,test department,hitlerad,2,0 +2,Tadeusz,Tadeuszowicz,tadeuszowiczta,tadeuszowiczta@company.com,0,1,0,dfdfdv,hitlerad,3,0 +3,Aleksander,Lukaszenko,lukaszenkoal,lukaszenkoal@company.com,0,1,0,fsdfgfg,hitlerad,4,0 +4,Adolf,Hitler,hitlerad,hitlerad@company.com,0,1,0,fg,hitlerad,5,0 diff --git a/templates/base.html b/templates/base.html index 4bdcfcb..8976638 100644 --- a/templates/base.html +++ b/templates/base.html @@ -1,10 +1,24 @@ +{% load static %} + - - $Title$ + + Title + + {% block stylesheet_hr_module_base %} + {% endblock %} -$END$ + + +
+ + {% block core_content %} + {% endblock %} + +
+ \ No newline at end of file diff --git a/timefall/__pycache__/settings.cpython-38.pyc b/timefall/__pycache__/settings.cpython-38.pyc index 9ce795ea5a3753d4098567eb1c33cfb45ed38845..f2bc50801d638a39e60fbc75091d45512621661a 100644 GIT binary patch delta 619 zcmYLG%Z?I36zzJ@&HFtAGk}f?2tFE`#CdHDK}3=P4UL;xNQk$mrwI%Q?S{=PX5-G7 z-p&G+E)Cz{FKE(R|G>nBM1wVujCFEP&bc}FRwcCzEhGNdKA&6Q=j6xt&Kut+fARt& zK>&dXfB^T=05jg;n)C@H8rJ9~nmOh|Pwa_I0?M4=U@j0r(lK*`6I|d14|u@`eqCZ7 z2tW`*5QYduVT*UXu+4lB(H7y129|x49lC10>%1Tj@mD1tVrIZfjB8M_f zosBz#A-wNva(6VE$S=l?wW|!zPYr!>iYwSVjogF^iy5t=^wd3h*EdYzvcP2=sA)m7Lq&UIDiFF`-q-0`_t*?@P zWYbaCJhN$UXq?+YwOwx4E6?jERkic1-cnhx-FVfx_8qnTvQ@5CKMUgw|M+pndg5$k zKX6ICUgRV}i4ux2!Ye9q{*T|(W6hk=oQT8~CiptC!5_TBOS+=r&47sff4TEp-<)ZY J67PzN{{UW=m_q;n delta 403 zcmX|7Jx>Bb6x>}NcieHu_lE)sC@QoT7RJPALJS2oYO~En9Xufz&4u1Xe}FO9844|} z>1<5=1=h6o_M#CN6PcGcnVC%S^2W(=JaTB;CR1=(`ubC`Fj!;u@1%cYIHjG%zVf+{ZN8HxkZ;WCO6%Bobt(jPDXaizmuk}<5vI96ps zosv|WQk%w_%%Hl@YPI1y-{!t2HiqwFR}43UTRc`1Bdy-rYqaVkYV9=Z!+WjDbFEr- zq&p5SP8?^XUmo?(dYxlWs7Lr8`mKK*IyIh{S5)3B`embe&{vWyD-hEuK!P;EXEP>q hrl;vAnM8tzgu;L8TTH|kO(;(KG}C^Rw*5Dw@(W;jSJVIi diff --git a/timefall/settings.py b/timefall/settings.py index 9dec448..225e1d9 100644 --- a/timefall/settings.py +++ b/timefall/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/3.1/ref/settings/ """ from pathlib import Path +import os # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent @@ -25,12 +26,14 @@ SECRET_KEY = 'tx#+u3u-r1$n_4r(!6vvcb@1f5!z21^74w(zesiz$&59&72$kq' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['192.168.101.128', + '127.0.0.1',] # Application definition INSTALLED_APPS = [ + 'hr_module.apps.HrModuleConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', @@ -54,7 +57,8 @@ ROOT_URLCONF = 'timefall.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [BASE_DIR / 'templates'] + 'DIRS': [BASE_DIR / 'templates', + BASE_DIR / 'hr_module/templates'] , 'APP_DIRS': True, 'OPTIONS': { @@ -78,6 +82,7 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', + 'STRING': 'sqlite:///' + str(BASE_DIR / 'db.sqlite3') } } @@ -119,3 +124,11 @@ USE_TZ = True # https://docs.djangoproject.com/en/3.1/howto/static-files/ STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, 'static'), + +] + + +TMP_FILE_STORAGE = os.path.join(BASE_DIR, 'temp/') \ No newline at end of file