Changeset 9166


Ignore:
Timestamp:
6 Sep 2012, 16:50:17 (12 years ago)
Author:
uli
Message:

All remaining changes from last weeks. Sorry for the mess.

Location:
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa
Files:
7 added
11 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/accesscodes/browser.py

    r8387 r9166  
    2323from hurry.workflow.interfaces import InvalidTransitionError
    2424from waeup.kofa.browser.resources import datatable
    25 from waeup.kofa.browser import KofaPage, KofaAddFormPage, NullValidator
     25from waeup.kofa.browser.layout import KofaPage, KofaAddFormPage, NullValidator
    2626from waeup.kofa.browser.breadcrumbs import Breadcrumb
    2727from waeup.kofa.browser.viewlets import (
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/applicants/browser.py

    r8742 r9166  
    3838    INITIALIZED, STARTED, PAID, SUBMITTED, ADMITTED)
    3939from waeup.kofa.browser import (
    40     KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
     40#    KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
    4141    DEFAULT_PASSPORT_IMAGE_PATH)
     42from waeup.kofa.browser.layout import (
     43    KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage)
    4244from waeup.kofa.browser.interfaces import ICaptchaManager
    4345from waeup.kofa.browser.breadcrumbs import Breadcrumb
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/__init__.py

    r7819 r9166  
    11import os
    22
    3 from waeup.kofa.browser.layout import (
    4     KofaPage, KofaForm, KofaLayout, KofaDisplayFormPage, KofaEditFormPage,
    5     KofaAddFormPage, NullValidator)
    6 from waeup.kofa.browser.pages import ContactAdminForm
     3#from waeup.kofa.browser.layout import (
     4#    KofaPage, KofaForm, KofaLayout, KofaDisplayFormPage, KofaEditFormPage,
     5#    KofaAddFormPage, NullValidator)
     6#from waeup.kofa.browser.pages import ContactAdminForm
    77
    88IMAGE_PATH = os.path.join(
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/breadcrumbs.py

    r7819 r9166  
    2626    IConfigurationContainer, ISessionConfiguration)
    2727from waeup.kofa.interfaces import MessageFactory as _
    28 from waeup.kofa.browser import interfaces
    29 from waeup.kofa.browser.interfaces import (IBreadcrumb,
    30     IBreadcrumbIgnorable, IBreadcrumbContainer)
     28from waeup.kofa.browser.interfaces import (
     29    IBreadcrumb, IBreadcrumbIgnorable, IBreadcrumbContainer, IKofaObject,
     30    IUniversity, IFacultiesContainer, IUsersContainer, IDataCenter, IFaculty,
     31    IDepartment, ICourse, ICertificate, ICoursesContainer, ICertificateCourse,
     32    ICertificatesContainer,
     33    )
    3134
    3235class Breadcrumb(grok.Adapter):
     
    3437    """
    3538    grok.provides(IBreadcrumb)
    36     grok.context(interfaces.IKofaObject)
     39    grok.context(IKofaObject)
    3740    grok.name('index')
    3841
     
    8790    """A breadcrumb for university index pages.
    8891    """
    89     grok.context(interfaces.IUniversity)
     92    grok.context(IUniversity)
    9093    title = _(u'Home')
    9194    parent = None
     
    100103    itself is bound to.
    101104    """
    102     grok.context(interfaces.IUniversity)
     105    grok.context(IUniversity)
    103106    grok.name('manage')
    104107    title = _(u'Portal Settings')
     
    113116    """A breadcrumb for faculty containers.
    114117    """
    115     grok.context(interfaces.IFacultiesContainer)
     118    grok.context(IFacultiesContainer)
    116119    title = _(u'Academics')
    117120
     
    119122    """A breadcrumb for administration areas of University instances.
    120123    """
    121     grok.context(interfaces.IUniversity)
     124    grok.context(IUniversity)
    122125    grok.name('administration')
    123126    title = _(u'Administration')
     
    145148    """A breadcrumb for user containers.
    146149    """
    147     grok.context(interfaces.IUsersContainer)
     150    grok.context(IUsersContainer)
    148151    title = _(u'Portal Users')
    149152    parent_viewname = 'administration'
     
    152155    """A breadcrumb for data centers.
    153156    """
    154     grok.context(interfaces.IDataCenter)
     157    grok.context(IDataCenter)
    155158    title = _(u'Data Center')
    156159    parent_viewname = 'administration'
     
    159162    """A breadcrumb for faculties.
    160163    """
    161     grok.context(interfaces.IFaculty)
     164    grok.context(IFaculty)
    162165
    163166    @property
     
    168171    """A breadcrumb for departments.
    169172    """
    170     grok.context(interfaces.IDepartment)
     173    grok.context(IDepartment)
    171174
    172175class CourseBreadcrumb(FacultyBreadcrumb):
    173176    """A breadcrumb for courses.
    174177    """
    175     grok.context(interfaces.ICourse)
     178    grok.context(ICourse)
    176179
    177180class CertificateBreadcrumb(FacultyBreadcrumb):
    178181    """A breadcrumb for certificates.
    179182    """
    180     grok.context(interfaces.ICertificate)
     183    grok.context(ICertificate)
    181184
    182185class CoursesContainerBreadcrumb(Breadcrumb):
    183186    """ We don't want course container breadcrumbs.
    184187    """
    185     grok.context(interfaces.ICoursesContainer)
     188    grok.context(ICoursesContainer)
    186189    grok.implements(IBreadcrumbIgnorable)
    187190
     
    189192    """ We don't want course container breadcrumbs.
    190193    """
    191     grok.context(interfaces.ICertificatesContainer)
     194    grok.context(ICertificatesContainer)
    192195    grok.implements(IBreadcrumbIgnorable)
    193196
     
    195198    """ We don't want course container breadcrumbs.
    196199    """
    197     grok.context(interfaces.ICertificateCourse)
     200    grok.context(ICertificateCourse)
    198201    @property
    199202    def title(self):
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/captcha.py

    r8127 r9166  
    2828from zope.interface import Interface
    2929from zope.publisher.interfaces.http import IHTTPRequest
    30 from waeup.kofa.browser import KofaPage, resources
     30from waeup.kofa.browser import resources
     31from waeup.kofa.browser.layout import KofaPage
    3132from waeup.kofa.browser.interfaces import (
    3233    ICaptchaRequest, ICaptchaResponse, ICaptcha, ICaptchaConfig,
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/pages.py

    r9003 r9166  
    3939    IPrincipalRoleManager, IPrincipalRoleMap)
    4040from zope.session.interfaces import ISession
    41 from waeup.kofa.browser import (
     41from waeup.kofa.browser.layout import (
    4242    KofaPage, KofaForm, KofaEditFormPage, KofaAddFormPage,
    4343    KofaDisplayFormPage, NullValidator)
     
    4848    ICaptchaManager, IChangePassword)
    4949from waeup.kofa.browser.layout import jsaction, action, UtilityView
    50 from waeup.kofa.browser.resources import warning, datepicker, tabs, datatable
     50from waeup.kofa.browser.resources import (
     51    warning, datepicker, tabs, datatable, page_reloader, page_not_reloader)
    5152from waeup.kofa.interfaces import MessageFactory as _
    5253from waeup.kofa.interfaces import(
     
    5455    IKofaXMLImporter, IKofaXMLExporter, IBatchProcessor,
    5556    ILocalRolesAssignable, DuplicationError, IConfigurationContainer,
    56     ISessionConfiguration, ISessionConfigurationAdd,
     57    ISessionConfiguration, ISessionConfigurationAdd, IJobManager,
    5758    IPasswordValidator, IContactForm, IKofaUtils, ICSVExporter,)
    5859from waeup.kofa.permissions import (
    5960    get_users_with_local_roles, get_all_roles, get_all_users)
     61
    6062from waeup.kofa.students.catalog import search as searchstudents
    6163from waeup.kofa.university.catalog import search
     
    13301332    label = _('Download portal data as CSV file')
    13311333    pnav = 0
    1332     export_button = _(u'Download')
     1334    export_button = _(u'Create CSV file')
     1335    _running_exports = None
    13331336
    13341337    def getExporters(self):
     
    13381341        return sorted(title_name_tuples)
    13391342
    1340     def update(self, export=None, exporter=None):
    1341         if None in (export, exporter):
    1342             return
    1343         self.redirect(
    1344             self.url(self.context, 'export.csv') + '?exporter=%s' % exporter)
     1343    def job_finished(self, status):
     1344        return status == 'completed'
     1345
     1346    def getRunningExports(self):
     1347        """Returns running exports as list of tuples.
     1348
     1349        Only exports triggered by the current user (identified by
     1350        principal.id) are returned.
     1351
     1352        Each tuple has the form (<STATUS>, <STATUS_TITLE>, <EXPORTER_NAME>).
     1353
     1354        ``STATUS``:
     1355           the status as machine readable string (something like
     1356           ``'completed'``)
     1357
     1358        ``STATUS_TITLE``:
     1359           status of export as translated string.
     1360
     1361        ``EXPORTER_NAME``:
     1362           string representing the exporter title used when triggering
     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.
     1370        """
     1371        if self._running_exports is None:
     1372            self._running_exports = self._getRunningExports()
     1373        return self._running_exports
     1374
     1375    def _getRunningExports(self):
     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()
     1382        return result
     1383
     1384    def update(self, export=None, start_export=None, exporter=None,
     1385               discard=None, download=None):
     1386        self.user_id = self.request.principal.id
     1387        if discard:
     1388            myjobs = self.context.get_running_export_jobs(self.user_id)
     1389            for entry in myjobs:
     1390                self.context.delete_export_entry(entry)
     1391                self.flash(_('Discarded export result'))
     1392            return
     1393        if download:
     1394            myjobs = self.context.get_running_export_jobs(self.user_id)
     1395            if not len(myjobs):
     1396                self.flash(_('This export was already discarded.'))
     1397                return
     1398            job_id = myjobs[0][0]
     1399            self.redirect(
     1400                self.url(self.context, 'export.csv') + '?job_id=%s' % job_id)
     1401            return
     1402        if None in (start_export, exporter):
     1403            return
     1404        job_id = self.context.start_export_job(
     1405            exporter, self.request.principal.id)
     1406        self.redirect(self.url(self.context, 'export'))
    13451407        return
    13461408
     
    13501412    grok.require('waeup.manageDataCenter')
    13511413
    1352     def render(self, exporter=None):
    1353         if exporter is None:
    1354             return
    1355         ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
    1356         self.context.logger.info(
    1357             '%s - exported: %s' % (ob_class, exporter))
    1358         exporter = getUtility(ICSVExporter, name=exporter)
    1359         csv_data = exporter.export_all(grok.getSite())
    1360         #csv_data.seek(0)
     1414    def render(self, exporter=None, job_id=None):
     1415
     1416        manager = getUtility(IJobManager)
     1417        job = manager.get(job_id)
     1418        if job is None:
     1419            return
     1420        if hasattr(job.result, 'traceback'):
     1421            # XXX: Some error happened. Do something more approriate here...
     1422            return
     1423        path = job.result
     1424        if not os.path.exists(path):
     1425            # XXX: Do something more appropriate here...
     1426            return
     1427        result = open(path, 'rb').read()
    13611428        self.response.setHeader(
    13621429            'Content-Type', 'text/csv; charset=UTF-8')
    1363         return csv_data
     1430        # remove job and running_exports entry from context
     1431        self.context.delete_export_entry(
     1432            self.context.entry_from_job_id(job_id))
     1433        return result
    13641434
    13651435class ExportXMLPage(grok.View):
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/resources.py

    r8126 r9166  
    302302    waeup_kofa, 'recaptcha_white.js'
    303303    )
     304
     305#: A page reloader (reloads after 3 secs)
     306page_reloader = ResourceInclusion(
     307    waeup_kofa, 'page_reloader.js', depends=[jquery])
     308
     309#: Disables page reloader (which is triggered by a JavaScript timer).
     310page_not_reloader = ResourceInclusion(
     311    waeup_kofa, 'page_not_reloader.js', depends=[jquery])
     312
     313loadbar = ResourceInclusion(
     314    waeup_kofa, 'loadbar.js', depends=[jquery])
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/templates/datacenterexportpage.pt

    r9110 r9166  
    1010      </p>
    1111      <p i18n:translate="">
    12         The file will be generated and then be made available for you to
    13         download.
     12        The file will be generated and then be made available for you
     13        to download. You must download or discard any existing export
     14        file before creating a new one.
    1415      </p>
    1516    </div>
     
    4849              </div>
    4950            </div>
     51
     52            <div>
     53              <tal:loading_bar content="structure provider:loadingbar" />
     54            </div>
    5055          </div>
    5156
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/browser/tests/test_browser.py

    r8755 r9166  
    2626import os
    2727import grok
     28from zc.async.testing import wait_for_result
    2829from zope.event import notify
    29 from zope.component import createObject, queryUtility
     30from zope.component import createObject, queryUtility, getUtility
    3031from zope.component.hooks import setSite, clearSite
    3132from zope.catalog.interfaces import ICatalog
     
    3637from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
    3738from waeup.kofa.app import University
     39from waeup.kofa.interfaces import IJobManager
     40from waeup.kofa.tests.test_async import FunctionalAsyncTestCase
    3841from waeup.kofa.university.faculty import Faculty
    3942from waeup.kofa.university.department import Department
     43
     44
     45
    4046
    4147SAMPLE_FILE = os.path.join(os.path.dirname(__file__), 'test_file.csv')
     
    106112        shutil.rmtree(self.dc_root)
    107113
    108 
    109114class DataCenterUITests(UniversitySetup):
    110115    # Tests for DataCenter class views and pages
     
    149154        return
    150155
    151     def test_export(self):
     156
     157class DataCenterUIExportTests(UniversitySetup, FunctionalAsyncTestCase):
     158    # Tests for DataCenter class views and pages
     159
     160    layer = FunctionalLayer
     161
     162    def wait_for_export_job_completed(self):
     163        # helper function waiting until the current export job is completed
     164        manager = getUtility(IJobManager)
     165        job_id = self.app['datacenter'].running_exports[0][0]
     166        job = manager.get(job_id)
     167        wait_for_result(job)
     168        return job_id
     169
     170    def stored_in_datacenter(self, job_id):
     171        # tell whether job_id is stored in datacenter's running jobs list
     172        for entry in list(self.app['datacenter'].running_exports):
     173            if entry[0] == job_id:
     174                return True
     175        return False
     176
     177    def test_export_start(self):
     178        # we can trigger export file creation
    152179        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
    153180        self.browser.open(self.datacenter_path)
     
    156183        self.browser.getLink("Export CSV file").click()
    157184        self.browser.getControl(name="exporter").value = ['faculties']
     185        self.browser.getControl("Create CSV file").click()
     186        self.assertEqual(self.browser.headers['Status'], '200 Ok')
     187        return
     188
     189    def test_export_download(self):
     190        # we can download a generated export result
     191        self.test_export_start()
     192        # while the export file is created, we get a reload button
     193        # (or a loading bar if javascript is enabled)...
     194        self.browser.getControl("Reload").click()
     195        # ...which is displayed as long as the job is not finished.
     196        # When the job is finished and we reload the page...
     197        job_id = self.wait_for_export_job_completed()
     198        try:
     199            self.browser.getControl("Reload").click()
     200        except LookupError:
     201            # if the job completed very fast, we will get the download
     202            # link immediately
     203            pass
     204        # ...we can download the result
    158205        self.browser.getControl("Download").click()
    159         self.assertEqual(self.browser.headers['Status'], '200 Ok')
    160206        self.assertEqual(self.browser.headers['Content-Type'],
    161207                         'text/csv; charset=UTF-8')
    162208        self.assertEqual(self.browser.contents,
    163209            'code,title,title_prefix\r\nfac1,Unnamed Faculty,faculty\r\n')
    164         logfile = os.path.join(
    165             self.app['datacenter'].storage, 'logs', 'datacenter.log')
    166         logcontent = open(logfile).read()
    167         self.assertTrue('zope.mgr - browser.pages.ExportCSVView - '
    168                         'exported: faculties' in logcontent)
    169         return
     210
     211        # after download, the job and the result file are removed
     212        manager = getUtility(IJobManager)
     213        result = manager.get(job_id)
     214        self.assertEqual(result, None)
     215        self.assertEqual(self.stored_in_datacenter(job_id), False)
     216        #logfile = os.path.join(
     217        #    self.app['datacenter'].storage, 'logs', 'datacenter.log')
     218        #logcontent = open(logfile).read()
     219        #self.assertTrue('zope.mgr - browser.pages.ExportCSVView - '
     220        #                'exported: faculties' in logcontent)
     221        return
     222
     223    def test_export_discard(self):
     224        # we can discard a generated export result
     225        self.test_export_start()
     226        self.wait_for_export_job_completed()
     227        self.browser.open(self.datacenter_path + '/@@export')
     228        self.browser.getControl("Discard").click()
     229        self.assertTrue('Discarded export result' in self.browser.contents)
     230        return
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/browser.py

    r8685 r9166  
    2222from zope.i18n import translate
    2323from zope.component import getUtility
    24 from waeup.kofa.browser import (
     24from waeup.kofa.browser.layout import (
    2525    KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
    2626    NullValidator)
  • main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/students/browser.py

    r8780 r9166  
    3333    invalidate_accesscode, get_access_code)
    3434from waeup.kofa.accesscodes.workflow import USED
    35 from waeup.kofa.browser import (
     35from waeup.kofa.browser.layout import (
    3636    KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
    37     ContactAdminForm, KofaForm, NullValidator)
     37    KofaForm, NullValidator)
     38from waeup.kofa.browser.pages import ContactAdminForm
    3839from waeup.kofa.browser.breadcrumbs import Breadcrumb
    3940from waeup.kofa.browser.resources import datepicker, datatable, tabs, warning
Note: See TracChangeset for help on using the changeset viewer.