1 #!/usr/bin/env python 2 3 """ 4 A Web interface to the user profile. 5 6 Copyright (C) 2015 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from imipweb.resource import FormUtilities, ResourceClient 23 24 class ProfilePage(ResourceClient, FormUtilities): 25 26 "A request handler for the user profile page." 27 28 # See: imiptools.config, imiptools.profile 29 30 pref_labels = [ 31 ("participating" , "Participate in the calendar system"), 32 ("CN" , "Your common name"), 33 ("LANG" , "Language"), 34 ("TZID" , "Time zone/regime"), 35 ("incoming" , "How to present incoming calendar messages"), 36 ("freebusy_sharing" , "Share free/busy information"), 37 ("freebusy_bundling" , "Bundle free/busy details with messages"), 38 ("freebusy_publishing" , "Publish free/busy details via the Web"), 39 ("freebusy_messages" , "Deliver details of received free/busy messages"), 40 ("add_method_response" , "How to respond to messages adding events"), 41 ("event_refreshing" , "How to handle event refresh requests"), 42 ("organiser_replacement" , "Recognise whom as a new organiser of an event?"), 43 ] 44 45 def handle_request(self): 46 args = self.env.get_args() 47 save = args.has_key("save") 48 cancel = args.has_key("cancel") 49 action = save or cancel 50 51 if not action: 52 return ["action"] 53 54 if save: 55 errors = self.update_preferences() 56 if errors: 57 return errors 58 else: 59 self.redirect(self.link_to()) 60 61 elif cancel: 62 self.redirect(self.link_to()) 63 64 return None 65 66 def update_preferences(self): 67 68 "Update the stored preferences." 69 70 settings = self.get_current_preferences() 71 prefs = self.get_preferences() 72 errors = [] 73 74 for name, value in settings.items(): 75 choices = prefs.known_key_choices.get(name) 76 if choices and not choices.has_key(value): 77 errors.append(name) 78 79 if errors: 80 return errors 81 82 for name, value in settings.items(): 83 prefs[name] = value 84 85 # Request logic methods. 86 87 def is_initial_load(self): 88 89 "Return whether the event is being loaded and shown for the first time." 90 91 return not self.env.get_args().has_key("editing") 92 93 def get_stored_preferences(self): 94 95 "Return stored preference information for the current user." 96 97 prefs = self.get_preferences() 98 return dict(prefs.items()) 99 100 def get_current_preferences(self): 101 102 "Return the preferences currently being edited." 103 104 if self.is_initial_load(): 105 return self.get_stored_preferences() 106 else: 107 return dict([(name, values and values[0] or "") for (name, values) in self.env.get_args().items()]) 108 109 # Output fragment methods. 110 111 def show_preferences(self, errors=None): 112 113 "Show the preferences, indicating any 'errors' in the output." 114 115 page = self.page 116 settings = self.get_current_preferences() 117 prefs = self.get_preferences() 118 119 # Add a hidden control to help determine whether editing has already begun. 120 121 self.control("editing", "hidden", "true") 122 123 # Show the range of preferences, getting all possible entries and using 124 # configuration defaults. 125 126 page.table(class_="profile", cellspacing=5, cellpadding=5) 127 page.thead() 128 page.tr() 129 page.th("Preferences", class_="mainheading", colspan=2) 130 page.tr.close() 131 page.thead.close() 132 page.tbody() 133 134 for name, label in self.pref_labels: 135 value = settings.get(name) 136 default = prefs.known_keys.get(name) 137 choices = prefs.known_key_choices.get(name) 138 139 page.tr() 140 page.th(class_="profileheading %s%s" % (name, errors and name in errors and " error" or "")) 141 page.label(label, for_=name) 142 page.th.close() 143 page.td() 144 145 if not choices: 146 page.input(name=name, value=(value or default), type="text", class_="preference", id_=name) 147 else: 148 choices = list(choices.items()) 149 choices.sort() 150 self.menu(name, default, choices, [value], class_="preference") 151 152 page.td.close() 153 page.tr.close() 154 155 page.tbody.close() 156 page.table.close() 157 158 def show_controls(self): 159 160 "Show controls for performing actions." 161 162 page = self.page 163 164 page.p(class_="controls") 165 page.input(name="save", type="submit", value="Save") 166 page.input(name="cancel", type="submit", value="Cancel") 167 page.p.close() 168 169 # Full page output methods. 170 171 def show(self): 172 173 "Show the preferences of a user." 174 175 page = self.page 176 errors = self.handle_request() 177 178 if not errors: 179 return True 180 181 self.new_page(title="Profile") 182 page.form(method="POST") 183 self.show_preferences(errors) 184 self.show_controls() 185 page.form.close() 186 187 return True 188 189 # vim: tabstop=4 expandtab shiftwidth=4