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:
2 edited

Legend:

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

  • 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 ' +
Note: See TracChangeset for help on using the changeset viewer.