Ignore:
Timestamp:
20 Sep 2012, 08:49:37 (12 years ago)
Author:
uli
Message:

Merge changes from update branch (includes trunk changes until r9107).

Location:
main/waeup.kofa/branches/uli-zc-async
Files:
18 edited
5 copied

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/branches/uli-zc-async

  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/batchprocessing.txt

    r8472 r9209  
    7575
    7676    >>> import cStringIO
    77     >>> browser.getLink('Upload CSV file').click()
     77    >>> browser.getLink('Upload data').click()
    7878    >>> filecontents = cStringIO.StringIO(
    7979    ...   open('faculties.csv', 'rb').read())
     
    8484Step 1: start batch processing:
    8585
    86     >>> browser.getLink('Batch processing').click()
     86    >>> browser.getLink('Process data').click()
    8787    >>> button = lookup_submit_value(
    8888    ...   'select', 'faculties_zope.mgr.csv', browser)
     
    9797    'Course Processor', 'CourseTicket Processor',
    9898    'Department Processor', 'Faculty Processor',
    99     'Payment Processor', 'Student Processor',
     99    'Hostel Processor',
     100    'Student Payment Processor', 'Student Processor',
    100101    'StudentStudyCourse Processor (update only)',
    101     'StudentStudyLevel Processor', 'Verdict Processor (update only)']
     102    'StudentStudyLevel Processor',
     103    'User Processor',
     104    'Verdict Processor (update only)']
    102105
    103106    >>> importerselect.getControl('Faculty Processor').selected = True
     
    175178
    176179    >>> import cStringIO
    177     >>> browser.getLink('Upload CSV file').click()
     180    >>> browser.getLink('Upload data').click()
    178181    >>> filecontents = cStringIO.StringIO(
    179182    ...   open('departments.csv', 'rb').read())
     
    184187Step 1: start batch processing:
    185188
    186     >>> browser.getLink('Batch processing').click()
     189    >>> browser.getLink('Process data').click()
    187190    >>> button = lookup_submit_value(
    188191    ...   'select', 'departments_zope.mgr.csv', browser)
     
    240243
    241244    >>> import cStringIO
    242     >>> browser.getLink('Upload CSV file').click()
     245    >>> browser.getLink('Upload data').click()
    243246    >>> filecontents = cStringIO.StringIO(
    244247    ...   open('courses.csv', 'rb').read())
     
    249252Step 1: start batch processing:
    250253
    251     >>> browser.getLink('Batch processing').click()
     254    >>> browser.getLink('Process data').click()
    252255    >>> button = lookup_submit_value(
    253256    ...   'select', 'courses_zope.mgr.csv', browser)
     
    305308
    306309    >>> import cStringIO
    307     >>> browser.getLink('Upload CSV file').click()
     310    >>> browser.getLink('Upload data').click()
    308311    >>> filecontents = cStringIO.StringIO(
    309312    ...   open('certificates.csv', 'rb').read())
     
    314317Step 1: start batch processing:
    315318
    316     >>> browser.getLink('Batch processing').click()
     319    >>> browser.getLink('Process data').click()
    317320    >>> button = lookup_submit_value(
    318321    ...   'select', 'certificates_zope.mgr.csv', browser)
     
    371374
    372375    >>> import cStringIO
    373     >>> browser.getLink('Upload CSV file').click()
     376    >>> browser.getLink('Upload data').click()
    374377    >>> filecontents = cStringIO.StringIO(
    375378    ...   open('mycertcourses.csv', 'rb').read())
     
    380383Step 1: start batch processing:
    381384
    382     >>> browser.getLink('Batch processing').click()
     385    >>> browser.getLink('Process data').click()
    383386    >>> button = lookup_submit_value(
    384387    ...   'select', 'mycertcourses_zope.mgr.csv', browser)
     
    420423    ...File:...mycertcourses_zope.mgr.csv...
    421424
     425Batch processing users
     426======================
     427
     428    >>> browser.open('http://localhost/app/datacenter')
     429
     430Prepare 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
     438Upload 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
     448Step 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
     455Step 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
     463Step 3: Fix headerlines
     464
     465We 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
     473The submit button is enabled:
     474
     475    >>> browser.getControl('Perform import').disabled
     476    False
     477
     478    >>> browser.getControl('Perform import').click()
     479
     480Step 4: See import results
     481
     482The 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...
    422489
    423490Pending files
     
    444511
    445512    >>> import cStringIO
    446     >>> browser.getLink('Upload CSV file').click()
     513    >>> browser.getLink('Upload data').click()
    447514    >>> filecontents = cStringIO.StringIO(
    448515    ...   open('newfaculties.csv', 'rb').read())
     
    453520Step 1: start batch processing:
    454521
    455     >>> browser.getLink('Batch processing').click()
     522    >>> browser.getLink('Process data').click()
    456523    >>> button = lookup_submit_value(
    457524    ...   'select', 'newfaculties_zope.mgr.csv', browser)
     
    515582
    516583    >>> browser.open('http://localhost/app/datacenter')
    517     >>> browser.getLink('Batch processing').click()
     584    >>> browser.getLink('Process data').click()
    518585    >>> button = lookup_submit_value(
    519586    ...   'select', 'newfaculties_zope.mgr.create.pending.csv', browser)
     
    551618    >>> sorted(os.listdir(dc_path + '/finished'))
    552619    ['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
     622Processed (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
    556628
    557629Log Files
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/browser.txt

    r8777 r9209  
    8181  >>> browser.getControl(name="form.identifier").value = 'forgetful'
    8282  >>> browser.getControl(name="form.email").value = 'aa@aa.ng'
    83   >>> browser.getControl("Get login credentials").click()
     83  >>> browser.getControl("Send login credentials").click()
    8484  >>> print browser.contents
    8585  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
     
    10001000with their code as key.
    10011001
    1002 Each certificate provides a ``Add course referrer`` action button near top.
     1002Each certificate provides a ``Add certificate course`` action button near top.
    10031003
    10041004Certificates provide an add-form to add new certcourses:
     
    10061006  >>> cert_url = dept_url + '/certificates/CERT1'
    10071007  >>> browser.open(cert_url + '/manage')
    1008   >>> browser.getControl('Add course referrer').click()
     1008  >>> browser.getControl('Add certificate course').click()
    10091009  >>> print browser.contents
    10101010  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
     
    10251025  >>> ctrl.getControl('COURSE1').selected = True
    10261026  >>> browser.getControl(name='form.level').value = ['100']
    1027   >>> browser.getControl('Add course referrer').click()
     1027  >>> browser.getControl('Add certificate course').click()
    10281028
    10291029Our certificatecourse will be linked on the parent certificate page:
     
    10381038  >>> cert_url = dept_url + '/certificates/CERT1'
    10391039  >>> browser.open(cert_url + '/manage')
    1040   >>> browser.getControl('Add course referrer').click()
     1040  >>> browser.getControl('Add certificate course').click()
    10411041  >>> ctrl = browser.getControl(name='form.course')
    10421042  >>> ctrl.getControl('COURSE1').selected = True
    10431043  >>> browser.getControl(name='form.level').value = ['100']
    1044   >>> browser.getControl('Add course referrer').click()
    1045   >>> 'The chosen course referrer is already' in browser.contents
     1044  >>> browser.getControl('Add certificate course').click()
     1045  >>> 'The chosen certificate course is already' in browser.contents
    10461046  True
    10471047
     
    10631063
    10641064  >>> browser.open(cert_url + '/COURSE1_100')
    1065   >>> browser.getLink('Edit course referrer').click()
     1065  >>> browser.getLink('Edit certificate course').click()
    10661066
    10671067If we just click 'Save and return' nothing will change:
     
    10881088changed:
    10891089
    1090   >>> browser.getLink('Edit course referrer').click()
     1090  >>> browser.getLink('Edit certificate course').click()
    10911091  >>> browser.getControl(name='form.level').value = ['400']
    10921092  >>> browser.getControl('Cancel').click()
     
    11251125  >>> 'COURSE1_200</a>' in browser.contents
    11261126  True
    1127   >>> browser.getControl('Remove selected course referrers').click()
     1127  >>> browser.getControl('Remove selected certificate courses').click()
    11281128  >>> 'No item selected' in browser.contents
    11291129  True
    11301130  >>> browser.getControl(name='val_id').getControl(
    11311131  ...    value='COURSE1_200').selected = True
    1132   >>> browser.getControl('Remove selected course referrers').click()
     1132  >>> browser.getControl('Remove selected certificate courses').click()
    11331133  >>> 'Successfully removed: COURSE1_200' in browser.contents
    11341134  True
     
    12181218page:
    12191219
    1220   >>> browser.getLink('Upload CSV file').click()
     1220  >>> browser.getLink('Upload data').click()
    12211221
    12221222and enter the appropriate data in the form:
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/layout.py

    r9003 r9209  
    191191    grok.baseclass()
    192192    template = default_waeup_display_template
     193    hide_hint = True
    193194
    194195class KofaEditFormPage(UtilityView,EditForm):
     
    215216        if self.widgets.get('perm_address'):
    216217            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
    218225        if self.widgets.get('description'):
    219226            self.widgets['description'].cssClass = 'span12'
     
    306313        else:
    307314            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         
    308324
    309325    def update(self):
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pages.py

    r9166 r9209  
    1818""" Viewing components for Kofa objects.
    1919"""
    20 import copy
    2120import csv
    2221import grok
     
    2423import re
    2524import sys
    26 import time
    27 import re
     25from urllib import urlencode
    2826from zope import schema
    2927from zope.authentication.interfaces import (
     
    3432    getUtilitiesFor,
    3533    )
    36 #from zope.component.interfaces import Invalid
    3734from zope.event import notify
    38 from zope.securitypolicy.interfaces import (
    39     IPrincipalRoleManager, IPrincipalRoleMap)
     35from zope.securitypolicy.interfaces import IPrincipalRoleManager
    4036from zope.session.interfaces import ISession
     37from zope.password.interfaces import IPasswordManager
    4138from waeup.kofa.browser.layout import (
    4239    KofaPage, KofaForm, KofaEditFormPage, KofaAddFormPage,
     
    4946from waeup.kofa.browser.layout import jsaction, action, UtilityView
    5047from waeup.kofa.browser.resources import (
    51     warning, datepicker, tabs, datatable, page_reloader, page_not_reloader)
     48    warning, tabs, datatable)
    5249from waeup.kofa.interfaces import MessageFactory as _
    5350from waeup.kofa.interfaces import(
     
    6461from waeup.kofa.university.vocabularies import course_levels
    6562from waeup.kofa.authentication import LocalRoleSetEvent
    66 #from waeup.kofa.widgets.restwidget import ReSTDisplayWidget
    6763from waeup.kofa.widgets.htmlwidget import HTMLDisplayWidget
    68 from waeup.kofa.authentication import get_principal_role_manager
    69 from waeup.kofa.utils.helpers import get_user_account, msave
     64from waeup.kofa.utils.helpers import get_user_account
     65from waeup.kofa.mandates.mandate import PasswordMandate
    7066
    7167grok.context(IKofaObject)
     
    156152    return
    157153
     154# Save function used for save methods in pages
     155def 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
    158167#
    159168# Login/logout and language switch pages...
     
    192201                self.redirect(self.camefrom)
    193202                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.'))
    195215
    196216
     
    372392    def entries(self):
    373393        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
    404394
    405395#
     
    801791    def delFiles(self, **data):
    802792        form = self.request.form
    803         logger = self.context.logger
    804793        if form.has_key('val_id'):
    805794            child_id = form['val_id']
     
    826815        return
    827816
     817class 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
    828828class DatacenterUploadPage(KofaPage):
    829829    grok.context(IDataCenter)
    830830    grok.name('upload')
    831831    grok.require('waeup.manageDataCenter')
    832     label = _(u'Upload file')
     832    label = _(u'Upload portal data as CSV file')
    833833    pnav = 0
    834834    upload_button =_(u'Upload')
     
    849849                self.flash(_("Only csv files are allowed."))
    850850                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)
    853860            open(target, 'wb').write(uploadfile.read())
    854861            os.chmod(target, 0664)
     
    881888        return '%s_%s%s' % (base, filtered_username, ext.lower())
    882889
     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
    883911class FileDownloadView(UtilityView, grok.View):
    884912    grok.context(IDataCenter)
     
    897925            'Content-Type', 'text/csv; charset=UTF-8')
    898926        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/',''))
    901929        fullpath = os.path.join(self.context.storage, self.filename)
    902930        return open(fullpath, 'rb').read()
     931
     932class 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
    903954
    904955class DatacenterImportStep1(KofaPage):
     
    914965
    915966    def getFiles(self):
    916         files = self.context.getFiles(sort='date')
     967        files = self.context.getPendingFiles(sort='date')
    917968        for file in files:
    918969            name = file.name
     
    11381189        return False
    11391190
    1140     @property
    1141     def nextstep(self):
    1142         return self.url(self.context, '@@import4')
    1143 
    11441191    def update(self, headerfield=None, back2=None, cancel=None, proceed=None):
    11451192        datatable.need()
     
    13621409           string representing the exporter title used when triggering
    13631410           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.
    13701411        """
    13711412        if self._running_exports is None:
     
    13751416    def _getRunningExports(self):
    13761417        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()
    13821418        return result
    13831419
     
    14261462            return
    14271463        result = open(path, 'rb').read()
     1464        acronym = grok.getSite()['configuration'].acronym.replace(' ','')
     1465        filename = "%s_%s" % (acronym, os.path.basename(path))
    14281466        self.response.setHeader(
    14291467            'Content-Type', 'text/csv; charset=UTF-8')
     1468        self.response.setHeader(
     1469            'Content-Disposition', 'attachment; filename="%s' % filename)
    14301470        # remove job and running_exports entry from context
    14311471        self.context.delete_export_entry(
     
    19872027    grok.template('certificatemanagepage')
    19882028    taboneactions = [_('Save'),_('Cancel')]
    1989     tabtwoactions = [_('Add course referrer'),
    1990                      _('Remove selected course referrers'),_('Cancel')]
     2029    tabtwoactions = [_('Add certificate course'),
     2030                     _('Remove selected certificate courses'),_('Cancel')]
    19912031    tabthreeactions1 = [_('Remove selected local roles')]
    19922032    tabthreeactions2 = [_('Add local role')]
     
    20112051        return msave(self, **data)
    20122052
    2013     @jsaction(_('Remove selected course referrers'))
     2053    @jsaction(_('Remove selected certificate courses'))
    20142054    def delCertificateCourses(self, **data):
    20152055        delSubobjects(self, redirect='@@manage', tab='2')
    20162056        return
    20172057
    2018     @action(_('Add course referrer'), validator=NullValidator)
     2058    @action(_('Add certificate course'), validator=NullValidator)
    20192059    def addCertificateCourse(self, **data):
    20202060        self.redirect(self.url(self.context, 'addcertificatecourse'))
     
    20532093    form_fields = grok.AutoFields(ICertificateCourseAdd)
    20542094    pnav = 1
    2055     label = _('Add course referrer')
    2056 
    2057     @action(_('Add course referrer'))
     2095    label = _('Add certificate course')
     2096
     2097    @action(_('Add certificate course'))
    20582098    def addCertcourse(self, **data):
    20592099        try:
    2060             self.context.addCourseRef(**data)
     2100            self.context.addCertCourse(**data)
    20612101        except KeyError:
    2062             self.status = self.flash(_('The chosen course referrer is already '
     2102            self.status = self.flash(_('The chosen certificate course is already '
    20632103                                  'part of this certificate.'))
    20642104            return
    20652105        self.status = self.flash(
    2066             _("Course referrer ${a}_${b} added.",
     2106            _("certificate course ${a}_${b} added.",
    20672107            mapping = {'a': data['course'].code, 'b': data['level']}))
    20682108        code = "%s_%s" % (data['course'].code, data['level'])
     
    21052145    grok.require('waeup.manageAcademics')
    21062146    form_fields = grok.AutoFields(ICertificateCourse)
    2107     label = _('Edit course referrer')
     2147    label = _('Edit certificate course')
    21082148    pnav = 1
    21092149
     
    21182158            old_level = self.context.level
    21192159            data['course'] = self.context.course
    2120             parent.addCourseRef(**data)
    2121             parent.delCourseRef(data['course'].code, level=old_level)
     2160            parent.addCertCourse(**data)
     2161            parent.delCertCourse(data['course'].code, level=old_level)
    21222162            self.flash(_('Form has been saved.'))
    21232163            old_code = "%s_%s" % (data['course'].code, old_level)
     
    21782218        return None
    21792219
    2180     @action(_('Get login credentials'), style='primary')
     2220    @action(_('Send login credentials to email address'), style='primary')
    21812221    def request(self, **data):
    21822222        if not self.captcha_result.is_valid:
     
    21932233        # Change password
    21942234        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')
    22002246        success = kofa_utils.sendCredentials(
    2201             IUserAccount(user),pwd,login_url,msg)
     2247            IUserAccount(user),password,url_info,msg)
    22022248        if success:
    22032249            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  
    8383
    8484    Main things fixed here:
    85 
     85    If html code:
    8686    - remove newlines (not visible in HTML but visible in PDF)
    8787    - 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
    8890    """
    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 />')
    9398    return html
    9499
     
    265270                                target_language=lang)
    266271            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
    268277            f_text = Paragraph(f_text, ENTRY1_STYLE)
    269278            table_data.append([f_label,f_text])
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/datatable.js

    r7811 r9209  
    11$(document).ready(function(){
    2     $('.dataTable').dataTable();
     2  $('.dataTable').dataTable();
     3
     4        $('.dataTableFiles').dataTable( {
     5                "aaSorting": [[ 2, "desc" ]],
     6        } );
     7
    38        $('.dataTableManage').dataTable( {
    49                "aaSorting": [[ 1, "asc" ]],
    510                "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }]
    611        } );
     12
     13        $('.dataTableManageFiles').dataTable( {
     14                "aaSorting": [[ 3, "desc" ]],
     15                "aoColumnDefs":[{ "bSortable": false, "aTargets": [ 0 ] }]
     16        } );
     17
     18
    719});
    820
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/static/jquery.dataTables.min.js

    r6820 r9209  
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    1616 * 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 *
    1720 */
    1821(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",
     
    3841[];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=
    3942[];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));
     43this.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));
    4144return 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,
    4245d.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  
    11<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">
    33  <img src="" alt="edit"
    44   tal:attributes="src viewlet/icon_url;
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/certificatemanagepage.pt

    r7811 r9209  
    44  <ul class="tabs" data-tabs="tabs">
    55    <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="">Course Referrers</a></li>
     6    <li tal:attributes="class view/tab2"><a href="#tab-2" i18n:translate="">Certificate Courses</a></li>
    77    <li tal:attributes="class view/tab3"><a href="#tab-3" i18n:translate="">Local Roles</a></li>
    88  </ul>
     
    2424    </div>
    2525    <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>
    2730      <table class="display dataTableManage">
    2831        <thead>
    2932          <tr>
    30             <th>&nbsp;</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>&nbsp;</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>
    3339            <th i18n:translate="">Mandatory</th>
    3440          </tr>
     
    3743          <tr tal:repeat="cc context/values" class="gradeC">
    3844             <td>
    39               <input type="checkbox"
    40                          name="val_id"
     45              <input type="checkbox" name="val_id"
    4146                         tal:attributes="value cc/__name__" />
    4247            </td>
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/certificatepage.pt

    r7811 r9209  
    2020<h3>
    2121  <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>
    2323</h3>
    2424<br />
     
    2626<thead>
    2727  <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>
    3134  </tr>
    3235</thead>
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenterpage.pt

    r8366 r9209  
    1111<form action="." tal:attributes="action request/URL" method="post"
    1212      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">
    1414      <thead>
    1515        <tr>
    1616          <th></th>
    1717          <th i18n:translate="">File</th>
    18           <th i18n:translate="">Size</th>
     18          <th i18n:translate="">Datasets</th>
    1919          <th i18n:translate="">Upload Date</th>
    2020        </tr>
    2121      </thead>
    2222      <tbody>
    23         <tr tal:repeat="file context/getFiles" class="gradeC">
     23        <tr tal:repeat="file context/getPendingFiles" class="gradeC">
    2424          <td>
    2525            <input type="checkbox" name="val_id"
     
    2828          <td><a tal:attributes="href python: 'download?filename=' + file.name"
    2929                 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>
    3131          <td tal:content="file/uploaddate">Mar 12, 2008</td>
    3232        </tr>
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenteruploadpage.pt

    r7705 r9209  
    99  </div>
    1010</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  
    3737    If you are having trouble logging in, make sure to enable  cookies in your web browser.
    3838  </p>
    39   <p i18n:translate="login_trouble2">
     39  <p i18n:translate="login_trouble2" tal:condition="python:False">
    4040    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>.
    4347  </p>
    4448  <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  
    1818        <div tal:content="structure widget/error">ERROR</div>
    1919      </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)">
    2122        <div class="hint" tal:content="structure widget/hint">HINT</div>
    2223      </tal:hint>
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/tests/test_browser.py

    r9166 r9209  
    2121import shutil
    2222import tempfile
    23 import pytz
    24 from datetime import datetime, timedelta
    25 from StringIO import StringIO
    2623import os
    27 import grok
    2824from zc.async.testing import wait_for_result
    29 from zope.event import notify
    30 from zope.component import createObject, queryUtility, getUtility
     25from zope.component import createObject, getUtility
    3126from zope.component.hooks import setSite, clearSite
    32 from zope.catalog.interfaces import ICatalog
    3327from zope.security.interfaces import Unauthorized
    34 from zope.securitypolicy.interfaces import IPrincipalRoleManager
    3528from zope.testbrowser.testing import Browser
    36 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
    3729from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
    3830from waeup.kofa.app import University
     
    4133from waeup.kofa.university.faculty import Faculty
    4234from waeup.kofa.university.department import Department
    43 
    44 
    45 
    4635
    4736SAMPLE_FILE = os.path.join(os.path.dirname(__file__), 'test_file.csv')
     
    9079        self.app['faculties']['fac1']['dep1'].courses.addCourse(
    9180            self.course)
    92         self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCourseRef(
     81        self.app['faculties']['fac1']['dep1'].certificates['CERT1'].addCertCourse(
    9382            self.course, level=100)
    9483
     
    127116        self.assertEqual(self.browser.headers['Status'], '200 Ok')
    128117        self.assertEqual(self.browser.url, self.datacenter_path)
    129         self.browser.getLink("Upload CSV file").click()
     118        self.browser.getLink("Upload data").click()
    130119        file = open(SAMPLE_FILE)
    131120        ctrl = self.browser.getControl(name='uploadfile:file')
     
    181170        self.assertEqual(self.browser.headers['Status'], '200 Ok')
    182171        self.assertEqual(self.browser.url, self.datacenter_path)
    183         self.browser.getLink("Export CSV file").click()
     172        self.browser.getLink("Export data").click()
    184173        self.browser.getControl(name="exporter").value = ['faculties']
    185174        self.browser.getControl("Create CSV file").click()
     
    204193        # ...we can download the result
    205194        self.browser.getControl("Download").click()
    206         self.assertEqual(self.browser.headers['Content-Type'],
     195        self.assertEqual(self.browser.headers['content-type'],
    207196                         'text/csv; charset=UTF-8')
     197        self.assertEqual(self.browser.headers['content-disposition'],
     198                         'attachment; filename="WAeUP.Kofa_faculties.csv')
    208199        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')
    210202
    211203        # after download, the job and the result file are removed
     
    229221        self.assertTrue('Discarded export result' in self.browser.contents)
    230222        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  
    9191        cert.code = 'cert1'
    9292        dept.certificates.addCertificate(cert)
    93         cert.addCourseRef(course)
     93        cert.addCertCourse(course)
    9494
    9595        self.browser = Browser()
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/viewlets.py

    r8387 r9209  
    6666    """A base for action buttons.
    6767
    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
    7071    for some active button below, just override the approriate
    7172    attribute in the concerned viewlet.
     
    8283     * ``target_url``
    8384          The URL of the link target.
     85
     86     * ``onclick``
     87          An onclick Javascript event handler.
    8488
    8589    """
     
    143147        return self.view.url(self.view.context, self.target)
    144148
     149    @property
     150    def onclick(self):
     151        """Onclick event...
     152        """
     153        return
     154
    145155class PlainActionButton(ActionButton):
    146156    """A base for action buttons without image
     
    386396    grok.require('waeup.manageDataCenter')
    387397    text = _('Edit settings')
     398    grok.order(1)
    388399
    389400class ManageFacultiesContainerActionButton(ManageActionButton):
     
    456467    grok.context(ICertificateCourse)
    457468    grok.view(CertificateCoursePage)
    458     text = _('Edit course referrer')
    459 
    460 #
    461 # Add actions...
    462 #
     469    text = _('Edit certificate course')
    463470
    464471class AddUserActionButton(AddActionButton):
     
    468475    text = _('Add user')
    469476
    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)
     477class BrowseDatacenterLogs(ActionButton):
     478    grok.context(IDataCenter)
    478479    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):
    484     grok.context(IDataCenter)
    485480    grok.view(DatacenterPage)
    486     grok.order(4)
     481    grok.order(2)
    487482    icon = 'actionicon_info.png'
    488483    target = '@@logs'
    489484    text = _('Show logs')
    490485
    491 #
    492 # Misc. buttons...
    493 #
     486class 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
    494495class BatchOpButton(ActionButton):
    495496    grok.context(IDataCenter)
    496497    grok.view(DatacenterPage)
    497498    grok.require('waeup.importData')
    498     grok.order(6)
     499    grok.order(4)
    499500    icon = 'actionicon_gear.png'
    500501    target = '@@import1'
    501     text = _('Batch processing')
    502 
    503 class UploadCSVButton(ActionButton):
     502    text = _('Process data')
     503
     504class ExportCSVButton(ActionButton):
    504505    grok.context(IDataCenter)
    505506    grok.view(DatacenterPage)
    506507    grok.require('waeup.manageDataCenter')
    507508    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)
    517509    icon = 'actionicon_down.png'
    518510    target = '@@export'
    519     text = _('Export CSV file')
     511    text = _('Export data')
     512
     513class 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')
    520521
    521522#
Note: See TracChangeset for help on using the changeset viewer.