From e39b3b68ea98737a2b4e54077eef2058ad6e7783 Mon Sep 17 00:00:00 2001 From: Doug Blank Date: Sat, 2 Jan 2010 16:34:37 +0000 Subject: [PATCH] Added profile, with css theme svn: r13959 --- src/web/grampsdb/admin.py | 1 + src/web/grampsdb/fixtures/initial_data.json | 2 +- src/web/grampsdb/models.py | 19 +++++++- src/web/grampsdb/profile.py | 48 ++++++++++++++++++++ src/web/grampsdb/views.py | 20 +++----- src/web/init.py | 3 +- src/web/settings.py | 2 + src/web/sqlite.db | Bin 204800 -> 207872 bytes 8 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 src/web/grampsdb/profile.py diff --git a/src/web/grampsdb/admin.py b/src/web/grampsdb/admin.py index ee2502975..a947ac0cc 100644 --- a/src/web/grampsdb/admin.py +++ b/src/web/grampsdb/admin.py @@ -4,3 +4,4 @@ from django.contrib import admin for type_name in get_tables("all"): admin.site.register(type_name[1]) +admin.site.register(Profile) diff --git a/src/web/grampsdb/fixtures/initial_data.json b/src/web/grampsdb/fixtures/initial_data.json index 234b2e572..7ec73bab3 100644 --- a/src/web/grampsdb/fixtures/initial_data.json +++ b/src/web/grampsdb/fixtures/initial_data.json @@ -18,7 +18,7 @@ "setting" : "db_created" , "description" : "database creation date/time" , "value_type" : "str" , - "value" : "2010-01-01 10:12" + "value" : "2010-01-02 11:30" } }, { diff --git a/src/web/grampsdb/models.py b/src/web/grampsdb/models.py index 8b97b54f0..c6e3dbf0c 100644 --- a/src/web/grampsdb/models.py +++ b/src/web/grampsdb/models.py @@ -36,6 +36,8 @@ from django.contrib.contenttypes import generic from gen.lib.date import Date as GDate, Today from Utils import create_id, create_uid +from web.grampsdb.profile import Profile + #--------------------------------------------------------------------------- # # Support functions @@ -290,7 +292,21 @@ class DateNewYearType(mGrampsType): _DEFAULT = _DATAMAP[NEWYEAR_JAN1] val = models.IntegerField('New Year start date', choices=_DATAMAP, blank=False) - + +class ThemeType(mGrampsType): + _DATAMAP = list(enumerate(["Web_Mainz.css", + "Web_Basic-Ash.css", + "Web_Basic-Cypress.css", + "Web_Nebraska.css", + "Web_Basic-Lilac.css", + "Web_Print-Default.css", + "Web_Basic-Peach.css", + "Web_Visually.css", + "Web_Basic-Spruce.css",])) + + _DEFAULT = _DATAMAP[0] + val = models.IntegerField('Theme', choices=_DATAMAP, blank=False) + #--------------------------------------------------------------------------- # # Support definitions @@ -737,6 +753,7 @@ TABLES = [ ("type", GenderType), ("type", LdsType), ("type", LdsStatus), + ("type", ThemeType), ("abstract", DateObject), ("meta", Config), ("abstract", PrimaryObject), diff --git a/src/web/grampsdb/profile.py b/src/web/grampsdb/profile.py new file mode 100644 index 000000000..8854639ff --- /dev/null +++ b/src/web/grampsdb/profile.py @@ -0,0 +1,48 @@ +# Gramps - a GTK+/GNOME based genealogy program +# +# Copyright (C) 2009 Douglas S. Blank +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# $Id$ +# + +from django.db import models +from django.db.models.signals import post_save +from django.contrib.auth.models import User + +class Profile(models.Model): + """ + Used to save additional information of a user, such as + themes, bookmarks, etc. + """ + user = models.ForeignKey(User, unique=True) + css_theme = models.CharField(max_length=40, + default="Web_Mainz.css") + + def __unicode__(self): + return unicode(self.user) + +def save_profile(sender, instance, created, **kwargs): + """ + Creates the profile when the user gets created. + """ + if created: + profile = Profile(user=instance) + profile.save() + else: + print sender + +post_save.connect(save_profile, sender=User) diff --git a/src/web/grampsdb/views.py b/src/web/grampsdb/views.py index 670d0ab9a..ff2b46942 100644 --- a/src/web/grampsdb/views.py +++ b/src/web/grampsdb/views.py @@ -65,27 +65,19 @@ def context_processor(request): This function is executed before template processing. takes a request, and returns a dictionary context. """ - # FIXME: make the css_theme based on user's selection context = {} - context["css_theme"] = "Web_Mainz.css" - # FIXME: get the views from a config? + if request.user.is_authenticated(): + profile = request.user.get_profile() + context["css_theme"] = profile.css_theme + else: + context["css_theme"] = "Web_Mainz.css" + # Other things for all environments: context["views"] = VIEWS context["True"] = True context["False"] = False context["default"] = "" return context -# CSS Themes: -#Web_Basic-Ash.css -#Web_Mainz.css -#Web_Basic-Cypress.css -#Web_Nebraska.css -#Web_Basic-Lilac.css -#Web_Print-Default.css -#Web_Basic-Peach.css -#Web_Visually.css -#Web_Basic-Spruce.css - def main_page(request): context = RequestContext(request) context["view"] = 'home' diff --git a/src/web/init.py b/src/web/init.py index 0250b5fbd..7db2bbc01 100644 --- a/src/web/init.py +++ b/src/web/init.py @@ -43,7 +43,8 @@ from gen.lib.srcmediatype import SourceMediaType from gen.lib.eventroletype import EventRoleType from gen.lib.notetype import NoteType -from grampsdb.models import GenderType, LdsType, LdsStatus, NameFormatType +from grampsdb.models import (GenderType, LdsType, LdsStatus, + NameFormatType, ThemeType) def get_datamap(x): """ diff --git a/src/web/settings.py b/src/web/settings.py index d2c97aad6..012264397 100644 --- a/src/web/settings.py +++ b/src/web/settings.py @@ -111,6 +111,8 @@ DEBUG_TOOLBAR_CONFIG = { 'HIDE_DJANGO_SQL': False, } +AUTH_PROFILE_MODULE = "grampsdb.Profile" + # Had to add these to use settings.configure(): DATABASE_OPTIONS = '' URL_VALIDATOR_USER_AGENT = '' diff --git a/src/web/sqlite.db b/src/web/sqlite.db index 007a2a0187fedb2c2236620bbf0af6f9236afe6f..db8df5aa7b4d42afe85067229a8157da8854099c 100644 GIT binary patch delta 16406 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 delta 15228 zcmeHud3;nwzVG=}oz70kLZ>@RC!LK>XYYh;B!mPEsH_Pf$ZAL$2xKD($RaikF5}4R zQA-_X#EW-k9NA3N%yk$99Y;VAb<{WGe&47U)Om>W#;4=G&imEUC+P&|&imuO&->%$ z6Dp^^^;@cbRrNc+U!7w6@1wS#jM|qRJ5vk(xn+NTZAb&he!IWB!O}=)&;}zm>f3>* zVK4Zch(G5K$MTnc3zkp%uy}kk7LWE|@!&cv?rFv1hs&|pu@H+bbFo-81B>QqSS+o_ zV)0}w7S&>L!z3)`*I?09jm4aaSj?=%;`(wdrk7z+UxGz#Ar{qX1z1+*VNsTYMTrZG zqHHYkGqG@`8~>fU;btRBFDT|}_>U{mqLqSsYICQvxwX~V(cH7n+vDup-0cm=`U+Xc z>Oh;ml@|8;Bao+OJr+9;-%-eEhTg#f}&ebE^+;$y25Y1&-gSm1Nbtr`~#{RH)pG!U~2`y{d+FN_P ztGMj(2|5(O7|uT&&K{?O8=_QqHuSV}+AIkwDGJPt)gcq2xB!J@Bm97ppG~lvLS-Y2tX+) zwyp@m6~8&l-ejRKTuB(hlf)=TEQ!>JeK0ExNHfmf`e+>-kR4Fcfl#}!Z=%xC(%kOt zY;Er01LmuJ-OwBjP0_%&kq08Z6&2nRPnM^u+0#0qtZG8*$|_H3afxSTRXK`pEp4eN zUsX|3T3K1{Eh|}71^^|+p5lUH5B@qm#S=ZH6N}3WD=RCiiap=o(r=H9sp_WR(gSoO zy^%K19IBI#$g|{O(o3e3Z1^j@35yRjEyn>?!{N?^aYj9s@rKu(264vi?p%m9j=2jV#`plA z#~Km2=@4z?=jP$ET$GywQHDR)0g=Wdxo(Is&g7;+xN#{r({Sg#+1!=PcNx%+c`r85 zkLl<10(}&p(&0DcOW2_O5Pk}G!FbY6o`YHBF*05ofWMMhZ3S)89wD{bMeR56KCRK- zA~!&@_ANw{x1fsLNu%g4x(#Kr^!LH)%N?gXl3{gEb4Pb?>q<0wkGHqi9R#*E_ceDk zcjv_Gjzp7^ua^zot{B}BZ({AOz2jqbht&l58q5wxy866Xak|5%Xco7w?C`d>HD?aP zT32?rH@A2*Y`P=e6g9MP(t}8a191j*t+#7KPm4FrNH2(=mKxO3?d|F9>U0EQEnS_f z+E%Be=#D&78IIW7>AiWgSFYh?V}F4Il8mDTiMRmH6eJhe6Ld$KNsi<0?Q8Da&}$2_ z8^U}CBp9)UwnS^tXr%RcD=wKrYgK%b?r@p%#F%=z&=Vp-Tu{&C*o4V=W2~{aFbQJV z{&ye&*Vn1SWL#hG6(%N(3F?V*Oi}FE+mHm2>@}QuTyT?$Y(`s=&))Yvqv?+d2|E~4 zsi)z4C0l!g{D4l^(zV%qK@R`X2R7BT5>gXwTsyY}*S+T}o00O;7~_$-tFcd^jfJ=) z5M$fNf^IZ6w)fwr>jU~s&<8B@{}vi!(eV9Nu6+kjk_Fx~}^hVvLiGmAIq0 zw3w!waVPEHVKsi-WHZVd?Z&yL^{A0{bm)niS+Y2F8AP2VhL?wpW zN=so!T3_?ZcEjTzXO#Hkjox*3W0}84^rtUsK)(&b#%dS@OcoaCrqxCNWXp{%9!-vntSGl4210ZF7lv$AS{MLs|Ky4j8g3pZK<{t`*SUs zlxftzSQEx04&A>c-FWg?F1Uq=k|(!Q|Lip5=MUBzO%K?O?;hNOz1;jz4djUS^ABwz zBN%@9QyujFL#Jt|bmJw)g`;Hy`f(B#@q`9X&{MDm)(pf(Ednwr8}()zzj)0S#)A+2 zw)hO=PfzATF3PqK6!*W1B%*7O*MB@BEChM0p&EJfu)!sGFaFLJ<`KMgS;om1bD@Cu zYk>UryW!%Yu>W{SSj6)hJdZN`;71wjfmFMVJ(nhiP2l`HZy9gA_*yO$bAEPc9)u6X zyxtFBssT^`8`UHG7&Rr^ja!!d$I%2^2=|f=23$fi;YOFt&ZhZJz8dUUu z{$e;32??M5#Tv$=NPTB@z7h6S4pa?zzA|7)K1}TYx*^Qs39-#`aS8XWgZQvI&T+@2 z!u#%k9Ba*}{;C$E_$xbGI*)`6MglC2gi^L93bNoDVT#A1ppZ6Ho4wE{?Ob2X;>W;v zm@GPfV7orJU<@3CVBLD%UF9Wg%2=eEA_Sq2@WIq)?4av|`Zy?w9j!-i*wHe9{c|?t z!Zgk^_;1-5fI%6HbU{8`E1)?p_<1;#v#*O0x=uhf9{BeVs9;rP8N; z;}=QP;K{jA7!Eb;@{Oo#p1|+=ltd2JErvCrFo`|hjDf}iAqHo4kgkNWVNlEB*P@t( z2-}U~ehWJmLPG{uuZ8?jn9S~7kD_iAEW74~4YsbuSaC467d#fIXTRA3m5IxOXRdie z-VW)-uUxyp+Lq?}D62 zFJBomri9p5RIw-bf`h%c3*7qh9rmd#VmDf11*_N%pW_-hH93XV?STyarX39pY}Fp9 zgO!6n+XEJWY3%S`Xo8k!_CZNZ*z{1_q)Bj_m0frgtZdE!a6+p&;MoTtoZWu_J{Zvt z-Miz4>)7c>;d)qY5*PmyT!!nJ^B^qM*Z8#=Z2LhRg1U z^Pj=CL-1o-RI1U}=s(eIw28XN*W?AVhpZ!0NFsa&gRm2al&pQE{aV|nwP>YUVIkY} z9HjVScvQTqxudOpbB|Xf4S59?tpW;o)+NJZrwm#6>wByUn1`~Ue3Mwl<->_pq;3*t z=UFrlxB~ec#}oQQJ{O!?mF2RIW02;!dU93fwrKUZFX~?dYlh&CR*Hr~F5cIo9E(;B z9_IN3;uAR_a;{*S5*Lel5>jQ-MM}oAI;{D|D0##4tNd(>Rwb>17ITUwC#Gbg1EaDr zSC*N%DjQ-%BS=SNXs%3?P}y%o&qPJ3dZA*W^bCtu0GR>fnezDjDU#B3X6uJk+we@z z%+^YsY^G>bVuMn)f;8suhvadilR0-PJJt`0aU;_?w}ZWdctwN~7s%c+Q!H8$WCyy* zVKMHY6t5te^(K%j05?hQdzR_78PwriqmE-Tb+W&+oNI{1(1sb6RHo%>jz&{Bu z!H4h-i6l-^My??@kTqm0*-w5(j*~aY=j3nHO7rMcx}0vNcVlMtG(AT@p+BNe(O2o` zC|nb1Byf9nvu#hojnFmt)>A0bca{9ooA`ansKnJi8A?)YoAo|u1NTrFNRW%CH@#V zd>|p5Agme3(w~KKzA{-+5`yT;#TJR@{GFI}^HpCVHbZ>C$0)Q?qDn@9wn{A4ah!c9 zTb(HSG)@WVX!h|#04}*&HYgcG3^hWEl}lNTXF^_aCNxP9Ta}a{yjJ2$$PhkRY_9|^ zMCH_VLTo~dPaX*>v|gf$Ux8D^(y%FJnWs+`Yrv*DfP@mhM#4k<5^fO3S9UIe``=Yv zJss%nanRF}=kr5Ld%&JSjnlMONMLi0Lu9m7iIlU#F7t+4v0>ckX>?6uKRyn2 z--uZ+sNt{tqG5rMTqdF;N93z^Q(cl1#@zAhrm_?-T#z0NRR9E%(a^X(a=pX1I>Z7x$ zmAprek!|=68VA3}$YM3*Yge?_v?sLNH7`H<&@}$-B=D1U12?V+Yt=lcV>>nHvX;8Q zqPZbG5Ev;EZh!fhHQ$sXZRAu3ead38mNidO)eTL$B2&s_Eww2~nIhrJw#B*l+%P370Jwaikui!z9k08k8apqvSR=$@r2@#`AvquNcJs%ka+x zx&JSJCt&WE;GGF}n5E(8fwS}|z9_cRMRYP9Psd`$`bTn_Jb_tj7gEbT1jer{HK7L$n_wgmrN>#}HxjzsBv1H`fxKVAsIISAnR zXvMV9>agmV_%Q3jZp+ObAe1#8Z>PgT4HiNV?1Lltx$|Q}NIY?o zYBCd}>^^ckd5|0?C&=sM6Y>=erzzA!ucOU$J-rPh?Vr(S>3RAt{U78l@+tXu8jG`4 ziC%Ig-GF)2qd1GFsPA|5B4pvp7l98JB8Eu`a$WOdbetE*kjGmfh#YDQNH2JU#1x~% z77E5x&M4jaB0-d@7&+!^-+ZG46{jRzEI89Rr?lDChGkfV2L}$-*=y;U-eJ*a6Y!&{ncD9I|uI4!B$Ye%!afDZ$ zD;v4jPVhB~(WUSn$f<4;BS}%L5}PNn|ALwD@iU{*Q}KUoCVc$cy4WTwbFQD4x!)`aW;Fd=FsE{WfmWdub<~jh~7M zz5-6-r{X>`jo9&1@mqLodM|XtOiZ<-wa>Lz@n*v={9KF?_&8tcdNWdxx}50M#w)e> zXz#XYnUEZK`SV8JMf~gRvS@koKuY$>$vt0opnv%6>@+EqY(Wti6H+AkIxJc?I0E8D zyD$M~Z#UTk3eXJP%kUc)BGz4JQUnxmihu%qPFfo*pEn0goY7{{d?Y2$lnP0sbcjmIYK!KAw7?)F0oNiWtTH7iE%IxzsLb%nrIq0|iIf^iq|}H? zN^6iBNx;>Jr~DQc{Td{VOIN)gTE_V+Sq--MMlbyF%{?q0!eENgUo?v(0Tswks+oWG(Vs&R9%+{0@?nspcr!)>5#dQ&gBnf%l{42 z;sT|Q?>K>nn3=0GlGuybRG@Sz%5=YluL<+a+9cz86iu#Q=UMFV&kg3ubiPm=?;W~c zlURqk+*Uc_&4WPmhvWAEmw(a?`mo8YwPOF*~YDwH!S4{wB#zefqKR*=1$^+ z2*9~qL7*~ztGRR42(VS$gi&hwbtqmRzlEKA6KpjN#9d!qd=V(cAS|c^2k*p>@Vvr}`G-hP4 zlF#uC;iBVcE?$kRrH$|x+D31u50V)A41Ec+vMZPw?*jJldw4ajG{`verGqx}1od&~ zC67(TK^*2QqAlm(epMo+F_@&1KKygwq}&}izUW%PQwjP}yI zF!6qz{t7=$UL+;>K`aEW;9{Hh|(v-Y5b1K%G+-#PvOria<2RJg?eEfcgQN@?5=`t~ zOsEQoM@cXjqGs59qCv?RYPbi}H5c)4Aw%GP{2)HeL+v{44onp@NdcD-fNmF=V0M5IcSom0)WCQa)ip+kWC-MH z-QuVK(>kBHk&c^py+jlT0zCq7aXoUo_KK4Om(n7!K8YzViER+Nb2y`Nr5i=^oufDv zc(VX~If_@In*_6)GvhxVuxu7|Bf^y}5>&j3a;r$9gTkU)#FxR50o68%a&8}Hj)55J zR$-z*+~&icq?2JWp0-^gN-1t*&5zx1k>Frb+aacYR4l6Plz5=e^5%SQpI5t$Cjw(( z70=p_&>fftq~O8Z2}}Z3;tL=KK7tc)53EARUI*0ePh@o;L1O&KE$#N(SvxjVl?G-= z?cYqljR#2P6%4W0c_t9F%iaD2b^_VGBlo%6ZyotrN$hJbp+u<)Z1hb3xFA(SgnU8+ zRC)e*R`W5YrlTA}oI<74VDw!gHn!|bd}VfC!CPvF zE|D;}MY7HR5|)HtMFnh=?J<9bC82S1Lv1tifc5+tuMFHe`1qe;WfW|GI*R;>f^YDz zltk!s5xm7h!^o4kR8wK_t#GnA1RB}g7*YU!c54io0!{2x3@L-1%pXhA*!wXglsRJY zKQPQ=Q)3C94=w6 zhm40M>=_TKh26tg;!8+9Eal^|vb80sc8_etXRFkRw{s)dTTLVmma&T^q!RXWiUqKo z-CRm4U>~nJ2G5m}XHzWAq5dr^*xhqU3G5d*duJ}m54$PU)>umX(^3j3e~4ZDVo?L>n=EFpI%PDy7caY=zL_UlgUSzQNlu#Y-P zKCET2UBttl??CyByGSXlV|%(tAv_{FH~2;u=}ducwssFT{jU(ld>l6 z!9fIRWQ%s;s?9DzyDs00y?=KP&c}MW7<_whPw0Db<^NQ%@5Pnh!?x}v6)a;9n)B>l zvMvQ~=Hs-oqen<0^;>$`>O;6FelA&_IfQoYW0wz+YSzCO4WS=K(uIeyvm4mX!`S$Q zBwT(3SHru9v40y`)DhfThfKVBn1&QMEb%`cL91T?R(V$$8qWmG7^2QvbMZtm+&o3c>%YSBjnO zdIh)Gt?a@pXoZsV2z>MkTH)|Tly&SC+|6e$k{EX1d2}u_ui#CCW#(cwm>z0dSVjEv z_$E$aXFo+>aa;}`w{A2CqS@!^RBX{$AwR3Gcsr#{6@+@nMuPrdJQ@vq?iIP48uR*)cZ1MF|GB7ur>>w z4JXWQEkR@Ch0r=UDIxUUA?&UYS`T5|l2-O%2xhRShBfAd(#iN*5(X{QQ7^vZLfI>! zG*rH?zW5Tt;rU_udHW!?+Y%v~ed45(;IwS5PN!3043|{PESc!{5C~`Qr_-9hH;j`1 a)CyB@+M?LHOgf4EG?b