GenroPy, un framework innovativo per applicazioni web AJAX

76
Un progetto in GenroPy Framework tutto italiano per applicazioni web e AJAX sabato 29 maggio 2010

description

Roberto Lupi

Transcript of GenroPy, un framework innovativo per applicazioni web AJAX

Page 1: GenroPy, un framework innovativo per applicazioni web AJAX

Un progetto in

GenroPyFramework tutto italiano

per applicazioni web e AJAX

sabato 29 maggio 2010

Page 2: GenroPy, un framework innovativo per applicazioni web AJAX

Un progetto in

GenroPyFramework tutto italiano

per applicazioni web e AJAX

gestionali

sabato 29 maggio 2010

Page 3: GenroPy, un framework innovativo per applicazioni web AJAX

Roberto Lupi@robertolupi

• 10 anni di esperienza web

• enterprise e intranet

• Clienti: Amadori, Merloni, 21 banche

• Italia e India

• oggi: direttore tecnico di MedMediasoftware per la sanità

• http://www.medmediagroup.it/

sabato 29 maggio 2010

Page 4: GenroPy, un framework innovativo per applicazioni web AJAX

Siti vs. applicazioni

sabato 29 maggio 2010

Page 5: GenroPy, un framework innovativo per applicazioni web AJAX

Business logic

Web AJAXBase dati

ORM

XML

/

JSON

Object-relationalimpedance mismatch

domain objects / GUIimpedance mismatch

!!

PDF

RDBMSvs. objects

domain objects vs. GUI

sabato 29 maggio 2010

Page 6: GenroPy, un framework innovativo per applicazioni web AJAX

HTML✗

sabato 29 maggio 2010

Page 7: GenroPy, un framework innovativo per applicazioni web AJAX

Personalizzazioni?

sabato 29 maggio 2010

Page 8: GenroPy, un framework innovativo per applicazioni web AJAX

Stampe?

sabato 29 maggio 2010

Page 9: GenroPy, un framework innovativo per applicazioni web AJAX

La storia

sabato 29 maggio 2010

Page 10: GenroPy, un framework innovativo per applicazioni web AJAX

Stansabato 29 maggio 2010

Page 11: GenroPy, un framework innovativo per applicazioni web AJAX

Il progetto

sabato 29 maggio 2010

Page 12: GenroPy, un framework innovativo per applicazioni web AJAX

Il progetto

15 processiamministrativi

sabato 29 maggio 2010

Page 13: GenroPy, un framework innovativo per applicazioni web AJAX

Il progetto

15 processiamministrativi

200+ formsWeb

sabato 29 maggio 2010

Page 14: GenroPy, un framework innovativo per applicazioni web AJAX

Il progetto

15 processiamministrativi

190 reports e forms PDF

200+ formsWeb

sabato 29 maggio 2010

Page 15: GenroPy, un framework innovativo per applicazioni web AJAX

Il progetto

15 processiamministrativi

190 reports e forms PDF

200+ formsWeb

sabato 29 maggio 2010

Page 16: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 17: GenroPy, un framework innovativo per applicazioni web AJAX

2 sviluppatori

sabato 29 maggio 2010

Page 18: GenroPy, un framework innovativo per applicazioni web AJAX

2 designers2 sviluppatori

sabato 29 maggio 2010

Page 19: GenroPy, un framework innovativo per applicazioni web AJAX

2 mesi2 designers2 sviluppatori

sabato 29 maggio 2010

Page 20: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 21: GenroPy, un framework innovativo per applicazioni web AJAX

GenroPy

sabato 29 maggio 2010

Page 22: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 23: GenroPy, un framework innovativo per applicazioni web AJAX

Bags

sabato 29 maggio 2010

Page 24: GenroPy, un framework innovativo per applicazioni web AJAX

Bags

gerarchica ed ordinatasimile a XML

valori ed attributi

sabato 29 maggio 2010

Page 25: GenroPy, un framework innovativo per applicazioni web AJAX

Bags

gerarchica ed ordinatasimile a XML

valori ed attributi

lazy loadingdinamica

observer pattern

sabato 29 maggio 2010

Page 26: GenroPy, un framework innovativo per applicazioni web AJAX

Bags

gerarchica ed ordinatasimile a XML

valori ed attributi

lazy loadingdinamica

observer patterndatabase

versatilefiles XML directory trees

web services

sabato 29 maggio 2010

Page 27: GenroPy, un framework innovativo per applicazioni web AJAX

Bags

gerarchica ed ordinatasimile a XML

valori ed attributi

lazy loadingdinamica

observer pattern

base datiuniversale

interfaccia utente

domain specific languages

databaseversatile

files XML directory trees

web services

sabato 29 maggio 2010

Page 28: GenroPy, un framework innovativo per applicazioni web AJAX

Business

Logic

Web AJAXBase dati

ORM

XML

/

JSON

PDFBags

sabato 29 maggio 2010

Page 29: GenroPy, un framework innovativo per applicazioni web AJAX

Database

sabato 29 maggio 2010

Page 30: GenroPy, un framework innovativo per applicazioni web AJAX

Quasi un ORM...

class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

sabato 29 maggio 2010

Page 31: GenroPy, un framework innovativo per applicazioni web AJAX

Quasi un ORM...

class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

tbl.column('id',size='22',group='_',readOnly='y',name_long='Id')

sabato 29 maggio 2010

Page 32: GenroPy, un framework innovativo per applicazioni web AJAX

Quasi un ORM...

class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

validate_notnull=True,validate_notnull_error='!!Mandatory field'

sabato 29 maggio 2010

Page 33: GenroPy, un framework innovativo per applicazioni web AJAX

Quasi un ORM...

class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name')

sabato 29 maggio 2010

Page 34: GenroPy, un framework innovativo per applicazioni web AJAX

Quasi un ORM...

class Table(object): def config_db(self, pkg): tbl = pkg.table('user', pkey='id', name_long='!!User', rowcaption='username,email:%s (%s)') self.sysFields(tbl,ins=True, upd=True, md5=True) tbl.column('id',size='22',group='_',readOnly='y',name_long='Id') tbl.column('username', size=':32',name_long='!!Username', unique='y', _sendback=True, indexed='y',validate_notnull=True,validate_notnull_error='!!Mandatory field') tbl.column('email',name_long='Email',validate_notnull=True, validate_notnull_error='!!Mandatory field') tbl.column('firstname', size=':32',name_long='!!First name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('lastname', size=':32',name_long='!!Last name', validate_notnull=True,validate_case='c',validate_notnull_error='!!Mandatory field') tbl.column('registration_date', 'D' ,name_long='!!Registration Date') tbl.column('auth_tags', name_long='!!Authorization Tags') tbl.column('status', name_long='!!Status', size='4', validate_values_conf='!!Confirmed', validate_values_wait='!!Waiting') tbl.column('md5pwd', name_long='!!PasswordMD5', size=':65') tbl.column('locale', name_long='!!Default Language', size=':12') tbl.column('preferences', dtype='X', name_long='!!Preferences') tbl.formulaColumn('fullname', "firstname||' '||lastname", name_long=u'!!Name') # ... metodi d'utilità ... def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

def trigger_onUpdating(self, record,**kwargs): # ... def trigger_onInserting(self, record,**kwargs): # ...

sabato 29 maggio 2010

Page 35: GenroPy, un framework innovativo per applicazioni web AJAX

GUI

sabato 29 maggio 2010

Page 36: GenroPy, un framework innovativo per applicazioni web AJAX

HTML✗

sabato 29 maggio 2010

Page 37: GenroPy, un framework innovativo per applicazioni web AJAX

Dojo

sabato 29 maggio 2010

Page 38: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 39: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 40: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 41: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 42: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 43: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 44: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 45: GenroPy, un framework innovativo per applicazioni web AJAX

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

AJAX semplicissimo

sabato 29 maggio 2010

Page 46: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 47: GenroPy, un framework innovativo per applicazioni web AJAX

Package(s)

sabato 29 maggio 2010

Page 48: GenroPy, un framework innovativo per applicazioni web AJAX

Istanze

Package(s)

sabato 29 maggio 2010

Page 49: GenroPy, un framework innovativo per applicazioni web AJAX

Siti

Istanze

Package(s)

sabato 29 maggio 2010

Page 50: GenroPy, un framework innovativo per applicazioni web AJAX

Siti

Istanze

Package(s)

GUI

Database

Risorse

sabato 29 maggio 2010

Page 51: GenroPy, un framework innovativo per applicazioni web AJAX

Siti

Istanze

Package(s)

GUI

Database

Risorse

Mixin

sabato 29 maggio 2010

Page 52: GenroPy, un framework innovativo per applicazioni web AJAX

Siti

Istanze

Package(s)

GUI

Database

Risorse

Mixin

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

sabato 29 maggio 2010

Page 53: GenroPy, un framework innovativo per applicazioni web AJAX

Siti

Istanze

Package(s)

GUI

Database

Risorse

Mixin

class GnrCustomWebPage(object): def windowTitle(self): return '!!Hello world'

def main(self, root, **kwargs): tabber = root.tabContainer() tab = tabber.contentPane(title='Tab') tab.button('Che ore sono?',action='FIRE chiedi_ora;') root.dataRpc('risultato','dammi_ora',_fired='^chiedi_ora') tab.div('^risultato') def rpc_dammi_ora(self): return datetime.datetime.now()

def rpc_dammi_ora(self): return Bag('http://www.example.com/websvc/get_time')['Europe.Rome']

sabato 29 maggio 2010

Page 54: GenroPy, un framework innovativo per applicazioni web AJAX

Stampe

sabato 29 maggio 2010

Page 55: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 56: GenroPy, un framework innovativo per applicazioni web AJAX

Codice

sabato 29 maggio 2010

Page 57: GenroPy, un framework innovativo per applicazioni web AJAX

Editor PDFCodice

sabato 29 maggio 2010

Page 58: GenroPy, un framework innovativo per applicazioni web AJAX

Il progettoatto II

sabato 29 maggio 2010

Page 59: GenroPy, un framework innovativo per applicazioni web AJAX

User

Inserimento dati tramite form Web

Inserimento dati tramite form PDF

Stampa ed archiviazione

Utente

sabato 29 maggio 2010

Page 60: GenroPy, un framework innovativo per applicazioni web AJAX

sabato 29 maggio 2010

Page 61: GenroPy, un framework innovativo per applicazioni web AJAX

m4.py (mixin)

Componenti

fascicolo.py (webpage)

form richiesta

formato dati PDF

azioni pre / post

elementi GUI condivisi nelle forms

GUI comune

communicazione con PDF

sabato 29 maggio 2010

Page 62: GenroPy, un framework innovativo per applicazioni web AJAX

class Table(object):

def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)

Tabella “documento”

sabato 29 maggio 2010

Page 63: GenroPy, un framework innovativo per applicazioni web AJAX

class Table(object):

def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)

Tabella “documento”

sabato 29 maggio 2010

Page 64: GenroPy, un framework innovativo per applicazioni web AJAX

class Table(object):

def config_db(self, pkg): tbl = pkg.table('documento', pkey='id',name_long='!!Documento', name_plural='!!Documenti', rowcaption="$descrizione") self.sysAndComuneIdFields(tbl) tbl.column('fascicolo',name_long='!!Fascicolo') tbl.column('modello',name_long='!!Modello') tbl.column('data','D',name_long='!!Data del documento') tbl.column('ts_richiesta','DH',name_long='!!Data e ora') tbl.column('dati_richiesta','X',group='_',name_long='!!Dati richiesta', _sendback=True) tbl.column('dati_pdf','X',group='_',name_long='!!Dati del documento PDF') tbl.column('descrizione',name_long='!!Descrizione') tbl.column('user_id',size='22',group='_', _sendback=True).relation('adm.user.id',mode='foreignkey',onDelete='cascade',deferred=True, one_one=True)

Tabella “documento”

sabato 29 maggio 2010

Page 65: GenroPy, un framework innovativo per applicazioni web AJAX

class Personale(BaseComponent):

py_requires="elezforms:BaseElezForms" def formPersonale(self, pane, **base_kwargs): kwargs = {'width': '100%', 'border_spacing': '4px'} kwargs.update(base_kwargs) fb = pane.formbuilder(cols=2, dbtable="comune.personale", **kwargs) fb.field('num') fb.field('nominativo', autospan=1) fb.field('data_nas', autospan=1) fb.field('qualifica', autospan=1) fb.field('categoria', autospan=1) fb.field('ufficio', autospan=1) fb.field('num_ore', autospan=1) fb.field('incarico', autospan=1) return fb

Componenti

sabato 29 maggio 2010

Page 66: GenroPy, un framework innovativo per applicazioni web AJAX

class Personale(BaseComponent):

# ... continua ... def selezionaMoltiPersonale(self, parentBC, **base_kwargs): kwargs = dict( label="Personale", basename="personale", table="comune.personale", selectionPars=dict(order_by="nominativo")) kwargs.update(base_kwargs) self.selezionaMolti(parentBC, **kwargs) def personale_struct(self, struct): r = struct.view().rows() r.fieldcell("num", width="4em") r.fieldcell("nominativo", width="15em") r.fieldcell("data_nas", width="8em", format_fullYear=True) r.fieldcell("categoria", width="10em") r.fieldcell("ufficio", width="15em") return struct

Componenti

sabato 29 maggio 2010

Page 67: GenroPy, un framework innovativo per applicazioni web AJAX

class Modulo(object):

def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]

def abilitaCompilazioneGuidata(self): return True

def enableSaveDatiPdf(self): return False

def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))

Mixin

sabato 29 maggio 2010

Page 68: GenroPy, un framework innovativo per applicazioni web AJAX

class Modulo(object):

def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]

def abilitaCompilazioneGuidata(self): return True

def enableSaveDatiPdf(self): return False

def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

Mixin

sabato 29 maggio 2010

Page 69: GenroPy, un framework innovativo per applicazioni web AJAX

class Modulo(object):

def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]

def abilitaCompilazioneGuidata(self): return True

def enableSaveDatiPdf(self): return False

def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id",multiple=True))

Mixin

sabato 29 maggio 2010

Page 70: GenroPy, un framework innovativo per applicazioni web AJAX

class Modulo(object):

def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]

def abilitaCompilazioneGuidata(self): return True

def enableSaveDatiPdf(self): return False

def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))

Mixin

sabato 29 maggio 2010

Page 71: GenroPy, un framework innovativo per applicazioni web AJAX

class Modulo(object):

def windowTitle(self): return '!!1/4. Nomina messi notificatori straordinari' def fascicolo(self): return 'f1' def modelli(self): return [('1_4', '1/4. Nomina messi notificatori straordinari')]

def abilitaCompilazioneGuidata(self): return True

def enableSaveDatiPdf(self): return False

def div_toolbar(self, div): div.button("Personale", connect_onclick="genro.gotoURL('/comune/personale')")

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaMoltiPersonale(bc, values="#dati_richiesta.personale_id", label="Seleziona i messi notificatori")

def formatoDatiPdf(self, root): root.personale(onLoad=self.selezionaRecord('$comune_id = :comune_id and $id in :personale_id', personale_id="=dati_richiesta.personale_id", multiple=True))

def form_NuovaRichiesta(self, parentBC,**kwargs): bc = parentBC.borderContainer(**kwargs) self.selezionaSezione(bc, storeRecord="#dati_richiesta.sezione", label="Seleziona la sezione")

def formatoDatiPdf(self, root): sez = root.sezione(onLoad=self.creaRecord(datapath='dati_richiesta.sezione')) sez.attestazione(onLoad=self.selezionaRecord(where='$comune_id = :comune_id and $sezione_id = :sezione_id and not fuori_comune', sezione_id='=parent.id', order_by='$sesso,$nominativo', multiple=True))

Mixin

sabato 29 maggio 2010

Page 72: GenroPy, un framework innovativo per applicazioni web AJAX

RSS Reader

sabato 29 maggio 2010

Page 73: GenroPy, un framework innovativo per applicazioni web AJAX

#!/usr/bin/env pythonw# -*- coding: UTF-8 -*-## untitled## Created by Giovanni Porcari on 2007-03-24.# Copyright (c) 2007 Softwell. All rights reserved.#

""" RSS READER """from gnr.core.gnrbag import Bag

class GnrCustomWebPage(object): maintable='rss.feed' css_require='rssreader' def pageAuthTags(self, **kwargs): return 'user' def main(self, root, **kwargs): layout = root.borderContainer(design="sidebar") self.left(layout.borderContainer(region='left', width="30%", splitter=True, _class='fakeclass',datapath='feed')) self.top(layout.contentPane(region='top',height='30%', splitter=True,_class='fakeclass')) center = layout.stackContainer(region='center',_class='fakeclass',selectedPage='^rss.page') center.contentPane(pageName='loading').div('...Loading...') center.contentPane(pageName='loaded').iframe(height='100%',width='100%', delay=2000,border='0', onUpdating='genro.setData("rss.page","loading");', onLoad='genro.setData("rss.page","loaded");', src='^rss.link') def left(self,bc): self.feedform(bc.contentPane(region='top',_class='fakeclass')) center = bc.contentPane(region='center',_class='fakeclass') center.tree(storepath='.tree',labelAttribute='caption',selected_k_id='.curr.pkey', selected_k_url='.curr.url',_fired='^.refreshTree', inspect='shift') center.dataRpc('.tree','getFeeds',_fired='^.refresh',_onResult='FIRE .refreshTree',_onStart=True) center.dataRpc('rss.rows','getItems',url='^.curr.url',_if='url',_else="null")

def feedform(self,pane): fb = pane.formbuilder(cols=2,border_spacing='4px',datapath='.record',formId='rss', controllerPath='form',pkeyPath='feed.curr.pkey', width='90%',dbtable='rss.feed') #fb.textbox(value='^.topic',lbl='!!Topic',width='100%') #fb.textbox(value='^.title',lbl='!!Title',width='100%') #fb.textbox(value='^.url',lbl='!!Address',colspan='2',width='100%') fb.field('topic',autospan=1) fb.field('title',autospan=1) fb.field('url',autospan=2) fb.button('!!Save',action="genro.formById('rss').save();", disabled='==!_valid',_valid='^form.valid') fb.button('!!New',action="FIRE feed.curr.pkey='*newrecord*';") # == ritorna un espressione javascript pane.dataController(""" genro.formById('rss').load({destPkey:destPkey});""", destPkey='^.curr.pkey',_onStart=True) pane.dataRpc('.savedId','saveFeed',record='=.record', _onResult=""" genro.formById('rss').saved(); FIRE .refresh;""",nodeId='rss_saver') pane.dataRecord('.record','rss.feed',pkey='=.curr.pkey',nodeId='rss_loader', _onResult="genro.formById('rss').loaded()") def rpc_saveFeed(self,record=None,**kwargs): tblfeed = self.db.table(self.maintable) if not record['id']: record['username'] = self.user tblfeed.insert(record) else: tblfeed.update(record) self.db.commit() return record['id'] def rpc_getFeeds(self): results = self.db.table(self.maintable).getFeeds(user = self.user) return results

def rpc_getItems(self,url=None,**kwargs): rss=Bag(url)['rss.channel'].digest('#v') rows = Bag() for i,item in enumerate(rss): if isinstance(item,Bag): rows.setItem('n_%i' %i,None,title=item['title'],link=item['link'],description=item['description']) return rows def item_struct(self): struct = self.newGridStruct() r = struct.view().rows() r.cell('title', name='!!Title', width='20em',classes='titleCell') r.cell('description', name='!!Description', width='50em',classes='descCell') return struct def top(self,pane): pane.includedView(storepath='rss.rows', nodeId='rssItemsGrid',autoWidth=True, selected_link='rss.link', struct=self.item_struct())

RSS Reader

109 righe

sabato 29 maggio 2010

Page 74: GenroPy, un framework innovativo per applicazioni web AJAX

Presente Futuro

sabato 29 maggio 2010

Page 75: GenroPy, un framework innovativo per applicazioni web AJAX

Futuro

Community, Community, Community

sabato 29 maggio 2010

Page 76: GenroPy, un framework innovativo per applicazioni web AJAX

Grazie!

Roberto Lupi

[email protected]://www.medmediagroup.it/

GenroPyhttp://www.genropy.org/

http://blog.lupi-software.com/http://svn.genropy.org/genro/trunk

@robertolupi

sabato 29 maggio 2010