From 1013c167ae4a4d891572b0eadbe4e31008f14ad6 Mon Sep 17 00:00:00 2001 From: Ricardo Markiewicz Date: Sat, 10 Mar 2007 20:03:07 +0000 Subject: [PATCH] Controlador MisEntregas para los Alumnos Permite a los alumnos hacer entregas en las Instancias De Entrega --- sercom/controllers.py | 16 +- sercom/model.py | 1 + sercom/subcontrollers/__init__.py | 1 + sercom/subcontrollers/misentregas/__init__.py | 152 ++++++++++++++++++ .../misentregas/templates/__init__.py | 0 .../misentregas/templates/list.kid | 49 ++++++ .../misentregas/templates/new.kid | 18 +++ sercom/templates/welcome.kid | 21 ++- sercom/widgets.py | 1 - 9 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 sercom/subcontrollers/misentregas/__init__.py create mode 100644 sercom/subcontrollers/misentregas/templates/__init__.py create mode 100644 sercom/subcontrollers/misentregas/templates/list.kid create mode 100644 sercom/subcontrollers/misentregas/templates/new.kid diff --git a/sercom/controllers.py b/sercom/controllers.py index 849d25c..4954d56 100644 --- a/sercom/controllers.py +++ b/sercom/controllers.py @@ -34,17 +34,25 @@ class Root(controllers.RootController): @expose(template='.templates.welcome') @identity.require(identity.not_anonymous()) def dashboard(self): + now = DateTimeCol.now() if 'admin' in identity.current.permissions: # TODO : Fijar el curso !! correcciones = Correccion.selectBy(corrector=identity.current.user, corregido=None).count() - now = DateTimeCol.now() instancias = list(InstanciaDeEntrega.select( AND(InstanciaDeEntrega.q.inicio <= now, InstanciaDeEntrega.q.fin > now)) .orderBy(InstanciaDeEntrega.q.fin)) - return dict(a_corregir=correcciones, - instancias_activas=instancias, now=now) + return dict(a_corregir=correcciones, + instancias_activas=instancias, now=now) + + if 'entregar' in identity.current.permissions: + instancias = list(InstanciaDeEntrega.select( + AND(InstanciaDeEntrega.q.inicio <= now, + InstanciaDeEntrega.q.fin > now)) + .orderBy(InstanciaDeEntrega.q.fin)) + return dict(instancias_activas=instancias, now=now) + return dict() @expose(template='.templates.login') def login(self, forward_url=None, previous_url=None, tg_errors=None, *args, @@ -113,6 +121,8 @@ class Root(controllers.RootController): admin = identity.SecureObject(CatWalk(model), identity.has_permission('admin')) + mis_entregas = MisEntregasController() + #{{{ Agrega summarize a namespace tg de KID def summarize(text, size, concat=True, continuation='...'): """Summarize a string if it's length is greater than a specified size. This diff --git a/sercom/model.py b/sercom/model.py index dbf342f..a99995f 100644 --- a/sercom/model.py +++ b/sercom/model.py @@ -742,6 +742,7 @@ class Entrega(SQLObject): #{{{ pk = DatabaseIndex(instancia, entregador, fecha, unique=True) # Campos archivos = BLOBCol(notNone=True) # ZIP con fuentes de la entrega + archivos_nombre = UnicodeCol(length=255) correcta = BoolCol(default=None) # None es que no se sabe qué pasó inicio_tareas = DateTimeCol(default=None) # Si es None no se procesó fin_tareas = DateTimeCol(default=None) # Si es None pero inicio no, se está procesando diff --git a/sercom/subcontrollers/__init__.py b/sercom/subcontrollers/__init__.py index 7be8ae8..9b12669 100644 --- a/sercom/subcontrollers/__init__.py +++ b/sercom/subcontrollers/__init__.py @@ -8,3 +8,4 @@ from docente_inscripto import DocenteInscriptoController from grupo import GrupoController from correccion import CorreccionController from alumno_inscripto import AlumnoInscriptoController +from misentregas import MisEntregasController diff --git a/sercom/subcontrollers/misentregas/__init__.py b/sercom/subcontrollers/misentregas/__init__.py new file mode 100644 index 0000000..4570b84 --- /dev/null +++ b/sercom/subcontrollers/misentregas/__init__.py @@ -0,0 +1,152 @@ +# vim: set et sw=4 sts=4 encoding=utf-8 foldmethod=marker : + +#{{{ Imports +import cherrypy +from turbogears import controllers, expose, redirect +from turbogears import validate, flash, error_handler +from turbogears import validators as V +from turbogears import widgets as W +from turbogears import identity +from turbogears import paginate +from docutils.core import publish_parts +from sercom.subcontrollers import validate as val +from sercom.model import Entrega, Correccion, Curso, Ejercicio, InstanciaDeEntrega +from sqlobject import * + +#}}} + +#{{{ Configuración +cls = Entrega +name = 'entrega' +namepl = name + 's' +#}}} + +#{{{ Validación +def validate_get(id): + return val.validate_get(cls, name, id) + +def validate_set(id, data): + return val.validate_set(cls, name, id, data) + +def validate_new(data): + return val.validate_new(cls, name, data) +#}}} + +def get_ejercicios_activos(): + # TODO : Mostrar solo los ejercicios con instancias de entrega activos + return [(0, _(u'--'))] + [(fk.id, fk.shortrepr()) for fk in Ejercicio.select()] + +ajax = """ + function clearInstancias () + { + l = MochiKit.DOM.getElement('form_instancia'); + l.options.length = 0; + l.disabled = true; + } + + function mostrarInstancias(res) + { + clearInstancias(); + for(i=0; i < res.instancias.length; i++) { + id = res.instancias[i].id; + label = res.instancias[i].numero; + MochiKit.DOM.appendChildNodes("form_instancia", OPTION({"value":id}, label)) + } + if (l.options.length > 0) + l.disabled = false; + } + + function err (err) + { + alert("The metadata for MochiKit.Async could not be fetched :("); + } + + function actualizar_instancias () + { + l = MochiKit.DOM.getElement('form_ejercicio'); + id = l.options[l.selectedIndex].value; + if (id == 0) { + clearInstancias(); + return; + } + + url = "/mis_entregas/instancias?ejercicio_id="+id; + var d = loadJSONDoc(url); + d.addCallbacks(mostrarInstancias, err); + } + + function prepare() + { + connect('form_ejercicio', 'onchange', actualizar_instancias); + clearInstancias(); + } + + MochiKit.DOM.addLoadEvent(prepare) +""" +#{{{ Formulario +class EntregaForm(W.TableForm): + class Fields(W.WidgetsList): + ejercicio = W.SingleSelectField(label=_(u'Ejercicio'), + options=get_ejercicios_activos, validator=V.Int(not_empty=True)) + instancia = W.SingleSelectField(label=_(u'Instancia de Entrega'), validator=V.Int(not_empty=True)) + archivo = W.FileField(label=_(u'Archivo'), help_text=_(u'Archivo en formaro ZIP con tu entrega')) + fields = Fields() + javascript = [W.JSSource("MochiKit.DOM.focusOnLoad('form_ejercicio');"), W.JSSource(ajax)] + +form = EntregaForm() +#}}} + +#{{{ Controlador +class MisEntregasController(controllers.Controller, identity.SecureResource): + """Basic model admin interface""" + require = identity.has_permission('entregar') + + @expose() + def default(self, tg_errors=None): + """handle non exist urls""" + raise redirect('list') + + @expose() + def index(self): + raise redirect('list') + + @expose(template='kid:%s.templates.new' % __name__) + def new(self, **kw): + """Create new records in model""" + return dict(name=name, namepl=namepl, form=form, values=kw) + + @expose(template='kid:%s.templates.list' % __name__) + @paginate('records') + def list(self): + """List records in model""" + r = cls.select(cls.q.entregadorID == identity.current.user.id) + return dict(records=r, name=name, namepl=namepl) + + @expose(template='kid:%s.templates.show' % __name__) + def show(self,id, **kw): + """Show record in model""" + r = validate_get(id) + if r.observaciones is None: + r.obs = '' + else: + r.obs = publish_parts(r.observaciones, writer_name='html')['html_body'] + return dict(name=name, namepl=namepl, record=r) + + @validate(form=form) + @error_handler(new) + @expose() + def create(self, archivo, ejercicio, **kw): + """Save or create record to model""" + kw['archivos'] = archivo.file.read() + kw['archivos_nombre'] = archivo.filename + kw['entregador'] = identity.current.user + validate_new(kw) + flash(_(u'Se creó una nueva %s.') % name) + raise redirect('list') + + @expose("json") + def instancias(self, ejercicio_id): + c = Ejercicio.get(ejercicio_id) + return dict(instancias=c.instancias) +#}}} + diff --git a/sercom/subcontrollers/misentregas/templates/__init__.py b/sercom/subcontrollers/misentregas/templates/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sercom/subcontrollers/misentregas/templates/list.kid b/sercom/subcontrollers/misentregas/templates/list.kid new file mode 100644 index 0000000..3b99a27 --- /dev/null +++ b/sercom/subcontrollers/misentregas/templates/list.kid @@ -0,0 +1,49 @@ + + + + + +list + + + +

Administración de Objetos

+ + + + + + + + + + + + + + + + + + + + +
EjercicioIECorrectaInicioTareasFinTareasObservacionesOperaciones
usuariousuariofecha asignadofecha corregidofecha corregidonota + Ver + Bajar Archivo +
+ +
+Agregar + +
+ ${page} + ${page} +
+ + + + + diff --git a/sercom/subcontrollers/misentregas/templates/new.kid b/sercom/subcontrollers/misentregas/templates/new.kid new file mode 100644 index 0000000..2ba40fc --- /dev/null +++ b/sercom/subcontrollers/misentregas/templates/new.kid @@ -0,0 +1,18 @@ + + + + +new + + + +

Crear Nuevo Objeto

+ +

Formulario

+ +
+Cancelar + + + diff --git a/sercom/templates/welcome.kid b/sercom/templates/welcome.kid index 8f45504..cb28193 100644 --- a/sercom/templates/welcome.kid +++ b/sercom/templates/welcome.kid @@ -37,9 +37,26 @@ -
-

Soy entregar

+

Soy entregar

+

Instancias de Entrega

+
+
    +
  • + + La entrega ${instancia.numero} del + ejercicio ${instancia.ejercicio.numero} vence + el ${instancia.fin.strftime(r'%A %d de %B a las %R')} +
    + (falta ${delta.days} días, + ${delta.seconds//3600} horas y + ${delta.seconds//60%60} minutos). +
  • +
+
+
+ No hay Ejercicios con entregas en curso en este momento. +
diff --git a/sercom/widgets.py b/sercom/widgets.py index b9a14c1..53d9e4c 100644 --- a/sercom/widgets.py +++ b/sercom/widgets.py @@ -123,7 +123,6 @@ DosListasAjax = ''' list(ifilterfalse(itemgetter('selected'), $(fromSelect).options)) ); } - ''' class AjaxDosListasSelect(widgets.MultipleSelectField): -- 2.43.0