From e709570f2253e8f6b8fe41527ace72551a647bf4 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Tue, 31 Oct 2017 22:36:31 +0200 Subject: [PATCH 1/7] Change stuff to use excel files --- locale/en/LC_MESSAGES/django.mo | Bin 9781 -> 9233 bytes locale/en/LC_MESSAGES/django.po | 91 ++++++++++------ locale/fi/LC_MESSAGES/django.mo | Bin 15006 -> 15384 bytes locale/fi/LC_MESSAGES/django.po | 103 ++++++++++++------ members/forms.py | 6 +- members/resources.py | 26 +++++ members/static/img/excel_csv_save_example.PNG | Bin 0 -> 5882 bytes .../static/img/excel_csv_save_tutorial.PNG | Bin 0 -> 5131 bytes members/templates/application_list.html | 4 + members/templates/member_add_many.html | 41 ++++--- members/templates/member_edit.html | 2 +- members/templates/member_list.html | 2 +- members/templates/payment_list.html | 4 + members/templates/upload_form.html | 10 ++ members/urls.py | 11 +- members/views/utils.py | 56 +++++----- requirements.txt | 2 + sikweb/base.py | 8 ++ 18 files changed, 248 insertions(+), 118 deletions(-) create mode 100644 members/resources.py create mode 100644 members/static/img/excel_csv_save_example.PNG create mode 100644 members/static/img/excel_csv_save_tutorial.PNG create mode 100644 members/templates/upload_form.html diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index ec48ec6d7a5c586861ffcf6c0127edb61ef90fa1..b66103652d23e13da5c789937e3b71d41081e22e 100644 GIT binary patch delta 3126 zcmYk-drX&A9LMnkUO+J~K&UA4>z5e94;2*^Gn0!6f@n#2OH;@!#0*h0HJ?;aOL3{$ zY%sUV73S1Gu<3GM{>ZK7`lrim+N`7|wpOmjU~_5j&+~lQI{STjopXNAb1vWKJU>1w zJy7J`jPH5aQ5uQiM14=^F5w@s{GqhRIj8C!^Ka}y`yOWE1MH2N{eu4S*q8PsHdlel zR2AyF8q|hrQ5o2Qx^6%A!X}Jie)oZO97jIxG=DVkMQdL{4fGuj!QW5|x{q3LZ&s^` z2cZT|M!s?(9EW3ZHZI2qoFC3xgHg~~A04Y{ZcQS_zcG!VhXirwD*Q^g}Vd<#fiEK>Ar8o+AA&<;+C#gi!aUN%ING_soe85rH4q{oh z4p%&Cpd{2z^R2%ab!g|HGO`f$x~)V#+FEOGM=i7wwUK6Dp8rWIy73}L@G53u7iveN zl7qvQiE8Jf7B(G~nIg==dDg!R^@H;cDidcg6~8tAL56k-q`j}+|12t6=@ir{E5zS=6`}tbGMNrQ|9V4SXHd{slGA zUDOXw6bC~$CZkdvMopZB8h8@wzG;|&C0K|XaRQ!4UH2F2{tnckybQ`tvyJjb9ocqYf#q#s19cEw}7GemiQ5)Hd90SjN zVjW)u9qwn;O8-TrvKJ3bJ5EA9iY(L)o5oy&?;pH<^lv6K@vFf#?gi8Yb;NjL3h@-tU5cnYMkp&=2&G+TNxOfIP|;~$NGOx( z#IuCTi^Ogsh56kaqPuA2(~0MZb=FypdBhsxWkS1ONvMz{zvvn7BpQOIn}-vuz71y+ z`jJwJCNlk+bBAK%25Jqi);hYWq*6}oB~}n6gi0eZmUxADi&#R;B6bielL$SoX~ZsK zE#apfdlAnN-KCTYPsQ_3IB$wuZr{9)Gl@5>-Hi_16T}!|6)}U@PE-*8FV9=!Y1~A- zM1%+qoL|P71?cGvs5~AJyq8vAgd+(4ZTr83t8qS|GMCVSR2dcEA2huM+1A#9eADX7 zu%0L*bTHQwdx##IKaEhy2yky>4Y8G2KcztVEzpr9i+Y@g@9}1@pX}vXgMN~|7Xngk6ak+BNby#<6ZpFfSP$brm2~B<&Or+M0K2x8nD2&$Dvj} z88zVgWKE{X{_fh}gB{5~eVS!l&_uSP&cJi12ajPozK5xJ z0e53OY0=8}qcV38yI>u5#!vB1JdcqrLME8_ZdhP%C_!by zYYn0XegrkZYTJGWm5IHmj$c7#;HdR&R6oa2Tl@)Xq2b@C^rX^~-W=?YTFDgD_rPb{ zn{4|`#dJ(lZEjb99c^c|)_CpOc4ApTVYQQ4fo`qVu2Q}eJRH_%D?pujk*cwy@c41gI zK2Jrj-K(gM>umciR7UDi9e-xqr%@f9M|Qo@EuRn$Q9J`!UqY>#ZN52L1vyz*n|?8I^$s)IiO8 zL^IIF+7Z=H7i7(0)02u;Iu7+A@}PqoP%Alzyb$IC+y36R|3alUiH9`d6jW+6P%F0Ln# zCj7*7LYXTf3W*uS8X}))EcZ}ZMU)f0qHE`L(ol(wVuGmCyv?>J;R0KK(7Fsggtl%D zF@l&+=!29@tRt$3)x;=bCh;)Au0~4B$X{}=Z}VtEhb@g*OZ;0I&P5$W9WH&vTq2#| z8)X&~oMtndxSv=`OduX5iiyXFYC>fq5s1|IwlKcQv5iNpdM^uXy&u*RTZjsKZ3%`5 zo#w6fnohWiLkuIP5t|8pH8&D^wHwQj#tLeDGnMeELK#Z*AnqpgUaO3YV#=%|WxR7k zDfb3~p<=(M%FT3qo`0%tmB;HV_LP+c++fi0_{*GyK2NDzTwPvV9q?9o{Z2SoS-r?t z=FD@Q3h!dq?*u~uufM`s?C~vfgZ*wA#8X>aT;*2Ha|4mC=6iz00k_n<(Chj`&aM4~ zD&1%&PPWs#y1YEYsSY?fRQ(w@_S(d8>V9tZWn52hFsN};L+;X0x!3iTr8-k4Pb+c) zZVeL&Igx91?{@gMN%LBN$g_0k)zqZABb_}laoJAJfc(6iom~@u4Bs^0|D2Rt*K*rA f8SnfrNg*fK5@*JxPrSXPOm`01q|{wa?G*Djbx@@9 diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 3811b8f..76f0867 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-10-30 13:41+0100\n" +"POT-Creation-Date: 2017-10-31 21:09+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -201,7 +201,7 @@ msgid "Place of residence" msgstr "Place of residence" #: .\members\models.py:19 .\members\models.py:70 -#: .\members\templates\member_add_many.html:35 +#: .\members\templates\member_add_many.html:39 msgid "AYY" msgstr "AYY" @@ -225,7 +225,7 @@ msgstr "Source" msgid "Cash" msgstr "Cash" -#: .\members\models.py:72 .\members\templates\member_add_many.html:36 +#: .\members\models.py:72 .\members\templates\member_add_many.html:40 msgid "Bank transfer" msgstr "Bank transfer" @@ -284,7 +284,7 @@ msgid "Muista myös maksaa jäsenmaksusi!" msgstr "Don't forget to pay your membership fee!" #: .\members\templates\application_index.html:16 -#: .\members\templates\member_add_many.html:48 +#: .\members\templates\member_add_many.html:55 #: .\members\templates\member_add_many_confirm.html:22 #: .\webapp\templates\kaehmy_list.html:48 msgid "Send" @@ -322,48 +322,50 @@ msgstr "" msgid "" "\n" " Enter member information in CSV format, separate members on " -"separate lines.\n" +"separate lines. \n" +" If a new member already exists in the database, a new payment " +"event will be created for that member instead.\n" " " msgstr "" -#: .\members\templates\member_add_many.html:18 +#: .\members\templates\member_add_many.html:21 +msgid "Format the member table like this:" +msgstr "" + +#: .\members\templates\member_add_many.html:25 msgid "" -"\n" -" first_name, last_name, email_address and place_of_origin should " -"be given string values.\n" -" ayy_member and jas_recipient should be given the value 0 (off) " -"or 1 (on).\n" -" " +"Columns: First name, last name, email address, place of origin, AYY member, " +"JAS recipient" msgstr "" -"\n" -" first_name, last_name, email_address and place_of_origin should " -"be given string values.\n" -" ayy_member and jas_recipient should be given the value 0 (off) " -"or 1 (on).\n" -" " -#: .\members\templates\member_add_many.html:23 -msgid "Syntax" -msgstr "Syntax" - -#: .\members\templates\member_add_many.html:29 -msgid "Data" +#: .\members\templates\member_add_many.html:28 +msgid "Save the file as CSV" msgstr "" #: .\members\templates\member_add_many.html:33 -msgid "Payment source" +msgid "Upload file" msgstr "" #: .\members\templates\member_add_many.html:37 -msgid "Cash payment" +msgid "Payment source" msgstr "" #: .\members\templates\member_add_many.html:41 -msgid "CSV delimiter" +msgid "Cash payment" msgstr "" #: .\members\templates\member_add_many.html:44 msgid "" +"This payment source will be used to create any payments for new members that " +"already exist in the database." +msgstr "" + +#: .\members\templates\member_add_many.html:48 +msgid "CSV delimiter" +msgstr "" + +#: .\members\templates\member_add_many.html:51 +msgid "" "The symbol that is used to separate items in one line. Defaults to " "';' (semicolon)." msgstr "" @@ -469,11 +471,11 @@ msgstr "Member register" msgid "Language" msgstr "Language" -#: .\members\templates\settings.html:20 .\sikweb\base.py:222 +#: .\members\templates\settings.html:20 .\sikweb\base.py:226 msgid "Finnish" msgstr "Finnish" -#: .\members\templates\settings.html:21 .\sikweb\base.py:223 +#: .\members\templates\settings.html:21 .\sikweb\base.py:227 msgid "English" msgstr "English" @@ -560,9 +562,9 @@ msgstr "Successfully updated payment" msgid "Could not update payment object" msgstr "Could not update payment object" -#: .\members\views\utils.py:117 -msgid "Missing \"textfield\" POST request field" -msgstr "Missing \"textfield\" POST request field" +#: .\members\views\utils.py:121 +msgid "Missing CSV file" +msgstr "" #: .\templates\admin\base_site.html:43 msgid "Go" @@ -576,7 +578,7 @@ msgstr "Error" msgid "Back" msgstr "Back" -#: .\templates\footer.html:23 +#: .\templates\footer.html:23 .\webapp\templates\kaehmy_footer.html:23 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" @@ -850,7 +852,7 @@ msgstr "" msgid "SIK Admin" msgstr "SIK Admin" -#: .\webapp\templates\base.html:15 +#: .\webapp\templates\base.html:15 .\webapp\templates\kaehmy_base.html:14 msgid "Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" @@ -1047,5 +1049,26 @@ msgstr "All challenges" msgid "Total challenges:" msgstr "Total challenges:" +#~ msgid "" +#~ "\n" +#~ " first_name, last_name, email_address and place_of_origin " +#~ "should be given string values.\n" +#~ " ayy_member and jas_recipient should be given the value 0 " +#~ "(off) or 1 (on).\n" +#~ " " +#~ msgstr "" +#~ "\n" +#~ " first_name, last_name, email_address and place_of_origin " +#~ "should be given string values.\n" +#~ " ayy_member and jas_recipient should be given the value 0 " +#~ "(off) or 1 (on).\n" +#~ " " + +#~ msgid "Syntax" +#~ msgstr "Syntax" + +#~ msgid "Missing \"textfield\" POST request field" +#~ msgstr "Missing \"textfield\" POST request field" + #~ msgid "Options" #~ msgstr "Options" diff --git a/locale/fi/LC_MESSAGES/django.mo b/locale/fi/LC_MESSAGES/django.mo index a1860c533edaa77dbc4df160d85f49191ebe7178..9b35184b851d2ef78884cdbada802a4a676b5b67 100644 GIT binary patch delta 5906 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 XQ?hm~4W$dS&f~2)F_xCSrEmNf4;>or delta 5529 zcmbW(dw7gj0>|+)k(3}wCUCduSBB$HHV%$6#3TWMO& zVkuRs#p+JjwG_pwc4=Lzs;G78W4r8Hy6v;2`*gp*%-KHC{dUO@8MdkhuKYnPRBab%dj(+<9)c< zwr|G<)T{A++>iC~1U59rZ_e8jzQia#_}bRPng%b3MvbK%s-slfKEOH#+t8kYbZGpT zic2sF_hJ{kj-eRS%$Nvljg7d!Nur<&2VyvmvL}p3U65%%_n>B8ikg8Rb^an`(acN8 zKeL)YKf{1+KY=}|pGBP?)!dk9jKMhWZ#q+GjcKTv6k3;I4E1fO8y-Qe&?(dmuApvw z%la)gqV8y647+5Spq4xlld&&qqB*FEm7rgRSrpWfAGLQ2P)ofGb-_y1%r~LV-;U~d z2kN}TsPj&u`niZLx6A`LPFwbyRcQu$B=nuEIGeEazd zTYnwt+w4RQ>?70-K1TI-0oC6X)D3T=R`L$&ys%i-Uk#D5#)M!D>cUo7^Uz@m^;8^* zQ!xp*Vmy9^T58iWcwG}zf3esW<86Hy^8A^{Q8&)PM4aKLpuJp)Jox4f)J)z%t-t}) z>vhz&A4i@ea~kz5+^~L!*LZCk@(yb&{>2lh&mBBiJun(Iv7xAbN1+DdA8#8ntRB?U zS&ZsvzV$`aK-Z$SWGiY(t5I9C$9{ecb)$2r^Dd!Q=PneR{oYtEC-F8ECc3hHPO zY6V8v`V>r{o`vmjDOTZj)C!Go2A6saGI=u*wK65hi(r=6`UccYccUhB2(7>nvC1(|^vfO^WGu;!v>T#h=g0yV)ksPBc1w*3&^ z&;88_3R>FBsHOWSYKGs~`d!oj94v!IUfGz(233Cf?LrC^;?o|>oaV9DXPCW zQT@Li$NKBx*+ql=0PEm6d%{K346k7_-arksW&7ay38;s)H|o3*I1b042D~2i`4-fc z?!{0%hCGMnWP8?MOLL2c&UgnCF@b3%U>a(~rKk?eQ5`HmE#(r_60gJ%+=P!hm?36U z|AtQ9#3>zu0}iKiT^EaWFwsvzH%`KOI03aZF4PS@sF4?2=UOXJ9leTr__m>D`mX)_ z6zVm*Z0omC=Q}zE_dW`>0{%D(TKd7*3&)|pFcx8d+=un>E^6sRI|VzALfyCxY6ZGs zeH@74IMTMK+qw%ikv!Cj&I-2s&9f93oLP)|DyvZ)9zp$VoLwIu*m`H=!8X0H0Zv5iy&JW( zxu_e=LJe@9brEU>DliOJp|*4#s{hT_-59C&|Cl}DJT|0$74=nl3kPGvF2QfcG}H|< zQ5_ecZd8ogigJv=<){g*K@EJfZQp@f;e)6zqBH2%$iAka6aRy%hbIST7>&A7TU2`o z)J(ggZqUot2cgazj*&P9Q*bhl#AV1_%vtP&_jL`fL~2*oUrYKh4RSbYWTR0lk%!vj znW)#L3iS=Q8Y8e8wNeM{=NC{ba>>@OqXv4@dIzJZhcPAHF1M~l4R9N(-#w`F-nZ@NP`@Q#`YC86-=l66)jhbx zO;N99E7VtM7u0zpaR5$24WJ4&!*!^w*@A5`fO>dOqkc92jauOfW~HrOfm&(*dJ6ja z+>g58JZdK2qh=7vJE#j{W$hLa&g$5nEQ ze54A;05XyMg>2UTXA&K*Am$kIonnrYlY}q6n&V^sK1UjmUy@+RaXNZp^k=f)d(RYE4-;vW~Jeft_Cr+ZH4_Qe{$R|X{ zIifEr9iNfWBtjLAW@K4Sspj{?Z;GgNv<*A(B6-->|HnQGeaU0C;RvSL@*k{qtYSs2 z@^5OD^K3aETaeX;7d6{9cED1ymb^#0klzv=pOdXMrQrVyTH3N$P^pN>5=AK%Xr>NMMQRpggCpq(7KNQ^sE>C`jD>JjmU0m#R6=pi8=ewr4GrUb@dRVYai>m0#j6PQK?J!(C-%83pcwsqUhhu5w+)8Aa}C zp6MQUq3i7=+JR(-t`1rYa;*-fn>-tgO)Inpqjr{;Nt?eA;V! z;vIEUoT=UW^+>Hen9x?`9{qZB3tUflz~TQtRw>u@lST5Dx_r(8cTrxRC)Zo(&2`afpklFdNBXo$%=L$U1<**}=)OBfC yiyyB{mpoS7cW^`H@iuz{^LpNP1YYTV#Zg!5l2_~r%5$OR5pdv_DL5d+#6cCUON=FR@ zl@LHcgixeNNRTE?f`Nay_rCG&yZ62^{vUsgBLx>p^5)Ga9{|uxTFKBAPQ4}i-R88#@ZlIbt?NW7bf7E?WVq6 zAPB^X+y63j`Mq!jfexn{=xJM`92XsWEWRrXe$#YUT7KicKG}*=Q4a!l2SJw zVDa;wq@iu(Op9_`kkG?q@ z%tPY(!UXk%*N#p1tkGys6!n}9O1KJzY##|anI}!jxBt?~xO+0+R9J_6o!g&~cpqj8 z)qQ#Y25w^-zJD|UDFl@bQBW15NU!o=U3HX?kOnO>n%6BPAUe?I%U+`cEV z`@{6f9_@*mglHi={YLf3(`N&=>cC?|kW$7|Ta!_Kk2T?NdlIf%_-pNm&&pe$vm$7f zjL~}V2Et2~Gf;&SyHjId_bRmWoz!qzpRLg?F_UvCa+)(ekY(w>pQxQ{51GG(Up`WR zl1-kP+}k>C4%2YZ;>{h(3f8<-AHs>X8T@HqrZ8C4$I;QNwddo@b&>!6F_lDzYHVLY zb`o56`<~2@!N9Ca&{Een!H+jxH7DWA6Eh*(h&u?ELVJFfO;2K?i;I8~Yu{k$x#bSX= z3BMXF*bOC8)8kTMN#X$gS_4jE01t!j9Rty5@w1dgFnsQIB`v>@+IAUvdQE|!o+sdlRE&six=4E|dzSQeNx`5zew zb?4ogn(665zomB5xCZ+QlIet~TPll}mu8Rb83oUBS| zeIB0VqZwYpe2Xy^Y0)QXG^u0Nc3coQp6EY6b~k%MAqOFB5OO9qdrUzXK5^R?Oh`;* z|BcB|@P0!0LmQA;Z-h;fD+`mwJr14hLAP(u33;o-Pp#<${0tq(EezZv%&I(U761Tq z>847%($|w_)~EF!!j3P(ng#$4VijiDkntA=a;h z;v#c2>fqxlk;wggdbm^eDjj~Q*~CO4#W#T6aGv9Bok~Q@fO2erOEK77qsSK=7m0jJ z#IZqjy&^W0V;z8iVFVi|w3~02o9YWn=rF=TgR{)kh9=QfCuy7pK$9;M4k5Ux9x)!! zFaq*(do`mQ>H1-62D>R78X0LKSb#DjK@HJTwSVAxOkMb{bo%~_SDk}0GFj%SnM&i^3*6s^O2F$^rr_9`4Ezzj8Xt+im7nh+J6n8MXBl*C*2FKBqFoxAR z1~lrtm}oluOe`BHUWf&#lIMlj7^iy<&{lw3q|nY_2#6QPnYX4Gtun{dfniyn0&X#* zt)GeQ-dplQg0sZOw-tA?gsKEU1_lfyOt>w`n?f(SD5*GjeR1>d7l zz@vhcW53Ctdg%ogajvmkkyxssowwo5AhLNsmuz~)GUz9q6S>uz@sP}->1gO15)yI< z9g^Ty$D*QX-S0K4R?H~-J=`QOP}&1Mhuf^0+dGl9VH+5nLUR6&?PFV3t&b;OPld(KjoNPY+M>AJp^ z41*~1@E4KXp&UUw!$0;)dzls-#&)ldd!sdjc}v?=i(Rp%bJc?jW>FCvyohFq?q~L9 z0!)UB!?ld7#DFC0j@1%5PZ^+}i%rbJS7|n04Yi;en9COsck^jqLlFN$SMPYvKB&}V zRFFp&dv&;vc>9a0WRG!c!>I$G)=f7qJe~CErDFU~mwTUb&Zu_`q=#^iY7K4*_KC`W zyOvjfs{RxGRNjsc)Ye<9HfpHNI4i5E)ZvQEZp&ua&)qW{`5}_bvfr5qzx*GR!@W|1 z0!8sv@>1wein008Hjv^Y5eta?aOy8tjQ>|-L@wMiY=Nfk)nD@Ty0>0cP)McAN=}+D zWw%Ze=J0up{}E}Zda1sF#9Q9>q%u3QnRU@rq#NtUR)_R8LsD(v+ zVhDEp5&S|6fzBI`XJEg@Akj8L#Sup4R4(kU1;S-&fl^7JM_!?EwvgHYys@__ze1BLFO;w6mGy&UwVK-Z?1W3Tn8O)lp zro$-F(^w$cS_F5T4OVjn~XpuNVm` z8KL3vZBOXnjSr>r0vR-OJ{!pya>s{++DeXv9Ddqh+$a`WRV9!YP@vOBt21_1<@~-4 z+Q!}eB)O;sSCDM~9CK92buJPGot%UlHR4b=g|;Jewdc)xME#vDx7Ka3=Dv*=b&Y zj&JMc!Nz-`6%NR$7RL*xD$04@4%r#YeBR*11bz&fKU@DZbH^af3WM_^U0ASh$fC4` zd`KZ@5d4y#sW9KU*m`z&3fqP&sz@2U0Oq2<{>z^qPJ7oyS2b1<1yREBH#L zt&0AddD8O1A50LmCH{+v9YoHWo4)Q z!@{KH&^^^V4{S|F`R@L2->)c2WGQkiY;fEnnn(gi8e*y|4{K z%lLe7x8RWu1WIOqAYGv=WD=*RWY6-FfqO@7WOLo7FDPlF*xSFgA~N-iKntXGweahc z(`+z*<9KSFzf|k+dc6U-s_OE4)jLFm`Qr@e45mWUH&E-Mo642lbG6rQ-LjE=Nk@g8 zja{I8_aT_EHT<{sbv{WJS8tqemf-Ip$%LP^ZofPF{TZ>0 z`lN9xqI0mB!V99yXUcF2KIDptmJ|dhD#n#T%wawxMAWSJ^(-W1 z%5t9VNePF^n$G4lhXp=1lxz56bmPlRq0e1SVh%E>dCpJswUOJ4N%hWE+Uv4JwJVbG zwvB^iC|hv_yr_b`6K5CmI5t*!EVv^2r9epbWs6H9V(RAnd0gvuOzH5}BL|Alf&npWuv@IB_+!q6+xkz%r;HJPQO%w+!Zwt`5QT-F0JZ{RnMawJRqKQn zDgt4v7ARO(;Z1Lp>~Uvj-Z8F)1D}-CnrCw2)q=F(`ZPgYc%>;ckww_;{^CmZx5*%ZCUUASZ0H8tyj z6*Na33Mb72OO_RKy>K?q22|-yws?gg>?sgngXa!&=9x0g*D6Y()r4@L_-@3H#-A*taj!nuBk7((@>hydS%YBi@yIhAf zdcpPv)6llN`6Q_`oqL~@o!eET_`VUQ~k~Zjeud2x#Svn z-J`}reiM+uajPYLE#3`}&`*B3pj2mdGil0#E-IC&c*jj`6A#xUvLRK@Ku_oY!OR_e zRm+txd(G^|%*iecN~@M>Wp|zsu;*V(po-ytW=3BzF&8~i(~@#YU%obp8W-QU`p|{q zvw_=(QS6vWE;x)JAyn{PzLJj-H>=-{-R!!o8v3(hINMKWv0`lbedBW;nKa)fe9!l* znKKT_J!jVtf`bZ|_mz@?^Z!dJ6tZD{PvAXYGgOzY{^)0jL1XR~j*uU3gp)-+^3VrX za-_*<<-r)jyqVlfJ&~a{E9-i1Ih8p^9u2shEEXGSD;TrB81CSnZ6)7x*KPu;MQ1MY z>0XSBaiQ`tqLVY&2B7Uh5SREVQ;3vlMdAzSPc76M<#Q#C#-pKQIfvprw{u z`>Cca#jANCqLp#q#HX(?(D&yr*8S(C!oG|Jbk$&Z@i)_;hQO0bNUb|-Arb}EirEJ?5B^ec?;)g8Yj+mb6MbKUtS-J$ceEeAE;xUviDPZSYgE1bi=VD;AjYe*jMIJOY!}~) zwW2nO8RLt^fnMiqMN%uv;#vMgquSo;2bsEL@vn?P^K+eokgHi2I>E9u{*-Wg^^pL# z-@aw8Pia#QAhSRZ8vGwTCDJ&PdI7)O;<-NY2KC`j_IF#s2&6xzqHpc70qsB?w1I@O zNjta9{;6m3`NtNJH#IeNdTL60Y;rQOxmn%+)~!=FZrtb?8hYH&(!wVoATa&w7a|9X zjUO1e;vW!jEG0Fyv%mkLiiQRs3k%D&s3@oJi;L1oDIu2MH`WGDE8!uc0)#DQ0NU99borzHGob&ipXPGnZ;FS!#k4 z$xQJBXQFbz{{VBpR49uc3EK z{+vnM_(u*hekQp@{g)~JpPTzv6O)sjBoYRNM)S+d%TI4_+i7TO#&>mHTK)H?L_=#U zKMV$&rcwMMV?t-aSy=-Y&nnxtXqz zo_zPW1=}48ZzvcN4L(>E_BS&BcxV2?LjUJW_xBE*9^Dvmr))U_`_&+W3nqFMI?i|g E2VaX_h5!Hn literal 0 HcmV?d00001 diff --git a/members/static/img/excel_csv_save_tutorial.PNG b/members/static/img/excel_csv_save_tutorial.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1cc02322f40fda289bf9ba4b97d21ad6f0fda652 GIT binary patch literal 5131 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 V3LnxvZlMfdb>8+I@+>&{zX0H+z`+0j literal 0 HcmV?d00001 diff --git a/members/templates/application_list.html b/members/templates/application_list.html index 0fee6ad..ae22bcf 100644 --- a/members/templates/application_list.html +++ b/members/templates/application_list.html @@ -15,6 +15,10 @@ {% endif %} {{ table|safe }} + + {% endblock content %} diff --git a/members/templates/member_add_many.html b/members/templates/member_add_many.html index 148b1b4..15a2c85 100644 --- a/members/templates/member_add_many.html +++ b/members/templates/member_add_many.html @@ -1,7 +1,7 @@ {% extends "members_base.html" %} {% load i18n %} - +{% load static %} {% block content %}
@@ -11,24 +11,28 @@

{% blocktrans %} - Enter member information in CSV format, separate members on separate lines. + Enter member information in CSV format, separate members on separate lines. + If a new member already exists in the database, a new payment event will be created for that member instead. {% endblocktrans %}

-

- {% blocktrans %} - first_name, last_name, email_address and place_of_origin should be given string values. - ayy_member and jas_recipient should be given the value 0 (off) or 1 (on). - {% endblocktrans %} -

-

{% trans "Syntax" %}

-
first_name, last_name, email_address, place_of_origin, ayy_member, jas_recipient
-
-
{% csrf_token %} -
- - + +
+ +
+
+

{% blocktrans %}Columns: First name, last name, email address, place of origin, AYY member, JAS recipient{% endblocktrans %}

+
+
+ +
+
+ + {% csrf_token %} +

{% trans "Upload file" %}

+ +
+ + {% trans "This payment source will be used to create any payments for new members that already exist in the database." %} +
-

+ {% blocktrans %}The symbol that is used to separate items in one line. Defaults to ';' (semicolon).{% endblocktrans %} -

+
diff --git a/members/templates/member_edit.html b/members/templates/member_edit.html index 4f2c7ea..c8ef05c 100644 --- a/members/templates/member_edit.html +++ b/members/templates/member_edit.html @@ -1,7 +1,7 @@ {% extends "members_base.html" %} {% load i18n %} -{% load bootstrap3 %} +{% load bootstrap4 %} {% block content %}
diff --git a/members/templates/member_list.html b/members/templates/member_list.html index 9c0eb80..2dc38f8 100644 --- a/members/templates/member_list.html +++ b/members/templates/member_list.html @@ -41,7 +41,7 @@ {{ table|safe }}
{% endblock content %} diff --git a/members/templates/payment_list.html b/members/templates/payment_list.html index 1665f0a..bce2421 100644 --- a/members/templates/payment_list.html +++ b/members/templates/payment_list.html @@ -36,5 +36,9 @@ {% endif %} {{ table|safe }} + +
{% endblock content %} diff --git a/members/templates/upload_form.html b/members/templates/upload_form.html new file mode 100644 index 0000000..b028b1d --- /dev/null +++ b/members/templates/upload_form.html @@ -0,0 +1,10 @@ +{% extends "members_base.html" %} + +{% block content %} +

{{ title }}

+

{{ header }}

+{% csrf_token %} + {{ form }} + + +{% endblock %} \ No newline at end of file diff --git a/members/urls.py b/members/urls.py index 4988f5d..707571e 100644 --- a/members/urls.py +++ b/members/urls.py @@ -7,7 +7,7 @@ from django.views.generic.base import RedirectView # members from members.views import member_list, payment_add, payment_submit from members.views import application_delete_confirm, application_delete -from members.views import application_accept, import_csv, export_csv +from members.views import application_accept, import_csv from members.views import settings_page, payment_edit from members.views import payment_delete_confirm from members.views import payment_delete, payment_update @@ -20,6 +20,9 @@ from members.views import member_delete_confirm from members.views import member_delete from members.views import payment_list from members.views import add_many_confirm +from members.views import export_members_excel +from members.views import export_payments_excel +from members.views import export_applications_excel # autocomplete view from members.views import MemberAutoComplete @@ -108,8 +111,10 @@ urlpatterns = [ # send CSV member data by POST url(r'^import_csv', import_csv), - # download CSV member data - url(r'^export_csv', export_csv), + # export members as excel file + url(r'export_members', export_members_excel), + url(r'export_payments', export_payments_excel), + url(r'export_applications', export_applications_excel), # favourite icon url(r'^favicon\.ico$', favicon_view), diff --git a/members/views/utils.py b/members/views/utils.py index 83727a6..6223cba 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -2,7 +2,7 @@ from django.shortcuts import render from django.contrib.auth.decorators import permission_required, login_required from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import ensure_csrf_cookie -from django.http import HttpResponse, HttpResponseRedirect +from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest from django.core.mail import send_mail from django.conf import settings from django.utils.translation import ugettext as _ @@ -20,8 +20,9 @@ from rest_framework import generics from rest_framework import permissions from members.models import Member, Request, Payment -from members.forms import MemberForm, PaymentForm, ApplicationForm, CSVValidationError +from members.forms import MemberForm, PaymentForm, ApplicationForm, CSVValidationError, UploadFileForm from members.tables import MemberTable, PaymentTable, RequestTable +from members.resources import MemberResource, PaymentResource, ApplicationResource # Can be used to retrieve single member information via REST API @@ -108,13 +109,16 @@ def settings_page(request, *args, **kwargs): def import_csv(request, *args, **kwargs): """Get csv data imported to page and create members based on that.""" try: - data = request.POST['textfield'] + csv_in_memory_file = request.FILES.get('csvFile') + csv_file = csv_in_memory_file.file + data = csv_file.read().decode('utf-8') + delimiter = request.POST.get('delimiter', ',') payment_source = request.POST['payment_source'] except: return render(request, 'error.html', - {'error': _('Missing "textfield" POST request field')}) + {'error': _('Missing CSV file')}) try: result = MemberForm.csv_to_models(data, payment_source=payment_source, delimiter=delimiter) @@ -149,27 +153,6 @@ def import_csv(request, *args, **kwargs): return render(request, 'member_add_many_confirm.html', context) -@ensure_csrf_cookie -@require_http_methods(["GET"]) -@permission_required('members.read_member', login_url='/login', raise_exception=True) -def export_csv(request, *args, **kwargs): - """Export members as csv.""" - response = HttpResponse() - response['Content-type'] = 'text/csv' - response['Accept'] = 'text/csv' - response['Content-Disposition'] = 'filename; filename=members.csv' - writer = csv.writer(response, csv.excel) - # BOM (optional...Excel needs it to open UTF-8 file properly) - response.write(u'\ufeff'.encode('utf8')) - for obj in Member.objects.all(): - data = obj.as_array() - field_list = list(map(lambda d: str(d), data)) - - writer.writerow(field_list) - - return response - - def send_mail_wrapper(subject, message, email_to): """Send mail to default email.""" send_mail(subject, @@ -177,3 +160,26 @@ def send_mail_wrapper(subject, message, email_to): settings.DEFAULT_EMAIL_FROM, [email_to], fail_silently=False) + + +def make_excel_response(Resource): + res = Resource() + dataset = res.export() + response = HttpResponse(dataset.xlsx, content_type='application/vnd.ms-excel; charset=utf-8') + response['Content-Disposition'] = 'attachment; filename="export.xlsx"' + return response + + +@require_http_methods(['GET']) +def export_members_excel(request, *args, **kwargs): + return make_excel_response(MemberResource) + + +@require_http_methods(['GET']) +def export_payments_excel(request, *args, **kwargs): + return make_excel_response(PaymentResource) + + +@require_http_methods(['GET']) +def export_applications_excel(request, *args, **kwargs): + return make_excel_response(ApplicationResource) diff --git a/requirements.txt b/requirements.txt index bc58902..925b4f7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,3 +30,5 @@ django-autocomplete-light==3.2.10 six==1.10.0 django-suit==0.2.25 telepot==12.3 +django-excel==0.0.9 +pyexcel-xls==0.5.2 \ No newline at end of file diff --git a/sikweb/base.py b/sikweb/base.py index c094344..b761136 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -82,11 +82,15 @@ INSTALLED_APPS = [ 'rest_framework', 'django_nose', 'bootstrap3', + 'bootstrap4', 'django_tables2', 'auditlog', 'phonenumber_field', + 'import_export', ] +IMPORT_EXPORT_USE_TRANSACTIONS = True + TEST_RUNNER = 'django_nose.NoseTestSuiteRunner' NOSE_ARGS = [ @@ -255,6 +259,10 @@ MEDIA_URL = '/media/' LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/admin' +# for django-excel +FILE_UPLOAD_HANDLERS = ("django_excel.ExcelMemoryFileUploadHandler", + "django_excel.TemporaryExcelFileUploadHandler") + SUIT_CONFIG = { # header 'ADMIN_NAME': 'SIK Admin', From 755abe5647d0a9ef4e1bf7568802366f1b821d5f Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Wed, 1 Nov 2017 13:17:31 +0200 Subject: [PATCH 2/7] Add missing pip dependency --- requirements.txt | 3 +-- sikweb/base.py | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 925b4f7..a725a9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -30,5 +30,4 @@ django-autocomplete-light==3.2.10 six==1.10.0 django-suit==0.2.25 telepot==12.3 -django-excel==0.0.9 -pyexcel-xls==0.5.2 \ No newline at end of file +django-import-export==0.5.1 \ No newline at end of file diff --git a/sikweb/base.py b/sikweb/base.py index b761136..5f30fb1 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -82,7 +82,6 @@ INSTALLED_APPS = [ 'rest_framework', 'django_nose', 'bootstrap3', - 'bootstrap4', 'django_tables2', 'auditlog', 'phonenumber_field', From b9e9cdb2b0bc2eb5b2cbd0dad932de9d46e6bd2f Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 2 Nov 2017 15:12:32 +0200 Subject: [PATCH 3/7] Add new payment event for new members --- members/templates/member_edit.html | 2 +- members/views/members.py | 4 ++++ members/views/utils.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/members/templates/member_edit.html b/members/templates/member_edit.html index c8ef05c..4f2c7ea 100644 --- a/members/templates/member_edit.html +++ b/members/templates/member_edit.html @@ -1,7 +1,7 @@ {% extends "members_base.html" %} {% load i18n %} -{% load bootstrap4 %} +{% load bootstrap3 %} {% block content %}
diff --git a/members/views/members.py b/members/views/members.py index eb2a3c4..ada6953 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -94,11 +94,15 @@ def member_add_many(request, *args, **kwargs): @permission_required('members.add_member', raise_exception=True) def add_many_confirm(request, *args, **kwargs): models = request.session['models'] + payment_source = request.session['payment_source'] try: members, payments = models.members, models.payments + for member in members: member.save() + if not member.payments.exists(): # create payment for new members + payment = Payment.objects.create(member=member, source=payment_source) for payment in payments: payment.save() diff --git a/members/views/utils.py b/members/views/utils.py index 6223cba..8b26496 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -146,6 +146,7 @@ def import_csv(request, *args, **kwargs): payment_table_html = convert_table_to_html(payment_table, request) request.session['models'] = result + request.session['payment_source'] = payment_source context = { 'members': member_table_html, 'payments': payment_table_html From cf33d81d6953c3973ae3a6ef9ad3341a5c2b22f9 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 2 Nov 2017 22:56:34 +0200 Subject: [PATCH 4/7] Write some unit tests for excel stuff --- members/test_resources/multi_line_import.csv | 3 + members/test_resources/single_line_import.csv | 1 + members/tests.py | 80 +++++++++++++++++-- members/views/applications.py | 37 +++------ members/views/members.py | 25 ++---- members/views/payments.py | 23 ++---- members/views/utils.py | 10 +-- 7 files changed, 107 insertions(+), 72 deletions(-) create mode 100644 members/test_resources/multi_line_import.csv create mode 100644 members/test_resources/single_line_import.csv diff --git a/members/test_resources/multi_line_import.csv b/members/test_resources/multi_line_import.csv new file mode 100644 index 0000000..3974655 --- /dev/null +++ b/members/test_resources/multi_line_import.csv @@ -0,0 +1,3 @@ +Testi;Ukkeli;testi@ukkeli.fi;Espoo;1;0 +Jäbä;Kakkeli;jaba@kakkeli.fi;Hamina;0;1 +Kolmas;Kaveri;kolmas@kaveri.com;Mesta;1;1 \ No newline at end of file diff --git a/members/test_resources/single_line_import.csv b/members/test_resources/single_line_import.csv new file mode 100644 index 0000000..1a65674 --- /dev/null +++ b/members/test_resources/single_line_import.csv @@ -0,0 +1 @@ +Testi;Ukkeli;testi@ukkeli.fi;Espoo;1;0 \ No newline at end of file diff --git a/members/tests.py b/members/tests.py index 622fbf6..645a1ee 100644 --- a/members/tests.py +++ b/members/tests.py @@ -3,10 +3,12 @@ from django.test import TestCase, Client from django.contrib.auth.models import User from members.management.commands.createsahkopiikkiuser import Command as SahkopiikkiCommand -from members.models import Member +from members.models import Member, Payment, Request from rest_framework.authtoken.models import Token import logging +import os +import pyexcel class MemberRegisterTestCase(TestCase): @@ -14,7 +16,13 @@ class MemberRegisterTestCase(TestCase): def setUp(self): """Setup testing environment by creating member and admin.""" - memb = Member.objects.create(first_name="Tidus", last_name="Tester") + memb = Member.objects.create(first_name="Tidus", last_name="Tester", email="tidus@tester.fi") + payment = Payment.objects.create(member=memb, source='AYY') + appl = Request.objects.create( + first_name="Liisa", last_name="Mattila", + email="liisa.mattila@pylly.com", POR="Kouvola", + AYY=True, jas=False) + username, password = 'test_admin', 'password123' test_admin = User.objects.create_superuser( username, 'myemail@test.com', password) @@ -31,16 +39,27 @@ class MemberRegisterTestCase(TestCase): def test_import_csv_single_line(self): """Test csv import only with single line in csv file.""" - data = 'Teppo, Tulppu, teppo@tulppu.fi, Ankkalinna, 0, 0' - response = self.c.post('/members/import_csv', {'textarea': data}, follow=True) + + current_dir = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(current_dir, 'test_resources', 'single_line_import.csv')) as csvFile: + response = self.c.post('/members/import_csv', { + 'csvFile': csvFile, + 'delimiter': ';', + 'payment_source': 'AYY' + }, follow=True) self.assertEqual(response.status_code, 200) def test_import_csv_multi_line(self): """Test csv import with multilined csv.""" - data = ('Teppo, Tulppu, teppo@tulppu.fi, Ankkalinna, 0, 0\n' - 'Reiska, Remontti, remontti@reiska.fi, Värisilmä, 1, 1') - response = self.c.post('/members/import_csv', {'textarea': data}, follow=True) + current_dir = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(current_dir, 'test_resources', 'multi_line_import.csv')) as csvFile: + response = self.c.post('/members/import_csv', { + 'csvFile': csvFile, + 'delimiter': ';', + 'payment_source': 'AYY' + }, follow=True) + self.assertEqual(response.status_code, 200) def test_autocomplete_search_found(self): @@ -87,3 +106,50 @@ class MemberRegisterTestCase(TestCase): response = self.c.get('/members/check?email={}'.format(email), follow=True) self.assertEqual(response.status_code, 401) + + def test_export_members_excel(self): + """Test if the user can download an excel file of the member register""" + resp = self.c.get('/members/export_members') + content_type = 'application/vnd.ms-excel' + self.assertIn(content_type, resp['Content-Type']) + + content = resp.content + arrays = pyexcel.get_array(file_content=content, file_type='xlsx') + tidus_array = ['Tidus', 'Tester', 'tidus@tester.fi', '', '0', '0'] + self.assertIn(tidus_array, arrays) + + def test_export_payments_excel(self): + """Test if the user can download an excel file of the payment register""" + resp = self.c.get('/members/export_payments') + content_type = 'application/vnd.ms-excel' + self.assertIn(content_type, resp['Content-Type']) + + content = resp.content + arrays = pyexcel.get_array(file_content=content, file_type='xlsx') + created = Payment.objects.get(member__email='tidus@tester.fi').date.strftime('%Y-%m-%d %H:%M:%S') + tidus_array = ['Tidus Tester', created, 'AYY'] + self.assertIn(tidus_array, arrays) + + def test_export_applications_excel(self): + """Test if the user can download an excel file of the member application register""" + resp = self.c.get('/members/export_applications') + content_type = 'application/vnd.ms-excel' + self.assertIn(content_type, resp['Content-Type']) + + content = resp.content + arrays = pyexcel.get_array(file_content=content, file_type='xlsx') + submitted = Request.objects.get(email='liisa.mattila@pylly.com').submitted.strftime('%Y-%m-%d %H:%M:%S') + liisa_array = ['Liisa', 'Mattila', 'liisa.mattila@pylly.com', 'Kouvola', '1', '0', submitted] + self.assertIn(liisa_array, arrays) + + def test_submit_member_application(self): + """Test if submitting a member application works""" + data = { + 'first_name': 'Seppo', 'last_name': 'Saastamoinen', + 'email': 'seppo@saastamoin.en', 'jas': 'on', + 'POR': 'Dipolin viinibaari' + } + resp = self.c.post('/members/submit_application', data=data) + self.assertEqual(resp.status_code, 200) + + self.assertTrue(Request.objects.filter(email='seppo@saastamoin.en').exists()) diff --git a/members/views/applications.py b/members/views/applications.py index 3fb0cef..f1b5321 100644 --- a/members/views/applications.py +++ b/members/views/applications.py @@ -14,6 +14,7 @@ import html from members.views.utils import * from members.tables import RequestTable from members.forms import ApplicationForm +from members.views import error_view @ensure_csrf_cookie @@ -47,8 +48,7 @@ def application_edit(request, *args, **kwargs): """Edit member request information.""" i = kwargs.pop('index', None) if i is None: - return render( - request, 'error.html', {'error': _('No application id specified')}) + return error_view(request, _('No application id specified')) else: application = Request.objects.get(id=i) form = ApplicationForm(instance=application) @@ -68,9 +68,7 @@ def application_accept(request, *args, **kwargs): if id is not None: application = Request.objects.get(id=id) else: - return render(request, - 'error.html', - {'error': _("Application missing 'id' field.")}) + return error_view(request, _("Application missing 'id' field.")) form = ApplicationForm(request.POST, instance=application) if form.is_valid(): @@ -78,9 +76,9 @@ def application_accept(request, *args, **kwargs): application = form.save() if Member.objects.filter(email=application.email).exists(): - return render(request, - 'error.html', - {'error': _('Email {} is already in use by a member. Application cannot be accepted.').format(application.email)}) + return error_view(request, _( + 'Email {} is already in use by a member. Application cannot be accepted.' + ).format(application.email)) member = application.to_member() member.save() @@ -96,14 +94,10 @@ def application_accept(request, *args, **kwargs): '/members/list?notification={}'.format(html.escape(notification))) except Exception as ex: logging.exception('Exception while accepting application') - return render(request, - 'error.html', - {'error': str(ex)}) + return error_view(request, str(ex)) else: logging.info(form) - return render(request, - 'error.html', - {'error': form.errors}) + return error_view(request, form.errors) @ensure_csrf_cookie @@ -115,8 +109,7 @@ def application_delete(request, *args, **kwargs): try: id = request.POST['id'] except KeyError: - return render( - request, 'error.html', {'error': _('No application id specified')}) + return error_view(request, _('No application id specified')) try: application = Request.objects.get(id=id) @@ -130,9 +123,7 @@ def application_delete(request, *args, **kwargs): '/members/applications?notification={}' .format(html.escape(notification))) except: - return render(request, - 'error.html', - {'error': _('Could not delete application object')}) + return error_view(request, _('Could not delete application object')) @ensure_csrf_cookie @@ -143,9 +134,7 @@ def application_delete_confirm(request, *args, **kwargs): """Confirm application deletion.""" i = kwargs.pop('index', None) if i is None: - return render(request, - 'error.html', - {'error': _('No application id specified')}) + return error_view(request, _('No application id specified')) else: application = Request.objects.get(id=i) form = ApplicationForm(instance=application) @@ -172,6 +161,4 @@ def application_submit(request, *args, **kwargs): form.save() return render(request, 'application_success.html', {}) else: - return render(request, - 'error.html', - {'error': form.errors}) + return error_view(request, form.errors) diff --git a/members/views/members.py b/members/views/members.py index ada6953..4ae9a6b 100644 --- a/members/views/members.py +++ b/members/views/members.py @@ -70,8 +70,7 @@ def member_delete_confirm(request, *args, **kwargs): """Render member deletion confirmation page.""" i = kwargs.pop('index', None) if i is None: - return render(request, 'error.html', - {'error': _('No member id specified')}) + return error_view(request, _('No member id specified')) else: member = Member.objects.get(id=i) form = MemberForm(instance=member) @@ -133,7 +132,7 @@ def member_submit(request, *args, **kwargs): return HttpResponseRedirect( '/members/list?notification={}'.format(html.escape(notification))) else: - return render(request, 'error.html', {'error': form.errors}) + return error_view(request, form.errors) @ensure_csrf_cookie @@ -147,10 +146,7 @@ def member_update(request, *args, **kwargs): if id is not None: member = Member.objects.get(id=id) else: - return render(request, - 'error.html', - {'error': _("Member missing 'id' field.")}) - logging.debug(member) + return error_view(request, _("Member missing 'id' field.")) form = MemberForm(request.POST, instance=member) if form.is_valid(): @@ -164,10 +160,7 @@ def member_update(request, *args, **kwargs): return HttpResponseRedirect( '/members/list?notification={}'.format(html.escape(notification))) else: - return render( - request, - 'error.html', - {'error': form.errors}) + return error_view(request, form.errors) @ensure_csrf_cookie @@ -179,8 +172,7 @@ def member_delete(request, *args, **kwargs): try: id = request.POST['id'] except KeyError: - return render(request, - 'error.html', {'error': _('No member id specified')}) + return error_view(request, _('No member id specified')) try: member = Member.objects.get(id=id) @@ -193,9 +185,7 @@ def member_delete(request, *args, **kwargs): return HttpResponseRedirect( '/members/list?notification={}'.format(html.escape(notification))) except: - return render(request, - 'error.html', - {'error': _('Could not delete member object')}) + return error_view(request, _('Could not delete member object')) @ensure_csrf_cookie @@ -206,8 +196,7 @@ def member_edit(request, *args, **kwargs): """Edit member information.""" i = kwargs.pop('index', None) if i is None: - return render( - request, 'error.html', {'error': _('No member id specified')}) + return error_view(request, _('No member id specified')) else: member = Member.objects.get(id=i) form = MemberForm(instance=member) diff --git a/members/views/payments.py b/members/views/payments.py index 4c9a587..11db4db 100644 --- a/members/views/payments.py +++ b/members/views/payments.py @@ -14,6 +14,7 @@ import html from members.views.utils import * from members.tables import PaymentTable from members.forms import PaymentForm +from members.views import error_view @ensure_csrf_cookie @@ -73,7 +74,7 @@ def payment_submit(request, *args, **kwargs): '/members/payments?notification={}' .format(html.escape(notification))) else: - return render(request, 'error.html', {'error': form.errors}) + return error_view(request, form.errors) @ensure_csrf_cookie @@ -84,9 +85,7 @@ def payment_edit(request, *args, **kwargs): """Edit payment.""" i = kwargs.pop('index', None) if i is None: - return render(request, - 'error.html', - {'error': _('No payment id specified')}) + return error_view(request, _('No payment id specified')) else: payment = Payment.objects.get(id=i) form = PaymentForm(instance=payment) @@ -103,9 +102,7 @@ def payment_delete_confirm(request, *args, **kwargs): """Render payment delete confirmation page.""" i = kwargs.pop('index', None) if i is None: - return render(request, - 'error.html', - {'error': _('No payment id specified')}) + return error_view(request, _('No payment id specified')) else: payment = Payment.objects.get(id=i) form = PaymentForm(instance=payment) @@ -123,9 +120,7 @@ def payment_delete(request, *args, **kwargs): try: id = request.POST['id'] except KeyError: - return render(request, - 'error.html', - {'error': _('No payment id specified')}) + return error_view(request, _('No payment id specified')) try: payment = Payment.objects.get(id=id) @@ -138,9 +133,7 @@ def payment_delete(request, *args, **kwargs): '/members/payments?notification={}' .format(html.escape(notification))) except: - return render(request, - 'error.html', - {'error': _('Could not delete payment object')}) + return error_view(request, _('Could not delete payment object')) @ensure_csrf_cookie @@ -165,6 +158,4 @@ def payment_update(request, *args, **kwargs): '/members/payments?notification={}' .format(html.escape(notification))) else: - return render(request, - 'error.html', - {'error': _('Could not update payment object')}) + return error_view(request, _('Could not update payment object')) diff --git a/members/views/utils.py b/members/views/utils.py index 8b26496..773be1d 100644 --- a/members/views/utils.py +++ b/members/views/utils.py @@ -35,8 +35,8 @@ class MemberDetail(generics.RetrieveAPIView): throttle_classes = (BurstRateThrottle, SustainedRateThrottle, ) -def error_view(request, message): - return render(request, 'error.html', {'error': str(message)}) +def error_view(request, message, status=400): + return render(request, 'error.html', {'error': message}, status=400) def validate_recaptcha(response): @@ -116,9 +116,7 @@ def import_csv(request, *args, **kwargs): delimiter = request.POST.get('delimiter', ',') payment_source = request.POST['payment_source'] except: - return render(request, - 'error.html', - {'error': _('Missing CSV file')}) + return error_view(request, _('Missing CSV file')) try: result = MemberForm.csv_to_models(data, payment_source=payment_source, delimiter=delimiter) @@ -127,7 +125,7 @@ def import_csv(request, *args, **kwargs): return error_view(request, ex.form_errors) except Exception as ex: logging.exception('Other error in CSV import') - return error_view(request, ex) + return error_view(request, str(ex)) member_table = MemberTable(result.members, request=request, From 1fdc9e9ff82b94f3dee278f6538ccb3a1d29cbd9 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 2 Nov 2017 23:10:24 +0200 Subject: [PATCH 5/7] Write translations --- locale/en/LC_MESSAGES/django.mo | Bin 9233 -> 14081 bytes locale/en/LC_MESSAGES/django.po | 328 ++++++++++++++++++-------------- locale/fi/LC_MESSAGES/django.mo | Bin 15384 -> 16441 bytes locale/fi/LC_MESSAGES/django.po | 184 +++++++++++------- 4 files changed, 299 insertions(+), 213 deletions(-) diff --git a/locale/en/LC_MESSAGES/django.mo b/locale/en/LC_MESSAGES/django.mo index b66103652d23e13da5c789937e3b71d41081e22e..3d5c60e2b5395b92df6a0f47d5d9506f2a7cee34 100644 GIT binary patch literal 14081 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 literal 9233 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, YEAR. # -#, fuzzy msgid "" msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" +"Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-10-31 21:09+0100\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" +"POT-Creation-Date: 2017-11-02 21:59+0100\n" +"PO-Revision-Date: 2017-11-02 23:09+0200\n" +"Language: en\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Last-Translator: \n" +"Language-Team: \n" +"X-Generator: Poedit 2.0.4\n" #: .\infoscreen\models.py:97 msgid "ABB jobs" @@ -177,11 +177,11 @@ msgstr "Member" #: .\members\forms.py:123 msgid "I'm a member of AYY" -msgstr "" +msgstr "I'm a member of AYY" #: .\members\forms.py:124 msgid "I want to receive a weekly newsletter" -msgstr "" +msgstr "I want to receive a weekly newsletter" #: .\members\models.py:14 msgid "First name" @@ -235,7 +235,6 @@ msgstr "Created" #: .\members\models.py:104 .\members\templates\member_add_many_confirm.html:12 #: .\members\templates\members_base.html:52 -#: .\webapp\templates\main_index.html:7 msgid "Members" msgstr "Members" @@ -248,10 +247,8 @@ msgid "Edit" msgstr "Edit" #: .\members\templates\application_delete_confirm.html:9 -#, fuzzy -#| msgid "Are you sure you want to delete this payment?" msgid "Are you sure you want to delete this application?" -msgstr "Are you sure you want to delete this payment?" +msgstr "Are you sure you want to delete this application?" #: .\members\templates\application_delete_confirm.html:19 #: .\members\templates\member_delete_confirm.html:19 @@ -286,6 +283,7 @@ msgstr "Don't forget to pay your membership fee!" #: .\members\templates\application_index.html:16 #: .\members\templates\member_add_many.html:55 #: .\members\templates\member_add_many_confirm.html:22 +#: .\templates\password_reset\recovery_form.html:10 #: .\webapp\templates\kaehmy_list.html:48 msgid "Send" msgstr "Send" @@ -294,6 +292,12 @@ msgstr "Send" msgid "Member applications" msgstr "Member applications" +#: .\members\templates\application_list.html:20 +#: .\members\templates\member_list.html:44 +#: .\members\templates\payment_list.html:41 +msgid "Download Excel" +msgstr "Download Excel" + #: .\members\templates\application_success.html:8 msgid "Hienoa! Jäsenhakemuksesi on nyt lähetetty." msgstr "Amazing! Your membership application has been sent." @@ -316,7 +320,7 @@ msgstr "Save" #: .\members\templates\member_add_many.html:8 msgid "Add many members" -msgstr "" +msgstr "Add many members" #: .\members\templates\member_add_many.html:13 msgid "" @@ -327,52 +331,64 @@ msgid "" "event will be created for that member instead.\n" " " msgstr "" +"\n" +" Enter member information in CSV format, separate members on " +"separate lines. \n" +" If a new member already exists in the database, a new payment " +"event will be created for that member instead.\n" +" " #: .\members\templates\member_add_many.html:21 msgid "Format the member table like this:" -msgstr "" +msgstr "Format the member table like this:" #: .\members\templates\member_add_many.html:25 msgid "" "Columns: First name, last name, email address, place of origin, AYY member, " "JAS recipient" msgstr "" +"Columns: First name, last name, email address, place of origin, AYY member, " +"JAS recipient" #: .\members\templates\member_add_many.html:28 msgid "Save the file as CSV" -msgstr "" +msgstr "Save the file as CSV" #: .\members\templates\member_add_many.html:33 msgid "Upload file" -msgstr "" +msgstr "Upload file" #: .\members\templates\member_add_many.html:37 msgid "Payment source" -msgstr "" +msgstr "Payment source" #: .\members\templates\member_add_many.html:41 msgid "Cash payment" -msgstr "" +msgstr "Cash payment" #: .\members\templates\member_add_many.html:44 msgid "" "This payment source will be used to create any payments for new members that " "already exist in the database." msgstr "" +"This payment source will be used to create any payments for new members that " +"already exist in the database." #: .\members\templates\member_add_many.html:48 msgid "CSV delimiter" -msgstr "" +msgstr "CSV delimiter" #: .\members\templates\member_add_many.html:51 msgid "" "The symbol that is used to separate items in one line. Defaults to " "';' (semicolon)." msgstr "" +"The symbol that is used to separate items in one line. Defaults to " +"';' (semicolon)." #: .\members\templates\member_add_many_confirm.html:8 msgid "Confirm adding these entries?" -msgstr "" +msgstr "Confirm adding these entries?" #: .\members\templates\member_add_many_confirm.html:16 #: .\members\templates\members_base.html:60 @@ -394,21 +410,17 @@ msgstr "Member register" #: .\members\templates\member_list.html:21 msgid "Members in register:" -msgstr "" +msgstr "Members in register:" #: .\members\templates\member_list.html:28 #: .\members\templates\payment_list.html:25 msgid "Search" -msgstr "" +msgstr "Search" #: .\members\templates\member_list.html:36 #: .\members\templates\payment_list.html:33 msgid "Showing results for" -msgstr "" - -#: .\members\templates\member_list.html:44 -msgid "Download CSV" -msgstr "Download CSV" +msgstr "Showing results for" #: .\members\templates\members_base.html:33 #: .\members\templates\members_base.html:42 @@ -462,10 +474,8 @@ msgid "Payment events" msgstr "Payment events" #: .\members\templates\payment_list.html:18 -#, fuzzy -#| msgid "Member register" msgid "Payments in register:" -msgstr "Member register" +msgstr "Payments in register:" #: .\members\templates\settings.html:17 msgid "Language" @@ -483,92 +493,98 @@ msgstr "English" msgid "Submit" msgstr "Submit" -#: .\members\views\applications.py:51 .\members\views\applications.py:119 -#: .\members\views\applications.py:148 +#: .\members\views\applications.py:51 .\members\views\applications.py:112 +#: .\members\views\applications.py:137 msgid "No application id specified" msgstr "No application id specified" -#: .\members\views\applications.py:73 +#: .\members\views\applications.py:71 msgid "Application missing 'id' field." -msgstr "" +msgstr "Application missing 'id' field." -#: .\members\views\applications.py:83 +#: .\members\views\applications.py:80 msgid "Email {} is already in use by a member. Application cannot be accepted." msgstr "" +"Email {} is already in use by a member. Application cannot be accepted." -#: .\members\views\applications.py:93 +#: .\members\views\applications.py:91 msgid "Successfully accepted application" msgstr "Successfully accepted application" -#: .\members\views\applications.py:123 +#: .\members\views\applications.py:116 msgid "Successfully deleted application" msgstr "Successfully deleted application" -#: .\members\views\applications.py:135 +#: .\members\views\applications.py:126 msgid "Could not delete application object" msgstr "Could not delete application object" -#: .\members\views\members.py:74 .\members\views\members.py:179 -#: .\members\views\members.py:206 +#: .\members\views\members.py:73 .\members\views\members.py:175 +#: .\members\views\members.py:199 msgid "No member id specified" msgstr "No member id specified" -#: .\members\views\members.py:111 +#: .\members\views\members.py:114 msgid "Failed to import members" msgstr "Failed to import members" -#: .\members\views\members.py:125 +#: .\members\views\members.py:128 msgid "Successfully added member" msgstr "Successfully added member" -#: .\members\views\members.py:148 +#: .\members\views\members.py:149 msgid "Member missing 'id' field." -msgstr "" +msgstr "Member missing 'id' field." #: .\members\views\members.py:158 msgid "Successfully updated member" msgstr "Successfully updated member" -#: .\members\views\members.py:183 +#: .\members\views\members.py:179 msgid "Successfully deleted member" msgstr "Successfully deleted member" -#: .\members\views\members.py:194 +#: .\members\views\members.py:188 msgid "Could not delete member object" msgstr "Could not delete member object" -#: .\members\views\payments.py:70 +#: .\members\views\payments.py:71 msgid "Successfully added payment for member" msgstr "Successfully added payment for member" -#: .\members\views\payments.py:89 .\members\views\payments.py:108 -#: .\members\views\payments.py:128 +#: .\members\views\payments.py:88 .\members\views\payments.py:105 +#: .\members\views\payments.py:123 msgid "No payment id specified" msgstr "No payment id specified" -#: .\members\views\payments.py:133 +#: .\members\views\payments.py:128 msgid "Successfully deleted payment" msgstr "Successfully deleted payment" -#: .\members\views\payments.py:143 +#: .\members\views\payments.py:136 msgid "Could not delete payment object" msgstr "Could not delete payment object" -#: .\members\views\payments.py:163 +#: .\members\views\payments.py:156 msgid "Successfully updated payment" msgstr "Successfully updated payment" -#: .\members\views\payments.py:170 +#: .\members\views\payments.py:161 msgid "Could not update payment object" msgstr "Could not update payment object" -#: .\members\views\utils.py:121 +#: .\members\views\utils.py:119 msgid "Missing CSV file" -msgstr "" +msgstr "Missing CSV file" #: .\templates\admin\base_site.html:43 msgid "Go" -msgstr "" +msgstr "Go" + +#: .\templates\base.html:14 .\webapp\templates\kaehmy_base.html:14 +#: .\webapp\templates\main_index.html:9 +msgid "Aalto-yliopiston Sähköinsinöörikilta ry" +msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" #: .\templates\error.html:8 .\webapp\templates\kaehmy_error.html:8 msgid "Error" @@ -578,53 +594,117 @@ msgstr "Error" msgid "Back" msgstr "Back" -#: .\templates\footer.html:23 .\webapp\templates\kaehmy_footer.html:23 +#: .\templates\footer.html:10 .\templates\footer.html:60 +#: .\webapp\templates\kaehmy_footer.html:23 msgid "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" msgstr "Copyright Aalto-yliopiston Sähköinsinöörikilta ry" +#: .\templates\login.html:12 .\templates\login.html:13 +msgid "Username" +msgstr "Username" + +#: .\templates\login.html:16 .\templates\login.html:17 +msgid "Password" +msgstr "Password" + +#: .\templates\login.html:20 +msgid "Forgot password?" +msgstr "Forgot password?" + +#: .\templates\login.html:26 +msgid "Log in" +msgstr "Log in" + +#: .\templates\password_reset\recovery_done.html:3 +msgid "New password set" +msgstr "New password set" + +#: .\templates\password_reset\recovery_done.html:6 +msgid "" +"Your password has successfully been reset. You can use it right now on the " +"login page." +msgstr "" +"Your password has successfully been reset. You can use it right now on the " +"login page." + +#: .\templates\password_reset\recovery_form.html:4 +msgid "Password recovery" +msgstr "Password recovery" + +#: .\templates\password_reset\reset.html:5 +#, python-format +msgid "" +"Sorry, this password reset link is invalid. You can still request a new one." +msgstr "" +"Sorry, this password reset link is invalid. You can still request a new one." + +#: .\templates\password_reset\reset.html:7 +#, python-format +msgid "Hi, %(username)s. Please choose your new password." +msgstr "Hi, %(username)s. Please choose your new password." + +#: .\templates\password_reset\reset.html:11 +msgid "Set new password" +msgstr "Set new password" + +#: .\templates\password_reset\reset_sent.html:4 +msgid "Password recovery sent" +msgstr "Password recovery sent" + +#: .\templates\password_reset\reset_sent.html:7 +#, python-format +msgid "" +"An email was sent to %(email)s %(ago)s ago. Use the link in " +"it to set a new password." +msgstr "" +"An email was sent to %(email)s %(ago)s ago. Use the link in " +"it to set a new password." + #: .\webapp\forms.py:38 msgid "Email (not public)" -msgstr "" +msgstr "Email (not public)" #: .\webapp\forms.py:39 msgid "Phone number (not public)" -msgstr "" +msgstr "Phone number (not public)" #: .\webapp\forms.py:44 msgid "Custom roles" -msgstr "" +msgstr "Custom roles" #: .\webapp\forms.py:52 .\webapp\templates\kaehmy.html:41 msgid "Preset roles" -msgstr "" +msgstr "Preset roles" #: .\webapp\forms.py:76 msgid "Invalid phone number" -msgstr "" +msgstr "Invalid phone number" #: .\webapp\forms.py:84 msgid "Custom role with the same name already exists." -msgstr "" +msgstr "Custom role with the same name already exists." #: .\webapp\models.py:17 msgid "Webapp" -msgstr "" +msgstr "Webapp" #: .\webapp\models.py:28 msgid "Tag" -msgstr "" +msgstr "Tag" #: .\webapp\models.py:29 msgid "Tags" -msgstr "" +msgstr "Tags" #: .\webapp\models.py:32 msgid "Tag: {}" -msgstr "" +msgstr "Tag: {}" #: .\webapp\models.py:52 msgid "Feed: {}" -msgstr "" +msgstr "Feed: {}" #: .\webapp\models.py:55 msgid "Feed" @@ -658,13 +738,13 @@ msgstr "" msgid "Corporate affairs" msgstr "" -#: .\webapp\models.py:95 .\webapp\templates\freshmen.html:7 -#: .\webapp\templates\navigation.html:10 +#: .\webapp\models.py:95 .\webapp\templates\freshmen.html:10 +#: .\webapp\templates\navigation.html:9 msgid "Freshmen" msgstr "Freshmen" -#: .\webapp\models.py:96 .\webapp\templates\international.html:7 -#: .\webapp\templates\navigation.html:16 +#: .\webapp\models.py:96 .\webapp\templates\international.html:10 +#: .\webapp\templates\navigation.html:15 msgid "International" msgstr "International" @@ -701,66 +781,48 @@ msgid "Studies" msgstr "" #: .\webapp\models.py:105 -#, fuzzy -#| msgid "Sössö articles" msgid "Sössö magazine" -msgstr "Sössö articles" +msgstr "Sössö magazine" #: .\webapp\models.py:106 -#, fuzzy -#| msgid "Applications" msgid "Alumni relations" -msgstr "Applications" +msgstr "Alumni relations" #: .\webapp\models.py:107 msgid "Others" msgstr "" #: .\webapp\models.py:111 .\webapp\models.py:191 -#, fuzzy -#| msgid "Add member" msgid "Board member" -msgstr "Add member" +msgstr "Board member" #: .\webapp\models.py:112 msgid "Category" msgstr "" #: .\webapp\models.py:116 -#, fuzzy -#| msgid "Add member" msgid "board member" -msgstr "Add member" +msgstr "board member" #: .\webapp\models.py:122 -#, fuzzy -#| msgid "Duration" msgid "Description" -msgstr "Duration" +msgstr "Description" #: .\webapp\models.py:129 -#, fuzzy -#| msgid "Total challenges:" msgid "Preset kaehmy role" -msgstr "Total challenges:" +msgstr "Preset kaehmy role" #: .\webapp\models.py:130 -#, fuzzy -#| msgid "Total challenges:" msgid "Preset kaehmy roles" -msgstr "Total challenges:" +msgstr "Preset kaehmy roles" #: .\webapp\models.py:137 -#, fuzzy -#| msgid "Total challenges:" msgid "Custom kaehmy role" -msgstr "Total challenges:" +msgstr "Custom kaehmy role" #: .\webapp\models.py:138 -#, fuzzy -#| msgid "Total challenges:" msgid "Custom kaehmy roles" -msgstr "Total challenges:" +msgstr "Custom kaehmy roles" #: .\webapp\models.py:145 msgid "Timestamp" @@ -803,10 +865,8 @@ msgid "Custom role name" msgstr "" #: .\webapp\models.py:199 -#, fuzzy -#| msgid "Member applications" msgid "Kaehmy application: {}" -msgstr "Member applications" +msgstr "Kaehmy application: {}" #: .\webapp\models.py:221 msgid "Board: {}" @@ -852,24 +912,20 @@ msgstr "" msgid "SIK Admin" msgstr "SIK Admin" -#: .\webapp\templates\base.html:15 .\webapp\templates\kaehmy_base.html:14 -msgid "Aalto-yliopiston Sähköinsinöörikilta ry" -msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" - -#: .\webapp\templates\contact.html:7 .\webapp\templates\navigation.html:22 +#: .\webapp\templates\contact.html:10 .\webapp\templates\navigation.html:21 msgid "Contact" msgstr "Contact" -#: .\webapp\templates\event_calendar.html:7 -#: .\webapp\templates\navigation.html:13 +#: .\webapp\templates\event_calendar.html:10 +#: .\webapp\templates\navigation.html:12 msgid "Event calendar" msgstr "Event calendar" -#: .\webapp\templates\guild.html:7 +#: .\webapp\templates\guild.html:10 msgid "Kilta" msgstr "Guild" -#: .\webapp\templates\jobs.html:7 .\webapp\templates\navigation.html:29 +#: .\webapp\templates\jobs.html:10 .\webapp\templates\navigation.html:28 msgid "Jobs" msgstr "Jobs" @@ -931,22 +987,16 @@ msgid "Vaalikokous, osa 3 (toimarien valinta)" msgstr "Election meeting, part 3 (non-board election)" #: .\webapp\templates\kaehmy_export.html:9 -#, fuzzy -#| msgid "Applications" msgid "All applications" -msgstr "Applications" +msgstr "All applications" #: .\webapp\templates\kaehmy_export.html:13 -#, fuzzy -#| msgid "Applications" msgid "Board applications" -msgstr "Applications" +msgstr "Board applications" #: .\webapp\templates\kaehmy_export.html:18 -#, fuzzy -#| msgid "Member applications" msgid "Non-board applications" -msgstr "Member applications" +msgstr "Non-board applications" #: .\webapp\templates\kaehmy_export.html:23 msgid "Front page" @@ -966,10 +1016,8 @@ msgid "Comment" msgstr "" #: .\webapp\templates\kaehmy_list.html:57 -#, fuzzy -#| msgid "List kaehmys" msgid "Filter kaehmys" -msgstr "List applications" +msgstr "Filter kaehmys" #: .\webapp\templates\kaehmy_list.html:70 #: .\webapp\templates\kaehmy_statistics.html:18 @@ -1001,35 +1049,15 @@ msgstr "New application" msgid "Statistics" msgstr "" -#: .\webapp\templates\login.html:25 .\webapp\templates\login.html:27 -msgid "Username" -msgstr "Username" - -#: .\webapp\templates\login.html:31 .\webapp\templates\login.html:33 -msgid "Password" -msgstr "Password" - -#: .\webapp\templates\login.html:43 -msgid "Log in" -msgstr "Log in" - -#: .\webapp\templates\main_index.html:8 -msgid "Infoscreen" -msgstr "Infoscreen" - -#: .\webapp\templates\main_index.html:9 -msgid "Admin tools" -msgstr "Admin tools" - -#: .\webapp\templates\navigation.html:7 +#: .\webapp\templates\navigation.html:6 msgid "Guild" msgstr "Guild" -#: .\webapp\templates\navigation.html:19 .\webapp\templates\sosso.html:7 +#: .\webapp\templates\navigation.html:18 .\webapp\templates\sosso.html:10 msgid "Sössö" msgstr "Sössö" -#: .\webapp\templates\navigation.html:26 +#: .\webapp\templates\navigation.html:25 msgid "Corporate" msgstr "Corporate" @@ -1049,6 +1077,12 @@ msgstr "All challenges" msgid "Total challenges:" msgstr "Total challenges:" +#~ msgid "Infoscreen" +#~ msgstr "Infoscreen" + +#~ msgid "Admin tools" +#~ msgstr "Admin tools" + #~ msgid "" #~ "\n" #~ " first_name, last_name, email_address and place_of_origin " diff --git a/locale/fi/LC_MESSAGES/django.mo b/locale/fi/LC_MESSAGES/django.mo index 9b35184b851d2ef78884cdbada802a4a676b5b67..e776cb028b1d6ec041e7ef12bd729270ab10fcaf 100644 GIT binary patch delta 6309 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 a new one." +msgstr "" +"Pahoittelut, tämä salasanan palautuslinkki on epäkelpo. Voit kuitenkin hankkia uuden." + +#: .\templates\password_reset\reset.html:7 +#, python-format +msgid "Hi, %(username)s. Please choose your new password." +msgstr "Hei, %(username)s. Valitse uusi salasanasi." + +#: .\templates\password_reset\reset.html:11 +msgid "Set new password" +msgstr "Aseta uusi salasana" + +#: .\templates\password_reset\reset_sent.html:4 +msgid "Password recovery sent" +msgstr "Salasanan palautusviesti lähetetty" + +#: .\templates\password_reset\reset_sent.html:7 +#, python-format +msgid "" +"An email was sent to %(email)s %(ago)s ago. Use the link in " +"it to set a new password." +msgstr "" +"Sähköposti on lähetetty osoitteeseen %(email)s %(ago)s:a " +"sitten. Käytä linkkiä asettaaksesi uuden salasanan." + #: .\webapp\forms.py:38 msgid "Email (not public)" msgstr "Sähköposti (ei julkinen)" @@ -665,13 +735,13 @@ msgstr "Ilmoittautumiset" msgid "Corporate affairs" msgstr "Yrityssuhteet" -#: .\webapp\models.py:95 .\webapp\templates\freshmen.html:7 -#: .\webapp\templates\navigation.html:10 +#: .\webapp\models.py:95 .\webapp\templates\freshmen.html:10 +#: .\webapp\templates\navigation.html:9 msgid "Freshmen" msgstr "Fuksit" -#: .\webapp\models.py:96 .\webapp\templates\international.html:7 -#: .\webapp\templates\navigation.html:16 +#: .\webapp\models.py:96 .\webapp\templates\international.html:10 +#: .\webapp\templates\navigation.html:15 msgid "International" msgstr "International" @@ -839,24 +909,20 @@ msgstr "Telegram-kanavat" msgid "SIK Admin" msgstr "SIK Hallintapaneeli" -#: .\webapp\templates\base.html:15 .\webapp\templates\kaehmy_base.html:14 -msgid "Aalto-yliopiston Sähköinsinöörikilta ry" -msgstr "Aalto-yliopiston Sähköinsinöörikilta ry" - -#: .\webapp\templates\contact.html:7 .\webapp\templates\navigation.html:22 +#: .\webapp\templates\contact.html:10 .\webapp\templates\navigation.html:21 msgid "Contact" msgstr "Yhteystiedot" -#: .\webapp\templates\event_calendar.html:7 -#: .\webapp\templates\navigation.html:13 +#: .\webapp\templates\event_calendar.html:10 +#: .\webapp\templates\navigation.html:12 msgid "Event calendar" msgstr "Tapahtumakalenteri" -#: .\webapp\templates\guild.html:7 +#: .\webapp\templates\guild.html:10 msgid "Kilta" msgstr "Kilta" -#: .\webapp\templates\jobs.html:7 .\webapp\templates\navigation.html:29 +#: .\webapp\templates\jobs.html:10 .\webapp\templates\navigation.html:28 msgid "Jobs" msgstr "Työpaikat" @@ -983,35 +1049,15 @@ msgstr "Uusi kaehmy" msgid "Statistics" msgstr "Kaehmytilastot" -#: .\webapp\templates\login.html:25 .\webapp\templates\login.html:27 -msgid "Username" -msgstr "Käyttäjänimi" - -#: .\webapp\templates\login.html:31 .\webapp\templates\login.html:33 -msgid "Password" -msgstr "Salasana" - -#: .\webapp\templates\login.html:43 -msgid "Log in" -msgstr "Kirjaudu sisään" - -#: .\webapp\templates\main_index.html:8 -msgid "Infoscreen" -msgstr "Infonäyttö" - -#: .\webapp\templates\main_index.html:9 -msgid "Admin tools" -msgstr "Hallintatyökalut" - -#: .\webapp\templates\navigation.html:7 +#: .\webapp\templates\navigation.html:6 msgid "Guild" msgstr "Kilta" -#: .\webapp\templates\navigation.html:19 .\webapp\templates\sosso.html:7 +#: .\webapp\templates\navigation.html:18 .\webapp\templates\sosso.html:10 msgid "Sössö" msgstr "Sössö" -#: .\webapp\templates\navigation.html:26 +#: .\webapp\templates\navigation.html:25 msgid "Corporate" msgstr "Yritys" @@ -1031,6 +1077,12 @@ msgstr "Kaikki haasteet" msgid "Total challenges:" msgstr "Haasteita yhteensä:" +#~ msgid "Infoscreen" +#~ msgstr "Infonäyttö" + +#~ msgid "Admin tools" +#~ msgstr "Hallintatyökalut" + #~ msgid "" #~ "\n" #~ " first_name, last_name, email_address and place_of_origin " From e5c00a47e8b5977cffd60a0b5935cbf8e362e216 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 2 Nov 2017 23:11:59 +0200 Subject: [PATCH 6/7] Add missing pyexcel dependency --- requirements.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/requirements.txt b/requirements.txt index 2dfabfe..3db9b7a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -31,3 +31,5 @@ django-suit==0.2.25 telepot==12.3 django-import-export==0.5.1 django-password-reset==1.0 +pyexcel==0.5.6 +pyexcel-xlsx==0.5.2 \ No newline at end of file From 31e324e478748a2b43c6117a208738d2bff50f02 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Thu, 2 Nov 2017 23:20:57 +0200 Subject: [PATCH 7/7] Remove obsolete setting in base.py --- members/templates/member_add_many.html | 2 +- sikweb/base.py | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/members/templates/member_add_many.html b/members/templates/member_add_many.html index 15a2c85..8595c2f 100644 --- a/members/templates/member_add_many.html +++ b/members/templates/member_add_many.html @@ -31,7 +31,7 @@
{% csrf_token %}

{% trans "Upload file" %}

- +
diff --git a/sikweb/base.py b/sikweb/base.py index 48e42eb..454b977 100644 --- a/sikweb/base.py +++ b/sikweb/base.py @@ -259,10 +259,6 @@ MEDIA_URL = '/media/' LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/admin' -# for django-excel -FILE_UPLOAD_HANDLERS = ("django_excel.ExcelMemoryFileUploadHandler", - "django_excel.TemporaryExcelFileUploadHandler") - SUIT_CONFIG = { # header 'ADMIN_NAME': 'SIK Admin',