- Timestamp:
- 21 Sep 2012, 08:19:35 (12 years ago)
- Location:
- main/waeup.kofa/branches/uli-zc-async
- Files:
-
- 5 deleted
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/branches/uli-zc-async
- Property svn:mergeinfo changed
/main/waeup.kofa/branches/uli-async-update removed /main/waeup.kofa/branches/uli-autoinclude-less removed /main/waeup.kofa/trunk removed
- Property svn:mergeinfo changed
-
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/batchprocessing.txt
r9209 r9211 75 75 76 76 >>> import cStringIO 77 >>> browser.getLink('Upload data').click()77 >>> browser.getLink('Upload CSV file').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(' Process data').click()86 >>> browser.getLink('Batch processing').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 'Hostel Processor', 100 'Student Payment Processor', 'Student Processor', 99 'Payment Processor', 'Student Processor', 101 100 'StudentStudyCourse Processor (update only)', 102 'StudentStudyLevel Processor', 103 'User Processor', 104 'Verdict Processor (update only)'] 101 'StudentStudyLevel Processor', 'Verdict Processor (update only)'] 105 102 106 103 >>> importerselect.getControl('Faculty Processor').selected = True … … 178 175 179 176 >>> import cStringIO 180 >>> browser.getLink('Upload data').click()177 >>> browser.getLink('Upload CSV file').click() 181 178 >>> filecontents = cStringIO.StringIO( 182 179 ... open('departments.csv', 'rb').read()) … … 187 184 Step 1: start batch processing: 188 185 189 >>> browser.getLink(' Process data').click()186 >>> browser.getLink('Batch processing').click() 190 187 >>> button = lookup_submit_value( 191 188 ... 'select', 'departments_zope.mgr.csv', browser) … … 243 240 244 241 >>> import cStringIO 245 >>> browser.getLink('Upload data').click()242 >>> browser.getLink('Upload CSV file').click() 246 243 >>> filecontents = cStringIO.StringIO( 247 244 ... open('courses.csv', 'rb').read()) … … 252 249 Step 1: start batch processing: 253 250 254 >>> browser.getLink(' Process data').click()251 >>> browser.getLink('Batch processing').click() 255 252 >>> button = lookup_submit_value( 256 253 ... 'select', 'courses_zope.mgr.csv', browser) … … 308 305 309 306 >>> import cStringIO 310 >>> browser.getLink('Upload data').click()307 >>> browser.getLink('Upload CSV file').click() 311 308 >>> filecontents = cStringIO.StringIO( 312 309 ... open('certificates.csv', 'rb').read()) … … 317 314 Step 1: start batch processing: 318 315 319 >>> browser.getLink(' Process data').click()316 >>> browser.getLink('Batch processing').click() 320 317 >>> button = lookup_submit_value( 321 318 ... 'select', 'certificates_zope.mgr.csv', browser) … … 374 371 375 372 >>> import cStringIO 376 >>> browser.getLink('Upload data').click()373 >>> browser.getLink('Upload CSV file').click() 377 374 >>> filecontents = cStringIO.StringIO( 378 375 ... open('mycertcourses.csv', 'rb').read()) … … 383 380 Step 1: start batch processing: 384 381 385 >>> browser.getLink(' Process data').click()382 >>> browser.getLink('Batch processing').click() 386 383 >>> button = lookup_submit_value( 387 384 ... 'select', 'mycertcourses_zope.mgr.csv', browser) … … 423 420 ...File:...mycertcourses_zope.mgr.csv... 424 421 425 Batch processing users426 ======================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,roles434 ... uli,Uli Fouquet,Chief Developer,uli@abc.de,+49-234-567435 ... henrik,Henrik Bettermann,Admin,henrik@abc.de,+49-234-567,['waeup.PortalManager']436 ... """)437 438 Upload the file:439 440 >>> import cStringIO441 >>> 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 = True459 >>> modeselect = browser.getControl(name='mode')460 >>> modeselect.getControl(value='create').selected = True461 >>> browser.getControl('Proceed to step 3').click()462 463 Step 3: Fix headerlines464 465 We get informed that there are no problems with the current header:466 467 >>> print browser.contents468 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"469 ...470 Header fields OK471 ...472 473 The submit button is enabled:474 475 >>> browser.getControl('Perform import').disabled476 False477 478 >>> browser.getControl('Perform import').click()479 480 Step 4: See import results481 482 The import was successful:483 484 >>> print browser.contents485 <!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...489 422 490 423 Pending files … … 511 444 512 445 >>> import cStringIO 513 >>> browser.getLink('Upload data').click()446 >>> browser.getLink('Upload CSV file').click() 514 447 >>> filecontents = cStringIO.StringIO( 515 448 ... open('newfaculties.csv', 'rb').read()) … … 520 453 Step 1: start batch processing: 521 454 522 >>> browser.getLink(' Process data').click()455 >>> browser.getLink('Batch processing').click() 523 456 >>> button = lookup_submit_value( 524 457 ... 'select', 'newfaculties_zope.mgr.csv', browser) … … 582 515 583 516 >>> browser.open('http://localhost/app/datacenter') 584 >>> browser.getLink(' Process data').click()517 >>> browser.getLink('Batch processing').click() 585 518 >>> button = lookup_submit_value( 586 519 ... 'select', 'newfaculties_zope.mgr.create.pending.csv', browser) … … 618 551 >>> sorted(os.listdir(dc_path + '/finished')) 619 552 ['certificates_zope.mgr.create.finished.csv', ..., 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 553 'newfaculties_zope.mgr.create.finished.csv', 554 'newfaculties_zope.mgr.csv'] 555 628 556 629 557 Log Files -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/browser.txt
r9209 r9211 81 81 >>> browser.getControl(name="form.identifier").value = 'forgetful' 82 82 >>> browser.getControl(name="form.email").value = 'aa@aa.ng' 83 >>> browser.getControl(" Sendlogin credentials").click()83 >>> browser.getControl("Get 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 ertificate course`` action button near top.1002 Each certificate provides a ``Add course referrer`` 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 ertificate course').click()1008 >>> browser.getControl('Add course referrer').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 ertificate course').click()1027 >>> browser.getControl('Add course referrer').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 ertificate course').click()1040 >>> browser.getControl('Add course referrer').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 ertificate course').click()1045 >>> 'The chosen c ertificate courseis already' in browser.contents1044 >>> browser.getControl('Add course referrer').click() 1045 >>> 'The chosen course referrer 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 ertificate course').click()1065 >>> browser.getLink('Edit course referrer').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 ertificate course').click()1090 >>> browser.getLink('Edit course referrer').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 ertificate courses').click()1127 >>> browser.getControl('Remove selected course referrers').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 ertificate courses').click()1132 >>> browser.getControl('Remove selected course referrers').click() 1133 1133 >>> 'Successfully removed: COURSE1_200' in browser.contents 1134 1134 True … … 1218 1218 page: 1219 1219 1220 >>> browser.getLink('Upload data').click()1220 >>> browser.getLink('Upload CSV file').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
r9209 r9211 191 191 grok.baseclass() 192 192 template = default_waeup_display_template 193 hide_hint = True194 193 195 194 class KofaEditFormPage(UtilityView,EditForm): … … 216 215 if self.widgets.get('perm_address'): 217 216 self.widgets['perm_address'].cssClass = 'span8' 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 217 self.widgets['perm_address'].height = 10 225 218 if self.widgets.get('description'): 226 219 self.widgets['description'].cssClass = 'span12' … … 313 306 else: 314 307 return None 315 316 def formatTZDate(self,datetimeobj):317 if isinstance(datetimeobj, datetime):318 tz = getUtility(IKofaUtils).tzinfo319 date = to_timezone(320 datetimeobj, tz).strftime("%d/%m/%Y")321 return date322 else:323 return None324 308 325 309 def update(self): -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pages.py
r9209 r9211 18 18 """ Viewing components for Kofa objects. 19 19 """ 20 import copy 20 21 import csv 21 22 import grok … … 23 24 import re 24 25 import sys 25 from urllib import urlencode 26 import time 27 import re 26 28 from zope import schema 27 29 from zope.authentication.interfaces import ( … … 32 34 getUtilitiesFor, 33 35 ) 36 #from zope.component.interfaces import Invalid 34 37 from zope.event import notify 35 from zope.securitypolicy.interfaces import IPrincipalRoleManager 38 from zope.securitypolicy.interfaces import ( 39 IPrincipalRoleManager, IPrincipalRoleMap) 36 40 from zope.session.interfaces import ISession 37 from zope.password.interfaces import IPasswordManager38 41 from waeup.kofa.browser.layout import ( 39 42 KofaPage, KofaForm, KofaEditFormPage, KofaAddFormPage, … … 46 49 from waeup.kofa.browser.layout import jsaction, action, UtilityView 47 50 from waeup.kofa.browser.resources import ( 48 warning, tabs, datatable)51 warning, datepicker, tabs, datatable, page_reloader, page_not_reloader) 49 52 from waeup.kofa.interfaces import MessageFactory as _ 50 53 from waeup.kofa.interfaces import( … … 61 64 from waeup.kofa.university.vocabularies import course_levels 62 65 from waeup.kofa.authentication import LocalRoleSetEvent 66 #from waeup.kofa.widgets.restwidget import ReSTDisplayWidget 63 67 from waeup.kofa.widgets.htmlwidget import HTMLDisplayWidget 64 from waeup.kofa. utils.helpers import get_user_account65 from waeup.kofa. mandates.mandate import PasswordMandate68 from waeup.kofa.authentication import get_principal_role_manager 69 from waeup.kofa.utils.helpers import get_user_account, msave 66 70 67 71 grok.context(IKofaObject) … … 152 156 return 153 157 154 # Save function used for save methods in pages155 def msave(view, **data):156 changed_fields = view.applyData(view.context, **data)157 # Turn list of lists into single list158 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 return166 167 158 # 168 159 # Login/logout and language switch pages... … … 201 192 self.redirect(self.camefrom) 202 193 return 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.')) 194 self.flash(_('You entered wrong credentials.')) 215 195 216 196 … … 392 372 def entries(self): 393 373 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 return 388 cat = queryUtility(ICatalog, name='%s_catalog' % ctlg) 389 if cat is None: 390 self.flash('%s_catalog does not exist' % ctlg) 391 return 392 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 return 400 401 def render(self): 402 self.redirect(self.url(self.context, '@@index')) 403 return 394 404 395 405 # … … 791 801 def delFiles(self, **data): 792 802 form = self.request.form 803 logger = self.context.logger 793 804 if form.has_key('val_id'): 794 805 child_id = form['val_id'] … … 815 826 return 816 827 817 class DatacenterFinishedPage(KofaEditFormPage):818 grok.context(IDataCenter)819 grok.name('processed')820 grok.require('waeup.manageDataCenter')821 label = _(u'Processed Files')822 pnav = 0823 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 portal data as CSVfile')832 label = _(u'Upload file') 833 833 pnav = 0 834 834 upload_button =_(u'Upload') … … 849 849 self.flash(_("Only csv files are allowed.")) 850 850 return 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) 851 target = os.path.join(self.context.storage, 852 self.getNormalizedFileName(filename)) 860 853 open(target, 'wb').write(uploadfile.read()) 861 854 os.chmod(target, 0664) … … 888 881 return '%s_%s%s' % (base, filtered_username, ext.lower()) 889 882 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 911 883 class FileDownloadView(UtilityView, grok.View): 912 884 grok.context(IDataCenter) … … 925 897 'Content-Type', 'text/csv; charset=UTF-8') 926 898 self.response.setHeader( 927 'Content-Disposition:', 'attachment; filename="%s ' %928 self.filename.replace(' finished/',''))899 'Content-Disposition:', 'attachment; filename="%s.csv' % 900 self.filename.replace('.csv','')) 929 901 fullpath = os.path.join(self.context.storage, self.filename) 930 902 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 return942 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_data954 903 955 904 class DatacenterImportStep1(KofaPage): … … 965 914 966 915 def getFiles(self): 967 files = self.context.get PendingFiles(sort='date')916 files = self.context.getFiles(sort='date') 968 917 for file in files: 969 918 name = file.name … … 1189 1138 return False 1190 1139 1140 @property 1141 def nextstep(self): 1142 return self.url(self.context, '@@import4') 1143 1191 1144 def update(self, headerfield=None, back2=None, cancel=None, proceed=None): 1192 1145 datatable.need() … … 1409 1362 string representing the exporter title used when triggering 1410 1363 the export job. 1364 1365 Calling this method also installs a JavaScript page reloader 1366 that reloads the page after some time (1.5 secs), if there is 1367 a running export that is not completed yet. 1368 1369 The method caches results. 1411 1370 """ 1412 1371 if self._running_exports is None: … … 1416 1375 def _getRunningExports(self): 1417 1376 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() 1418 1382 return result 1419 1383 … … 1462 1426 return 1463 1427 result = open(path, 'rb').read() 1464 acronym = grok.getSite()['configuration'].acronym.replace(' ','')1465 filename = "%s_%s" % (acronym, os.path.basename(path))1466 1428 self.response.setHeader( 1467 1429 'Content-Type', 'text/csv; charset=UTF-8') 1468 self.response.setHeader(1469 'Content-Disposition', 'attachment; filename="%s' % filename)1470 1430 # remove job and running_exports entry from context 1471 1431 self.context.delete_export_entry( … … 2027 1987 grok.template('certificatemanagepage') 2028 1988 taboneactions = [_('Save'),_('Cancel')] 2029 tabtwoactions = [_('Add c ertificate course'),2030 _('Remove selected c ertificate courses'),_('Cancel')]1989 tabtwoactions = [_('Add course referrer'), 1990 _('Remove selected course referrers'),_('Cancel')] 2031 1991 tabthreeactions1 = [_('Remove selected local roles')] 2032 1992 tabthreeactions2 = [_('Add local role')] … … 2051 2011 return msave(self, **data) 2052 2012 2053 @jsaction(_('Remove selected c ertificate courses'))2013 @jsaction(_('Remove selected course referrers')) 2054 2014 def delCertificateCourses(self, **data): 2055 2015 delSubobjects(self, redirect='@@manage', tab='2') 2056 2016 return 2057 2017 2058 @action(_('Add c ertificate course'), validator=NullValidator)2018 @action(_('Add course referrer'), validator=NullValidator) 2059 2019 def addCertificateCourse(self, **data): 2060 2020 self.redirect(self.url(self.context, 'addcertificatecourse')) … … 2093 2053 form_fields = grok.AutoFields(ICertificateCourseAdd) 2094 2054 pnav = 1 2095 label = _('Add c ertificate course')2096 2097 @action(_('Add c ertificate course'))2055 label = _('Add course referrer') 2056 2057 @action(_('Add course referrer')) 2098 2058 def addCertcourse(self, **data): 2099 2059 try: 2100 self.context.addC ertCourse(**data)2060 self.context.addCourseRef(**data) 2101 2061 except KeyError: 2102 self.status = self.flash(_('The chosen c ertificate courseis already '2062 self.status = self.flash(_('The chosen course referrer is already ' 2103 2063 'part of this certificate.')) 2104 2064 return 2105 2065 self.status = self.flash( 2106 _(" certificate course${a}_${b} added.",2066 _("Course referrer ${a}_${b} added.", 2107 2067 mapping = {'a': data['course'].code, 'b': data['level']})) 2108 2068 code = "%s_%s" % (data['course'].code, data['level']) … … 2145 2105 grok.require('waeup.manageAcademics') 2146 2106 form_fields = grok.AutoFields(ICertificateCourse) 2147 label = _('Edit c ertificate course')2107 label = _('Edit course referrer') 2148 2108 pnav = 1 2149 2109 … … 2158 2118 old_level = self.context.level 2159 2119 data['course'] = self.context.course 2160 parent.addC ertCourse(**data)2161 parent.delC ertCourse(data['course'].code, level=old_level)2120 parent.addCourseRef(**data) 2121 parent.delCourseRef(data['course'].code, level=old_level) 2162 2122 self.flash(_('Form has been saved.')) 2163 2123 old_code = "%s_%s" % (data['course'].code, old_level) … … 2218 2178 return None 2219 2179 2220 @action(_(' Send login credentials to email address'), style='primary')2180 @action(_('Get login credentials'), style='primary') 2221 2181 def request(self, **data): 2222 2182 if not self.captcha_result.is_valid: … … 2233 2193 # Change password 2234 2194 kofa_utils = getUtility(IKofaUtils) 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') 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') 2246 2200 success = kofa_utils.sendCredentials( 2247 IUserAccount(user),p assword,url_info,msg)2201 IUserAccount(user),pwd,login_url,msg) 2248 2202 if success: 2249 2203 self.flash(_('An email with your user name and password ' + -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pdf.py
r9209 r9211 83 83 84 84 Main things fixed here: 85 If html code: 85 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> tags90 88 """ 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 />') 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', '') 98 93 return html 99 94 … … 270 265 target_language=lang) 271 266 f_label = Paragraph(f_label, ENTRY1_STYLE) 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 267 f_text = format_html(widget()) 277 268 f_text = Paragraph(f_text, ENTRY1_STYLE) 278 269 table_data.append([f_label,f_text]) -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/datatable.js
r9209 r9211 1 1 $(document).ready(function(){ 2 $('.dataTable').dataTable(); 3 4 $('.dataTableFiles').dataTable( { 5 "aaSorting": [[ 2, "desc" ]], 6 } ); 7 2 $('.dataTable').dataTable(); 8 3 $('.dataTableManage').dataTable( { 9 4 "aaSorting": [[ 1, "asc" ]], 10 5 "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }] 11 6 } ); 12 13 $('.dataTableManageFiles').dataTable( {14 "aaSorting": [[ 3, "desc" ]],15 "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }]16 } );17 18 19 7 }); 20 8 -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/jquery.dataTables.min.js
r9209 r9211 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._iDisplayEnd19 *20 17 */ 21 18 (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", … … 41 38 [];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= 42 39 [];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.")}})}; 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=10 00;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));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)); 44 41 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, 45 42 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
r9209 r9211 1 1 <a class="btn actionbar" tal:condition="viewlet/target_url" 2 tal:attributes="href viewlet/target_url ; onclick viewlet/onclick">2 tal:attributes="href viewlet/target_url"> 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
r9209 r9211 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 ertificate Courses</a></li>6 <li tal:attributes="class view/tab2"><a href="#tab-2" i18n:translate="">Course Referrers</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> 27 <span tal:content="context/__name__">Code</span> 28 <span i18n:domain="waeup.kofa" i18n:translate="">Courses</span> 29 </h3> 26 <h3 i18n:translate="">Course Referrers</h3> 30 27 <table class="display dataTableManage"> 31 28 <thead> 32 29 <tr> 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> 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> 39 33 <th i18n:translate="">Mandatory</th> 40 34 </tr> … … 43 37 <tr tal:repeat="cc context/values" class="gradeC"> 44 38 <td> 45 <input type="checkbox" name="val_id" 39 <input type="checkbox" 40 name="val_id" 46 41 tal:attributes="value cc/__name__" /> 47 42 </td> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/certificatepage.pt
r9209 r9211 20 20 <h3> 21 21 <span tal:content="context/__name__">Code</span> 22 <span i18n:domain="waeup.kofa" i18n:translate="">Course s</span>22 <span i18n:domain="waeup.kofa" i18n:translate="">Course Referrers</span> 23 23 </h3> 24 24 <br /> … … 26 26 <thead> 27 27 <tr> 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> 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> 34 31 </tr> 35 32 </thead> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenterpage.pt
r9209 r9211 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 Files">13 <table i18n:domain="waeup.kofa" class="display dataTableManage"> 14 14 <thead> 15 15 <tr> 16 16 <th></th> 17 17 <th i18n:translate="">File</th> 18 <th i18n:translate=""> Datasets</th>18 <th i18n:translate="">Size</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 PendingFiles" class="gradeC">23 <tr tal:repeat="file context/getFiles" 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=" python: file.lines - 1">100</td>30 <td tal:content="file/size">12 k</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
r9209 r9211 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
r9209 r9211 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" tal:condition="python:False">39 <p i18n:translate="login_trouble2"> 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 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>. 41 Acquire a Password Access Code (PWD) and inititialize your student account 42 <strong><a href ="setpassword"> here</a></strong>. 47 43 </p> 48 44 <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
r9209 r9211 18 18 <div tal:content="structure widget/error">ERROR</div> 19 19 </tal:error> 20 <tal:hint 21 tal:condition="python: widget.hint and not getattr(view,'hide_hint',False)"> 20 <tal:hint tal:condition="widget/hint"> 22 21 <div class="hint" tal:content="structure widget/hint">HINT</div> 23 22 </tal:hint> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/tests/test_browser.py
r9209 r9211 21 21 import shutil 22 22 import tempfile 23 import pytz 24 from datetime import datetime, timedelta 25 from StringIO import StringIO 23 26 import os 27 import grok 24 28 from zc.async.testing import wait_for_result 25 from zope.component import createObject, getUtility 29 from zope.event import notify 30 from zope.component import createObject, queryUtility, getUtility 26 31 from zope.component.hooks import setSite, clearSite 32 from zope.catalog.interfaces import ICatalog 27 33 from zope.security.interfaces import Unauthorized 34 from zope.securitypolicy.interfaces import IPrincipalRoleManager 28 35 from zope.testbrowser.testing import Browser 36 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState 29 37 from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase 30 38 from waeup.kofa.app import University … … 33 41 from waeup.kofa.university.faculty import Faculty 34 42 from waeup.kofa.university.department import Department 43 44 45 35 46 36 47 SAMPLE_FILE = os.path.join(os.path.dirname(__file__), 'test_file.csv') … … 79 90 self.app['faculties']['fac1']['dep1'].courses.addCourse( 80 91 self.course) 81 self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addC ertCourse(92 self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCourseRef( 82 93 self.course, level=100) 83 94 … … 116 127 self.assertEqual(self.browser.headers['Status'], '200 Ok') 117 128 self.assertEqual(self.browser.url, self.datacenter_path) 118 self.browser.getLink("Upload data").click()129 self.browser.getLink("Upload CSV file").click() 119 130 file = open(SAMPLE_FILE) 120 131 ctrl = self.browser.getControl(name='uploadfile:file') … … 170 181 self.assertEqual(self.browser.headers['Status'], '200 Ok') 171 182 self.assertEqual(self.browser.url, self.datacenter_path) 172 self.browser.getLink("Export data").click()183 self.browser.getLink("Export CSV file").click() 173 184 self.browser.getControl(name="exporter").value = ['faculties'] 174 185 self.browser.getControl("Create CSV file").click() … … 193 204 # ...we can download the result 194 205 self.browser.getControl("Download").click() 195 self.assertEqual(self.browser.headers[' content-type'],206 self.assertEqual(self.browser.headers['Content-Type'], 196 207 'text/csv; charset=UTF-8') 197 self.assertEqual(self.browser.headers['content-disposition'],198 'attachment; filename="WAeUP.Kofa_faculties.csv')199 208 self.assertEqual(self.browser.contents, 200 'code,title,title_prefix,users_with_local_roles\r\n' 201 'fac1,Unnamed Faculty,faculty,[]\r\n') 209 'code,title,title_prefix\r\nfac1,Unnamed Faculty,faculty\r\n') 202 210 203 211 # after download, the job and the result file are removed … … 221 229 self.assertTrue('Discarded export result' in self.browser.contents) 222 230 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
r9209 r9211 91 91 cert.code = 'cert1' 92 92 dept.certificates.addCertificate(cert) 93 cert.addC ertCourse(course)93 cert.addCourseRef(course) 94 94 95 95 self.browser = Browser() -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/viewlets.py
r9209 r9211 66 66 """A base for action buttons. 67 67 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 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 71 70 for some active button below, just override the approriate 72 71 attribute in the concerned viewlet. … … 83 82 * ``target_url`` 84 83 The URL of the link target. 85 86 * ``onclick``87 An onclick Javascript event handler.88 84 89 85 """ … … 147 143 return self.view.url(self.view.context, self.target) 148 144 149 @property150 def onclick(self):151 """Onclick event...152 """153 return154 155 145 class PlainActionButton(ActionButton): 156 146 """A base for action buttons without image … … 396 386 grok.require('waeup.manageDataCenter') 397 387 text = _('Edit settings') 398 grok.order(1)399 388 400 389 class ManageFacultiesContainerActionButton(ManageActionButton): … … 467 456 grok.context(ICertificateCourse) 468 457 grok.view(CertificateCoursePage) 469 text = _('Edit certificate course') 458 text = _('Edit course referrer') 459 460 # 461 # Add actions... 462 # 470 463 471 464 class AddUserActionButton(AddActionButton): … … 475 468 text = _('Add user') 476 469 477 class BrowseDatacenterLogs(ActionButton): 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) 478 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 button 482 483 class BrowseDatacenterLogs(BrowseActionButton): 478 484 grok.context(IDataCenter) 479 grok.require('waeup.manageDataCenter')480 485 grok.view(DatacenterPage) 481 grok.order( 2)486 grok.order(4) 482 487 icon = 'actionicon_info.png' 483 488 target = '@@logs' 484 489 text = _('Show logs') 490 491 # 492 # Misc. buttons... 493 # 494 class BatchOpButton(ActionButton): 495 grok.context(IDataCenter) 496 grok.view(DatacenterPage) 497 grok.require('waeup.importData') 498 grok.order(6) 499 icon = 'actionicon_gear.png' 500 target = '@@import1' 501 text = _('Batch processing') 485 502 486 503 class UploadCSVButton(ActionButton): … … 488 505 grok.view(DatacenterPage) 489 506 grok.require('waeup.manageDataCenter') 490 grok.order( 3)507 grok.order(5) 491 508 icon = 'actionicon_up.png' 492 509 target = '@@upload' 493 text = _('Upload data') 494 495 class BatchOpButton(ActionButton): 496 grok.context(IDataCenter) 497 grok.view(DatacenterPage) 498 grok.require('waeup.importData') 499 grok.order(4) 500 icon = 'actionicon_gear.png' 501 target = '@@import1' 502 text = _('Process data') 510 text = _('Upload CSV file') 503 511 504 512 class ExportCSVButton(ActionButton): … … 506 514 grok.view(DatacenterPage) 507 515 grok.require('waeup.manageDataCenter') 508 grok.order( 5)516 grok.order(7) 509 517 icon = 'actionicon_down.png' 510 518 target = '@@export' 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') 519 text = _('Export CSV file') 521 520 522 521 #
Note: See TracChangeset for help on using the changeset viewer.