- Timestamp:
- 20 Sep 2012, 08:49:37 (12 years ago)
- Location:
- main/waeup.kofa/branches/uli-zc-async
- Files:
-
- 18 edited
- 5 copied
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/branches/uli-zc-async
- Property svn:mergeinfo changed
-
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/batchprocessing.txt
r8472 r9209 75 75 76 76 >>> import cStringIO 77 >>> browser.getLink('Upload CSV file').click()77 >>> browser.getLink('Upload data').click() 78 78 >>> filecontents = cStringIO.StringIO( 79 79 ... open('faculties.csv', 'rb').read()) … … 84 84 Step 1: start batch processing: 85 85 86 >>> browser.getLink(' Batch processing').click()86 >>> browser.getLink('Process data').click() 87 87 >>> button = lookup_submit_value( 88 88 ... 'select', 'faculties_zope.mgr.csv', browser) … … 97 97 'Course Processor', 'CourseTicket Processor', 98 98 'Department Processor', 'Faculty Processor', 99 'Payment Processor', 'Student Processor', 99 'Hostel Processor', 100 'Student Payment Processor', 'Student Processor', 100 101 'StudentStudyCourse Processor (update only)', 101 'StudentStudyLevel Processor', 'Verdict Processor (update only)'] 102 'StudentStudyLevel Processor', 103 'User Processor', 104 'Verdict Processor (update only)'] 102 105 103 106 >>> importerselect.getControl('Faculty Processor').selected = True … … 175 178 176 179 >>> import cStringIO 177 >>> browser.getLink('Upload CSV file').click()180 >>> browser.getLink('Upload data').click() 178 181 >>> filecontents = cStringIO.StringIO( 179 182 ... open('departments.csv', 'rb').read()) … … 184 187 Step 1: start batch processing: 185 188 186 >>> browser.getLink(' Batch processing').click()189 >>> browser.getLink('Process data').click() 187 190 >>> button = lookup_submit_value( 188 191 ... 'select', 'departments_zope.mgr.csv', browser) … … 240 243 241 244 >>> import cStringIO 242 >>> browser.getLink('Upload CSV file').click()245 >>> browser.getLink('Upload data').click() 243 246 >>> filecontents = cStringIO.StringIO( 244 247 ... open('courses.csv', 'rb').read()) … … 249 252 Step 1: start batch processing: 250 253 251 >>> browser.getLink(' Batch processing').click()254 >>> browser.getLink('Process data').click() 252 255 >>> button = lookup_submit_value( 253 256 ... 'select', 'courses_zope.mgr.csv', browser) … … 305 308 306 309 >>> import cStringIO 307 >>> browser.getLink('Upload CSV file').click()310 >>> browser.getLink('Upload data').click() 308 311 >>> filecontents = cStringIO.StringIO( 309 312 ... open('certificates.csv', 'rb').read()) … … 314 317 Step 1: start batch processing: 315 318 316 >>> browser.getLink(' Batch processing').click()319 >>> browser.getLink('Process data').click() 317 320 >>> button = lookup_submit_value( 318 321 ... 'select', 'certificates_zope.mgr.csv', browser) … … 371 374 372 375 >>> import cStringIO 373 >>> browser.getLink('Upload CSV file').click()376 >>> browser.getLink('Upload data').click() 374 377 >>> filecontents = cStringIO.StringIO( 375 378 ... open('mycertcourses.csv', 'rb').read()) … … 380 383 Step 1: start batch processing: 381 384 382 >>> browser.getLink(' Batch processing').click()385 >>> browser.getLink('Process data').click() 383 386 >>> button = lookup_submit_value( 384 387 ... 'select', 'mycertcourses_zope.mgr.csv', browser) … … 420 423 ...File:...mycertcourses_zope.mgr.csv... 421 424 425 Batch processing users 426 ====================== 427 428 >>> browser.open('http://localhost/app/datacenter') 429 430 Prepare a CSV file for users: 431 432 >>> open('users.csv', 'wb').write( 433 ... """name,title,public_name,email,phone,roles 434 ... uli,Uli Fouquet,Chief Developer,uli@abc.de,+49-234-567 435 ... henrik,Henrik Bettermann,Admin,henrik@abc.de,+49-234-567,['waeup.PortalManager'] 436 ... """) 437 438 Upload the file: 439 440 >>> import cStringIO 441 >>> browser.getLink('Upload data').click() 442 >>> filecontents = cStringIO.StringIO( 443 ... open('users.csv', 'rb').read()) 444 >>> filewidget = browser.getControl(name='uploadfile:file') 445 >>> filewidget.add_file(filecontents, 'text/plain', 'users.csv') 446 >>> browser.getControl(name='SUBMIT').click() 447 448 Step 1: start batch processing: 449 450 >>> browser.getLink('Process data').click() 451 >>> button = lookup_submit_value( 452 ... 'select', 'users_zope.mgr.csv', browser) 453 >>> button.click() 454 455 Step 2: select a processor and mode: 456 457 >>> importerselect = browser.getControl(name='importer') 458 >>> importerselect.getControl('User Processor').selected = True 459 >>> modeselect = browser.getControl(name='mode') 460 >>> modeselect.getControl(value='create').selected = True 461 >>> browser.getControl('Proceed to step 3').click() 462 463 Step 3: Fix headerlines 464 465 We get informed that there are no problems with the current header: 466 467 >>> print browser.contents 468 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 469 ... 470 Header fields OK 471 ... 472 473 The submit button is enabled: 474 475 >>> browser.getControl('Perform import').disabled 476 False 477 478 >>> browser.getControl('Perform import').click() 479 480 Step 4: See import results 481 482 The import was successful: 483 484 >>> print browser.contents 485 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 486 ...Successfully processed 2 rows... 487 ...Batch processing finished... 488 ...File:...users_zope.mgr.csv... 422 489 423 490 Pending files … … 444 511 445 512 >>> import cStringIO 446 >>> browser.getLink('Upload CSV file').click()513 >>> browser.getLink('Upload data').click() 447 514 >>> filecontents = cStringIO.StringIO( 448 515 ... open('newfaculties.csv', 'rb').read()) … … 453 520 Step 1: start batch processing: 454 521 455 >>> browser.getLink(' Batch processing').click()522 >>> browser.getLink('Process data').click() 456 523 >>> button = lookup_submit_value( 457 524 ... 'select', 'newfaculties_zope.mgr.csv', browser) … … 515 582 516 583 >>> browser.open('http://localhost/app/datacenter') 517 >>> browser.getLink(' Batch processing').click()584 >>> browser.getLink('Process data').click() 518 585 >>> button = lookup_submit_value( 519 586 ... 'select', 'newfaculties_zope.mgr.create.pending.csv', browser) … … 551 618 >>> sorted(os.listdir(dc_path + '/finished')) 552 619 ['certificates_zope.mgr.create.finished.csv', ..., 553 'newfaculties_zope.mgr.create.finished.csv', 554 'newfaculties_zope.mgr.csv'] 555 620 'users_zope.mgr.create.finished.csv', 'users_zope.mgr.csv'] 621 622 Processed (finished) Files 623 ========================== 624 625 >>> browser.open('http://localhost/app/datacenter/processed') 626 >>> '<a href="download?filename=finished/certificates_zope.mgr.csv">' in browser.contents 627 True 556 628 557 629 Log Files -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/browser.txt
r8777 r9209 81 81 >>> browser.getControl(name="form.identifier").value = 'forgetful' 82 82 >>> browser.getControl(name="form.email").value = 'aa@aa.ng' 83 >>> browser.getControl(" Getlogin credentials").click()83 >>> browser.getControl("Send login credentials").click() 84 84 >>> print browser.contents 85 85 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... … … 1000 1000 with their code as key. 1001 1001 1002 Each certificate provides a ``Add c ourse referrer`` action button near top.1002 Each certificate provides a ``Add certificate course`` action button near top. 1003 1003 1004 1004 Certificates provide an add-form to add new certcourses: … … 1006 1006 >>> cert_url = dept_url + '/certificates/CERT1' 1007 1007 >>> browser.open(cert_url + '/manage') 1008 >>> browser.getControl('Add c ourse referrer').click()1008 >>> browser.getControl('Add certificate course').click() 1009 1009 >>> print browser.contents 1010 1010 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... … … 1025 1025 >>> ctrl.getControl('COURSE1').selected = True 1026 1026 >>> browser.getControl(name='form.level').value = ['100'] 1027 >>> browser.getControl('Add c ourse referrer').click()1027 >>> browser.getControl('Add certificate course').click() 1028 1028 1029 1029 Our certificatecourse will be linked on the parent certificate page: … … 1038 1038 >>> cert_url = dept_url + '/certificates/CERT1' 1039 1039 >>> browser.open(cert_url + '/manage') 1040 >>> browser.getControl('Add c ourse referrer').click()1040 >>> browser.getControl('Add certificate course').click() 1041 1041 >>> ctrl = browser.getControl(name='form.course') 1042 1042 >>> ctrl.getControl('COURSE1').selected = True 1043 1043 >>> browser.getControl(name='form.level').value = ['100'] 1044 >>> browser.getControl('Add c ourse referrer').click()1045 >>> 'The chosen c ourse referreris already' in browser.contents1044 >>> browser.getControl('Add certificate course').click() 1045 >>> 'The chosen certificate course is already' in browser.contents 1046 1046 True 1047 1047 … … 1063 1063 1064 1064 >>> browser.open(cert_url + '/COURSE1_100') 1065 >>> browser.getLink('Edit c ourse referrer').click()1065 >>> browser.getLink('Edit certificate course').click() 1066 1066 1067 1067 If we just click 'Save and return' nothing will change: … … 1088 1088 changed: 1089 1089 1090 >>> browser.getLink('Edit c ourse referrer').click()1090 >>> browser.getLink('Edit certificate course').click() 1091 1091 >>> browser.getControl(name='form.level').value = ['400'] 1092 1092 >>> browser.getControl('Cancel').click() … … 1125 1125 >>> 'COURSE1_200</a>' in browser.contents 1126 1126 True 1127 >>> browser.getControl('Remove selected c ourse referrers').click()1127 >>> browser.getControl('Remove selected certificate courses').click() 1128 1128 >>> 'No item selected' in browser.contents 1129 1129 True 1130 1130 >>> browser.getControl(name='val_id').getControl( 1131 1131 ... value='COURSE1_200').selected = True 1132 >>> browser.getControl('Remove selected c ourse referrers').click()1132 >>> browser.getControl('Remove selected certificate courses').click() 1133 1133 >>> 'Successfully removed: COURSE1_200' in browser.contents 1134 1134 True … … 1218 1218 page: 1219 1219 1220 >>> browser.getLink('Upload CSV file').click()1220 >>> browser.getLink('Upload data').click() 1221 1221 1222 1222 and enter the appropriate data in the form: -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/layout.py
r9003 r9209 191 191 grok.baseclass() 192 192 template = default_waeup_display_template 193 hide_hint = True 193 194 194 195 class KofaEditFormPage(UtilityView,EditForm): … … 215 216 if self.widgets.get('perm_address'): 216 217 self.widgets['perm_address'].cssClass = 'span8' 217 self.widgets['perm_address'].height = 10 218 self.widgets['perm_address'].height = 6 219 if self.widgets.get('next_kin_address'): 220 self.widgets['next_kin_address'].cssClass = 'span8' 221 self.widgets['next_kin_address'].height = 6 222 if self.widgets.get('notice'): 223 self.widgets['notice'].cssClass = 'span8' 224 self.widgets['notice'].height = 6 218 225 if self.widgets.get('description'): 219 226 self.widgets['description'].cssClass = 'span12' … … 306 313 else: 307 314 return None 315 316 def formatTZDate(self,datetimeobj): 317 if isinstance(datetimeobj, datetime): 318 tz = getUtility(IKofaUtils).tzinfo 319 date = to_timezone( 320 datetimeobj, tz).strftime("%d/%m/%Y") 321 return date 322 else: 323 return None 308 324 309 325 def update(self): -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pages.py
r9166 r9209 18 18 """ Viewing components for Kofa objects. 19 19 """ 20 import copy21 20 import csv 22 21 import grok … … 24 23 import re 25 24 import sys 26 import time 27 import re 25 from urllib import urlencode 28 26 from zope import schema 29 27 from zope.authentication.interfaces import ( … … 34 32 getUtilitiesFor, 35 33 ) 36 #from zope.component.interfaces import Invalid37 34 from zope.event import notify 38 from zope.securitypolicy.interfaces import ( 39 IPrincipalRoleManager, IPrincipalRoleMap) 35 from zope.securitypolicy.interfaces import IPrincipalRoleManager 40 36 from zope.session.interfaces import ISession 37 from zope.password.interfaces import IPasswordManager 41 38 from waeup.kofa.browser.layout import ( 42 39 KofaPage, KofaForm, KofaEditFormPage, KofaAddFormPage, … … 49 46 from waeup.kofa.browser.layout import jsaction, action, UtilityView 50 47 from waeup.kofa.browser.resources import ( 51 warning, datepicker, tabs, datatable, page_reloader, page_not_reloader)48 warning, tabs, datatable) 52 49 from waeup.kofa.interfaces import MessageFactory as _ 53 50 from waeup.kofa.interfaces import( … … 64 61 from waeup.kofa.university.vocabularies import course_levels 65 62 from waeup.kofa.authentication import LocalRoleSetEvent 66 #from waeup.kofa.widgets.restwidget import ReSTDisplayWidget67 63 from waeup.kofa.widgets.htmlwidget import HTMLDisplayWidget 68 from waeup.kofa. authentication import get_principal_role_manager69 from waeup.kofa. utils.helpers import get_user_account, msave64 from waeup.kofa.utils.helpers import get_user_account 65 from waeup.kofa.mandates.mandate import PasswordMandate 70 66 71 67 grok.context(IKofaObject) … … 156 152 return 157 153 154 # Save function used for save methods in pages 155 def msave(view, **data): 156 changed_fields = view.applyData(view.context, **data) 157 # Turn list of lists into single list 158 if changed_fields: 159 changed_fields = reduce(lambda x,y: x+y, changed_fields.values()) 160 fields_string = ' + '.join(changed_fields) 161 view.flash(_('Form has been saved.')) 162 ob_class = view.__implemented__.__name__.replace('waeup.kofa.','') 163 if fields_string: 164 grok.getSite().logger.info('%s - %s - saved: %s' % (ob_class, view.context.__name__, fields_string)) 165 return 166 158 167 # 159 168 # Login/logout and language switch pages... … … 192 201 self.redirect(self.camefrom) 193 202 return 194 self.flash(_('You entered wrong credentials.')) 203 # Display appropriate flash message if credentials are correct 204 # but student has been deactivated. 205 login = self.request.form['form.login'] 206 if len(login) == 8 and grok.getSite()['students'].has_key(login): 207 student = grok.getSite()['students'][ 208 self.request.form['form.login']] 209 password = self.request.form['form.password'] 210 passwordmanager = getUtility(IPasswordManager, 'SSHA') 211 if passwordmanager.checkPassword(student.password, password): 212 self.flash(_('Your account has been deactivated.')) 213 return 214 self.flash(_('You entered invalid credentials.')) 195 215 196 216 … … 372 392 def entries(self): 373 393 return () 374 375 class ReindexPage(UtilityView, grok.View):376 """ Reindex view.377 378 Reindexes a catalog. For managers only.379 """380 grok.context(IUniversity)381 grok.name('reindex')382 grok.require('waeup.managePortal')383 384 def update(self,ctlg=None):385 if ctlg is None:386 self.flash('No catalog name provided.')387 return388 cat = queryUtility(ICatalog, name='%s_catalog' % ctlg)389 if cat is None:390 self.flash('%s_catalog does not exist' % ctlg)391 return392 self.context.logger.info(393 'Catalog `%s_catalog` re-indexing started.' % ctlg)394 cat.updateIndexes()395 no_of_entries = cat.values()[0].documentCount()396 self.flash('%d %s re-indexed.' % (no_of_entries,ctlg))397 self.context.logger.info(398 'Re-indexing of %d objects finished.' % no_of_entries)399 return400 401 def render(self):402 self.redirect(self.url(self.context, '@@index'))403 return404 394 405 395 # … … 801 791 def delFiles(self, **data): 802 792 form = self.request.form 803 logger = self.context.logger804 793 if form.has_key('val_id'): 805 794 child_id = form['val_id'] … … 826 815 return 827 816 817 class DatacenterFinishedPage(KofaEditFormPage): 818 grok.context(IDataCenter) 819 grok.name('processed') 820 grok.require('waeup.manageDataCenter') 821 label = _(u'Processed Files') 822 pnav = 0 823 824 def update(self): 825 datatable.need() 826 return super(DatacenterFinishedPage, self).update() 827 828 828 class DatacenterUploadPage(KofaPage): 829 829 grok.context(IDataCenter) 830 830 grok.name('upload') 831 831 grok.require('waeup.manageDataCenter') 832 label = _(u'Upload file')832 label = _(u'Upload portal data as CSV file') 833 833 pnav = 0 834 834 upload_button =_(u'Upload') … … 849 849 self.flash(_("Only csv files are allowed.")) 850 850 return 851 target = os.path.join(self.context.storage, 852 self.getNormalizedFileName(filename)) 851 normalized_filename = self.getNormalizedFileName(filename) 852 finished_file = os.path.join( 853 self.context.storage, 'finished', normalized_filename) 854 unfinished_file = os.path.join( 855 self.context.storage, 'unfinished', normalized_filename) 856 if os.path.exists(finished_file) or os.path.exists(unfinished_file): 857 self.flash(_("File with same name was uploaded earlier.")) 858 return 859 target = os.path.join(self.context.storage, normalized_filename) 853 860 open(target, 'wb').write(uploadfile.read()) 854 861 os.chmod(target, 0664) … … 881 888 return '%s_%s%s' % (base, filtered_username, ext.lower()) 882 889 890 def getImporters(self): 891 importers = getAllUtilitiesRegisteredFor(IBatchProcessor) 892 importer_props = [] 893 for x in importers: 894 iface_fields = schema.getFields(x.iface) 895 available_fields = [] 896 for key in iface_fields.keys(): 897 iface_fields[key] = (iface_fields[key].__class__.__name__, 898 iface_fields[key].required) 899 for value in x.available_fields: 900 available_fields.append( 901 dict(f_name=value, 902 f_type=iface_fields.get(value, (None, False))[0], 903 f_required=iface_fields.get(value, (None, False))[1] 904 ) 905 ) 906 available_fields = sorted(available_fields, key=lambda k: k['f_name']) 907 importer_props.append( 908 dict(title=x.name, name=x.util_name, fields=available_fields)) 909 return sorted(importer_props, key=lambda k: k['title']) 910 883 911 class FileDownloadView(UtilityView, grok.View): 884 912 grok.context(IDataCenter) … … 897 925 'Content-Type', 'text/csv; charset=UTF-8') 898 926 self.response.setHeader( 899 'Content-Disposition:', 'attachment; filename="%s .csv' %900 self.filename.replace(' .csv',''))927 'Content-Disposition:', 'attachment; filename="%s' % 928 self.filename.replace('finished/','')) 901 929 fullpath = os.path.join(self.context.storage, self.filename) 902 930 return open(fullpath, 'rb').read() 931 932 class SkeletonDownloadView(UtilityView, grok.View): 933 grok.context(IDataCenter) 934 grok.name('skeleton') 935 grok.require('waeup.manageDataCenter') 936 937 def update(self, processorname=None): 938 self.processorname = self.request.form['name'] 939 self.filename = ('%s_000.csv' % 940 self.processorname.replace('processor','import')) 941 return 942 943 def render(self): 944 #ob_class = self.__implemented__.__name__.replace('waeup.kofa.','') 945 #self.context.logger.info( 946 # '%s - skeleton downloaded: %s' % (ob_class, self.filename)) 947 self.response.setHeader( 948 'Content-Type', 'text/csv; charset=UTF-8') 949 self.response.setHeader( 950 'Content-Disposition:', 'attachment; filename="%s' % self.filename) 951 processor = getUtility(IBatchProcessor, name=self.processorname) 952 csv_data = processor.get_csv_skeleton() 953 return csv_data 903 954 904 955 class DatacenterImportStep1(KofaPage): … … 914 965 915 966 def getFiles(self): 916 files = self.context.get Files(sort='date')967 files = self.context.getPendingFiles(sort='date') 917 968 for file in files: 918 969 name = file.name … … 1138 1189 return False 1139 1190 1140 @property1141 def nextstep(self):1142 return self.url(self.context, '@@import4')1143 1144 1191 def update(self, headerfield=None, back2=None, cancel=None, proceed=None): 1145 1192 datatable.need() … … 1362 1409 string representing the exporter title used when triggering 1363 1410 the export job. 1364 1365 Calling this method also installs a JavaScript page reloader1366 that reloads the page after some time (1.5 secs), if there is1367 a running export that is not completed yet.1368 1369 The method caches results.1370 1411 """ 1371 1412 if self._running_exports is None: … … 1375 1416 def _getRunningExports(self): 1376 1417 result = self.context.get_export_jobs_status(self.user_id) 1377 uncompleted = [x for x in result if x[0] != 'completed']1378 #if len(uncompleted):1379 # page_reloader.need()1380 #else:1381 # page_not_reloader.need()1382 1418 return result 1383 1419 … … 1426 1462 return 1427 1463 result = open(path, 'rb').read() 1464 acronym = grok.getSite()['configuration'].acronym.replace(' ','') 1465 filename = "%s_%s" % (acronym, os.path.basename(path)) 1428 1466 self.response.setHeader( 1429 1467 'Content-Type', 'text/csv; charset=UTF-8') 1468 self.response.setHeader( 1469 'Content-Disposition', 'attachment; filename="%s' % filename) 1430 1470 # remove job and running_exports entry from context 1431 1471 self.context.delete_export_entry( … … 1987 2027 grok.template('certificatemanagepage') 1988 2028 taboneactions = [_('Save'),_('Cancel')] 1989 tabtwoactions = [_('Add c ourse referrer'),1990 _('Remove selected c ourse referrers'),_('Cancel')]2029 tabtwoactions = [_('Add certificate course'), 2030 _('Remove selected certificate courses'),_('Cancel')] 1991 2031 tabthreeactions1 = [_('Remove selected local roles')] 1992 2032 tabthreeactions2 = [_('Add local role')] … … 2011 2051 return msave(self, **data) 2012 2052 2013 @jsaction(_('Remove selected c ourse referrers'))2053 @jsaction(_('Remove selected certificate courses')) 2014 2054 def delCertificateCourses(self, **data): 2015 2055 delSubobjects(self, redirect='@@manage', tab='2') 2016 2056 return 2017 2057 2018 @action(_('Add c ourse referrer'), validator=NullValidator)2058 @action(_('Add certificate course'), validator=NullValidator) 2019 2059 def addCertificateCourse(self, **data): 2020 2060 self.redirect(self.url(self.context, 'addcertificatecourse')) … … 2053 2093 form_fields = grok.AutoFields(ICertificateCourseAdd) 2054 2094 pnav = 1 2055 label = _('Add c ourse referrer')2056 2057 @action(_('Add c ourse referrer'))2095 label = _('Add certificate course') 2096 2097 @action(_('Add certificate course')) 2058 2098 def addCertcourse(self, **data): 2059 2099 try: 2060 self.context.addC ourseRef(**data)2100 self.context.addCertCourse(**data) 2061 2101 except KeyError: 2062 self.status = self.flash(_('The chosen c ourse referreris already '2102 self.status = self.flash(_('The chosen certificate course is already ' 2063 2103 'part of this certificate.')) 2064 2104 return 2065 2105 self.status = self.flash( 2066 _(" Course referrer${a}_${b} added.",2106 _("certificate course ${a}_${b} added.", 2067 2107 mapping = {'a': data['course'].code, 'b': data['level']})) 2068 2108 code = "%s_%s" % (data['course'].code, data['level']) … … 2105 2145 grok.require('waeup.manageAcademics') 2106 2146 form_fields = grok.AutoFields(ICertificateCourse) 2107 label = _('Edit c ourse referrer')2147 label = _('Edit certificate course') 2108 2148 pnav = 1 2109 2149 … … 2118 2158 old_level = self.context.level 2119 2159 data['course'] = self.context.course 2120 parent.addC ourseRef(**data)2121 parent.delC ourseRef(data['course'].code, level=old_level)2160 parent.addCertCourse(**data) 2161 parent.delCertCourse(data['course'].code, level=old_level) 2122 2162 self.flash(_('Form has been saved.')) 2123 2163 old_code = "%s_%s" % (data['course'].code, old_level) … … 2178 2218 return None 2179 2219 2180 @action(_(' Get login credentials'), style='primary')2220 @action(_('Send login credentials to email address'), style='primary') 2181 2221 def request(self, **data): 2182 2222 if not self.captcha_result.is_valid: … … 2193 2233 # Change password 2194 2234 kofa_utils = getUtility(IKofaUtils) 2195 pwd = kofa_utils.genPassword() 2196 IUserAccount(user).setPassword(pwd) 2197 # Send email with new redentials 2198 msg = _('You have successfully changed your password for the') 2199 login_url = self.url(grok.getSite(), 'login') 2235 password = kofa_utils.genPassword() 2236 mandate = PasswordMandate() 2237 mandate.params['password'] = password 2238 mandate.params['user'] = user 2239 site = grok.getSite() 2240 site['mandates'].addMandate(mandate) 2241 # Send email with credentials 2242 args = {'mandate_id':mandate.mandate_id} 2243 mandate_url = self.url(site) + '/mandate?%s' % urlencode(args) 2244 url_info = u'Confirmation link: %s' % mandate_url 2245 msg = _('You have successfully requested a password for the') 2200 2246 success = kofa_utils.sendCredentials( 2201 IUserAccount(user),p wd,login_url,msg)2247 IUserAccount(user),password,url_info,msg) 2202 2248 if success: 2203 2249 self.flash(_('An email with your user name and password ' + -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pdf.py
r8257 r9209 83 83 84 84 Main things fixed here: 85 85 If html code: 86 86 - remove newlines (not visible in HTML but visible in PDF) 87 87 - add <br> tags after <div> (as divs break lines in HTML but not in PDF) 88 If not html code: 89 - just replace newlines by <br> tags 88 90 """ 89 # Add br tag if widgets contain div tags 90 # which are not supported by reportlab 91 html = html.replace('</div>', '</div><br />') 92 html = html.replace('\n', '') 91 if '</' in html: 92 # Add br tag if widgets contain div tags 93 # which are not supported by reportlab 94 html = html.replace('</div>', '</div><br />') 95 html = html.replace('\n', '') 96 else: 97 html = html.replace('\n', '<br />') 93 98 return html 94 99 … … 265 270 target_language=lang) 266 271 f_label = Paragraph(f_label, ENTRY1_STYLE) 267 f_text = format_html(widget()) 272 f_text = translate(widget(), domain, target_language=lang) 273 f_text = format_html(f_text) 274 if f_text: 275 hint = ' <font size=9>' + widget.hint + '</font>' 276 f_text = f_text + hint 268 277 f_text = Paragraph(f_text, ENTRY1_STYLE) 269 278 table_data.append([f_label,f_text]) -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/datatable.js
r7811 r9209 1 1 $(document).ready(function(){ 2 $('.dataTable').dataTable(); 2 $('.dataTable').dataTable(); 3 4 $('.dataTableFiles').dataTable( { 5 "aaSorting": [[ 2, "desc" ]], 6 } ); 7 3 8 $('.dataTableManage').dataTable( { 4 9 "aaSorting": [[ 1, "asc" ]], 5 10 "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }] 6 11 } ); 12 13 $('.dataTableManageFiles').dataTable( { 14 "aaSorting": [[ 3, "desc" ]], 15 "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }] 16 } ); 17 18 7 19 }); 8 20 -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/jquery.dataTables.min.js
r6820 r9209 15 15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 16 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. 17 * 18 * Customized by Henrik Bettermann: this.aLengthMenu, this._iDisplayLength, this._iDisplayEnd 19 * 17 20 */ 18 21 (function(j,ra,p){j.fn.dataTableSettings=[];var D=j.fn.dataTableSettings;j.fn.dataTableExt={};var n=j.fn.dataTableExt;n.sVersion="1.7.6";n.sErrMode="alert";n.iApiIndex=0;n.oApi={};n.afnFiltering=[];n.aoFeatures=[];n.ofnSearch={};n.afnSortData=[];n.oStdClasses={sPagePrevEnabled:"paginate_enabled_previous",sPagePrevDisabled:"paginate_disabled_previous",sPageNextEnabled:"paginate_enabled_next",sPageNextDisabled:"paginate_disabled_next",sPageJUINext:"",sPageJUIPrev:"",sPageButton:"paginate_button",sPageButtonActive:"paginate_active", … … 38 41 [];this.aoColumns=[];this.iNextId=0;this.asDataSearch=[];this.oPreviousSearch={sSearch:"",bRegex:false,bSmart:true};this.aoPreSearchCols=[];this.aaSorting=[[0,"asc",0]];this.aaSortingFixed=null;this.asStripClasses=[];this.asDestoryStrips=[];this.sDestroyWidth=0;this.fnFooterCallback=this.fnHeaderCallback=this.fnRowCallback=null;this.aoDrawCallback=[];this.fnInitComplete=null;this.sTableId="";this.nTableWrapper=this.nTBody=this.nTFoot=this.nTHead=this.nTable=null;this.bInitialised=false;this.aoOpenRows= 39 42 [];this.sDom="lfrtip";this.sPaginationType="two_button";this.iCookieDuration=7200;this.sCookiePrefix="SpryMedia_DataTables_";this.fnCookieCallback=null;this.aoStateSave=[];this.aoStateLoad=[];this.sAjaxSource=this.oLoadedState=null;this.bAjaxDataGet=true;this.fnServerData=function(a,b,c){j.ajax({url:a,data:b,success:c,dataType:"json",cache:false,error:function(d,f){f=="parsererror"&&alert("DataTables warning: JSON data from server could not be parsed. This is caused by a JSON formatting error.")}})}; 40 this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[10,25,50,100,1000,5000];this.bDrawing=this.iDraw=0;this.iDrawError=-1;this._iDisplayLength=10 ;this._iDisplayStart=0;this._iDisplayEnd=10;this._iRecordsDisplay=this._iRecordsTotal=0;this.bJUI=false;this.oClasses=n.oStdClasses;this.bSorted=this.bFiltered=false;this.oInit=null}function r(a){return function(){var b=[A(this[n.iApiIndex])].concat(Array.prototype.slice.call(arguments));43 this.fnFormatNumber=function(a){if(a<1E3)return a;else{var b=a+"";a=b.split("");var c="";b=b.length;for(var d=0;d<b;d++){if(d%3===0&&d!==0)c=","+c;c=a[b-d-1]+c}}return c};this.aLengthMenu=[10,25,50,100,1000,5000];this.bDrawing=this.iDraw=0;this.iDrawError=-1;this._iDisplayLength=1000;this._iDisplayStart=0;this._iDisplayEnd=1000;this._iRecordsDisplay=this._iRecordsTotal=0;this.bJUI=false;this.oClasses=n.oStdClasses;this.bSorted=this.bFiltered=false;this.oInit=null}function r(a){return function(){var b=[A(this[n.iApiIndex])].concat(Array.prototype.slice.call(arguments)); 41 44 return n.oApi[a].apply(this,b)}}function s(a){var b,c;if(a.bInitialised===false)setTimeout(function(){s(a)},200);else{sa(a);U(a);K(a,true);a.oFeatures.bAutoWidth&&$(a);b=0;for(c=a.aoColumns.length;b<c;b++)if(a.aoColumns[b].sWidth!==null)a.aoColumns[b].nTh.style.width=v(a.aoColumns[b].sWidth);if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();E(a);C(a)}if(a.sAjaxSource!==null&&!a.oFeatures.bServerSide)a.fnServerData.call(a.oInstance,a.sAjaxSource,[],function(d){for(b=0;b<d.aaData.length;b++)u(a, 42 45 d.aaData[b]);a.iInitDisplayStart=a._iDisplayStart;if(a.oFeatures.bSort)O(a);else{a.aiDisplay=a.aiDisplayMaster.slice();E(a);C(a)}K(a,false);w(a,d)});else if(!a.oFeatures.bServerSide){K(a,false);w(a)}}}function w(a,b){a._bInitComplete=true;if(typeof a.fnInitComplete=="function")typeof b!="undefined"?a.fnInitComplete.call(a.oInstance,a,b):a.fnInitComplete.call(a.oInstance,a)}function y(a,b,c){o(a.oLanguage,b,"sProcessing");o(a.oLanguage,b,"sLengthMenu");o(a.oLanguage,b,"sEmptyTable");o(a.oLanguage, -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/actionbutton.pt
r7459 r9209 1 1 <a class="btn actionbar" tal:condition="viewlet/target_url" 2 tal:attributes="href viewlet/target_url ">2 tal:attributes="href viewlet/target_url; onclick viewlet/onclick"> 3 3 <img src="" alt="edit" 4 4 tal:attributes="src viewlet/icon_url; -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/certificatemanagepage.pt
r7811 r9209 4 4 <ul class="tabs" data-tabs="tabs"> 5 5 <li tal:attributes="class view/tab1"><a href="#tab-1" i18n:translate="">Settings</a></li> 6 <li tal:attributes="class view/tab2"><a href="#tab-2" i18n:translate="">C ourse Referrers</a></li>6 <li tal:attributes="class view/tab2"><a href="#tab-2" i18n:translate="">Certificate Courses</a></li> 7 7 <li tal:attributes="class view/tab3"><a href="#tab-3" i18n:translate="">Local Roles</a></li> 8 8 </ul> … … 24 24 </div> 25 25 <div id="tab-2" tal:attributes="class view/tab2"> 26 <h3 i18n:translate="">Course Referrers</h3> 26 <h3> 27 <span tal:content="context/__name__">Code</span> 28 <span i18n:domain="waeup.kofa" i18n:translate="">Courses</span> 29 </h3> 27 30 <table class="display dataTableManage"> 28 31 <thead> 29 32 <tr> 30 <th> </th><th i18n:translate="">Level</th> 31 <th i18n:translate="">Semester</th><th i18n:translate="">Referrer</th> 32 <th i18n:translate="">Course</th><th i18n:translate="">Title</th> 33 <th> </th> 34 <th i18n:translate="">Level</th> 35 <th i18n:translate="">Semester</th> 36 <th i18n:translate="">Cert. Course</th> 37 <th i18n:translate="">Dep. Course</th> 38 <th i18n:translate="">Title</th> 33 39 <th i18n:translate="">Mandatory</th> 34 40 </tr> … … 37 43 <tr tal:repeat="cc context/values" class="gradeC"> 38 44 <td> 39 <input type="checkbox" 40 name="val_id" 45 <input type="checkbox" name="val_id" 41 46 tal:attributes="value cc/__name__" /> 42 47 </td> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/certificatepage.pt
r7811 r9209 20 20 <h3> 21 21 <span tal:content="context/__name__">Code</span> 22 <span i18n:domain="waeup.kofa" i18n:translate="">Course Referrers</span>22 <span i18n:domain="waeup.kofa" i18n:translate="">Courses</span> 23 23 </h3> 24 24 <br /> … … 26 26 <thead> 27 27 <tr> 28 <th i18n:translate="">Level</th><th i18n:translate="">Semester</th> 29 <th i18n:translate="">Referrer</th><th i18n:translate="">Course</th> 30 <th i18n:translate="">Title</th><th i18n:translate="">Mandatory</th> 28 <th i18n:translate="">Level</th> 29 <th i18n:translate="">Semester</th> 30 <th i18n:translate="">Cert. Course</th> 31 <th i18n:translate="">Dep. Course</th> 32 <th i18n:translate="">Title</th> 33 <th i18n:translate="">Mandatory</th> 31 34 </tr> 32 35 </thead> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenterpage.pt
r8366 r9209 11 11 <form action="." tal:attributes="action request/URL" method="post" 12 12 i18n:domain="waeup.kofa" enctype="multipart/form-data"> 13 <table i18n:domain="waeup.kofa" class="display dataTableManage ">13 <table i18n:domain="waeup.kofa" class="display dataTableManageFiles"> 14 14 <thead> 15 15 <tr> 16 16 <th></th> 17 17 <th i18n:translate="">File</th> 18 <th i18n:translate=""> Size</th>18 <th i18n:translate="">Datasets</th> 19 19 <th i18n:translate="">Upload Date</th> 20 20 </tr> 21 21 </thead> 22 22 <tbody> 23 <tr tal:repeat="file context/get Files" class="gradeC">23 <tr tal:repeat="file context/getPendingFiles" class="gradeC"> 24 24 <td> 25 25 <input type="checkbox" name="val_id" … … 28 28 <td><a tal:attributes="href python: 'download?filename=' + file.name" 29 29 tal:content="file/name">FILENAME</a></td> 30 <td tal:content=" file/size">12 k</td>30 <td tal:content="python: file.lines - 1">100</td> 31 31 <td tal:content="file/uploaddate">Mar 12, 2008</td> 32 32 </tr> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenteruploadpage.pt
r7705 r9209 9 9 </div> 10 10 </form> 11 12 <br /><br /> 13 14 <h2 i18n:translate="">Available Processors (Importers)</h2> 15 16 <table i18n:domain="waeup.kofa"> 17 <thead> 18 <tr> 19 <th i18n:translate="">Processor</th> 20 <th i18n:translate="">Required Schema Fields</th> 21 <th i18n:translate="">Optional Schema Fields</th> 22 <th i18n:translate="">Non-Schema Fields</th> 23 <th i18n:translate="">CSV Skeleton File</th> 24 </tr> 25 </thead> 26 <tr tal:repeat="importer view/getImporters"> 27 <td tal:content="importer/title"></td> 28 <td nowrap> 29 <span tal:repeat="field importer/fields"> 30 <tal:schemafield condition="field/f_type"> 31 <tal:required condition="field/f_required"> 32 <span tal:replace="field/f_name"></span> 33 (<span tal:replace="field/f_type"></span>) 34 <br /> 35 </tal:required> 36 </tal:schemafield> 37 </span> 38 </td> 39 <td nowrap> 40 <span tal:repeat="field importer/fields"> 41 <tal:schemafield condition="field/f_type"> 42 <tal:notrequired condition="not:field/f_required"> 43 <span tal:replace="field/f_name"></span> 44 (<span tal:replace="field/f_type"></span>) 45 <br /> 46 </tal:notrequired> 47 </tal:schemafield> 48 </span> 49 </td> 50 <td> 51 <span tal:repeat="field importer/fields"> 52 <tal:extrafield condition="not:field/f_type"> 53 <span tal:replace="field/f_name"></span> 54 <br /> 55 </tal:extrafield> 56 </span> 57 </td> 58 59 <td> 60 <a i18n:translate="" 61 tal:attributes="href python: 'skeleton?name=' + importer['name']">Download</a> 62 </td> 63 </tr> 64 </table> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/loginpage.pt
r8777 r9209 37 37 If you are having trouble logging in, make sure to enable cookies in your web browser. 38 38 </p> 39 <p i18n:translate="login_trouble2" >39 <p i18n:translate="login_trouble2" tal:condition="python:False"> 40 40 You don't have an account because you are a fresh student, or your student record has just been created? 41 Acquire a Password Access Code (PWD) and inititialize your student account 42 <strong><a href ="setpassword"> here</a></strong>. 41 Acquire a Password Activation Code (PWD) and inititialize your student account 42 <strong><a href ="setpassword"> here</a></strong>. 43 </p> 44 <p i18n:translate="login_trouble4"> 45 You don't have an account because you are a fresh student, or your student record has just been created? 46 Inititialize your student account <strong><a href="requestpw"> here</a></strong>. 43 47 </p> 44 48 <p i18n:translate="login_trouble3"> Or simply forgot your student id, application id or password? Then request a new password -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/widgets.pt
r8045 r9209 18 18 <div tal:content="structure widget/error">ERROR</div> 19 19 </tal:error> 20 <tal:hint tal:condition="widget/hint"> 20 <tal:hint 21 tal:condition="python: widget.hint and not getattr(view,'hide_hint',False)"> 21 22 <div class="hint" tal:content="structure widget/hint">HINT</div> 22 23 </tal:hint> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/tests/test_browser.py
r9166 r9209 21 21 import shutil 22 22 import tempfile 23 import pytz24 from datetime import datetime, timedelta25 from StringIO import StringIO26 23 import os 27 import grok28 24 from zc.async.testing import wait_for_result 29 from zope.event import notify 30 from zope.component import createObject, queryUtility, getUtility 25 from zope.component import createObject, getUtility 31 26 from zope.component.hooks import setSite, clearSite 32 from zope.catalog.interfaces import ICatalog33 27 from zope.security.interfaces import Unauthorized 34 from zope.securitypolicy.interfaces import IPrincipalRoleManager35 28 from zope.testbrowser.testing import Browser 36 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState37 29 from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase 38 30 from waeup.kofa.app import University … … 41 33 from waeup.kofa.university.faculty import Faculty 42 34 from waeup.kofa.university.department import Department 43 44 45 46 35 47 36 SAMPLE_FILE = os.path.join(os.path.dirname(__file__), 'test_file.csv') … … 90 79 self.app['faculties']['fac1']['dep1'].courses.addCourse( 91 80 self.course) 92 self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addC ourseRef(81 self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse( 93 82 self.course, level=100) 94 83 … … 127 116 self.assertEqual(self.browser.headers['Status'], '200 Ok') 128 117 self.assertEqual(self.browser.url, self.datacenter_path) 129 self.browser.getLink("Upload CSV file").click()118 self.browser.getLink("Upload data").click() 130 119 file = open(SAMPLE_FILE) 131 120 ctrl = self.browser.getControl(name='uploadfile:file') … … 181 170 self.assertEqual(self.browser.headers['Status'], '200 Ok') 182 171 self.assertEqual(self.browser.url, self.datacenter_path) 183 self.browser.getLink("Export CSV file").click()172 self.browser.getLink("Export data").click() 184 173 self.browser.getControl(name="exporter").value = ['faculties'] 185 174 self.browser.getControl("Create CSV file").click() … … 204 193 # ...we can download the result 205 194 self.browser.getControl("Download").click() 206 self.assertEqual(self.browser.headers[' Content-Type'],195 self.assertEqual(self.browser.headers['content-type'], 207 196 'text/csv; charset=UTF-8') 197 self.assertEqual(self.browser.headers['content-disposition'], 198 'attachment; filename="WAeUP.Kofa_faculties.csv') 208 199 self.assertEqual(self.browser.contents, 209 'code,title,title_prefix\r\nfac1,Unnamed Faculty,faculty\r\n') 200 'code,title,title_prefix,users_with_local_roles\r\n' 201 'fac1,Unnamed Faculty,faculty,[]\r\n') 210 202 211 203 # after download, the job and the result file are removed … … 229 221 self.assertTrue('Discarded export result' in self.browser.contents) 230 222 return 223 224 def test_skeleton_download(self): 225 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 226 self.browser.open(self.datacenter_path) 227 self.browser.getLink("Upload data").click() 228 self.assertTrue( 229 '<a href="skeleton?name=facultyprocessor">Download</a>' 230 in self.browser.contents) 231 self.browser.getLink(url='skeleton?name=facultyprocessor').click() 232 self.assertEqual(self.browser.headers['Status'], '200 Ok') 233 self.assertEqual(self.browser.headers['Content-Type'], 234 'text/csv; charset=UTF-8') 235 self.assertEqual(self.browser.contents, 236 'code,local_roles,title,title_prefix\r\n') 237 return -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/tests/test_permissions.py
r7811 r9209 91 91 cert.code = 'cert1' 92 92 dept.certificates.addCertificate(cert) 93 cert.addC ourseRef(course)93 cert.addCertCourse(course) 94 94 95 95 self.browser = Browser() -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/viewlets.py
r8387 r9209 66 66 """A base for action buttons. 67 67 68 An action button provides an icon, some text and links to a 69 target. If you want to set a different text, icon or target name 68 An action button provides an icon, some text, links to a 69 target and optionally an onclick event handler. 70 If you want to set a different text, icon or target name 70 71 for some active button below, just override the approriate 71 72 attribute in the concerned viewlet. … … 82 83 * ``target_url`` 83 84 The URL of the link target. 85 86 * ``onclick`` 87 An onclick Javascript event handler. 84 88 85 89 """ … … 143 147 return self.view.url(self.view.context, self.target) 144 148 149 @property 150 def onclick(self): 151 """Onclick event... 152 """ 153 return 154 145 155 class PlainActionButton(ActionButton): 146 156 """A base for action buttons without image … … 386 396 grok.require('waeup.manageDataCenter') 387 397 text = _('Edit settings') 398 grok.order(1) 388 399 389 400 class ManageFacultiesContainerActionButton(ManageActionButton): … … 456 467 grok.context(ICertificateCourse) 457 468 grok.view(CertificateCoursePage) 458 text = _('Edit course referrer') 459 460 # 461 # Add actions... 462 # 469 text = _('Edit certificate course') 463 470 464 471 class AddUserActionButton(AddActionButton): … … 468 475 text = _('Add user') 469 476 470 # 471 # Actions with a 'browse' icon... 472 # 473 class BrowseActionButton(ActionButton): 474 grok.baseclass() 475 grok.context(IKofaObject) 476 grok.template('actionbutton') 477 grok.viewletmanager(ActionBar) 477 class BrowseDatacenterLogs(ActionButton): 478 grok.context(IDataCenter) 478 479 grok.require('waeup.manageDataCenter') 479 icon = 'actionicon_manage.png' # File must exist in static/480 target = '@@show' # link to this viewname.481 text = _('Show logs') # Text to display on the button482 483 class BrowseDatacenterLogs(BrowseActionButton):484 grok.context(IDataCenter)485 480 grok.view(DatacenterPage) 486 grok.order( 4)481 grok.order(2) 487 482 icon = 'actionicon_info.png' 488 483 target = '@@logs' 489 484 text = _('Show logs') 490 485 491 # 492 # Misc. buttons... 493 # 486 class UploadCSVButton(ActionButton): 487 grok.context(IDataCenter) 488 grok.view(DatacenterPage) 489 grok.require('waeup.manageDataCenter') 490 grok.order(3) 491 icon = 'actionicon_up.png' 492 target = '@@upload' 493 text = _('Upload data') 494 494 495 class BatchOpButton(ActionButton): 495 496 grok.context(IDataCenter) 496 497 grok.view(DatacenterPage) 497 498 grok.require('waeup.importData') 498 grok.order( 6)499 grok.order(4) 499 500 icon = 'actionicon_gear.png' 500 501 target = '@@import1' 501 text = _(' Batch processing')502 503 class UploadCSVButton(ActionButton):502 text = _('Process data') 503 504 class ExportCSVButton(ActionButton): 504 505 grok.context(IDataCenter) 505 506 grok.view(DatacenterPage) 506 507 grok.require('waeup.manageDataCenter') 507 508 grok.order(5) 508 icon = 'actionicon_up.png'509 target = '@@upload'510 text = _('Upload CSV file')511 512 class ExportCSVButton(ActionButton):513 grok.context(IDataCenter)514 grok.view(DatacenterPage)515 grok.require('waeup.manageDataCenter')516 grok.order(7)517 509 icon = 'actionicon_down.png' 518 510 target = '@@export' 519 text = _('Export CSV file') 511 text = _('Export data') 512 513 class BrowseFinishedFiles(ActionButton): 514 grok.context(IDataCenter) 515 grok.require('waeup.manageDataCenter') 516 grok.view(DatacenterPage) 517 grok.order(6) 518 icon = 'actionicon_finished.png' 519 target = '@@processed' 520 text = _('View processed files') 520 521 521 522 #
Note: See TracChangeset for help on using the changeset viewer.