/tags/2.0/htdocs/data/public/anagrafiche.mql |
---|
0,0 → 1,172 |
<%doc> |
</%doc> |
<%method FROM>anagrafiche</%method> |
<%method FUNZIONE>Anagrafiche</%method> |
<%method DESCRIPTION>Anagrafiche Utenti</%method> |
<%method CHILDREN>anagrafiche_gruppi</%method> |
<%method CHILDREN_FIELDS>id</%method> |
<%method FIELDS>nome, cognome, codice_fiscale, descrizione, indirizzo, provincia, citta, tel1, tel2, cell_sms, |
email, login, password, no_psw_expiration, no_change_password, concurrent_sessions</%method> |
<%method FIELDS_NOT_NULL>nome, cognome</%method> |
%# invio il campo 'password' vuoto e non modificabile |
<%method SELECT_FIELDS>nome, cognome, codice_fiscale, descrizione, indirizzo, provincia, citta, tel1, tel2, cell_sms, |
email, login, '' as password, no_psw_expiration, no_change_password, concurrent_sessions</%method> |
<%method FIELDS_DESCR>Nome\, Cognome, Codice Fiscale, Descrizione, Indirizzo, Provincia\, Città, Telefono\, 2° Telefono, Cell. SMS, |
E-mail, Login, Password\, Blocco scadenza psw\, Blocco cambio psw\, sessioni simultanee</%method> |
<%method FIELDS_NEW>,,,,,,,,,,,,,,</%method> |
<%method FIND_FIELDS>login, nome, cognome, descrizione, codice_fiscale</%method> |
<%method DELETE>\ |
<%args>$KEY</%args> |
delete from anagrafiche_gruppi where id_anagrafiche = <%$KEY%>; |
delete from <&SELF:FROM&> where <&SELF:KEY&> = <%$KEY%>; |
</%method> |
<%method FIELDS_RO>\ |
% if(!$Session{Group_Admins}){ |
*\ |
% } |
</%method> |
<%method FIELDS_NO_WRITE>\ |
</%method> |
<%method WHERE></%method> |
<%method ORDER>order by upper(cognome), upper(nome), upper(login)</%method> |
<%method password_FIELD> |
<& /input/string.comp, %ARGS, length => 18 &> |
</%method> |
<%method codice_fiscale_FIELD><& /input/codfisc_pi.comp, %ARGS &></%method> |
<%method PARAMETERS_SELECT_FIELDS>cognome, nome</%method> |
<%method login_CHECK> |
<%args> |
$KEY => undef |
$VALUE |
</%args> |
<%perl> |
length($VALUE) || return; |
# verifico che la login indicata non sia già presente |
my $sth = $KEY ? |
ExecQuery('Check unique login', undef, qq{ |
select id from public.anagrafiche where login = ? and id != ? |
}, $VALUE, $KEY) : |
ExecQuery('Check unique login', undef, qq{ |
select id from public.anagrafiche where login = ? |
}, $VALUE); |
$Session{Dbh}->commit; |
if($sth->rows){ |
</%perl> |
La login (<% $VALUE %>) è già utilizzata. |
% } |
<%perl> |
# verifico che la login indicata non sia tra quelle proibite |
$sth = ExecQuery('Check reserved login', undef, qq{ |
select id from public.reserved_login where login = ? |
}, $VALUE); |
if($sth->rows){ |
</%perl> |
La login (<% $VALUE %>) è riservata. |
% } |
</%method> |
<%method PRE_UPDATE> |
<%args> |
$FIELDS_UPDATE |
$PARAMS |
</%args> |
<%perl> |
$m->comp('SELF:PRE_INSERT', FIELDS_INSERT => $FIELDS_UPDATE, PARAMS => $PARAMS); |
</%perl> |
</%method> |
<%method POST_UPDATE> |
<%args> |
$KEY |
$PARAMS |
</%args> |
<& SELF:ChangePassword, KEY => $KEY, PARAMS => $PARAMS &> |
</%method> |
<%method PRE_INSERT> |
<%args> |
$FIELDS_INSERT |
$PARAMS |
</%args> |
<%perl> |
if(defined $FIELDS_INSERT->{password}){ |
$PARAMS->{password} = $FIELDS_INSERT->{password}; |
delete $FIELDS_INSERT->{password}; |
} |
</%perl> |
</%method> |
<%method POST_NO_INSERT> |
<%args> |
$KEY |
$PARAMS |
</%args> |
<& SELF:ChangePassword, KEY => $KEY, PARAMS => $PARAMS &> |
</%method> |
<%method POST_NO_UPDATE> |
<%args> |
$KEY |
$PARAMS |
</%args> |
<& SELF:ChangePassword, KEY => $KEY, PARAMS => $PARAMS &> |
</%method> |
<%method POST_INSERT> |
<%args> |
$KEY |
$PARAMS |
</%args> |
<& SELF:ChangePassword, KEY => $KEY, PARAMS => $PARAMS &> |
</%method> |
<%method ChangePassword> |
<%args> |
$KEY |
$PARAMS |
</%args> |
<%perl> |
if(defined $PARAMS->{password}){ |
$Session{Dbh}->commit; |
# recupero la login utente |
my $sth = ExecQuery('User login', undef, q{ |
select id, login, password from public.anagrafiche where id = ? |
}, $KEY); |
my($id, $login, $password) = $sth->rows ? @{$sth->fetchrow_arrayref} : undef; |
if($login){ |
# cambiamento password e forzo richiesta cambio password all'utente |
my $err_message = $r->auth_type->update_password($r, $login, $PARAMS->{password}, 1); |
if($err_message){ |
BrowserAlert('Password non '.($password ? 'sostituita' : 'inserita')."\n\n" . $err_message); |
}else{ |
$password && BrowserAlert('Password sostituita'); |
} |
}else{ |
if($id){ |
BrowserAlert('Non è codificata la login dell\'utente'); |
}else{ |
BrowserAlert('Errore inaspettato nel cambio password: '.$sth->errstr); |
} |
} |
} |
</%perl> |
</%method> |
/tags/2.0/htdocs/data/public/anagrafiche_gruppi.mql |
---|
0,0 → 1,78 |
<%doc> |
Tabella "public.anagrafiche_gruppi" |
Colonna | Tipo | Modificatori |
----------------+---------+---------------------------------------------------------- |
id | integer | not null default nextval('anagrafiche_gruppi_seq'::text) |
id_anagrafiche | integer | not null |
id_gruppi | integer | not null |
Indici: |
"anagrafiche_gruppi_pkey" chiave primaria, btree (id) |
"fki_anagrafiche_gruppi_id_anagrafiche" btree (id_anagrafiche) |
"fki_anagrafiche_gruppi_id_gruppi" btree (id_gruppi) |
Vincoli di integrità referenziale |
"anagrafiche_gruppi_id_gruppi" FOREIGN KEY (id_gruppi) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT |
"anagrafiche_gruppi_id_anagrafiche" FOREIGN KEY (id_anagrafiche) REFERENCES anagrafiche(id) ON UPDATE RESTRICT ON DELETE RESTRICT |
</%doc> |
<%method FUNZIONE>Anagrafiche</%method> |
<%method DESCRIPTION>Gruppi a cui appartiene l'utente</%method> |
<%method FIELDS>id_gruppi</%method> |
<%method FIELDS_NOT_NULL>id_gruppi</%method> |
<%method FIELDS_DESCR>Gruppi</%method> |
%# formato: idref:table:key |
%# idref = chiave_locale key = tabella padre |
<%method FATHER>id_anagrafiche:anagrafiche</%method> |
<%method PRE_UPDATE> |
<%args> |
$KEY |
$FIELDS_UPDATE |
</%args> |
<%perl> |
$m->comp('SELF:PRE_INSERT', FIELDS_INSERT => $FIELDS_UPDATE); |
</%perl> |
</%method> |
<%method PRE_INSERT> |
<%args> |
$FIELDS_INSERT |
</%args> |
<%perl> |
# chiamata anche per l'inserimento di un nuovo record |
if(!$Session{Group_Admins}){ # se Admins non occorre alcun controllo |
my $id_gruppi = $FIELDS_INSERT->{'id_gruppi'}; |
# verifico che l'utente corrente abbia diritto di assegnare il gruppo indicato |
# Nota: l'interfaccia grafica propone gia la lista corretta. Il controllo viene fatto |
# per motivi di sicurezza |
my $query = <<__SQL__; |
select distinct |
gruppi.id |
from |
gruppi_modifica left join gruppi on gruppi.id = gruppi_modifica.id_gruppo_modifica |
where |
gruppi.id = ? and |
gruppi_modifica.id_gruppo in ( |
select distinct |
gruppi.id |
from gruppi |
left join anagrafiche_gruppi on anagrafiche_gruppi.id_gruppi = gruppi.id |
left join anagrafiche on anagrafiche.id = anagrafiche_gruppi.id_anagrafiche |
where |
anagrafiche.login = ? |
) |
__SQL__ |
my $sth = $Session{Dbh}->prepare($query); |
$sth->execute($id_gruppi, $Session{Login}); |
if($sth->rows != 1){ |
# annullo l'inserimento o modifica annullando il campo |
delete $FIELDS_INSERT->{'id_gruppi'}; |
die "Richiesta di assegnazione del gruppo (id=$id_gruppi) non autorizzata!\n"; |
} |
} |
</%perl> |
</%method> |
/tags/2.0/htdocs/data/public/funzioni.mql |
---|
0,0 → 1,132 |
<%method FROM>funzioni</%method> |
<%method FUNZIONE>Funzioni</%method> |
<%method DESCRIPTION>Funzioni applicative</%method> |
<%method CHILDREN>funzioni_permessi, funzioni_help</%method> |
<%method CHILDREN_FIELDS>id, id</%method> |
<%method FIELDS>nome, descrizione, commento, menu_ord, menu_contents, menu_father_id, menu_status, menu_cmdtype, menu_icon, menu_style, menu_command</%method> |
<%method FIELDS_NOT_NULL>nome</%method> |
<%method FIELDS_DESCR>Nome, Descrizione, Commento, Ord\, Menu\, Menu padre, Menu avviso, Tipo comando\, Icona, Menu style, Comando Menu</%method> |
<%method FIELDS_NO_WRITE>permissions</%method> |
<%method FIELDS_NEW>,,,,,,,,,,,</%method> |
<%method FIND_FIELDS>\ |
nome, descrizione, menu_contents, menu_father_id |
</%method> |
<%method ORDER>order by menu_ord, nome, id</%method> |
<%method menu_ord_FIELD><& /input/number.comp, ValMin => 0, ValMax => 9999, length => 4, NumDec => 0, NumCifre => 4, %ARGS &></%method> |
<%method commento_FIELD>\ |
<& /input/string.comp, %ARGS, rows=>2, cols=>80 &> |
</%method> |
<%method menu_cmdtype_FIELD>\ |
<& /input/select.comp, %ARGS, list => [ |
'' => 'nessun comando', |
'u' => 'Link WEB', |
'U' => 'Link WEB - applicando eval Perl', |
'j' => 'Client Javascript', |
'J' => 'Client Javascript - applicando eval Perl', |
]&> |
</%method> |
<%method menu_style_FIELD>\ |
<& /input/string.comp, %ARGS, width => '500' &> |
</%method> |
<%method menu_command_FIELD>\ |
<& /input/string.comp, %ARGS, rows=>4, cols=>80 &> |
</%method> |
<%method menu_father_id_FIELD>\ |
<& SELF:GenericSelect_FIELD, from => 'sel_funzioni', %ARGS, widget => 'htmlselect', width => 120 &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'sel_funzioni' |
</%attr> |
</%method> |
<%method DELETE>\ |
<%args>$KEY</%args> |
delete from gruppi_funzioni where id_funzioni = <%$KEY%>;\ |
delete from <&SELF:FROM&> where <&SELF:KEY&> = <%$KEY%>; |
</%method> |
<%doc> |
########################## Selettore delle Icone ####################### |
ATTENZIONE: quando sarà disponibile il widget select con il componente di dojo |
si potrà eliminare questa 'pezza' |
Estraggo l'elenco dei nomi delle classi delle icone disponibili |
dal file /css/icons_controls.css che contiene delle righe del tipo: |
.masonSqlIcons.cancel { background-position: 0px 0px; } |
.masonSqlIcons.change { background-position: -22px 0px; } |
</%doc> |
<%method menu_icon_FIELD> |
<%args> |
$id # identificatore del componente nel documento HTML |
</%args> |
<%perl> |
my $css = $m->scomp('/css/icons_controls.css'); |
my @list; |
$css =~ s/^\s*\.masonSqlIcons\.(\w+)\s*\{/push(@list,$1)/meg; |
</%perl> |
<script> |
require(["dojo/parser", "dijit/form/Select"]); |
</script> |
<span id="<% $id %>"> |
<div id="<% $id %>_dojo" data-dojo-type="dijit/form/Select" style="width:140px; height:28px;" maxHeight="-1"> |
<span value="">...</span> |
% foreach my $value (@list){ |
<span value="<% $value %>"><span class="dijitInline masonSqlIcons <% $value %>"></span> <% $value %></span> |
% } |
</div> |
</span> |
<script> |
require(["dojo/dom", "dijit/registry", "dojo/dom-class"], function (dom, registry, domClass){ |
masonSql.once('ready', function(data){ |
var Obj = Input_Init('<% $id %>', 'Icona del menu'); |
Obj.dojo_widget = registry.byId('<% $id %>_dojo'); |
Obj.get_value = function(){ |
return this.dojo_widget.get('value'); |
}; |
Obj.set_value = function(value){ |
return this.dojo_widget.set('value', value); |
}; |
Obj.Readonly = function(read){ |
if(read == null){ |
return this.dojo_widget.get('readOnly'); |
}else{ |
this.dojo_widget.set('readOnly', read); |
this.set_status(); |
return read; |
} |
}; |
Obj.Readonly(true); |
Obj.set_status = function(status){ |
var classList = this.eval_status(status); |
if(this.prev_classList != classList){ |
this.prev_classList && domClass.remove(this.dojo_widget.domNode, this.prev_classList); |
console.debug('set_status obj <% $id %> status:' + status + ' classList:' + classList + ' className:' + this.className); |
domClass.add(this.dojo_widget.domNode, classList); |
this.prev_classList = classList; |
} |
}; |
window.Id_<% $id %> = Obj; |
}); |
}); |
</script> |
</%method> |
/tags/2.0/htdocs/data/public/gruppi_anagrafiche.mql |
---|
0,0 → 1,22 |
<%doc> |
</%doc> |
<%method FUNZIONE>Gruppi</%method> |
<%method DESCRIPTION>Utenti del gruppo</%method> |
<%method FROM>anagrafiche_gruppi</%method> |
<%method FIELDS>id_anagrafiche</%method> |
<%method FIELDS_NOT_NULL>id_anagrafiche</%method> |
<%method FIELDS_DESCR>Utenti</%method> |
%# formato: idref:table:key |
%# idref = chiave_locale key = tabella padre |
<%method FATHER>id_gruppi:gruppi</%method> |
<%method FIELDS_RO>\ |
% if(!$Session{Group_Admins}){ |
*\ |
% } |
</%method> |
/tags/2.0/htdocs/data/public/gruppi_modifica.mql |
---|
0,0 → 1,38 |
<%doc> |
Tabella "public.gruppi_modifica" |
Colonna | Tipo | Modificatori |
--------------------+---------+------------------------------------------------------- |
id | integer | not null default nextval('gruppi_modifica_seq'::text) |
id_gruppo | integer | not null |
id_gruppo_modifica | integer | not null |
Indici: |
"gruppi_modifica_pkey" chiave primaria, btree (id) |
"fki_gruppi_modifica_id_gruppo" btree (id_gruppo) |
"fki_gruppi_modifica_id_gruppo_modifica" btree (id_gruppo_modifica) |
Vincoli di integrità referenziale |
"gruppi_modifica_id_gruppo" FOREIGN KEY (id_gruppo) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT |
"gruppi_modifica_id_gruppo_modifica" FOREIGN KEY (id_gruppo_modifica) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT |
</%doc> |
<%method FUNZIONE>Gruppi</%method> |
<%method DESCRIPTION>Gruppi modificabili</%method> |
<%method FROM>gruppi_modifica</%method> |
<%method FIELDS>id_gruppo_modifica</%method> |
<%method FIELDS_NOT_NULL>id_gruppo_modifica</%method> |
<%method FIELDS_DESCR>Gruppi</%method> |
<%method id_gruppo_modifica_ALIAS>id_gruppi</%method> |
%# formato: idref:table:key |
%# idref = chiave_locale key = tabella padre |
<%method FATHER>id_gruppo:gruppi</%method> |
<%method FIELDS_RO>\ |
% if(!$Session{Group_Admins}){ |
*\ |
% } |
</%method> |
/tags/2.0/htdocs/data/public/logs.mql |
---|
0,0 → 1,174 |
<%doc> |
</%doc> |
<%flags> |
inherit => 'logs.common.mql' |
</%flags> |
<%method TABLE_ROWS><% $ARGS{'rows'} ? $ARGS{'rows'} : '20' %></%method> |
<%method AUTHORIZED_KEYWORDS>AND, IN</%method> |
<%method IS_WHERE2> |
<%perl> |
my $where = $Session{ARGS}->{where2}; |
if($where && !$where =~ m/^table_name = '\w+\.\w+' AND id_record IN \([\d,]+\)$/){ |
die "SQL injection detection width [$where]. Execution aborted!"; |
} |
return $where; |
</%perl> |
</%method> |
<%method FIELDS_HIDDEN>\ |
% if($m->comp('SELF:IS_WHERE2')){ |
table_name |
% } |
</%method> |
<%method DESCRIPTION>Log modifiche al database da parte degli utenti</%method> |
<%method FIELDS>timestamp, id_anagrafiche, table_name, id_record, field, old_value, new_value</%method> |
<%method FIELDS_DESCR>Data e ora, Utente, <% $Session{Group_Admins} ? 'Scheda (tabella)' : 'Scheda' %>, Id, Campo, Valore precedente, Nuovo valore</%method> |
<%method FIND_FIELDS> |
% if(!$m->comp('SELF:IS_WHERE2')){ |
timestamp, timestamp, id_anagrafiche, table_name, field, old_value, new_value, id_record, id_record |
% } |
</%method> |
<%method FIELDS_RO>*</%method> |
<%method FIELDS_NO_WRITE>*</%method> |
<%method ORDER>order by timestamp desc, id desc</%method> |
<%method timestamp_FIELD><& /input/span.comp, width => 120, %ARGS &></%method> |
<%method timestamp_FIND_FIELD> |
<& /input/timestamp.comp, %ARGS &> |
<%attr> |
find_select_list => ['<=' => '<=', '>=' => '>='] |
</%attr> |
</%method> |
<%method field_OUT_FILTER>\ |
<%args> |
$Value |
$Key |
$names |
$fetch_row |
</%args> |
<%perl> |
if(length $Value){ |
my $field = $fetch_row->{field}; |
if($Value eq 'ARC.'){ |
$Value = 'Arc. file'.($Session{Group_Admins} ? " ($field)" : ''); |
}else{ |
my $table_name = $fetch_row->{table_name}; |
$table_name =~ s/\./\//; |
my $base_comp = $Session{"Logs_report_COMP_$table_name"}; |
# cerco del campo $field l'attributo 'select_from' |
if($base_comp){ |
# valuto la descrizione del campo corrispondente all'oggetto .mql |
my $descr = $base_comp->scall_method('INFO', NAME => $field, WHAT => 'DESCR'); |
$Value = $descr ? $descr.($Session{Group_Admins} ? " ($field)" : '') : $field ; |
$Value =~ s/[\\\/]//sg; |
}else{ |
$Value = $field; |
} |
$Value =~ s/\<br\>/ /ig; |
} |
} |
</%perl> |
$_ = '<%$Value |js%>'; |
</%method> |
<%method field_FIELD> |
<& /input/string.comp, %ARGS, size => $Session{Group_Admins} ? 18 : 12 &> |
</%method> |
<%method new_value_OUT_FILTER>\ |
<%args> |
$Value |
$Key |
$names |
$fetch_row |
</%args> |
<%perl> |
my $param; |
if(length $Value){ |
my $table_name = $fetch_row->{table_name}; |
$table_name =~ s/\./\//; |
my $field = $fetch_row->{field}; |
my $base_comp = $Session{"Logs_report_COMP_$table_name"}; |
# cerco del campo $field l'attributo 'select_from' |
# valuto gli attributi del widget corrispondente all'oggetto .mql, quando esiste |
$param = $base_comp ? FieldFilter_from($base_comp, $field, $Key, $Value, $names, $fetch_row) : ''; |
} |
</%perl> |
$param = '<% $param |js%>'; |
$_ = '<%$Value |js%>'; |
</%method> |
<%method old_value_OUT_FILTER><& SELF:new_value_OUT_FILTER, %ARGS&></%method> |
<%method old_value_FIELD> |
<& /input/span.comp, %ARGS, width => 160, disp_template => q{P.join('; ')}.($Session{Group_Admins} ? q{+' ('+P[-1]+')'} : '') &> |
</%method> |
<%method new_value_FIELD> |
<& /input/span.comp, %ARGS, width => 160, disp_template => q{P.join('; ')}.($Session{Group_Admins} ? q{+' ('+P[-1]+')'} : '') &> |
</%method> |
<%method old_value_FIND_FIELD> |
<& /input/string.comp, %ARGS &> |
</%method> |
<%method new_value_FIND_FIELD> |
<& /input/string.comp, %ARGS &> |
</%method> |
<%method FORM_INCLUDE_POST> |
<%args> |
$Display |
$Recordset |
</%args> |
<script> |
// chiamata da id_record_FIELD per visualizzare il form corrispondente al campo variato |
<% $Display %>.view_form = function (widget){ |
// verifico che il widget non sia disabilitato |
if(widget.Readonly()){ |
return false; |
} |
var table_name = <%$Display%>.getField('table_name', widget.dbRow).get_value(); |
// costruisco un oggetto 'display' minimale con i soli elementi necessari a lanciare il form |
var display_log = { |
prefix: 'Log_detail', |
dataBinding: new DataBinding('Log_detail_db', 'log', 'Log ' + table_name), |
gotoRecords: function (mode, key, recordset){ |
return this.dataBinding.gotoRecords(mode, key, recordset); |
}, |
openFormDetailByKey: DisplayBinding_openFormDetailByKey |
}; |
var d = new Date(); |
display_log.openFormDetailByKey('rewind', null, table_name, 1000, 600, 'Log ' + table_name, { |
U: d.getTime() + '' + Math.floor(1000 * Math.random()), |
rows: null, |
disp_update: '', |
pk: widget.get_value() |
}); |
} |
<%$Display%>.onchange = function(){ |
%# // disabilito i pulsanti che puntano a record cancellati |
var Col = this.dataBinding.pos_name['id_record']; |
for(var Row=0; Row<this.fields.length; Row++){ |
var Button = this.fields[Row][Col]; |
if(Button.get_param() == 'D'){ |
Button.Readonly(true); |
} |
} |
}; |
</script> |
</%method> |
/tags/2.0/htdocs/data/public/messages.mql |
---|
0,0 → 1,194 |
<%doc> |
Gestione messaggi |
</%doc> |
<%method FUNZIONE>Messages</%method> |
<%method DESCRIPTION>Messaggi inviati agli utenti</%method> |
<%method FIELDS> |
owner, modification_time, |
<% $r->dir_config('MailSmtpServer') ? 'email,' : '' %> |
transmission_time, |
<% $r->dir_config('SMSPlatform') ? 'sms,' : '' %> |
subject, |
<% $r->dir_config('SMSPlatform') ? 'short_message,' : '' %> |
message |
</%method> |
<%method FIELDS_NEW>,,<% $r->dir_config('MailSmtpServer') ? ',' : '' %>,<% $r->dir_config('SMSPlatform') ? ',' : '' %>,<% $r->dir_config('SMSPlatform') ? '' : '' %>,</%method> |
<%method FIELDS_NOT_NULL>message</%method> |
<%method FIELDS_DESCR> |
Proprietario, Data ultima modifica\ |
<% $r->dir_config('MailSmtpServer') ? '\,E-Mail' : '' %>, |
Data di trasmissione\ |
<% $r->dir_config('SMSPlatform') ? '\,S.M.S.' : '' %>, |
Oggetto\ |
<% $r->dir_config('SMSPlatform') ? ',Messaggio breve' : '' %>, |
Messaggio |
</%method> |
<%method FIELDS_RO>owner, modification_time, transmission_time</%method> |
<%method FIND_FIELDS>owner, transmission_time, transmission_time, subject<% $r->dir_config('SMSPlatform') ? ', short_message' : '' %>, message</%method> |
<%method PERMISSION><%perl> |
my $permission = $m->scomp('SELF:PERMISSION_BY_PROFILE'); |
my $Record0 = $Session{ARGS}->{Record0}; |
# disabilito cancellazione e modifica se record trasmesso |
if($Record0->{'modification_time'} && $Record0->{'transmission_time'}){ |
$permission =~ s/DELETE//; |
$permission =~ s/UPDATE//; |
} |
$m->out($permission); |
</%perl></%method> |
<%method ORDER>order by modification_time desc, id desc</%method> |
<%method CHILDREN>messages_users</%method> |
<%method CHILDREN_FIELDS>id</%method> |
<%method message_FIELD><& /input/string.comp, %ARGS, rows => 5, cols => 80 &></%method> |
<%method message_FIND_FIELD> |
<& /input/string.comp, %ARGS &> |
<%attr> |
find_select_list => ['~*' => '~*', 'ilike' => 'ilike'] |
</%attr> |
</%method> |
<%method short_message_FIELD><& /input/string.comp, %ARGS, rows => 2, cols => 80 &></%method> |
<%method short_message_FIND_FIELD> |
<& /input/string.comp, %ARGS &> |
<%attr> |
find_select_list => ['~*' => '~*', 'ilike' => 'ilike'] |
</%attr> |
</%method> |
<%method owner_FIELD>\ |
<& SELF:id_anagrafiche_FIELD, %ARGS, empty_descr => 'Gestore sistema' &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'anagrafiche' |
</%attr> |
</%method> |
<%method PRE_UPDATE> |
<%args> |
$KEY |
$FIELDS_UPDATE |
</%args> |
<%perl> |
$m->comp('SELF:PRE_INSERT', FIELDS_INSERT => $FIELDS_UPDATE); |
</%perl> |
</%method> |
<%method PRE_INSERT> |
<%args> |
$FIELDS_INSERT |
</%args> |
<%perl> |
$FIELDS_INSERT->{'owner'} = $Session{User_id}; |
my($sec, $min, $hour, $mday, $mon, $year) = localtime time; |
$FIELDS_INSERT->{'modification_time'} = sprintf '%04i-%02i-%02i %02i:%02i:%02i', 1900+$year, $mon+1, $mday, $hour, $min, $sec; |
</%perl> |
</%method> |
<%method FIELDS_INCLUDE_POST> |
<%args> |
$Display |
</%args> |
<br> |
<& /input/button.comp, caption => 'Conferma invio messaggio', style => 'display:none;', |
id => $Display.'_send_button', onclick => "$Display.invio_messaggio();" &> |
<br> |
<script> |
<%$Display%>.send_button = document.getElementById('<%$Display%>_send_button'); |
<%$Display%>.invio_messaggio = function(){ |
// valuto se ci sono registrazioni della tabella |
var mess = 'Siete certi di voler inviare il messaggio '; |
mess += this.dataBinding.children[0].max_rows ? 'agli utenti selezionati?' : 'a tutti gli utenti?'; |
if(confirm(mess)){ |
this.callRemote('send', {id:this.dataBinding.keys[0]}); |
} |
} |
</script> |
</%method> |
<%method FORM_INCLUDE_POST> |
<%args> |
$Display |
</%args> |
<script> |
<%$Display%>.onreadonly = function (set){ |
var id = this.dataBinding.keys[0]; |
var transmission_time = this.getField('transmission_time').get_value(); |
// bottone attivo e visibile se record in lettura nonché non vuoto e non trasmesso |
this.send_button.set_value(set ? id && !transmission_time : ''); |
this.send_button.style.display = set && id && !transmission_time ? '' : 'none'; |
} |
<%$Display%>.onchange = function (set){ |
var id = this.dataBinding.keys[0]; |
var transmission_time = this.getField('transmission_time').get_value(); |
// bottone attivo e visibile se record in lettura nonché non vuoto e non trasmesso |
this.send_button.set_value(this.readOnly() ? id && !transmission_time : ''); |
this.send_button.style.display = this.readOnly() && id && !transmission_time ? '' : 'none'; |
} |
</script> |
</%method> |
<%method CALL_REMOTE_send> |
<%args> |
$id |
$dbms_params |
</%args> |
<%perl> |
# verifico se devo inviare a tutti gli utenti o solo ad un elenco ristretto |
my $sth = ExecQuery('Test list users', undef, q{ |
select count(*) from public.messages_users |
where id_messages = ? |
}, $id); |
if($sth->fetchrow_arrayref->[0] >= 1){ |
# esplodo la lista degli utenti se ci sono indicati dei gruppi e modifico lo stato del messaggio |
my $sth = ExecQuery('Explode message\'s list users', undef, q{ |
insert into public.messages_users (id_messages, id_anagrafiche) |
select * from ( |
select distinct |
?::integer as id_messages, |
anagrafiche_gruppi.id_anagrafiche as id_anagrafiche |
from public.messages_users |
left join public.anagrafiche_gruppi on anagrafiche_gruppi.id_gruppi = - messages_users.id_anagrafiche |
left join public.anagrafiche on anagrafiche.id = anagrafiche_gruppi.id_anagrafiche and anagrafiche.login is not null |
where messages_users.id_messages = ?::integer and messages_users.id_anagrafiche < 0 and anagrafiche_gruppi.id_anagrafiche is not null |
) as lista |
where id_anagrafiche not in ( -- escludo dall'inserimento le anagrafiche che sono già nella lista |
select |
messages_users.id_anagrafiche |
from public.messages_users |
where messages_users.id_messages = ?::integer and id_anagrafiche > 0 |
); |
delete from public.messages_users |
where messages_users.id_messages = ?::integer and id_anagrafiche < 0; |
update public.messages set transmission_time = now() where id = ?::integer; |
}, $id, $id, $id, $id, $id); |
}else{ |
# inserisco nella lista tutti gli utenti e modifico lo stato del messaggio |
my $sth = ExecQuery('Insert all users in list', undef, q{ |
insert into public.messages_users (id_messages, id_anagrafiche) |
select |
?::integer as id_messages, |
gruppi_and_anagrafiche.id as id_anagrafiche |
from public.gruppi_and_anagrafiche |
where gruppi_and_anagrafiche.id > 0; |
update public.messages set transmission_time = now() where id = ?::integer; |
}, $id, $id); |
} |
$Session{Dbh}->commit; |
</%perl> |
// aggiorna il record corrente |
<%$dbms_params->{'name'}%>.children[0].loadRecords('reload'); |
</%method> |
/tags/2.0/htdocs/data/public/odt_portion_queries.mql |
---|
0,0 → 1,17 |
<%method FUNZIONE>OdtReports</%method> |
<%method FROM>odt_report_portions</%method> |
<%method DESCRIPTION>Portion Queries</%method> |
<%method FIELDS>name, query</%method> |
<%method FIELDS_DESCR>Portion Name, Query</%method> |
<%method FIND_FIELDS>name</%method> |
<%method FATHER>id_odt_reports:odt_reports</%method> |
<%method ORDER>order by ord, id</%method> |
<%method CHILD_TEMPLATE>FORM</%method> |
<%method name_FIELD><& /input/string.comp, %ARGS, size => 30 &></%method> |
<%method query_FIELD><& /input/string.comp, %ARGS, rows => 35, cols => 100 &></%method> |
/tags/2.0/htdocs/data/public/odt_report_fields.mql |
---|
0,0 → 1,15 |
<%method FUNZIONE>OdtReports</%method> |
<%method DESCRIPTION>Report Fields</%method> |
<%method TABLE_ROWS>14</%method> |
<%method FATHER>id_odt_reports:odt_reports</%method> |
<%method FIELDS>key, function, format</%method> |
<%method FIELDS_DESCR>Name, Value, Formatting</%method> |
<%method ORDER>order by key, id</%method> |
<%method key_FIELD><& /input/string.comp, %ARGS, width => 100 &></%method> |
<%method function_FIELD><& /input/string.comp, %ARGS, width => 500 &></%method> |
<%method format_FIELD><& /input/string.comp, %ARGS, width => 200 &></%method> |
/tags/2.0/htdocs/data/public/odt_report_portions.mql |
---|
0,0 → 1,49 |
<%method FROM>odt_report_portions</%method> |
<%method FUNZIONE>OdtReports</%method> |
<%method DESCRIPTION>Report Portions</%method> |
<%method DETAIL_FROM>public/odt_portion_queries</%method> |
<%method TABLE_ROWS>14</%method> |
<%method FIELDS>ord, name, type, id_father, file_name, obj_ref</%method> |
<%method FIELDS_NOT_NULL>ord</%method> |
<%method FIELDS_DESCR>Order, Portion Name, Portion Type, Father Portion, Filename, Obj. Reference</%method> |
<%method ORDER>order by ord, id</%method> |
<%method FATHER>id_odt_reports:odt_reports</%method> |
<%method name_FIELD><& /input/string.comp, %ARGS, width => 70 &></%method> |
<%method ord_FIELD><& /input/number.comp, %ARGS, length => 3 &></%method> |
<%method file_name_FIELD><& /input/string.comp, %ARGS, width => 200 &></%method> |
<%method obj_ref_FIELD><& /input/string.comp, %ARGS, width => 200 &></%method> |
<%method type_FIELD> |
<& /input/select.comp, %ARGS, list => [ |
'' => '', |
'base_report' => 'ODT base template', |
'odt_section' => 'ODT section', |
'odt_table' => 'ODT table', |
'odt_file' => 'ODT file', |
'pdf_file' => 'PDF file (attach to PDF)', |
'pdf_report' => 'ODT report (attach to PDF)', |
]&>\ |
</%method> |
<%method id_father_FIELD> |
<& SELF:GenericSelect_FIELD, buffer => 'father', from => 'sel_odt_report_portions', widget => 'htmlselect', width => '80px', %ARGS &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'sel_odt_report_portions' |
</%attr> |
</%method> |
/tags/2.0/htdocs/data/public/sel_funzioni.mql |
---|
0,0 → 1,13 |
<%flags> |
inherit => 'funzioni.mql' |
</%flags> |
<%method FIELDS>nome</%method> |
<%method SELECT_FIELDS>nome</%method> |
<%method FIELDS_DESCR>Nome funzione</%method> |
<%method ORDER>nome, id</%method> |
<%method WHERE>id != <% $Session{ARGS}{child_id} || -1 %></%method> |
/tags/2.0/htdocs/data/public/sel_gruppi_and_anagrafiche.mql |
---|
0,0 → 1,17 |
<%doc> |
Elenco dei gruppi e degli utenti |
</%doc> |
<%method FROM>gruppi_and_anagrafiche</%method> |
<%method FUNZIONE>Anagrafiche</%method> |
<%method DESCRIPTION>Gruppi e Utenti</%method> |
<%method FIELDS_DESCR>Gruppo o utente</%method> |
<%method FIELDS>descrizione</%method> |
<%method SELECT_FIELDS>CASE WHEN id < 0 THEN 'GRUPPO - ' || descrizione || ' -' ELSE descrizione END</%method> |
<%method ORDER>id > 0, descrizione, id</%method> |
/tags/2.0/htdocs/data/public/session.mql |
---|
0,0 → 1,26 |
<%method FUNZIONE>Session</%method> |
<%method FROM>session</%method> |
<%method DESCRIPTION>Sessioni utenti</%method> |
<%method FIELDS>id_anagrafiche, user_ip, session, session_time, session_inactive_time, user_agent</%method> |
<%method FIELDS_DESCR>Utente, Indirizzo IP, Sessione, Ultima login, Inattivo, Browser</%method> |
<%method FIND_FIELDS>id_anagrafiche, user_ip, session, session_time</%method> |
<%method FORM_TYPE>TABLE</%method> |
<%method TABLE_ROWS>20</%method> |
<%method ORDER>session_time DESC, id DESC</%method> |
<%method session_inactive_time_OUT_FILTER> |
my $m = int(time/60) - $_; |
my $h = int($m/60); |
$m -= $h*60; |
$_ = $h || $m ? sprintf('%02i:%02i', $h, $m) : ''; |
</%method> |
<%method user_ip_FIELD><& /input/string.comp, width => '100px', %ARGS &></%method> |
<%method session_inactive_time_FIELD><& /input/span.comp, width => '48px', %ARGS &></%method> |
<%method user_agent_FIELD><& /input/span.comp, width => '180px', %ARGS &></%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/data/public/user_messages.mql |
---|
0,0 → 1,75 |
<%method FROM>messages</%method> |
<%method FUNZIONE>User_messages</%method> |
<%method FORM_TYPE>TABLE</%method> |
<%method TABLE_ROWS>10</%method> |
<%method CHILDREN>user_messages_body</%method> |
<%method CHILDREN_FIELDS>messages.id</%method> |
<%method DESCRIPTION>Messaggi inviati all'utente <%$Session{Nominativo}%></%method> |
<%method FIELDS>owner, transmission_time, notification_time, subject</%method> |
<%method FIELDS_DESCR>Mittente\, Data di trasmissione, Data di notifica, Oggetto</%method> |
<%method WHERE>transmission_time is not null</%method> |
<%method ORDER>notification_time desc, transmission_time desc, id desc</%method> |
<%method ATTRS> |
notification_time => { |
TYPE => 'timestamp' |
} |
</%method> |
<%method JOIN_TABLES> |
public.messages |
inner join public.messages_users on messages_users.id_messages = messages.id |
and messages_users.id_anagrafiche = <%$Session{User_id}%> |
</%method> |
<%method FIELDS_RO>*</%method> |
<%method FIND_FIELDS>owner, subject, transmission_time, transmission_time, notification_time, notification_time</%method> |
<%method subject_FIELD> |
<& /input/string.comp, %ARGS, width => '400' &> |
</%method> |
<%method subject_FIND_FIELD> |
<& /input/string.comp, %ARGS &> |
<%attr> |
find_select_list => ['~*' => '~*', 'ilike' => 'ilike'] |
</%attr> |
</%method> |
<%method owner_FIELD>\ |
<& SELF:id_anagrafiche_FIELD, %ARGS, empty_descr => 'Gestore sistema' &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'anagrafiche' |
</%attr> |
</%method> |
<%method FORM_INCLUDE_POST> |
<%args> |
$Display |
$Recordset |
</%args> |
<script> |
<%$Display%>.onchange = function (){ |
require(["dojo/dom-class"], function(domClass){ |
for(var row = 0; row < <%$Recordset%>.keys.length; row++){ |
if(<%$Recordset%>.keys[row] && !<%$Recordset%>.get_value('notification_time', row)){ |
domClass.replace(<%$Display%>.getField('subject', row), 'MessagesNewMessage', 'widgetRo'); |
}else{ |
domClass.replace(<%$Display%>.getField('subject', row), 'widgetRo', 'MessagesNewMessage'); |
} |
} |
}); |
} |
</script> |
</%method> |
/tags/2.0/htdocs/data/public/autohandler |
---|
0,0 → 1,35 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2018 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method id_anagrafiche_FIELD>\ |
<& SELF:GenericSelect_FIELD, from => 'public/sel_anagrafiche', widget => 'divselect', width => '200', |
cols => $Session{Group_Admins} ? [100, 100, 100] : [100, 100], |
disp_template => q{P[0] + ' ' + P[1]}.($Session{Group_Admins} ? q{ + (P[2] ? ' (' + P[2] + ')' : '')} : ''), |
%ARGS |
&> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'public/sel_anagrafiche' |
</%attr> |
</%method> |
<%method id_gruppi_FIELD>\ |
<& SELF:GenericSelect_FIELD, width => 220, from => 'public/sel_gruppi', %ARGS &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'public/sel_gruppi' |
</%attr> |
</%method> |
<%method commento_FIELD>\ |
<& /input/string.comp, %ARGS, rows=>6, cols=>60 &> |
</%method> |
/tags/2.0/htdocs/data/public/autorizzazioni.mql |
---|
0,0 → 1,22 |
<%doc> |
</%doc> |
<%method FROM>autorizzazioni</%method> |
<%method FUNZIONE>ListAuth</%method> |
<%method DESCRIPTION>Autorizzazioni</%method> |
<%method FIELDS>nome, descrizione, commento</%method> |
<%method FIELDS_NOT_NULL>nome, descrizione</%method> |
<%method FIELDS_DESCR>Nome autorizzazione, Descrizione, Commento</%method> |
<%method FIELDS_NEW>,,</%method> |
<%method FIND_FIELDS>nome, descrizione</%method> |
<%method ORDER>order by nome</%method> |
/tags/2.0/htdocs/data/public/funzioni.common.mql |
---|
0,0 → 1,18 |
<%method FUNZIONE>Funzioni</%method> |
<%method FROM>funzioni</%method> |
<%method CHILD_TEMPLATE>FORM</%method> |
<%method PERL_EVAL_PRE> |
$ARGS{'disp_navbar'} = 0; # non visualizza il form padre con i pulsanti << < > >> Goto[ ] di navigazione |
$ARGS{'disp_insert'} = 0; # ... pulsante inserimento |
$ARGS{'disp_delete'} = 0; # ... pulsante cancella |
$ARGS{'disp_print'} = 0; # ... pulsante stampa |
$ARGS{'disp_xls'} = 0; # ... pulsante espostazione XLS |
$ARGS{'disp_log'} = 0; # ... pulsante visualizzazione Log |
</%method> |
<%method FATHER>id:funzioni</%method> |
<%method KEY>id</%method> |
/tags/2.0/htdocs/data/public/funzioni_help.mql |
---|
0,0 → 1,15 |
<%flags> |
inherit => 'funzioni.common.mql' |
</%flags> |
<%method DESCRIPTION>Help</%method> |
<%method FIELDS>help</%method> |
<%method FIELDS_DESCR>Help</%method> |
<%method help_FIELD> |
<& /input/FCKeditor.comp, %ARGS, width => '800px', height => '400px', |
editWidth => '800px', editHeight => '400px' &> |
</%method> |
/tags/2.0/htdocs/data/public/funzioni_permessi.mql |
---|
0,0 → 1,87 |
<%flags> |
inherit => 'funzioni.common.mql' |
</%flags> |
<%method DESCRIPTION>Permessi</%method> |
<%method FIELDS>permissions</%method> |
<%method SELECT_FIELDS>'' as permissions</%method> |
<%method FIELDS_DESCR>Permessi</%method> |
<%method FIELDS_NO_WRITE>permissions</%method> |
<%method FIELDS_NEW>perm:</%method> |
<%method permissions_FIELD> |
<& /input/Permission.comp, %ARGS &> |
</%method> |
<%method UpdatePermissions>\ |
<%args> |
$KEY |
$PERM |
</%args> |
<%perl> |
my @permissions = split /\n/, $PERM; |
# DEBUG $PLogger->debug(sub{ '?' x 20, "$KEY => permission: [$PERM]"; }); |
if(shift(@permissions) eq 'perm:'){ |
# cancello i permessi presenti |
my $sth = $Session{Dbh}->prepare(q| |
delete from gruppi_funzioni where id_funzioni = ?; |
|); |
$sth->execute($KEY); |
# nuovi permessi ... |
$sth = $Session{Dbh}->prepare(q|insert into gruppi_funzioni (id_funzioni, id_gruppi, id_autorizzazioni) values (?, ?, ?)|); |
foreach my $row (@permissions){ |
my($group, $perm) = split /\s+/, $row, 2; |
$group =~ s/^g//; |
$perm =~ s/^p//; |
$PLogger->debug(sub{ "NEW QUERY-permissions_IN_FILTER=[insert into gruppi_funzioni (id_funzioni, id_gruppi, id_autorizzazioni) values ($KEY, $group, $perm)]"; }); |
$sth->execute($KEY, $group, $perm); |
} |
} |
</%perl> |
</%method> |
<%method POST_INSERT>\ |
<%args> |
$KEY |
$ROW |
</%args> |
<%perl> |
# 10== posizione del campo permissions in <%method FIELDS> |
$m->scomp('SELF:UpdatePermissions', KEY => $KEY, PERM => $ROW->[10]); |
</%perl> |
</%method> |
<%method permissions_IN_FILTER>\ |
<%args> |
$Key |
$Value |
</%args> |
<%perl> |
# solo se c'è la chiave del record effettuo l'aggiornamento |
if($Key){ |
$m->scomp('SELF:UpdatePermissions', KEY => $Key, PERM => $Value); |
} |
</%perl>\ |
</%method> |
<%method permissions_OUT_FILTER>\ |
<%args> |
$Key |
</%args> |
<%perl> |
my $permissions = "perm:\n"; |
# devo estrarre i permessi associati ai gruppi per la funzione di id = $Key |
my $sth = $Session{Dbh}->prepare(q|select id_gruppi, id_autorizzazioni from gruppi_funzioni where id_funzioni = ?|); |
$sth->execute($Key); |
while(my $auth = $sth->fetchrow_arrayref){ |
$permissions .= "g$auth->[0] p$auth->[1]\n"; |
} |
</%perl> |
$_ = q|<%$permissions%>|; |
</%method> |
/tags/2.0/htdocs/data/public/gruppi.mql |
---|
0,0 → 1,31 |
<%doc> |
Tabella "public.gruppi" |
Colonna | Tipo | Modificatori |
-------------+------------------------+---------------------------------------------- |
id | integer | not null default nextval('gruppi_seq'::text) |
nome | character varying(16) | |
descrizione | character varying(60) | |
commento | character varying(240) | |
Indici: |
"gruppi_pkey" chiave primaria, btree (id) |
"idx_nome" unica, btree (nome) |
</%doc> |
<%method FROM>gruppi</%method> |
<%method FUNZIONE>Gruppi</%method> |
<%method DESCRIPTION>Gruppi</%method> |
<%method FIELDS>nome, descrizione, commento</%method> |
<%method FIELDS_NOT_NULL>nome, descrizione</%method> |
<%method FIELDS_DESCR>Nome, Descrizione, Commento</%method> |
<%method FIND_FIELDS>nome, descrizione</%method> |
<%method ORDER>order by nome</%method> |
<%method CHILDREN>gruppi_anagrafiche, gruppi_modifica</%method> |
<%method CHILDREN_FIELDS>id, id</%method> |
/tags/2.0/htdocs/data/public/gruppi_funzioni.mql |
---|
0,0 → 1,28 |
<%doc> |
</%doc> |
<%method FUNZIONE>Gruppi</%method> |
<%method DESCRIPTION>Autorizzazioni</%method> |
<%method FIELDS>id_gruppi, id_autorizzazioni</%method> |
<%method FIELDS_NOT_NULL>id_gruppi, id_autorizzazioni</%method> |
<%method FIELDS_DESCR>Gruppo, Autorizzazione</%method> |
<%method FIND_FIELDS>\ |
id_gruppi |
</%method> |
<%method ORDER>order by id_gruppi, id_autorizzazioni</%method> |
<%method id_autorizzazioni_FIELD>\ |
<& SELF:GenericSelect_FIELD, from => 'sel_autorizzazioni', %ARGS &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'sel_autorizzazioni' |
</%attr> |
</%method> |
%# formato: idref:table:key |
%# idref = chiave_locale key = tabella padre |
<%method FATHER>id_funzioni:funzioni</%method> |
/tags/2.0/htdocs/data/public/logs.common.mql |
---|
0,0 → 1,125 |
<%doc> |
Used by logs.mql and logs_report.mql |
</%doc> |
<%method FUNZIONE>Logs</%method> |
<%method FATHER_TEMPLATE>TABLE</%method> |
<%method OUT_FILTER>\ |
<%args> |
$row |
</%args> |
<%perl> |
my $table_name = $row->{table_name}; |
$table_name =~ s/\./\//; |
my $cache_table = "Logs_report_COMP_$table_name"; |
if(!$Session{$cache_table}){ |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
my $table = "$DataBaseUrl/$table_name.mql"; |
my $base_comp = $m->fetch_comp($table); |
my $sth; |
if($base_comp){ |
my $KEY = $base_comp->scall_method('KEY'); |
my $schema = $base_comp->scall_method('SCHEMA'); |
my $query = $base_comp->scall_method('NUMREC', WHERE => qq{where $KEY = ?}); |
$sth = $Session{Dbh}->prepare("SET search_path TO $schema, public;\n$query"); |
} |
# Save base component used when call next <field>_OUT_FILTER filters |
$Session{$cache_table} = $base_comp; |
$Session{'STH_'.$cache_table} = $sth; |
} |
my $base_comp = $Session{$cache_table}; |
my $permission; |
if($base_comp){ |
if($Session{Group_Admins}){ |
# Force LOG permission to Admins |
$permission = 'LOG'; |
}else{ |
# Autorizzazione in base alla configurazione della tabella |
my $method = $base_comp->method_exists('PERMISSION') ? 'PERMISSION' : 'PERMISSION_BY_PROFILE'; |
$permission = $base_comp->scall_method($method); |
} |
}else{ |
# Autorizzo solo se utente amministratore |
$permission = $Session{Group_Admins} ? 'LOG' : undef; |
} |
if(" $permission " !~ m/ LOG /i){ |
my $na = 'N.A.'; |
return { |
id => $row->{id}, |
timestamp => undef, |
id_anagrafiche => undef, |
table_name => undef, |
id_record => undef, |
field => $na, |
old_value => $na, |
new_value => $na |
} |
} |
return $row; |
</%perl> |
</%method> |
<%method table_name_OUT_FILTER>\ |
<%args> |
$Value |
$Key |
$names |
$fetch_row |
</%args> |
<%perl> |
my $param; |
if(length $Value){ |
$Value =~ s/\./\//; |
my $base_comp = $Session{"Logs_report_COMP_$Value"}; |
# cerco del campo $field l'attributo 'select_from' |
$param = $base_comp ? $base_comp->scall_method('DESCRIPTION').($Session{Group_Admins} ? " ($Value)" : '') : "$Value (FORM Cancellato!)"; |
# elimino i tag <*> e </*> |
$param =~ s/<[^>]*>//sg; |
$param =~ s/<\/[^>]*>//sg; |
} |
</%perl> |
$param = '<% $param |js%>'; |
$_ = '<%$Value |js%>'; |
</%method> |
<%method table_name_FIND_FIELD><& /input/string.comp, %ARGS &></%method> |
<%method table_name_FIELD> |
<& /input/span.comp, %ARGS, width => $Session{Group_Admins} ? 160 : 130 &> |
</%method> |
<%method id_record_OUT_FILTER>\ |
<%args> |
$Value |
$Key |
$names |
$fetch_row |
</%args> |
<%perl> |
my $Param = 'D'; |
if(length $Value){ |
my $table_name = $fetch_row->{table_name}; |
$table_name =~ s/\./\//; |
my $sth = $Session{"STH_Logs_report_COMP_$table_name"}; |
if($sth){ |
$sth->execute($Value); |
$Param = $sth->fetchrow_arrayref->[0] ? '' : 'D'; |
}else{ |
$Value = ''; |
} |
} |
</%perl> |
$param = '<% $Param |js%>'; |
$_ = '<%$Value |js%>'; |
</%method> |
<%method id_record_FIND_FIELD><& /input/number.comp, %ARGS &></%method> |
<%method id_record_FIELD> |
<& /input/button.comp, %ARGS, width => 60, caption_value => 1, |
onclick => "this.displayBinding.view_form(this);" |
&> |
</%method> |
/tags/2.0/htdocs/data/public/logs_report.mql |
---|
0,0 → 1,425 |
<%doc> |
Used to create variation logs on archives (widget input/Files.mql) |
Creation sql commands in file utility/sql/create_logs_report.mql |
</%doc> |
<%flags> |
inherit => 'logs.common.mql' |
</%flags> |
<%once> |
use String::Diff qw(diff_merge); |
sub diff_report($$$$$$$$){ |
my($KEY, $fields, $fields_descr, $comp, $old_record, $new_record, $report_inserito, $report_cancellato) = @_; |
# elaboro il report delle variazioni accumulate prima del LOG corrente |
my @report; |
if($report_inserito){ |
push @report, '(RECORD INSERITO)'; |
} |
foreach my $key (keys %$new_record){ |
# salto se il campo è la chiave primaria |
$key eq $KEY && next; |
if($old_record->{$key} ne $new_record->{$key}){ |
# campo variato |
my($old_val, $old_param) = Call_OutFieldFilter($key, $old_record->{$KEY}, $old_record->{$key}, $fields, $old_record, $comp); |
my $old = $old_param ? $old_param : $old_val; |
my($new_val, $new_param) = Call_OutFieldFilter($key, $new_record->{$KEY}, $new_record->{$key}, $fields, $new_record, $comp); |
my $new = $new_param ? $new_param : $new_val; |
my $diff_merge = diff_merge( $old, $new, |
remove_open => '[', |
remove_close => ']', |
append_open => '{', |
append_close => '}', |
); |
push @report, (exists $fields_descr->{$key} ? $fields_descr->{$key} : "Field $key").': '.$diff_merge; |
} |
} |
if($report_cancellato){ |
push @report, '(RECORD CANCELLATO)'; |
} |
return join "\n", @report; |
} |
# separa il nome del file indicato nei log nelle sue componenti dir, file e versione |
sub split_archive_log_file($){ |
$_[0] || return undef; |
my($file, $version) = split /:/, $_[0], 2; |
if($file !~ m|^/|){ |
$file = '/'.$file; |
} |
my $is_dir; |
if($file =~ m|(.*)/$|){ |
$is_dir = 1; |
$file = $1; |
} |
my $dir = $file; |
$dir =~ s|/[^/]*$||; |
if(!$dir){ |
$dir = '/'; |
} |
my $name = $file; |
$name =~ s|^.*/||; |
return ($is_dir, $dir, $name, $version); |
} |
</%once> |
<%method TABLE_ROWS><% $ARGS{'rows'} ? $ARGS{'rows'} : '10' %></%method> |
<%method FIELDS_HIDDEN> |
<%perl> |
my $where = $Session{ARGS}{'where2'}; |
if($where && |
$where !~ m/ and id_record\s*=\s*'{0,1}\d+'{0,1}/ && |
$where !~ m/table_name\s*=\s*'\w+\.\w+'/ |
){ |
die "SQL injection detection width [$where]. Execution aborted!"; |
} |
</%perl> |
% if($where =~ m/table_name\s*=/){ |
table_name, |
% } |
% if($where =~ m/ and id_record\s*=/){ |
id_record |
% } |
</%method> |
<%method DESCRIPTION>Report delle modifiche \ |
<% $Session{ARGS}{'where2'} =~ m/table_name\s*=\s*'(.*)'/ ? "alla tabella $1 " : ''%> \ |
da parte degli utenti</%method> |
<%method FIELDS>timestamp, id_anagrafiche, table_name, id_record, report</%method> |
<%method FIELDS_DESCR>Data e ora, Utente, <% $Session{Group_Admins} ? 'Scheda (tabella)' : 'Scheda' %>, Id, Report variazioni</%method> |
<%method FIND_FIELDS>timestamp, timestamp, id_anagrafiche, id_record, report</%method> |
<%method FIELDS_RO>*</%method> |
<%method FIELDS_NO_WRITE>*</%method> |
<%method ORDER>order by timestamp desc, id</%method> |
<%method timestamp_FIELD><& /input/span.comp, width => 120, %ARGS &></%method> |
<%method timestamp_FIND_FIELD> |
<& /input/timestamp.comp, %ARGS &> |
<%attr> |
find_select_list => ['=' => '=', '<=' => '<=', '>=' => '>='] |
</%attr> |
</%method> |
<%method report_FIELD> |
<& /input/span.comp, %ARGS, width => 600, style => 'font-size: 8pt; white-space: normal; text-wrap: normal;', disp_template => q{P.join('; ')}.($Session{Group_Admins} ? q{+' ('+P[-1]+')'} : '') &> |
</%method> |
<%method FORM_INCLUDE_POST> |
<%args> |
$Display |
$Recordset |
</%args> |
<script> |
// chiamata da id_record_FIELD per visualizzare il form corrispondente al campo variato |
<% $Display %>.view_form = function (widget){ |
// verifico che il widget non sia disabilitato |
if(widget.Readonly()){ |
return false; |
} |
var table_name = <%$Display%>.getField('table_name', widget.dbRow).get_value(); |
var table = table_name.replace(/.*\//, ''); |
// costruisco un oggetto 'display' minimale con i soli elementi necessari a lanciare il form |
var display_log = { |
prefix: 'Log_detail', |
dataBinding: new DataBinding('Log_detail_db', 'log', 'Log ' + table), |
gotoRecords: function (mode, key, recordset){ |
return this.dataBinding.gotoRecords(mode, key, recordset); |
}, |
openFormDetailByKey: DisplayBinding_openFormDetailByKey |
}; |
var d = new Date(); |
display_log.openFormDetailByKey('rewind', null, table, 1000, 600, 'Log ' + table_name, { |
U: d.getTime() + '' + Math.floor(1000 * Math.random()), |
rows: null, |
disp_update: '', |
pk: widget.get_value() |
}); |
} |
</script> |
</%method> |
<%method REPORT_UPGRADE> |
<%args> |
$TABLE_NAME |
$ID_RECORD |
</%args> |
<%perl> |
# verifica se ci sono da aggiornare i report del record selezionato |
# lettura dei due logs_report più recenti |
my $sth_logs_report = ExecQuery('check update logs_report', undef, q{ |
select *, to_char(timestamp, 'YYYYMMDD') as day |
from public.logs_report |
where table_name = ? |
and id_record = ? |
order by timestamp desc, id |
limit 2; |
}, $TABLE_NAME, $ID_RECORD); |
my $logs_report = $sth_logs_report->rows >=1 ? $sth_logs_report->fetchrow_hashref : { id_anagrafiche => undef, timestamp => '1970-01-01T00:00:00+00' }; |
# verifico se il primo log della lista è dello stesso utente e nello stesso giorno dell'ultimo report presente. |
# Se è il caso provvedo a cancellare l'ultimo report così da aggiornarlo |
my $sth_check_logs = ExecQuery('check first logs', undef, q{ |
select id_anagrafiche, to_char(timestamp, 'YYYYMMDD') as day |
from public.logs |
where table_name = ? |
and id_record = ? |
and timestamp > ? |
order by timestamp, id |
limit 1; |
}, $TABLE_NAME, $ID_RECORD, $logs_report->{'timestamp'}); |
if($sth_check_logs->rows == 1){ |
# c'è almeno un nuovo log da elaborare |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
my $table = $TABLE_NAME; |
$table =~ s/\./\//; # il nome della tabella con schema --> in formato schema/tabella |
my $KEY = $m->scomp("$DataBaseUrl/$table.mql:KEY_NAME"); |
my $check_logs = $sth_check_logs->fetchrow_hashref; |
if($check_logs->{'id_anagrafiche'} eq $logs_report->{'id_anagrafiche'} && $check_logs->{'day'} eq $logs_report->{'day'}){ |
# c'è almeno un ulteriore log da includere nell'ultimo report presente |
# quindi lo scarto per ricrearlo aggiornato |
ExecQuery('delete logs_report', undef, q{delete from public.logs_report where id = ?;}, $logs_report->{$KEY}); |
# il penultimo report, diventato ora l'ultimo |
$logs_report = $sth_logs_report->rows == 2 ? $sth_logs_report->fetchrow_hashref : { id_anagrafiche => undef, timestamp => '1970-01-01T00:00:00+00' }; |
} |
# elenco dei logs successivi a partire dal più recente |
my $sth_logs = ExecQuery('check logs_report', undef, q{ |
select *, to_char(timestamp, 'YYYYMMDD') as day |
from public.logs |
where table_name = ? |
and id_record = ? |
and timestamp > ? |
order by timestamp desc, id desc; |
}, $TABLE_NAME, $ID_RECORD, $logs_report->{'timestamp'}); |
# leggo i dati attuali del record |
my $sth_record = ExecQuery("read $TABLE_NAME:$ID_RECORD", undef, qq{ |
select * |
from $TABLE_NAME |
where $KEY=? |
}, $ID_RECORD); |
my $old_record = $sth_record->rows == 1 ? $sth_record->fetchrow_hashref : { id => $ID_RECORD }; |
my %new_record = %{$old_record}; |
my $log = $sth_logs->fetchrow_hashref; |
my $max_curr_timestamp = $log->{'timestamp'}; |
my $curr_id_anagrafiche = $log->{'id_anagrafiche'}; |
my $curr_day = $log->{'day'}; |
# descrizioni dei campi per il report |
# nella stessa sessione il metodo REPORT_UPGRADE viene richiamato più volte, quindi metto in cache la hash con le descrizioni dei campi |
if(!$Session{"Logs_report_fields_descr_$TABLE_NAME"}){ |
my %fields_descr; |
my $comp = $m->fetch_comp("$DataBaseUrl/$table.mql"); |
my @fields = &Method2Array("$DataBaseUrl/$table.mql:FIELDS"); |
my @fields_descr = &Method2Array("$DataBaseUrl/$table.mql:FIELDS_DESCR"); |
for(my $I=0; $I<@fields; $I++){ |
my $field = $fields[$I]; |
$field =~ s/^\w+\.//; # tolgo il nome della tabella |
my $descr = $fields_descr[$I]; |
$descr =~ s/[\\\/]$//; |
$fields_descr{$field} = $descr; |
} |
$Session{"Logs_report_$TABLE_NAME"} = [$comp, \@fields, \%fields_descr ]; |
} |
my($comp, $fields, $fields_descr) = @{$Session{"Logs_report_$TABLE_NAME"}}; |
my $report_inserito; |
my $report_cancellato; |
my $old_report_cancellato; |
my %ghost_old_record; |
my %ghost_new_record; |
my @log_archive; |
my $sql_insert_report = q{ |
insert into public.logs_report (timestamp, id_anagrafiche, table_name, id_record, report) values (?, ?, ?, ?, ?) |
}; |
while(1){ |
if($log->{'id_anagrafiche'} ne $curr_id_anagrafiche || $log->{'day'} ne $curr_day){ |
# se vi sono state variazioni fantasma (LOG assenti) le registro |
if(!$report_cancellato && %ghost_new_record){ |
# aggiungo le chiavi primarie |
$ghost_new_record{$KEY} = $new_record{$KEY}; |
$ghost_old_record{$KEY} = $old_record->{$KEY}; |
# genero il report delle differenze |
my $report = diff_report($KEY, $fields, $fields_descr, $comp, \%ghost_old_record, \%ghost_new_record, undef, undef); |
if(length($report)){ |
# salvo il report |
ExecQuery('new ghost logs_report', undef, $sql_insert_report, $max_curr_timestamp, undef, $TABLE_NAME, $ID_RECORD, $report); |
} |
%ghost_new_record = undef; |
%ghost_old_record = undef; |
} |
# genero il report delle differenze |
my $report = diff_report($KEY, $fields, $fields_descr, $comp, $old_record, \%new_record, $report_inserito, $report_cancellato); |
if(@log_archive){ |
$report .= "\nArchivio: ".join("; ", @log_archive).'.'; |
@log_archive = (); |
} |
$report_inserito = undef; |
if($report_cancellato){ |
$old_report_cancellato = 1; |
} |
$report_cancellato = undef; |
# salvo il report |
ExecQuery('new logs_report', undef, $sql_insert_report, $max_curr_timestamp, $curr_id_anagrafiche, $TABLE_NAME, $ID_RECORD, $report); |
# prossimo report ... |
%new_record = %{$old_record}; |
$max_curr_timestamp = $log->{'timestamp'}; |
$curr_id_anagrafiche = $log->{'id_anagrafiche'}; |
$curr_day = $log->{'day'}; |
} |
# ho terminato la lettura del log? |
$log->{$KEY} || last; |
# accumulo i cambiamenti effettuati dallo stesso utente nello stesso giorno |
my $field = $log->{'field'}; |
if(defined $field){ |
if($field eq 'ARC.'){ |
# modifiche all'archivio associato |
my($old_is_dir, $old_dir, $old_name, $old_ver) = split_archive_log_file($log->{'old_value'}); |
my($new_is_dir, $new_dir, $new_name, $new_ver) = split_archive_log_file($log->{'new_value'}); |
if(!$old_name){ |
# caricamento |
if($new_is_dir){ |
unshift @log_archive, "new dir $new_name in $new_dir"; |
}else{ |
unshift @log_archive, "load file $new_name in $new_dir".($new_ver ? " ver.$new_ver" : ''); |
} |
}elsif(!$new_name){ |
# cancellazione |
unshift @log_archive, ($old_is_dir ? 'del dir' : 'del file')." $old_name in $old_dir"; |
}else{ |
if($old_name ne $new_name && $old_dir eq $new_dir){ |
# modificato il nome |
unshift @log_archive, 'mod. '.($old_is_dir ? ' dir ' : ' file '). |
"$old_name a $new_name in $old_dir"; |
}elsif($old_name eq $new_name && $old_dir ne $new_dir && $old_ver == $new_ver){ |
# spostamento del file |
unshift @log_archive, 'spost.'.($old_is_dir ? ' dir ' : ' file '). |
"$old_name da $old_dir a $new_dir"; |
}else{ |
unshift @log_archive, 'spost.'.($old_is_dir ? ' dir ' : ' file '). |
"da $old_dir/$old_name a $new_dir/$new_name"; |
} |
} |
}else{ |
# modifica di un campo |
if($old_report_cancellato && !exists $old_record->{$field}){ |
# mancando l'informazione del record finale (in quanto cancellato) se il campo non è |
# stato registrato nel LOG (letto a ritroso nel tempo) devo considerare il dato corrente del LOG veritiero |
$new_record{$field} = $log->{'new_value'}; |
$old_record->{$field} = $log->{'old_value'}; |
}elsif($log->{'new_value'} eq $old_record->{$field}){ |
$old_record->{$field} = $log->{'old_value'}; |
}else{ |
# c'è stata una variazione del campo intermedia nel log che non è registrata |
$ghost_old_record{$field} = $log->{'new_value'}; |
$ghost_new_record{$field} = $old_record->{$field}; |
$new_record{$field} = $log->{'new_value'}; |
$old_record->{$field} = $log->{'old_value'}; |
} |
} |
}elsif($ID_RECORD eq $log->{'new_value'}){ |
# inserimento del record |
$old_record->{$KEY} = undef; |
$report_inserito = 1; |
}elsif($ID_RECORD eq $log->{'old_value'}){ |
# cancellazione del record |
$old_record->{$KEY} = $ID_RECORD; |
$report_cancellato = 1; |
}else{ |
die 'Dati inaspettati',$log, Dumper($log); |
} |
# riga di log precedente del giorno |
$log = $sth_logs->fetchrow_hashref; |
} # while(1) |
$Session{Dbh}->commit; |
return 1; |
} |
</%perl> |
</%method> |
<%method PRE_SELECT> |
<%args> |
$PARAMS |
</%args> |
<%perl> |
# DEBUG $PARAMS->{'where2'} = q{table_name = 'impianti.apparecchiature' and id_record = '31173'}; |
my $where = $PARAMS->{'where2'}; |
if($where && $where =~ m/table_name\s*=\s*'(\w+\.\w+)'\s*and\s*id_record\s*=\s*'{0,1}(\d+)'{0,1}/){ |
my $table_name = $1; |
my $id_record = $2; |
if($m->comp('SELF:REPORT_UPGRADE', TABLE_NAME => $table_name, ID_RECORD => $id_record)){ |
$PARAMS->{'RecordsetCache'}= undef; |
} |
}elsif($where && $where =~ m/table_name\s*=\s*'(\w+\.\w+)'/){ |
# devo provvedere all'aggiornamento dei dati di tutti i record della tabella |
my $table_name = $1; |
my $id_list = ExecQuery('logs_report table id list', undef, q{ |
select id_record from ( |
select max(logs.timestamp) as t_log, max(logs_report.timestamp) as t_rep, logs.id_record |
from logs |
left join logs_report on logs_report.table_name = logs.table_name and logs_report.id_record = logs.id_record |
where logs.table_name = ? |
group by logs.id_record |
) as logs |
where t_rep is null or t_log > t_rep; |
}, $table_name); |
#my $C=10; |
while(my $rec = $id_list->fetchrow_arrayref){ |
if($m->comp('SELF:REPORT_UPGRADE', TABLE_NAME => $table_name, ID_RECORD => $rec->[0])){ |
$PARAMS->{'RecordsetCache'}= undef; |
} |
#$C--; |
#$C || last; |
} |
}else{ |
die "Errore inaspettato; il form logs_report deve essere richiamato con limitazione WHERE(table_name = '<nome tabella>)'"; |
} |
</%perl> |
</%method> |
<%method FIELDS_INCLUDE_POST> |
<%args> |
$Display |
</%args> |
<script> |
dojo.addOnLoad(function(){ |
%# // la stampa comprende tutto il recordset |
var print_btn = dojo.byId('<%$Display%>_Ctrl_print'); |
print_btn.value = 'Stampa'; |
print_btn.onclick = function(){ |
<%$Display%>.printSelected('recordset'); |
}; |
}); |
<%$Display%>.onchange = function(){ |
%# // disabilito i pulsanti che puntano a record cancellati |
var Col = this.dataBinding.pos_name['id_record']; |
for(var Row=0; Row<this.fields.length; Row++){ |
var Button = this.fields[Row][Col]; |
if(Button.get_param() == 'D'){ |
Button.Readonly(true); |
} |
} |
}; |
</script> |
</%method> |
<%method PERMISSION>SELECT PRINT PRINTSEL</%method> |
<%method FIND_MENU_POST> |
<p><br><br><br> |
Per filtrare i cancellati<br> |
inserire la frase<br> |
<B>RECORD CANCELLATO</B><br> |
in 'Report variazioni'. |
</p> |
</%method> |
/tags/2.0/htdocs/data/public/messages_users.mql |
---|
0,0 → 1,68 |
<%doc> |
Utenti destinatari dei messaggi |
</%doc> |
<%method FUNZIONE>Messages</%method> |
<%method DESCRIPTION>Utenti destinatari dei messaggi</%method> |
<%method FIELDS_COMMON> |
notification_time |
<% $r->dir_config('MailSmtpServer') ? ', email_result' : '' %> |
<% $r->dir_config('SMSPlatform') ? ', sms_result' : '' %> |
</%method> |
<%method FIELDS>id_anagrafiche, <& SELF:FIELDS_COMMON &></%method> |
<%method FIELDS_NOT_NULL></%method> |
<%method FIELDS_DESCR>Destinatari, Notifica Web\ |
<% $r->dir_config('MailSmtpServer') ? ', E-mail' : '' %>\ |
<% $r->dir_config('SMSPlatform') ? ', S.M.S.' : '' %> |
</%method> |
<%method FIELDS_RO><& SELF:FIELDS_COMMON &></%method> |
<%method FIND_AREA>left</%method> |
<%method FIND_FIELDS>id_anagrafiche, notification_time, notification_time</%method> |
<%method FATHER>id_messages:messages</%method> |
<%method DETAIL_FROM>messages_users_detail</%method> |
<%method TABLE_ROWS>15</%method> |
<%method PERMISSION><%perl> |
my $permission = $m->scomp('SELF:PERMISSION_BY_PROFILE'); |
# verifico lo stato del padre |
my $sth = ExecQuery('Check message status', undef, q{ |
select transmission_time from public.messages where id = ?; |
}, $Session{ARGS}->{'father_id'}); |
if($sth->rows){ |
my $transmission_time = $sth->fetchrow_arrayref->[0]; |
# disabilito cancellazione e modifica se record trasmesso |
if($transmission_time){ |
$permission =~ s/DELETE//; |
$permission =~ s/INSERT//; |
$permission =~ s/UPDATE//; |
} |
} |
$m->out($permission); |
</%perl></%method> |
<%method id_anagrafiche_FIELD> |
<& SELF:GenericSelect_FIELD,from => 'sel_gruppi_and_anagrafiche', widget => 'divselect', width => '260', |
cols => [250], |
disp_template => q{P[0]}, |
%ARGS |
&> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'sel_gruppi_and_anagrafiche' |
</%attr> |
</%method> |
<%method email_result_FIELD><& /input/span.comp, %ARGS, width => 300 &></%method> |
<%method sms_result_FIELD><& /input/span.comp, %ARGS, width => 300 &></%method> |
/tags/2.0/htdocs/data/public/messages_users_detail.mql |
---|
0,0 → 1,58 |
<%doc> |
Dettaglio utente destinatario dei messaggi |
</%doc> |
<%method FROM>messages_users</%method> |
<%method FUNZIONE>Messages</%method> |
<%method DESCRIPTION>Utente destinatario del messaggo</%method> |
<%method FIELDS> |
id_anagrafiche, notification_time, |
<% $r->dir_config('MailSmtpServer') ? 'email_result,' : '' %> |
<% $r->dir_config('SMSPlatform') ? 'sms_result, user_short_message,' : '' %> |
user_message |
</%method> |
<%method SELECT_FIELDS> |
id_anagrafiche, notification_time, |
<% $r->dir_config('MailSmtpServer') ? 'email_result,' : '' %> |
<% $r->dir_config('SMSPlatform') ? q{sms_result, coalesce(user_short_message, messages.short_message) as user_short_message,} : '' %> |
coalesce(user_message, messages.message) as user_message |
</%method> |
<%method FIELDS_NOT_NULL></%method> |
<%method FIELDS_DESCR> |
Destinatari, Notifica Web, |
<% $r->dir_config('MailSmtpServer') ? 'E-mail,' : '' %> |
<% $r->dir_config('SMSPlatform') ? 'S.M.S., Messaggio breve,' : '' %> |
Messaggio |
</%method> |
<%method FIELDS_RO>*</%method> |
<%method JOIN_TABLES> |
public.messages_users |
inner join public.messages on messages.id = messages_users.id_messages |
</%method> |
<%method id_anagrafiche_FIELD> |
<& SELF:GenericSelect_FIELD, from => 'sel_gruppi_and_anagrafiche', %ARGS &> |
<%attr> |
find_select_list => ['=' => '='] |
select_from => 'sel_gruppi_and_anagrafiche' |
</%attr> |
</%method> |
<%method email_result_FIELD><& /input/span.comp, %ARGS, width => 500 &></%method> |
<%method sms_result_FIELD><& /input/span.comp, %ARGS, width => 500 &></%method> |
<%method user_message_FIELD><& /input/string.comp, %ARGS, rows => 18, cols => 86, style => 'font-family: monospace;' &></%method> |
<%method user_short_message_FIELD><& /input/string.comp, %ARGS, rows => 3, cols => 86, style => 'font-family: monospace;' &></%method> |
/tags/2.0/htdocs/data/public/odt_reports.mql |
---|
0,0 → 1,63 |
<%method FUNZIONE>OdtReports</%method> |
<%method DESCRIPTION>ODT Reports</%method> |
<%method CHILDREN>odt_report_portions, odt_report_fields</%method> |
<%method CHILDREN_FIELDS>id, id</%method> |
<%method FIELDS>name, description, comment, cmd_parameters, global_parameters, id</%method> |
<%method FIELDS_NOT_NULL>name</%method> |
<%method FIELDS_DESCR>Report Name, Description, Comment, Test parameters, Global parameters, Template Files</%method> |
<%method FIND_FIELDS>name, description, comment</%method> |
<%method name_FIELD><& /input/string.comp, %ARGS, size => 60 &></%method> |
<%method description_FIELD><& /input/string.comp, %ARGS, size => 60 &></%method> |
<%method comment_FIELD><& /input/string.comp, %ARGS, rows => 4, cols => 80 &></%method> |
<%method comment_FIND_FIELD><& /input/string.comp, %ARGS, rows => 1 &></%method> |
<%method FORM_HEIGHT>300</%method> |
<%method id_FIELD> |
<& /input/Files.comp, %ARGS, |
from => 'public/odt_reports', |
width => 400, |
height => 300, |
readonly => 0, |
&>\ |
</%method> |
<%method PRE_INSERT> |
<%args> |
$FIELDS_INSERT |
$PARAMS |
</%args> |
% delete $FIELDS_INSERT->{'id'}; |
% delete $PARAMS->{'id'}; |
</%method> |
<%method PRINT_FORM>, <%$ARGS{'cmd_parameters'}%></%method> |
<%method cmd_parameters_FIELD> |
<%args> |
$Display |
</%args> |
<& /input/string.comp, %ARGS, rows => 2, cols => 64 &> |
<button dojoType="dijit.form.Button" style="vertical-align:top;" type="submit" onClick="GenerateOdtReport();">Test<br>ODT</button> |
<button dojoType="dijit.form.Button" style="vertical-align:top;" type="submit" onClick="GeneratePdfReport();">Test<br>PDF</button> |
<script> |
function GenerateOdtReport(){ |
var report_name = <%$Display%>.getField('name').get_value(); |
var cmd_parameters = <%$Display%>.getField('cmd_parameters').get_value(); |
<%$Display%>.printSelected('odt_rpt', report_name+'.odt', cmd_parameters); |
} |
function GeneratePdfReport(){ |
var report_name = <%$Display%>.getField('name').get_value(); |
var cmd_parameters = <%$Display%>.getField('cmd_parameters').get_value(); |
<%$Display%>.printSelected('pdf_rpt', report_name+'.pdf', cmd_parameters); |
} |
</script> |
</%method> |
<%method global_parameters_FIELD> |
<& /input/string.comp, %ARGS, rows => 1, size => 64 &> |
</%method> |
/tags/2.0/htdocs/data/public/sel_anagrafiche.mql |
---|
0,0 → 1,9 |
<%flags> |
inherit => 'anagrafiche.mql' |
</%flags> |
<%method FIELDS>nome, cognome<% $Session{Group_Admins} ? ', login' : ''%></%method> |
<%method SELECT_FIELDS><& SELF:FIELDS &></%method> |
<%method FIELDS_DESCR>Nome, Cognome<% $Session{Group_Admins} ? ', Login' : ''%></%method> |
/tags/2.0/htdocs/data/public/sel_autorizzazioni.mql |
---|
0,0 → 1,10 |
<%flags> |
inherit => 'autorizzazioni.mql' |
</%flags> |
<%method FIELDS>nome</%method> |
<%method SELECT_FIELDS>nome</%method> |
<%method FIELDS_DESCR>Nome</%method> |
/tags/2.0/htdocs/data/public/sel_gruppi.mql |
---|
0,0 → 1,50 |
<%flags> |
inherit => 'gruppi.mql' |
</%flags> |
<%method FIELDS_DESCR>Gruppo</%method> |
<%method FIELDS>gruppo</%method> |
<%method SELECT_FIELDS>(coalesce(gruppi.nome , '') || ' - ' || coalesce(gruppi.descrizione, '')) as gruppo</%method> |
<%method ORDER>gruppo</%method> |
<%method SELECT>\ |
<%args> |
$ID => undef |
$WHERE => '' |
</%args> |
% if(defined $ID){ |
select <& SELF:KEY &>, <& SELF:SELECT_FIELDS &> from <& SELF:JOIN_TABLES &> where <& SELF:KEY &> = '<%$ID%>';\ |
% }else{ |
% if($Session{Group_Admins}){ # amministratore; lista completa |
select distinct |
<& SELF:KEY &>, <& SELF:SELECT_FIELDS &> |
from gruppi |
<% $WHERE %> |
<& SELF:ORDER_BY &>;\ |
% }else{ |
% # elenco solo i gruppi che l'utente è autorizzato ad assegnare |
% if($WHERE){ |
% $WHERE =~ s/\s*where\s*/and /i; |
% } |
select distinct |
<& SELF:KEY &>, <& SELF:SELECT_FIELDS &> |
from |
gruppi_modifica left join gruppi on gruppi.id = gruppi_modifica.id_gruppo_modifica |
where |
gruppi_modifica.id_gruppo in ( |
select distinct |
gruppi.id |
from gruppi |
left join anagrafiche_gruppi on anagrafiche_gruppi.id_gruppi = gruppi.id |
left join anagrafiche on anagrafiche.id = anagrafiche_gruppi.id_anagrafiche |
where |
anagrafiche.id = '<%$Session{User_id}%>' |
) |
<%$WHERE%> |
<& SELF:ORDER_BY &>;\ |
% } |
% } |
</%method> |
/tags/2.0/htdocs/data/public/sel_odt_report_portions.mql |
---|
0,0 → 1,14 |
<%flags> |
inherit => 'odt_report_portions.mql' |
</%flags> |
<%method FIELDS>name</%method> |
<%method FIELDS_DESCR>Porzione</%method> |
<%method SELECT_FIELDS>coalesce (name, '')</%method> |
<%method WHERE> |
id_odt_reports = <% $Session{ARGS}{father_id} %> AND |
id != <% $Session{ARGS}{child_id} || -1 %> |
</%method> |
/tags/2.0/htdocs/data/public/user_messages_body.mql |
---|
0,0 → 1,84 |
<%method FROM>messages_users</%method> |
<%method FUNZIONE>User_messages</%method> |
<%method FORM_TYPE>FORM</%method> |
<%method TABLE_ROWS>1</%method> |
<%method FATHER>id_messages:user_messages</%method> |
<%method DESCRIPTION>Messaggio</%method> |
<%method FIELDS>message</%method> |
<%method SELECT_FIELDS> |
CASE |
WHEN messages_users.user_message is not null THEN messages_users.user_message |
WHEN messages_users.user_short_message is not null THEN messages_users.user_short_message |
WHEN messages.message is not null THEN messages.message |
ELSE messages.short_message |
END as message |
</%method> |
<%method JOIN_TABLES> |
public.messages_users |
inner join public.messages on messages_users.id_messages = messages.id |
and messages_users.id_anagrafiche = <%$Session{User_id}%> |
</%method> |
<%method FIELDS_DESCR>Messaggio</%method> |
<%method FIELDS_RO>message</%method> |
<%method message_FIELD> |
<& /input/string.comp, %ARGS, rows => 26, cols => 140, style => 'font-family: monospace;' &> |
</%method> |
<%method FORM_INCLUDE_POST> |
<%args> |
$Display |
$Recordset |
</%args> |
<script> |
<%$Display%>.onload = function (){ |
this.getField('message').TooltipShowDelay = 9999999999; |
this.getField('message').TooltipObj.showDelay = 9999999999; |
} |
<%$Display%>.onchange = function (){ |
// metto in evidenza il nuovo messaggio |
var new_mess = <%$Recordset%>.keys[0] && !<%$Recordset%>.father.get_value('notification_time', <%$Recordset%>.father.rowFather); |
require(["dojo/dom-class"], function(domClass){ |
if(new_mess){ |
domClass.replace(<%$Display%>.getField('message'), 'MessagesNewMessage', 'widgetRo'); |
}else{ |
domClass.replace(<%$Display%>.getField('message'), 'widgetRo', 'MessagesNewMessage'); |
} |
}); |
// notifico al server che l'utente ha visionato il record caricato nel form |
if(new_mess){ |
// Messaggio visionato per la prima volta |
<%$Display%>.callRemote('viewed', {id:<%$Recordset%>.keys[0]}); |
} |
} |
</script> |
</%method> |
<%method CALL_REMOTE_viewed> |
<%args> |
$id |
$dbms_params |
</%args> |
<%perl> |
# l'utente ha visionato il messaggio che posso quindi aggiornare |
my $sth = ExecQuery('Displayed message', undef, q{ |
UPDATE public.messages_users |
SET notification_time = now() |
WHERE id_anagrafiche = ? |
AND notification_time IS NULL |
AND id = ?; |
}, $Session{User_id}, $id); |
$Session{Dbh}->commit; |
</%perl> |
</%method> |
/tags/2.0/htdocs/data/public/user_session.mql |
---|
0,0 → 1,27 |
<%flags> |
inherit => 'session.mql' |
</%flags> |
<%method FUNZIONE>UserSession</%method> |
<%method DESCRIPTION>Sessioni dell'utente</%method> |
<%method FIELDS>user_ip, session_time, session_inactive_time, user_agent</%method> |
<%method FIELDS_DESCR>Indirizzo IP, Ultima login, Inattivo, Browser</%method> |
<%method FIND_FIELDS></%method> |
<%method WHERE>id_anagrafiche = <% $Session{User_id} %></%method> |
<%method session_inactive_time_OUT_FILTER> |
my $m = int(time/60) - $_; |
my $h = int($m/60); |
$m -= $h*60; |
$_ = $h || $m ? sprintf('%02i:%02i', $h, $m) : ''; |
</%method> |
<%method user_ip_FIELD><& /input/span.comp, width => '100px', %ARGS &></%method> |
<%method session_inactive_time_FIELD><& /input/span.comp, width => '48px', %ARGS &></%method> |
<%method user_agent_FIELD><& /input/span.comp, width => '280px', %ARGS &></%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/data/public/anagrafiche.kylix.rep |
---|
0,0 → 1,769 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end |
item |
SubReport = TRpSubReport1 |
end |
item |
SubReport = TRpSubReport2 |
end> |
DataInfo = < |
item |
Alias = 'ANAGRAFICHE' |
DatabaseAlias = 'MASONSQL' |
SQL = |
#13#10'select '#13#10' anagrafiche.*'#13#10'from '#13#10' report_id, anagrafiche'#13 + |
#10'where '#13#10' report_id.group_id = :GROUP_ID'#13#10' and anagrafiche.i' + |
'd=key'#13#10'order by id;'#13#10 |
end |
item |
Alias = 'DATI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select nome from gruppi, anagrafiche_gruppi ag'#13#10'where ag.id_anag' + |
'rafiche = :ID'#13#10'and ag.id_gruppi = gruppi.id'#13#10' ' |
DataSource = 'ANAGRAFICHE' |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdatazeos |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = '' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
Value = -1 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'ANAGRAFICHE') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection3 |
end |
item |
Section = TRpSection4 |
end> |
Alias = 'ANAGRAFICHE' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport1: TRpSubReport |
Sections = < |
item |
Section = TRpSection10 |
end> |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection0 |
end |
object TRpSection10: TRpSection |
Width = 10605 |
Height = 2430 |
SubReport = TRpSubReport1 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression4 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel5 |
end |
item |
Component = TRpExpression8 |
end |
item |
Component = TRpExpression10 |
end |
item |
Component = TRpLabel7 |
end |
item |
Component = TRpLabel9 |
end |
item |
Component = TRpLabel10 |
end |
item |
Component = TRpLabel15 |
end |
item |
Component = TRpShape2 |
end |
item |
Component = TRpShape5 |
end |
item |
Component = TRpExpression11 |
end |
item |
Component = TRpExpression3 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpExpression6 |
end |
item |
Component = TRpShape0 |
end> |
AutoExpand = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport2: TRpSubReport |
Sections = < |
item |
Section = TRpSection1 |
end> |
Alias = 'DATI' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection3 |
end |
object TRpSection1: TRpSection |
Width = 1425 |
Height = 225 |
SubReport = TRpSubReport2 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression1 |
end> |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection3: TRpSection |
Width = 10772 |
Height = 30 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression1: TRpExpression |
Width = 915 |
Height = 225 |
PosX = 465 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 8 |
VAlignment = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'DATI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression0: TRpExpression |
Width = 2295 |
Height = 225 |
PosX = 6675 |
PosY = 810 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.descrizione' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 2295 |
Height = 225 |
PosX = 6675 |
PosY = 1050 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.indirizzo' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression4: TRpExpression |
Width = 2415 |
Height = 225 |
PosX = 6675 |
PosY = 1275 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.tel1' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel3: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1050 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Via: ' |
end |
object TRpLabel5: TRpLabel |
Width = 690 |
Height = 225 |
PosX = 5985 |
PosY = 1725 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'C.F.: ' |
end |
object TRpExpression8: TRpExpression |
Width = 1140 |
Height = 225 |
PosX = 6675 |
PosY = 1725 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.codice_fiscale' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression10: TRpExpression |
Width = 2640 |
Height = 225 |
PosX = 6675 |
PosY = 1500 |
Type1Font = poHelvetica |
FontSize = 8 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.tel2' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel7: TRpLabel |
Width = 1260 |
Height = 225 |
PosX = 5400 |
PosY = 810 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Descrizione: ' |
end |
object TRpLabel9: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1275 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tel1: ' |
end |
object TRpLabel10: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1500 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tel2: ' |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1230 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel11 |
end |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpLabel14 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel11: TRpLabel |
Width = 2070 |
Height = 345 |
PosX = 8745 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 13 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'MasonSQL' |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8400 |
PosY = 915 |
Type1Font = poHelvetica |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 8850 |
PosY = 915 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel14: TRpLabel |
Width = 2995 |
Height = 691 |
PosX = 225 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 28 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Anagrafiche' |
end |
object TRpLabel15: TRpLabel |
Width = 3210 |
Height = 225 |
PosX = 465 |
PosY = 2190 |
Type1Font = poHelvetica |
FontSize = 7 |
Alignment = 1 |
VAlignment = 16 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Gruppi di appartenenza dell'#39'utente:' |
end |
object TRpShape2: TRpShape |
Width = 10470 |
Height = 240 |
PosX = 0 |
PosY = 345 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape5: TRpShape |
Width = 5055 |
Height = 1380 |
PosX = 120 |
PosY = 690 |
BrushColor = 15724527 |
PenColor = 16777215 |
Shape = rpsRoundRect |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpExpression11: TRpExpression |
Width = 4485 |
Height = 345 |
PosX = 570 |
PosY = 810 |
Type1Font = poHelvetica |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.nome + '#39' '#39' + ANAGRAFICHE.cognome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2880 |
Height = 345 |
PosX = 1260 |
PosY = 1265 |
Type1Font = poHelvetica |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.login' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel1: TRpLabel |
Width = 585 |
Height = 345 |
PosX = 570 |
PosY = 1260 |
Type1Font = poHelvetica |
Alignment = 1 |
VAlignment = 16 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'login: ' |
end |
object TRpExpression6: TRpExpression |
Width = 3210 |
Height = 345 |
PosX = 570 |
PosY = 1730 |
Type1Font = poHelvetica |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.email' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpShape0: TRpShape |
Width = 10350 |
Height = 75 |
PosX = 120 |
PosY = 2070 |
Shape = rpsHorzLine |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpSection4: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape3 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpShape3: TRpShape |
Width = 10350 |
Height = 120 |
PosX = 110 |
PosY = 0 |
Shape = rpsHorzLine |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
end |
/tags/2.0/htdocs/data/public/anagrafiche.wine.rep |
---|
0,0 → 1,796 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end |
item |
SubReport = TRpSubReport1 |
end |
item |
SubReport = TRpSubReport2 |
end> |
DataInfo = < |
item |
Alias = 'ANAGRAFICHE' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#13#10' anagrafiche.*'#13#10'from '#13#10' report_id, anagrafiche'#13#10'w' + |
'here '#13#10' :GROUP_ID > 0 and'#13#10' report_id.group_id = :GROUP_ID'#13#10' ' + |
'and anagrafiche.id=key'#13#10#13#10'UNION'#13#10#13#10'select '#13#10' anagrafiche.*'#13#10'f' + |
'rom '#13#10' anagrafiche'#13#10'where '#13#10' :GROUP_ID < 0 and'#13#10' anagrafich' + |
'e.id = - :GROUP_ID'#13#10#13#10'order by id;'#13#10#13#10 |
end |
item |
Alias = 'DATI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select nome from gruppi, anagrafiche_gruppi ag'#13#10'where ag.id_anag' + |
'rafiche = :id'#13#10'and ag.id_gruppi = gruppi.id'#13#10' ' |
DataSource = 'ANAGRAFICHE' |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdataado |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = |
'Provider=MSDASQL.1;Persist Security Info=False;Mode=Read;Extende' + |
'd Properties="DRIVER={PostgreSQL Unicode};DATABASE=masonsql;SERV' + |
'ER=127.0.0.1;USER=report;PASSWORD=<password>;PORT=5432;UID=repor' + |
't;SSLmode=allow;ReadOnly=1;Protocol=7.4-1;FakeOidIndex=0;ShowOid' + |
'Column=0;RowVersioning=0;ShowSystemTables=0;ConnSettings=;Fetch=' + |
'100;Socket=4096;UnknownSizes=0;MaxVarcharSize=254;MaxLongVarchar' + |
'Size=8190;Debug=0;CommLog=0;Optimizer=1;Ksqo=1;UseDeclareFetch=0' + |
';TextAsLongVarchar=1;UnknownsAsLongVarchar=0;BoolsAsChar=1;Parse' + |
'=1;CancelAsFreeStmt=0;ExtraSysTablePrefixes=dd_;;LFConversion=1;' + |
'UpdatableCursors=1;DisallowPremature=0;TrueIsMinus1=0;BI=0;Bytea' + |
'AsLongVarBinary=0;UseServerSidePrepare=0;LowerCaseIdentifier=0;X' + |
'aOpt=1"' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
Value = -1 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'ANAGRAFICHE') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end |
item |
Name = 'ID' |
AllowNulls = False |
Value = 0 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'DATI') |
Description = '' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection3 |
end |
item |
Section = TRpSection4 |
end> |
Alias = 'ANAGRAFICHE' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport1: TRpSubReport |
Sections = < |
item |
Section = TRpSection10 |
end> |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection0 |
end |
object TRpSection10: TRpSection |
Width = 10605 |
Height = 2430 |
SubReport = TRpSubReport1 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression4 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel5 |
end |
item |
Component = TRpExpression8 |
end |
item |
Component = TRpExpression10 |
end |
item |
Component = TRpLabel7 |
end |
item |
Component = TRpLabel9 |
end |
item |
Component = TRpLabel10 |
end |
item |
Component = TRpLabel15 |
end |
item |
Component = TRpShape2 |
end |
item |
Component = TRpShape5 |
end |
item |
Component = TRpExpression11 |
end |
item |
Component = TRpExpression3 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpExpression6 |
end |
item |
Component = TRpShape0 |
end> |
AutoExpand = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport2: TRpSubReport |
Sections = < |
item |
Section = TRpSection1 |
end> |
Alias = 'DATI' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection3 |
end |
object TRpSection1: TRpSection |
Width = 1425 |
Height = 225 |
SubReport = TRpSubReport2 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression1 |
end> |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection3: TRpSection |
Width = 10772 |
Height = 30 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression1: TRpExpression |
Width = 915 |
Height = 225 |
PosX = 465 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 8 |
VAlignment = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'DATI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression0: TRpExpression |
Width = 2295 |
Height = 225 |
PosX = 6675 |
PosY = 810 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.descrizione' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 2295 |
Height = 225 |
PosX = 6675 |
PosY = 1050 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.indirizzo' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression4: TRpExpression |
Width = 2415 |
Height = 225 |
PosX = 6675 |
PosY = 1275 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.tel1' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel3: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1050 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Via: ' |
end |
object TRpLabel5: TRpLabel |
Width = 690 |
Height = 225 |
PosX = 5985 |
PosY = 1725 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'C.F.: ' |
end |
object TRpExpression8: TRpExpression |
Width = 1140 |
Height = 225 |
PosX = 6675 |
PosY = 1725 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.codice_fiscale' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression10: TRpExpression |
Width = 2640 |
Height = 225 |
PosX = 6675 |
PosY = 1500 |
Type1Font = poLinked |
FontSize = 8 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.tel2' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel7: TRpLabel |
Width = 1260 |
Height = 225 |
PosX = 5400 |
PosY = 810 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Descrizione: ' |
end |
object TRpLabel9: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1275 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tel1: ' |
end |
object TRpLabel10: TRpLabel |
Width = 570 |
Height = 225 |
PosX = 6090 |
PosY = 1500 |
Type1Font = poHelvetica |
FontSize = 8 |
Alignment = 2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tel2: ' |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1230 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel11 |
end |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpLabel14 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel11: TRpLabel |
Width = 2070 |
Height = 345 |
PosX = 8745 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 13 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'MasonSQL' |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8400 |
PosY = 915 |
Type1Font = poLinked |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 8850 |
PosY = 915 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel14: TRpLabel |
Width = 2995 |
Height = 691 |
PosX = 225 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 28 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Anagrafiche' |
end |
object TRpLabel15: TRpLabel |
Width = 3210 |
Height = 225 |
PosX = 465 |
PosY = 2190 |
Type1Font = poHelvetica |
FontSize = 7 |
Alignment = 1 |
VAlignment = 16 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Gruppi di appartenenza dell'#39'utente:' |
end |
object TRpShape2: TRpShape |
Width = 10470 |
Height = 240 |
PosX = 0 |
PosY = 345 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape5: TRpShape |
Width = 5055 |
Height = 1380 |
PosX = 120 |
PosY = 690 |
BrushColor = 15724527 |
PenColor = 16777215 |
Shape = rpsRoundRect |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpExpression11: TRpExpression |
Width = 4485 |
Height = 345 |
PosX = 570 |
PosY = 810 |
Type1Font = poLinked |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.nome + '#39' '#39' + ANAGRAFICHE.cognome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2880 |
Height = 345 |
PosX = 1260 |
PosY = 1265 |
Type1Font = poLinked |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.login' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel1: TRpLabel |
Width = 585 |
Height = 345 |
PosX = 570 |
PosY = 1260 |
Type1Font = poHelvetica |
Alignment = 1 |
VAlignment = 16 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'login: ' |
end |
object TRpExpression6: TRpExpression |
Width = 3210 |
Height = 345 |
PosX = 570 |
PosY = 1730 |
Type1Font = poLinked |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.email' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpShape0: TRpShape |
Width = 10350 |
Height = 75 |
PosX = 120 |
PosY = 2070 |
Shape = rpsHorzLine |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpSection4: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape3 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpShape3: TRpShape |
Width = 10350 |
Height = 120 |
PosX = 110 |
PosY = 0 |
Shape = rpsHorzLine |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
end |
/tags/2.0/htdocs/data/public/gruppi.kylix.rep |
---|
0,0 → 1,1076 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end |
item |
SubReport = TRpSubReport2 |
end |
item |
SubReport = TRpSubReport1 |
end |
item |
SubReport = TRpSubReport3 |
end> |
DataInfo = < |
item |
Alias = 'ANAGRAFICHE' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#13#10' anagrafiche.*'#13#10'from '#13#10' anagrafiche, anagrafiche_' + |
'gruppi ag'#13#10'where ag.id_gruppi = :ID_GRUPPO'#13#10'and ag.id_anagrafich' + |
'e = anagrafiche.id'#13#10'order by id;' |
DataSource = 'GRUPPI' |
end |
item |
Alias = 'AUTORIZZAZIONI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select distinct funzioni.nome , '#13#10' (select distinct id_autoriz' + |
'zazioni'#13#10' from gruppi_funzioni gf'#13#10' where gf.id_funzion' + |
'i = gg.id_funzioni and'#13#10' gf.id_autorizzazioni = 1) as ' + |
'm_menu,'#13#10' (select distinct id_autorizzazioni'#13#10' from grupp' + |
'i_funzioni gf'#13#10' where gf.id_funzioni = gg.id_funzioni and'#13#10' ' + |
' gf.id_autorizzazioni = 2) as m_select,'#13#10' (select dis' + |
'tinct id_autorizzazioni'#13#10' from gruppi_funzioni gf'#13#10' wher' + |
'e gf.id_funzioni = gg.id_funzioni and'#13#10' gf.id_autoriz' + |
'zazioni = 3) as m_update,'#13#10' (select distinct id_autorizzazioni' + |
#13#10' from gruppi_funzioni gf'#13#10' where gf.id_funzioni = gg.' + |
'id_funzioni and'#13#10' gf.id_autorizzazioni = 4) as m_delet' + |
'e,'#13#10' (select distinct id_autorizzazioni'#13#10' from gruppi_fun' + |
'zioni gf'#13#10' where gf.id_funzioni = gg.id_funzioni and'#13#10' ' + |
' gf.id_autorizzazioni = 5) as m_print,'#13#10' (select distinct ' + |
'id_autorizzazioni'#13#10' from gruppi_funzioni gf'#13#10' where gf.' + |
'id_funzioni = gg.id_funzioni and'#13#10' gf.id_autorizzazion' + |
'i = 6) as m_printsel,'#13#10' (select distinct id_autorizzazioni'#13#10' ' + |
' from gruppi_funzioni gf'#13#10' where gf.id_funzioni = gg.id_f' + |
'unzioni and'#13#10' gf.id_autorizzazioni = 7) as m_insert'#13#10'f' + |
'rom funzioni'#13#10'inner join gruppi_funzioni gg on gg.id_funzioni = ' + |
'funzioni.id'#13#10'inner join autorizzazioni on gg.id_autorizzazioni =' + |
' autorizzazioni.id'#13#10'where gg.id_gruppi= :ID_GRUPPO' |
DataSource = 'GRUPPI' |
end |
item |
Alias = 'GRUPPI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select *, gruppi.id as ID_GRUPPO from report_id, gruppi '#13#10'where ' + |
'report_id.group_id = :GROUP_ID'#13#10' and gruppi.id=key;'#13#10 |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdatazeos |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = '' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
Value = -1 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'GRUPPI') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection3 |
end |
item |
Section = TRpSection4 |
end |
item |
Section = TRpSection6 |
end> |
Alias = 'GRUPPI' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport1: TRpSubReport |
Sections = < |
item |
Section = TRpSection10 |
end> |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection0 |
end |
object TRpSection10: TRpSection |
Width = 11355 |
Height = 1455 |
SubReport = TRpSubReport1 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape2 |
end |
item |
Component = TRpExpression16 |
end |
item |
Component = TRpExpression17 |
end |
item |
Component = TRpExpression18 |
end |
item |
Component = TRpLabel0 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpLabel2 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel4 |
end |
item |
Component = TRpLabel5 |
end |
item |
Component = TRpLabel6 |
end |
item |
Component = TRpLabel7 |
end |
item |
Component = TRpShape0 |
end |
item |
Component = TRpLabel9 |
end |
item |
Component = TRpShape3 |
end> |
AutoExpand = True |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection3: TRpSection |
Width = 10772 |
Height = 30 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport3 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1230 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel11 |
end |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpLabel14 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel11: TRpLabel |
Width = 2070 |
Height = 345 |
PosX = 8745 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 13 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'MasonSQL' |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8400 |
PosY = 915 |
Type1Font = poHelvetica |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 8850 |
PosY = 915 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel14: TRpLabel |
Width = 4380 |
Height = 690 |
PosX = 225 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 28 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Distinta GRUPPI' |
end |
object TRpSubReport3: TRpSubReport |
Sections = < |
item |
Section = TRpSection5 |
end> |
Alias = 'AUTORIZZAZIONI' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection3 |
end |
object TRpSection5: TRpSection |
Width = 11130 |
Height = 225 |
SubReport = TRpSubReport3 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression13 |
end |
item |
Component = TRpExpression14 |
end |
item |
Component = TRpExpression15 |
end |
item |
Component = TRpExpression20 |
end |
item |
Component = TRpExpression21 |
end |
item |
Component = TRpExpression22 |
end |
item |
Component = TRpExpression23 |
end |
item |
Component = TRpExpression24 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection6: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression13: TRpExpression |
Width = 1380 |
Height = 225 |
PosX = 120 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'AUTORIZZAZIONI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression14: TRpExpression |
Width = 1275 |
Height = 225 |
PosX = 3330 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_menu == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression15: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 4605 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_select == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression16: TRpExpression |
Width = 1725 |
Height = 360 |
PosX = 1260 |
PosY = 570 |
Type1Font = poHelvetica |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression17: TRpExpression |
Width = 1485 |
Height = 240 |
PosX = 2985 |
PosY = 690 |
Type1Font = poHelvetica |
FontSize = 8 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.descrizione' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression18: TRpExpression |
Width = 1380 |
Height = 240 |
PosX = 4605 |
PosY = 690 |
Type1Font = poHelvetica |
FontSize = 8 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.commento' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression20: TRpExpression |
Width = 810 |
Height = 225 |
PosX = 5640 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_update == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression21: TRpExpression |
Width = 930 |
Height = 225 |
PosX = 6780 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_delete == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression22: TRpExpression |
Width = 945 |
Height = 225 |
PosX = 10125 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_print == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression23: TRpExpression |
Width = 1050 |
Height = 225 |
PosX = 8970 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_printsel == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression24: TRpExpression |
Width = 990 |
Height = 225 |
PosX = 7815 |
PosY = 0 |
Type1Font = poHelvetica |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_insert == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel0: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 8625 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'stampa sel.' |
end |
object TRpLabel1: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 9885 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'stampa' |
end |
object TRpLabel2: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 6435 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'cancella' |
end |
object TRpLabel3: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 5280 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'aggiorna' |
end |
object TRpLabel4: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 4140 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'selezione' |
end |
object TRpLabel5: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 3105 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'menu' |
end |
object TRpLabel6: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 120 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Nome' |
end |
object TRpLabel7: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 7365 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'inserimento' |
end |
object TRpSubReport2: TRpSubReport |
Sections = < |
item |
Section = TRpSection1 |
end> |
Alias = 'ANAGRAFICHE' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection6 |
end |
object TRpSection1: TRpSection |
Width = 11730 |
Height = 135 |
SubReport = TRpSubReport2 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression3 |
end> |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression0: TRpExpression |
Width = 1605 |
Height = 225 |
PosX = 120 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.nome + '#39' '#39' + ANAGRAFICHE.cognome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 1380 |
Height = 225 |
PosX = 2295 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.login' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2760 |
Height = 195 |
PosX = 4140 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.email' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpShape2: TRpShape |
Width = 10815 |
Height = 225 |
PosX = 0 |
PosY = 345 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpSection4: TRpSection |
Width = 10772 |
Height = 630 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape1 |
end |
item |
Component = TRpLabel8 |
end |
item |
Component = TRpLabel10 |
end |
item |
Component = TRpLabel15 |
end |
item |
Component = TRpShape4 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpShape1: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 120 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel9: TRpLabel |
Width = 1035 |
Height = 225 |
PosX = 120 |
PosY = 690 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'GRUPPO: ' |
end |
object TRpShape3: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 1380 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel8: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 120 |
PosY = 225 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'ELENCO UTENTI' |
end |
object TRpLabel10: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 2295 |
PosY = 240 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'login' |
end |
object TRpLabel15: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 4140 |
PosY = 240 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'e-mail' |
end |
object TRpShape0: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 1035 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape4: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 465 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
end |
/tags/2.0/htdocs/data/public/gruppi.wine.rep |
---|
0,0 → 1,1105 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end |
item |
SubReport = TRpSubReport2 |
end |
item |
SubReport = TRpSubReport1 |
end |
item |
SubReport = TRpSubReport3 |
end> |
DataInfo = < |
item |
Alias = 'ANAGRAFICHE' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#13#10' anagrafiche.*'#13#10'from '#13#10' anagrafiche, anagrafiche_' + |
'gruppi ag'#13#10'where ag.id_gruppi = :ID_GRUPPO'#13#10'and ag.id_anagrafich' + |
'e = anagrafiche.id'#13#10'order by id;' |
DataSource = 'GRUPPI' |
end |
item |
Alias = 'AUTORIZZAZIONI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select distinct funzioni.nome , '#13#10' (select distinct id_autoriz' + |
'zazioni'#13#10' from gruppi_funzioni gf'#13#10' where gf.id_funzion' + |
'i = gg.id_funzioni and'#13#10' gf.id_autorizzazioni = 1) as ' + |
'm_menu,'#13#10' (select distinct id_autorizzazioni'#13#10' from grupp' + |
'i_funzioni gf'#13#10' where gf.id_funzioni = gg.id_funzioni and'#13#10' ' + |
' gf.id_autorizzazioni = 2) as m_select,'#13#10' (select dis' + |
'tinct id_autorizzazioni'#13#10' from gruppi_funzioni gf'#13#10' wher' + |
'e gf.id_funzioni = gg.id_funzioni and'#13#10' gf.id_autoriz' + |
'zazioni = 3) as m_update,'#13#10' (select distinct id_autorizzazioni' + |
#13#10' from gruppi_funzioni gf'#13#10' where gf.id_funzioni = gg.' + |
'id_funzioni and'#13#10' gf.id_autorizzazioni = 4) as m_delet' + |
'e,'#13#10' (select distinct id_autorizzazioni'#13#10' from gruppi_fun' + |
'zioni gf'#13#10' where gf.id_funzioni = gg.id_funzioni and'#13#10' ' + |
' gf.id_autorizzazioni = 5) as m_print,'#13#10' (select distinct ' + |
'id_autorizzazioni'#13#10' from gruppi_funzioni gf'#13#10' where gf.' + |
'id_funzioni = gg.id_funzioni and'#13#10' gf.id_autorizzazion' + |
'i = 6) as m_printsel,'#13#10' (select distinct id_autorizzazioni'#13#10' ' + |
' from gruppi_funzioni gf'#13#10' where gf.id_funzioni = gg.id_f' + |
'unzioni and'#13#10' gf.id_autorizzazioni = 7) as m_insert'#13#10'f' + |
'rom funzioni'#13#10'inner join gruppi_funzioni gg on gg.id_funzioni = ' + |
'funzioni.id'#13#10'inner join autorizzazioni on gg.id_autorizzazioni =' + |
' autorizzazioni.id'#13#10'where gg.id_gruppi= :ID_GRUPPO' |
DataSource = 'GRUPPI' |
end |
item |
Alias = 'GRUPPI' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#13#10' gruppi.id as ID_GRUPPO, '#13#10' gruppi.* '#13#10'from gruppi, r' + |
'eport_id'#13#10'where :GROUP_ID > 0 and gruppi.id=report_id.key and ' + |
'report_id.group_id = :GROUP_ID'#13#10#13#10'UNION'#13#10#13#10'select '#13#10' gruppi.id ' + |
'as ID_GRUPPO, '#13#10' gruppi.* '#13#10'from gruppi'#13#10'where :GROUP_ID < 0 a' + |
'nd gruppi.id = - :GROUP_ID'#13#10#13#10 |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdataado |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = |
'Provider=MSDASQL.1;Persist Security Info=False;Mode=Read;Extende' + |
'd Properties="DRIVER={PostgreSQL Unicode};DATABASE=masonsql;SERV' + |
'ER=127.0.0.1;USER=report;PASSWORD=<password>;PORT=5432;UID=repor' + |
't;SSLmode=allow;ReadOnly=1;Protocol=7.4-1;FakeOidIndex=0;ShowOid' + |
'Column=0;RowVersioning=0;ShowSystemTables=0;ConnSettings=;Fetch=' + |
'100;Socket=4096;UnknownSizes=0;MaxVarcharSize=254;MaxLongVarchar' + |
'Size=8190;Debug=0;CommLog=0;Optimizer=1;Ksqo=1;UseDeclareFetch=0' + |
';TextAsLongVarchar=1;UnknownsAsLongVarchar=0;BoolsAsChar=1;Parse' + |
'=1;CancelAsFreeStmt=0;ExtraSysTablePrefixes=dd_;;LFConversion=1;' + |
'UpdatableCursors=1;DisallowPremature=0;TrueIsMinus1=0;BI=0;Bytea' + |
'AsLongVarBinary=0;UseServerSidePrepare=0;LowerCaseIdentifier=0;X' + |
'aOpt=1"' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
Value = -1 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'GRUPPI') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end |
item |
Name = 'ID_GRUPPO' |
AllowNulls = False |
Value = 0 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'ANAGRAFICHE' |
'AUTORIZZAZIONI') |
Description = '' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection3 |
end |
item |
Section = TRpSection4 |
end |
item |
Section = TRpSection6 |
end> |
Alias = 'GRUPPI' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSubReport1: TRpSubReport |
Sections = < |
item |
Section = TRpSection10 |
end> |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection0 |
end |
object TRpSection10: TRpSection |
Width = 11355 |
Height = 1455 |
SubReport = TRpSubReport1 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape2 |
end |
item |
Component = TRpExpression16 |
end |
item |
Component = TRpExpression17 |
end |
item |
Component = TRpExpression18 |
end |
item |
Component = TRpLabel0 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpLabel2 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel4 |
end |
item |
Component = TRpLabel5 |
end |
item |
Component = TRpLabel6 |
end |
item |
Component = TRpLabel7 |
end |
item |
Component = TRpShape0 |
end |
item |
Component = TRpLabel9 |
end |
item |
Component = TRpShape3 |
end> |
AutoExpand = True |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection3: TRpSection |
Width = 10772 |
Height = 30 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport3 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1230 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel11 |
end |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpLabel14 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel11: TRpLabel |
Width = 2070 |
Height = 345 |
PosX = 8745 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 13 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'MasonSQL' |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8400 |
PosY = 915 |
Type1Font = poLinked |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 8850 |
PosY = 915 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel14: TRpLabel |
Width = 4380 |
Height = 690 |
PosX = 225 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 28 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Distinta GRUPPI' |
end |
object TRpSubReport3: TRpSubReport |
Sections = < |
item |
Section = TRpSection5 |
end> |
Alias = 'AUTORIZZAZIONI' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection3 |
end |
object TRpSection5: TRpSection |
Width = 11130 |
Height = 225 |
SubReport = TRpSubReport3 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression13 |
end |
item |
Component = TRpExpression14 |
end |
item |
Component = TRpExpression15 |
end |
item |
Component = TRpExpression20 |
end |
item |
Component = TRpExpression21 |
end |
item |
Component = TRpExpression22 |
end |
item |
Component = TRpExpression23 |
end |
item |
Component = TRpExpression24 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection6: TRpSection |
Width = 10772 |
Height = 0 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = <> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
ChildSubReport = TRpSubReport2 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression13: TRpExpression |
Width = 1380 |
Height = 225 |
PosX = 120 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'AUTORIZZAZIONI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression14: TRpExpression |
Width = 1275 |
Height = 225 |
PosX = 3330 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_menu == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression15: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 4605 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_select == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression16: TRpExpression |
Width = 1725 |
Height = 360 |
PosX = 1260 |
PosY = 570 |
Type1Font = poLinked |
FontSize = 12 |
FontStyle = 1 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.nome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression17: TRpExpression |
Width = 1485 |
Height = 240 |
PosX = 2985 |
PosY = 690 |
Type1Font = poLinked |
FontSize = 8 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.descrizione' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression18: TRpExpression |
Width = 1380 |
Height = 240 |
PosX = 4605 |
PosY = 690 |
Type1Font = poLinked |
FontSize = 8 |
VAlignment = 16 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'GRUPPI.commento' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression20: TRpExpression |
Width = 810 |
Height = 225 |
PosX = 5640 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_update == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression21: TRpExpression |
Width = 930 |
Height = 225 |
PosX = 6780 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_delete == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression22: TRpExpression |
Width = 945 |
Height = 225 |
PosX = 10125 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_print == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression23: TRpExpression |
Width = 1050 |
Height = 225 |
PosX = 8970 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_printsel == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression24: TRpExpression |
Width = 990 |
Height = 225 |
PosX = 7815 |
PosY = 0 |
Type1Font = poLinked |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'IIF(AUTORIZZAZIONI.m_insert == NULL , '#39' '#39', '#39'x'#39')' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel0: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 8625 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'stampa sel.' |
end |
object TRpLabel1: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 9885 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'stampa' |
end |
object TRpLabel2: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 6435 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'cancella' |
end |
object TRpLabel3: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 5280 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'aggiorna' |
end |
object TRpLabel4: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 4140 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'selezione' |
end |
object TRpLabel5: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 3105 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'menu' |
end |
object TRpLabel6: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 120 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Nome' |
end |
object TRpLabel7: TRpLabel |
Width = 915 |
Height = 240 |
PosX = 7365 |
PosY = 1155 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'inserimento' |
end |
object TRpSubReport2: TRpSubReport |
Sections = < |
item |
Section = TRpSection1 |
end> |
Alias = 'ANAGRAFICHE' |
ParentSubReport = TRpSubReport0 |
ParentSection = TRpSection6 |
end |
object TRpSection1: TRpSection |
Width = 11730 |
Height = 135 |
SubReport = TRpSubReport2 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression3 |
end> |
HorzDesp = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression0: TRpExpression |
Width = 1605 |
Height = 225 |
PosX = 120 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.nome + '#39' '#39' + ANAGRAFICHE.cognome' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 1380 |
Height = 225 |
PosX = 2295 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.login' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2760 |
Height = 195 |
PosX = 4140 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 6 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'ANAGRAFICHE.email' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpShape2: TRpShape |
Width = 10815 |
Height = 225 |
PosX = 0 |
PosY = 345 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpSection4: TRpSection |
Width = 10772 |
Height = 630 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpShape1 |
end |
item |
Component = TRpLabel8 |
end |
item |
Component = TRpLabel10 |
end |
item |
Component = TRpLabel15 |
end |
item |
Component = TRpShape4 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpShape1: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 120 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel9: TRpLabel |
Width = 1035 |
Height = 225 |
PosX = 120 |
PosY = 690 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'GRUPPO: ' |
end |
object TRpShape3: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 1380 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel8: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 120 |
PosY = 225 |
Type1Font = poHelvetica |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'ELENCO UTENTI' |
end |
object TRpLabel10: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 2295 |
PosY = 240 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'login' |
end |
object TRpLabel15: TRpLabel |
Width = 1605 |
Height = 225 |
PosX = 4140 |
PosY = 240 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'e-mail' |
end |
object TRpShape0: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 1035 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape4: TRpShape |
Width = 10815 |
Height = 75 |
PosX = 0 |
PosY = 465 |
BrushColor = 14540253 |
PenColor = 16777215 |
PenWidth = 0 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
end |
/tags/2.0/htdocs/data/public/logs_report.kylix.rep |
---|
0,0 → 1,503 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end> |
DataInfo = < |
item |
Alias = 'LOGS_REPORT' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#10' logs_report.table_name,'#10' logs_report.id_record,'#10' to' + |
'_char(logs_report.timestamp, '#39'DD/MM/YYYY HH24:MM'#39') as timestamp,' + |
#10' logs_report.report,'#10' coalesce(anagrafiche.nome || '#39' '#39', '#39#39') |' + |
'| coalesce(anagrafiche.cognome) as nominativo'#10'from '#10' public.rep' + |
'ort_id, public.logs_report, public.anagrafiche'#10'where '#10' ( :GROUP' + |
'_ID = 0 or report_id.group_id = :GROUP_ID'#10' ) and logs_report.id' + |
'=report_id.key and anagrafiche.id = logs_report.id_anagrafiche'#10'o' + |
'rder by logs_report.timestamp desc;'#10#10 |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdatazeos |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = '' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
AllowNulls = False |
Value = 0 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'LOGS_REPORT') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection1 |
end> |
Alias = 'LOGS_REPORT' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 911 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression3 |
end |
item |
Component = TRpShape1 |
end> |
AutoExpand = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1007 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpExpression1 |
end |
item |
Component = TRpLabel0 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpLabel2 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel4 |
end |
item |
Component = TRpExpression6 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8983 |
PosY = 118 |
Type1Font = poHelvetica |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 9433 |
PosY = 118 |
Type1Font = poHelvetica |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression0: TRpExpression |
Width = 8229 |
Height = 696 |
PosX = 2527 |
PosY = 118 |
Type1Font = poHelvetica |
FontSize = 8 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.report' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 2420 |
Height = 460 |
PosX = 0 |
PosY = 343 |
Type1Font = poHelvetica |
FontSize = 9 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.nominativo' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2420 |
Height = 225 |
PosX = 0 |
PosY = 118 |
Type1Font = poHelvetica |
FontSize = 9 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.timestamp' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel0: TRpLabel |
Width = 3100 |
Height = 294 |
PosX = 3791 |
PosY = 0 |
Type1Font = poHelvetica |
FontSize = 12 |
FontStyle = 1 |
Alignment = 4 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Variazioni dei dati' |
end |
object TRpSection1: TRpSection |
Width = 10767 |
Height = 349 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpfooter |
Components = < |
item |
Component = TRpExpression4 |
end |
item |
Component = TRpShape0 |
end |
item |
Component = TRpExpression5 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
FooterAtReportEnd = True |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression4: TRpExpression |
Width = 2762 |
Height = 231 |
PosX = 7703 |
PosY = 114 |
Type1Font = poHelvetica |
FontSize = 9 |
Alignment = 2 |
VAlignment = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = #39'Pag. '#39'+Str(NUMPAGINA)+'#39' di '#39 |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel2: TRpLabel |
Width = 2880 |
Height = 235 |
PosX = 6787 |
PosY = 463 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = '[xxxx] - dato cancellato' |
end |
object TRpLabel3: TRpLabel |
Width = 2880 |
Height = 235 |
PosX = 6787 |
PosY = 691 |
Type1Font = poHelvetica |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = '{xxxx} - dato inserito' |
end |
object TRpShape0: TRpShape |
Width = 10810 |
Height = 115 |
PosX = 0 |
PosY = 114 |
Shape = rpsHorzLine |
PenWidth = 17 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape1: TRpShape |
Width = 10810 |
Height = 115 |
PosX = 0 |
PosY = 50 |
PenColor = 5855577 |
Shape = rpsHorzLine |
PenWidth = 17 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel1: TRpLabel |
Width = 911 |
Height = 353 |
PosX = 0 |
PosY = 578 |
Type1Font = poHelvetica |
FontSize = 11 |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tabella: ' |
end |
object TRpExpression1: TRpExpression |
Width = 4144 |
Height = 353 |
PosX = 921 |
PosY = 578 |
Type1Font = poHelvetica |
FontSize = 11 |
FontStyle = 1 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.table_name' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel4: TRpLabel |
Width = 338 |
Height = 338 |
PosX = 0 |
PosY = 235 |
Type1Font = poHelvetica |
FontSize = 11 |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'ID: ' |
end |
object TRpExpression6: TRpExpression |
Width = 1734 |
Height = 338 |
PosX = 338 |
PosY = 235 |
Type1Font = poHelvetica |
FontSize = 11 |
FontStyle = 1 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.id_record' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression5: TRpExpression |
Width = 298 |
Height = 231 |
PosX = 10466 |
PosY = 114 |
Type1Font = poHelvetica |
FontSize = 9 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'PAGECOUNT' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
end |
/tags/2.0/htdocs/data/public/logs_report.wine.rep |
---|
0,0 → 1,515 |
object TRpReport |
PageOrientation = rpOrientationPortrait |
Pagesize = rpPageSizeCustom |
PageHeight = 8120 |
PageWidth = 5742 |
PageBackColor = 2147483647 |
LeftMargin = 454 |
TopMargin = 454 |
RightMargin = 454 |
BottomMargin = 454 |
SubReports = < |
item |
SubReport = TRpSubReport0 |
end> |
DataInfo = < |
item |
Alias = 'LOGS_REPORT' |
DatabaseAlias = 'MASONSQL' |
SQL = |
'select '#13#10' logs_report.table_name,'#13#10' logs_report.id_record,'#13#10' ' + |
' to_char(logs_report.timestamp, '#39'DD/MM/YYYY HH24:MM'#39') as timesta' + |
'mp,'#13#10' logs_report.report,'#13#10' coalesce(anagrafiche.nome || '#39' '#39', ' + |
#39#39') || coalesce(anagrafiche.cognome) as nominativo'#13#10'from '#13#10' pub' + |
'lic.report_id, public.logs_report, public.anagrafiche'#13#10'where '#13#10' ' + |
'( :GROUP_ID = 0 or report_id.group_id = :GROUP_ID'#13#10' ) and logs' + |
'_report.id=report_id.key and anagrafiche.id = logs_report.id_ana' + |
'grafiche'#13#10'order by logs_report.timestamp desc;'#13#10#13#10 |
end> |
DatabaseInfo = < |
item |
Alias = 'MASONSQL' |
LoadParams = True |
LoadDriverParams = True |
LoginPrompt = False |
Driver = rpdataado |
ReportTable = 'REPMAN_REPORTS' |
ReportSearchField = 'REPORT_NAME' |
ReportField = 'REPORT' |
ReportGroupsTable = 'REPMAN_GROUPS' |
ADOConnectionString = |
'Provider=MSDASQL.1;Persist Security Info=False;Mode=Read;Extende' + |
'd Properties="DRIVER={PostgreSQL Unicode};DATABASE=masonsql;SERV' + |
'ER=127.0.0.1;USER=report;PASSWORD=<password>;PORT=5432;UID=repor' + |
't;SSLmode=allow;ReadOnly=1;Protocol=7.4-1;FakeOidIndex=0;ShowOid' + |
'Column=0;RowVersioning=0;ShowSystemTables=0;ConnSettings=;Fetch=' + |
'100;Socket=4096;UnknownSizes=0;MaxVarcharSize=254;MaxLongVarchar' + |
'Size=8190;Debug=0;CommLog=0;Optimizer=1;Ksqo=1;UseDeclareFetch=0' + |
';TextAsLongVarchar=1;UnknownsAsLongVarchar=0;BoolsAsChar=1;Parse' + |
'=1;CancelAsFreeStmt=0;ExtraSysTablePrefixes=dd_;;LFConversion=1;' + |
'UpdatableCursors=1;DisallowPremature=0;TrueIsMinus1=0;BI=0;Bytea' + |
'AsLongVarBinary=0;UseServerSidePrepare=0;LowerCaseIdentifier=0;X' + |
'aOpt=1"' |
end> |
Params = < |
item |
Name = 'GROUP_ID' |
AllowNulls = False |
Value = -1 |
ParamType = rpParamInteger |
Datasets.Strings = ( |
'LOGS_REPORT') |
Description = 'Identificatore report_id per stampa multipla' |
Hint = '' |
Search = '' |
ErrorMessage = '' |
Validation = '' |
end> |
TwoPass = True |
StreamFormat = rpStreamText |
ReportAction = [] |
Type1Font = poHelvetica |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
object TRpSubReport0: TRpSubReport |
Sections = < |
item |
Section = TRpSection2 |
end |
item |
Section = TRpSection0 |
end |
item |
Section = TRpSection1 |
end> |
Alias = 'LOGS_REPORT' |
PrintOnlyIfDataAvailable = False |
end |
object TRpSection0: TRpSection |
Width = 10772 |
Height = 911 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecdetail |
Components = < |
item |
Component = TRpExpression0 |
end |
item |
Component = TRpExpression2 |
end |
item |
Component = TRpExpression3 |
end |
item |
Component = TRpShape1 |
end> |
AutoExpand = True |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpSection2: TRpSection |
Width = 10772 |
Height = 1007 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpheader |
Components = < |
item |
Component = TRpLabel12 |
end |
item |
Component = TRpExpression12 |
end |
item |
Component = TRpExpression1 |
end |
item |
Component = TRpLabel0 |
end |
item |
Component = TRpLabel1 |
end |
item |
Component = TRpLabel2 |
end |
item |
Component = TRpLabel3 |
end |
item |
Component = TRpLabel4 |
end |
item |
Component = TRpExpression6 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpLabel12: TRpLabel |
Width = 465 |
Height = 225 |
PosX = 8983 |
PosY = 118 |
Type1Font = poLinked |
FontSize = 8 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'helvetica' |
WideText = 'Data:' |
end |
object TRpExpression12: TRpExpression |
Width = 1155 |
Height = 225 |
PosX = 9433 |
PosY = 118 |
Type1Font = poLinked |
FontSize = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'FormatStr('#39'dd/mm/yyyy'#39', today)' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression0: TRpExpression |
Width = 8229 |
Height = 696 |
PosX = 2535 |
PosY = 120 |
Type1Font = poLinked |
FontSize = 8 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.report' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression2: TRpExpression |
Width = 2420 |
Height = 460 |
PosX = 8 |
PosY = 345 |
Type1Font = poLinked |
FontSize = 9 |
WordWrap = True |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.nominativo' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression3: TRpExpression |
Width = 2420 |
Height = 225 |
PosX = 8 |
PosY = 120 |
Type1Font = poLinked |
FontSize = 9 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.timestamp' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel0: TRpLabel |
Width = 3100 |
Height = 294 |
PosX = 3791 |
PosY = 0 |
Type1Font = poLinked |
FontSize = 12 |
FontStyle = 1 |
Alignment = 4 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Variazioni dei dati' |
end |
object TRpSection1: TRpSection |
Width = 10767 |
Height = 349 |
SubReport = TRpSubReport0 |
ChangeBool = False |
PageRepeat = False |
SkipPage = False |
AlignBottom = False |
SectionType = rpsecpfooter |
Components = < |
item |
Component = TRpExpression4 |
end |
item |
Component = TRpShape0 |
end |
item |
Component = TRpExpression5 |
end> |
ExternalTable = 'REPMAN_REPORTS' |
ExternalField = 'REPORT' |
ExternalSearchField = 'REPORT_NAME' |
StreamFormat = rpStreamText |
FooterAtReportEnd = True |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
ChangeExpression = '' |
BeginPageExpression = '' |
ChangeExpression = '' |
SkipExpreV = '' |
SkipExpreH = '' |
SkipToPageExpre = '' |
BackExpression = '' |
Stream = {0000000000000000} |
end |
object TRpExpression4: TRpExpression |
Width = 2762 |
Height = 231 |
PosX = 7703 |
PosY = 114 |
Type1Font = poHelvetica |
FontSize = 9 |
Alignment = 2 |
VAlignment = 8 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = #39'Pag. '#39'+Str(NUMPAGINA)+'#39' di '#39 |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel2: TRpLabel |
Width = 2880 |
Height = 235 |
PosX = 6787 |
PosY = 463 |
Type1Font = poLinked |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = '[xxxx] - dato cancellato' |
end |
object TRpLabel3: TRpLabel |
Width = 2880 |
Height = 235 |
PosX = 6787 |
PosY = 691 |
Type1Font = poLinked |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = '{xxxx} - dato inserito' |
end |
object TRpShape0: TRpShape |
Width = 10810 |
Height = 115 |
PosX = 0 |
PosY = 114 |
Shape = rpsHorzLine |
PenWidth = 17 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpShape1: TRpShape |
Width = 10810 |
Height = 115 |
PosX = 8 |
PosY = 52 |
PenColor = 5855577 |
Shape = rpsHorzLine |
PenWidth = 17 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
end |
object TRpLabel1: TRpLabel |
Width = 911 |
Height = 353 |
PosX = 0 |
PosY = 578 |
Type1Font = poLinked |
FontSize = 11 |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'Tabella: ' |
end |
object TRpExpression1: TRpExpression |
Width = 4144 |
Height = 353 |
PosX = 921 |
PosY = 578 |
Type1Font = poLinked |
FontSize = 11 |
FontStyle = 1 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.table_name' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpLabel4: TRpLabel |
Width = 338 |
Height = 338 |
PosX = 0 |
PosY = 235 |
Type1Font = poLinked |
FontSize = 11 |
FontStyle = 1 |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
WideText = 'ID: ' |
end |
object TRpExpression6: TRpExpression |
Width = 1734 |
Height = 338 |
PosX = 338 |
PosY = 235 |
Type1Font = poLinked |
FontSize = 11 |
FontStyle = 1 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'LOGS_REPORT.id_record' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
object TRpExpression5: TRpExpression |
Width = 298 |
Height = 231 |
PosX = 10466 |
PosY = 114 |
Type1Font = poHelvetica |
FontSize = 9 |
AutoExpand = False |
AutoContract = False |
ExportPosition = 0 |
ExportSize = 1 |
ExportDoNewLine = False |
PrintCondition = '' |
DoBeforePrint = '' |
DoAfterPrint = '' |
WFontName = 'Arial' |
LFontName = 'Helvetica' |
Expression = 'PAGECOUNT' |
DisplayFormat = '' |
ExportDisplayFormat = '' |
AgIniValue = '0' |
ExportExpression = '' |
end |
end |
/tags/2.0/htdocs/data/dhandler |
---|
0,0 → 1,10 |
<%doc> |
Metodo di 'default'; non fa nulla in quanto i metodi di default sono |
implementati in autohandler. |
Questo permette di definire oggetti di accesso al database il cui <nome>.mql |
corrispondono al nome della tabella. |
NON CANCELLARE QUESTO FILE!!! |
</%doc> |
/tags/2.0/htdocs/data/global_autohandler |
---|
0,0 → 1,179 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2018 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%once> |
use JSON; |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
my $BaseUrl = $r->dir_config('BaseUrl'); |
</%once> |
<%flags> |
inherit => '/lib/dbms_library.comp' # # NON CANCELLARE !!! |
</%flags> |
%#----------------------------------------------------------------------- |
%# overload metodi di uso generale nell'applicazione specifica |
%#----------------------------------------------------------------------- |
%# per definire un campo è possibile definire un metodo di nome <nome_campo>_FIELD |
<%method GenericSelect_FIELD>\ |
<%args> |
$from |
$remote => undef |
$buffer => $from |
$readonly => 1 |
$widget => 'htmlselect' # oppure 'select' o 'divselect' |
</%args> |
<%perl> |
$buffer =~ s/[\/\\\.]/_/g; # caratteri che non si possono utilizzare come nome buffer |
$ARGS{'buffer'} = $buffer; |
$ARGS{'remote'} = $remote; |
if(!exists $ARGS{empty}){ |
$ARGS{empty} = ''; |
} |
if(!exists $ARGS{empty_descr}){ |
$ARGS{empty_descr} = ''; |
} |
if(!exists $ARGS{empty_button} && $widget eq 'divselect'){ |
# il pulsante di nessuna selezione nel widget divselect è incomprensibile se non contiene una descrizione; |
$ARGS{empty_button} = 'Nessuna descrizione'; |
} |
delete $ARGS{'length'}; |
delete $ARGS{'size'}; |
$widget = "/input/$widget.comp"; |
</%perl> |
<& $widget, %ARGS &>\ |
</%method> |
<%method JSON_SELECT_FIELDS> |
<%args> |
$JSON_FIELD => 'fields' |
</%args> |
<%perl> |
my $attrs = $m->comp('SELF:INFO', OBJ => 1); |
my @list; |
my @names = &Method2Array('FIELDS'); |
my %standards = map { $_ => 1 } &Method2Array('STANDARD_FIELDS'); |
foreach my $name (@names){ |
if(exists $ARGS{$name}){ |
push @list, $ARGS{$name}; |
}elsif($standards{$name}){ |
push @list, $name; |
}else{ |
# Nota: se il campo contiene altri oggetti JSON annidati viene restituita una stringa JSON |
my $json_key = exists $attrs->{$name}{JSON} ? $attrs->{$name}{JSON} : $name; |
push @list, "$JSON_FIELD->>'$json_key' as $name"; |
} |
} |
$m->out(join ', ', @list); |
</%perl> |
</%method> |
<%method JSON_INSERT> |
<%args> |
$JSON_FIELD => 'fields' |
$FIELDS_INSERT |
</%args> |
<%perl> |
my $attrs = $m->comp('SELF:INFO', OBJ => 1); |
my @standards = &Method2Array('STANDARD_FIELDS'); |
my %standards; |
foreach my $name (@standards){ |
$standards{$name} = 1; |
} |
my %FIELDS; |
# empty fields are replaced with undef value |
foreach my $key (keys %$FIELDS_INSERT){ |
if(!$standards{$key}){ |
my $value = delete $FIELDS_INSERT->{$key}; |
if(defined $value && $value ne ''){ |
if($value =~ m/^\{.*\}$/ or $value =~ m/^\[.*\]$/){ |
# se il campo contiene una stringa in formato JSON senza errori ... |
my $json = eval { from_json $value }; |
if(!$@){ |
$value = $json; |
} |
} |
my $json_key = exists $attrs->{$key}{JSON} ? $attrs->{$key}{JSON} : $key; |
$FIELDS{$json_key} = $value; |
} |
} |
} |
# fields are returned with values in the JSON hash |
$FIELDS_INSERT->{$JSON_FIELD} = to_json(\%FIELDS); |
</%perl> |
</%method> |
<%method JSON_UPDATE> |
<%args> |
$JSON_FIELD => 'fields' |
$FIELDS_UPDATE |
</%args> |
<%perl> |
my $attrs = $m->comp('SELF:INFO', OBJ => 1); |
my @standards = &Method2Array('STANDARD_FIELDS'); |
my %standards; |
foreach my $name (@standards){ |
$standards{$name} = 1; |
} |
my %FIELDS; |
foreach my $key (keys %$FIELDS_UPDATE){ |
if(!$standards{$key}){ |
my $value = delete $FIELDS_UPDATE->{$key}; |
if($value eq ''){ |
# empty fields are replaced with undef value |
$value = undef; |
}elsif($value =~ m/^\{.*\}$/ or $value =~ m/^\[.*\]$/){ |
# se il campo contiene una stringa in formato JSON senza errori ... |
my $json = eval { from_json $value }; |
if(!$@){ |
$value = $json; |
} |
} |
my $json_key = exists $attrs->{$key}{JSON} ? $attrs->{$key}{JSON} : $key; |
$FIELDS{$json_key} = $value; |
} |
} |
# using array ref it is possible to change assignment (default equal to '?' as value of the field) |
# fields are replaced with new values in the JSON hash |
$FIELDS_UPDATE->{$JSON_FIELD} = [qq[coalesce($JSON_FIELD, '{}'::jsonb) || ?::jsonb], to_json(\%FIELDS)]; |
</%perl> |
</%method> |
%# chiamata per valutare la query fornita dal browser |
<%method JSON_WHERE>\ |
<%args> |
$JSON_FIELD => 'fields' |
$arr_where |
$no_check => undef |
</%args> |
<%perl> |
my $attrs = $m->comp('SELF:INFO', OBJ => 1); |
# rielaboro la query per adattarla ai reali campi presenti nel database di tipo JSON |
my %standards = map { $_ => 1 } &Method2Array('STANDARD_FIELDS'); |
foreach my $par (@$arr_where){ |
my $key = $par->[0]; |
if($key !~ m/^--/){ # no special key |
if(!exists $standards{$key}){ |
my $json_key = exists $attrs->{$key}{JSON} ? $attrs->{$key}{JSON} : $key; |
if(defined $par->[2]){ |
$par->[4] = "$JSON_FIELD->>'$json_key'"; |
}else{ |
$par->[4] = "coalesce($JSON_FIELD->>'$json_key', '')"; |
$par->[3] = undef; |
$par->[2] = ''; |
} |
} |
}elsif(!$no_check && $key =~ '^--where'){ |
# verifica la sub-query alla ricerca di codice SQL non autorizzato (sql injection) |
&check_where_clause(shift @$par); |
} |
} |
return $arr_where; |
</%perl></%method> |
/tags/2.0/htdocs/data/autohandler |
---|
0,0 → 1,16 |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%once> |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
my $BaseUrl = $r->dir_config('BaseUrl'); |
</%once> |
<%flags> |
inherit => '/data/global_autohandler' # # NON CANCELLARE !!! |
</%flags> |
/tags/2.0/htdocs/lib/displaybinding.js |
---|
0,0 → 1,2001 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2003 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
---+ libreria DisplayBinding |
Provvede ad effettuare l'aggiornamento dei dati gestiti dalla classe dataBinding |
L'oggetto mette a disposizione una serie di metodi richiamati direttamente |
da recordset a risposta degli eventi che aggiornano i dati. |
Per accedere ai campi nel form la libreria utilizza una matrice di riferimenti agli oggetti |
<this.fields[row,col]> che deve viene predisposta dopo la creazione dell'oggetto "DisplayBinding" |
utilizzando il metodo ... . |
Per la selezione di righe da cancellare va predisposto un vettore <checks[row]> contenetene |
i riferimenti agli oggetti "checkbox". |
Al caricamento del primo blocco di dati la libreria inizializza anche il seguente vettore: |
* vettore <labels[col]> con la etichetta dei campi da visualizzare nel form. |
---++ Form associati ai dataBinding con numero di record variabili, visualizzati dinamicamente |
Oltre alla gestione del recordset con form dal rumero di righe fisse (per visualizzare e modificare un corrispondente |
numero di record), la libreria permette anche la rappresentazione di form con numero di righe visualizzate pari al numero di |
record o meno del recordset. |
Lo scopo di questa modalità di funzionamento è quello di permettere il caricamento dinamico di template differenti per ogni |
riga associati a differenti contenuti del record relativo e/o rappresentare l'intero recordset (poche righe comunque) abilitando |
le funzioni di inserimento, modifica e cancellazione di record e gestire la corrispondente visualizzazione dinamica nel form che |
cambierà di lunghezza e contenuto grafico. |
La modalità è disponibile solo per i form DIVS (non per TABLE) in quanto gestiscono meglio le funzionalià di inserimento e |
cancellazione di blocchi HTML, collocati in tag "<div/>" |
Per il caricamento dinamico delle righe viene utilizzato il metodo ROWS_DIVS che restituisce tutte le righe che rappresentano |
i singoli form di un record (una righa). |
Per ottenere un form differente in funzione del contenuto del record si passa al metodo il parametro "type" che determina il |
tipo di form; è responsabilità dell'applicazione definire il metodo .type_div che restituisce il tipo di form; se il metodo |
non è definito, al parametro "type" verrà passato il valore "undef". |
DEPRECATED: Per il caricamento dinamico delle righe viene utilizzato il metodo ROW_DIVS che rappresenta il singolo form di un rec |
Per ottenere un form differente in funzione del contenuto del record si passa al metodo il parametro "type" che determina il |
tipo di form; è responsabilità dell'applicazione definire il metodo .type_div che restituisce il tipo di form; se il metodo |
non è definito, al parametro "type" verrà passato il valore "undef". |
</%doc> |
// variabile globale con i riferimenti nome --> oggetto DisplayBinding |
DisplayBinding_ContextPool = []; |
// Oggetto DisplayBinding per la navigazione di dati SQL nel browser |
// |
// constructor for DisplayBinding object |
// Parametri: |
// dataBinding oggetto dataBinding |
// |
function DisplayBinding(prefix, db){ |
// oggetto DataBinding |
this.dataBinding = db; |
this.prefix = prefix; |
this.id = prefix; |
// l'oggetto DisplayBinding (usato dagli Handler degli eventi lanciati dall'oggetto DataBinding |
db.displayBinding = this; |
// aggancio le funzioni agli eventi generati da DataBinding |
db.onload = DisplayBinding_onloadHandler; |
db.onloadrecord = DisplayBinding_onloadrecordHandler; |
db.ondeleterecords = DisplayBinding_ondeleterecordsHandler; |
db.onrequest = DisplayBinding_onrequestHandler; |
db.onprechange = DisplayBinding_onprechangeHandler; |
db.onchange = DisplayBinding_onchangeHandler; |
db.onerror = DisplayBinding_onerrorHandler; |
db.onreadonly = DisplayBinding_onreadonlyHandler; |
// Oggetto grafico contenitore del widget interessato dal binding dei dati |
// (utilizzato per bloccare o nascondere l'area interessata) |
this.widgetsContainer = null; |
// matrice dei widget |
this.fields = []; |
// vettore di input di tipo check utilizzati per selezionare i record visualizzati |
// per operazioni di insieme (stampa, cancellazione) |
this.checks = null; |
// vettore delle etichette nel form (usate per visualizzare la chiave del record) |
this.labels = []; |
// vettore delle intestazioni nel form |
this.headers = []; |
// vettore di template; usato con il componente di tipo DIVS |
this.divs = []; |
// dup è un oggetto utilizzato per copiare la riga record nel display da duplicare |
this.dup = null; |
// cp_record is a copy of record to be duplicated in the pasted lines with Copy-Paste method |
this.cp_record = null; |
//this.cp = null; |
// indicates row number of copied record |
this.cp_row = null; |
// contains cp_fields which are selected |
this.cp_modes = []; |
// contains row number of previously checked row |
this.cp_previous = null; |
// indicates whether there is any selectable row |
this.cp_enabled = false; |
// oggetto contenente i vari controlli di navigazione |
this.navigationBar = {}; |
// abilita/disabilita i pulsanti di navigazione |
this.navigationBar.setButtons = NavigationBar_setButtons; |
// campi del filtro di ricerca |
// widget contenuto del campo filtro |
this.finds = null; |
// contiene i nomi dei campi di ricerca nell'ordine in cui vengono forniti nel vettore .finds |
this.find_fields = null; |
// contiene gli operatori di filtro |
this.ftypes = null; |
// contiene le posizioni dei campi di ricerca, individuati dal loro nome (è l'inverso di .find_fields) |
this.find_fields_pos = []; |
// oggetto del documento (SPAN, DIV, ecc.) per la visualizzazione della posizione nel recordset |
this.info = null; |
// condizione where imposta al display |
this.where = ''; |
// abilita il movimento tra i campi con Enter(Invio) e con i tasti freccia |
this.formKeysMovement = ''; |
// record padre in evidenza |
this.rowFather = null; |
// methods |
// chiamato da /frame.comp dopo la creazione del form |
this.post_init = DisplayBinding_post_init; |
// valuta l'elenco delle chiavi dei record selezionati |
this.selectedKeys = DisplayBinding_selectedKeys; |
// stampa il recordset in funzione del tipo di stampa |
this.printSelected = DisplayBinding_printSelected; |
// visualizza il Log delle modifiche apportate |
this.displayLog = DisplayBinding_displayLog; |
// modifica lo stato lettura/scrittura dei widget e relativo recordset |
this.readOnly = DisplayBinding_readOnly; |
// modifica lo ststo dei bottoni di navigazione |
this.setButtons = DisplayBinding_setButtons; |
// Abilita/disabilita il bottone (se nascosto lo attiva) |
this.disableButton = DisplayBinding_disableButton; |
// utilizzata per aggiornare lo stato di una riga quando si utilizzano i DIVS |
this.Divs_onChange = DisplayBinding_Divs_onChange; |
// sostituisce nell'oggetto HTML "div_container" la riga template identificata da "id" |
// sostituendo nel template l'identificativo di riga "id_row" |
this.updateTemplateRow = DisplayBinding_updateTemplateRow; |
// |
this.load_Row = DisplayBinding_load_Row; |
// Inizializza gli array .checks, .labels e la matrice .fields con i riferimenti |
// dei widget che compongono il form |
this.bindEditComponents = DisplayBinding_bindEditComponents; |
// Inizializza gli array .checks, .labels e la matrice .fields con i riferimenti |
// dei widget che compongono la singola riga del form |
this.bindEditComponentsRow = DisplayBinding_bindEditComponentsRow; |
// ritorna l'identificatore del widget del campo/etichetta, campi di ricerca o intestazione |
this.getField = DisplayBinding_getField; |
// nasconde/mostra la colonna del campo nel form |
this.hiddenColumn = DisplayBinding_hiddenColumn; |
// ritorna l'identificatore del widget di una particolare chiave record |
this.getFieldByKey = DisplayBinding_getFieldByKey; |
// metodo che ritorna una clausola "where" in formato JSON da inviare al server |
// il package mette a disposizione la funzione DisplayBinding_jsonWhere |
// utilizzata, ad esempio, da method FIND e method FIND_MENU (vedi dbms_library.comp) |
this.jsonWhere = DisplayBinding_jsonWhere; |
// metodo che ritorna una clausola di ordinamento dei campi da inviare al server |
this.sqlOrderBy = null; |
// attiva/disattiva l'area dei widget dallo stato di attesa |
this.waitingStatus = DisplayBinding_waitingStatus; |
// calcella i record selezionati |
this.deleteSelected = DisplayBinding_deleteSelected; |
// recupera i dati dal server applicando il filtro corrente |
this.loadRecords = DisplayBinding_loadRecords; |
// lancia un metodo remoto sul server definito come CALL_REMOTE_<function> aggiornando le condizioni di filtro ed ordinamento |
this.callRemote = DisplayBinding_callRemote; |
// spostamenti nel recordset |
this.gotoRecords = DisplayBinding_gotoRecords; |
// Annulla le modifiche in corso |
this.cancelUpdate = DisplayBinding_cancelUpdate; |
// Apre un form con maggiore dettaglio del record indicato (parametro: riga del record) |
this.openFormDetail = DisplayBinding_openFormDetail; |
// Apre un form con maggiore dettaglio del record indicato per chiave |
this.openFormDetailByKey = DisplayBinding_openFormDetailByKey; |
// Seleziona la riga quale Padre corrente |
this.selectRowFather = DisplayBinding_selectRowFather; |
// Uncheck all rows and return list of rows that were checked |
this.uncheckAll = DisplayBinding_uncheckAll; |
// Functions used by both dup (Duplica button) and cp (Copy-Paste): |
// Create a new record |
this.newRecord = DisplayBinding_newRecord; |
// Make a copy of the original field by taking into account cp_fields and dup_fields |
this.duplicateField = DisplayBinding_duplicateField; |
// Make a copy of the original record by taking into account cp_fields and dup_fields |
this.duplicateRecord = DisplayBinding_duplicateRecord; |
// Make a full copy of the content of the original record |
this.copyRecord = DisplayBinding_copyRecord; |
// Functions for Copy-Pasting in the displayed table: |
// Undo changes of the record - only in the fields selected for copy-paste |
this.cpUndoRecord = DisplayBinding_cpUndoRecord; |
// Delete row to be copied |
this.cpDeleteCopy = DisplayBinding_cpDeleteCopy; |
// Set Copy-Paste class of the 'sel.' field in the table header |
this.cpSetSelect = DisplayBinding_cpSetSelect; |
// Invert Copy-Paste selection of the field in the table header |
this.cpInvertHeader = DisplayBinding_cpInvertHeader; |
// Set all Copy-Paste classes in the table header |
this.cpSetHeaderClass = DisplayBinding_cpSetHeaderClass; |
// Deselect selection in the table header |
this.cpDeselectHeaders = DisplayBinding_cpDeselectHeaders; |
// Invert Copy-Paste selection of entire table header |
this.cpInvertAllHeaders = DisplayBinding_cpInvertAllHeaders; |
// Set Copy-Paste properties and classes of the table row |
this.cpSetRow = DisplayBinding_cpSetRow; |
// Set Copy-Paste classes of the table row |
this.cpSetRowClasses = DisplayBinding_cpSetRowClasses; |
// Set Copy-Paste properties and classes of table rows checked with Shift key |
this.cpSetMultipleRows = DisplayBinding_cpSetMultipleRows; |
// Update row's Copy-Paste classes |
this.cpRefreshRow = DisplayBinding_cpRefreshRow; |
// Set Copy-Paste properties and classes of the table column |
this.cpSetColumn = DisplayBinding_cpSetColumn; |
// Set Copy-Paste classes of single table field |
this.cpSetFieldClass = DisplayBinding_cpSetFieldClass; |
// Uncheck all rows except of the copied row |
this.cpUncheckPasted = DisplayBinding_cpUncheckPasted; |
// Convert FIELDS_COPY_PASTE information to the cp.modes[] array |
this.cpSetModes = DisplayBinding_cpSetModes; |
// Update complete displayed table with Copy-Paste properties and classes |
this.cpSetAll = DisplayBinding_cpSetAll; |
// Forza il campo nel form e nel dataset (no aggiornamento nel server) |
this.forceValueField = DisplayBinding_forceValueField; |
// events |
this.oninit = null; // chiamata dopo la inizializzazione del form |
this.onload = null; // chiamata dopo la prima inizializzazione |
this.onchange = null; // richiama la funzione indicata quando i dati sono stati aggiornati |
this.onrequest = null; // richiama la funzione indicata quando inizia una richiesta di cambio del recordset |
this.onloadrecord = null; // richiama la funzione indicata dopo che displaybinding ha preparato i dati nel databinding per l'invio |
this.deleterecords = null; // richiama la funzione indicata quando arriva una richiesta di cancellazione di records |
this.onreadonly = null; // richiama la funzione indicata dopo che displaybinding ha modificato lo stato lettura/scrittura del display |
this.onclosedetail = null // richiama la funzione indicata alla chiusura del form di dettaglio |
masonSql.disp[prefix] = this; |
} |
// valuta l'elenco delle chiavi dei record selezionati |
function DisplayBinding_selectedKeys(){ |
var lista = []; |
var db = this.dataBinding; |
if(db.max_table_rows == 1){ |
// se ho un solo record non occorre testare i check dei record da cancellare |
if(db.keys[0] != null){ |
lista.push(db.keys[0]); |
} |
}else if(this.checks){ |
for(var R=0; R < db.max_table_rows; R++){ |
var checksR = this.checks[R]; |
if(db.keys[R] && checksR && checksR.checked){ |
checksR.checked = false; |
lista.push(db.keys[R]); |
} |
} |
if(!lista.length && this.rowFather != null){ |
lista.push(db.keys[this.rowFather]); |
} |
} |
return lista; |
} |
// stampa del recordset |
// type: sel -> stampa della selezione corrente |
// type: recordset -> stampa del recordset filtrato |
function DisplayBinding_printSelected(type, report, cmdParams){ |
var db = this.dataBinding; |
// aggiorno il filtro corrente |
var json_where = this.jsonWhere(); |
if(!db.json_where != !json_where && !confirm('Hai cambiato la selezione senza aggiornare i dati visualizzati.\nConfermi la stampa dei dati con i filtri indicati?')){ |
return false; |
} |
db.json_where = json_where; |
// aggiorno ordinamento corrente |
db.orderby = (this.sqlOrderBy) ? this.sqlOrderBy() : ''; |
var url; |
//DEBUG my_alert("DisplayBinding_printSelected "+type); |
switch(type){ |
case 'odt_rpt': |
case 'pdf_rpt': |
case 'sel': |
if(!db.canPrint && report == null){ // test solo sul report principale |
my_alert('Non siete autorizzati a stampare','txt'); |
return; |
} |
// valutazione della lista delle chiavi da stampare |
var keyList = this.selectedKeys(); |
if(!keyList.length){ |
my_alert('Nessun record selezionato per la stampa','txt'); |
return; |
} |
url = db.printUrl(type, keyList, report, cmdParams); |
break; |
case 'xls_sel': |
if(!db.canXls){ |
my_alert('Non siete autorizzati a scaricare i dati in formato XLS','txt'); |
return; |
} |
// valutazione della lista delle chiavi da stampare |
var keyList = this.selectedKeys(); |
// if keylist is empty the xls file include all records |
url = db.printUrl(type, keyList); |
window.open(url, '_blank'); |
return; |
case 'recordset': |
if(!db.canPrintsel){ |
my_alert('Non siete autorizzati a stampare','txt'); |
return; |
} |
url = db.printUrl(type, report); |
break; |
case 'create_recordset': |
if(!db.canPrintsel){ |
my_alert('Non siete autorizzati a stampare','txt'); |
return; |
} |
url = db.printUrl(type); |
break; |
case 'xls_recordset': |
if(!db.canXls){ |
my_alert('Non siete autorizzati a scaricare i dati in formato XLS','txt'); |
return; |
} |
url = db.printUrl(type); |
window.open(url, '_blank'); |
return; |
default: |
my_alert("ERRORE: DisplayBinding_Print type="+type+" sconosciuto",'txt'); |
return; |
} |
//DEBUG my_alert(URL); |
// apro una nuova finestra indipendente |
var params = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable,alwaysRaised,dependent,titlebar=no'; |
var LANDSCAPE = false; |
var re_landscape = /^LAND/i; |
// db.print_form contiene <method PRINT_FORM> inizializzato da dbms_library.comp |
// se il nome del form (che per default corrisponde a <method FROM%>.rep) |
// inizia per "LAND" o "land" verrà scelta la visualizzazione landscape (orizzontale) |
for(var I=1; I<db.print_form.length; I++){ |
if(re_landscape.test(db.print_form[I])){ |
LANDSCAPE = true; |
break; |
} |
} |
var w = LANDSCAPE ? 800 : 600; |
var h = LANDSCAPE ? 600 : 800; |
var left = (screen.width - w) / 2; |
var top = (screen.height - h) / 3; |
window.open(url, '_blank', 'width='+w+',height='+h+',top='+top+',left='+left+','+params); |
} |
// visualizza il Log delle modifiche apportate al recordset |
function DisplayBinding_displayLog(){ |
var keys = this.selectedKeys(); |
var db = this.dataBinding; |
if(keys.length == 0){ |
// se nessun record selezionato viene mostrato il log dei record visibili nel form |
for(var R=0; R < db.max_table_rows; R++){ |
if(db.keys[R]){ |
keys.push(db.keys[R]); |
} |
} |
} |
if(keys.length == 0){ |
my_alert('Nessun record da mostrare', 'alert'); |
return |
} |
var list = keys.join(','); |
// costruisco un oggetto 'display' minimale con i soli elementi necessari a lanciare il form |
var display_log = { |
prefix: 'Log_' + this.prefix, |
dataBinding: new DataBinding('Log_' + db.prefix + '_db', 'log', 'Log ' + db.from), |
gotoRecords: function (mode, key, recordset){ |
return this.dataBinding.gotoRecords(mode, key, recordset); |
}, |
openFormDetailByKey: DisplayBinding_openFormDetailByKey |
}; |
display_log.openFormDetailByKey('rewind', null, 'logs', 865, 590, 'Log ' + db.from, { |
form: 'TABLE', |
rows: null, |
disp_find: 1, |
disp_navbar: 1, |
find_area: 'left', |
where: "table_name = '" + db.from.replace(/\//, '.') + "' AND id_record IN (" + list + ")" |
}); |
} |
// metodo getField - ritorna l'identificatore del campo |
// name = nome del campo |
// row = riga del campo; se omessa verrà ritornata la prima riga (riga = 0) |
function DisplayBinding_getField(name, row){ |
if(row == null){ |
row = this.rowFather == null ? 0 : this.rowFather; |
} |
if(row == 'find'){ |
return this.finds[this.find_fields_pos[name]]; |
}else if(row == 'type'){ |
return this.ftypes[this.find_fields_pos[name]]; |
}else if(row == 'header'){ |
return this.headers[this.dataBinding.pos_name[name]]; |
}else{ |
return this.fields[row][this.dataBinding.pos_name[name]]; |
} |
} |
// metodo hiddenColumn - nasconde la colonna del form |
// name = nome del campo |
// hidden = se true nasconde, altrimenti mostra |
function DisplayBinding_hiddenColumn(name, hidden){ |
var display = hidden ? 'none' : ''; |
this.getField(name, 'header').style.display = display; |
for(var Col=0; Col<this.fields.length; Col++){ |
this.getField(name, Col).dispSpan.style.display = display; |
} |
} |
// metodo getFieldByKey - ritorna l'identificatore del campo di una particolare chiave record |
// name = nome del campo |
// key = chiave del record. Se la chiave non è presente nella tabella ritornerà null |
function DisplayBinding_getFieldByKey(name, key){ |
if(key == null){ |
return null; |
} |
var row = this.dataBinding.pos_key[key]; |
if(row == null){ |
return null; |
}else{ |
return this.fields[row][this.dataBinding.pos_name[name]]; |
} |
} |
// metodo readOnly |
// chiama il metodo corrispondente in dataBinding che provvederà a sua volta a richiamare |
// la funzione DisplayBinding_onreadonlyHandler se c'è variazione di stato |
function DisplayBinding_readOnly(set, update){ |
return this.dataBinding.readOnly(set, update); |
} |
// richiamata da dataBinding se c'è variazione di stato lettura/scrittura |
// modifica gli attributi di lettura/scrittura di tutti gli oggetti 'input' associati al recordset |
// se al cambio del set c'è il record corrente in modifica provvede ad aggiornarlo |
function DisplayBinding_onreadonlyHandler(set, update){ |
//DEBUG my_alert('DisplayBinding_readOnly '+this.prefix+'\n set='+set+' update='+update+'\nfields_ro:'+Array2String(this.fields_ro)+'\nfields_ro_update:'+Array2String(this.fields_ro_update)); |
var disp = this.displayBinding; |
// sblocco/blocco i campi del filtro di selezione (se presente) |
if(disp.finds){ |
var set_find = !set; |
for(var I=0; I<disp.finds.length; I++){ |
disp.finds[I].Readonly(set_find); |
disp.ftypes[I].Readonly(set_find); |
} |
} |
// blocco/sblocco dei componenti |
for(var I=0; I<disp.fields.length; I++){ |
var row = disp.fields[I]; |
//GDO my_alert("DataBinding_readOnly("+set+") this.keys="+this.keys[I]); |
var ro = this.keys[I] == null ? this.fields_ro : this.fields_ro_update; |
var set_row = set || (this.keys[I] == null && !this.canInsert) || (this.keys[I] != null && !this.canUpdate); |
//GDO my_alert('DataBinding_readOnly set_row:'+set_row+' ro'+Array2String(ro)); |
for(var J=0; J<row.length; J++){ |
if(row[J]){ |
//GDO my_alert('DataBinding_readOnly I:'+I+'set:'+set+' this.keys='+this.keys[I]+'readonly:'+(set || ro[J] == true)); |
row[J].Readonly(set_row || ro[J] == true); |
} |
} |
} |
disp.cpDeselectHeaders(set); |
disp.uncheckAll(this.max_table_rows); |
disp.cpDeleteCopy(set); |
disp.cpSetAll(); |
// se update è nullo o true e lo stato del recordset era in modifica |
if((update == null || update) && set){ |
// provvedo ad aggiornare i dati nei widget in this.new_data in modo che |
// le modifiche vengano inviate al server |
Form2Array(disp.fields, this.new_data); |
} |
disp.setButtons(); |
// chiamo l'eventuale funzione in risposta all'evento onreadonly |
if(disp.onreadonly){ |
disp.onreadonly(set, update); |
} |
} |
// abilita/disabilita il pulsante (se inizialmente nascosto, anche lo visualizza/nasconde) |
function DisplayBinding_disableButton(button, disable){ |
button.set('disabled', disable); |
if(!disable && button.domNode.style.display == 'none'){ |
button.domNode.style.display = ''; |
button._hidden_when_disabled = true; |
} |
if(disable && button._hidden_when_disabled){ |
button.domNode.style.display = 'none'; |
} |
} |
// regola lo stato dei pulsanti di navigazione |
function DisplayBinding_setButtons(){ |
var db = this.dataBinding; |
// my_alert('DisplayBinding_setButtons '+this.prefix+' canUpdate:'+db.canUpdate); |
var navBar = this.navigationBar; |
var readonly = db.readonly; |
// valuto se tutti i campi sono in sola lettura |
var readOnlyAll = true; |
if(this.fields && this.fields.length){ |
var row = this.fields[0]; // utilizzo la prima riga |
for(var J=0; J<row.length; J++){ |
if(!db.fields_ro[J]){ |
readOnlyAll = false; |
break; |
} |
if(!db.fields_ro_update[J]){ |
readOnlyAll = false; |
break; |
} |
} |
} |
if(readOnlyAll){ |
this.disableButton(navBar.cancelButton, true); |
this.disableButton(navBar.refreshButton, false); |
this.disableButton(navBar.changeButton, true); |
this.disableButton(navBar.saveButton, true); |
}else{ |
this.disableButton(navBar.cancelButton, readonly); |
this.disableButton(navBar.refreshButton, !readonly); |
this.disableButton(navBar.changeButton, !readonly || !db.canUpdate); |
this.disableButton(navBar.saveButton, readonly || !(db.canUpdate || db.canInsert)); |
} |
this.disableButton(navBar.insertButton, !db.canInsert); |
this.disableButton(navBar.deleteButton, !db.canDelete); |
this.disableButton(navBar.printButton, !readonly || !db.canPrint); |
this.disableButton(navBar.xlsButton, !readonly || !db.canXls); |
this.disableButton(navBar.logButton, !db.keys[0] || !readonly || !db.canLog); |
this.disableButton(navBar.dupButton, !db.canInsert); |
// abilito il pulsante di salto se il numero di record disponibili e maggiore dei record visualizzati in ciascuna pagina |
var goto_disabled = (db.max_rows == null || db.max_rows <= db.rows); |
navBar._record.disabled = goto_disabled; |
this.disableButton(navBar.gotoButton, goto_disabled); |
if(navBar.filterButton){ |
// non sempre il form di filtro viene utilizzato |
this.disableButton(navBar.filterButton, !readonly); |
if(navBar.printselButton){ |
this.disableButton(navBar.printselButton, !(readonly && db.canPrintsel)); |
} |
if(navBar.xlsselButton){ |
this.disableButton(navBar.xlsselButton, !(readonly && db.canXls)); |
} |
} |
var dis = db.max_rows == null || db.start >= (db.max_rows - db.max_table_rows); |
this.disableButton(navBar.forwardButton, dis); |
this.disableButton(navBar.upButton, dis); |
dis = db.max_rows == null || db.start < 1; |
this.disableButton(navBar.rewindButton, dis); |
this.disableButton(navBar.downButton, dis); |
var disp = this; |
require(["dijit/registry", "dojo/dom-style"], function(registry, domStyle){ |
// valuto se visualizzare o meno i pulsanti specifici di ciascun record visualizzato |
for(var R=0; R<disp.fields.length; R++){ |
var button = registry.byId(disp.prefix + '_d_' + R); |
if(button){ |
domStyle.set(button.domNode, 'display', db.keys[R] ? 'inline' : 'none'); |
} |
} |
// valuto se visualizzare il pulsante per la duplicazione dei record (solo se è visibile anche il pulsante di inserimento) |
domStyle.set(navBar.dupButton.domNode, 'display', db.canDup && db.dup_fields.length && db.canInsert ? '' : 'none'); |
}); |
} |
// utilizzata per aggiornare lo stato di una riga quando si utilizzano i DIVS |
// div_id ID dell'oggetto DIV da cambiare |
// row riga del recordset da sostituire |
// changed_col colonna del campo che ha determinato il cambiamento |
// |
function DisplayBinding_Divs_onChange(div_id, row, changed_col){ |
var db = this.dataBinding; |
var old = db.new_data[row][changed_col]; |
Form2Row(row, this.fields, db.new_data); |
this.updateTemplateRow(document.getElementById(div_id), row); |
db.new_data[row][changed_col] = old; |
} |
// sostituisce nell'oggetto HTML "div_container" la riga template identificata da "id" |
// sostituendo nel template l'identificativo di riga "id_row" |
// |
function DisplayBinding_updateTemplateRow(Div, id_row){ |
var db = this.dataBinding; |
//my_alert("DisplayBinding_updateTemplateRow("+id_row+") Div.id="+Div.id_row+' Div.type_row='+Div.type_row+'.'); |
if(!Div.type_row){ |
Div.type_row = ''; |
} |
if(!db.type_div){ |
my_alert('ERROR DisplayBinding_updateTemplateRow: ['+this.prefix+'] non ha inizializzato il metodo .type_div\n'+ |
', id_row='+id_row,'txt'); |
return null; |
} |
// il tipo dipende dal valore nel db |
var type = db.type_div(id_row); |
if(Div.type_row != type){ |
//my_alert("UPDATE DisplayBinding_updateTemplateRow("+id_row+") "+Div.type_row+'<>'+type); |
Div.type_row = type; |
this.load_Row(Div, id_row, type); |
} |
Row2Form(id_row, db.data, db.params, this.fields, db.keys, this.labels); |
} |
// sostituisco il codice del template di tipo type con l'identificativo id_row e lo inserisco nel contenitore div_container |
// ed aggiorno lo stato read/write del record |
function DisplayBinding_load_Row(div_container, id_row, type){ |
var db = this.dataBinding; |
if(!type){ |
type = ''; |
} |
// verifico se il template c'è nel buffer |
var template = this.divs[type]; |
if(template == null){ |
my_alert('ERROR DisplayBinding_load_Row: ['+this.prefix+'] non ha precaricato il template di riga "'+type+'"','txt'); |
return null; |
} |
// sostituisco il codice di riga nel template |
template = template.replace(/@@@/g, id_row); |
//DEBUG my_alert('DisplayBinding_Load_Row id_row='+id_row+', str='+template, 'txt'); |
// carico nel form |
hReqMason_innerHTML(div_container, template); |
div_container.type_row = type; |
// aggiorno lo stato readOnly |
// blocco/sblocco flag cancellazione |
// db.checks[id_row].disabled = db.readonly; |
// blocco/sblocco dei componenti |
var row = this.fields[id_row]; |
var ro = db.keys[id_row] == null ? db.fields_ro : db.fields_ro_update; |
for(var J=0; J<row.length; J++){ |
if(row[J]){ |
row[J].Readonly(db.readonly || ro[J] == true); |
} |
} |
} |
// Inizializza gli array .checks, .labels e la matrice .fields con i riferimenti |
// dei widget che compongono la singola riga del form |
function DisplayBinding_bindEditComponentsRow(pos, cols, suff_check, suff_label, suff_field1, suff_field2){ |
var db = this.dataBinding; |
// caso in cui al posto del numero di riga si mette il codice '@@@' da sostituire successivamente |
var check = document.getElementById(this.prefix+suff_check+pos); |
if(check){ |
if(!this.checks){ |
this.checks = []; |
} |
this.checks[pos] = document.getElementById(this.prefix+suff_check+pos); |
} |
this.labels[pos] = document.getElementById(this.prefix+suff_label+pos); |
var row = this.fields[pos] = []; |
for(var col=0; col<cols; col++){ |
var obj = document.getElementById(this.prefix+suff_field1+pos+suff_field2+col); |
row[col] = obj; |
// indico al componente a quale DisplayBinding appartiene |
obj.displayBinding = this; |
obj.dbCol = col; |
obj.dbRow = pos; |
// riferimento al tag <span> che racchiude il widget con la sua descrizione del campo |
var id = this.prefix+suff_field1+pos+suff_field2+col; |
obj.dispSpan = document.getElementById('Span_'+id); |
// riferimento al tag <span> che racchiude la descrizione |
obj.descrSpan = document.getElementById('Descr_'+id); |
obj.getField = function (nome){ |
this.displayBinding.getField(nome, this.dbRow); |
} |
} |
} |
// Inizializza gli array .checks, .labels e la matrice .fields con i riferimenti |
// dei widget che compongono il form |
// I campi "ID" dei widget vengono formati utilizzando nomi composti con le seguenti regole |
// check '<prefix><suff_check>[0..row-1]' |
// label '<prefix><suff_label>[0..row-1]' |
// field '<prefix><suff_field1>[0..row-1]<suff_field2>[0..col-1]' |
// |
function DisplayBinding_bindEditComponents(rows, cols, suff_check, suff_label, suff_field1, suff_field2){ |
// header |
this.headers_select = document.getElementById(this.prefix+'_h_sel'); |
for(var col=0; col<cols; col++){ |
this.headers[col] = document.getElementById(this.prefix+'_h_'+col); |
} |
if(rows == '@@@'){ |
this.bindEditComponentsRow('@@@', cols, suff_check, suff_label, suff_field1, suff_field2); |
}else{ |
for(var j=0;j<rows; j++){ |
this.bindEditComponentsRow(j, cols, suff_check, suff_label, suff_field1, suff_field2); |
} |
} |
} |
// gestione cursore e dati del recordset durante il caricamento |
function DisplayBinding_waitingStatus(wait){ |
var db = this.dataBinding; |
if(wait){ |
this.widgetsContainer.style.cursor='wait'; |
if(this.info){ |
this.info.innerHTML='Caricamento ...'; |
} |
}else{ |
if(this.info){ |
// aggiorno il range di visualizzazione |
if(db.max_table_rows == 1){ |
this.info.innerHTML='Rec. '+(db.start+1)+' / '+db.max_rows |
}else{ |
this.info.innerHTML='Rec. '+(db.start+1)+'-'+(db.start+db.rows)+' / '+db.max_rows |
} |
} |
this.widgetsContainer.style.cursor='auto'; |
} |
} |
// costruisce un oggetto JSON con i parametri di filtro |
// campi = array dei nomi dei campi della selezione |
// values = array agli oggetti nel form che contengono i campi selezionati |
// |
function DisplayBinding_jsonWhere(disp){ |
// l'oggetto displayBinding è fornito come parametro |
// oppure utilizzo this (suppongo che la funzione sia usata come metodo) |
if(disp == null){ |
disp = this; |
} |
var test = false; |
var arr_where = []; |
if(disp.finds && disp.finds.length && disp.find_fields){ |
for(var I=0; I<disp.find_fields.length; I++){ |
var Op = disp.ftypes[I].get_value().toUpperCase(); |
if(Op != ''){ |
var widget = disp.finds[I]; |
var Type = widget.getAttribute('value-type'); |
// default hour non attribuita se campo di tipo timestamp |
var Val = Type == 'timestamp' ? widget.get_value('') : widget.get_value(); |
Val = Val == null ? '' : Val.toString(); |
Val = Val.replace(/\s+$/, ''); |
Val = Val.replace(/^\s+/, ''); |
if(Op == '~*' && !Val.length){ |
my_alert('Con l\'operatore ~* si deve inserire un valore di ricerca non vuoto; ignoro il filtro per ' + disp.find_fields[I],'txt', 400,200); |
}else{ |
if(widget.className.replace(/.*_FIND$/,'') == ''){ |
Val = Val.replace(/:.*$/,''); |
} |
if(Val == ''){ Val = null; } |
arr_where.push([disp.find_fields[I], Op, Val, Type]); |
test = true; |
} |
} |
} |
} |
if(disp.where){ |
arr_where.push(['--where-disp', disp.where]) |
test = true; |
} |
return test ? JSON.stringify(arr_where) : ''; |
} |
// cambio lo stato di visibilità dell'oggetto |
function setDisplay(Obj, visible){ |
var status = visible ? '' : 'none'; |
// evito di assegnare lo stato se uguale, altrimenti in Mozilla si ha l'effetto indesiderato di refresh del form |
if(Obj.style.display != status){ |
Obj.style.display = status |
} |
} |
// richiamata da /frame.comp dopo la creazione degli oggetti nel form |
function DisplayBinding_post_init(){ |
// forzo l'azzeramento dei widget del filtro, altrimenti se si ricarica il form dal browser |
// rimangono visibili dei valori dal form precedente che non corrispondono al reale contenuto |
if(this.finds){ |
for(var C=0; C<this.finds.length; C++){ |
var w = this.finds[C]; w.set_value(w.init_find_value); |
w = this.ftypes[C]; w.set_value(w.init_find_sel); |
} |
} |
// chiamo il metodo anche nelle tabelle figlie |
var children = this.dataBinding.children; |
for(var I = 0; I < children.length; I++){ |
children[I].displayBinding.post_init(); |
} |
if(this.oninit){ |
return this.oninit(); |
} |
return true; |
} |
// richiamata da dataBinding quando sono disponibili i dati riguardanti i campi del dataset |
// chiamata la prima volta che l'oggetto viene utilizzato |
function DisplayBinding_onloadHandler(mode){ |
//my_alert('DisplayBinding_onloadHandler mode='+mode); |
var disp = this.displayBinding; |
// init array posizione campi di filtro |
if(disp.find_fields){ |
disp.find_fields_pos = []; |
for(var col=0; col<disp.find_fields.length; col++){ |
disp.find_fields_pos[disp.find_fields[col]] = col; |
} |
} |
// cambio il nome dei widget con il nome dei campi nel recordset |
for(var R=0; R<disp.fields.length; R++){ |
var row = disp.fields[R]; |
for(var C=0; C<row.length; C++){ |
if(row[C]){ |
row[C].name = this.names[C]; |
} |
} |
} |
// cambio il nome dei widget di ricerca con il nome dei campi nel recordset e pongo il filtro vuoto |
if(disp.finds){ |
for(var C=0; C<disp.finds.length; C++){ |
var wfind = disp.finds[C]; |
var wtype = disp.ftypes[C]; |
wtype.displayBinding = disp; |
wtype.ftypePos = C; |
wtype.name = disp.find_fields[C]; |
wfind.displayBinding = disp; |
wfind.findPos = C; |
wfind.name = disp.find_fields[C]; |
if(!wfind.setFocus && (wfind.type == 'text' || wfind.type == 'textarea')){ |
// attribuisco il metodo se si tratta di un cambo input di tipo testo |
wfind.setFocus = Input_setFocus; |
} |
} |
} |
// metto in evidenza il primo recordset |
this.children.length && disp.selectRowFather(null, true); |
// se il primo caricamento riguarda una operazione di inserimento ... |
if(mode == 'insert'){ |
disp.readOnly(false); |
} |
// evento primo caricamento |
if(disp.onload){ |
disp.onload(mode); |
} |
disp.cpSetAll(); |
} |
// richiamata da dataBinding quando arriva una richiesta di cambio del recordset |
function DisplayBinding_onloadrecordHandler(pos, key, recordset){ |
var disp = this.displayBinding; |
if(!this.readonly){ |
// provvedo ad aggiornare i dati nei widget in .new_data in modo che |
// le modifiche vengano inviate al server |
Form2Array(disp.fields, this.new_data); |
} |
// .onloadrecord dell'applicazione viene chiamata prima |
if(disp.onloadrecord){ |
if(!disp.onloadrecord(pos, key, recordset)){ |
return false; |
} |
} |
if(!this.readonly){ |
// anticipo il calcolo delle differenze, che verranno utilizzate da DisplayBinding_CheckForm |
this._difference = ArrayDiffKeys(this.keys, this.data, this.new_data, true); |
//DEBUG my_alert('DisplayBinding_onloadrecordHandler diff '+Array2String(this._difference, 'null')); |
// il form è in modalità di modifica; verifico se i campi del form sono tutti validi |
if(!DisplayBinding_CheckForm(disp, pos, key, recordset)){ |
// altrimenti annullo la richiesta di aggiornamento |
// Attenzione: se ci sono campi che richiedono un test asincrono (es. chiamata al server) |
// la funzione ritorna false provvisoriamente, ma si occupa di monitorare |
// le risposte dal server, che se positive, rilanceranno la richiesta con i |
// parametri passati 'pos' e 'key' |
// annullo la matrice differenze, che andrà ricalcolata |
this._difference = null; |
return false; |
} |
} |
return true; |
} |
function DisplayBinding_ondeleterecordsHandler(keyList){ |
// chiamo la funzione utente, se definita prima di elaborare la richiesta |
var disp = this.displayBinding; |
if(disp.ondeleterecords){ |
return disp.ondeleterecords(keyList); |
} |
return true; |
} |
// richiamata da dataBinding quando ha inizio una richiesta di dati al server |
function DisplayBinding_onrequestHandler(){ |
// my_alert('DisplayBinding_onrequestHandler'); |
var disp = this.displayBinding; |
// anticipo la scomparsa del form se figlio di un padre con un nuovo record |
disp.widgetsContainer.style.display != 'none' && setDisplay(disp.widgetsContainer, this.father_id != -1); |
// form in stato di attesa |
disp.waitingStatus(true); |
this.storeRowToCopy(); |
// se ho un solo record non occorre azzerare i check di cancellazione |
if(this.max_table_rows > 1 && disp.checks){ |
disp.uncheckAll(this.max_table_rows); |
disp.cpSetAll(); |
} |
// anticipo la messa in attesa delle tabelle figlie |
for(var I = 0; I < this.children.length; I++){ |
var disp_child = this.children[I].displayBinding; |
disp_child && disp_child.waitingStatus(true); |
} |
} |
function DisplayBinding_onprechangeHandler(){ |
var disp = this.displayBinding; |
// comparsa del form se figlio di un padre con record (.onrequest anticipa la scomparsa se record padre nuovo) |
setDisplay(disp.widgetsContainer, this.father_id != -1); |
} |
// richiamata da dataBinding quando è completata una richiesta di dati al server |
function DisplayBinding_onchangeHandler(){ |
var disp = this.displayBinding; |
// my_alert('DisplayBinding_onchangeHandler prefix='+this.prefix+'readonly='+this.readonly+' start=' + this.start + ' rows=' + this.rows + ' max_rows=' + this.max_rows); |
// aggiorno il range del campo di immissione del recordset |
var record = disp.navigationBar._record; |
if(record){ |
record.ValMax = this.max_rows; |
record.maxLength = this.max_rows ? this.max_rows.toString().length : 0; |
} |
// aggiorno lo stato dei pulsanti di navigazione e di editing |
disp.setButtons(); |
// aggiorno lo stato dei widget se obbligatori |
for(var R=0; R<this.data.length; R++){ |
var row = disp.fields[R]; |
for(var C=0; C<row.length; C++){ |
var input = row[C]; |
input.set_status(this.required_fields[C] == true ? 'Required' : ''); |
} |
} |
// solo se è stato definito il metodo "type_div" attivo lo scambio dinamico delle righe |
if(this.type_div){ |
// <div/> che contiene tutte le righe del recordset |
var DIVS = document.getElementById(disp.prefix+'_DIVS'); |
var elenco = DIVS.getElementsByTagName('div'); |
// percorro le righe del recordset e modifico il form |
// in modo da adattarlo |
//DEBUG my_alert(this.data.length+' '+this.fields.length+' '); |
for(var R=0; R<this.data.length; R++){ |
// verifico che la riga corrente sia conforme al template |
disp.updateTemplateRow(this, elenco[R], R); |
} |
}else{ |
// altrimenti aggiorno i dati nel documento |
Array2Form(this.data, this.params, disp.fields, this.keys, disp.labels); |
} |
disp.waitingStatus(false); |
// compilo i campi dell'eventuale record da duplicare |
if(disp.dup){ |
// cerco la prima riga vuota da usare per la copia dei dati |
var R; |
for(R=0; R < this.max_table_rows; R++){ |
if(!this.keys[R]){ |
break; |
} |
} |
if(R >= this.max_table_rows){ |
my_alert('ERRORE: non c\'è neanche una riga disponibile per duplicare i dati','txt'); |
}else{ |
disp.duplicateRecord(disp.dup, R, this.dup_fields); |
// Salvo i riferimenti dei record duplicati |
this.dup_keys[R] = disp.dup.key; |
} |
} |
// aggiorno l'evidenza del record padre |
this.children.length && disp.selectRowFather(null, true); |
// chiamo l'eventuale funzione in risposta all'evento onchange |
if(disp.onchange){ |
disp.onchange(); |
} |
disp.dup = null; |
this.retrieveRowToCopy(); |
} |
function DisplayBinding_duplicateRecord(Original, R, Mode){ |
// riga da modificare |
var copy = this.fields[R]; |
for(var C = 0; C < copy.length; C++){ |
this.duplicateField(Original, copy, C, Mode[C]); |
} |
} |
function DisplayBinding_duplicateField(Original, Copy, C, Mode){ |
if(!Original){ |
return; |
} |
if(Copy[C] != null){ |
// valuto cosa copiare |
var value = Original.value[C] == null ? '' : Original.value[C].toString(); |
if(Mode == 'D' || (Mode == 'd' && value.length > 0) || |
Mode == 'C' || (Mode == 'c' && value.length > 0)){ |
Copy[C].set_value(value, Original.param[C]); |
// duplico anche le condizioni di errore e di stato del widget |
Copy[C].widgetStatus = Original.widgetStatus[C]; |
Copy[C].widgetError = Original.widgetError[C]; |
Copy[C].set_status(); |
} |
} |
return; |
} |
// richiamata da dataBinding quando si presenta un errore |
function DisplayBinding_onerrorHandler(err, str){ |
var disp = this.displayBinding; |
disp.waitingStatus(false); |
disp.setButtons(); |
if(err == 'TIMEOUT'){ |
my_alert('Timeout ricezione dati [' + this.prefix + ']\n il server potrebbe non essere raggiungibile.', 'txt'); |
}else{ |
my_alert(err + ': ' + str, 'txt', 400,200); |
} |
} |
// cancella i record selezionati (se multiriga) o il record corrente (singolo record) |
function DisplayBinding_deleteSelected(){ |
var db = this.dataBinding; |
// valutazione della lista delle chiavi da stampare |
var keyList = this.selectedKeys(); |
if(!keyList.length){ |
my_alert('Nessun record selezionato per la cancellazione','txt'); |
return; |
} |
if(!confirm(this.confirmDelMessage + ': ' + keyList.join(',') + '.')){ |
return; |
} |
if(!db.deleteRecords(keyList)){ |
my_alert('Errore inaspettato: cancellazione annullata!','txt'); |
} |
} |
// recupera i dati dal server applicando il filtro corrente |
function DisplayBinding_loadRecords(mode, key){ |
// richiamo i dati dal server |
var db = this.dataBinding; |
%#//DEBUG my_alert('DisplayBinding_loadRecords '+mode+' key:'+key + ' start:'+db.start); |
// aggiorno il filtro corrente |
db.json_where = this.jsonWhere(); |
// aggiorno ordinamento corrente |
db.orderby = (this.sqlOrderBy) ? this.sqlOrderBy() : ''; |
// dataBinding.max_rows è null al primo caricamento |
if(db.start != null && this.onrequest){ |
// evento non lanciato al primo caricamento (db.start==null) |
this.onrequest(mode, key); |
} |
return db.loadRecords(mode, key); |
} |
%#// lancia un metodo remoto sul server definito come CALL_REMOTE_<function> aggiornando le condizioni di filtro ed ordinamento |
function DisplayBinding_callRemote(remote_func, params, mode, win_params){ |
var db = this.dataBinding; |
// aggiorno il filtro corrente |
var json_where = this.jsonWhere(); |
if(!db.json_where != !json_where && !confirm('Hai cambiato la selezione senza aggiornare i dati visualizzati.\nConfermi l\'elaborazione dei dati con i filtri modificati?')){ |
return false; |
} |
db.json_where = json_where; |
// aggiorno ordinamento corrente |
db.orderby = (this.sqlOrderBy) ? this.sqlOrderBy() : ''; |
return db.callRemote(remote_func, params, mode, win_params); |
} |
function DisplayBinding_newRecord(){ |
return { |
key: null, |
value: [], |
param: [], |
widgetStatus: [], |
widgetError: [] |
}; |
} |
function DisplayBinding_copyRecord(Original, R, Copy){ |
Form2Vect(Original, Copy.value, Copy.param); |
for(var C = 0; C < Original.length; C++){ |
Copy.widgetStatus[C] = Original[C].widgetStatus; |
Copy.widgetError[C] = Original[C].widgetError; |
} |
return; |
} |
// spostamenti nel recordset corrente |
function DisplayBinding_gotoRecords(mode, key, recordset){ |
%#//DEBUG my_alert('DisplayBinding_gotoRecords "'+mode+'","'+key+'"'); |
if(mode.length == 0){ |
my_alert('Indicare la posizione del record nella selezione corrente a cui si vuole puntare','txt'); |
return; |
} |
var db = this.dataBinding; |
if(mode == 'dup'){ |
this.dup = this.newRecord(); |
// copio i dati presenti della riga indicata nel display |
if(db.max_table_rows == 1){ |
// se in numero delle righe è 1 devo salvare il record da copiare |
// che potrò rimpiazzare solo dopo aver richiamato un record nuovo |
// (salvando eventualmente quello corrente, se modificato) |
this.dup.key = db.keys[0]; |
this.copyRecord(this.fields[0], 0, this.dup); |
}else if(this.checks){ |
// lista delle righe selezionate |
var lista = this.uncheckAll(db.max_table_rows); |
this.cpDeleteCopy(true); |
this.cpSetAll(); |
var riga_dup; // riga da duplicare |
if(!lista.length){ |
// individuo il record non vuoto più in basso nella lista |
var R; |
var Data = []; |
Form2Array(this.fields, Data); |
RICERCA:for(R=Data.length-1; R>=0; R--){ |
var Row = Data[R]; |
var C; |
for(C=0; C<Row.length; C++){ |
if(Row[C]){ |
riga_dup = R; |
break RICERCA; |
} |
} |
} |
if(riga_dup == null){ |
my_alert('Nulla da duplicare; le righe sono tutte vuote','txt'); |
return false; |
} |
}else if(lista.length > 1){ |
my_alert('E\' possibile duplicare un solo record per volta','txt'); |
return false; |
}else{ |
riga_dup = lista[0]; |
} |
this.dup.key = db.keys[riga_dup]; |
this.copyRecord(this.fields[riga_dup], riga_dup, this.dup); |
// se c'è nel form almeno una riga ancora non utilizzata |
// posso duplicare il record senza chiamare il server |
var unusedRow = DisplayBinding_unusedRow(this, db); |
if(unusedRow.found){ |
// c'è una riga vuota che utilizzo per duplicare il record |
this.duplicateRecord(this.dup, unusedRow.R, db.dup_fields); |
db.dup_keys[unusedRow.R] = this.dup.key ? this.dup.key : db.dup_keys[riga_dup]; |
this.dup = null; |
this.readOnly(false); |
return true; |
} |
// duplico la riga dovo aver salvato le eventuali righe correnti modificate |
} |
mode = 'insert'; |
}else{ |
this.dup = null; |
} |
if(db.start != null && this.onrequest){ |
// evento non lanciato al primo caricamento (db.start==null) |
this.onrequest(mode, key); |
} |
return db.gotoRecords(mode, key, recordset); |
} |
function DisplayBinding_unusedRow(Disp, Db){ |
var data = []; |
Form2Array(Disp.fields, data); |
var diff = ArrayDiffKeys(Db.keys, Db.data, data, true); |
//DEBUG my_alert('length=' + diff.length+ '' +KeyArray2String(Db.keys, diff, 'null', true, true),'txt'); |
for(var R = 0; R < diff.length; R++){ |
if(Db.keys[R] == null){ |
var row = diff[R]; |
for(var C = 0; C < row.length; C++){ |
if(row[C]){ |
break; |
} |
} |
if(C == row.length){ |
break; |
} |
} |
} |
var unusedRow = { |
R: R, |
found: (R < diff.length) |
}; |
return unusedRow; |
} |
// Annulla le modifiche in corso |
function DisplayBinding_cancelUpdate(key, pos){ |
this.dataBinding.cancelUpdate(key, pos); |
} |
// Dialog Edit |
DisplayBinding_Edit = null; |
// Apre un form con maggiore dettaglio del record indicato (row: riga del record) |
function DisplayBinding_openFormDetailByKey(mode, find_key, from, dimX, dimY, title, form_params){ |
dimX = dimX || 800; |
dimY = dimY || 600; |
var display = this; |
this.modeDetail = mode; |
require(["dojo/io-query", "dojox/widget/DialogSimple", "dojo/dom-construct", "dojo/dom-style"], |
function(ioQuery, DialogSimple, domConstruct, domStyle){ |
if(!DisplayBinding_Edit){ |
DisplayBinding_Edit = new DialogSimple({ |
title: title, |
executeScripts: true, |
renderStyles: true, |
scriptHasHooks: true, |
parseOnLoad: true, |
cleanContent: true, |
closable: false, |
ioArgs: { |
headers: { |
'MasonSql-body': '1' |
}, |
timeout: <% $r->dir_config('GetFormTimeout') %> |
}, |
onLoad: function(){ |
domStyle.set(DisplayBinding_Edit.containerNode, 'height', (DisplayBinding_Edit.dimY - DisplayBinding_Edit.titleBar.offsetHeight - 6) + 'px'); |
} |
}); |
DisplayBinding_Edit.editSingle_Handler = function(save){ |
if(save){ |
var display = masonSql.disp[this.disp_prefix]; // vedi definizione del nome in /frame.html |
display.onchange = function () { |
// aggiorno i record correnti e chiudo il popup |
window.setTimeout("DisplayBinding_Edit.closeDetail(true);", 10); |
}; |
display.gotoRecords('save'); |
}else{ |
DisplayBinding_Edit.closeDetail(); |
} |
}; |
DisplayBinding_Edit.closeDetail = function(update){ |
var disp = this.displayBinding; |
update && disp.gotoRecords('update', null, disp.modeDetail == 'insert'); |
this.hide(); |
if(disp.onclosedetail){ |
disp.onclosedetail(update); |
} |
disp = null; |
}; |
DisplayBinding_Edit.containerNode.style.padding = '2px 2px'; |
domConstruct.place('<% q{ |
<span style="float:right;"> |
<button tabindex="-1" onclick="DisplayBinding_Edit.editSingle_Handler(true);">Salva e chiudi</button> |
<button tabindex="-1" onclick="DisplayBinding_Edit.editSingle_Handler()">Annulla</button> |
</span> |
} |js%>', DisplayBinding_Edit.titleBar, 2 /* seconda posizione */); |
}else{ |
DisplayBinding_Edit.set('content', ''); |
} |
DisplayBinding_Edit.displayBinding = display; |
DisplayBinding_Edit.dimY = dimY; |
DisplayBinding_Edit.set('style', 'width:' + dimX + 'px; height:' + dimY + 'px;'); |
DisplayBinding_Edit.show(); |
var d = new Date(); |
// valori 'di default' da passare alla chiamata |
var url_params = { |
U: d.getTime() + '' + Math.floor(1000 * Math.random()), |
prefix: 'Detail', |
from: from, |
rows: 1, |
disp_navbar: '', |
disp_insert: '', |
disp_delete: '', |
disp_xls: '', |
disp_log: '', |
disp_dup: '', |
find_area: 'none', |
disp_refresh: '', |
disp_print: '', |
mode: display.modeDetail, // forward/insert |
find_key: find_key, |
father_id: display.dataBinding.father_id, |
father_id_update: display.dataBinding.father_id_update |
}; |
// parametri aggiuntivi |
for(var k in form_params){ |
url_params[k] = form_params[k]; |
} |
DisplayBinding_Edit.disp_prefix = 'Disp_' + url_params.prefix + '_' + url_params.from.replace(/\//g, '_'); |
DisplayBinding_Edit.set('href', '/frame.html?' + ioQuery.objectToQuery(url_params)).then( |
function(){ |
console.debug('downloaded href', DisplayBinding_Edit); |
masonSql.ready(); |
}, |
function(err){ |
tab.set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+' id:'+DisplayBinding_Edit.id+' timeout:'+<% $r->dir_config('GetFormTimeout') %>+"</span>"); |
console.error('ERROR href',err , DisplayBinding_Edit); |
} |
); |
}); |
} |
// Apre un form con maggiore dettaglio del record indicato (row: riga del record) |
function DisplayBinding_openFormDetail(mode, row, from, dimX, dimY, title, params){ |
return this.openFormDetailByKey(mode, this.dataBinding.keys[row], from, dimX, dimY, title, params); |
} |
// in risposta al click di una riga di TABLE o DIVS indica quale sia il padre corrente da mostrare nei recordset figli |
function DisplayBinding_selectRowFather(row, no_update){ |
if(row == null){ |
row = this.rowFather == null ? 0 : this.rowFather; |
} |
var db = this.dataBinding; |
var row_div = dojo.byId(this.id + '_div_' + row); |
if(!row_div){ |
// row_div se non esiste, non gestisco il cambio dei figli (ad esempio il template 'FORM' non lo prevede) |
return; |
} |
var old_rowFather = this.rowFather; |
this.rowFather = null; |
// tolgo evidenza dell'eventuale riga selezionata in precedenza |
if(old_rowFather != null){ |
dojo.removeClass(dojo.byId(this.id + '_div_' + old_rowFather), 'selectRowFather'); |
} |
// se il record padre non esiste oppure il recordset non ha figli non devo evidenziare la riga selezionata |
if(db.children.length){ |
if(db.fathers_id && db.fathers_id[row]){ |
// evidenzio la riga selezionata |
dojo.addClass(row_div, 'selectRowFather'); |
this.rowFather = row; |
} |
// aggiorno i figli se chiamata da onclick delle righe da parte dell'utente |
if(!no_update && db.keys[row] && this.rowFather != old_rowFather){ |
db.updateChildren(row); |
}else if(!db.keys[row] || (no_update && !db.fathers_id)){ |
db.rowFather = null; |
// le tabelle figlie vanno nascoste |
for(var I = 0; I < db.children.length; I++){ |
var disp_child = db.children[I].displayBinding; |
if(disp_child){ |
disp_child.waitingStatus(false); |
setDisplay(disp_child.widgetsContainer, false); |
} |
} |
} |
} |
} |
function DisplayBinding_cpDeleteCopy(ReadOnly){ |
if(ReadOnly){ |
this.dataBinding.cp_key = null; |
this.cp_row = null; |
this.cp_record = null; |
} |
return; |
} |
// Check multiple rows if the shift key has been pressed. Otherwise keep track |
// of last checked row and proceed with normal updating of the |
// checked/unchecked row. |
function DisplayBinding_cpSetMultipleRows(Evt, R){ |
var db = this.dataBinding; |
if(!this.checks || !this.checks[R]){ |
return; |
} |
var cp = !db.readonly && this.cp_enabled; |
var checkedR = this.checks[R].checked; |
var prev = this.cp_previous; |
if(Evt.shiftKey && prev !== null && prev != R){ |
var from; |
var to; |
if(prev < R){ |
from = prev; |
to = R; |
}else{ |
from = R; |
to = prev; |
} |
for(var row = from; row <= to; row++){ |
var checksRow = this.checks[row]; |
if(checksRow && (!checksRow.checked || row == R)){ |
checksRow.checked = true; |
cp && this.cpSetRow(row, true); |
} |
} |
}else{ |
if(checkedR){ |
this.cp_previous = R; |
}else{ |
this.cp_previous = null; |
} |
cp && this.cpSetRow(R, checkedR); |
} |
cp && this.cpSetSelect(false); |
return; |
} |
// Determine whether the row is unchecked, is to be copied or is to be pasted. |
// Manage row to be copied and its content. Set row classes accordingly. |
function DisplayBinding_cpSetRow(R, Checked){ |
var db = this.dataBinding; |
if(db.readonly || !this.cp_enabled || !this.fields || !this.fields[R]){ |
return; |
} |
var row = this.fields[R]; |
if(Checked){ |
if(this.cp_row === null && db.cp_key === null){ |
this.cp_record = this.newRecord(); |
this.copyRecord(row, R, this.cp_record); |
this.cp_row = R; |
this.cpSetRowClasses(row, Checked, 'WidgetToCopy'); |
// cp_row must not be overwritten with Shift selection |
}else if(this.cp_row != R){ |
this.duplicateRecord(this.cp_record, R, this.cp_modes); |
this.cpSetRowClasses(row, Checked, 'WidgetPasted'); |
}else{ |
this.cpSetRowClasses(row, Checked, 'WidgetToCopy'); |
} |
}else{ |
this.cpUndoRecord(db.data[R], row); |
if(this.cp_row == R){ |
this.cpDeleteCopy(true); |
this.cpSetSelect(false); |
} |
this.cpSetRowClasses(row, Checked, ''); |
} |
return; |
} |
function DisplayBinding_cpSetRowClasses(Row, Checked, WidgetClass){ |
var h = this.headers; |
if(h){ |
for(var C = 0; C < Row.length; C++){ |
var field = Row[C]; |
var header = h[C]; |
var isSelected = header.selectable && header.selected && Checked; |
this.cpSetFieldClass(field, WidgetClass, isSelected); |
} |
} |
return; |
} |
// Set Copy-Paste properties and classes, of the field specified with 'Pos'. |
// If the field is not checked revert its value. Set the field class according |
// to the determined status. |
function DisplayBinding_cpSetColumn(Header, Pos){ |
var db = this.dataBinding; |
if(db.readonly || !this.cp_enabled || !this.checks){ |
return; |
} |
for(var R = 0; R < db.max_table_rows; R++){ |
if(this.checks[R]){ |
var isSelected = Header.selectable && Header.selected && this.checks[R].checked; |
var record = this.fields[R]; |
var field = record[Pos]; |
if(db.data[R]){ |
//console.log('undo from db.data[R][Pos]=', db.data[R][Pos]); |
Scalar2Form(db.data[R][Pos], null, field); |
} |
if(this.cp_row === R){ |
this.cpSetFieldClass(field, 'WidgetToCopy', isSelected); |
}else{ |
this.cpSetFieldClass(field, 'WidgetPasted', isSelected); |
} |
} |
} |
return; |
} |
// Field Copy-Paste classes: |
// 'WidgetToCopy' indicates a row to be copied; |
// 'WidgetPasted' indicates a row in which the copied row is pasted; |
// '' absence of both classes indicates unchanged row. |
function DisplayBinding_cpSetFieldClass(Field, WidgetClass, IsSelected){ |
require(["dojo/dom-class", "dojo/domReady!"], function(domClass){ |
if(IsSelected){ |
domClass.replace(Field.dispSpan, WidgetClass, 'WidgetToCopy WidgetPasted'); |
}else{ |
domClass.remove(Field.dispSpan, 'WidgetToCopy WidgetPasted'); |
} |
}); |
return; |
} |
// Used for deactivating Copy-Paste properties and classes of the table headers |
// during transition to read-only state. |
function DisplayBinding_cpDeselectHeaders(ReadOnly){ |
if(ReadOnly){ |
var h = this.headers; |
for(var C = 0; C < h.length; C++){ |
if(h && h[C]){ |
h[C].selectable = false; |
h[C].selected = false; |
this.cpSetHeaderClass(h[C], C, true); |
} |
} |
this.cpSetSelect(true); |
} |
return; |
} |
function DisplayBinding_cpRefreshRow(Row){ |
if(this.checks[Row]){ |
this.checks[Row].checked = true; |
this.cpSetRow(Row, true); |
} |
return; |
} |
// Called from onclick event on 'sel.' header. |
// Invert 'selected' status of all columns that can be selected for Copy-Paste. |
// Do not modify field classes of the displayed records except if the row is to be copied. |
// Also update cp_modes, 'sel.' classes and the classes of the rest of the table headers |
function DisplayBinding_cpInvertAllHeaders(){ |
var db = this.dataBinding; |
if(db.readonly){ |
return; |
} |
var h = this.headers; |
for(var C = 0; C < this.headers.length; C++){ |
h[C].selected = h[C].selected ? false : true; |
} |
this.cpSetModes(h, db.cp_fields); |
this.cpUncheckPasted(db.max_table_rows); |
this.cpRefreshRow(this.cp_row); |
this.cpSetSelect(false); |
for(var C = 0; C < this.headers.length; C++){ |
this.cpSetHeaderClass(h[C], C, false); |
} |
return; |
} |
// Called from onclick event on table header field. |
// 1. Invert 'selected' status of the header field. |
// 2. Uncheck all rows except the row to be copied. |
// 3. Update classess of the row to be copied. |
// 4. Update classes of the 'sel.' header and the rest of the table headers. |
function DisplayBinding_cpInvertHeader(Pos){ |
var db = this.dataBinding; |
if(db.readonly){ |
return; |
} |
var h = this.headers; |
h[Pos].selected = h[Pos].selected ? false : true; |
this.cpSetModes(h, db.cp_fields); |
this.cpUncheckPasted(db.max_table_rows); |
this.cpRefreshRow(this.cp_row); |
this.cpSetSelect(false); |
this.cpSetHeaderClass(h[Pos], Pos, false); |
return; |
} |
// Header classes: |
// 'ColSelected' set when column Copy-Paste is active; |
// 'ColSelectable' set when its possible to select column for Copy-Paste operation; |
// 'CopyPasteDisabled' set when at least one column is selectable; |
// '' absence of all three classes indicates the column is in read-only state. |
function DisplayBinding_cpSetHeaderClass(Header, Pos, ReadOnly){ |
var cp_fields = this.dataBinding.cp_fields; |
require(["dojo/dom-class", "dojo/domReady!"], function(domClass){ |
if(Header){ |
if(Header.selectable){ |
if(Header.selected){ |
domClass.replace(Header, 'ColSelected', 'ColSelectable CopyPasteDisabled'); |
}else{ |
domClass.replace(Header, 'ColSelectable', 'ColSelected CopyPasteDisabled'); |
} |
}else{ |
if(ReadOnly){ |
domClass.remove(Header, 'CopyPasteDisabled ColSelectable ColSelected'); |
}else if(cp_fields.length > 0){ |
domClass.replace(Header, 'CopyPasteDisabled', 'ColSelectable ColSelected'); |
} |
} |
} |
}); |
return; |
} |
// 1. Search if any of the columns can be selected for Copy-Paste and if any of |
// the columns is selected for copy paste by user. The column property |
// 'selectable' is obtained during parsing of FIELDS_COPY_PASTE method. The |
// column property 'selected' indicates whether the column is also selected for |
// Copy-Paste. |
// 2.a Use found information to determine whether Copy-Paste is active ('cp_enabled' property). |
// 2.b When the Copy-Paste is (re)activated uncheck all rows and delete row to be copied. |
// 3.a Set 'sel.' header class to 'CopyPasteResetInvert' only when at least one |
// column can be selected and Copy-Paste is active and the row to be copied has been |
// checked by user. |
// 3.b Set 'sel.' header class to 'CopyPasteDisabled' if not in read-only mode and |
// at least one column is selectable. |
function DisplayBinding_cpSetSelect(ReadOnly){ |
var obj = this; |
var h = this.headers; |
var db = this.dataBinding; |
var sel = this.headers_select; |
var cp_fields = this.dataBinding.cp_fields; |
if(!sel || !h){ |
return; |
} |
require(["dojo/dom-class", "dojo/_base/array", "dojo/domReady!"], function(domClass, array){ |
var existsSelectable = false; |
var existsSelected = false; |
array.forEach(h, function(header){ |
if(header.selectable){ |
existsSelectable = true; |
if(header.selected){ |
existsSelected = true; |
} |
} |
}); |
if(existsSelected){ |
if(!obj.cp_enabled){ |
obj.cp_enabled = true; |
obj.uncheckAll(db.max_table_rows); |
obj.cpDeleteCopy(true); |
} |
}else{ |
obj.cp_enabled = false; |
} |
//console.log('cp_enabled=', obj.cp_enabled); |
if(existsSelectable && (obj.cp_row !== null || db.cp_key !== null) && obj.cp_enabled){ |
domClass.replace(sel, 'CopyPasteResetInvert', 'CopyPasteDisabled'); |
}else if(ReadOnly){ |
domClass.remove(sel, 'CopyPasteResetInvert CopyPasteDisabled'); |
}else if(cp_fields.length > 0){ |
domClass.replace(sel, 'CopyPasteDisabled', 'CopyPasteResetInvert'); |
} |
}); |
return; |
} |
function DisplayBinding_cpUncheckPasted(MaxTableRows){ |
if(!this.checks){ |
return; |
} |
for(var R = 0; R < MaxTableRows; R++){ |
var checksR = this.checks[R]; |
if(this.cp_row != R && checksR && checksR.checked){ |
checksR.checked = false; |
} |
} |
return; |
} |
function DisplayBinding_uncheckAll(MaxTableRows){ |
var lista = []; |
if(!this.checks){ |
return lista; |
} |
for(var R = 0; R < MaxTableRows; R++){ |
var checksR = this.checks[R]; |
var row = this.fields[R]; |
if(checksR && checksR.checked){ |
checksR.checked = false; |
this.cpSetRowClasses(row, false, ''); |
lista.push(R); |
} |
} |
this.cp_previous = null; |
return lista; |
} |
function DisplayBinding_cpSetModes(H, CpFields){ |
this.cp_modes = []; |
for(var C = 0; C < H.length; C++){ |
var cpField = CpFields[C]; |
if(cpField && (cpField == 'C' || cpField == 'c')){ |
H[C].selectable = true; |
if(H[C].selected){ |
this.cp_modes[C] = cpField; |
}else{ |
this.cp_modes[C] = ''; |
} |
}else if(H[C]){ |
H[C].selectable = false; |
this.cp_modes[C] = ''; |
} |
} |
return; |
} |
function DisplayBinding_cpSetAll(){ |
var db = this.dataBinding; |
if(db.readonly){ |
return; |
} |
var h = this.headers; |
this.cpSetModes(h, db.cp_fields); |
this.cpSetSelect(false); |
for(var C = 0; C < h.length; C++){ |
var cpField = db.cp_fields[C]; |
this.cpSetHeaderClass(h[C], C, false); |
if(h[C] && cpField && (cpField == 'C' || cpField == 'c')){ |
this.cpSetColumn(h[C], C); |
} |
} |
return; |
} |
// abilita/disabilita i pulsanti di navigazione |
function NavigationBar_setButtons(set, list){ |
var re_button = /Button$/; |
if(list == null){ |
// disabilito tutti i pulsanti di controllo |
for(name in this){ |
var elem = this[name]; |
if(elem != null && re_button.test(name)){ |
elem.disabled = !set; |
} |
} |
}else{ |
// disabilito i pulsanti di controllo il cui nome è elencato nella lista |
for(I in list){ |
var name = list[I]; |
if(!re.test(name)){ |
// se il nome non termina con 'Button' lo aggiungo |
name += Button; |
} |
var elem = this[name]; |
if(elem != null){ |
elem.disabled = !set; |
} |
} |
} |
} |
// copia una singola riga dell'Array nel form |
function Row2Form(Row, Data, Params, formP, key, Lbl){ |
if(key && Lbl && Lbl[Row]){ |
var rec = key[Row]; |
Lbl[Row].innerHTML = key.length == 1 ? '(' + (key[Row] == null ? '...' : key[Row]) + ')' : key[Row]; |
} |
Vect2Form(Data[Row], Params[Row], formP[Row]); |
} |
function DisplayBinding_cpUndoRecord(BackedUpVals, Form){ |
var h = this.headers; |
if(BackedUpVals && h){ |
for(var C = 0; C < Form.length; C++){ |
var header = h[C]; |
if(header.selectable && header.selected){ |
Scalar2Form(BackedUpVals[C], null, Form[C]); |
} |
} |
} |
return; |
} |
function Scalar2Form(Value, Parameter, Field){ |
if(Field != null){ |
if(Value == null){ |
Field.set_value('', Parameter); |
}else{ |
Field.set_value(Value, Parameter); |
} |
Field.widgetError = false; |
Field.set_status(); |
} |
return; |
} |
function Vect2Form(Vals, Params, Form){ |
for(var C = 0; C < Form.length; C++){ |
Scalar2Form(Vals[C], Params ? Params[C] : null, Form[C]); |
} |
} |
function Array2Form(Data, Params, formP, key, Lbl){ |
// my_alert('Array2Form('+key+')\nformp='+Data); |
// riempio i campi |
for(var R=0; R<Data.length; R++){ |
Row2Form(R, Data, Params, formP, key, Lbl); |
} |
} |
// riempio i campi della riga R dell'Array Data con i campi del form formP |
function Form2Row(Row, formP, arrayVal){ |
if(!arrayVal[Row]){ |
arrayVal[Row] = []; |
} |
Form2Vect(formP[Row], arrayVal[Row]); |
} |
function Form2Vect(P, Val, Par){ |
for(var C=0; C<P.length; C++){ |
var input = P[C]; |
if(input != null){ |
Val[C] = input.get_value(); |
if(Par){ |
Par[C] = input.get_param(); |
} |
//alert("value="+Val[C]+" "+input.id+":"+input.type+" check:"+input.checked+" cal="+input.value); |
} |
} |
} |
// riempio i campi dell'Array con i valori inseriti nel form |
function Form2Array(formP, Data){ |
for(var R=0; R<formP.length; R++){ |
Form2Row(R, formP, Data); |
} |
} |
// verifico se tutti i campi contengono valori validi |
// Se ci sono campi che richiedono un test asincrono (es. chiamata al server) |
// la funzione ritorna false provvisoriamente, ma si occupa di monitorare |
// le risposte dal server, che se tutte positive, rilanceranno la richiesta con i |
// parametri passati 'pos' e 'key' |
function DisplayBinding_CheckForm(displayBinding, pos, key, recordset, loop){ |
var check = displayBinding.CheckForm_check; |
if(check && check.widgets.length == 0){ |
// chiamata arrivata in quanto ho richiamato databinding dopo il test concluso positivo |
displayBinding.CheckForm_check = null; |
// segnalo OK |
return true; |
} |
var formP = displayBinding.fields; |
var db = displayBinding.dataBinding; |
if(loop){ |
// verifico lo stato dei campi che hanno segnalato una verifica asincrona |
// loop all'indietro in quanto tolgo dalla lista i widget che hanno terminato il test |
for(var C=check.widgets.length-1; C>=0; C--){ |
var input = check.widgets[C]; |
// test effettuato senza che venga gestito dal singolo campo la visualizzazione del messaggio di errore |
var str_err = input.remote_test(); |
if(typeof(str_err) == 'string'){ |
if(str_err){ |
var descRiga = formP.length == 1 ? '' : 'Riga:' + (input.dbRow + 1) + ' '; |
check.errors += descRiga + input.Descr + ': ' + str_err + '\n'; |
} |
// tolgo il widget dalla lista |
check.widgets.splice(C, 1); |
} |
} |
}else{ |
check = displayBinding.CheckForm_check = { |
widgets: [], |
errors: '' |
}; |
// test validità dei campi locale e campo non nullo |
for(var R=0; R<formP.length; R++){ |
var P = formP[R]; |
var row_difference = db._difference[R]; |
// valuto se la riga è stata modificata |
var row_is_changed = false; |
var descRiga = formP.length == 1 ? '' : 'Riga:' + (R+1) + ' '; |
for(var C=0; C<P.length; C++){ |
if(row_difference[C] != null){ |
row_is_changed = true; |
// la verifica la eseguo solo se il campo è stato variato dall'utente |
var input = P[C]; |
// test validità locale |
if(input && input.local_test){ |
var str_err = input.local_test(); |
if(str_err){ |
check.errors += descRiga + input.Descr + ': ' + str_err + '\n'; |
} |
} |
} |
} |
if(row_is_changed){ |
// test campi non nulli |
if(db.keys[R] != null){ |
// record modificato: la verifica la eseguo solo se il campo è stato variato dall'utente |
for(var C=0; C<P.length; C++){ |
if(db.required_fields[C] == true && row_difference[C] != null && row_difference[C].length == 0){ |
var input = P[C]; |
input.widgetError = 'Error'; |
input.set_status(); |
check.errors += descRiga + input.Descr + ': campo obbligatorio\n'; |
} |
} |
}else{ |
// nuovo record: la verifica la eseguo su tutti i campi |
for(var C=0; C<P.length; C++){ |
var input = P[C]; |
if(db.required_fields[C] == true && input.get_value().length == 0){ |
input.widgetError = 'Error'; |
input.set_status(); |
check.errors += descRiga + input.Descr + ': campo obbligatorio\n'; |
} |
} |
} |
} |
} |
if(check.errors){ |
// se ci sono errori nei campi a livello locale non effettuo il rest remoto |
my_alert('Controllo locale dei campi negativo:\n' + check.errors, 'auto'); |
displayBinding.CheckForm_check = null; |
return false; |
} |
// test validità dei campi remota: la verifica la eseguo solo se il campo è stato variato dall'utente |
for(var R=0; R<formP.length; R++){ |
var row_difference = db._difference[R]; |
var P = formP[R]; |
var descRiga = formP.length == 1 ? '' : 'Riga:' + (R+1) + ' '; |
for(var C=0; C<P.length; C++){ |
if(row_difference[C] != null){ |
var input = P[C]; |
if(input && input.remote_test){ |
var str_err = input.remote_test(); |
if(typeof(str_err) == 'boolean' && !str_err){ |
input.widgetError = 'Wait'; |
input.set_status(); |
// aggiungo il widget per il controllo successivo |
check.widgets.push(input); |
}else if(typeof(str_err) == 'string' && str_err){ |
input.widgetError = 'Error'; |
input.set_status(); |
check.errors += descRiga + input.Descr + ': ' + str_err + '\n'; |
} |
} |
} |
} |
} |
} |
if(check.widgets.length){ |
// c'è almeno un widget che sta effettuando un controllo remoto |
window.setTimeout('DisplayBinding_CheckForm('+displayBinding.prefix+', "'+pos+'", '+ |
(key == null ? 'null' : key)+', '+(recordset == null ? 'null' : recordset)+',true);', 100); |
return false; |
}else if(check.errors){ |
my_alert('Controllo remoto dei campi negativo:\n' + check.errors, 'txt'); |
displayBinding.CheckForm_check = null; |
return false; |
} |
if(loop){ |
// chiamate di controllo successive alla prima |
if(pos){ |
// se tutti i widget sono OK lancio il comando che avevo sospeso |
db.gotoRecords(pos, key, recordset); |
} |
}else{ |
displayBinding.CheckForm_check = null; |
return true; |
} |
} |
// ritorna il widget adiacente in funzione della direzione indicata |
function DisplayBinding_getWidget(input, event){ |
if(input.dbRow != null){ |
// widget appartenente a un form di tipo DisplayBinding |
var fields = input.displayBinding.fields; |
var formKeysMovement = input.displayBinding.formKeysMovement; |
// alert(input.id +': ' + event.keyCode + ' R:' + input.dbRow + ' C:' + input.dbCol); |
if((event.keyCode == 9 && !event.shiftKey) || (event.keyCode == 39 && formKeysMovement.search('ARROWS') != -1)){ // TAB o Right arrow |
return input.dbCol == fields[0].length - 1 ? (input.dbRow == fields.length - 1 ? fields[0][0] : fields[input.dbRow + 1][0]) : fields[input.dbRow][input.dbCol + 1]; |
}else if((event.keyCode == 9 && event.shiftKey) || (event.keyCode == 37 && formKeysMovement.search('ARROWS') != -1)){ // Shift-TAB o Left arrow |
return input.dbCol == 0 ? (input.dbRow == 0 ? fields[fields.length - 1][fields[0].length -1] : fields[input.dbRow - 1][fields[0].length -1]) : fields[input.dbRow][input.dbCol - 1]; |
}else if(event.keyCode == 38 && formKeysMovement.search('ARROWS') != -1){ // Up arrow |
return input.dbRow == 0 ? (input.dbCol == 0 ? fields[fields.length - 1][fields[0].length -1] : fields[fields.length - 1][input.dbCol - 1]) : fields[input.dbRow - 1][input.dbCol]; |
}else if((event.keyCode == 13 && !event.shiftKey && formKeysMovement.search('ENTER') != -1) || (event.keyCode == 40 && formKeysMovement.search('ARROWS') != -1)){ // CR o Down arrow |
return input.dbRow == fields.length - 1 ? (input.dbCol == fields[0].length -1 ? fields[0][0] : fields[0][input.dbCol + 1]) : fields[input.dbRow + 1][input.dbCol]; |
}else{ |
return null; |
} |
}else if(input.findPos != null){ |
// widget appartenente ad un form di filtro finds |
var fields = input.displayBinding.finds; |
if(event.keyCode == 39 || (event.keyCode == 9 && !event.shiftKey)){ // Right arrow o TAB |
return input.findPos == fields.length - 1 ? input.displayBinding.ftypes[0] : input.displayBinding.ftypes[input.findPos + 1]; |
}else if(event.keyCode == 37 || event.keyCode == 9 && event.shiftKey){ // Left arrow o Shift-TAB |
return input.displayBinding.ftypes[input.findPos]; |
}else if((event.keyCode == 13 && !event.shiftKey) || event.keyCode == 40){ // CR o Down arrow |
return input.findPos == fields.length - 1 ? input.displayBinding.ftypes[0] : fields[input.findPos + 1]; |
}else if(event.keyCode == 38){ // Up arrow |
return input.findPos == 0 ? input.displayBinding.ftypes[fields.length - 1] : fields[input.findPos - 1]; |
}else{ |
return null; |
} |
}else if(input.ftypePos != null){ |
// widget appartenente ad un form di filtro ftypes |
var fields = input.displayBinding.ftypes; |
if(event.keyCode == 39 || (event.keyCode == 9 && !event.shiftKey)){ // Right arrow o TAB |
return input.displayBinding.finds[input.ftypePos]; |
}else if(event.keyCode == 37 || event.keyCode == 9 && event.shiftKey){ // Left arrow o Shift-TAB |
return input.ftypePos == 0 ? input.displayBinding.finds[fields.length - 1] : input.displayBinding.finds[input.ftypePos - 1]; |
}else if((event.keyCode == 13 && !event.shiftKey) || event.keyCode == 40){ // CR o Down arrow |
return input.ftypePos == fields.length - 1 ? input.displayBinding.finds[0] : fields[input.ftypePos + 1]; |
}else if(event.keyCode == 38){ // Up arrow |
return input.ftypePos == 0 ? input.displayBinding.finds[fields.length - 1] : fields[input.ftypePos - 1]; |
}else{ |
return null; |
} |
}else{ |
return null; |
} |
} |
// Forza il campo nel form e nel dataset (no aggiornamento nel server) |
function DisplayBinding_forceValueField(value, field_name, row){ |
if(arguments.length == 2){ |
row = 0 |
} |
this.getField(field_name, row).set_value(value); |
var db = this.dataBinding; |
db.data[row][db.pos_name[field_name]] = value; |
db.new_data[row][db.pos_name[field_name]] = value; |
} |
%# END displaybinding.js |
/tags/2.0/htdocs/lib/dbms_library.comp |
---|
0,0 → 1,5731 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010-2016 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
in $method va indicato il formato dei dati restituiti |
'select' codice javascript per popolare <select/> |
'array' codice javascript di inizializzazione di array 2 dimensioni |
'pdf' report di stampa in formato pdf (richiede che venga creato il report in formato .rep (http://reportman.sourceforge.net/) |
'xml' documento xml |
'txt' formato tabulare con \t come delimitatore di campo; nome dei campi sulla prima riga |
'xls' formato Excel (XLS) |
'html' tabella html (per debug) |
'array' tabella in formato Array jscript |
'field_check' richiesta di verifica validità di un widget |
'call_remote' chiamata di funzione remota |
. . . . . |
</%doc> |
<%args> |
$method => $Session{ARGS}{method} |
@P => () |
</%args> |
%##################################################### html |
<%method html>\ |
<% $r->dir_config('HtmlDocType') %> |
<html> |
<head> |
<meta http-equiv="Content-Type" content="test/html; charset=utf-8"> |
<title><& SELF:DESCRIPTION &></title> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
<style type='text/css'> |
body { |
color:#000000; background:#FFFFFF; |
margin:0px; padding:0px; |
} |
</style> |
<meta name="AUTHOR" content="Brugnara ing. Guido - gdo@leader.it"> |
<meta name="COPYRIGHT" content="Leader.IT di Guido Brugnara; Strada della Pozzata, 41 - Villazzano; 38123 TRENTO (ITALY); info@leader.it"> |
</head> |
<body><p align="center"> |
<H3><& SELF:DESCRIPTION &></H3> |
<table border="1"> |
<%perl> |
my $KEY = $m->scomp('SELF:KEY'); |
my $base_comp = $m->base_comp; |
$sth = SqlSelect('SELECT', 'SELECT_FIELDS', \%ARGS); |
# i nomi dei campi risultato della query |
my $query_names = $sth->{NAME}; |
</%perl> |
<hr>\ |
% foreach my $key ( @$query_names ){ |
<td><b><%$key%></b></td>\ |
% } |
</hr> |
<%perl> |
while(my $row = $sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
if($row){ |
</%perl> |
<tr> |
<%perl> |
my $id = $row->{$query_names->[0]}; |
for(my $i=0; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, undef) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 1); |
$val =~ s/\n/<br>/gm; |
$val || ($val = ' '); |
</%perl> |
<td><%$val%></td> |
% } |
</tr> |
% } |
% } |
</table></p></body></html> |
</%method> |
%##################################################### metodi utilizzati da /archive |
%## Vedi widget /input/Files.comp |
%## |
<%method archive_check>\ |
<%args> |
$Base |
$rec_id |
$permission |
</%args> |
<%perl> |
my $perm = Permission($ARGS{PermissionGroup}); |
if(!$rec_id){ |
$m->out('{}'); |
$m->abort; |
} |
$rec_id =~ m/[^\w]/s && return {error => "Field rec_id malformed"}; |
# verifico esistenza del record |
if($ARGS{RecordsetCache} && !RecordsetCache($ARGS{name}, 'check_key', $rec_id)){ |
# recordset non attivo oppure record assente nel recordset ... |
$ARGS{json_where} = to_json [[$m->scomp('SELF:KEY'), '=', $rec_id]]; |
# chiamo SqlSelectWhere con father_id=-2 per disabilitare il controllo (tanto uso una query con la PK) |
my $sth = ExecQuery('numrec', 'SELF:NUMREC', WHERE => SqlSelectWhere(\%ARGS, -2)); |
if(!$sth->fetchrow_arrayref->[0]){ |
return {error => "Not found or no $permission in archive of $Base record $rec_id"}; |
} |
} |
my $dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
if(! -d $dir){ |
make_path $dir || return {error => "create dir for $Base:$rec_id $!"}; |
} |
return undef; |
</%perl> |
</%method> |
<%method archive_get>\ |
<%args> |
$Base |
$name |
$path |
$rec_id |
$mode_download |
</%args> |
<%perl> |
$r->headers_out->{'Cache-Control'} = 'max-age=0'; |
# $r->content_type($mime); |
#DEBUG print STDERR Dumper(\%ARGS); |
if(my $err = $m->comp('SELF:archive_check', %ARGS, permission => 'Select')){ |
$Session{StatusCode} = 404; |
die $err->{error}."\n"; |
} |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
if($path =~ m/\.\./s){ |
$Session{StatusCode} = 404; |
die "path malformed\n"; |
} |
my $Files_Trash_dir = $r->dir_config('Files_Trash_dir'); |
if(!$Session{Group_Admins} && ($path eq '/.'.$Files_Trash_dir || $path =~ m|^/\.$Files_Trash_dir/|)){ |
die "cestino visibile solo agli amministratori\n"; |
} |
my $files; |
my $finds = File::Find::Rule->file; |
if($path =~ /[\*\?]/){ |
# esistono wildcard nel percorso |
($files,$path) = fileparse($path); |
if($path eq './'){ |
$path = ''; |
} |
$finds->name($files); |
} |
my $file = "$base_dir/$path"; |
$path = '/'.$path; |
my $obj_name = $path; |
$obj_name =~ s|^.*/||; |
if(! -e $file){ |
$Session{StatusCode} = 404; |
die "File $Base:$rec_id:$path not exists"; |
} |
if($mode_download && $mode_download ne 'json' && $mode_download ne 'csv' ){ |
my $filetype; |
my $filename = $file; |
$filename =~ s/^.*\///; |
$r->headers_out->{'Content-transfer-encodig'} = 'binary'; |
if($mode_download eq 'save'){ |
$filetype = 'application/octet-stream; charset=binary'; |
$r->headers_out->{'Content-disposition'} = qq{attachment; filename="$filename"}; |
}elsif($mode_download eq 'download'){ |
$r->headers_out->{'Content-disposition'} = qq{inline; filename="$filename"}; |
my $mime_file = $file; |
if(-l $file){ |
run ['/bin/readlink', '-f', $file], '>', \$mime_file; |
chomp $mime_file; |
} |
if(!run ['/usr/bin/file', '--mime', '--brief', $mime_file], '>', \$filetype){ |
$Session{StatusCode} = 500; |
die "run: $!"; |
} |
chomp $filetype; |
}elsif($mode_download eq 'zipSave'){ |
$filetype = 'application/zip; charset=binary'; |
if(!$filename){ |
$filename = "$name.$rec_id"; |
} |
$r->headers_out->{'Content-disposition'} = qq{attachment; filename="$filename.zip"}; |
# creazione dell'archivio coi i file presenti nella cartella $file |
my $zip = Archive::Zip->new(); |
my($zip_fh, $zip_file) = tempfile( |
DIR => $r->dir_config('TmpDir'), |
SUFFIX => '.zip', |
UNLINK => 0 |
); |
$finds->start($file); |
while(my $path_file = $finds->match){ |
my $rel_file = $path_file; |
# tolgo la radice del percorso |
$rel_file = substr($rel_file, length($file)); |
$rel_file =~ s/^\///; |
if($rel_file && $rel_file !~ m/^\./ && $rel_file !~ m/\/\./ && -r $path_file){ |
# non allego i file/dir nascosti, la radice e i file non leggibili |
Encode::_utf8_on($rel_file); |
$zip->addFileOrDirectory($path_file, $rel_file) || die "Failed Zip to add $rel_file\n"; |
} |
} |
die "Copy files to zip error\n" unless $zip->writeToFileHandle($zip_fh) == 0; |
close $zip_fh; |
$file = $zip_file; |
}elsif($mode_download eq 'tgzSave'){ |
$filetype = 'application/x-tar; charset=binary'; |
if(!$filename){ |
$filename = "$name.$rec_id"; |
} |
$r->headers_out->{'Content-disposition'} = qq{attachment; filename="$filename.tgz"}; |
# creazione dell'archivio coi i file presenti nella cartella $file |
my $tmp_dir = $r->dir_config('TmpDir'); |
my $tar = Archive::Tar::Wrapper->new( tmpdir => $tmp_dir ); |
my($tar_fh, $tar_file) = tempfile( |
DIR => $tmp_dir, |
SUFFIX => '.tgz', |
UNLINK => 0 |
); |
close $tar_fh; |
my $count_file; |
$finds->start($file); |
while(my $path_file = $finds->match){ |
my $rel_file = $path_file; |
# tolgo la radice del percorso |
$rel_file = substr($rel_file, length($file)); |
$rel_file =~ s/^\///; |
if($rel_file && $rel_file !~ m/^\./ && $rel_file !~ m/\/\./ && -r $path_file){ |
# non allego i file/dir nascosti, la radice e i file non leggibili |
Encode::_utf8_on($rel_file); |
$tar->add($rel_file, $path_file) || die "Failed Tar to add $rel_file: $!\n"; |
$count_file++; |
} |
} |
if($count_file){ |
$tar->write($tar_file, 9) || die "Copy files to tar error: $!\n"; |
} |
$file = $tar_file; |
}elsif($mode_download eq 'tgzArc'){ |
$filetype = 'application/x-tar; charset=binary'; |
if(!$filename){ |
$filename = "$name.$rec_id"; |
} |
if($m->APACHE2){ |
$r->headers_out->{'Content-disposition'} = qq{attachment; filename="$filename.tgz"}; |
}else{ |
$r->header_out('Content-disposition' => qq{attachment; filename="$filename.tgz"}); |
} |
# creazione dell'archivio coi i file presenti nella cartella $file |
my $tmp_dir = $r->dir_config('TmpDir'); |
my($tar_fh, $tar_file) = tempfile( |
DIR => $tmp_dir, |
SUFFIX => '.tgz', |
UNLINK => 0 |
); |
close $tar_fh; |
chdir $file || die "Error to change dir $file: $!\n"; |
system '/bin/tar', 'czf', $tar_file, '-C', $file, './' || die "Error to create tar archive from $file: $!\n"; |
$file = $tar_file; |
} |
#DEBUG print STDERR "DOWNLOAD [$mode_download: $filetype] $Base:$rec_id $path\n"; |
$r->content_type($filetype); |
sysopen FILE, $file, 'O_RDONLY' || die "sysopen $file: $!"; |
my $buffer; |
# leggo il file generato a blocchi di 64Kbyte |
while(my $numchar = sysread FILE, $buffer, 2^16){ |
if(undef $numchar){ |
$Session{StatusCode} = 500; |
die "sysread $file: $!"; |
}; |
$m->clear_buffer; |
$m->out($buffer); |
$m->flush_buffer; |
} |
if($mode_download eq 'zipSave' || $mode_download eq 'zgzSave'){ |
unlink $file |
} |
return 200; |
}else{ |
# oggetto per preparare la lista |
my %list_obj; |
if(-d $file){ |
#DEBUG print STDERR "RETURN DIR $Base:$rec_id $path\n"; |
my @children; |
if($path eq '/.'.$Files_Trash_dir){ |
%list_obj = ('name' => $r->dir_config('Files_Trash_name'), 'id' => $path, type => 'trash'); |
}else{ |
%list_obj = ('name' => $obj_name || '...', 'id' => $path ); |
} |
my $dir; |
opendir($dir, $file) || die "can't opendir $Base:$rec_id $path: $!"; |
if($path eq '/'){ |
$path = ''; |
} |
# usato per ritardare l'inserimento del cestino nella lista |
my $trash_p_obj; |
while(my $filename = readdir $dir){ |
utf8::is_utf8($filename) || utf8::decode($filename); |
# salto se puntatori alla dir corrente, dir padre o dir/file nascosti |
my %file_obj; |
if($Session{Group_Admins} && "$path/$filename" eq '/.'.$Files_Trash_dir){ |
%file_obj = ( 'name' => $r->dir_config('Files_Trash_name'), 'id' => "$path/$filename", type => 'trash'); |
}else{ |
next if($filename =~ m/^\./); |
%file_obj = ( 'name' => $filename, 'id' => "$path/$filename"); |
} |
if(-d "$file/$filename"){ |
# verifico se la cartella contiene dei file |
my $empty = 1; |
my $dir; |
opendir($dir, "$file/$filename") || die "can't opendir $Base:$rec_id $file/$filename: $!"; |
while(my $filename = readdir $dir){ |
next if($filename =~ m/^\./); |
$empty = 0; |
closedir $dir; |
last; |
} |
$file_obj{children} = $empty ? [] : 1; |
} |
if($file_obj{type} eq 'trash'){ |
# ritardo l'inserimento del cestino nella lista |
$trash_p_obj = \%file_obj; |
}else{ |
push @children, \%file_obj; |
} |
} |
closedir $dir; |
# ordinamento con le cartelle in testa |
my @sorted = sort { $b->{'children'} cmp $a->{'children'} || uc $a->{'name'} cmp uc $b->{'name'} } @children; |
# piazzo il cestino in fondo alla lista |
$trash_p_obj && push @sorted, $trash_p_obj; |
$list_obj{children} = \@sorted; |
#DEBUG print STDERR Dumper(\%list_obj), objToJson(\%list_obj); |
}else{ |
#DEBUG print STDERR "RETURN FILE $Base:$rec_id $path\n"; |
%list_obj = ( 'name' => $obj_name, 'id' => $path ); |
} |
if($mode_download eq 'csv'){ |
# lista file/cartelle nel formato svs (separatore \t) |
$r->content_type('text/plain; charset=utf-8'); |
$m->print("id\ttype\tname\n"); |
my $type = $list_obj{type} || $list_obj{children} ? 'dir' : 'file'; |
$m->print("$list_obj{id}\t$type\t$list_obj{name}\n"); |
if(defined $list_obj{children}){ |
foreach my $child (@{$list_obj{children}}){ |
my $type = $child->{type} || $child->{children} ? 'dir' : 'file'; |
$m->print("$child->{id}\t$type\t$child->{name}\n"); |
} |
} |
}else{ |
$r->content_type('application/json; charset=utf-8'); |
$m->print(objToJson(\%list_obj)); |
} |
} |
</%perl> |
</%method> |
<%perl> |
sub move_file_archive($$$$){ |
my($Base, $rec_id, $file_old, $file_new) = @_; |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
# verifico che non venga usato '/..' nel percorso dei file |
$file_old =~ m|\/\.\.| && return {error => "file_old malformed"}; |
$file_new =~ m|\/\.\.| && return {error => "file_new malformed"}; |
$base_dir =~ s|/$||; |
$file_old =~ s|^/||; |
$file_new =~ s|^/||; |
# verifico che il nome non contenga caratteri proibiti, altrimenti li converto in '_' |
$file_new =~ s/[\*<>#\?\\'"]/_/g; |
-e "$base_dir/$file_old" || return {name => $file_old, error => "file/dir non esistente"}; |
my $Files_Trash_dir = $r->dir_config('Files_Trash_dir'); |
$file_new eq $Files_Trash_dir && return {name => $file_new, error => "nome riservato al cestino"}; |
if($file_new =~ m/^\.$Files_Trash_dir\//){ |
if(-e "$base_dir/$file_new"){ |
# aggiungo un suffisso per non sovrascrivere il file/dir presente nel cestino |
my $suff = 1; |
while(-e "$base_dir/$file_new.$suff"){ |
$suff++; |
} |
$file_new .= ".$suff"; |
} |
}else{ |
-d "$base_dir/$file_new" && return {name => $file_new, error => "esiste già una cartella con quel nome"}; |
} |
-e "$base_dir/$file_new" && return {name => $file_new, error => "esiste già un file/link con quel nome"}; |
# separo il nome dal percorso della cartella (es '/my/dir/file' => '/my/dir/' 'file' -- 'file' => '' 'file') |
my $name_old = $file_old; $name_old =~ s|^.*/||; |
my $dir_old = $file_old; $dir_old =~ s|[^/]*$||; |
my $name_new = $file_new; $name_new =~ s|^.*/||; |
my $dir_new = $file_new; $dir_new =~ s|[^/]*$||; |
if($dir_new =~ m/\.$Files_Trash_dir\// && !-d "$base_dir/$dir_new"){ |
make_path "$base_dir/$dir_new" || return {name => $file_new, error => "creando cartella $dir_new"}; |
} |
-d "$base_dir/$dir_new" || return {name => $dir_new, error => "la cartella non esiste"}; |
-e "$base_dir/$dir_new.$name_new" && return {name => $file_new, error => "sono presenti delle versioni del file"}; |
my $op = $dir_old eq $dir_new ? "rinominando $name_old in $name_new" : "spostando $file_old in $file_new"; |
if(-l "$base_dir/$file_old"){ |
# sposto/rinomino la cartella associata al file |
-d "$base_dir/$dir_old.$name_old" || return {name => $file_old, error => "manca la cartella delle versioni"}; |
# recupero il numero della versione |
my $version_name = readlink("$base_dir/$file_old") || return {name => $file_old, error => "lettura del link: $!"}; |
$version_name =~ s|.*/||; |
my(undef, $version, undef, undef) = split /\./, $version_name, 4; |
move("$base_dir/$dir_old.$name_old", "$base_dir/$dir_new.$name_new") || return {error => "$op: $!"}; |
if($name_old eq $name_new){ |
# sposto il link |
move("$base_dir/$file_old", "$base_dir/$file_new") || return {error => "$op: $!"}; |
}else{ |
# ricreo il link |
if(!symlink ".$name_new/$version_name", "$base_dir/$file_new"){ |
# rimetto history al posto di prima |
my $err = "nel creare il link al file $file_new della versione $version: $!"; |
move("$base_dir/$dir_new.$name_new", "$base_dir/$dir_old.$name_old") |
|| return {name => $file_old, error => "$err e ripristinando la cartella delle versioni: $!"}; |
return {error => $err}; |
} |
if(!unlink("$base_dir/$file_old")){ |
DB_log('update', $rec_id, { 'ARC.' => "$file_new:$version" }, { 'ARC.' => "$file_old:$version" }); |
return {name => $file_old, info => "nel cancellare il link alla versione: $!"}; |
} |
} |
DB_log('update', $rec_id, { 'ARC.' => "$file_new:$version"}, { 'ARC.' => "$file_old:$version"}); |
}else{ |
if(-d "$base_dir/$file_old"){ |
$file_old .= '/'; |
$file_new .= '/'; |
} |
# sposto il file/dir |
move("$base_dir/$file_old", "$base_dir/$file_new") || return {error => "$op: $!"}; |
# se ho spostato/cambiato nome a una cartella nel Log si comprende che era una cartella se i nomi terminano con '/' |
DB_log('update', $rec_id, { 'ARC.' => $file_new}, { 'ARC.' => $file_old}); |
} |
return undef; |
} |
</%perl> |
<%method archive_put>\ |
<%args> |
$Base |
$path |
$rec_id |
$obj_id |
$obj_new_id |
$obj_name |
$obj_new_name |
</%args> |
<%perl> |
#DEBUG print STDERR Dumper(\%ARGS); |
# modifica del nome o creazione di una cartella? |
my $mess = $m->comp('SELF:archive_check', %ARGS, permission => 'Update'); |
if(!$mess){ |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
my $test = '/'.$path; |
$test =~ m|\/\.\.| && return {error => "path malformed"}; |
$test = '/'.$obj_name; |
$test =~ m|\/\.\.| && return {error => "obj_id malformed"}; |
$test = '/'.$obj_new_name; |
$test =~ m|\/\.\.| && return {error => "obj_new_name malformed"}; |
$obj_id =~ m|\/\.\.| && return {error => "obj_id malformed"}; |
$obj_new_id =~ m|\/\.\.| && return {error => "obj_new_id malformed"}; |
my $file = "$base_dir/$path"; |
my $filename = $obj_id; |
$filename =~ s|^.*/||; |
if($obj_new_name){ |
### CREATE DIR |
# 'obj_new_name' => 'NUOVA', |
# 'table' => 'apparecchiature', |
# 'schema' => 'impianti', |
# 'rec_id' => '31173', |
# 'obj_new_id' => undef, |
# 'obj_id' => '/test/NUOVA', |
# 'path' => 'test/NUOVA', |
# 'obj_name' => undef, |
if("$path" eq '.'.$r->dir_config('Files_Trash_dir')){ |
$mess = { name => $obj_new_id, error => "Nome riservato al cestino"}; |
}elsif(-d "$base_dir/$path"){ |
$mess = { name => $path, error => "Esiste già una cartella con quel nome"}; |
}elsif(-e $base_dir.'/'.$path){ |
$mess = { name => $path, error => "Esiste già un file/link con quel nome"}; |
}elsif(!make_path $base_dir.'/'.$path){ |
$mess = { name => $path, error => "Errore nella creazione della cartella: $!"}; |
} |
$path .= '/'; |
DB_log('update', $rec_id, { 'ARC.' => $path }, { 'ARC.' => undef }); |
}else{ |
if($obj_new_id){ |
### MOVE |
# 'obj_new_name' => undef, |
# 'table' => 'apparecchiature', |
# 'schema' => 'impianti', |
# 'rec_id' => '31173', |
# 'obj_new_id' => '/test/readme.html', |
# 'obj_id' => '/readme.html', |
# 'path' => 'readme.html', |
# 'obj_name' => 'readme.html', |
# muovi |
if($path eq '.'.$r->dir_config('Files_Trash_dir')){ |
$mess = { name => $path, error => "Il cestino non si può spostare"}; |
}else{ |
$mess = move_file_archive $Base, $rec_id, $obj_id, $obj_new_id; |
} |
}else{ |
# RENAME |
#'rec_id' => '31173', |
#'obj_new_id' => undef, |
#'obj_id' => '/oldname', |
#'path' => 'oldname', |
#'obj_name' => 'NEWNAME', |
#'table' => 'apparecchiature', |
#'schema' => 'impianti', |
#'obj_new_name' => undef, |
if($path eq '.'.$r->dir_config('Files_Trash_dir')){ |
$mess = { name => $path, error => "Il cestino non si può rinominare"}; |
}else{ |
# rinomino il file e il relativo archivio storico |
my $obj_new_id = $obj_id; |
$obj_new_id =~ s|[^/]*$||; |
$obj_new_id .= $obj_name; |
$mess = move_file_archive $Base, $rec_id, $obj_id, $obj_new_id; |
} |
} |
} |
} |
$m->out($mess ? JSON::objToJson($mess) : '{}'); |
$Session{Dbh}->commit; |
</%perl> |
</%method> |
<%method archive_delete>\ |
<%args> |
$Base |
$rec_id |
$path |
</%args> |
<%perl> |
#DEBUG print STDERR Dumper(\%ARGS); |
my $mess = $m->comp('SELF:archive_check', %ARGS, permission => 'Delete'); |
if(!$mess){ |
my $test = '/'.$path; |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
my $file = "$base_dir/$path"; |
my $Files_Trash_dir = $r->dir_config('Files_Trash_dir'); |
if($test =~ m|\/\.\.|){ |
$mess = {error => "path malformed"} |
}elsif(! -e $file){ |
$mess = { name => $path, info => "file o cartella inesistente"}; |
}elsif(-d $file){ |
if($file !~ m/\/$/){ |
$file .= '/'; |
} |
if($path =~ m/^\.$Files_Trash_dir/){ |
# svuoto il cestino |
if(remove_tree $file){ |
$path .= '/'; |
DB_log 'update', $rec_id, { 'ARC.' => undef }, { 'ARC.' => $path }; |
}else{ |
$mess = { name => $path, error => "cancellazione cartella: $!"}; |
} |
}else{ |
$mess = move_file_archive $Base, $rec_id, $path, ".$Files_Trash_dir/$path"; |
} |
}else{ |
if($path =~ m/^\.$Files_Trash_dir/){ |
# svuoto il cestino |
if(unlink $file){ |
DB_log 'update', $rec_id, { 'ARC.' => undef }, { 'ARC.' => $path }; |
# cancello anche la cartella delle versioni (se presente) |
my $name = $file; $name =~ s|^.*/||; |
my $subdir = $file; $subdir =~ s|[^/]*$||; |
if(-d "$subdir/.$name"){ |
if(!remove_tree "$subdir/.$name"){ |
$mess = { name => $path, error => "cancellazione della cartella delle versioni: $!"}; |
} |
} |
}else{ |
$mess = { name => $path, error => "cancellazione file: $!"}; |
} |
}else{ |
$mess = move_file_archive $Base, $rec_id, $path, ".$Files_Trash_dir/$path"; |
} |
} |
} |
#DEBUG print STDERR "DELETED $Base:$rec_id $path\n"; |
$m->out($mess ? JSON::objToJson($mess) : '{}'); |
$Session{Dbh}->commit; |
</%perl> |
</%method> |
<%method archive_history> |
<%args> |
$Base |
$rec_id |
$obj_id |
$new_ver => undef |
$edit => undef |
</%args> |
<%perl> |
$Session{StatusCode} = 200; |
if(my $err = $m->comp('SELF:archive_check', %ARGS, permission => $edit ? 'Update' : 'Select')){ |
die $err->{error}."\n"; |
} |
$obj_id =~ m|\/\.\.|s && die "obj_id malformed\n"; |
$new_ver =~ m/^\d*$/ || die "new_ver malformed\n"; |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id"; |
my $file = "$base_dir$obj_id"; |
-e $file || die "File/dir $obj_id inesistente\n"; |
if(-l $file){ |
my $name = $obj_id; $name =~ s|^.*/||; |
my $dir = $obj_id; $dir =~ s|[^/]*$||; |
my $v_dir = "$base_dir$dir/.$name"; |
if(!-d $v_dir){ |
die "Cartella delle versioni non presente\n"; |
} |
# versione corrente |
my $v_name_curr = readlink $file; |
$v_name_curr =~ s/.*\///; |
my(undef, $ver_curr, undef, undef) = split /\./, $v_name_curr, 4; |
opendir (DIR, $v_dir) || die "opendir: $!"; |
$m->out('<table class="Files_table_history"><tr><th>Ver.</th><th>Data</th><th>Utente</th></tr>'); |
my %entries; |
my %users; |
while(my $v_name = readdir(DIR)){ |
next if($v_name =~ /^\./); |
my($date, $ver, $userid, $hash) = split /\./, $v_name, 4; |
if($new_ver && $ver eq $new_ver){ |
# cambio la versione corrente |
unlink $file || die "unlink: $!"; |
symlink ".$name/$v_name", $file || die "link ver. $new_ver: $!"; |
$ver_curr = $new_ver; |
} |
$entries{$ver} = $v_name; |
if($userid){ |
$users{$userid} = "id: $userid"; |
} |
} |
# recupero i dati anagrafici degli utenti |
my $elenco_id = join(',', keys(%users)); |
if($elenco_id){ |
my $sth_users = ExecQuery("Get users", undef, qq{ |
select id, coalesce(nome || ' ', '') || coalesce(cognome, '') as nominativo |
from public.anagrafiche |
where id in ($elenco_id); |
}); |
while(my $user = $sth_users->fetchrow_hashref){ |
$users{$user->{id}} = $user->{nominativo}; |
} |
} |
# tabella versioni da postare all'utente |
for my $version (sort {$b <=> $a} keys %entries){ |
my($date, $ver, $userid, $hash) = split /\./, $entries{$version}, 4; |
$date =~ s/_/ /; |
my $curr = ($new_ver || $ver_curr ) eq $ver; |
my $curr_class = $curr ? ' class="Files_current"' : ''; |
my $button = !$edit || $curr ? '' : qq{<button class="Files_button" onClick="Input_Files_TreeNodeObj.set_new_version('$ver');">Set</button>}; |
$m->out("<tr".($curr_class)."><td>$ver $button</td><td>$date</td> <td>$users{$userid}</td></tr>"); |
} |
closedir(DIR); |
if($new_ver && $ver_curr ne $new_ver){ |
$m->out(qq{<tr><td colspan="3" class="Files_alert">ATTENZIONE:<br> Versione richiesta ($new_ver) inesistente</td></tr>}); |
} |
$m->out("</table>"); |
}elsif(-f $file){ |
$m->out("<pre>Non è presente l'archivio delle versioni</pre>"); |
}elsif(-d $file){ |
###DIR |
}else{ |
die "unexpected typeof $obj_id\n"; |
} |
</%perl> |
</%method> |
<%method archive_post> |
% $Session{StatusCode} = 500; |
% die "POST is not provided"; |
</%method> |
%##################################################### metodi utilizzati da /dbms |
%# genera il tag che contiene il tracciato XML |
<%method XML_PATH>\ |
<%args> |
$close => 0 |
$start => undef |
$rows => undef |
$max_rows => undef |
</%args> |
% if($close){ |
</<%$Session{ARGS}{xml_path}%>>\ |
% }else{ |
% my $sth = $Session{Dbh}->prepare('select now();'); |
% $sth->execute; |
% my $timestamp = $sth->fetchrow_arrayref->[0]; |
<<%$Session{ARGS}{xml_path}%> method="<%$Session{ARGS}{method}%>" user="<%$Session{Login}%>" timestamp="<%$timestamp%>"\ |
% if(defined $start){ |
start="<%$start%>" rows="<%$rows%>" max_rows="<%$max_rows%>"\ |
% } |
>\ |
% } |
</%method> |
%##################################################### keyname |
<%method keyname>\ |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
# se abilitato ... |
my $permission = Permission($ARGS{PermissionGroup}); |
my $keyname = $m->scomp('SELF:KEY'); |
if($keyname =~ m/\.(.*)$/){ |
$keyname = $1; |
} |
</%perl> |
<<%$ARGS{name}%> keyname="<%$keyname|xml%>" /> |
<& SELF:XML_PATH, close => 1 &> |
</%method> |
%##################################################### info |
<%method info>\ |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
# se abilitato ... |
my $permission = Permission($ARGS{PermissionGroup}); |
my $keyname = $m->scomp('SELF:KEY'); |
if($keyname =~ m/\.(.*)$/){ |
$keyname = $1; |
} |
</%perl> |
<<%$ARGS{name}%> keyname="<%$keyname|xml%>"\ |
% # elenco dei permessi |
% foreach my $perm (keys %{$permission}){ |
<%lc $perm%>="<%$permission->{$perm}%>"\ |
% } |
% # tabella padre |
father_name="<& SELF:FATHER_NAME &>"\ |
% # campo che collega la tabella padre |
father_id_name="<& SELF:FATHER_ID_NAME &>"\ |
% # nome del campo chiave del padre |
father_key_name="<& SELF:FATHER_KEY_NAME &>"\ |
> |
<%perl> |
my @names = &Method2Array('FIELDS'); |
unshift @names, $keyname; |
foreach my $name (@names){ |
$name =~ s/^.*\.//; |
my $info = $m->comp('SELF:INFO', NAME => $name); |
delete $info->{FIND_DESCR}; |
delete $info->{PRIMARY_KEY} if(!$info->{PRIMARY_KEY}); |
delete $info->{HIDDEN}; |
delete $info->{FIND}; |
delete $info->{NOTNULL} if(!$info->{NOTNULL}); |
delete $info->{DECIMAL} if(!$info->{DECIMAL}); |
$info->{DESCR} =~ s|[\\/]$||; |
$info->{TYPE} =~ s| varying||; |
</%perl> |
<field\ |
% foreach my $key (keys %{$info}){ |
<%lc $key%>="<%$info->{$key}|xml%>"\ |
% } |
/> |
% } |
<%perl> |
my %entity_children = method2hash('ENTITY_CHILDREN'); |
foreach my $key (keys %entity_children){ |
my($table, $keyname) = split /\s*\:\s*/, $entity_children{$key}, 2; |
</%perl> |
<child field="<%$key|xml%>" table="<%$table|xml%>" key="<%$keyname|xml%>" /> |
<%perl> |
} |
my %entity_relations = method2hash('ENTITY_RELATIONS'); |
foreach my $key (keys %entity_relations){ |
my($table, $keyname) = split /\s*\:\s*/, $entity_relations{$key}, 2; |
</%perl> |
<relation field="<%$key|xml%>" table="<%$table|xml%>"<%$keyname ? ' key="'.$keyname.'"' : ''%> /> |
% } |
</<%$ARGS{name}%>> |
<& SELF:XML_PATH, close => 1 &> |
</%method> |
%##################################################### newkey |
<%method newkey>\ |
<%perl> |
my $rest = $ARGS{envelope_response} eq 'rest'; |
if($rest){ |
# The status code used in case of error |
$Session{StatusCode} = 400; |
} |
if(!$rest && !$ARGS{no_xml_header}){ |
</%perl> |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
} |
# se abilitato all'inserimento |
my $permission = Permission($ARGS{PermissionGroup}); |
if(!$permission->{Insert}){ |
die "No insert permission\n"; |
} |
my $keyname = $m->scomp('SELF:KEY'); |
if($keyname =~ m/\.(.*)$/){ |
$keyname = $1; |
} |
# ritorna una nuova chiave utilizzabile per l'inserimento |
my $serial_seq = $m->scomp('SELF:SERIAL_SEQ'); |
my $sth = $Session{Dbh}->prepare('select nextval(?);'); |
$sth->execute($serial_seq); |
my $new_key = $sth->fetchrow_arrayref->[0]; |
$Session{Dbh}->commit; |
if($rest){ |
$m->out(to_json({ key => $new_key, keyname => $keyname })); |
}else{ |
</%perl> |
<<%$ARGS{name}%> key="<%$new_key|xml%>" keyname="<%$keyname|xml%>" /> |
<& SELF:XML_PATH, close => 1 &> |
% } |
</%method> |
%##################################################### delete |
<%method delete>\ |
<%perl> |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
my $rest = $ARGS{envelope_response} eq 'rest'; |
if($rest){ |
# The status code used in case of error |
$Session{StatusCode} = 400; |
}else{ |
</%perl> |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
} |
# se abilitato alla cancellazione |
my $permission = Permission($ARGS{PermissionGroup}); |
if(!$permission->{Delete}){ |
die "No delete permission\n"; |
} |
if(!length $ARGS{key_list}){ |
die "No key param\n"; |
} |
if($ARGS{key_list} =~ m/,/){ |
die "No multiple key in param key\n"; |
} |
$sth = ExecQuery('records t delete', 'SELF:RECORDS', WHERE => SqlSelectWhere(\%ARGS)); |
my $rec = $sth->fetchrow_arrayref; |
my $record_id = $rec ? $rec->[0] : undef; |
if(!defined $record_id){ |
die "No record retrieve or record not exists\n"; |
} |
# verifico se il record può essere letto (altrimenti non è concesso di poterlo cancellare) |
# N.B. SqlSelectWhere controlla anche i diritti di accesso al padre, se definito |
my %params; # per il passaggio di parametri tra PRE_DELETE DELETE POST_DELETE e POST_NO_DELETE |
# eseguo il metodo di pre delete se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('PRE_DELETE')){ |
$m->scomp('SELF:PRE_DELETE', KEY => $record_id, PARAMS => \%params); |
} |
my $sth = ExecQuery('delete', 'SELF:DELETE', KEY => $record_id, PARAMS => \%params); |
if($sth){ |
if($sth->rows != 1){ |
die 'Delete record return '.$sth->rows." rows\n"; |
} |
# log cancellazione record |
DB_log('delete', $record_id, undef); |
# eseguo il metodo di post delete se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('POST_DELETE')){ |
$m->scomp("SELF:POST_DELETE", KEY => $record_id, PARAMS => \%params); |
} |
}elsif($m->base_comp->method_exists('POST_NO_DELETE')){ |
$m->scomp("SELF:POST_NO_DELETE", KEY => $record_id, PARAMS => \%params); |
} |
if($Session{Dbh}->commit){ |
# notifico la cancellazione dei record |
</%perl> |
<<%$ARGS{name}%> key="<%$record_id|xml%>" /> |
% }else{ |
% die 'SQL error: '.DBI::errstr; |
% } |
% if(!$rest){ |
<& SELF:XML_PATH, close => 1 &> |
% }else{ |
% # The status code used in case of normal exit |
% $Session{StatusCode} = 204; |
% $r->status(204); |
% } |
</%method> |
%##################################################### numrec |
<%method numrec>\ |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
# se abilitato ... |
my $permission = Permission($ARGS{PermissionGroup}); |
if(!$permission->{Select}){ |
die "No retrieve permission\n"; |
} |
my $sth = ExecQuery('numrec', 'SELF:NUMREC', WHERE => SqlSelectWhere(\%ARGS)); |
my $numrec=$sth->fetchrow_arrayref->[0]; |
</%perl> |
<<%$ARGS{name}%> numrec="<%$numrec%>" /> |
<& SELF:XML_PATH, close => 1 &> |
</%method> |
%##################################################### retrieve |
<%method retrieve>\ |
<%perl> |
my $rest = $ARGS{envelope_response} eq 'rest'; |
if($rest){ |
# The status code used in case of error |
$Session{StatusCode} = 400; |
} |
if(!$rest && !$ARGS{no_xml_header}){ |
$m->out(qq{<?xml version="1.0" encoding="utf-8"?>\n}); |
} |
# se abilitato alla lettura |
my $permission = Permission($ARGS{PermissionGroup}); |
#DEBUG print STDERR "permission ".Dumper($permission); |
if(!$permission->{Select}){ |
die "No retrieve permission\n"; |
} |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
# $Params{orderby}='id'; |
$sth = SqlSelect('SELECT', 'ENTITY_FIELDS', \%ARGS); |
my $KEY = $m->scomp('SELF:KEY'); |
# i nomi dei campi risultato della query |
my $query_names = $sth->{NAME}; |
my $base_comp = $m->base_comp; |
if($rest){ # rispondo in formato JSON |
$r->headers_out->{'Content-Range'} = 'items '.$SQL{START}.'-'.($SQL{START}+$SQL{ROWS}-1).'/'.$SQL{MAX_ROWS}; |
$m->out('['); |
my $rec_sep="\n"; |
while(my $row = $sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
if($row){ |
my %out_row; |
my $id = $row->{$query_names->[0]}; |
for(my $i=0; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, undef) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 1); |
if(defined $val){ |
$out_row{$key} = $val; |
} |
} |
$m->out($rec_sep.to_json(\%out_row)); |
$rec_sep = ",\n"; |
} |
} |
$m->out("\n]"); |
}else{ # rispondo in formato XML |
if(!$ARGS{no_xml_header}){ |
$m->comp('SELF:XML_PATH', start => $SQL{START}, rows => $SQL{ROWS}, max_rows => $SQL{MAX_ROWS}); |
} |
while (my $row=$sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
my %children; |
if($row){ |
$m->out("<$ARGS{name} "); |
my $id = $row->{$query_names->[0]}; |
for(my $i=0; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, undef) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 1); |
if(ref $val eq 'ARRAY'){ |
# presumo ci sia un array di hash o di scalari |
$children{$key} = $val; |
}elsif(defined $val){ |
$m->out(qq{$key="}.$m->interp->apply_escapes($val, 'xml').qq{" }); |
} |
} |
if(%children){ |
$m->out(">\n"); |
foreach my $key (keys %children){ |
foreach my $subrec (@{$children{$key}}){ |
$m->out("<$key "); |
if(ref $subrec eq 'HASH'){ |
foreach my $subkey (keys %{$subrec}){ |
$m->out(qq{$subkey="}.$m->interp->apply_escapes($subrec->{$subkey}, 'xml').qq{" }); |
} |
$m->out('/>'); |
}else{ |
$m->out(">$subrec</$key>"); |
} |
} |
} |
$m->out("</$ARGS{name}>"); |
}else{ |
$m->out("/>\n"); |
} |
} |
} |
if(!$ARGS{no_xml_header}){ |
$m->comp('SELF:XML_PATH', close => 1); |
} |
} |
if($rest){ |
# The status code used in case of normal exit |
$Session{StatusCode} = undef; |
} |
</%perl> |
</%method> |
%##################################################### update |
<%method update>\ |
% my $rest = $ARGS{envelope_response} eq 'rest'; |
% if(!$rest){ |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
% } |
<%perl> |
if($rest){ |
# The status code used in case of error |
$Session{StatusCode} = 400; |
} |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
# se abilitato ... |
my $permission = Permission($ARGS{PermissionGroup}); |
if(!$permission->{Update}){ |
die "No update permission\n"; |
} |
if(!length $ARGS{key_list}){ |
die "No key param\n"; |
} |
if($ARGS{key_list} =~ m/,/){ |
die "No multiple key in param key\n"; |
} |
my @keynames; |
my $keyname = $m->scomp('SELF:KEY'); |
$keyname =~ s/^\s+\|\s+$//; |
push @keynames, $keyname; |
if($keyname =~ m/\.(.*)$/){ |
unshift @keynames, $1; |
} |
my $fields; |
if($rest){ |
# parsing JSON |
my $rows = from_json($ARGS{content}); |
# $fields = $rows->{params}; |
$fields = $rows; |
# die "NOT IMPLEMENTED"; |
}else{ |
my $xml_simple = new XML::Simple( |
keyattr => \@keynames, |
RootName => $ARGS{xml_path}, |
xmldecl => '<?xml version="1.0" encoding="utf-8"?>', |
); |
if($ARGS{content} !~ m|<dbms>.*</dbms>\s*$|is){ |
die "Malformed xml content: no <dbms> tag\n"; |
} |
my $data = $xml_simple->XMLin($ARGS{content}); |
$fields = $data->{$ARGS{name}}; |
$ARGS{father_id_update} = $ARGS{father_id}; |
} |
# trasformo la hash in un array |
my @update; |
# chiave del record |
push @update, $ARGS{key_list}; |
# elenco dei nomi dei campi |
my @names = &Method2Array('FIELDS'); |
for(my $I=0; $I<@names; $I++){ |
my $name = $names[$I]; |
my $val = $fields->{$name}; |
push @update, defined $val ? $val : undef; |
} |
my @update_list = (\@update); |
my $id_list = Array2UpdateSql(\@update_list, \%ARGS); |
if(@{$id_list}){ |
$m->comp('SELF:retrieve', %ARGS, key_list => $id_list->[0], no_xml_header => 1); |
} |
if($rest){ |
# The status code used in case of normal exit |
$Session{StatusCode} = undef; |
}else{ |
</%perl> |
<& SELF:XML_PATH, close => 1 &> |
% } |
</%method> |
%##################################################### create |
<%method create>\ |
<%perl> |
my $rest = $ARGS{envelope_response} eq 'rest'; |
if($rest){ |
# The status code used in case of error |
$Session{StatusCode} = 400; |
}else{ |
</%perl> |
<?xml version="1.0" encoding="utf-8"?> |
<& SELF:XML_PATH &> |
<%perl> |
} |
# se abilitato ... |
my $permission = Permission($ARGS{PermissionGroup}); |
if(!$permission->{Insert}){ |
die "No insert permission\n"; |
} |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
my @keynames; |
my $keyname = $m->scomp('SELF:KEY'); |
$keyname =~ s/^\s+\|\s+$//; |
push @keynames, $keyname; |
if($keyname =~ m/\.(.*)$/){ |
unshift @keynames, $1; |
} |
my $fields; |
if($rest){ |
# parsing JSON |
my $rows = from_json($ARGS{content}); |
$fields = $rows->{params}; |
}else{ |
my $xml_simple = new XML::Simple( |
keyattr => \@keynames, |
RootName => $ARGS{xml_path}, |
xmldecl => '<?xml version="1.0" encoding="utf-8"?>', |
); |
if($ARGS{content} !~ m|<dbms>.*</dbms>\s*$|is){ |
#DEBUG $PLogger->debug(sub{ "ARGS=$ARGS{content}"}); |
die "Malformed xml content: no <dbms> tag\n"; |
} |
my $data = $xml_simple->XMLin($ARGS{content}); |
$fields = $data->{$ARGS{name}}; |
} |
# trasformo la hash in un array |
my @insert; |
# chiave del record (array) per l'inserimento con chiave fornita |
push @insert, $ARGS{key_list} ? [$ARGS{key_list}] : undef; |
# elenco dei nomi dei campi |
my @names = &Method2Array('FIELDS'); |
for(my $I=0; $I<@names; $I++){ |
my $name = $names[$I]; |
if($name =~ m/\.(\w+)$/){ |
# campo definito completo di nome della tabella |
my $name_field = $1; |
# se non esiste il campo con nome completo di tabella ma è definito senza, utilizzo quest'ultimo |
if(!exists $fields->{$name} && exists $fields->{$name_field}){ |
$fields->{$name} = $fields->{$name_field}; |
} |
} |
my $val = $fields->{$name}; |
if($name eq $keyname && length $ARGS{key_list}){ |
# inserisco la chiave dichiarata nella URL |
push @insert, $ARGS{key_list}; |
}else{ |
push @insert, defined $val ? $val : undef; |
} |
} |
my @insert_list = (\@insert); |
my $id_list = Array2UpdateSql(\@insert_list, \%ARGS); |
if(@{$id_list}){ |
$m->comp('SELF:retrieve', %ARGS, key_list => $id_list->[0], no_xml_header => 1); |
} |
if($rest){ |
# The status code used in case of normal exit |
$Session{StatusCode} = undef; |
}else{ |
</%perl> |
<& SELF:XML_PATH, close => 1 &> |
% } |
</%method> |
%##################################################### metodi utilizzati da /dbms - END |
%##################################################### xml |
<%method xml>\ |
<& SELF:XML_PATH &> |
<%perl> |
# se abilitato alla cancellazione |
my $permission = Permission(); |
if($permission->{Select}){ |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
$sth = SqlSelect('SELECT', 'ENTITY_FIELDS', \%ARGS); |
my $KEY = $m->scomp('SELF:KEY'); |
# i nomi dei campi risultato della query |
my $query_names = $sth->{NAME}; |
my $base_comp = $m->base_comp; |
while (my $row = $sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
if($row){ |
</%perl> |
<<%$ARGS{name}%> \ |
<%perl> |
my $id = $row->{$query_names->[0]}; |
for(my $i=1; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, undef) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 1); |
</%perl> |
<%$key%>="<%$val|xml%>" \ |
% } |
/> |
% } |
% } |
% } |
<& SELF:XML_PATH, close => 1 &> |
</%method> |
%##################################################### xml_tree |
<%method ENTITY_RELATIONS></%method> |
<%method ENTITY_CHILDREN></%method> |
<%method ENTITY_FIELDS><& SELF:SELECT_FIELDS &></%method> |
<%method xml_tree>\ |
<%args> |
$myxml => undef |
$header => 1 |
$name |
</%args> |
<%perl> |
use XML::Simple; |
my $name_xml = $name; |
$name_xml =~ s/\//\./gs; |
if($name_xml !~ m/\./){ |
my $schema = $m->scomp('SELF:SCHEMA'); |
$name_xml = "$schema.$name_xml"; |
} |
my $xml_op = new XML::Simple(keyattr => ['id'], |
RootName => $ARGS{xml_path}, |
xmldecl => '<?xml version="1.0" encoding="utf-8"?>' ); |
my %relations; |
#DEBUG $PLogger->debug(sub{ 'XML_TREE_'x10, Dumper(\%ARGS), 'xml_tree_'x10; }); |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
my $sth = SqlSelect('SELECT', 'ENTITY_FIELDS', \%ARGS); |
#DEBUG $PLogger->debug(sub{ 'XML_TREE NUMERO RIGHE DA PROCESSARE:',$sth->rows; }); |
if($header){ |
$m->clear_buffer; |
} |
my %entity_relations = method2hash('ENTITY_RELATIONS'); |
my %entity_children = method2hash('ENTITY_CHILDREN'); |
#DEBUG $PLogger->debug(sub{ "NAME:$name \nRELATIONS:".Dumper(\%entity_relations).'CHILDREN:'.Dumper(\%entity_children) }); |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
while (my $row = $sth->fetchrow_hashref){ |
foreach my $key (keys %entity_relations){ |
if(length($row->{$key})){ |
$relations{$entity_relations{$key}.'|'.$row->{$key}}=1; |
} |
} |
foreach my $key ( keys %$row ){ |
$_ = $row->{$key}; |
s/^\s+//; |
s/\s+$//; |
s/\\/\\\\/g; |
s/\t/\\t/g; |
s/\n/\\n/g; |
if (length($_)) { |
$myxml->{$name_xml}->{$row->{"id"}}->{$key} = $_; |
} |
} |
foreach my $key (keys %entity_children){ |
#DEBUG $PLogger->debug(sub{ "##### entity_child '$key' '$entity_children{$key}'"; }); |
if(length($row->{$key})){ |
my($table, $keyname) = split /\s*\:\s*/, $entity_children{$key}, 2; |
if(!$keyname){ |
$keyname = $m->scomp('SELF:KEY_NAME'); |
} |
my $KEY = $row->{$key}; |
#DEBUG $PLogger->debug(sub{"key:$KEY table:$table keyname:$keyname"; }); |
#DEBUG $PLogger->debug(sub{ "###################################### $table.mql:CHILDREN"; }); |
my $child = $m->fetch_comp("$DataBaseUrl/$table.mql") || die("No table $table.mql\n"); |
# fornisco il parametro father_id solo se la tabella figlia ha come padre l'oggetto corrente |
my $father_name = $child->scall_method('FATHER_NAME'); |
my $father_id_name = $child->scall_method('FATHER_ID_NAME'); |
my $father_id; |
if($father_name && ($father_name eq $name_xml) && $father_id_name eq $keyname){ |
$father_id = $KEY; |
} |
#DEBUG $PLogger->debug(sub{ "name:$name_xml child:$table key:$KEY keyname:$keyname father_id:$father_id, father_name:$father_name father_id_name:$father_id_name\n" }); |
$m->comp("$DataBaseUrl/$table.mql:xml_tree", |
%ARGS, |
start => undef, |
rows => undef, # tutti i record |
key_list => undef, |
father_id => $father_id, |
name => $table, |
json_where => to_json({ $keyname => ['=', $KEY] }), |
header => undef, |
myxml => $myxml |
); |
} |
} |
} |
#### Inserisco dati ENTITY_RELATIONS |
foreach my $key (sort keys %relations){ |
#DEBUG $PLogger->debug(sub{ 'RELATIONS_'x6, Dumper(\%relations), 'relations_'x6; }); |
my($table_keyname, $KEY) = split /\|/, $key, 2; |
my($table, $keyname) = split /\s*\:\s*/, $table_keyname, 2; |
if(!$keyname){ |
$keyname = 'id'; |
} |
#DEBUG print STDERR "name:$name_xml child:$table key:$KEY keyname:$keyname\n"; |
$m->comp("$DataBaseUrl/$table.mql:xml_tree", |
%ARGS, |
name => $table, |
json_where => to_json({ $keyname => ['=', $KEY] }), |
rows => '1', # un solo record |
start => undef, |
father_id => undef, |
key_list => undef, |
header => undef, |
myxml => $myxml |
); |
} |
if($header){ |
$m->clear_buffer; |
$m->out($xml_op->XMLout($myxml)); |
} |
</%perl> |
</%method> |
%##################################################### txt |
<%method txt>\ |
<%perl> |
my $sth = SqlSelect('SELECT', 'SELECT_FIELDS', \%ARGS); |
$m->out(join("\t", @{$sth->{NAME}}), "\n"); |
while(my $row = $sth->fetchrow_arrayref){ |
map { |
s/\t/\\t/sg; |
s/\n/\\n/sg; |
s/\r/\\r/sg; |
} @{$row}; |
$m->out(join("\t", @{$row}), "\n"); |
} |
</%perl> |
</%method> |
%##################################################### xls |
<%method xls>\ |
<%perl> |
my $permission = Permission('Xls'); |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
use Spreadsheet::WriteExcel; |
# mi assicuro che non venga utilizzata la cache per le query |
$ARGS{RecordsetCache} = undef; |
my $sth = SqlSelect('SELECT_XLS', 'SELECT_XLS_FIELDS', \%ARGS); |
# creazione nuovo spreadsheet |
my $file_xls = $r->dir_config('TmpDir')."/file_excel.$$.xls"; |
my $workbook = Spreadsheet::WriteExcel->new($file_xls); |
my $worksheet = $workbook->add_worksheet(); |
# individuo i tipi delle colonne |
my @types; |
if($m->base_comp->method_exists('TYPE_FIELDS_XLS')){ |
# elenco tipi definito |
@types = &Method2Array('TYPE_FIELDS_XLS'); |
}else{ |
# ricavo l'elenco dai tipi campo del database |
foreach my $name (@{$sth->{NAME}}){ |
my $type = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'TYPE'); |
if($type =~ m/int/i || $type =~ m/real/i || $type =~ m/bool/i || $type =~ m/num/i || $type =~ m/numeric/i){ |
push @types, 'number'; |
}elsif($type =~ m/dat/i || $type =~ m/time/i){ |
push @types, 'date'; |
}else{ |
push @types, 'string'; |
} |
} |
} |
for(my $col=0; $col<@{$sth->{NAME}}; $col++){ |
my $type = $types[$col]; |
if($type eq 'number'){ |
$worksheet->set_column($col, $col, 8); |
}elsif($type eq 'date'){ |
$worksheet->set_column($col, $col, 11); |
}elsif($type eq 'string'){ |
$worksheet->set_column($col, $col, 20); |
}else{ # auto |
$worksheet->set_column($col, $col, 10); |
} |
} |
# intestazioni |
# formato di stampa dell'intestazione dei campi |
my $format_int = $workbook->add_format(); |
#$format_int->set_text_wrap(); |
$format_int->set_bold(); |
$format_int->set_align('center'); |
$format_int->set_align('vcenter'); |
$worksheet->write_row(0, 0, $sth->{NAME}, $format_int); |
# formato di stampa delle righe dei dati |
$worksheet->keep_leading_zeros(); |
my $string_format = $workbook->add_format(); |
$string_format->set_text_wrap(); |
# formato di stampa delle date |
my $date_format = $workbook->add_format(num_format => 'dd/mm/yyyy'); |
my $date_time_format = $workbook->add_format(num_format => 'dd/mm/yyyy hh:mm:ss'); |
my $timestamp_format = $workbook->add_format(num_format => 'dd/mm/yyyy hh:mm:ss.sss'); |
# appendo tutte le righe del dataset |
# righe del foglio elettronico |
my $row=1; |
while(my $columns = $sth->fetchrow_arrayref){ |
my $col = 0; |
foreach my $column (@{$columns}){ |
if(defined $column){ |
my $type = $types[$col]; |
if(!defined $type || $type eq 'auto'){ |
if($column =~ m/^\s*\d+[.,]*\d*$/){ |
$worksheet->write_number($row, $col, $column); |
}else{ |
# verifico se si tratta di una data |
my($date, $dformat) = dateXls($column); |
if(defined $dformat){ |
$worksheet->write_date_time($row, $col, $date, ($date_format, $date_time_format, $timestamp_format)[$dformat]); |
}else{ |
$worksheet->write_string($row, $col, $column, $string_format); |
} |
} |
}elsif($type eq 'number'){ |
$worksheet->write_number($row, $col, $column); |
}elsif($type eq 'date'){ |
my($date, $dformat) = dateXls($column); |
$worksheet->write_date_time($row, $col, $date, ($date_format, $date_time_format, $timestamp_format)[$dformat]); |
}else{ |
$worksheet->write_string($row, $col, $column, $string_format); |
} |
} |
$col++; |
} |
$row++; |
} |
$workbook->close(); |
if(-f $file_xls){ |
sysopen XLS, $file_xls, 'O_RDONLY' || die "sysopen $file_xls: $!"; |
my $buffer; |
# leggo il file generato a blocchi di 64Kbyte |
while(my $numchar = sysread XLS, $buffer, 2^16){ |
if(undef $numchar){ |
die "sysread $file_xls: $!"; |
}; |
$m->out($buffer); |
} |
close XLS; |
}else{ |
$r->content_type('application/html'); |
$m->out("ERRORE: il report non ha generato il file XLS") |
} |
unlink $file_xls || $PLogger->warn("unlink $file_xls: $!"); |
</%perl> |
</%method> |
<%method pdf>\ |
<%perl> |
# identifico gli ID in base alle condizioni WHERE indicate |
my($GROUP_ID, $report_ids) = SqlSelect2report_id(\%ARGS); |
$m->clear_buffer; |
if($GROUP_ID){ |
if(@$report_ids){ |
# inizializzo la tabella report_id |
$m->comp('SELF:PDF', GROUP_ID => $GROUP_ID, report_ids => $report_ids, %ARGS); |
}else{ |
# elenco vuoto |
$r->content_type('text/html; charset=utf-8'); |
$m->out('<br><br><br><p align="center">Elenco vuoto</p>'); |
} |
# cancello l'elenco ... |
ExecQuery('delete print group', undef, "delete from public.report_id where group_id = ?", $GROUP_ID); |
}else{ |
$m->comp('SELF:PDF', %ARGS); |
} |
</%perl> |
</%method> |
%##################################################### field_check |
<%doc> |
Metodo chiamato per la verifica del campo |
Parametri passati in %ARGS: |
$COL colonna nel form |
$ROW riga nel form |
$KEY chiave del record in modifica (se inserimento sarà uguale a undef) |
$VALUE valore del campo da verificare |
$PARAM parametri del campo da verificare |
$ID_FIELD identificatore del widget nel browser |
$FIELD nome del campo (se definito, completo del nome della tabella) |
$FATHER_ID chiave del record padre |
@VALUES array dei valori nello stesso record del campo da verificare |
Al metodo specifico <nome_campo>_CHECK vengono passati anche i parametri: |
@NAMES array con i nomi dei campi |
%VALUES hash con i valori dei campi |
</%doc> |
<%method field_check>\ |
<%args> |
$FIELD |
$ID_FIELD |
@VALUES |
</%args>\ |
<%perl> |
my $field = $FIELD; |
$field =~ s/^\w\.//; |
my $comp = Exist_Check($FIELD); |
my @names = &Method2Array('FIELDS'); |
my %values; |
for(my $I=0; $I<@names; $I++){ |
$values{$names[$I]} = $VALUES[$I]; |
} |
$m->clear_buffer; |
if($comp){ |
$m->comp($comp, %ARGS, NAMES => \@names, VALUES => \%values); |
}else{ |
$m->out("Non esiste sul server un metodo per verificare il campo $FIELD di id:$ID_FIELD"); |
} |
</%perl>\ |
</%method> |
%##################################################### table |
<%method table>\ |
% $m->comp('SELF:TABLE', 'rows' => $ARGS{rows}); |
</%method> |
%##################################################### array |
<%method array>\ |
<%perl> |
$SQL{DIFF_RECORDS}=0; |
if(!$ARGS{recordset}){ |
$ARGS{recordset} = 'new'; |
} |
# valuto la clausola Where |
$ARGS{SelectWhere} = SqlSelectWhere(\%ARGS); |
# Predispongo la cache per il recordset |
$ARGS{RecordsetCache} = RecordsetCache($ARGS{name}, $ARGS{recordset}, |
'SELF:NUMREC', |
'SELF:RECORDS', |
'SELF:FIND_RECORDS', |
$ARGS{SelectWhere}); # 'new' oppure 'cache' |
if($ARGS{start} < 0){ |
# devo calcolare la posizione di start in fondo al recordset |
$ARGS{start} += $ARGS{RecordsetCache}{Size}; |
} |
if(defined $ARGS{update}){ |
my $arr = $ARGS{update}; |
my $data = my_eval($arr); |
if($SQL{UPDATE_LIST} = Array2UpdateSql($data, \%ARGS)){ |
$ARGS{recordsetChanged} = 1; |
} |
} |
#DEBUG $PLogger->debug(sub{ if($SQL{UPDATE_LIST}){ "UPDATE_LIST UPDATE_LIST UPDATE_LIST ", join ',', @{$SQL{UPDATE_LIST}};}; }); |
if(defined $ARGS{delete}){ |
if(Array2DeleteSql(\%ARGS)){ |
$ARGS{recordsetChanged} = 1; |
} |
} |
my $sth = SqlSelect('SELECT', 'SELECT_FIELDS', \%ARGS); |
# preparo il codice javascript ... |
$m->out("window.db = $ARGS{name};\n"); |
# i nomi dei campi risultato della query |
my $query_names = $sth->{NAME}; |
# messaggio da visualizzare all'utente |
if($ARGS{BrowserAlert}){ |
</%perl>\ |
my_alert('<%$ARGS{BrowserAlert}|js%>', 'alert'); |
% }elsif($Session{ARGS}->{BrowserAlert}){ |
my_alert('<%$Session{ARGS}->{BrowserAlert}|js%>', 'alert'); |
<%perl> |
} |
my @names = &Method2Array('FIELDS'); |
# solo alla prima richiesta invio i parametri di inizializzazione |
if($ARGS{initRecordset}){ |
&Fields_JList('db', \@names, 'FIELDS_NOT_NULL', 'required_fields'); |
</%perl>\ |
db.names = [<%ListJscript(\@names, '', 'array2list') %>]; |
db.descriptions = [<%ListJscript('FIELDS_DESCR', '', 'list') %>]; |
db.cols = <%$sth->{NUM_OF_FIELDS}-1%>; |
% my $print_form = ListJscript('PRINT_FORM', '', 'list'); |
% # non invio al client l'eventuale password di protezione del report |
% $print_form =~ s/,'PROTECT=.*'//; |
db.print_form = [<% $print_form %>]; |
% } #initRecordset |
% if($ARGS{initRecordset} or $ARGS{type} eq 'reload'){ |
db.new_fields = [<%ListJscript('FIELDS_NEW', '', 'list') %>]; |
db.dup_fields = [<%ListJscript('FIELDS_DUP', '', 'list') %>]; |
db.cp_fields = [<%ListJscript('FIELDS_COPY_PASTE', '', 'list') %>]; |
% } |
db.father_id_update = db.father_id = <% encodeJs($ARGS{father_id}) %>; |
db.start = <%$SQL{START}%>; |
db.rows = <%$SQL{ROWS}%>; |
db.max_rows = <%$SQL{MAX_ROWS}%>; |
db.recordset_changed = <% $ARGS{recordsetChanged} ? 'true' : 'false' %>; |
% # nome del campo chiave primaria |
% my $KEY = $m->scomp('SELF:KEY'); |
% # vettore delle chiavi primarie |
% my $keys = []; |
<%perl> |
# matrice dei dati |
my @data = (); |
# matrice dei parametri |
my @params = (); |
# reference record - solo se il recordset ha una sola riga |
# usato per cambiare dinamicamente l'elenco dei campi in FIELDS_RO, FIELDS_RO_UPDATE, PERMISSION ecc. |
$Session{ARGS}->{Record0} = undef; |
if($ARGS{RecordsetCache}){ |
#DEBUG $PLogger->debug(sub{ "Leggo tutto l'elenco per poter stampare le righe nell'ordine desiderato" }); |
# se le chiavi dei record sono rese persistenti, l'ordinamento dei record |
# deve tenere conto di quell'ordine anziché l'ordine della query di dettaglio in $sth |
# devo quindi leggere tutto il recordset per poi stampare le righe nell'ordine desiderato |
my %data; |
my %params; |
my $base_comp = $m->base_comp; |
while (my $row = $sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
if($row){ |
my @params_row = (); |
my @row = (); |
my $str; |
my $id = $row->{$query_names->[0]}; |
#DEBUG $PLogger->debug(sub{'row->'.Dumper($row)}); |
if($SQL{ROWS} == 1){ |
$Session{ARGS}->{Record0}{$KEY} = $id; |
} |
for(my $i=1; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, $param) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 0); |
if($SQL{ROWS} == 1){ |
$Session{ARGS}->{Record0}{$key} = $val; |
} |
push @params_row, escape_value($param); |
push @row, escape_value($val); |
} |
$data{$id} = \@row; |
$params{$id} = \@params_row; |
} |
} |
$keys = $ARGS{recordset_list}; |
for(my $R=0; $R<@$keys; $R++){ |
my $key = $keys->[$R]; |
if(exists $data{$key}){ |
push @data, $data{$key}; |
push @params, $params{$key}; |
}else{ |
# manca il record indicato in cache. Si tratta di un record cancellato |
#DEBUG $PLogger->debug(sub{"manca il record id:$key indicato in cache. Si tratta di un record cancellato"}); |
# genero una riga vuota |
push @data, []; |
push @params, []; |
} |
} |
#DEBUG $PLogger->debug(sub{ 'recordset_list ' . Dumper($ARGS{recordset_list}); }); |
}else{ |
#DEBUG PLogger->debug('Genero l\'array direttamente dal recordset di dettaglio'); |
# genero l'array direttamente dal recordset di dettaglio in $sth |
my $num_rows = $SQL{ROWS}-1; |
my $base_comp = $m->base_comp; |
while (my $row = $sth->fetchrow_hashref){ |
if($base_comp->method_exists('OUT_FILTER')){ |
$row = $base_comp->call_method('OUT_FILTER', row => $row); |
} |
if($row){ |
my $id = $row->{$query_names->[0]}; |
push @$keys, $id; |
my @params_row = (); |
if($SQL{ROWS} == 1){ |
$Session{ARGS}->{Record0}{$KEY} = $id; |
} |
my @row; |
for(my $i=1; $i<@$query_names; $i++){ |
my $key = $query_names->[$i]; |
my($val, $param) = Call_OutFieldFilter($key, $id, $row->{$key}, $query_names, $row, $base_comp, 0); |
if($SQL{ROWS} == 1){ |
$Session{ARGS}->{Record0}{$key} = $val; |
} |
push @params_row, escape_value($param); |
push @row, escape_value($val); |
} |
push @data, \@row; |
push @params, \@params_row; |
} |
} |
} |
</%perl> |
db.data = <% to_json(\@data) %>; |
%#DEBUG % $PLogger->debug(sub{Dumper(\@params)}); |
db.params = <% to_json(\@params) %>; |
db.keys = <% to_json(\@$keys) %>; |
%# aggiungo la matrice con i valori delle chiavi delle tabelle figlie |
<%perl> |
if($ARGS{rows} >= 1){ |
my @fathers_id = (); |
my $FIELDS = $m->scomp('SELF:CHILDREN_FIELDS'); |
if($FIELDS){ |
# abbiamo dei recordset figli |
# elenco chiavi dei recordset figli |
my $sth = ExecQuery('list children keys', 'SELF:SELECT_CHILDREN_ID', FIELDS => "$KEY, $FIELDS", WHERE => $SQL{LAST_WHERE}, ORDER => $SQL{LAST_ORDER}); |
# devo ordinare le chiavi come in (db.keys) |
my %children_keys; |
while(my @row = $sth->fetchrow_array){ |
# nella prima colonna ho la chiave primaria |
my $pk = shift @row; |
$children_keys{$pk} = \@row; |
} |
foreach my $pk (@$keys){ |
my $row = $children_keys{$pk}; |
my @cols; |
for(my $i=0; $i<@{$row}; $i++){ |
push @cols, $row->[$i]; |
} |
push @fathers_id, \@cols; |
} |
} |
$m->out('db.fathers_id = '.to_json(\@fathers_id).';'); |
} |
# campi FIELDS_RO & FIELDS_RO_UPDATE |
&Fields_RO('db', \@names); |
# permessi ... |
my $permission = Permission(); |
foreach my $perm (keys %{$permission}){ |
$m->out("db.can$perm = ".($permission->{$perm} ? 'true' : 'false').";\n"); |
#DEBUG $PLogger->debug(sub{ "db.can$perm = ".($permission->{$perm} ? 'true' : 'false'); }); |
} |
</%perl> |
% if($m->base_comp->method_exists('POST_array')){ |
%#// begin POST_array |
% $m->comp('SELF:POST_array', KEYS => $keys, Params => \%ARGS, SQL => \%SQL); |
%#// end POST_array |
% } |
%#// end array. |
</%method> |
%##################################################### select - elenco options in formato jscript (senza buffer) |
<%method select>\ |
% my $sth = ExecQuery('jscript select', 'SELF:SELECT', WHERE => EvalSqlWhere(undef, \%ARGS), %ARGS); |
% # Sel viene definito prima della chiamata |
function _Add(id, value, parameters){ |
var O=document.createElement("OPTION"); O.innerHTML=value; O.value=id; Sel.appendChild(O); Sel.Cache_parameters[id] = parameters; |
} |
% while (my @row = $sth->fetchrow_array){ |
% my $id = shift @row; |
_Add('<%$id |js%>','<%$row[0] |js%>', '<%join '|', @row |js%>'); |
% } |
</%method> |
%##################################################### bufferselect - elenco options in formato jscript per costituire un buffer |
<%method bufferselect>\ |
<%args> |
$C |
</%args> |
% my $sth = ExecQuery('bufferselect', 'SELF:SELECT', WHERE => EvalSqlWhere(undef, \%ARGS), %ARGS); |
function _Add_<%$C%>(S, id, value, param){ |
var O=document.createElement("OPTION"); O.innerHTML=value; O.value=id; S.appendChild(O); |
S.params[id]=param; |
} |
function _PopulateSelect_<%$C%>(S){ |
S.params = []; |
% while (my $row=$sth->fetchrow_arrayref){ |
_Add_<%$C%>(S,'<%($row->[0])|js%>','<%($row->[1])|js%>'<% defined $row->[2] ? (', \''.$m->interp->apply_escapes($row->[2], 'js').'\'') : ''%>); |
% } |
} |
</%method> |
%##################################################### parameters_select - restituisce la descrizione corrispondente ad un identificatore |
<%method parameters_select>\ |
<%args> |
$key |
</%args> |
% my $sth = ExecQuery('parameters_select', 'SELF:SELECT', ID => $key, WHERE => undef); |
% # formato p1|p2|p3|... |
% if($sth->rows){ |
% my @fields = $sth->fetchrow_array; |
% shift @fields; |
<% join('|', @fields) %>\ |
% } |
</%method> |
%##################################################### selectoptions - elenco opzioni in formato HTML |
<%method selectoptions>\ |
% my $sth = ExecQuery('selectoptions', 'SELF:SELECT', WHERE => EvalSqlWhere(undef, \%ARGS), %ARGS); |
% while (my $row=$sth->fetchrow_arrayref){ |
<option value="<%($row->[0])|h%>"><%($row->[1])|h%></option> |
% } |
</%method> |
%##################################################### htmlselectpopup - elenco opzioni in formato HTML da visualizzare in una finestra Popup |
<%method htmlselectpopup>\ |
<%args> |
$V => undef |
$max_width |
$max_height |
$empty => undef |
$empty_descr => '' |
</%args> |
% my $pari; |
<div class="htmlselect_Body" style="<% $max_width ? "max-width:$max_width;" : '' %><% $max_height ? "max-height:$max_height;" : '' %>"> |
% if(defined $empty){ |
<div class="htmlselect_<% ($pari = !$pari) ? 'P' : 'D'%>" id="htmlselect_Id<%$empty|h%>" onmouseover="htmlselect_PD(this, true)" onmouseout="htmlselect_PD(this)"\ |
onClick="Input_HtmlSelect_PopupHandler(this)" mql-id="<%$empty|h%>" mql-parameters=""><%$empty_descr|h%> </div> |
% } |
% my $sth = ExecQuery('htmlselectpopup', 'SELF:SELECT', WHERE => EvalSqlWhere(undef, \%ARGS), %ARGS); |
% my @Script_buffer; |
% while (my @row = $sth->fetchrow_array){ |
% my $id = shift @row; |
% my $descr = shift @row; |
<div class="htmlselect_<% ($pari = !$pari) ? 'P' : 'D'%>" id="htmlselect_Id<% $id |h%>" onmouseover="htmlselect_PD(this, true)" onmouseout="htmlselect_PD(this)"\ |
onClick="Input_HtmlSelect_PopupHandler(this)" mql-id="<% $id |h%>" mql-parameters="<% $m->interp->apply_escapes(join('|', @row)) |h%>"><% $descr |h%></div> |
% } |
</div> |
</%method> |
%##################################################### input_file_uload - per upload file dal widget input/file.comp |
<%method input_file_uload>\ |
<%args> |
$field |
$value |
$key |
</%args> |
<%perl> |
my $sth = ExecQuery('input_file_uload', 'SELF:SELECT', ID => $key, FIELDS => $field); |
my $file = from_json $sth->fetchrow_arrayref->[1]; |
my $check = from_json $value; |
if($file->{filename} eq $check->{filename} && |
$file->{'content-type'} eq $check->{'content-type'} && |
(!exists $file->{digest_md5} || $file->{digest_md5} eq $check->{digest_md5}) |
){ |
$m->clear_buffer; |
$r->content_type($file->{'content-type'}); |
$r->headers_out->{'Content-disposition'} = qq{inline; filename="$check->{filename}"}; |
$m->out(decode_base64($file->{base64})); |
$m->abort; |
}else{ |
die "Data file mismatch\n"; |
} |
</%perl> |
</%method> |
%##################################################### call_remote |
<%method call_remote>\ |
%#//GDO my_alert('<% $m->interp->apply_escapes(Dumper(\%ARGS), 'js') %>'); |
<%perl> |
# ricerco il metodo |
my $remote_func = 'CALL_REMOTE_'.$ARGS{remote_func_name}; |
if($m->base_comp->method_exists($remote_func)){ |
# valuto la clausola Where |
$ARGS{SelectWhere} = SqlSelectWhere(\%ARGS); |
#DEBUG $PLogger->debug('remote_func_params:'.Dumper(\%{$ARGS{remote_func_params}})); |
#DEBUG $PLogger->debug('dbms_params:'.Dumper(\%ARGS)); |
$m->comp("SELF:$remote_func", %{$ARGS{remote_func_params}}, dbms_params => \%ARGS); |
}else{ |
die("Il metodo remoto $remote_func non definito\n"); |
} |
</%perl> |
</%method> |
%################################################################################# END METHODS |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%shared> |
my %Params; |
%SQL = (); |
my $sth; |
BrowserAlert(); |
</%shared> |
<%once> |
use IPC::Run qw(run); |
use IPC::Run::SafeHandles; |
use File::Path qw(make_path remove_tree); |
use File::Temp qw/ tempfile /; |
use File::Find::Rule; |
use File::Copy qw/move/; |
use Archive::Zip qw( :ERROR_CODES :CONSTANTS ); |
use Archive::Tar::Wrapper; |
use Text::Balanced; |
use JSON; |
use MIME::Base64; |
my %envelope_type = ( |
xml => 'text/xml; charset=utf-8', |
json => 'application/json; charset=utf-8', |
rest => 'application/json; charset=utf-8' |
); |
my %mimelist = ( |
htmlselectpopup => 'text/html; charset=utf-8', |
divselectpopup => 'text/html; charset=utf-8', |
select => 'text/plain; charset=utf-8', |
bufferselect => 'text/plain; charset=utf-8', |
numrec => 'text/xml; charset=utf-8', |
xml => 'text/xml; charset=utf-8', |
xml_tree => 'text/xml; charset=utf-8', |
newkey => 'text/xml; charset=utf-8', |
info => 'text/xml; charset=utf-8', |
keyname => 'text/xml; charset=utf-8', |
html => 'text/html; charset=utf-8', |
table => 'text/plain; charset=utf-8', |
array => 'text/plain; charset=utf-8', |
field_check => 'text/plain; charset=utf-8', |
parameters_selecT => 'text/plain; charset=utf-8', |
pdf => 'application/pdf', |
txt => 'text/plain; charset=utf-8', |
xls => 'application/vnd.ms-excel', |
call_remote => 'text/plain; charset=utf-8', |
); |
# Appende un messaggio che verra' visualizzato sul browser |
sub BrowserAlert(@) { |
if(@_){ |
#DEBUG print STDERR 'BrowserAlert '.Dumper(\@_); |
$PLogger->debug(sub{ 'BrowserAlert '.Dumper(\@_);}); |
$Session{ARGS}->{BrowserAlert} .= join("\n", @_) . "\n"; |
}else{ |
$PLogger->debug('Reset BrowserAlert'); |
$Session{ARGS}->{BrowserAlert} = ''; |
} |
} |
sub escape_value($){ |
$_ = shift; |
s/\r//gs; |
# \x{2028} & \x{2029} count as line endings in Javascript ECMAScript standard (3rd edition section 7.3) |
s/\x{2028}/\n/gs; |
s/\x{2029}/\n/gs; |
return $_; |
} |
# tratta il parametro verificando il tipo |
# se numerico non viene posto tra '' |
# se undef ritorna null |
sub encodeJs($){ |
local $_ = $_[0]; |
if(!defined){ |
return 'null'; |
}elsif(m/^[+-]{0,1}0\d+\.*\d*$/){ |
s/'/\\'/; |
s/\n/\\n/; |
return '\''.$_.'\''; |
}elsif(m/^[+-]{0,1}\d+\.*\d*$/){ |
return $_; |
}else{ |
s/'/\\'/; |
s/\n/\\n/; |
return '\''.$_.'\''; |
} |
} |
# tratta il parametro verificando il tipo |
# se numerico non viene posto tra '' |
# se stringa vuota ritorna null |
sub encodeSql($){ |
local $_ = $_[0]; |
if(length == 0){ |
return 'null'; |
}elsif(m/^[+-]{0,1}0\d+\.*\d*$/){ |
$_ = $Session{Dbh}->quote($_); |
s/\n/\\n/; |
return $_; |
}elsif(m/^[+-]{0,1}\d+\.*\d*$/){ |
return $_; |
}else{ |
$_ = $Session{Dbh}->quote($_); |
s/\n/\\n/; |
return $_; |
} |
} |
# elabora l'out di un stringa contenente una lista, realizzando un array degli elementi |
# $sep è espressione regolare per la separazione degli elementi nella lista; se non dichiarato utilizza /\s*,\s*/ |
sub List2Array{ |
my $list = shift; |
my $sep = shift; |
if(!defined $sep){ |
$sep = '\s*,\s*'; |
} |
$list =~ s/^\s+|\s+$//g; # spazi davanti e dietro |
#DEBUG $PLogger->debug(sub{ my @arr = split /$sep/, $list; "List2Array '$list' with '$sep' -->", Dumper(\@arr); }); |
return split /$sep/, $list; |
} |
sub List2Params{ |
my $list = shift; |
my $sep = shift; |
if(!defined $sep){ |
$sep = '\s*,*\s*'; |
} |
my %params = (); |
if($list){ |
$list =~ s/\\//g; |
}else{ |
return \%params; |
} |
my $options = $list; |
my @name = Text::Balanced::extract_multiple($options, [ |
qr/$sep([\w-]+)\s*=\s*/, |
qr/^\s*([\w-]+)\s*=\s*/, |
], undef, 1); |
$options = $list; |
my @value = Text::Balanced::extract_multiple($options, [ |
sub { Text::Balanced::extract_quotelike($_[0]) }, |
qr/\s*=\s*([\w-]+)/, |
], undef, 1); |
if($#name != $#value){ |
die "Non valido formato di parametri di comando: $list\nUso [ param1=100 ][ MyPAR='my string data' ].\n"; |
} |
for (my $I = 0; $I<@value; $I++){ |
$value[$I] =~ s/^("|'|`|\s)+//; |
$value[$I] =~ s/("|'|`|\s)+$//; |
$value[$I] =~ s/$sep$//; |
$params{uc $name[$I]} = $value[$I]; |
$PLogger->debug(sub{ "List2Params param($name[$I])=$value[$I]"; }); |
} |
return \%params; |
} |
# elabora un array generando una lista separata da ', ' |
sub Array2List { |
#DEBUG $PLogger->debug('Array2List '.Dumper(\@_)); |
my @arr; |
foreach my $elem (@_){ |
push @arr, encodeSql($elem); |
} |
return join ', ', @arr; |
} |
# elabora l'out di un metodo realizzando un array degli elementi |
# $sep è espressione regolare per la separazione degli elementi nel metodo; se non dichiarato utilizza /\s*,\s*/ |
sub Method2Array{ |
my $comp = shift; |
my $sep = shift; |
if($comp !~ m/:/){ |
# se manca la definizione di oggetto:metodo considero si tratti di metodo dell'oggetto corrente |
$comp = "SELF:$comp"; |
#DEBUG $PLogger->debug("comp=$comp"); |
} |
return List2Array $m->scomp($comp, @_), $sep ; |
} |
# valuta un campo proveniente dal client |
# ritorna una stringa adatta ad essere inserita in una query SQL |
# o per essere inserita nel codice Javascipt |
sub str2sql_js_delimited($;$){ |
my($val, $null)=@_; |
if($null && length($val)==0){ |
return $null; |
}elsif(!defined $val){ |
return 'null'; |
}else{ |
return "'$val'"; |
} |
} |
# valuta il codice in modo protetto |
sub my_eval($){ |
use Safe; |
my $lim_eval = new Safe; |
$lim_eval->permit_only(qw(:default)); |
$lim_eval->share('%SQL'); |
#DEBUG $PLogger->debug(sub{ "MY_EVAL=($_[0])"; }); |
my $ris = $lim_eval->reval($_[0]); |
if(!$ris){ |
die "Errore nella valutazione di ".$_[0]."\n"; |
} |
# $PLogger->debug(sub{ "MY_EVAL=",Dumper($ris); }); |
return $ris; |
} |
# costruisce un Hash con il testo ritornato dal metodo Mason di nome $comp |
sub method2hash($){ |
my $comp = shift; |
if($comp !~ m/:/){ |
$comp = "SELF:$comp"; |
} |
my $str = $m->scomp($comp); |
#DEBUG $PLogger->debug("method2hash($str)"); |
$str =~ s/'{0,1}([\w\.\/:]+)'{0,1}/'$1'/g; |
#DEBUG $PLogger->debug("method2hash => '$str'"); |
#DEBUG $PLogger->debug(Dumper(eval "(${str})") ); |
return eval "(${str})"; |
} |
sub PrepareQuery(@){ |
my $descr = shift; |
my $cmd = shift; |
my $query = $cmd ? $m->scomp($cmd, @_) : shift; |
if($query){ |
my $schema = $m->scomp('SELF:SCHEMA'); |
if($schema ne 'public' && $query !~ m/SET\s+search_path\s+TO\s+/is){ |
$query = "SET search_path TO $schema, public;\n$query"; |
} |
my $sth = $Session{Dbh}->prepare($query); |
if($PLogger->is_debug){ |
if($query =~ m/\n/s){ |
# predispondo la query multiriga con '|' iniziale per migliorare la lettura nel file di log |
$query =~ s/\n/\n \| /sg; |
$PLogger->debug("PrepareQuery $descr $cmd query:{\n | $query\n |}."); |
}else{ |
$PLogger->debug("PrepareQuery $descr $cmd query:[$query]"); |
} |
# }else{ |
# $PLogger->info(sub{ "PrepareQuery $descr $cmd." }); |
} |
return $sth; |
}else{ |
$PLogger->debug(sub{ "PrepareQuery $descr $cmd ( no query )"; }); |
return undef; |
} |
} |
sub ExecQuery(@){ |
my $sth; |
if(defined $_[1]){ |
if($sth = PrepareQuery(@_)){ |
$sth->execute(); |
} |
}else{ # se $_[1] è undef allora $_[2] è la query ed i campi successivi sono i parametri |
my $descr = shift; |
shift; |
my $query = shift; |
my $schema = $m->scomp('SELF:SCHEMA'); |
if($schema ne 'public' && $query !~ m/SET\s+search_path\s+TO\s+/is){ |
$query = "SET search_path TO $schema, public;\n$query"; |
} |
$sth = $Session{Dbh}->prepare($query); |
my $rows = $sth->execute(@_); |
if($PLogger->is_debug){ |
if($query =~ m/\n/s){ |
$query =~ s/\n/\n \| /sg; |
$PLogger->debug("ExecQuery $descr with [".Array2List(@_)."] query:{\n | $query\n |}."); |
}else{ |
$PLogger->debug("ExecQuery $descr with [".Array2List(@_)."] query:[$query]"); |
} |
# }else{ |
# $PLogger->info(sub{ "ExecQuery $descr result rows:$rows." }); |
} |
} |
return $sth; |
} |
# check sintassi clausola where fornita dal client |
# |
# Utilizzo le keyword dichiarate nel parser SQL::Parser |
use SQL::Dialects::ANSI; |
my $check_where_clause_dialect = SQL::Dialects::ANSI->get_config_as_hash; |
# parser |
use HOP::Lexer 'string_lexer'; |
sub check_where_clause($){ |
my $sql = shift; |
#DEBUG $PLogger->debug("check_where_clause($sql)"); |
# List authorized keyword |
my %authorized_keywords = map { uc $_, 1 } Method2Array 'AUTHORIZED_KEYWORDS'; |
# List keywords |
# $check_where_clause_dialect->{reserved_words} & $check_where_clause_dialect->{valid_commands} |
# Authorized operators |
my %authorized_operators = map { uc $_, 1 } Method2Array 'AUTHORIZED_OPERATORS'; |
# List Operators |
my %forbidden_operators = %{$check_where_clause_dialect->{valid_comparison_operators}}; |
$forbidden_operators{'~*'} = 1; |
$forbidden_operators{ILIKE} = 1; |
$forbidden_operators{NOT} = 1; |
# List authorized field |
my %authorized_fields = map { $_, 1 } Method2Array 'AUTHORIZED_FIELDS'; |
# ai campi senza indicazione della tabella vanno aggiunti i campi completi di nome della tabella |
my $table = $m->scomp('SELF:FROM'); |
foreach my $field (keys %authorized_fields){ |
if($field !~ m/\./){ |
my $new_field = $table.'.'.$field; |
if(!exists $authorized_fields{$new_field}){ |
$authorized_fields{$new_field} = 1; |
} |
} |
} |
# List authorized function |
my %authorized_functions = map { uc $_, 1 } Method2Array 'AUTHORIZED_FUNCTIONS'; |
my @tokens = ( |
[ 'COMMENT', qr/--/ ], |
[ 'CR', qr/\n/ ], |
[ 'STR_DELIM', qr/'/ ], |
[ 'CAST', qr/\:\:\w+/ , sub {[]} ], |
[ 'FIELD_DELIM', qr/"[a-zA-Z][\w\.]*"/, sub { |
my($label, $value) = @_; |
$value =~ s/^"|"$//g; |
[ $label, $value ] |
}], |
[ 'FUNCTION', qr/[a-zA-Z][\w\.]*\s*\(/ ], |
[ 'FIELD', qr/[a-zA-Z][\w\.]*/ ], |
[ 'COMMAS', qr/[,;]/ ], |
[ 'P_UP', qr/\(/ ], |
[ 'P_DOWN', qr/\)/ ], |
[ 'NUMBER', qr/[\-\d\.]+/ ], |
[ 'RETURN', qr/\n/ ], |
[ 'SPACE', qr/\s+/ ], |
[ 'OTHER', qr/.*/ ] |
); |
#DEBUG $PLogger->debug(sub{ "LEXING [$sql]" }); |
my $lexer = string_lexer($sql, @tokens); |
# ad ogni chiamata $lexer ritorna il token successivo |
my $level = 0; # livello delle parantesi |
my $in_comment = 0; # ==1 quando il parser attraversa un commento (che inizia con -- fino a fine riga) |
my $in_string = 0; # ==1 quando il parser attraversa una stringa delimitata da "'" |
my $curr_string; # contiene il valore della stringa corrente |
while ( my $token = $lexer->() ) { |
my($name, $value) = @{$token}; |
#DEBUG $PLogger->debug(sub{ "\tLEXER $name: [$value]\n" }); |
if($in_comment){ |
if($name eq 'CR'){ |
$in_comment = 0; |
} |
}else{ |
if($in_string){ |
if($name eq 'STR_DELIM'){ |
$in_string = 0; |
} |
}else{ |
if($name eq 'COMMENT'){ |
$in_comment = 1; |
}elsif($name eq 'STR_DELIM'){ |
$in_string = 1; |
} |
}#in_string |
}#in_comment |
next if($in_string or $in_comment); |
my $uc_value = uc $value; |
#DEBUG $PLogger->debug(sub{ "\t\tEXAMINE $name: [$value]\n" }); |
if($name eq 'FUNCTION'){ |
$value =~ s/\s*\($//; |
my $uc_value = uc $value; |
next if($authorized_functions{$uc_value}); |
next if($authorized_keywords{$uc_value}); |
if($check_where_clause_dialect->{reserved_words}{$uc_value}){ |
die "Utilizzo della parola riservata '$value' non autorizzato\n"; |
} |
if($check_where_clause_dialect->{valid_commands}{$uc_value}){ |
die "Utilizzo della parola riservata '$value' non autorizzato\n"; |
} |
next if($authorized_operators{$uc_value}); |
if($forbidden_operators{$uc_value}){ |
die "Utilizzo dell'operatore '$value' non autorizzato\n"; |
} |
die "Utilizzo della funzione '$value' non autorizzato\n"; |
}elsif($name eq 'OTHER'){ |
next if($authorized_operators{$uc_value}); |
die "Utilizzo della parola sconosciuta '$value' non autorizzato\n"; |
}elsif($name eq 'FIELD_DELIM'){ |
next if($authorized_fields{$value}); |
die "Utilizzo del campo '\"$value\"' non autorizzato\n"; |
}elsif($name eq 'FIELD'){ |
next if($authorized_fields{$value}); |
next if($authorized_keywords{$uc_value}); |
if($check_where_clause_dialect->{reserved_words}{$uc_value}){ |
die "Utilizzo della parola riservata '$value' non autorizzato\n"; |
} |
if($check_where_clause_dialect->{valid_commands}{$uc_value}){ |
die "Utilizzo del comando '$value' non autorizzato\n"; |
} |
next if($authorized_operators{$uc_value}); |
if($forbidden_operators{$uc_value}){ |
die "Utilizzo dell'operatore '$value' non autorizzato\n"; |
} |
die "Utilizzo del campo '$value' non autorizzato\n"; |
} |
}#while lexer |
} |
# genera una clausola where dalla struttura array inviata dal client |
# arr_where = array query |
# check == true viene fatto il check nelle porzioni SQL (--were....) |
sub Json2SqlWhere { |
my($arr_where, $check) = @_; |
my @and_clauses; |
foreach my $par (@$arr_where){ |
my $key = $par->[0]; |
if($key =~ m/^--where/i){ |
my $query = $par->[1]; |
$query =~ s/^\s*where\s*//i; |
if(length $query){ |
if($check){ |
&check_where_clause($query); |
} |
push @and_clauses, $query; |
} |
}elsif($key =~ m/^--or/i){ |
push @and_clauses, '('.&Json2SqlWhere($par->[1]).' OR '.&Json2SqlWhere($par->[2]).')'; |
}else{ |
my(undef, $op, $value, $type, $elem) = @$par; |
if(!defined $elem){ |
$elem = $key; |
} |
if($elem !~ m/^[\w_]+$/){ |
# complex field (eg. field->>'subfield') |
$elem = "($elem)"; |
} |
if(defined $type && !$type =~ m/^[\w ]+$/){ |
die "Type '$type' in Json2SqlWhere function not authorized!\n"; |
} |
if(defined $value){ |
$value =~ s/'/''/gs; |
if($type eq 'timestamp' && $value !~ m/\s\d\d:\d\d$/){ |
# timestamp senza orario |
if($op eq '='){ |
push @and_clauses, "(${elem}::timestamp >= '$value 00:00:00'::timestamp AND $elem <= '$value 23:59:59.9999999'::timestamp)"; |
}elsif($op eq '>' || $op eq '<='){ |
push @and_clauses, "${elem}::timestamp $op '$value 23:59:59.9999999'::timestamp"; |
}elsif($op eq '<' || $op eq '>='){ |
push @and_clauses, "${elem}::timestamp $op '$value 00:00:00'::timestamp"; |
}else{ |
push @and_clauses, "${elem}::timestamp $op '$value'::timestamp"; |
} |
}else{ |
if($op eq '~*' || $op eq 'LIKE' || $op eq 'ILIKE'){ |
push @and_clauses, "${elem}::text $op '$value'::text"; |
}else{ |
if(defined $type){ |
# force field cast |
push @and_clauses, "${elem}::$type $op '$value'::$type" |
}else{ |
push @and_clauses, "$elem $op '$value'" |
} |
} |
} |
}else{ |
# valore non definito |
if($op eq '='){ |
push @and_clauses, "$elem IS NULL"; |
}elsif($op eq '!=' || $op eq '<>'){ |
push @and_clauses, "$elem IS NOT NULL"; |
} |
} |
} |
} |
return join(' AND ', @and_clauses); |
} |
# query di selezione |
sub SqlWhere($){ |
my $Params = shift; |
my $arr_where = []; |
if($Params->{json_where}){ |
$arr_where = from_json($Params->{json_where}); |
}else{ |
# costruzione della condizione where ricercando tra i parametri |
# i campi corrispondenti "FIND_<nome_campo>" |
my @names = &Method2Array('FIELDS'); |
my @where; |
for(my $C=0; $C<@names; $C++){ |
my $name = $names[$C]; |
if(defined $Params->{'FIND_'.$name}){ |
my $value = $Params->{'FIND_'.$name}; |
$value =~ s/\s+$//; |
$value =~ s/^\s+//; |
if($value ne ''){ |
push @where, "$name $value"; |
} |
} |
} |
if(@where){ |
push @$arr_where, [ '--where', join(' and ', @where) ]; |
} |
} |
return $m->scomp('SELF:EVAL_WHERE', arr_where => $arr_where); |
} |
# combina più condizioni where in una unica condizione "where ........ and ......... and .........." |
sub Combine_WhereClauses(@){ |
my $WHERE = ''; |
# tolgo un livello di parentesi |
while(@_){ |
my $where = shift; |
# tolgo spazi all'inizio ed alla fine |
$where =~ s/^\s+//; |
$where =~ s/\s+$//; |
$where =~ s/^where\s+//i; |
# tolgo un livello di parentesi |
$where =~ s/^\s*\(\s*(.*)\s*\)\s*$/$1/; |
$where =~ s/where\s+$//i; |
if($where){ |
$WHERE .= $WHERE ? " and ( $where )" : "( $where )"; |
} |
#DEBUG $PLogger->debug(sub{ "WHERE [$where][$WHERE]"; }); |
} |
return $WHERE ? 'where '.$WHERE : ''; |
} |
# Inizializza la tabella report_id con gli identificativi dei record da stampare |
# ritorna group_id da passare come parametro al report di stampa |
# |
# Initializes the report_id table with the IDs of the records to be printed. |
# Returns group_id and report_ids to be passed as parameters to the print report. |
# The returned parameter group_id contains a GROUP_ID value. |
# The returned parameter report_ids contains a reference to an array of REPORT_ID values. |
sub SqlSelect2report_id($){ |
my $Params = shift; |
my $group_id = NewGroupId(); |
if(defined $Params->{reportlist}){ |
return Array2report_idSql($group_id, $Params->{reportlist}); |
} |
# produco l'elenco dei record da stampare con la query del recordset corrente |
$Params->{type} = 'records'; |
# elenco degli ID da inserire |
# valutazione clausola where |
my $WHERE = EvalSqlWhere(undef, $Params); |
my $sth = ExecQuery('SqlSelect2report_id select', 'SELF:SELECT_REPORTS', WHERE => $WHERE); |
my $reports = $sth->fetchall_arrayref; |
$SQL{MAX_ROWS} = @{$reports}; |
#DEBUG $PLogger->debug(sub{ "SQL{MAX_ROWS}=".$SQL{MAX_ROWS}; }); |
#DEBUG $PLogger->debug(sub{ "reports=".Dumper($reports); }); |
my @report_ids = (); |
foreach my $report (@{$reports}){ |
ExecQuery('SqlSelect2report_id insert', 'SELF:INSERT_REPORTS', REPORT_ID => $report->[0], GROUP_ID => $group_id); |
push(@report_ids, $report->[0]); |
} |
if($Session{Dbh}->commit){ |
return ($group_id, \@report_ids); |
} |
return (undef, undef); |
} |
# valutazione della clausola Where da usare nella select dei record |
# con verifica dei permessi di accesso al padre, se dichiarato |
sub SqlSelectWhere { |
my($Params, $father_id) = @_; |
# father_id = -1 è usato nell'inserimento per individuare un insieme vuoto |
# -2 è usato in frame.html per il parametro 'pk' |
my @queries; |
# valuto se la tabella ha un padre |
my $father_name = $m->scomp('SELF:FATHER_NAME'); |
# valuto se ho il campo chiave della tabella padre |
$father_id = defined $father_id ? $father_id : $Params->{father_id}; |
if(length $father_name && !length $father_id){ |
die "No father_id param with father $father_name from ".$m->scomp('SELF:FROM')."\n"; |
}elsif(length $father_name && length($father_id) && $father_id >0 ){ |
# Se il record padre non è presente nella cache |
if(!RecordsetCache($father_name, 'check_key', $father_id)){ |
# verifico che il padre sia leggibile (altrimenti non autorizzo modifiche e cancellazioni dei figli) |
my $father_path = $father_name; |
$father_path =~ s|\.|/|; |
$father_path = $r->dir_config('DataBaseUrl').'/'.$father_path.'.mql'; |
# verifico i diritti di accesso all'oggetto padre |
my $father_permission = Permission(undef, $father_path); |
if(!$father_permission->{Select}){ |
die "No father retrieve permission from ".$m->scomp('SELF:FROM')."\n"; |
} |
my @father_queries; |
push @father_queries, $m->scomp($father_path.':WHERE'); |
my $father_key_name = $m->scomp('SELF:FATHER_TABLE_KEY_NAME'); |
push @father_queries, $father_key_name.' = '.encodeSql($father_id); |
my $sth = ExecQuery('check father retrieve record ', $father_path.':NUMREC', WHERE => Combine_WhereClauses(@father_queries)); |
if(!$sth->fetchrow_arrayref->[0]){ |
die "No father record retrieve id:$father_id from ".$m->scomp('SELF:FROM')."\n"; |
} |
} |
# aggiungo la condizione per selezionare solo i record figli |
#DEBUG $PLogger->debug(sub{ 'Record padre ',$father_name,'(',$m->scomp('SELF:FATHER_WHERE', FATHER_ID => $father_id),')'; }); |
push @queries, $m->scomp('SELF:FATHER_WHERE', FATHER_ID => $father_id); |
} |
if($father_id == -2){ |
# -2 è usato in frame.html per il parametro 'pk' |
$father_id = undef; |
} |
# aggiungo la condizione per selezionare solo i record con le "primary key" elencate |
my $key_list = $Params->{key_list}; |
if(length $key_list){ |
# lista di chiavi |
my $KEY = $m->scomp('SELF:KEY'); |
my @keys = split ',', $key_list; |
push @queries, $KEY.'='.join(' or '.$KEY.'=', map(encodeSql($_), @keys)); |
} |
# valutazione clausola where |
return EvalSqlWhere(\@queries, $Params); |
} |
# esegue la query selezionando il range indicato |
sub SqlSelect($$$){ |
my($select, $select_fields_method, $Params) = @_; |
my $select_fields = $m->scomp('SELF:'.$select_fields_method); |
my $start = $Params->{start}; |
my $rows = $Params->{rows}; |
my $KEY = $m->scomp('SELF:KEY'); |
# elenco delle chiavi dei record da inserire nel recordset |
my @RecordList = (); |
$Params->{recordset_list} = \@RecordList; |
if($Params->{father_id} == -1){ |
# ritorno un elenco vuoto |
$SQL{START}=0; |
$SQL{ROWS}=0; |
$SQL{MAX_ROWS}=0; |
$SQL{LAST_WHERE}=''; |
return ExecQuery('father_id is not defined', 'SELF:'.$select, FIELDS => $select_fields, WHERE => 'where false'); |
} |
if($Params->{type} eq 'update' && $SQL{UPDATE_LIST}){ |
# Imposto il recordset con i campi oggetto di modifica ed inserimento. |
# Come start metto la stessa posizione |
my $update_list = $SQL{UPDATE_LIST}; |
$SQL{ROWS} = @$update_list; |
$SQL{MAX_ROWS} = $Params->{max_rows} + $SQL{DIFF_RECORDS}; |
$SQL{START} = $Params->{start}; |
my $last; |
my $QUERY; |
my $query = "SELECT $KEY, $select_fields". |
' FROM '.$m->scomp('SELF:SCHEMA_FROM')." WHERE $KEY = "; |
foreach my $key (@$update_list){ |
$QUERY .= $query.encodeSql($key).' UNION ALL '; |
} |
$QUERY =~ s/ UNION ALL $//; |
if($SQL{ROWS} == 1){ |
$SQL{LAST_WHERE} = "WHERE $KEY = " . encodeSql($update_list->[0]); |
} |
# se è richiesto un update ma con la restituzione di un record con chiave diversa non devo ritornare |
# lo stesso record aggiornato |
my $find_key = $Params->{find_key}; |
if(!$find_key || $find_key eq $KEY){ |
$Params->{recordset_list} = $update_list; |
my $sth = ExecQuery('select with updated records', undef, $QUERY); |
$SQL{ROWS} = $sth->rows; |
return $sth; |
} |
} |
if($m->base_comp->method_exists('PRE_SELECT')){ |
$m->scomp('SELF:PRE_SELECT', PARAMS => $Params); |
} |
# elaborazione del recordset normale ... |
my $WHERE = $Params->{SelectWhere} ? $Params->{SelectWhere} : $Params->{SelectWhere} = SqlSelectWhere($Params); |
# espressione SQL (id = key1 or id = key2 ...) |
my $RecordList; |
my $ORDER; |
# quanti record sono presenti? |
my $numrec; |
my $sth; |
if($Params->{RecordsetCache}){ |
# utilizzo il numero dichiarato nella cache |
$numrec = RecordsetCache($Params->{name}, 'numrec'); |
}else{ |
# ricavo il numero dei record del recordset |
my $sth = ExecQuery('numrec', 'SELF:NUMREC', WHERE => $WHERE); |
$numrec = $sth->fetchrow_arrayref->[0]; |
} |
# aggiusto il record di inizio nel caso sia passata dal client una etichetta |
# di posizione, anzichè la posizione numerica |
if($start eq 'forward'){ |
# in fondo |
$start = $numrec-$SQL{MAX_ROWS}; |
}elsif($start eq 'insert'){ |
# oltre il fondo |
$start = $numrec+1-int($SQL{MAX_ROWS}/2); |
}elsif(!defined $start){ |
$start = 0; |
} |
$SQL{MAX_ROWS} = $numrec; |
# aggiusto i range minimi e massimi all'interno del range reale del recordset |
if($start < 0){ |
$start = 0; |
} |
if($rows =~ m/^\d+$/){ |
# se il numero di righe è un dato fornito procedo con l'individuazione |
# dell'elenco |
# find_key se presente, definisce un particolare id record che va ricercato |
# nel recordset indicato in modo che venga ritornato un range di record che |
# lo contenga in posizione centrale |
my $find_key = $Params->{find_key}; |
if(!defined $find_key){ |
$find_key = undef; |
} |
if(!$find_key){ # utilizzo LIMIT e OFFSET nella query |
# verifico i limiti per $rows all'interno del range di record |
# realmente presenti nel recordset |
if($start > $numrec){ |
$start = $numrec; |
$rows = 0; |
} |
if($rows > $numrec-$start){ |
$rows = $numrec-$start; |
} |
if($rows < 0){ |
$rows = 0; |
} |
# con find_key non definito posso recuperare i dati utilizzando i costrutti del linguaggio SQL LIMIT e OFFSET |
$SQL{START} = $start; |
$SQL{ROWS} = $rows; |
if($rows>0){ |
if($Params->{RecordsetCache}){ |
# è attiva la gestione dei recordset persistenti sul server |
# quindi verifico se il range di righe richieste è già presente nella cache |
if(!RecordsetCache($Params->{name}, 'list', \@RecordList, $Params->{rows}, $rows, $start)){ |
# è stato annullato il recordset persistente e a causa di un record recuperato ma già presente in cache e pertanto è necessario riformulare la query |
if($Params->{recordset} ne 'new'){ |
# invio un messaggio di allerta all'utente |
RecordsetCache($Params->{name}, 'alert'); |
} |
return &SqlSelect('SELECT', 'SELECT_FIELDS', $Params); |
} |
$ORDER = ''; |
}else{ |
$sth = ExecQuery('records', 'SELF:RECORDS', WHERE => $WHERE, LIMIT => "limit $rows", OFFSET => "offset $start"); |
while(my $row = $sth->fetchrow_arrayref){ |
push @RecordList, $row->[0]; |
} |
$ORDER = $m->scomp('SELF:ORDER_BY'); |
} |
} |
}else{ |
# find key |
# nel caso della ricerca si ignora il parametro 'start'. |
#Nel caso il record non venisse individuato, viene ritornato il recordset in fondo |
if($rows <= 0){ |
$SQL{START} = 0; |
$SQL{ROWS} = @RecordList = (); |
}else{ |
if($Params->{RecordsetCache}){ |
# individuo la posizione del record indicato nel recordset |
my $pos_key = RecordsetCache($Params->{name}, 'find_key', $find_key); |
if(defined $pos_key){ |
# chiave presente; mi posiziono a 1/2 |
$start = $pos_key - int($rows/2); |
#DEBUG print STDERR "chiave presente; mi posiziono a 1/2 - pos_key:$pos_key rows:$rows start:$start\n"; |
}else{ |
# chiave non presente; mi posiziono in fondo al recordset |
$start = $numrec - $rows; |
} |
if($start < 0){ |
$start = 0; |
} |
if($start + $rows > $numrec){ |
$start = $numrec - $rows; |
if($start < 0){ |
$start = 0; |
$rows = $numrec; |
} |
} |
if(!RecordsetCache($Params->{name}, 'list', \@RecordList, $Params->{rows}, $rows, $start)){ |
# è stato annullato il recordset persistente e a causa di un record recuperato ma già presente in cache e pertanto è necessario riformulare la query |
if($Params->{recordset} ne 'new'){ |
# invio un messaggio di allerta all'utente |
RecordsetCache($Params->{name}, 'alert'); |
} |
return &SqlSelect('SELECT', 'SELECT_FIELDS', $Params); |
} |
$SQL{START} = $start; |
$SQL{ROWS} = @RecordList |
}else{ |
$SQL{ROWS} = $rows; |
my $exist = 0; |
$sth = ExecQuery('records', 'SELF:RECORDS', WHERE => $WHERE); |
$ORDER = $m->scomp('SELF:ORDER_BY'); |
# cerco la posizione della chiave indicata |
my $count = 0; |
# scarto i record fino a trovare il record con chiave $find_key |
# mantenendo i precedenti $rows/2 o più record se in fondo al recordset |
while(my $row = $sth->fetchrow_arrayref){ |
$count++; |
# inserisco nello stack il nuovo record |
push @RecordList, $row->[0]; |
# svuoto lo stack se troppo pieno |
@RecordList > $rows && shift @RecordList; |
if($row->[0] eq $find_key){ |
$exist = $count; |
last; |
} |
} |
# se ho trovato un record con la chiave, allora potrebbero esserci |
# altri record da caricare, altrimenti ho esaurito l'elenco |
if($exist){ |
while(my $row = $sth->fetchrow_arrayref){ |
$count++; |
last if($count-$exist >= int($rows/2) && @RecordList >= $rows); |
push @RecordList, $row->[0]; |
@RecordList > $rows && shift @RecordList; |
} |
} |
# il record di partenza è la posizione della chiave trovata |
# altrimenti è in fondo al recordset (elenco vuoto) |
$SQL{START} = $exist ? $exist-1 : $numrec-@RecordList; |
$SQL{ROWS} = @RecordList; |
} |
} |
} |
# costruisco la clausola where di selezione dell'elenco |
if(@RecordList == 0){ |
# elenco vuoto |
$RecordList = 'false'; |
}elsif(@RecordList == 1){ |
# un solo record |
$RecordList = $KEY.'='.encodeSql($RecordList[0]); |
}elsif($r->dir_config('SqlWhereKeyListOr')){ |
# lista or |
$RecordList = "$KEY=".join(" or $KEY = ", map {encodeSql($_)} @RecordList); |
}else{ |
# lista in un insieme |
$RecordList = $KEY.' in ('.join(',', map(encodeSql($_), @RecordList)).')'; |
} |
# estraggo solo i record della lista |
$WHERE = "where ($RecordList)"; |
}else{ |
#DEBUG $PLogger->debug(sub{ "Non è stato fornito il numero di righe e quindi si ritorna l'intero recordset"; }); |
# se non viene fornito il numero di righe desiderato si ritorna |
# l'intero range di record presente in archivio |
$Params->{RecordsetCache} = undef; |
$SQL{START} = 0; |
$SQL{ROWS} = $numrec; |
$ORDER = $m->scomp('SELF:ORDER_BY'); |
} |
$SQL{LAST_WHERE} = $WHERE; |
$SQL{LAST_ORDER} = $ORDER; |
$sth = ExecQuery('select list', 'SELF:'.$select, FIELDS => $select_fields, WHERE => $WHERE, ORDER => $ORDER ); |
$SQL{ROWS} = $sth->rows; |
return $sth; |
} |
# recupera la lista delle chiavi dei record dalla cache del recordset, se presenti |
# altrimenti provvede a recuperare le righe mancanti |
# $recordset_id id del record persistente |
# $list array con l'elenco completo delle chiavi nel range richiesto |
# $records_query query SQL da utilizzare per recuperare le chiavi del recordset |
# $where clausola 'where' da usare assieme a $records_query |
# $limit_max numero di righe del blocco normalmente recuperato |
# $limit numero di righe da recuperare. <=$limit_max, limitato se $offset è in prossimità di $max |
# (è responsabilità del chiamante fornire un valore compatibile) |
# $offset posizione nel recordset (0==prima riga) |
# $max numero massimo di righe nel recordset |
# $dim_block dimensione del blocco di record da recuperare e salvare in cache |
sub getPersistentRecords { |
my($recordset_id, $list, $records_query, $where, $limit_max, $limit, $offset, $max, $dim_block) = @_; |
#DEBUG |
$PLogger->debug(sub{ "getPersistentRecords(recordset_id:$recordset_id limit:$limit offset:$offset limit_max:$limit_max max:$max query:'$records_query' where:'$where')"; }); |
# il numero di record da recuperare in una query sarà almeno di $dim_block record, oppure di 3 volte |
# il numero di record richiesto |
my $query_limit = $limit < $dim_block ? $dim_block : $limit * 3; |
#DEBUG $PLogger->debug(sub{ "\tquery_limit:$query_limit"; }); |
# prelevo dalla cache i record nel range specificato |
my $cache_sth = ExecQuery("Get records from cache id:$recordset_id", undef, q{ |
select num_row, id_record |
from public.recordset_rows |
where id_recordset = ? and num_row >= ? and num_row < ? |
order by num_row |
}, $recordset_id, $offset, $offset + $limit |
); |
my $num_rows = $cache_sth->rows; |
#DEBUG $PLogger->debug(sub{ "\tTrovati in cache $num_rows records"; }); |
# l'elenco potrebbe essere completo, incompleto o del tutto vuoto dato che in cache abbiamo |
# almeno il doppio dei record richiesti. Per questo motivo non avremo mai il caso di mancanza |
# di codici in mezzo ad un range di dati presenti in cache |
# controllo se il primo record corrisponde |
if($num_rows < $limit){ |
#DEBUG $PLogger->debug(sub{ "\talmeno un record è assente nella cache $num_rows < $limit"; }); |
# almeno un record è assente nella cache |
# verifico se manca all'inizio o alla fine del range ricercato |
my($num_row, $id_record) = $cache_sth->fetchrow_array; |
my $start = ( $num_row != $offset ? int($offset/$query_limit) : int(($offset+$limit-1)/$query_limit) ) * $query_limit; |
#DEBUG $PLogger->debug(sub{ "\tcalcolo start:$start = ($num_row != $offset ? int($offset/$query_limit) : int(($offset+$limit-1)/$query_limit) ) * $query_limit"; }); |
if(($start + $query_limit) > $max){ |
#DEBUG $PLogger->debug(sub{ "\tvero ($start + $query_limit) > $max"; }); |
# mi trovo nell'ultimo blocco della cache di dimensioni inferiori al blocco $query_limit |
if($query_limit < $max){ |
#DEBUG $PLogger->debug(sub{ "\tse c'è almeno un blocco di record di dimensione $query_limit < $max"; }); |
# se c'è almeno un blocco di record di dimensione $query_limit |
# verifico se ci sono record nel blocco precedente |
my $prev_sth = ExecQuery('Check previus range of records from cache', undef, q{ |
select id from public.recordset_rows |
where id_recordset = ? and num_row = ? |
}, $recordset_id, $start-1 |
); |
if($prev_sth->rows == 1){ |
# se sono già presenti recupero solo il blocco parziale |
$query_limit = $max - $start; |
#DEBUG $PLogger->debug(sub{ "\tgià presenti recupero solo il blocco parziale di $query_limit record da $start"; }); |
}else{ |
# altrimenti allargo il range aggiungendo al blocco parziale un ulteriore blocco intero |
$start -= $query_limit; |
$query_limit += $max - $start; |
#DEBUG $PLogger->debug(sub{ "\tassenti; allargo il range start:$start query_limit:$query_limit"; }); |
} |
}else{ |
#DEBUG $PLogger->debug(sub{ "\tnumero record ridotto; recupero solo il blocco parziale di $query_limit record da $start"; }); |
# numero record ridotto; recupero solo il blocco parziale |
$query_limit = $max - $start; |
} |
} |
# eseguo la query |
my $sth = ExecQuery('records', $records_query, WHERE => $where, LIMIT => "limit $query_limit", OFFSET => "offset $start"); |
if($sth->rows >= 1){ |
# preparo la query di inserimento |
my $insert_sth = $Session{Dbh}->prepare("insert into public.recordset_rows (id_recordset, num_row, id_record) values (?, ?, ?)"); |
while(my($id) = $sth->fetchrow_array){ |
#DEBUG $PLogger->debug(sub{ "\tinsert in cache rec:$id recordset:$recordset_id, start:$start"; }); |
# se il record fosse già presente devo provvedere ad svuotare la cache ed a ricalcolare il numero di record disponibili |
eval { $insert_sth->execute($recordset_id, $start, $id) }; |
if($@){ |
# controllo che l'errore non sia recorsivo |
if($Session{ARGS}->{conflict_on_load_records}){ |
$PLogger->warn("Recursive conflict on load records to cache id:$recordset_id"); |
die "Recursive conflict on load records to cache id:$recordset_id [[$@]]\n"; |
} |
$Session{ARGS}->{conflict_on_load_records} = 1; |
$PLogger->warn("Conflict on load records to cache id:$recordset_id [[$@]]"); |
# in caso di errore svuoto la cache |
$Session{Dbh}->commit; |
$sth = ExecQuery('Empty persistent recordset', undef, |
q{ |
delete from public.recordset_rows |
where id_recordset = ? |
}, |
$recordset_id |
); |
$Session{Dbh}->commit; |
return 0; |
} |
$start++; |
} |
$Session{Dbh}->commit; |
return getPersistentRecords($recordset_id, $list, $records_query, $where, $limit_max, $limit, $offset, $max, $dim_block); |
} |
} |
if($num_rows){ |
#DEBUG $PLogger->debug('\tinserisco i record nell\'elenco'); |
while(my($num_row, $id_record) = $cache_sth->fetchrow_array){ |
#DEBUG $PLogger->debug(sub{ "\tlist record $num_row: $id_record"; }); |
push @{$list}, $id_record; |
} |
} |
return 1; |
} |
# prepara la lista dei campi e la lista dei valori da utilizzare in una query |
# di inserimento o di aggiornamento |
sub fields_values($$){ |
my($type, $hash_fields) = @_; |
my @list = keys %$hash_fields; # array nomi dei campi della tabella |
if(!@list){ |
return undef; |
} |
if($type eq 'insert'){ |
my @values; |
my @sql_params; |
foreach my $key (@list){ |
# permit in PRE_INSERT method to redefine the assigment as a function, like 'insert ... (field) VALUES ((select x from y where id = ?)) |
my $val = $hash_fields->{$key}; |
if(ref $val eq 'ARRAY'){ |
push @sql_params, $val->[0]; |
for(my $C=1; $C<@$val; $C++){ |
my $value = $val->[$C]; |
# if the value is defined |
push @values, $value eq '' ? undef : $value; |
} |
}else{ |
push @sql_params, '?'; |
push @values, $val eq '' ? undef : $val; |
} |
} |
# restituisco la lista dei nomi, dei ?,... e la lista dei nuovi valori |
return join(',', @list), join(',', @sql_params), \@values; |
}elsif($type eq 'update'){ |
my @values; |
my @sql_params; |
foreach my $key (@list){ |
my $val = $hash_fields->{$key}; |
if(ref $val eq 'ARRAY'){ |
# permit in PRE_UPDATE method to redefine the assigment as a function, like 'field=field || ?::json' |
push @sql_params, $key.'='.$val->[0]; |
for(my $C=1; $C<@$val; $C++){ |
my $value = $val->[$C]; |
push @values, $value eq '' ? undef : $value; |
} |
}else{ |
push @sql_params, $key.'=?'; |
push @values, $val eq '' ? undef : $val; |
} |
} |
# restituisco la lista "field1=?, field2=?, ..." e la lista dei nuovi valori |
return join(',', @sql_params), \@values; |
}else{ |
return undef; |
} |
} |
# verifica la relazione esterna (vedi ENTITY_RELATIONS) |
sub check_related_table($$$){ |
my($relation, $key, $field) = @_; |
my($tablename, $keyname) = split /\s*\:\s*/, $relation, 2; |
if($tablename != /\./){ |
# se lo schema non è dichiarato uso lo schema del padre |
$tablename = $m->scomp('SELF:SCHEMA').'.'.$tablename; |
} |
# verifico i permessi della tabella collegata |
my $table_path = $tablename; |
$table_path =~ s|\.|/|; |
$table_path = $r->dir_config('DataBaseUrl').'/'.$table_path.'.mql'; |
my $table_permission = Permission(undef, $table_path); |
if(!$table_permission->{Select}){ |
die "No related '$tablename' retrieve permission\n"; |
} |
if(!defined $keyname){ |
# se la chiave non è dichiarata utilizzo la chiave primaria della tabella |
$keyname = $m->scomp($table_path.':KEY'); |
} |
# verifico se il record nella tabella collegata è leggibile |
my @table_queries; |
push @table_queries, $m->scomp($table_path.':WHERE'); |
push @table_queries, $keyname.' = '.encodeSql($key); |
my $sth = ExecQuery("check related '$tablename' retrieve record ", $table_path.':NUMREC', WHERE => Combine_WhereClauses(@table_queries)); |
if(!$sth->fetchrow_arrayref->[0]){ |
die "No related '$tablename' record retrieve $field:$key relation:$relation\n"; |
} |
} |
# aggiorna i dati passati in $array |
sub Array2UpdateSql($$){ |
my($data, $Params)=@_; |
my $father_id_update = $Params->{father_id_update}; |
my $father_id_name = $m->scomp('SELF:FATHER_ID_NAME'); |
my $father_id = $Params->{father_id}; |
my $schema_from = $m->scomp('SELF:SCHEMA_FROM'); |
# se dichiarato il padre deve essere dichiarato anche l'identificatore del padre |
if(!length $father_id_update && length $father_id_name){ |
die("No father_id param with father $father_id_name from $schema_from\n"); |
} |
if(length $father_id_name && $father_id_update == -1){ |
die "No father_id == -1\n"; |
} |
my $KEY = $m->scomp('SELF:KEY'); |
my $key_name = $m->scomp('SELF:KEY_NAME'); |
my @names = &Method2Array('FIELDS'); |
my @nw = &Method2Array('FIELDS_NO_WRITE'); |
# verifica dei diritti di accesso al padre |
# query di verifica dei diritti di accesso (anche del padre in quanto SqlSelectWhere effettua la verifica se è dichiarato il padre) |
my $where = SqlSelectWhere($Params, $father_id_update); |
if($nw[0] eq '*'){ |
@nw = @names; |
} |
# array contenente le key(id) dei record modificati ed inseriti |
my @id; |
# se abilitato ... |
my $permission = Permission(); |
# relazioni da verificare: i campi in relazione con altre tabelle devono contenere chiavi di oggetti accessibili all'utente |
my %entity_relations = method2hash('ENTITY_RELATIONS'); |
# usata per passare a POST_UPDATES i parametri eventualmente definiti |
# nelle varie chiamate a PRE/POST_INSERT/UPDATE |
my %PARAMS; |
# in $data abbiamo la matrice dei dati da aggiornare; costruisco la query di aggiornamento |
for(my $pos=0; $pos<@$data; $pos++){ |
my %params; # per passare parametri tra i metodi PRE/POST_INSERT/UPDATE, ..., POST_UPDATES |
my $row = $data->[$pos]; |
my $insert_with_key; |
# se hash viene fornita la chiave per l'inserimento (rif. method retrieve) |
if(ref($row->[0]) eq 'ARRAY'){ |
# tolgo l'array |
$row->[0] = $row->[0]->[0]; |
$insert_with_key = 1; |
} |
my $id = $row->[0]; |
if($insert_with_key){ |
my $key = $row->[0]; |
if($key == -1){ |
die "No key == -1\n"; |
} |
# verifico che la chiave non sia già presente |
my $sth = ExecQuery('check exists for insert', undef, q{ |
select count(*) from }.$schema_from.qq{ where $KEY = ? |
}, $key); |
if($sth->fetchrow_arrayref->[0] > 0){ |
die "Key already used\n"; |
} |
# verifico che la chiave non sia maggiore della sequenza |
my $serial_seq = $m->scomp('SELF:SERIAL_SEQ'); |
$sth = ExecQuery('check sequence for insert', undef, qq{ |
select last_value from $serial_seq; |
}); |
my $last_value = $sth->fetchrow_arrayref->[0]; |
if($key > $last_value){ |
die "Key greater last key\n"; |
} |
}elsif(length $id){ |
if($id == -1){ |
die "No key == -1\n"; |
} |
# verifico se i record possono essere letti (altrimenti non è certamente concesso di poterli anche modificare) |
# se è presente in cache non serve verificare ulteriormente |
if(!$Params->{RecordsetCache} || !RecordsetCache($Params->{name}, 'check_key', $id)){ |
my @queries; |
push @queries, $where; |
push @queries, $KEY.' = '.encodeSql($id); |
my $sth = ExecQuery('check record for update', 'SELF:NUMREC', WHERE => Combine_WhereClauses(@queries)); |
if(!$sth->fetchrow_arrayref->[0]){ |
$Session{StatusCode} = 404; |
die "No record permission or record not exists\n"; |
} |
} |
} |
if(!defined $id || $id eq '' || $insert_with_key){ |
if(!$permission->{Insert}){ |
die "No insert permission\n"; |
} |
if($father_id_update && !$father_id_name){ |
die("No FATHER_ID_NAME in this table\n"); |
} |
# la funzione KeyArray2String aggiunge in fondo all'elenco dei valori la chiave del record da cui la riga è stata duplicata |
my $dup_key = $row->[@$row-1]; |
# hash contenente i nuovi valori da inserire |
my %fields_insert; |
if($insert_with_key){ |
# se la chiave viene fornita provvedo a inserirla nella query di inserimento |
$fields_insert{$key_name} = $id; |
} |
# inserimento; manca l'identificatore del record |
for(my $i=0; $i<@names; $i++){ |
my $name = $names[$i]; |
# verifico se il campo è da escludere (FIELDS_NO_WRITE) |
my $rw=1; |
foreach my $val (@nw){ |
if($name eq $val){ |
$rw=0; |
last; |
} |
} |
# applico il filtro sullo specifico campo se definito |
# Attenzione a lasciare $_ !!! |
$_ = Call_InFieldFilter($name, $row->[0], $row->[$i+1]); |
if($rw){ |
# tolgo dal nome l'eventuale nome tabella "tabella.campo" |
$name =~ s/^\w+\.//; |
if(length){ |
# se si tratta di un campo in relazione con una tabella esterna |
my $relation = $entity_relations{$name}; |
if(defined $relation){ |
check_related_table($relation, $_, $name); |
} |
} |
$fields_insert{$name} = $_; |
} |
} |
# valuto se la tabella è di tipo "DETAIL" |
if($father_id_name && length($father_id_update)){ |
# aggiungo anche il valore del campo 'father_id_update' se presente |
# eliminando dal nome del campo la tabella, ma solo se corrisponde al nome della tabella nella quale si effettua l'inserimento |
my $from = $schema_from; |
$from =~ s/^.*\.//; |
if($father_id_name =~ m/^$from\.(.*)$/){ |
$father_id_name = $1; |
} |
$fields_insert{$father_id_name} = $father_id_update; |
} |
if(keys %fields_insert){ |
# eseguo il metodo di pre insert se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('PRE_INSERT')){ |
$m->scomp('SELF:PRE_INSERT', FIELDS_INSERT => \%fields_insert, DUP_KEY => $dup_key, PARAMS => \%params); |
} |
# PRE_INSERT può aver cambiato %fields_insert |
my($fields, $values, $list_values) = fields_values('insert', \%fields_insert); |
if($fields){ |
my $sth = PrepareQuery('insert', 'SELF:INSERT', |
FIELDS =>$fields, |
NEW_KEY => $id, |
FIELDS_INSERT => \%fields_insert, |
VALUES => $values, |
LIST_VALUES => $list_values, |
PARAMS => \%params |
); |
if($sth){ |
#DEBUG $PLogger->debug(sub{ 'execute(', ListJscript($list_values, 'null', 'array2list'),')' }); |
$sth->execute(@{$list_values}); |
if(!defined $id || $id eq ''){ |
# recupero l'id del nuovo record inserito |
$id = $sth->fetchrow_arrayref->[0]; |
push @id, $id; |
} |
# log inserimento nuovo record |
DB_log('insert', $id, \%fields_insert); |
# incremento il contatore dei record nuovi e cancellati |
$SQL{DIFF_RECORDS}++; |
push @id, $id; |
# eseguo il metodo di post insert se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('POST_INSERT')){ |
$m->scomp("SELF:POST_INSERT", KEY => $id, DUP_KEY => $dup_key, ROW => $row, FIELDS_INSERT => \%fields_insert, PARAMS => \%params); |
} |
} |
}elsif($m->base_comp->method_exists('POST_NO_INSERT')){ |
$m->scomp("SELF:POST_NO_INSERT", KEY => $id, DUP_KEY => $dup_key, ROW => $row, PARAMS => \%params); |
} |
} |
if($Params->{RecordsetCache} && $id){ |
# se ho i riferimenti al record padre attivi ma non coincidenti non devo |
# aggiungere al recordset permanente il nuovo record in quanto il record |
# inserito appartiene al recordset figlio precedente (caso spostamento |
# nel recordset padre con recordset figlio in modifica) |
if(!$father_id_update || !$father_id || |
( $father_id_update && $father_id && $father_id_update eq $father_id) |
){ |
# aggiungo in coda alla cache il nuovo record |
RecordsetCache($Params->{name}, 'append', $id); |
} |
} |
}else{ |
if(!$permission->{Update}){ |
die "No update permission\n"; |
} |
# modifica ... |
push @id, $id; |
# aggiornamento |
my %fields_update; |
for(my $C=0; $C<@names; $C++){ |
my $name = $names[$C]; |
# verifico se il campo è da escludere (FIELDS_NO_WRITE) |
my $rw=1; |
foreach my $val (@nw){ |
if($name eq $val){ |
$rw=0; |
last; |
} |
} |
# applico il filtro sullo specifico campo se definito |
# Attenzione a lasciare $_ !!! |
$_ = Call_InFieldFilter($name, $row->[0], $row->[$C+1]); |
if($rw){ |
if(defined){ |
# tolgo dal nome l'eventuale nome tabella "tabella.campo" |
$name =~ s/^\w+\.//; |
if(length){ |
# se si tratta di un campo in relazione con una tabella esterna |
my $relation = $entity_relations{$name}; |
if(defined $relation){ |
check_related_table($relation, $_, $name); |
} |
} |
$fields_update{$name} = $_; |
} |
} |
} |
if(keys %fields_update){ |
# eseguo il metodo di pre update se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('PRE_UPDATE')){ |
$m->scomp("SELF:PRE_UPDATE", KEY => $id, FIELDS_UPDATE => \%fields_update, PARAMS => \%params); |
} |
# PRE_UPDATE può aver cambiato %fields_update |
my($fields_values, $list_values) = fields_values('update', \%fields_update); |
if($fields_values){ |
if($m->base_comp->method_exists('DELETE_IF_FIELD_EMPTY')){ |
my $field = $m->scomp('SELF:DELETE_IF_FIELD_EMPTY'); |
if(exists $fields_update{$field} && (!defined $fields_update{$field} || $fields_update{$field} eq 'null')){ |
if($m->base_comp->method_exists('PRE_DELETE')){ |
$m->scomp('SELF:PRE_DELETE', KEY => $id, PARAMS => \%params); |
} |
ExecQuery('delete because join-field is empy', 'SELF:DELETE', KEY => $id, PARAMS => \%params); |
# log cancellazione record |
DB_log('delete', $id, undef); |
$fields_values = undef; |
} |
} |
} |
if($fields_values){ |
my $sth = PrepareQuery('update', 'SELF:UPDATE', KEY => $id, |
UPDATES => $fields_values, |
LIST_VALUES => $list_values, |
FIELDS_UPDATE => \%fields_update, |
PARAMS => \%params |
); |
if($sth){ |
DB_log('update', $id, \%fields_update); |
#DEBUG $PLogger->debug(sub{ 'execute(', ListJscript($list_values, 'null', 'array2list'),")"; }); |
$sth->execute(@{$list_values}); |
# eseguo il metodo di post update se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('POST_UPDATE')){ |
$m->scomp("SELF:POST_UPDATE", KEY => $id, ROW => $row, FIELDS_UPDATE => \%fields_update, PARAMS => \%params); |
} |
} |
}else{ |
# eseguo il metodo di post no update |
if($m->base_comp->method_exists('POST_NO_UPDATE')){ |
$m->scomp("SELF:POST_NO_UPDATE", KEY => $id, ROW => $row, PARAMS => \%params); |
} |
} |
} |
} |
# hash dei parametri |
$PARAMS{$id} = \%params; |
} |
#DEBUG print STDERR "TEST BrowserAlert".$Session{ARGS}->{BrowserAlert}; |
if($m->base_comp->method_exists('POST_UPDATES')){ |
$m->scomp("SELF:POST_UPDATES", KEYS => \@id, PARAMS => \%PARAMS); |
} |
# POST_UPDATES potrebbe aver annullato la transazione ponendo @id = undef o array vuoto |
if(@id && $Session{Dbh}->commit){ |
# se la transazione di modifica/inserimento è andata a buon fine fornisco l'elenco dei record modificati/inseriti |
return \@id; |
} |
return undef; |
} |
# determino un nuovo group_id da utilizzare |
sub NewGroupId(){ |
my $query = $r->dir_config('PrintNextValQuery') || "select nextval('public.report_id_id_seq')"; |
my $sth = ExecQuery('NewGroupId', undef, $query); |
return $sth->fetchrow_arrayref->[0]; |
} |
# Inserisce in report_id i record i cui identificatori (id) sono passati in $array |
# ritorna group_id |
# |
# Inserts an array of REPORT_ID values from the input into the publi.report_id table. |
# The inserted values are indentified by common group_id. |
# |
# Returns group_id and report_ids to be passed as parameters to the print report. |
# The returned parameter group_id contains a GROUP_ID value. |
# The returned parameter report_ids contains a reference to an array of REPORT_ID values. |
sub Array2report_idSql($$){ |
my($group_id, $arr)=@_; |
my $report_ids=my_eval($arr); |
# in $report_ids abbiamo il vettore degli ID da inserire |
# determino un nuovo group_id da utilizzare |
$PLogger->debug(sub{ "Array2report_idSql group_id = $group_id list = $arr"; }); |
$SQL{DIFF_RECORDS}-=@$report_ids; |
my $sth = PrepareQuery('insert Array2report_idSql', undef, "insert into public.report_id (group_id, key) values (?, ?)"); |
foreach my $id (@$report_ids){ |
$sth->execute($group_id, $id); |
} |
if($Session{Dbh}->commit){ |
return ($group_id, $report_ids); |
} |
return (undef, undef); |
} |
# cancella i record i cui identificatori (id) sono passati in $array |
sub Array2DeleteSql($){ |
my($Params)=@_; |
my $num_rec_deleted = 0; |
# se abilitato alla cancellazione |
my $permission = Permission(); |
if($permission->{Delete}){ |
my $data = my_eval($Params->{delete}); |
# in $data abbiamo il vettore dei dati da cancellare |
$SQL{DIFF_RECORDS}-=@$data; |
foreach my $id (@$data){ |
my %params; # per il passaggio di parametri tra DELETE e POST_NO_DELETE |
if($m->base_comp->method_exists('PRE_DELETE')){ |
$m->scomp('SELF:PRE_DELETE', KEY => $id, PARAMS => \%params); |
} |
my $sth = ExecQuery('delete', 'SELF:DELETE', KEY => $id, PARAMS => \%params); |
if($sth){ |
$num_rec_deleted++; |
# log cancellazione record |
DB_log('delete', $id, undef); |
# eseguo il metodo di post delete se dichiarato nel metodo ___.mql |
if($m->base_comp->method_exists('POST_DELETE')){ |
$m->scomp("SELF:POST_DELETE", KEY => $id, PARAMS => \%params); |
} |
if($Params->{RecordsetCache}){ |
# elimino dalla cache il record cancellato |
RecordsetCache($Params->{name}, 'delete', $id); |
} |
}elsif($m->base_comp->method_exists('POST_NO_DELETE')){ |
$m->scomp("SELF:POST_NO_DELETE", KEY => $id, PARAMS => \%params); |
} |
} |
if($Session{Dbh}->commit){ |
return $num_rec_deleted; |
} |
} |
return undef; |
} |
# elabora l'out di un componente realizzando una lista degli elementi separati da ',' aggiungendo gli apici ai campi testo |
sub ListJscript($$$){ |
my($comp, $null, $type)=@_; |
my $out =''; |
if($type =~ m/list/){ |
# l'alternativa è il caso array2list |
my @names = $type eq 'list' || $type eq 'method2list' ? &Method2Array($comp) : @{$comp}; |
#DEBUG $PLogger->debug(sub{ "ListJscript [".$m->scomp($comp)."]'$comp''$null''$type' ====", Dumper(\@names); }); |
for(my $col=0; $col<@names; $col++){ |
my $val = $names[$col]; |
$val =~ s/^\s+//; |
$val =~ s/\s+$//; |
$val =~ s/\\$//; |
$val =~ s/'/\\'/; |
$val =~ s/\n/\\n/; |
$out .= str2sql_js_delimited($val, $null).','; |
} |
$out =~ s/,$//; |
}elsif($type eq 'scalar'){ |
$out = $m->scomp($comp); |
$out =~ s/'/\\'/; |
$out =~ s/\n/\\n/; |
$out = str2sql_js_delimited($out, $null).','; |
} |
return $out |
} |
# valuta l'espressione sql Where sia dal metodo $where_method che dall'eventuale parametro where passato |
sub EvalSqlWhere($$){ |
my($queries, $Params) = @_; |
if(!defined $queries){ |
$queries = []; |
} |
# valuto la condizione where impostata nell'oggetto |
push @$queries, $m->scomp('SELF:WHERE'); |
# valuto la condizione where che proviene dal client (parametro 'json_where') |
push @$queries, SqlWhere($Params); |
# valuto la condizione WHERE finale |
my $WHERE = Combine_WhereClauses(@$queries); |
# completo la condizione con la clausola 'where' solo se ci sono presenti delle condizioni |
if($WHERE =~ m/^\s*where\s*$/i){ |
$WHERE = ''; |
} |
return $WHERE; |
} |
# genera codice Jscript per inizializzare l'elenco di campi |
sub Fields_JList($$$$){ |
my($Recordset, $names, $list, $array) = @_; |
my @lst = &Method2Array($list); |
my $cols = @{$names}; |
if($lst[0] eq '*'){ |
$m->out(qq|for(var J=0; J<$cols; J++){$Recordset.$array\[J] = true;}\n|); |
}else{ |
# creo la hash dei campi indicati nella lista |
my %ro; |
for(my $col=0; $col<@lst; $col++){ |
$ro{$lst[$col]} = 1; |
} |
my $str = "$Recordset.$array = ["; |
for(my $J=0; $J<$cols; $J++){ |
$str .= $ro{$names->[$J]} ? 'true,' : 'false,'; |
} |
$str =~ s/,$//; |
$m->out($str."];\n"); |
} |
} |
# genera codice Jscript per inizializzare l'elenco dei campi |
# - in sola lettura |
# - in sola lettura in aggiornamento (tipico dei campi chiave) |
sub Fields_RO($$){ |
my($Recordset, $names)=@_; |
&Fields_JList($Recordset, $names, 'FIELDS_RO', 'fields_ro'); |
&Fields_JList($Recordset, $names, 'FIELDS_RO_UPDATE', 'fields_ro_update'); |
} |
sub FieldFilter_from($$$$$$){ |
my($base_comp, $field, $key, $value, $names, $fetch_row) = @_; |
# verifico se il dato è presente in cache parametri |
my $cache = $Session{Fields_params}; |
my $key_cache = $base_comp->path."|$field|$value"; |
if(exists $cache->{$key_cache}){ |
return $cache->{$key_cache}; |
} |
my $widget = $m->fetch_comp(Field_Component($field, $base_comp, $base_comp->path)); |
my $param; |
my $tablename = $widget->attr_if_exists('select_from'); |
if($tablename eq '?'){ |
if($base_comp->method_exists("${field}_FROM")){ |
$tablename = $m->scomp("SELF:${field}_FROM", field => $field, key => $key, value => $value, names => $names, fetch_row => $fetch_row); |
#DEBUG $PLogger->debug(sub{ "FieldFilter_from with tablename:? and ${field}_FROM:$tablename"; }); |
}else{ |
die "Il metodo SELF:${field}_FROM non è definito\n"; |
} |
} |
if($tablename){ |
if($tablename !~ m|/|){ |
# tabella nello stesso schema del padre |
$tablename = $m->scomp('SELF:SCHEMA').'/'.$tablename; |
} |
# devo attivare il filtro specifico per il componente che prevede l'invio |
# di parametri aggiuntivi separati dal carattere speciale '|' |
my $table_comp = $m->fetch_comp($r->dir_config('DataBaseUrl').'/'.$tablename.'.mql'); |
if(!$table_comp){ |
die "Rif. (select_from => '$tablename') non esistente nel componente ".$base_comp->path."\n"; |
} |
my $sql = $table_comp->scall_method('SELECT', ID => $value); |
#DEBUG $PLogger->debug(sub{ "FieldFilter_from id:$value SELECT sql='$sql'".Dumper($Session{ARGS}); }); |
if($sql =~ m/^\s*$/s){ |
die "ERROR select_from from:$Session{ARGS}->{name} field:$field key:$key value:$value\n\tLa query è nulla\n"; |
} |
my $sth = ExecQuery("select_from from:$Session{ARGS}->{name} field:$field key:$key value:$value SELECT", undef, $sql); |
if($sth->rows > 0){ |
# formato p1|p2|p3|... |
my @fields = $sth->fetchrow_array; |
shift @fields; |
$param = join('|', @fields); |
# salvo in cache il parametro, dovesse essere richiesto nella stessa sessione |
$cache->{$key_cache} = $param; |
}else{ |
$cache->{$key_cache} = undef; |
} |
} |
#DEBUG $PLogger->debug(sub{ "FieldFilter_from select_from '$value'"; }); |
return $param |
} |
# applica il filtro del campo in uscita, se definito |
# ritorna una array con due campi (valore, parametro) |
# $field nome del campo |
# $key valore della chiave primaria del record |
# $value valore del campo |
# $names array dei nomi dei campi del record |
# $fetch_row hash dei valori dei campi del record |
# $comp componente (.mql) se non definito si utilizza il componente di base |
# $noparam se 1 non recupera i parametri (usato per ottimizzare nei casi in cui non sono utilizzati) |
sub Call_OutFieldFilter { |
my($field, $key, $value, $names, $fetch_row, $comp, $noparam) = @_; |
#DEBUG $PLogger->debug(sub{"Call_OutFieldFilter(field:$field, key:$key, value:$value"}); |
if(!$comp){ |
$comp = $m->base_comp; |
} |
my $param; |
if(!$noparam && length $value){ |
# valuto gli attributi del widget utilizzato |
$param = FieldFilter_from($comp, $field, $key, $value, $names, $fetch_row); |
} |
my $filter = $field.'_OUT_FILTER'; |
if($comp->method_exists($filter)){ |
#DEBUG $PLogger->debug(sub{ "Call_OutFieldFilter('$filter', '$key', '$value')"; }); |
my $func = $comp->scall_method($filter, Key => $key, Value => $value, names => $names, fetch_row => $fetch_row, noparam => $noparam); |
#DEBUG $PLogger->debug(sub{ "[$func]"; }); |
$_ = $value; |
# Nel codice del filtro la variabile $param potrebbe essere modificata !!! |
eval $func; |
$value = $_; |
#DEBUG $PLogger->debug(" to [$_]"); |
if($@) { |
die "ERROR: Call_OutFieldFilter('$filter', '$key', '$value'): $@\n"; |
} |
} |
#DEBUG $PLogger->debug(sub{ "Call_OutFieldFilter value:$value, param:$param" }); |
return ($value, $param); |
} |
# applica il filtro del campo, se definito |
sub Call_InFieldFilter($$$){ |
my($field, $key, $value) = @_; |
my $filter = $field.'_IN_FILTER'; |
if($m->base_comp->method_exists($filter)){ |
###DEBUG $PLogger->debug(sub{ "Call_InFieldFilter('$filter', '$key', '$value')"; }); |
my $func = $m->base_comp->scall_method($filter, Key => $key, Value => $value); |
###DEBUG $PLogger->debug(sub{ "[$func]"; }); |
$_ = $value; |
eval $func; |
$value = $_; |
###DEBUG $PLogger->debug(sub{ " to [$_]"; }); |
if($@) { |
die "ERROR: Call_InFieldFilter('$filter', '$key', '$value'): $@\n"; |
} |
} |
return $value; |
} |
# verifica se è definito il metodo <nome>_CHECK |
# e restituisce il nome del componente da utilizzare per il check |
sub Exist_Check($){ |
my $name = shift; |
# tolgo dal nome l'eventuale prefisso del nome della tabella |
$name =~ s/.+\.//; |
my $new_name; |
# verifico se esiste un campo alias il quale punti ad un componente esistente |
if($m->base_comp->method_exists($name.'_ALIAS')){ |
my $alias = $m->scomp('SELF:'.$name.'_ALIAS'); |
if($m->base_comp->method_exists($alias.'_CHECK')){ |
$new_name = 'SELF:'.$alias.'_CHECK'; |
} |
}elsif($m->base_comp->method_exists($name.'_CHECK')){ |
$new_name = 'SELF:'.$name.'_CHECK'; |
} |
#DEBUG $PLogger->debug(sub{ "Exist_Check '$name' -> '$new_name'"; }); |
return $new_name; |
} |
# restituisce il nome del componente da utilizzare per il campo |
sub Field_Component { |
my($name, $base_comp, $base_name) = @_; |
if(!$base_comp){ |
$base_comp = $m->base_comp; |
} |
if(!$base_name){ |
$base_name = 'SELF'; |
} |
# tolgo dal nome l'eventuale prefisso del nome della tabella |
$name =~ s/.+\.//; |
my $new_name; |
# verifico se esiste un campo alias il quale punti ad un componente esistente |
if($base_comp->method_exists($name.'_ALIAS')){ |
my $alias = $m->scomp($base_name.':'.$name.'_ALIAS'); |
if($base_comp->method_exists($alias.'_FIELD')){ |
$new_name = $base_name.':'.$alias.'_FIELD'; |
}else{ |
# altrimenti utilizzo il componente generico |
$new_name = $base_name.':STANDARD_FIELD'; |
} |
# verifico se esiste il componente <campo>_FIELD specifico |
}elsif($base_comp->method_exists($name.'_FIELD')){ |
$new_name = $base_name.':'.$name.'_FIELD'; |
}else{ |
# altrimenti utilizzo il componente generico |
$new_name = $base_name.':STANDARD_FIELD'; |
} |
#DEBUG $PLogger->debug(sub{ "Field_Component '$name' -> '$new_name'"; }); |
return $new_name; |
} |
# restituisce il nome del componente da utilizzare per il campo di ricerca |
sub Find_Component { |
my($name, $type) = @_; |
my $component; |
# tolgo dal nome l'eventuale prefisso del nome della tabella |
$name =~ s/.+\.//; |
# se esiste un componente specifico |
if($m->base_comp->method_exists($name.'_FIND_FIELD')){ |
return 'SELF:'.$name.'_FIND_FIELD'; |
} |
# componente generico |
my $standard_field = $type =~ m/^bool/i ? 'SELF:BOOL_FIND_FIELD' : 'SELF:STANDARD_FIELD'; |
# |
# verifico se esiste un campo alias che fornisce il nome di un componente esistente |
if($m->base_comp->method_exists($name.'_FIND_ALIAS')){ |
my $alias = $m->scomp('SELF:'.$name.'_FIND_ALIAS'); |
if($m->base_comp->method_exists($alias.'_FIELD')){ |
return 'SELF:'.$alias.'_FIELD'; |
}else{ |
$PLogger->warn(sub{ "WARNING: Il campo alias '${alias}_FIELD' dichiarato in ${name}_FIND_ALIAS' non è definito!"; }); |
return $standard_field; |
} |
# verifico se esiste un alias del campo |
}elsif($m->base_comp->method_exists($name.'_ALIAS')){ |
my $alias = $m->scomp('SELF:'.$name.'_ALIAS'); |
return Find_Component($alias, $type); |
# verifico se esiste il componente <campo>_FIELD specifico |
}elsif($m->base_comp->method_exists($name.'_FIELD')){ |
return 'SELF:'.$name.'_FIELD'; |
}else{ |
# altrimenti utilizzo il componente generico |
return $standard_field; |
} |
} |
# individua un array di selettori per le ricerche |
sub findSelectList($$){ |
my($comp, $type) = @_; |
if($comp->attr_exists('find_select_list')){ |
return $comp->attr('find_select_list'); |
}else{ |
if($type =~ m/int|numeric|real|double|decimal|serial/i){ |
return [ '=' => '=', '<' => '<', '<=' => '<=', '>' => '>', '>=' => '>=','!=' => '!=']; |
}elsif($type =~ m/date|timestamp|time/i){ |
return ['=' => '=', '<' => '<', '<=' => '<=', '>' => '>', '>=' => '>=','!=' => '!=']; |
}elsif($type =~ m/bool/i){ |
return [ '!=' => 'si', '=' => 'no']; |
}else{ |
return ['~*' => '~*', '=' => '=', '!=' => '!=', 'ilike' => 'ilike']; |
} |
} |
} |
# funzioni per la gestione del recordset permanente |
# alla chiamata provvede a creare il recordset per l'utente corrente |
sub RecordsetCache { |
my $Name = shift; |
my $Method = shift; |
#DEBUG print STDERR "RecordsetCache $Name method $Method params:[", join(',', @_),"]\n"; |
$PLogger->debug(sub{ "RecordsetCache $Name method $Method params:[", join(',', @_),"]"; }); |
# recupero i riferimenti del recordset |
my $Recordset = $Session{ARGS}->{RecordsetCache}->{$Name}; |
if(!$Recordset){ |
$Recordset = $Session{ARGS}->{RecordsetCache}->{$Name} = { Name => $Name }; |
} |
if($Recordset->{Disabled}){ |
return undef; |
} |
if(!defined $Session{Session_id}){ |
die "Session ID not defined\n"; |
} |
#DEBUG $PLogger->debug(sub{ "\t", Dumper($Recordset); }); |
if(!$Recordset->{Id}){ |
my $sth = ExecQuery("Select persistent recordset '$Name'", undef,q{ |
select id, size, block, query_numrec, query_records, query_find_records, query_where |
from public.recordset where name = ? and id_session = ? |
},$Name, |
$Session{Session_id} |
); |
my $row = $sth->fetchrow_arrayref; |
$Recordset->{Id} = $row ? $row->[0] : undef; |
if($Recordset->{Id}){ |
$Recordset->{Size} = $row ? $row->[1] : undef; |
$Recordset->{Block} = $row ? $row->[2] : undef; |
$Recordset->{Numrec} = $row ? $row->[3] : undef; |
$Recordset->{Records} = $row ? $row->[4] : undef; |
$Recordset->{Find_records} = $row ? $row->[5] : undef; |
$Recordset->{Where} = $row ? $row->[6] : undef; |
}else{ |
# dimensione del blocco di chiavi da copiare nella cache |
$Recordset->{Block} = 0 + $m->scomp('SELF:DIM_BLOCK_CACHE'); |
if($Recordset->{Block} > 0){ |
# solo se la dimensione del blocco della cache è maggiore di zero, abilito la gestione del recordset persistente |
# creo quindi un recordset persistente vuoto |
$sth = ExecQuery("Create persistent recordset '$Name'", undef, |
q{ |
insert into public.recordset (name, id_session, size, block) values (?, ?, null, ?); |
select currval('public.recordset_id_seq'); |
}, $Name, $Session{Session_id}, $Recordset->{Block}); |
$Session{Dbh}->commit; |
$Recordset->{Id} = $sth->fetchrow_arrayref->[0]; |
$Recordset->{Size} = undef; |
}else{ |
# gestione recordset disabilitata |
$Recordset->{Disabled} = 1; |
return undef; |
} |
} |
} |
if($Method eq 'new'){ |
$Recordset->{Numrec} = shift; |
$Recordset->{Records} = shift; |
$Recordset->{Find_records} = shift; |
$Recordset->{Where} = shift; |
# calcolo il numero dei record del recordset |
my $sth = ExecQuery("numrec '$Name'", $Recordset->{Numrec}, WHERE => $Recordset->{Where}); |
my $numrec = $sth->fetchrow_arrayref->[0]; |
# aggiorno nella cache i nuovi dati |
# e svuoto il recordset |
ExecQuery("Set new recordset '$Name'", undef, q{ |
update recordset |
set size = ?, query_numrec = ?, query_records = ?, query_find_records = ?, query_where = ? |
where id = ?; |
delete from public.recordset_rows |
where id_recordset = ?; |
}, $numrec, |
$Recordset->{Numrec}, |
$Recordset->{Records}, |
$Recordset->{Find_records}, |
$Recordset->{Where}, |
$Recordset->{Id}, |
$Recordset->{Id}); |
$Session{Dbh}->commit; |
$Recordset->{Size} = $numrec; |
}elsif($Method eq 'cache'){ |
# verifico che il recordset sia effettivamente in cache |
if(!exists $Recordset->{Size}){ |
$PLogger->warn(sub{ "RecordsetCache '$Name' not in cache"; }); |
# richiamo il metodo 'new' |
return RecordsetCache($Name, $Method, 'new', @_); |
} |
}elsif($Method eq 'numrec'){ |
#DEBUG// $PLogger->debug(sub{ "Return Size:$Recordset->{Size}"; }); |
return $Recordset->{Size}; |
}elsif($Method eq 'list'){ |
my($list, $limit_max, $limit, $offset) = @_; |
return getPersistentRecords($Recordset->{Id}, $list, $Recordset->{Records}, |
$Recordset->{Where}, $limit_max, $limit, $offset, |
$Recordset->{Size}, $Recordset->{Block}); |
}elsif($Method eq 'alert'){ |
BrowserAlert("E\' stato necessario ricalcolare la selezione dei record di ${Name}!\n". |
"Pertanto l'ordine potrebbe non essere identico a quello della selezione\n". |
"precedente, in quanto essa dipende dai record modificati nel fattempo."); |
}elsif($Method eq 'append'){ |
# verifico che il record non sia già presente nella cache |
my $sth = ExecQuery("Check key in recordset '$Name'", undef, q{ |
select num_row from public.recordset_rows |
where id_recordset = ? and id_record = ? |
}, $Recordset->{Id}, $_[0] |
); |
if($sth->rows){ |
#record presente; ritorno la posizione [1..N] |
return 1 + $sth->fetchrow_arrayref->[0]; |
}else{ |
# aggiungo in coda alla cache il nuovo record |
# e aggiorno il numero dei record |
ExecQuery("Append key to recordset '$Name'", undef, q{ |
insert into public.recordset_rows |
(id_recordset, num_row, id_record) values (?, ?, ?); |
update recordset set size = size+1 where id = ? |
}, $Recordset->{Id}, $Recordset->{Size}, $_[0], |
$Recordset->{Id} |
); |
$Recordset->{Size}++; |
$Session{Dbh}->commit; |
return $Recordset->{Size}; |
} |
}elsif($Method eq 'replace'){ |
my $delete; |
# sostituisco una chiave con un'altra |
# se la chiave da sostituire è già presente cancello la chiave in più |
my $sth= ExecQuery("Find records from recordset '$Name'", undef, q{ |
select id from public.recordset_rows |
where id_recordset = ? and id_record = ?; |
}, $Recordset->{Id}, $_[1] |
); |
if($sth->rows){ |
# c'è un record da cancellare |
RecordsetCache($Name, 'delete', $_[1]); |
$delete=1; |
} |
ExecQuery("Replace record in recordset '$Name'", undef, q{ |
update public.recordset_rows |
set id_record = ? where id_recordset = ? and id_record = ? |
}, $_[1], $Recordset->{Id}, $_[0] |
); |
$Session{Dbh}->commit; |
return $delete; |
}elsif($Method eq 'delete'){ |
# elimino dalla cache il record indicato |
# e aggiorno il numero dei record |
my $sth_c = ExecQuery("Delete records from recordset '$Name'", undef, q{ |
update public.recordset_rows |
set num_row = num_row-1 |
where id_recordset = ? and num_row > ( |
select num_row from public.recordset_rows |
where id_recordset = ? and id_record = ? |
); |
delete from public.recordset_rows |
where id_recordset = ? and id_record = ?; |
update recordset set size = size-1 where id = ?; |
select size from recordset where id = ?; |
}, $Recordset->{Id}, $Recordset->{Id}, $_[0], |
$Recordset->{Id}, $_[0], |
$Recordset->{Id}, |
$Recordset->{Id} |
); |
$Session{Dbh}->commit; |
$Recordset->{Size} = $sth_c->fetchrow_arrayref->[0]; |
}elsif($Method eq 'reset'){ |
# svuoto la cache |
ExecQuery("Delete all records from recordset_rows '$Name'", undef, q{ |
delete from public.recordset_rows |
where id_recordset = ?; |
}, $Recordset->{Id} |
); |
$Session{Dbh}->commit; |
}elsif($Method eq 'check_key'){ |
# cerco nel recordset la posizione del record con key == $_[0] |
#DEBUG $PLogger->debug(sub{ "RecordsetCache ".Dumper($Recordset); }); |
if(!$_[0]){ |
die "ERRORE: chiamata RecordsetCache($Recordset->{Find_records}, 'check_key' con parametro key nullo"; |
} |
# verifico se la chiave e' presente nella cache |
my $sth_check_cache = ExecQuery("Check record from cache '$Name'", undef, q{ |
select num_row from public.recordset_rows |
where id_record = ? |
and id_recordset = ?; |
}, $_[0], $Recordset->{Id}); |
my($row) = $sth_check_cache->fetchrow_array; |
return defined $row; |
}elsif($Method eq 'find_key'){ |
# cerco nel recordset la posizione del record con key == $_[0] |
#DEBUG $PLogger->debug(sub{ "RecordsetCache ".Dumper($Recordset); }); |
if(!$_[0]){ |
die "ERRORE: chiamata RecordsetCache($Recordset->{Find_records}, 'find_key' con parametro key nullo"; |
} |
# verifico se la chiave e' presente nella cache |
my $sth_find_cache = ExecQuery("Find record from cache '$Name'", undef, q{ |
select num_row from public.recordset_rows |
where id_record = ? |
and id_recordset = ?; |
}, $_[0], $Recordset->{Id}); |
my($row) = $sth_find_cache->fetchrow_array; |
if(!defined $row){ |
# se non e' presente nella cache cerco la chiave nell'intero recordset |
my $sth_find = ExecQuery("Find record from recordset '$Name'", $Recordset->{Find_records}, |
KEY => $_[0], WHERE => $Recordset->{Where}, RECORDS => $Recordset->{Records}); |
($row) = $sth_find->fetchrow_array; |
} |
return $row; |
}else{ |
die "recordset persistente: parametro recordset '$Method' sconosciuto\n"; |
} |
return $Recordset; |
} |
sub str2nbsp($){ |
$_ = shift; |
$_ = $_ ? $m->interp->apply_escapes($_, 'h') : ' '; |
s/\s/\ /gs; |
return $_; |
} |
# log modifiche al database |
# $type - tipo dell'aggiornamento |
# $id - identificativo del record |
# %{$fields} - hash dati modificati, inseriti o cancellati |
# %{$old_fields} - hash dati prima della modifica (opzionale) |
# $table_name - nome tabella (opzionale) |
sub DB_log { |
my($type, $id, $fields, $old_fields, $table_name) = @_; |
# nome dell'oggetto/tabella per i log |
if(!$table_name){ |
$table_name = $m->scomp('SELF:LOG_TABLE_NAME'); |
} |
$table_name =~ s/^\s+|\s+$//g; |
# se non definito un nome il log è disabilitato |
if(!$table_name){ |
return; |
} |
if($type eq 'delete'){ |
$Session{Logs}->execute($Session{User_id}, $table_name, $id, undef, $id, undef); |
}elsif($type eq 'insert'){ |
$Session{Logs}->execute($Session{User_id}, $table_name, $id, undef, undef, $id); |
foreach my $field (keys %{$fields}){ |
if(length($fields->{$field}) > 0){ |
$Session{Logs}->execute($Session{User_id}, $table_name, $id, $field, undef, $fields->{$field}); |
} |
} |
}elsif($type eq 'update'){ |
if(!defined $old_fields){ |
# devo recuperare i valori attuali da inserire in %{$old_fields} |
# i nomi dei campi nella hash %$fields sono privi del riferimento alla |
# tabella che invece è eventualmente presente nel metodo SELF:FIELD |
my $table_comp = $table_name; |
$table_comp =~ s/\./\//; |
my @names = &Method2Array($r->dir_config('DataBaseUrl')."/$table_comp.mql:FIELDS"); |
foreach my $field (@names){ |
if($field =~ m/^(\w+)\.(\w+)$/ && exists $fields->{$2}){ |
# sostituisco il nome del campo con il nome completo di |
# riferimento della tabella |
$fields->{$field} = $fields->{$2}; |
delete $fields->{$2}; |
} |
} |
my $FIELDS = join ', ', keys(%{$fields}); |
my $sth = ExecQuery('DB_log:old value', 'SELF:SELECT', ID => $id, FIELDS => $FIELDS); |
$old_fields = $sth->fetchrow_hashref; |
} |
foreach my $field (keys %{$fields}){ |
if($old_fields->{$field} ne $fields->{$field}){ |
$Session{Logs}->execute($Session{User_id}, $table_name, $id, $field, $old_fields->{$field}, $fields->{$field}); |
} |
} |
}else{ |
die "Error: DB_log. type '$type' mismatch\n"; |
} |
} |
sub ReportMethod($){ |
my $report = shift; |
my $method = ''; |
if($report && $report =~ /\.(\w+)$/){ |
my $suffix = $1; |
if($suffix =~ /(odt|pdf|rep)/i){ |
$method = lc $suffix; |
}else{ |
die "Unknown report suffix '.$suffix'"; |
} |
}elsif($r->dir_config('DefaultReportEngine')){ |
my $engine = $r->dir_config('DefaultReportEngine'); |
if($engine =~ /^(odt|pdf|rep)$/i){ |
$method = lc $1; |
}else{ |
die "Unknown DefaultReportEngine '$engine'"; |
} |
}else{ |
die "DefaultReportEngine is not defined"; |
} |
$PLogger->debug(sub{ "ReportMethod method='$method'"; }); |
return $method; |
} |
sub FindReportmanFile($){ |
my $report = shift; |
$PLogger->debug(sub{ "FindReportmanFile report=$report"; }); |
my $base = $r->dir_config('DataBaseUrl'); |
my $report_file = ''; |
unless($r->dir_config('ReportmanADOserver')){ |
# utilizzo la versione Kylix di Reportman che utilizza i driver con i dati di connessione al database nei file di configurazione |
$report_file = request_to_comp_path("$base/$report.rep"); |
# verifico che il file sia presente o se ha percorso nel framework |
unless(-e $report_file){ |
$report_file = request_to_comp_path("$base/$report.kylix.rep"); |
unless(-e $report_file){ |
return ('', "ERRORE: il report '$report' non esiste [$base/$report.rep oppure $base/$report.kylix.rep]"); |
} |
} |
}else{ |
# utilizzo la versione Windows di Reportman con il driver ADO che incorpora la stringa di connessione |
my $report_in = request_to_comp_path("$base/$report.rep"); |
if(-e $report_in){ |
$report_file = $report; |
$report_file =~ s|/|_|g; |
$report_file = $r->dir_config('TmpDir').'/'.$report_file.'.rep'; |
# verifico che il file sia presente |
}else{ |
$report_file = request_to_comp_path("$base/$report.wine.rep"); |
unless(-e $report_file){ |
return ('', "ERRORE: il report '$report' non esiste [$base/$report.rep oppure $base/$report.wine.rep]"); |
} |
} |
} |
$PLogger->debug(sub{ "FindReportmanFile report_file=$report_file"; }); |
return ($report_file, ''); |
} |
sub CheckIfReportExists($){ |
my $table = shift; |
my @print_form = &Method2Array($table.':PRINT_FORM'); |
#DEBUG $PLogger->debug(sub{ "CheckIfReportExists table=$table"; }); |
#DEBUG $PLogger->debug(sub{ "CheckIfReportExists print_form: ".Dumper(\@print_form); }); |
my $report = shift @print_form; |
$PLogger->debug(sub{ "CheckIfReportExists report=$report"; }); |
my $report_method = ReportMethod($report); |
my $report_exists = 0; |
if($report_method eq 'odt' || $report_method eq 'pdf'){ |
my $odtrpt_name = $report =~ s/\//\./r; |
#DEBUG $PLogger->debug(sub{ "CheckIfReportExists odt_rpt_name=$odtrpt_name"; }); |
my $sth = ExecQuery('', undef, "select name from public.odt_reports where odt_reports.name = '$odtrpt_name';"); |
if($sth->fetchrow_hashref){ |
$report_exists = 1; |
} |
}elsif($report_method eq 'rep'){ |
my ($report_file, $die_msg) = FindReportmanFile($report); |
$PLogger->debug(sub{ "CheckIfReportExists report_file=$report_file, die_msg=$die_msg"; }); |
if($report_file && -e $report_file){ |
$report_exists = 1; |
} |
} |
$PLogger->debug(sub{ "CheckIfReportExists report_exists=$report_exists"; }); |
return $report_exists; |
} |
# valutazione dei permessi |
# Parametri: |
# permission_group: gruppo/gruppi a cui si deve essere autorizzati (scalare o array ref) |
# table: tabella per la quale si determinano i permessi |
sub Permission { |
my $permission_group = shift; |
my $table = @_ ? shift : 'SELF'; |
my $permission; |
my $base_comp = $table eq 'SELF' ? $m->base_comp : $m->fetch_comp($table); |
$base_comp || die "Object $table not existent\n"; |
my $hash_perm = 'PermHash_'.$base_comp->path; |
if(exists $Session{$hash_perm}){ |
$permission = $Session{$hash_perm}; |
}else{ |
my %permission = ( Archive => 0, Dbms => 0, Insert => 0, Update => 0, Select => 0, Delete => 0, Print => 0, Printsel => 0, Xls => 0, Log => 0); |
my $method = $base_comp->method_exists('PERMISSION') ? 'PERMISSION' : 'PERMISSION_BY_PROFILE'; |
my @permission = &Method2Array("$table:$method", '\s*[\s,]\s*'); |
@permission || die "Method $method return empy permission list\n"; |
if($permission[0] eq '*'){ |
# Attivo tutti i permessi |
@permission = keys %permission; |
} |
my $report_exists = CheckIfReportExists($table); |
foreach my $perm (@permission){ |
$perm = ucfirst lc $perm; |
if(($perm ne 'Print' && $perm ne 'Printsel') || $report_exists){ |
$permission{$perm} = 1; |
#DEBUG $PLogger->debug(sub{ "permission($perm)=1"; }); |
} |
} |
$permission = \%permission; |
if($method ne 'PERMISSION'){ |
# abilito la cache solo se NON è definito il metodo PERMISSION |
# (usato nell'applicazione per alterare i permessi) |
$Session{$hash_perm} = $permission; |
} |
} |
if($permission_group){ |
if(!ref($permission_group)){ |
$permission_group = [ $permission_group ]; |
} |
foreach my $group (@$permission_group){ |
if(!$permission->{$group}){ |
$Session{StatusCode} = 403; |
die "No $group permission\n"; |
} |
} |
} |
return $permission; |
} |
# conversione campo data nel formato adatto per l'esportazione in formato Excel |
sub dateXls($){ |
$_ = shift; |
# gg/mm/yyyy |
if(m|^(\d\d)/(\d\d)/(\d\d\d\d)$|){ |
#DEBUG die "gg/mm/yyyy $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$3-$2-$1T", 0); |
}elsif(m|^(\d\d)/(\d\d)/(\d\d\d\d)[\sT](\d\d):(\d\d):(\d\d)$|){ |
#DEBUG die "gg/mm/yyyy hh:mm:ss $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$3-$2-$1T$4:$5:$6.000", 1); |
}elsif(m|^(\d\d)/(\d\d)/(\d\d\d\d)[\sT](\d\d):(\d\d):(\d\d)\.(\d+)$|){ |
#DEBUG die "gg/mm/yyyy hh:mm:ss.sss $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$3-$2-$1T$4:$5:$6.$7", 2); |
}elsif(m|^(\d\d\d\d)-(\d\d)-(\d\d)$|){ |
#DEBUG die "yyyy-mm-dd $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$1-$2-$3T", 0); |
}elsif(m|^(\d\d\d\d)-(\d\d)-(\d\d)[\sT](\d\d):(\d\d):(\d\d)$|){ |
#DEBUG die "yyyy-mm-dd hh:mm:ss $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$1-$2-$3T$4:$5:$6.000", 1); |
}elsif(m|^(\d\d\d\d)-(\d\d)-(\d\d)[\sT](\d\d):(\d\d):(\d\d)\.(\d+)$|){ |
#DEBUG die "yyyy-mm-dd hh:mm:ss.sss $_ to $1|$2|$3|$4|$5|$6|$7"; |
return ("$1-$2-$3T$4:$5:$6.$7", 2); |
}else{ |
#DEBUG die "$_ to undef"; |
return (undef, undef); |
} |
} |
</%once> |
<%method DATA_URI><%perl> |
# URI del file <DataBaseUrl>/<schema</<table>.mql |
my $name = $m->base_comp->path; |
$name =~ s/\.mql$//; |
$name = substr $name, 1 + length $r->dir_config('DataBaseUrl'); |
$name =~ s/\./_/gs; |
$name =~ s/\//\./gs; |
$m->out($name); |
</%perl></%method> |
%# metodi di default per i componenti /data |
%# |
%# informazione sulla tabella |
<%method INFO>\ |
<%args> |
$DATA_URI => $m->scomp('SELF:DATA_URI') |
$KEY => undef |
$WHAT => '' |
$SEP => ',' |
$NAME => undef |
$OBJ => undef |
</%args> |
<%perl> |
#DEBUG $PLogger->debug(sub{ "SCHEMA_FROM='$SCHEMA_FROM' NAME='$NAME' KEY='$KEY' WHAT='$WHAT' SEP='$SEP'"; }); |
my $SCHEMA_FROM = $m->scomp('SELF:SCHEMA_FROM'); |
if(!defined($Global{"ATTRS_${DATA_URI}"})){ |
# separo lo schema dal nome della tabella |
my($schema, $from) = split /\./, $SCHEMA_FROM, 2; |
# Get the primary key |
my $pri_key; |
if(my $sth = $Session{Dbh}->primary_key_info(undef, $schema, $from)){ |
my $data = $sth->fetchrow_hashref; |
$pri_key = $data->{COLUMN_NAME}; |
} |
## || die "DBH Error primary_key_info (schema=$schema from=$from):".DBI::errstr; |
## my $data = $sth->fetchrow_hashref; |
## my $pri_key = $data->{COLUMN_NAME}; |
# Get list of fields |
$sth = $Session{Dbh}->column_info(undef, $schema, $from, '%'); |
my $ATTRS = []; |
$Global{"ATTRS_${DATA_URI}"} = $ATTRS; |
while(my $field = $sth->fetchrow_hashref){ |
#DEBUG print STDERR Dumper($field); |
# caso tipo 'numeric' in PostgreSQL |
if($field->{TYPE_NAME} eq 'numeric'){ |
($field->{DECIMAL_DIGITS}, $field->{COLUMN_SIZE}) = split /,/, $field->{COLUMN_SIZE}; |
} |
push @$ATTRS, { NAME => $field->{COLUMN_NAME}, |
TYPE => $field->{TYPE_NAME}, |
SIZE => $field->{COLUMN_SIZE}, |
DECIMAL => $field->{DECIMAL_DIGITS}, |
NOTNULL => !$field->{NULLABLE}, |
PRIMARY_KEY => ($field->{COLUMN_NAME} eq $pri_key), |
}; |
} |
# GDO Ho dovuto inserire il commit dopo l'aggiornamento a SuSE8.2 e Postgres 7.3 |
$Session{Dbh}->commit; |
# costruisco una HASH di ricerca con chiave nome del campo |
my $FIELDS = {}; |
$Global{"FIELDS_${DATA_URI}"} = $FIELDS; |
foreach my $key (@{$ATTRS}){ |
my $name = $key->{NAME}; |
$FIELDS->{$name} = $key; |
} |
# recupero le descrizioni di ogni campo previsto |
# se FIELDS utilizza <%method INFO> i dati necessari sono stati creati |
# nelle righe precedenti del codice |
my @names = &Method2Array('FIELDS'); |
# tolgo dai nomi l'eventuale prefisso della tabella |
foreach(@names){ |
s/.*\.//; |
} |
my @fields_descr = &Method2Array('FIELDS_DESCR'); |
my %description; |
for(my $P=0; $P <@names; $P++){ |
$description{$names[$P]}=$fields_descr[$P]; |
} |
my @find_names = &Method2Array('FIND_FIELDS'); |
my @find_fields_descr = &Method2Array('FIND_FIELDS_DESCR'); |
my %find_description; |
for(my $P=0; $P <@find_names; $P++){ |
# tolgo dal nome il prefisso |
$find_names[$P] =~ s/.*\.//; |
$find_description{$find_names[$P]} = (defined $find_fields_descr[$P]) ? |
$find_fields_descr[$P] : $description{$find_names[$P]}; |
} |
my @hidden_names = &Method2Array('FIELDS_HIDDEN'); |
my %hidden_names; |
for(my $P=0; $P <@hidden_names; $P++){ |
# tolgo dal nome il prefisso |
$hidden_names[$P] =~ s/.*\.//; |
$hidden_names{$hidden_names[$P]} = 1; |
} |
foreach my $key (@{$ATTRS}){ |
my $name = $key->{NAME}; |
# aggiungo all'hash anche la descrizione del campo recuperata da SELF:FIELDS_DESCR |
$key->{DESCR} = delete $description{$name}; |
$key->{FIND_DESCR} = delete $find_description{$name}; |
$key->{HIDDEN} = delete $hidden_names{$name}; |
} |
# completo con i nomi non presenti nella tabella |
foreach my $name (keys %description){ |
my $key = $FIELDS->{$name} = { NAME => $name }; |
push @{$ATTRS}, $key; |
# aggiungo all'hash anche la descrizione del campo recuperata da SELF:FIELDS_DESCR e SELF:FIND_FIELDS_DESCR |
$key->{DESCR} = $description{$name}; |
$key->{FIND_DESCR} = delete $find_description{$name}; |
$key->{HIDDEN} = delete $hidden_names{$name}; |
} |
# completo con i nomi non presenti nella tabella |
foreach my $name (keys %find_description){ |
my $key = $FIELDS->{$name} = { NAME => $name }; |
push @{$ATTRS}, $key; |
# aggiungo all'hash anche la descrizione del campo recuperata da SELF:FIND_FIELDS_DESCR |
$key->{FIND_DESCR} = delete $find_description{$name}; |
$key->{HIDDEN} = delete $hidden_names{$name}; |
} |
#DEBUG $PLogger->debug(sub{ '°'x60,"\nFIELDS_${DATA_URI} = ",Dumper($Global{"FIELDS_${DATA_URI}"}); }); |
} |
# recupero i parametri dei campi del recordset inseriti manualmente |
my $params = {}; |
if($m->base_comp->method_exists('ATTRS')){ |
$params = eval('{'.$m->scomp('SELF:ATTRS').'}'); |
# aggiungo i parametri alla struttura dei parametri recuperata da 'table_attributes' |
my $FIELDS = $Global{"FIELDS_${DATA_URI}"}; |
foreach my $name (keys %{$params}){ |
my $keys = $params->{$name}; |
foreach my $k (keys %{$keys}){ |
$FIELDS->{$name}{$k} = $keys->{$k}; |
} |
} |
#DEBUG $PLogger->debug(sub{ "dopo aggiunta FIELDS_${DATA_URI} = ", Dumper($Global{"FIELDS_${DATA_URI}"}); }); |
} |
if($NAME){ |
# il nome potrebbe essere nella forma "tabella.nome" |
if($NAME =~ m/(.+)\.(.+)/){ |
$NAME = $2; |
} |
if($WHAT){ |
my $val = $Global{"FIELDS_${DATA_URI}"}->{$NAME}->{$WHAT}; |
#DEBUG $PLogger->debug(sub{ "INFO NAME:$NAME VAL:$val DATA_URI:$DATA_URI KEY:$KEY WHAT:$WHAT SEP:$SEP"; }); |
$m->out($val); |
return; |
}else{ |
return $Global{"FIELDS_${DATA_URI}"}->{$NAME}; |
} |
} |
if($OBJ){ |
return $Global{"FIELDS_${DATA_URI}"} |
} |
my $nokey; |
if($WHAT eq 'NAME_NOPK'){ |
$WHAT = 'NAME'; |
$nokey = 1; |
} |
# compongo la lista mettendo i campi PRIMARY_KEY all'inizio |
my $list=''; |
my $pklist=''; |
foreach my $key (@{$Global{"ATTRS_${DATA_URI}"}}){ |
if( ! $KEY || $key->{$KEY} ){ |
if($key->{PRIMARY_KEY}){ |
if(!$nokey){ |
$pklist.=$key->{$WHAT}.$SEP; |
} |
}else{ |
$list.=$key->{$WHAT}.$SEP; |
} |
} |
} |
local $/ = $SEP; |
chomp $pklist; |
if($pklist){ |
$pklist.=$SEP.$list; |
}else{ |
$pklist=$list; |
} |
chomp $pklist; |
#DEBUG $PLogger->debug(sub{ "INFO VAL:$pklist DATA_URI:$DATA_URI KEY:$KEY WHAT:$WHAT SEP:$SEP"; }); |
$m->out($pklist); |
</%perl> |
</%method> |
%# individua lo schema del database |
<%method SCHEMA>\ |
<%perl> |
# ricavo il nome dello schema dal nome della cartella in cui è salvato il componente |
my $path = $m->base_comp->path; |
my $base = $r->dir_config('DataBaseUrl'); |
if($path =~ m/^$base\/{0,1}(.*)$/){ |
my $name = $1; |
if($name eq 'dhandler'){ |
$name = $Session{ARGS}{name}; |
die "Unexpected path $path\n"; |
} |
if($name =~ m|^(\w+)/|){ |
$m->out($1); |
}else{ |
die "Unhautorized name ($name)\n;"; |
} |
}else{ |
die "Unhautorized path ($path)\n;"; |
} |
</%perl>\ |
</%method> |
<%method FROM_OBJ>\ |
<%perl> |
# ricavo il nome della tabella dal nome del componente richiamato |
my $from = $m->base_comp->name; |
if($from eq $m->dhandler_name){ |
$from = $m->dhandler_arg; |
} |
# tolgo il suffisso (.mql, .xsl, .txt, ecc.) |
$from =~ s/\.[^.]+//; |
# tolgo la classe, se presente |
$from =~ s|^.*/||; |
$m->out($from); |
</%perl>\ |
</%method> |
<%method DESCRIPTION>\ |
Tabella <& SELF:FROM &> (<& SELF:SCHEMA &>)\ |
</%method> |
<%method FROM><& SELF:FROM_OBJ &></%method> |
<%method SCHEMA_FROM><& SELF:SCHEMA &>.<& SELF:FROM &></%method> |
<%method LOG_TABLE_NAME><& SELF:SCHEMA &>.<& SELF:FROM_OBJ &></%method> |
<%method JOIN_TABLES><& SELF:SCHEMA_FROM &></%method> |
<%method KEY><& SELF:FROM &>.<& SELF:KEY_NAME &></%method> |
<%method KEY_NAME>\ |
<%perl># individua la colonna PRIMARY KEY |
if(my $key = $m->scomp('SELF:INFO', KEY => 'PRIMARY_KEY', WHAT => 'NAME') ){ |
$m->out($key); |
return; |
} |
my @names = &Method2Array('INFO', undef, WHAT => 'NAME'); |
foreach $_ (@names){ |
if(m/^pkey/i){ |
$m->out($_); |
return; |
} |
if(m/pkey$/i){ |
$m->out($_); |
return; |
} |
} |
foreach $_ (@names){ |
if(m/^id/i){ |
$m->out($_); |
return; |
} |
if(m/id$/i){ |
$m->out($_); |
return; |
} |
} |
# se non c'è una chiave primaria e nemmeno un campo di nome |
# pkey* *pkey id* *id ritorna il primo campo della lista |
$m->out($names[0]); |
</%perl></%method> |
<%method FIELDS><& SELF:INFO, WHAT => 'NAME_NOPK' &></%method> |
<%method SELECT_FIELDS><& SELF:FIELDS, %ARGS &></%method> |
<%method SELECT_XLS_FIELDS><& SELF:SELECT_FIELDS &></%method> |
<%method FIELDS_RO></%method> |
<%method FIELDS_HIDDEN></%method> |
<%method FIELDS_RO_UPDATE>\ |
<& SELF:FIELDS_RO &>\ |
</%method> |
<%method FIELDS_NO_WRITE>\ |
<& SELF:FIELDS_RO &>\ |
</%method> |
<%method FIELDS_NEW></%method> |
<%method FIELDS_DUP></%method> |
<%method FIELDS_COPY_PASTE></%method> |
<%method FIELDS_NOT_NULL></%method> |
<%method FIELDS_DESCR><& SELF:FIELDS &></%method> |
<%method FIND_FIELDS_DESCR></%method> |
%# metodi utilizzati in &check_where_clause per la verifica della clausola json_where elaborata dal client |
<%method AUTHORIZED_FIELDS><& SELF:KEY &>, <& SELF:FIELDS &>, <& SELF:FIND_FIELDS &></%method> |
<%method AUTHORIZED_KEYWORDS>AND, OR, NOT, IS, NULL</%method> |
<%method AUTHORIZED_FUNCTIONS></%method> |
<%method AUTHORIZED_OPERATORS><=, >=, !=, <, >, =, ~*, LIKE, ILIKE</%method> |
%# chiamata per valutare la query fornita dal browser |
<%method EVAL_WHERE>\ |
<%args> |
$arr_where |
</%args> |
<%perl> |
# genera la where e verifica nella query JSON le porzioni di codice SQL non autorizzato (sql injection) |
my $where = Json2SqlWhere($arr_where, 1); |
# riverifica l'intera query alla ricerca di codice SQL non autorizzato (sql injection) |
&check_where_clause($where); |
$m->out($where); |
</%perl></%method> |
<%method ORDER>order by <& SELF:KEY &></%method> |
<%method ORDER_BY> |
<%perl> |
my $orderby = $Params{orderby}; |
if(!length($orderby) || $orderby eq 'null'){ |
$orderby = $m->scomp('SELF:ORDER'); |
} |
if(length($orderby) && $orderby !~ m/^\s*order\s+by\s+/i){ |
$orderby = 'order by '.$orderby; |
} |
$m->out($orderby); |
</%perl> |
</%method> |
<%method DISTINCT></%method> |
<%method NUMREC>\ |
<%args> |
$WHERE => '' |
</%args> |
% my $schema_from = $m->scomp('SELF:JOIN_TABLES', WHERE =>$WHERE); |
% my $distinct = $m->scomp('SELF:DISTINCT'); |
% if($distinct){ |
% # se c'è la direttiva 'distinct' devo contare i record dopo averli raggruppati |
select count(*) from ( |
select <% $distinct %> <& SELF:KEY &> from <%$schema_from%> <% $WHERE %> |
) as count_table;\ |
% }else{ |
% if(!$r->dir_config('USEpgstattuple') || $WHERE && $schema_from !~ m/,/){ |
select count(*) from <%$schema_from%> <% $WHERE %>;\ |
% }else{ |
% # ottimizzazione; l'uso di pgstattuple('xx') è più veloce di count(*), soprattutto se ci sono molti record nella tabella |
% # installare il package postgresql_contrib ed eseguire il codice sql per creare la funzione e la struttura dati associata |
% # trucco per trovare i file interessati: 'find / -name "pgstattuple*" ' |
select tuple_count FROM pgstattuple('<%$schema_from%>');\ |
% } |
% } |
</%method> |
<%method NUM_RECORDS>\ |
<%perl> |
my $sth = ExecQuery('numrec', 'SELF:NUMREC', WHERE => EvalSqlWhere(undef, \%Params) ); |
my $numrec=$sth->fetchrow_arrayref->[0]; |
$m->out($numrec); |
</%perl> |
</%method> |
%# numero di record che vengono copiati nella cache (vedi tabelle public.recordset e public.recordset_rows) |
%# un numero pari a 0 disabilita la cache |
<%method DIM_BLOCK_CACHE>100</%method> |
<%method RECORDS>\ |
%# il metodo è utilizzato per ricavare le chiavi primarie di una select, per poi richiedere la select completa fornendo |
%# la clausola WHERE del tipo (where id=x or id=y or id=.....) |
<%args> |
$WHERE => '' |
$LIMIT => '' |
$OFFSET => '' |
</%args> |
<%perl> |
# se è applicato DISTINCT è necessario che nell'elenco dei campi vengano aggiunti anche i campi di ordinamento |
my $distinct = $m->scomp('SELF:DISTINCT'); |
my $order_by = $m->scomp('SELF:ORDER_BY'); |
my $key = $m->scomp('SELF:KEY'); |
my $list_sorted_field = ''; |
if($distinct && $order_by){ |
$list_sorted_field = $order_by; |
$list_sorted_field =~ s/\s+ASC\s*$|\s*DESC\s*$//i; |
$list_sorted_field =~ s/\s*ORDER BY\s+//i; |
$list_sorted_field =~ s/\s+USING.*//i; |
$list_sorted_field = ', '.$list_sorted_field.' '; |
# elimino dalla lista la KEY,se presente |
$list_sorted_field =~ s/,\s*$key([ ,])/$1/; |
} |
</%perl> |
select <%$distinct%> <%$key%><%$list_sorted_field%> from <& SELF:JOIN_TABLES, %ARGS &> <% $WHERE %> <%$order_by%> <%$OFFSET%> <%$LIMIT%>;\ |
</%method> |
<%method FIND_RECORDS>\ |
<%args> |
$WHERE => '' |
$RECORDS |
$KEY |
</%args> |
% my $sql = $m->scomp($RECORDS, WHERE => $WHERE); |
% my $key_name = $m->scomp('SELF:KEY_NAME'); |
% $sql =~ s/;\s*$//s; |
SELECT pos_<%$key_name%> FROM ( select ROW_NUMBER() OVER () AS pos_<%$key_name%>, <%$key_name%> FROM ( |
<% $sql %> |
) "TABLE1") "TABLE2" WHERE <%$key_name%> = <% $KEY %>; |
</%method> |
<%method SELECT_REPORTS>\ |
%# The method selects a recordset that will be used for printing a report. |
<%args> |
$WHERE => '' |
</%args> |
select <& SELF:KEY &> as key from <& SELF:JOIN_TABLES, %ARGS &> <% $WHERE %> <&SELF:ORDER_BY&>\ |
</%method> |
<%method INSERT_REPORTS>\ |
%# The method inserts one primary key from the selected recordset into the report_id table. |
<%args> |
$REPORT_ID |
$GROUP_ID |
</%args> |
insert into public.report_id (key, group_id) values (<%$REPORT_ID%>, <%$GROUP_ID%>) |
</%method> |
<%method SELECT_XLS><& SELF:SELECT, %ARGS &></%method> |
<%method SELECT>\ |
<%args> |
$WHERE => '' |
$ORDER => $m->scomp('SELF:ORDER_BY') |
$FIELDS => $m->scomp('SELF:SELECT_FIELDS') |
$ID => undef |
</%args> |
% if(defined $ID){ |
select <& SELF:KEY &>, <% $FIELDS %> |
from <& SELF:JOIN_TABLES, %ARGS &> where <& SELF:KEY &> = <% encodeSql($ID) %> |
% }else{ |
select <& SELF:DISTINCT &> <& SELF:KEY &>, <% $FIELDS %> |
from <& SELF:JOIN_TABLES, %ARGS &> <% $WHERE %> <% $ORDER %> |
% } |
</%method> |
<%method SERIAL_SEQ><& SELF:SCHEMA_FROM &>_<& SELF:KEY_NAME &>_seq</%method> |
<%method INSERT>\ |
<%args> |
$NEW_KEY # chiave primaria, se fornita |
$FIELDS # elenco campi "campo1,campo2,..." |
$FIELDS_INSERT # hash dei campi e rispettivi valori |
$VALUES # elenco "?,?,..." |
$LIST_VALUES # $LIST_VALUES->[n] lista valori usata in $sth->execute(); può essere modificata |
</%args> |
insert into <& SELF:SCHEMA_FROM &> (<% $FIELDS %>) values (<%$VALUES%>); |
% if(!defined $NEW_KEY){ |
% # se la chiave non è fornita, si deve recuperarla dalla sequenza |
select currval('<&SELF:SERIAL_SEQ&>'); |
% } |
</%method> |
<%method UPDATE>\ |
<%args> |
$UPDATES # elenco campi "campo1=?, campo2=?, ..." |
$FIELDS_UPDATE # hash dei campi e rispettivi valori |
$LIST_VALUES # $LIST_VALUES->[n] lista valori usata in $sth->execute(); può essere modificata |
$KEY # PK del record |
</%args> |
update <& SELF:SCHEMA_FROM &> set <%$UPDATES%> where <& SELF:KEY &> = <% encodeSql($KEY) %>;\ |
</%method> |
<%method DELETE>\ |
<%args>$KEY</%args> |
delete from <& SELF:SCHEMA_FROM &> where <& SELF:KEY &> = <% encodeSql($KEY) %>;\ |
</%method> |
<%method VARCHAR_DEFAULT_LENGTH>80</%method> |
<%method STANDARD_FIELD>\ |
<%args> |
$name |
$type |
$id |
$description |
$length => 12 |
$size => undef |
$length_in_descr => 1 |
</%args> |
<%perl> |
$ARGS{length} = $length; |
my $component; |
#DEBUG $PLogger->debug(sub{ "STANDARD_FIELD $name, $type, $id, $description, $length"; }); |
if($type =~ m/int/i){ |
$component = '/input/number.comp'; |
}elsif($type =~ m/date/i){ |
$component = '/input/date.comp'; |
}elsif($type =~ m/timestamp/i){ |
$component = '/input/timestamp.comp'; |
}elsif($type =~ m/time/i){ |
$component = '/input/time.comp'; |
}elsif($type =~ m/bool/i){ |
$component = '/input/checkbox.comp'; |
}elsif($type =~ m/float/i || $type =~ m/double precision/i || $type =~ m/real/i){ |
$component = '/input/number.comp'; |
}elsif($type =~ m/numeric/i){ |
$component = '/input/number.comp'; |
if($ARGS{NumDec}){ |
$ARGS{NumDec} = 2; |
} |
}else{ |
$component = '/input/string.comp'; |
if(!defined $length){ |
$ARGS{length} = $m->scomp('SELF:VARCHAR_DEFAULT_LENGTH'); |
} |
if($length_in_descr && defined $length){ |
$ARGS{description}.=" ($length)"; |
} |
} |
</%perl> |
%# $PLogger->debug(sub{ "COMPONENTE $component con parametri ", Dumper(\%ARGS); }); |
<& $component, %ARGS &>\ |
</%method> |
<%method GENERIC_D_FIELD>\ |
<%args> |
$id |
$name |
$description => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'DESCR') |
$hidden => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'HIDDEN') |
$break => undef |
$nobreak => undef |
$descr_sep_nobreak => undef |
$descr_sep_break => undef |
$descr_sep => undef |
</%args> |
<%perl> |
#DEBUG |
my $br = (($description =~ s/\/$//) && $break); # abbiamo / alla fine della descrizione |
my $nobr = (($description =~ s/\\$//) && $nobreak); # abbiamo \ alla fine della descrizione |
if(!$descr_sep){ |
if($br){ |
$descr_sep = $descr_sep_break; |
}elsif($nobr){ |
$descr_sep = $descr_sep_nobreak; |
} |
} |
#DEBUG $PLogger->debug(sub{ Dumper(\%ARGS), "br='$br' nobr='$nobr' descr_sep='$descr_sep'"; }); |
$ARGS{description} = $description; # applico modifica anche al parametro nella lista degli argomenti |
# annullo i campi che non devono propagarsi ai componenti richiamati |
delete $ARGS{break}; |
delete $ARGS{nobreak}; |
delete $ARGS{descr_sep_nobreak}; |
delete $ARGS{descr_sep_break}; |
delete $ARGS{descr_sep}; |
</%perl> |
<span class="widget_span" id="Span_<%$id%>" <% $hidden ? 'style="display:none;"' : '' %>>\ |
% if($descr_sep && $description){ |
<b id="DescrField_<%$id%>"><%$description%></b><%$descr_sep%>\ |
% } |
<& SELF:GENERIC_FIELD, %ARGS &></span> |
% if($br){ |
<%$break%> |
% }elsif($nobr){ |
<%$nobreak%> |
% } |
</%method> |
<%method GENERIC_FIELD> |
<%args> |
$id |
$name |
$type => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'TYPE') |
$description => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'DESCR') |
$length => undef |
$NumDec => undef |
$readonly => 1 |
</%args> |
<%perl> |
$ARGS{type} = $type; |
$description =~ s/\/$|\\$//; |
$ARGS{description} = $description; |
$ARGS{readonly} = $readonly; |
if(!$length){ |
$length = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'SIZE'); |
if($type =~ m/int/i){ |
$length = 8; |
}elsif($type =~ m/date/i || $type =~ m/timestamp/i){ |
}elsif($type =~ m/bool/i){ |
}elsif($type =~ m/float/i || $type =~ m/double precision/i || $type =~ m/real/i){ |
$length = 12; |
$ARGS{NumDec} = 4; |
$ARGS{NumCifre} = 16; |
} |
} |
if($type =~ m/numeric/i && !defined $NumDec){ |
$ARGS{NumDec} = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'DECIMAL'); |
} |
$ARGS{length} = $length; |
if(Exist_Check($name)){ |
# è definito il metodo per il test lato server del widget |
$ARGS{remote_check} = 1; |
} |
$m->comp(Field_Component($name), %ARGS); |
</%perl> |
</%method> |
<%method BOOL_FIND_FIELD>\ |
<%args> |
$id |
</%args> |
<& /input/span.comp, id => $id, style => 'display:none;', value => '', %ARGS, 'value-type' => 'boolean' &>\ |
</%method> |
%# larghezza dei campi di ricerca |
<%method FIND_FIELD_WIDTH>120</%method> |
%# generico componente per le ricerche |
<%method GENERIC_FIND>\ |
<%args> |
$name |
$id |
$length => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'SIZE') |
$type => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'TYPE') |
$description => $m->scomp('SELF:INFO', NAME => $name, WHAT => 'FIND_DESCR') |
$find_size => undef |
$find_width => undef |
$size => undef |
$width => undef |
</%args> |
<%perl> |
#DEBUG $PLogger->debug(sub{ "GENERIC_FIND name:$name id:$id type:$type, destination:$description length:$length, find_size:$find_size find_width:$find_width size:$size width:$width"; }); |
my $id_sel=$id.'_ftype'; |
$ARGS{id_sel} = $id_sel; |
$id.='_find'; |
$ARGS{id} = $id; |
# verifico se è definito un widget di ricerca |
if($m->base_comp->method_exists($name.'_FIND_WIDGET')){ |
$m->comp('SELF:'.$name.'_FIND_WIDGET', %ARGS); |
}else{ |
my $component = &Find_Component($name, $type); |
my $comp = $m->fetch_comp($component); |
# visualizzo un selettore per la scelta del tipo di confronto nella query |
# verifico se il componente definisce la lista degli operatori di confronto da utilizzare |
my $list_sel = findSelectList($comp, $type); |
$m->comp('/input/select.comp', id =>$id_sel, |
description => 'Selezione tipo di confronto', |
list => $list_sel, |
empty => ''); |
# sistemo alcuni parametri |
$ARGS{type} = $type; |
$ARGS{description} = $description; |
$ARGS{size} = $find_size ? $find_size : ($length<10 ? $length : 10); |
$ARGS{length} = 128; |
my $find_field_width = $m->scomp('SELF:FIND_FIELD_WIDTH'); |
$ARGS{width} = $find_width ? $find_width : (!defined $width || $find_field_width < $width ? $find_field_width : $width); |
# suffisso per la classe che identifica un campo di filtro |
#DEBUG $PLogger->debug(sub{ "GENERIC_FIND $component:$type ARGS:", Dumper(\%ARGS); }); |
$m->comp($comp, length_in_descr => 0, %ARGS, onchange => qq|Set_first_if_not_selected(this, '$id_sel', '$list_sel->[0]');|); |
} |
</%perl> |
</%method> |
%# restituisce i campi HTML per la navigazione del recordset |
<%method CONTROLS>\ |
<%args> |
$Recordset |
$Display |
$rows |
$disp_navbar => 1 |
$disp_cancel => undef |
$disp_refresh => 1 |
$disp_change => undef |
$disp_insert => undef |
$disp_dup => 0 |
$disp_save => undef |
$disp_delete => undef |
$disp_print => undef |
$disp_xls => undef |
$disp_log => undef |
</%args> |
<%perl> |
my $permission = Permission(); |
$disp_navbar = $disp_navbar ? '' : 'style="display: none;"'; |
$disp_cancel = $disp_cancel == 1 || ($disp_cancel eq '' && ($permission->{Insert} || $permission->{Update})) ? '' : 'style="display: none;"'; |
$disp_refresh = $disp_refresh ? '' : 'style="display: none;"'; |
$disp_change = $disp_change == 1 || ($disp_change eq '' && $permission->{Update}) ? '' : 'style="display: none;"'; |
$disp_insert = $disp_insert == 1 || ($disp_insert eq '' && $permission->{Insert}) ? '' : 'style="display: none;"'; |
$disp_dup = $disp_dup ? '' : 'style="display: none;"'; |
$disp_save = $disp_save == 1 || ($disp_save eq '' && ($permission->{Insert} || $permission->{Update})) ? '' : 'style="display: none;"'; |
$disp_delete = $disp_delete == 1 || ($disp_delete eq '' && $permission->{Delete}) ? '' : 'style="display: none;"'; |
$disp_print = $disp_print == 1 || ($disp_print eq '' && $permission->{Print}) ? '' : 'style="display: none;"'; |
$disp_xls = $disp_xls == 1 || ($disp_xls eq '' && $permission->{Xls}) ? '' : 'style="display: none;"'; |
my $table_name = $m->scomp('SELF:LOG_TABLE_NAME'); |
$table_name =~ s/^\s+|\s+$//g; |
# mostro il pulsante [Log] solo se la tabella non è figlia |
my $father = $m->scomp('SELF:FATHER'); |
$father =~ s/^\s+|\s+$//g; |
$disp_log = ($disp_log == 1 || ($disp_log eq '' && $permission->{Log})) && $table_name && !$father ? '' : 'style="display: none;"'; |
</%perl> |
<span style="white-space:nowrap;" id="<%$Display%>_Controls"> |
% if($m->base_comp->method_exists('CONTROLS_INCLUDE_PRE')){ |
<& SELF:CONTROLS_INCLUDE_PRE, %ARGS &> |
% } |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_cancel %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons cancel', showLabel:true, title:'Annulla le modifiche'" |
id="<%$Display%>_Ctrl_cancel" onclick="<%$Display%>.cancelUpdate()" type="button">Annulla</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_refresh %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons refresh', showLabel:true, title:'Ricarica i dati dal server'" |
id="<%$Display%>_Ctrl_refresh" onclick="<%$Display%>.cancelUpdate();<%$Display%>.gotoRecords('update');" type="button">Aggiorna</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_navbar %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons rewind', showLabel:false, title:'Salta all\'inizio della selezione dei record'" |
id="<%$Display%>_Ctrl_rewind" onclick="<%$Display%>.gotoRecords('rewind')" type="button">Primo</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_navbar %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons down', showLabel:false, title:'Salta al record precedente'" |
id="<%$Display%>_Ctrl_down" onclick="<%$Display%>.gotoRecords('down')" type="button">Precedente</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_navbar %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons up', showLabel:false, title:'Salta al record successivo'" |
id="<%$Display%>_Ctrl_up" onclick="<%$Display%>.gotoRecords('up')" type="button">Successivo</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_navbar %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons forward', showLabel:false, title:'Salta alla fine della selezione dei record'" |
id="<%$Display%>_Ctrl_forward" onclick="<%$Display%>.gotoRecords('forward')" type="button">Ultimo</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_change %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons change', showLabel:true, title:'Modifica <% $rows==1 ? 'il' : 'i' %> record'" |
id="<%$Display%>_Ctrl_change" onclick="<%$Display%>.readOnly(false);<%$Display%>.cpSetAll();" type="button">Modifica</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_insert %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons insert', showLabel:true, title:'Aggiunge <% $rows==1 ? 'un nuovo record' : 'nuovi record' %>'" |
id="<%$Display%>_Ctrl_insert" onclick="<%$Display%>.gotoRecords('insert')" type="button">Nuov<% $rows==1 ? 'o' : 'i' %></button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_dup %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons dup', showLabel:true, title:'Duplica <% $rows==1 ? 'il record' : 'i record selezionati' %>'" |
id="<%$Display%>_Ctrl_dup" onclick="<%$Display%>.gotoRecords('dup')" type="button">Duplica<% $rows==1 ? '' : ' sel.' %></button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_save %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons save', showLabel:true, title:'Salva le modifiche effettuate'" |
id="<%$Display%>_Ctrl_save" onclick="<%$Display%>.gotoRecords('save')" type="button">Salva</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_delete %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons delete', showLabel:true, title:'Cancella <% $rows==1 ? 'il record' : 'i record selezionati' %>'" |
id="<%$Display%>_Ctrl_delete" onclick="<%$Display%>.deleteSelected()" type="button"><%$rows==1?'Cancella':'Canc.sel.'%></button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_print %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons print', showLabel:true, title:'Stampa <% $rows==1 ? 'il record' : 'i record selezionati' %>'" |
id="<%$Display%>_Ctrl_print" onclick="<%$Display%>.printSelected('sel');" type="button"><%$rows==1?'Stampa':'St.sel.'%></button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_xls %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons xls', showLabel:true, title:'Esporta nel formato XLS'" |
id="<%$Display%>_Ctrl_xls" onclick="<%$Display%>.printSelected('xls_sel')" type="button">XLS</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_navbar %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons goto', showLabel:true, title:'Salta alla posizione indicata a fianco'" |
id="<%$Display%>_Ctrl_goto" onclick="<%$Display%>.gotoRecords(document.getElementById('<%$Display%>_record').value)" |
type="button"><% $rows==1 ? 'R' : 'Da r' %>ec. |
<& /input/number.comp, tabindex => -1, style => $disp_navbar ? 'display: none;' : '', id => $Display.'_record', value=>1, |
NumDec=>0, ValMin=>1, ValMax=>1, size=>6, description=>'Posizione del record a cui saltare' &> |
</button> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" <% $disp_log %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons log', showLabel:true, title:'Visualizza l\'attività <%$rows==1 ? 'del record' : 'dei record selezionati' %>'" |
id="<%$Display%>_Ctrl_log" onclick="<%$Display%>.displayLog()" type="button">LOG</button> |
% if($m->base_comp->method_exists('CONTROLS_INCLUDE_POST')){ |
<& SELF:CONTROLS_INCLUDE_POST, %ARGS &> |
% } |
</span> |
<script> |
require(["dijit/form/Button", "dijit/form/ValidationTextBox"]); |
% # inizializzo i puntatori agli oggetti per la "navigazione" del recordset |
require(["dojo/dom", "dijit/registry", "dojo/_base/array", "dojo/on", "dojo/_base/event"], function (dom, registry, array, on, event){ |
masonSql.once('ready', function(data){ |
array.forEach(['cancel', 'refresh', 'rewind', 'down', 'up', 'forward', 'change', 'insert', 'dup', 'save', 'delete', 'print', 'xls', 'goto', 'log'], function(prefix){ |
<%$Display%>.navigationBar[prefix + 'Button'] = registry.byId('<%$Display%>_Ctrl_'+prefix); |
}); |
<%$Display%>.navigationBar._record = window.Id_<% $Display %>_record; |
on(window.Id_<% $Display %>_record, 'click', function(evt){ |
event.stop(evt); |
this.setFocus(evt); |
}); |
}); |
}); |
</script> |
</%method> |
%# generica riga per il browsing della tabella |
<%method ROW_TABLE> |
<%args> |
$row |
$Recordset |
$Display |
$Class |
$delay_script => undef # ritarda l'esecuzione degli script associati ai componenti |
$Detail_from => undef |
</%args> |
<tr id="<%$Display%>_div_<%$row%>" class="ROW_TABLE_<%$Class%>" onclick="<%$Display%>.selectRowFather(<%$row%>);"> |
% if($row =~ m/^\d+$/ || $row eq '{{ row }}'){ |
<td class="ROW_TABLE_Sel" ><span id="<%$Display%>_l_<%$row%>">-</span></td> |
<td><input type="checkbox" class="checkbox" id="<%$Display%>_s_<%$row%>" onclick="<%$Display%>.cpSetMultipleRows(event, <%$row%>)"></td> |
% if($Detail_from){ |
% my $table_comp = $m->fetch_comp($r->dir_config('DataBaseUrl').'/'.$Detail_from.'.mql'); |
% my($width, $height, $properties); |
% if($table_comp->method_exists('DETAIL_WINDOW')){ |
% ($width, $height) = split /\s+/, $table_comp->scall_method('DETAIL_WINDOW'), 2; |
% } |
% my $title = $table_comp->scall_method('DESCRIPTION'); |
<td><button data-dojo-type="dijit/form/Button" class="controlBtn recordDetailBtn" data-dojo-props="tabIndex:-1, showLabel:true, title:'Apre form di dettaglio'" |
onclick="<%$Display%>.openFormDetail('forward', <%$row%>, '<%$Detail_from%>', <% $width || 'null' %>, <% $height || 'null' %>, '<% $title |js%>', {});" |
style="display:none;" id="<%$Display%>_d_<%$row%>">DET</button> |
</td> |
% } |
% }else{ |
<td colspan="<% $Detail_from ? 3 : 2 %>"></td> |
% } |
% my @fields = &Method2Array('FIELDS'); |
% for(my $col=0; $col<@fields; $col++){ |
% my $name = $fields[$col]; |
% $name =~ s/\s//g; |
<td class="nowrap"> |
% my $hidden = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'HIDDEN'); |
<span class="widget_span" id="Span_<%"${Display}_c_${row}_$col"%>" <% $hidden ? 'style="display:none;"' : '' %>> |
<& SELF:GENERIC_FIELD, name => $name, id =>"${Display}_c_${row}_$col", Display => $Display, row => $row, col => $col &> |
</span></td> |
% } |
<td width="10"></td> |
</tr> |
% if(!$delay_script && @Script_buffer){ |
<script> |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
</script> |
% } |
</%method> |
<%method TABLE_HEADER> |
<%args> |
@FIELDS |
$Display |
$Detail_from => undef |
</%args> |
<th colspan="<% $Detail_from ? 3 : 2 %>" width="<% $Detail_from ? 80 : 50 %>"> |
<p id="<%"${Display}_h_sel"%>" onclick="<%$Display%>.cpInvertAllHeaders();">sel.</p></th> |
%# descrizione campi |
% for(my $col=0; $col<@FIELDS; $col++){ |
% my $name = $FIELDS[$col]; |
% my $hidden = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'HIDDEN'); |
% my $descr = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'DESCR'); |
% $descr =~ s/\\$//; |
% $descr =~ s/\/$//; |
<th><p id="<%"${Display}_h_$col"%>" <% $hidden ? 'style="display:none;"' : '' %> |
onclick="<%$Display%>.cpInvertHeader(<%$col%>);"><%$descr%></p></th> |
% } |
</%method> |
%# generica tabella per il browsing della tabella del database |
<%method TABLE> |
<%args> |
$rows |
$group_cols => 1 # numero di gruppi con cui suddividere la tabella, da affiancare orizzontalmente |
$Recordset => 'TABLE' |
$Display => 'DISP_'.$Recordset |
$Header => 1 |
$Controls => 1 |
$Detail_from => undef # se definita viene inserito per ciascun record un bottone per richiamare un form separato per modificare/inserire il record |
</%args> |
<%perl> |
if($rows % $group_cols){ die "Il numero di righe (rows=$rows) non è multiplo del numero di gruppi (group_cols=$group_cols)\n" } |
my $rcol = $rows/$group_cols; |
if($Header){ |
$m->comp('SELF:FORM_HEADER', %ARGS); |
} |
if($Controls){ |
$m->comp('SELF:CONTROLS', %ARGS); |
} |
my @names = &Method2Array('FIELDS'); |
my $Row_buffer; |
my $Script_buffer; |
{ local @Script_buffer; |
$Row_buffer = $m->scomp('SELF:ROW_TABLE', row=>'{{ row }}', Class => '{{ class }}', Recordset => $Recordset, Display => $Display, delay_script => 1, Detail_from => $Detail_from); |
$Script_buffer = join('', @Script_buffer); |
} |
my $Header_buffer = $m->scomp('SELF:TABLE_HEADER', FIELDS => \@names , Display => $Display, Detail_from => $Detail_from, %ARGS); |
if($group_cols > 1){ |
</%perl> |
<table class="TABLE_group" id="<%$Display%>_table_list"><table> |
<script> |
require(['dojox/dtl/Context']); |
var buf = ['<tr>']; |
var jbuf = []; |
var row_template = new dojox.dtl.Template('<% $Row_buffer |js%>'); |
%#// On MS Edge with empty string the method .Template return wrong text |
var script_template = new dojox.dtl.Template('// Script_buffer\n<% $Script_buffer |js%>'); |
for(var C=0; C<<%$group_cols%>; C++){ |
buf.push('<td><table class="TABLE_form"><tr><% $Header_buffer |js%></tr>'); |
for(var R=0; R<<% $rcol %>; R++){ |
var row = C * <% $rcol %> + R; |
var context = new dojox.dtl.Context({ |
row: row, |
"class": row % 2 ? 'D' : 'P' |
}); |
buf.push(row_template.render(context)); |
jbuf.push(script_template.render(context)); |
}// for R |
buf.push('</table></td>'); |
} // for C |
buf.push('</tr>'); |
% }else{ # tabella di una sola colonna |
<table class="TABLE_form" id="<%$Display%>_table_list"></table> |
<script> |
require(['dojox/dtl/Context']); |
var buf = ['<tr><% $Header_buffer |js%></tr>']; |
var jbuf = []; |
var row_template = new dojox.dtl.Template('<% $Row_buffer |js%>'); |
var script_template = new dojox.dtl.Template('// Script_buffer\n<% $Script_buffer |js%>'); |
for(var R=0; R<<%$rows%>; R++){ |
var context = new dojox.dtl.Context({ |
row: R, |
"class": R % 2 ? 'D' : 'P' |
}); |
buf.push(row_template.render(context)); |
jbuf.push(script_template.render(context)); |
} |
% } # if $group_cols > 1 |
var html_table = buf.join('\n') + '<script>' + '<% join("\n", @Script_buffer) |js%>\n' + jbuf.join('\n') + '</' + 'script>'; |
hReqMason_innerHTML(document.getElementById('<%$Display%>_table_list'), html_table); |
% @Script_buffer = (); |
% my $cols = @names; |
<%$Display%>.bindEditComponents(<%$rows%>, <%$cols%>, '_s_', '_l_', '_c_', '_'); |
<%$Display%>.info = document.getElementById('<%$Display%>_info'); |
<%$Display%>.info.innerHTML = '? - ? ( ? )'; |
</script> |
</%method> |
<%method HEADER_INCLUDE></%method> |
<%method FORM_HEADER>\ |
<%args> |
$rows => 0 |
$Controls => 0 |
$Recordset => 'FORM' |
$Display => 'DISP_'.$Recordset |
$info => "${Display}_info" # identificatore <span/> per le informazioni del recordset |
$rec => ($rows==1 ? "${Display}_l_0" : "${Display}_rec") # se c'è un solo record l'identificatore corrisponde a DisplayBinding.label[0] |
</%args> |
<table class="FormHeader"> |
<tr style="width:100%;"> |
% if($Controls){ |
<td class="nowrap record_info" > |
<span id="<%$info%>"></span> <span id="<%$rec%>"></span> |
</td> |
<td align="left" style="width:150px;"> |
<& SELF:CONTROLS, %ARGS &> |
</td> |
<td align="left"><& SELF:HEADER_INCLUDE, %ARGS &></td> |
<td> |
<div class="FormHeaderDescription"> |
<& SELF:DESCRIPTION &> |
</div> |
</td> |
% }else{ |
<td class="nowrap record_info"> |
<span id="<%$info%>"></span> <span id="<%$rec%>"></span> |
</td> |
<td style="align:left;"><& SELF:HEADER_INCLUDE, %ARGS &></td> |
<td> |
<div class="FormHeaderDescription"> |
<& SELF:DESCRIPTION &> |
</div> |
</td> |
% } |
</tr> |
</table> |
</%method> |
%# generica riga <ROW_DIVS> per il browsing della tabella |
<%method ROW_DIVS>\ |
<%args> |
$row # riga nel form; nel caricamento dinamico potrebbe essere anche un TAG da usare poi per la sostituzione |
$Recordset # nome dell'oggetto Recordset di riferimento |
$Display # nome dell'oggetto DisplayBinding |
$delay_script => undef # ritarda l'esecuzione degli script associati ai componenti |
$Detail_from => undef |
</%args> |
% if($row =~ m/^\d+$/ || $row eq '@@@'){ |
<span class="ROW_DIVS_Sel" id="<%$Display%>_l_<%$row%>">-</span> |
<input type="checkbox" class="checkbox" id="<%$Display%>_s_<%$row%>"> |
% if($Detail_from){ |
% my $table_comp = $m->fetch_comp($r->dir_config('DataBaseUrl').'/'.$Detail_from.'.mql'); |
% my($width, $height, $properties); |
% if($table_comp->method_exists('DETAIL_WINDOW')){ |
% ($width, $height) = split /\s+/, $table_comp->scall_method('DETAIL_WINDOW'), 2; |
% } |
% my $title = $table_comp->scall_method('DESCRIPTION'); |
<button data-dojo-type="dijit/form/Button" class="controlBtn recordDetailBtn" data-dojo-props="tabIndex:-1, showLabel:true, title:'Apre form di dettaglio'" |
onclick="<%$Display%>.openFormDetail('forward', <%$row%>, '<%$Detail_from%>', <% $width || 'null' %>, <% $height || 'null' %>, '<% $title |js%>', {});" |
style="display:none;" id="<%$Display%>_d_<%$row%>">DET</button> |
% } |
% } |
% my @fields = &Method2Array('FIELDS'); |
% my $cols = @fields; |
% for(my $col=0; $col<$cols; $col++){ |
% my $name = $fields[$col]; |
% $name =~ s/\s//g; |
<& SELF:GENERIC_D_FIELD, descr_sep => ':', name => $name, id =>"${Display}_c_${row}_$col", Display => $Display, row => $row, col => $col, break => '<br>' &>\ |
% } |
% if($row =~ m/^\d+$/ || $row eq '@@@'){ |
% push @Script_buffer, qq| ${Display}.bindEditComponentsRow($row, $cols, '_s_', '_l_', '_c_', '_');\n|; |
% } |
% if(!$delay_script && @Script_buffer){ |
<script> |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
</script> |
% } |
</%method> |
%# riga <ROW_DIVS> per il browsing della tabella usando DIVS_TEMPLATE |
<%method ROW_DIVS_TEMPLATE>\ |
<%args> |
$row # riga nel form; nel caricamento dinamico potrebbe essere anche un TAG da usare poi per la sostituzione |
$Recordset # nome dell'oggetto Recordset di riferimento |
$Display # nome dell'oggetto DisplayBinding |
$delay_script => undef # ritarda l'esecuzione degli script associati ai componenti |
$Detail_from => undef |
</%args> |
<& SELF:TEMPLATE, Template => 'DIVS_TEMPLATE', Row => $row, Recordset => $Recordset, Display => $Display, Header => 0, |
Controls => 0, Class => 'ROW_DIVS' , Detail_from => $Detail_from &> |
% my @fields = &Method2Array('FIELDS'); |
% my $cols = @fields; |
% push @Script_buffer, qq| ${Display}.bindEditComponentsRow($row, $cols, '_s_', '_l_', '_c_', '_');\n|; |
% if(!$delay_script && @Script_buffer){ |
<script> |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
</script> |
% } |
</%method> |
%# indicazione del campo nel recordset che determina il tipo di riga nel caso di template di tipo DIVS variabili |
<%method FIELD_ROW_DIVS></%method> |
%# tutte le righe <ROW_DIVS> per il browsing della tabella che hanno template differenti |
%# restituisce del codice jscript che inizializza nell'oggetto DataBinding un array con i template |
%# per i vari tipi riga da utilizzare dal client |
<%method ALL_ROW_DIVS>\ |
<%args> |
$row # riga nel form; nel caricamento dinamico potrebbe essere anche un TAG da usare poi per la sostituzione |
$Recordset # nome dell'oggetto Recordset di riferimento |
$Display |
$delay_script => undef # ritarda l'esecuzione degli script associati ai componenti |
</%args> |
% foreach my $key ( undef ){ # elenco dei tipi; di default solo undef |
<%$Display%>.divs['<%$key%>'] = "\ |
<%$m->scomp('SELF:ROW_DIVS', row => $row, form_type => $key, Recordset => $Recordset, Display => $Display, delay_script => 0) |js %>\ |
"; |
% } |
% if(!$delay_script && @Script_buffer){ |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
% } |
</%method> |
%# separatore tra le righe |
<%method SEP_DIV><hr></%method> |
%# generico elenco di record racchiuso in elementi <DIV> |
%# tabella per il browsing della tabella del database |
<%method DIVS>\ |
<%args> |
$start => 0 |
$rows => 0 |
$where => undef |
$max_rows => $rows |
$Recordset => 'DIVS' |
$Display => 'DISP_'.$Recordset |
$inner => undef # se definito non viene generato il tag <DIV> che contiene le righe; usato dal Client per aggiornare le righe |
$Header => 1 |
$Controls => 1 |
$Detail_from => undef # se definita viene inserito per ciascun record un bottone per richiamare un form separato per modificare/inserire il record |
</%args> |
% my @names = &Method2Array('FIELDS'); |
% if(!$inner){ |
% if($Header){ |
<& SELF:FORM_HEADER, %ARGS &> |
% } |
% if($Controls){ |
<& SELF:CONTROLS, %ARGS &> |
% } |
<div id="<%$Display%>_DIVS"> |
% } |
% my $row_form = $m->base_comp->method_exists('DIVS_TEMPLATE') ? 'ROW_DIVS_TEMPLATE' : 'ROW_DIVS'; |
% for(my $j=0;$j<$rows; $j++){ |
%# un elemento <div/> per ogni record |
% if($j){ |
<& SELF:SEP_DIV &> |
% } |
<div id="<%$Display%>_div_<%$j%>" class="DIVS_<% $j % 2 ? 'P' : 'D' %>" style="align:block;" onclick="<%$Display%>.selectRowFather(<%$j%>);"> |
<& "SELF:$row_form", row => $j, Recordset => $Recordset, Display => $Display, form_type => undef, delay_script => 1, Detail_from => $Detail_from &> |
</div> |
% # identificatore del tipo di template corrente |
% } |
% if(!$inner){ |
</div> |
% } |
<script> |
% my $cols = @names; |
%# Script_buffer BEGIN |
% $m->out(@Script_buffer); |
%# Script_buffer END |
% @Script_buffer = (); |
% my $field_row_divs = $m->scomp('SELF:FIELD_ROW_DIVS'); |
% if($field_row_divs =~ m/\w/){ |
%# includo nell'oggetto DataBinding i template |
<& SELF:ALL_ROW_DIVS, row => '@@@', Recordset => $Recordset, Display => $Display, delay_script => 0 &> |
%# metodo per individuare il tipo di riga |
%# .type_div restituisce il tipo di form del record di posizione nel recordset "record" |
<%$Display%>.type_div = function(id_row){ |
%# posizione del campo indicato in %method FIELD_ROW_DIVS> |
% my $name = $m->scomp('SELF:FIELD_ROW_DIVS'); |
% $name =~ s/^\s*//; |
% $name =~ s/\s*$//; |
% if($name){ |
% my $pos=0; |
% for(my $i=0; $i<@names; $i++){ |
% if($names[$i] eq $name){ |
% $pos=$i; |
% last; |
% } |
% } |
% # alla funzione/metodo indicata viene passato il parametro "id_row", posizione nel buffer; |
% # deve restituire il tipo di riga da caricare |
% # posizione in colonna nel recordset (vedi posizione dei campi) |
return this.data[id_row][<%$pos%>]; |
% }else{ |
return null; |
% } |
}; |
% } |
<%$Display%>.info = document.getElementById('<%$Display%>_info'); |
<%$Display%>.info.innerHTML = '? - ? ( ? )'; |
% if(@Script_buffer){ |
// Script_buffer BEGIN |
% $m->out(@Script_buffer); |
// Script_buffer END |
% @Script_buffer = (); |
% } |
</script> |
</%method> |
%# generico form per il browsing della tabella del database |
<%method FORM>\ |
<%args> |
$Recordset => 'FORM' |
$Display => 'DISP_'.$Recordset |
$Header => 1 |
$Controls => 1 |
</%args> |
% if($Header){ |
<& SELF:FORM_HEADER, %ARGS &> |
% } |
% if($Controls){ |
<& SELF:CONTROLS, %ARGS &> |
% } |
% my @names = &Method2Array('FIELDS'); |
<table class="FORM_form"> |
% my $rcol=0; |
% for(my $col=0; $col<@names; $col++){ |
% if(!$rcol){ |
<tr> |
<td align="right">\ |
% } |
% $rcol++; |
% my $n = $names[$col]; |
% $n =~ s/\s//g; |
% my $description = $m->scomp('SELF:INFO', NAME => $n, WHAT => 'DESCR'); |
% my $hidden = $m->scomp('SELF:INFO', NAME => $n, WHAT => 'HIDDEN'); |
% $description =~ s/\/$//; |
% my $nobr = ($description =~ s/\\$//); # abbiamo \ alla fine della descrizione |
<span id="Descr_<%"${Display}_c_0_$col"%>" <% $hidden ? 'style="display:none;"' : '' %>><%$description%>:<span> \ |
% # se $nobr non devo iniziare una nuova riga, ma devo allineare il successivo campo nella stessa riga |
% if($rcol == 1){ # prima colonna: attivo seconda colonna |
</td> |
<td class="nowrap"> |
% } |
<span class="widget_span" id="Span_<%"${Display}_c_0_$col"%>" <% $hidden ? 'style="display:none;"' : '' %>> |
<& SELF:GENERIC_FIELD, id => "${Display}_c_0_$col", Display => $Display, row => 0, col => $col, name => $n &>\ |
</span> |
% if(!$nobr){ |
% $rcol=0; |
</td> |
</tr> |
% } |
% } |
</table> |
<script> |
% my $cols = @names; |
<%$Display%>.bindEditComponents(1, <%$cols%>, '_s_', '_l_', '_c_', '_'); |
<%$Display%>.info = document.getElementById('<%$Display%>_info'); |
<%$Display%>.info.innerHTML = '? ( ? )'; |
</script> |
</%method> |
%# generico form con formattazione lineare per il browsing della tabella del database |
%# i campi vengono allineati nell'ordine in cui sono stati elencati |
%# per interrompre una riga inserire il carattere "/" in fondo alla descrizione del campo |
<%method LINEAR>\ |
<%args> |
$Recordset => 'LINEAR' |
$Display => 'DISP_'.$Recordset |
$Header => 1 |
$Controls => 1 |
</%args> |
% if($Header){ |
<& SELF:FORM_HEADER, %ARGS &> |
% } |
% if($Controls){ |
<& SELF:CONTROLS, %ARGS &> |
% } |
% my @names = &Method2Array('FIELDS'); |
<table class="LINEAR_form"> |
<tr><td class="nowrap"> |
% for(my $col=0; $col<@names; $col++){ |
% my $n = $names[$col]; |
% $n =~ s/\s//g; |
<& SELF:GENERIC_D_FIELD, break => '</td></tr><tr><td class="nowrap">', descr_sep => ':', |
name => $n, id =>"${Display}_c_0_$col", Display => $Display, row => 0, col => $col &> |
% } |
</td></tr> |
</table> |
<script> |
% my $cols = @names; |
<%$Display%>.bindEditComponents(1, <%$cols%>, '_s_', '_l_', '_c_', '_'); |
<%$Display%>.info = document.getElementById('<%$Display%>_info'); |
<%$Display%>.info.innerHTML = '? ( ? )'; |
</script> |
</%method> |
%# generico form con formattazione lineare per il browsing della tabella del database |
%# i campi vengono inseriti nel template fornito <%method FORM_TEMPLATE> (o $Template, ad esempio DIVS_TEMPLATE)</%method> |
%# ad esempio: |
%# <%method FORM_TEMPLATE><p><DESCR:description>: <FIELD:description></p></%method> |
%# |
<%method TEMPLATE>\ |
<%args> |
$Recordset => 'FORM' |
$Display => 'DISP_'.$Recordset |
$Header => 1 |
$Controls => 1 |
$Row => undef # if not defined will create a form with 1 row |
$Template => 'FORM_TEMPLATE' |
$Class => 'TEMPLATE' |
</%args> |
% if($Header){ |
<& SELF:FORM_HEADER, %ARGS &> |
% } |
% if($Controls){ |
<& SELF:CONTROLS, %ARGS &> |
% } |
<%perl> |
my $row = $Row ? $Row : 0; |
my $TEMPLATE = $m->scomp("SELF:$Template", %ARGS); |
$TEMPLATE =~ s/\<INFO\>/<span id="${Display}_info"><\/span>/i; |
$TEMPLATE =~ s/\<RECORD\>/<span class="${Class}_Sel" id="${Display}_l_$row"><\/span>/i; |
$TEMPLATE =~ s/\<CHECKBOX\>/<input type="checkbox" class="checkbox" id="${Display}_s_$row">/i; |
# sostituisco i campi nel template |
$TEMPLATE =~ s/<DISPLAY>/${Display}/sg; |
$TEMPLATE =~ s/<RECORDSET>/${Recordset}/sg; |
my @names = &Method2Array('FIELDS'); |
for(my $col=0; $col<@names; $col++){ |
my $n = $names[$col]; |
$n =~ s/\s//g; |
my $descr = $m->scomp('SELF:INFO', NAME => $n, WHAT => 'DESCR'); |
$descr =~ s/\\$//; |
$descr =~ s/\/$//; |
my $field = $m->scomp('SELF:GENERIC_FIELD', name => $n, id =>"${Display}_c_${row}_$col", |
Display => $Display, , row => $row, col => $col, description => $descr); |
$TEMPLATE =~ s/<DESCR:$n>/$descr/s; |
if($TEMPLATE =~ m/<FIELD:$n>/s){ |
$TEMPLATE =~ s/<FIELD:$n>/$field/s; |
}else{ |
die "Elemento mancante <FIELD:$n> nel template del recordset $Recordset\n"; |
} |
} |
</%perl> |
<%$TEMPLATE%> |
<script> |
% my $cols = @names; |
% if(!defined $Row){ |
<%$Display%>.bindEditComponents(1, <%$cols%>, '_s_', '_l_', '_c_', '_'); |
<%$Display%>.info = document.getElementById('<%$Display%>_info'); |
<%$Display%>.info.innerHTML = '? ( ? )'; |
% } |
</script> |
</%method> |
<%method BUTTON_Ctrl_filter> |
<%args> |
$Display |
</%args> |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" id="<%$Display%>_Ctrl_filter" type="button" |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons refresh', showLabel:true, title:'Applica il filtro di selezione ai dati'" |
onclick="<%$Display%>.loadRecords('rewind')">Filtra</button> |
</%method> |
<%method BUTTON_Ctrl_printsel> |
<%args> |
$Display |
$disp_print => undef |
</%args> |
% my $permission = Permission(); |
% $disp_print = $disp_print == 1 || ($disp_print eq '' && $permission->{Print}) ? '' : 'style="display: none;"'; |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" id="<%$Display%>_Ctrl_printsel" type="button" <% $disp_print %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons print', showLabel:true, title:'Stampa la selezione filtrata'" |
onclick="<%$Display%>.printSelected('recordset');">St.sel.</button> |
</%method> |
<%method BUTTON_Ctrl_xlssel> |
<%args> |
$Display |
$disp_xls => undef |
</%args> |
% my $permission = Permission(); |
% $disp_xls = $disp_xls == 1 || ($disp_xls eq '' && $permission->{Xls}) ? '' : 'style="display: none;"'; |
<button disabled data-dojo-type="dijit/form/Button" class="controlBtn" id="<%$Display%>_Ctrl_xlssel" type="button" <% $disp_xls %> |
data-dojo-props="tabIndex:-1, iconClass:'masonSqlIcons xls', showLabel:true, title:'Download selezione filtrata in formato XLS'" |
onclick="<%$Display%>.printSelected('xls_recordset');">XLS</button> |
</%method> |
<%method INIT_FIND_FIELDS> |
<%args> |
$Display |
$names |
</%args> |
<script> |
% my $cols = @{$names}; |
masonSql.once('ready', function(data){ |
require(["dijit/registry"], function(registry){ |
var disp = <%$Display%>; |
disp.navigationBar.filterButton = registry.byId('<%$Display%>_Ctrl_filter'); |
disp.navigationBar.printselButton = registry.byId('<%$Display%>_Ctrl_printsel'); |
disp.navigationBar.xlsselButton = registry.byId('<%$Display%>_Ctrl_xlssel'); |
disp.find_fields = [<%ListJscript('FIND_FIELDS', '', 'list') %>]; |
var finds = disp.finds = []; |
var ftypes = disp.ftypes = []; |
for(var col=0; col<<% $cols %>; col++){ |
finds[col] = document.getElementById('<%$Display%>_'+col+'_find'); |
ftypes[col] = document.getElementById('<%$Display%>_'+col+'_ftype'); |
} |
% for(my $col=0; $col<$cols; $col++){ |
% my $name = $names->[$col]; |
% if(exists $ARGS{"find_value_$name"}){ |
var w = finds[<%$col%>]; |
w.init_find_value = '<%$ARGS{"find_value_$name"}|js%>'; |
w.set_value(w.init_find_value); |
% } |
% if(exists $ARGS{"find_sel_$name"}){ |
var w = ftypes[<%$col%>]; |
w.init_find_sel = '<%$ARGS{"find_sel_$name"}|js%>'; |
w.set_value(w.init_find_sel); |
% } |
% } |
}); |
}); |
</script> |
</%method> |
<%method FIND>\ |
<%doc> |
FIND: metodo per costruire un form per il filtraggio dei record ... |
Al metodo FIND vengono passati tutti i parametri passati al form di inizializzazione |
è possibile definire dei valori iniziali da inserire nei campi del form di filtro |
aggiungendo dei parametri nel seguente modo: &find_value_<nome_campo>=VALORE&.... |
</%doc> |
<%args> |
$find_fields => $m->scomp('SELF:FIND_FIELDS') # elenco (nome1, nome2, nome3, ecc.) di campi da visualizzare per la ricerca |
$Recordset |
$Display |
$disp_find_print => undef # ... pulsante stampa nella sezione di ricerca |
$disp_find_xls => undef # ... pulsante espostazione XLS nella sezione di ricerca |
</%args> |
% my @names = &List2Array($find_fields); |
% my $cols = @names; |
%# $PLogger->debug(sub{ "NAMES= ", Dumper(\@names); }); |
<table class="FIND_form"> |
<tr><td class="nowrap"> |
% if($cols){ |
% for(my $col=0; $col<$cols; $col++){ |
% my $name=$names[$col]; |
% my $break=($name =~ s/\\$//); |
% my $descr = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'FIND_DESCR'); |
% $descr =~ s/\\$//; |
% $descr =~ s/\/$//; |
<span class="widget_span" id="Span_find_<%$Display.'_'.$col%>"> |
<%$descr%>:<& SELF:GENERIC_FIND, readonly => 0, name => $name, id =>$Display.'_'.$col, description => $descr, Display => $Display, col => $col, class=>'|_FIND' &> |
</span> |
% if($break){ |
</td><td class="nowrap"> |
% } |
% } |
<& SELF:BUTTON_Ctrl_filter, Display => $Display &> |
<& SELF:BUTTON_Ctrl_printsel, Display => $Display, disp_print => $disp_find_print &> |
<& SELF:BUTTON_Ctrl_xlssel, Display => $Display, disp_xls => $disp_find_xls &> |
% } |
</td></tr> |
</table> |
<& SELF:INIT_FIND_FIELDS, %ARGS, names => \@names &> |
</%method> |
<%method FIND_MENU>\ |
<%doc> |
FIND_MENU: metodo per costruire un form per il filtraggio dei record ... |
</%doc> |
<%args> |
$find_fields => $m->scomp('SELF:FIND_FIELDS') # elenco (nome1, nome2, nome3, ecc.) di campi da visualizzare per la ricerca |
$Recordset |
$Display |
$DescrOnRight => undef |
$disp_find_print => undef # ... pulsante stampa nella sezione di ricerca |
$disp_find_xls => undef # ... pulsante espostazione XLS nella sezione di ricerca |
</%args> |
% my @names = &List2Array($find_fields); |
% my $cols = @names; |
%# $PLogger->debug(sub{ "FIND_MENU cols=$cols fields='$find_fields'..."; }); |
%# $PLogger->debug(sub{ "NAMES= ", Dumper(\@names); }); |
%# $PLogger->debug(sub{ '#################################################', Dumper(\%ARGS); }); |
% if($m->base_comp->method_exists('FIND_MENU_PRE')){ |
<& SELF:FIND_MENU_PRE, find_fields => $find_fields, Recordset => $Recordset, Display => $Display &> |
% } |
<table class="FIND_MENU_form" id="<%$Display%>_elencoFiltriRestrizione"> |
% if($cols){ |
% for(my $col=0; $col<$cols; $col++){ |
<tr class="widget_span" id="Span_find_<%$Display.'_'.$col%>"> |
% my $name=$names[$col]; |
% my $break=($name =~ s/\\$//); |
% my $descr = $m->scomp('SELF:INFO', NAME => $name, WHAT => 'FIND_DESCR'); |
% $descr =~ s/\\$//; |
% $descr =~ s/\/$//; |
% if($DescrOnRight){ |
<td class="nowrap" align="right"><%$descr%>: </td> |
% } |
<td class="nowrap"><p> |
<%$DescrOnRight ? '' : $descr.':<br>'%>\ |
<& SELF:GENERIC_FIND, readonly => 0, name => $name, id =>$Display.'_'.$col, |
Display => $Display, col => $col, description => $descr, class=>'|_FIND' &> |
</p></td> |
</tr> |
% } |
<tr><td class="nowrap" width="100%"<%$DescrOnRight ? ' colspan="2"' : ''%>><p align="center"><br> |
<& SELF:BUTTON_Ctrl_filter, Display => $Display &> |
<& SELF:BUTTON_Ctrl_printsel, Display => $Display, disp_print => $disp_find_print &> |
<& SELF:BUTTON_Ctrl_xlssel, Display => $Display, disp_xls => $disp_find_xls &> |
</p></td></tr> |
% } |
</table> |
<& SELF:INIT_FIND_FIELDS, %ARGS, names => \@names &> |
% if($m->base_comp->method_exists('FIND_MENU_POST')){ |
<& SELF:FIND_MENU_POST, find_fields => $find_fields, Recordset => $Recordset, Display => $Display &> |
% } |
</%method> |
<%method WHERE></%method> |
<%method FIND_FIELDS><& SELF:FIELDS &></%method> |
<%method SORT_FIELDS><& SELF:FIND_FIELDS &></%method> |
<%method CONFIRM_DEL_MESSAGE>Conferma cancellazione dei record selezionati</%method> |
%# formato: id:table |
%# id = chiave_locale key = tabella padre |
<%method FATHER></%method> |
%# metodo per ricavare il nome del campo da usare in insert e update |
<%method FATHER_ID_NAME><%perl> |
# identifico il nome del campo |
# il campo è nel formato [tabella_join.]field:tabella_father[:id] |
if(my $father = $m->scomp('SELF:FATHER')){ |
$father =~ s/\s//gs; |
my($field, $father_name, $father_id) = split /\s*:\s*/, $father; |
$m->out($field); |
} |
</%perl></%method> |
%# metodo per ricavare la tabella padre |
<%method FATHER_NAME><%perl> |
# identifico il nome del campo |
# il campo è nel formato [tabella_join].field:tabella_father[:id] |
if(my $father = $m->scomp('SELF:FATHER')){ |
$father =~ s/\s//gs; |
my($field, $father_name, $father_id) = split /\s*:\s*/, $father; |
if($father_name !~ m/\./){ |
# aggiungo lo schema della tabella figlia |
my $schema = $m->scomp('SELF:SCHEMA'); |
$father_name = "$schema.$father_name"; |
} |
$m->out($father_name); |
} |
</%perl></%method> |
%# metodo per ricavare il nome del campo della tabella padre |
<%method FATHER_KEY_NAME>\ |
<%perl> |
# identifico il nome del campo |
# il campo è nel formato [tabella_join].field:tabella_father[:id] |
if(my $father = $m->scomp('SELF:FATHER')){ |
$father =~ s/\s//gs; |
my($field, $father_name, $father_id) = split /\s*:\s*/, $father; |
if(!$father_id){ |
if($father_name !~ m/\./){ |
# aggiungo lo schema della tabella figlia |
my $schema = $m->scomp('SELF:SCHEMA'); |
$father_name = "$schema.$father_name"; |
} |
$father_name =~ s/\./\//; |
my $father_table = $r->dir_config('DataBaseUrl').'/'.$father_name.'.mql'; |
if(!$m->comp_exists($father_table)){ |
die "Father $father_name not exists in FATHER method [$father]\n"; |
} |
$father_id = $m->scomp("$father_table:KEY_NAME"); |
} |
$m->out($father_id); |
} |
</%perl></%method> |
%# metodo per ricavare il nome della tabella e del campo di join della tabella padre |
<%method FATHER_TABLE_KEY_NAME>\ |
<%perl> |
# identifico il nome del campo |
# il campo è nel formato [tabella_join].field:tabella_father[:id] |
if(my $father = $m->scomp('SELF:FATHER')){ |
$father =~ s/\s//gs; |
my($field, $father_name, $father_id) = split /\s*:\s*/, $father; |
if($father_name !~ m/\./){ |
# aggiungo lo schema della tabella figlia |
my $schema = $m->scomp('SELF:SCHEMA'); |
$father_name = "$schema.$father_name"; |
} |
$father_name =~ s/\./\//; |
my $father_table = $r->dir_config('DataBaseUrl').'/'.$father_name.'.mql'; |
if(!$m->comp_exists($father_table)){ |
die "Father $father_name not exists in FATHER method [$father]\n"; |
} |
if($father_id){ |
$father_id = $m->scomp("$father_table:FROM").'.'.$father_id |
}else{ |
$father_id = $m->scomp("$father_table:KEY"); |
} |
$m->out($father_id); |
} |
</%perl></%method> |
<%method FATHER_WHERE>\ |
<%args> |
$FATHER_ID |
</%args>\ |
% my $field = $m->scomp('SELF:FATHER'); |
% # il campo è nel formato [tabella_join].field:tabella_father |
% $field =~ s/\:.*//; |
% $field =~ s/^\s+//; |
% my $father_id = str2sql_js_delimited($FATHER_ID); |
<% $field %> = <%$father_id%>\ |
</%method> |
%# elenco separato da , di tabelle figlie |
<%method CHILDREN></%method> |
%# elabora elenco aggiungendo lo schema del padre, se non specificato |
<%method SCHEMA_CHILDREN>\ |
<%perl> |
my $children = $m->scomp('SELF:CHILDREN'); |
my $schema = $m->scomp('SELF:SCHEMA'); |
$children =~ s/\s+//g; |
my @children = split /,/, $children; |
for(my $C=0; $C<@children; $C++){ |
if($children[$C] !~ m|/|){ |
$children[$C] = $schema.'/'.$children[$C]; |
} |
} |
$m->out(join(',', @children)); |
</%perl>\ |
</%method> |
%# tabella figlia selezionata (con container di tipo Tab o Accordion) |
<%method CHILD_SELECTED></%method> |
<%method SCHEMA_CHILD_SELECTED>\ |
<%perl> |
my $child_selected = $m->scomp('SELF:CHILD_SELECTED'); |
my $schema = $m->scomp('SELF:SCHEMA'); |
$child_selected =~ s/\s+//g; |
if($child_selected !~ m|/|){ |
$child_selected = $schema.'/'.$child_selected; |
} |
$m->out($child_selected); |
</%perl>\ |
</%method> |
%# elenco di nomi campo di "join" con le tabelle figlie (separato da ,) |
<%method CHILDREN_FIELDS></%method> |
<%method SELECT_CHILDREN_ID>\ |
<%args> |
$FIELDS |
$WHERE |
$ORDER => $m->scomp('SELF:ORDER_BY') |
</%args>\ |
select <% $FIELDS %> from <& SELF:JOIN_TABLES, %ARGS &> <% $WHERE %> <% $ORDER %>;\ |
</%method> |
%# nome della funzione associata al comando; se non indicata corrisponde al nome della tabella |
<%method FUNZIONE><& SELF:SCHEMA_FROM &></%method> |
%# genera i permessi in base al profilo dei permessi dell'utente |
<%method PERMISSION_BY_PROFILE>\ |
<%perl> |
my $funzione = $m->scomp('SELF:FUNZIONE'); |
$funzione =~ s/^\s+|\s+$//; |
my $Auth = $Session{Auth}{$funzione}; |
if(!defined $Auth){ |
die "Function $funzione is not defined in object ".$m->base_comp->path."\n"; |
} |
my @permission; |
for my $auth (keys %{$Auth}){ |
if($Auth->{$auth}){ |
push @permission, uc $auth; |
} |
} |
#DEBUG $PLogger->debug(sub{ "PERMISSION_BY_PROFILE for ".$m->scomp('SELF:SCHEMA_FROM')." from $funzione: ".join(' ', @permission); }); |
$m->out(join(' ', @permission)); |
</%perl>\ |
</%method> |
%# nome del file report da utilizzare |
%# orientamento e nessun parametro aggiuntivo |
<%method PRINT_FORM>\ |
% my $schema = $m->scomp('SELF:SCHEMA'); |
<& SELF:SCHEMA &>/<& SELF:FROM &>, PORTRAIT, \ |
</%method> |
<%method DB_LOG> |
<%args> |
$type # tipo dell'aggiornamento (insert,update,delete)) |
$id # identificativo del record |
$fields # hash dati modificati, inseriti o cancellati |
$old_fields => undef # hash dati prima della modifica (opzionale) |
$table_name => undef # nome tabella (opzionale) |
</%args> |
<%perl> |
DB_log($type, $id, $fields, $old_fields, $table_name); |
</%perl> |
</%method> |
%# Metodo per definire la stampa in formato PDF |
%# Method that prints PDF and ODT reports. |
<%method PDF>\ |
<%args> |
$GROUP_ID => undef # Identification of the group of records that will be printed with Report Manager (see "record_id" table) |
$report_ids => undef # The group of records that will be printed with ODT Reportman |
$LANDSCAPE => undef |
$report => undef |
</%args> |
<%perl> |
# Process parameters ... |
# PRINT_FORM which contains part of the report name, PORTRAIT/LANDSCAPE, REPORT_ID, various other parameters (for example KEY=100, Descr='Example report', K=5) |
my @params = &List2Array($m->scomp('SELF:PRINT_FORM', %ARGS)); |
my $form_report = shift @params; |
if($report){ |
$form_report .= $report; |
} |
# portrait or landscape |
if($params[0] =~ m/portrait|landscape/i){ |
# The parameter is discarded because it is only used by the client to open the preview window |
shift @params; |
} |
my $params = List2Params(join(', ', @params)); |
my $report_method = ReportMethod($form_report); |
$form_report =~ s/\.(odt|pdf|rep)$//; |
my $report_file = undef; |
my $die_msg = ''; |
if($report_method eq 'rep'){ |
($report_file, $die_msg) = FindReportmanFile($form_report); |
unless($report_file){ |
die $die_msg; |
} |
$m->comp('/lib/report.pdf', |
base => $r->dir_config('DataBaseUrl'), |
report => $form_report, |
report_method => $report_method, |
report_file => $report_file, |
GROUP_ID => $GROUP_ID, |
%{$params} |
); |
}else{ |
# When the REPORT_ID is passed as a cmd_parameter from ODT Reportman form, it overrides the values from the report_ids (see ODT Reportman documentation), |
if(defined $params->{REPORT_ID}){ |
my @array = ($params->{REPORT_ID}); |
$report_ids = \@array; |
delete $params->{REPORT_ID}; |
} |
$m->comp('/lib/report.pdf', |
report => $form_report, |
report_method => $report_method, |
report_ids => $report_ids, |
%{$params} |
); |
} |
</%perl> |
</%method> |
<%doc> |
Il metodo FORM_KEYS_MOVEMENT definisce quali tasti attivare nella navigazione tra i campi del form: |
ENTER - il tasto Invio(Enter) sposta il corsore nel campo sottostante |
ARROWS - viene attivata la navigazione nelle quattro direzioni con i tasti freccia (arrow) |
Esempio: <%method FORM_KEYS_MOVEMENT>ARROWS ENTER</%method> |
</%doc> |
<%method FORM_KEYS_MOVEMENT></%method> |
<%perl> |
############################################################################################# MAIN |
### $PLogger->debug(sub{ 'PARAMETRI ARGS=', Dumper(\%ARGS); }); |
### ATTENZIONE: La normalizzazione delle veriabili viene fatta in init.comp |
### e resa disponibile in %{$Session{ARGS}} |
#DEBUG $PLogger->debug(sub{ "PARAMETRI ARGS=", Dumper($Session{ARGS}); }); |
$m->clear_buffer; |
my $mime = $envelope_type{$ARGS{envelope_response}} || $mimelist{$method} || 'text/plain; charset=utf-8'; |
$r->content_type($mime); |
# preload permissions and check minimal Read permission |
Permission('Select'); |
#DEBUG $PLogger->debug(sub{ "method=$method\n".Dumper($Session{ARGS}); }); |
$m->base_comp->call_method($method, %{$Session{ARGS}}); |
</%perl>\ |
%# ATTENZIONE; è importante che questa riga termini senza <CR> finale |
/tags/2.0/htdocs/lib/error.comp |
---|
0,0 → 1,102 |
<%perl> |
$m->clear_buffer; |
my $timestamp; |
if($Session{Dbh}){ |
$Session{Dbh}->rollback; |
my $sth = $Session{Dbh}->prepare('select now();'); |
$sth->execute; |
$timestamp = $sth->fetchrow_arrayref->[0]; |
}else{ |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
$timestamp = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year+1900,$mon+1,$mday,$hour,$min,$sec; |
} |
my $status_code = $Session{StatusCode} || $r->status(400); |
$r->status($status_code); |
my @error = split /\t/, $error->as_line(); |
if($Session{'envelope_response'} eq 'json' || $Session{'envelope_response'} eq 'rest'){ |
$r->content_type('application/json; charset=utf-8'); |
if($Session{'envelope_response'} eq 'json'){ |
$r->headers_out->{'X-JSON-RPC'} = 'JSONError'; |
} |
if($PLogger->level eq $DEBUG){ |
$m->out(MasonSQL::JSONRPCUtils::json_rpc_error_response($analyzed_error, $message, $status_code, $timestamp)); |
}else{ |
$m->out(MasonSQL::JSONRPCUtils::json_rpc_error_response('-', shift(@error), $status_code, $timestamp)); |
} |
}elsif($Session{'envelope_response'} eq 'xml'){ |
$r->content_type('text/xml; charset=utf-8'); |
</%perl> |
<?xml version="1.0" encoding="utf-8"?> |
<error user="<%$Session{Login}%>" timestamp="<%$timestamp%>" code="<%$status_code%>"> |
<message><% shift @error |xml%></message> |
% if($PLogger->level eq $DEBUG){ |
% for(my$L=1; $L<@error; $L++){ |
<debug row="<%$L%>"><%$error[$L]|xml%></debug> |
% } |
% } |
</error> |
<%perl> |
}elsif($Session{'envelope_response'} eq 'none' || !defined($Session{'envelope_response'}) || $Session{'envelope_response'} eq '' ){ |
$r->content_type('text/html; charset=utf-8'); |
if($PLogger->level eq $DEBUG){ |
$m->out($error->as_html()); |
}else{ |
$m->out('<h3>', $error->as_brief(), '</h3>'); |
} |
}else{ |
$r->content_type('text/html; charset=utf-8'); |
</%perl> |
<html> |
<head> |
<title>Envelope error!</title> |
</head> |
<body> |
<% "Envelope type \"$Session{'envelope_response'}\" is not valid!" %> |
<% $error->as_html() %> |
</body> |
</html> |
% } |
<%once> |
use Data::Dumper; |
</%once> |
<%init> |
use Log::Log4perl; |
my $error = $r->pnotes('error'); |
my $analyzed_error = $error->analyze_error(); |
my $message = "Operazione annullata!\n"; |
#DEBUG print STDERR Dumper({ANALIZED_ERROR => $analyzed_error, ERROR => $error->full_message(), DUMP_ERROR => Dumper($error)}); |
# Verifico se si tratta di un errore di integrità referenziale di PostgreSQL - ESEMPIO: |
# 'DBD::Pg::st execute failed: ERROR: update or delete on table "soggetti" violates |
# foreign key constraint "id_soggetto" on table "siti" |
# DETAIL: Key (id)=(3763) is still referenced from table "siti" |
if($error =~ m/^DBD::Pg::st execute failed: ERROR:\s*(.*)DETAIL:(.*)\.\s*\[for Statement/si){ |
my $sql_err = $1; |
my $sql_err_detail = $2; |
if($sql_err =~ m/duplicate key value violates unique constraint "(.*)"/si){ |
my $index = $1; |
$message .= "Il valore immesso è già presente nell'archivio"; |
}elsif($sql_err =~ m/constraint "([^"]*)" on table "([^"]*)"/si){ |
my $constraint = $1; |
my $table = $2; |
$message .= "L'oggetto in $table non può essere cancellato/alterato in quanto\nci sono altri oggetti che vi fanno riferimento ($constraint)."; |
}else{ |
$message .= "Database error!"; |
} |
if($PLogger->level eq $DEBUG){ |
$message .= "\n\n[".$error->full_message."]"; |
} |
}else{ |
$message = $error->full_message(); |
} |
if($PLogger){ |
$PLogger->error(sub{"envelope_response:$Session{envelope_response} - ".$error->as_string()}); |
}else{ |
print STDERR "envelope_response:$Session{envelope_response} - ".$error->as_string() |
} |
</%init> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/lib/httpRequestMason.js |
---|
0,0 → 1,550 |
<%doc> |
Authors: |
BA Brent Ashley <hReqMason_@megahuge.com> codice originario di partenza |
GDO Guido brugnara <gdo@leader.it> tutte le modifiche successive |
TRC Tarcisio Fedrizzi <tarch@leader.it> |
24/02/2018 GDO |
Limita l'esecuzione di "XMLHttpRequest" per evitare un Bug di Firefox che con più |
di 6 chiamate pone in attesa le chiamate in più ma poi le riattiva solo dopo 15 |
secondi. |
07/06/2006 TRC |
Creata una funzione che gestisce in maniera ibrida GET e POST decidendo a seconda del |
tipo dei dati passati se stringa array o null usa il metodo vecchio GET + oggetto in |
get, se viene invece passato un oggetto utilizza il POST. Modificata anche la gestione |
dell'oggetto XMLHttpRequest che per mozilla viene creato solo una volta all'inizio. |
Corretto anche un errore che dipendeva dal fatto che i parametri per una callback |
venivano attaccati all'oggetto ContextObj dopo la chiamata del timeout. Ora puo' |
essere passato un oggetto come parametro al metodo hReqMason_ExecuteTimeout in maniera |
che questo venga appiccicato all'oggetto contextObj selezionato dal pool nel campo |
obj_parms. |
07/05/2006 GDO |
Eliminato dal codice l'utilizzo di container DIV/SPAN in quanto si utilizza unicamente XMLHttpRequest quale metodo per il download |
30/04/2006 GDO |
Riscrittura del codice con integrazione in Mason anche per differenziare il codice |
tra IE e Moz. |
12/04/2004 GDO |
Libreria intermedia che utilizza le classi "XMLHttpRequest" per Mozilla e "Microsoft.XMLHTTP" per IE |
che permettono un maggior controllo sugli errori durante il caricamento, compresi i casi |
di mancata connessione per non risoluzione del DNS o errori dello stack TCP .... riscontrati |
nel caso di reti congestionate (con il risultato non desiderato di errori di Timeout) |
07/04/2004 GDO |
Parameter format compatible with Mason |
26/07/2001 BA Rel 2.0 (release utilizzata in partenza) |
Il codice è derivato dal lavoro di Brent Ashley [hReqMason_@megahuge.com http://www.ashleyit.com/rs/] |
la cui licenza Open Source è la seguente: |
License: |
You can use this however you like. I make no guarantees whatsoever that it |
will suit your purpose. You take full responsibility for getting it working |
properly and for any implications of its failure or inability to satisfy your |
every need. |
Possibili migliorie: |
1) unica istanza oggetto XMLHttpRequest per ciascun "context" |
2) gestione chiamate POST |
</%doc> |
dojo.require("dojo.json"); |
dojo.require("dojox.encoding.digests._base"); |
dojo.require("dojox.encoding.digests.MD5"); |
// callback pool needs global scope |
var hReqMason_ContextPoolSize = 0; |
var hReqMason_ContextMaxPool = 32; |
var hReqMason_ContextPool = {}; |
var hReqMason_Interval = 200; // intervallo di verifica dello stato del caricamento |
%#// numero massimo di chiamate XMLHttpRequest in esecuzione contemporaneamente |
%#// In firefox 52 e 59 Quantum se >3 ogni tanto una chiamata non viene inviata |
%#// anche se presente nel debug network, poi va in timeout. |
var hReqMason_MaxConcurrent = <% $Session{Browser}->firefox ? 3 : 'hReqMason_ContextMaxPool' %>; |
// constructor for context object |
function hReqMason_ContextObj( contextID, tag ){ |
// properties |
this.id = contextID; |
this.tag = tag; |
this.URL = null; |
this.busy = false; |
this.callStack = new Array(); |
// methods |
this.POST = hReqMason_contextPOST; |
var req = new XMLHttpRequest(); |
req.onload = httpRequest_handler; |
req.onerror = httpRequest_handler; |
req.hReqMason_obj = this; |
this.httpRequest = req; |
// annulla la chiamata |
this.abort = hReqMason_abort; |
} |
// chiamata a conclusione del caricamento remoto |
function httpRequest_handler(){ |
var httpRequest = this; |
var contextObj = this.hReqMason_obj; |
var contextID = contextObj.id; |
var ERROR = 'ERROR'; |
var ERR = null; |
switch(httpRequest.readyState) { |
case 1,2,3: |
ERR = 'Errore dal browser: '+httpRequest.status+' stato: '+httpRequest.readyState; |
break; |
case 4: |
if(httpRequest.status == 200){ |
var headers = httpRequest.getAllResponseHeaders(); |
// get context object and invoke callback |
var JSONResponse; |
if(!(/X-JSON-RPC/i.test(headers))){ |
JSONResponse = {version:1.1, result:httpRequest.responseText}; |
}else{ |
JSONResponse = dojo.json.parse(httpRequest.responseText); |
} |
if(JSONResponse){ |
if(JSONResponse.error){ |
ERR = JSONResponse.error.message; |
ERROR = 'SERVER'; |
window.status = 'Errore JSON ricevuto dal server'; |
}else{ |
window.status = 'Completato caricamento'; |
hReqMason_callbackStack(JSONResponse.result, contextID); |
} |
}else{ |
if(httpRequest.responseText.length == 0){ |
window.status = ERR = 'ERRORE: ricevuto inaspettatamente un messaggio vuoto'; |
}else{ |
window.status = ERR = 'ERRORE JSON: dati non validi ricevuti dal server'; |
ERR += '\n' +"[" + httpRequest.responseText + "]"; |
} |
ERROR = 'SERVER'; |
} |
}else if(httpRequest.status == 403){ |
ERR = 'Accesso negato; la sessione è probabilmente scaduta'; |
ERROR = 'AUTHFAILED'; |
window.status = 'Accesso negato'; |
}else{ |
if(httpRequest.status == 0 && httpRequest.responseText == ''){ |
ERROR = 'SERVER'; |
ERR = 'Il server non risponde'; |
}else{ |
var error = dojo.json.parse(httpRequest.responseText); |
if(error){ |
ERROR = 'SERVER'; |
ERR = error.message; |
}else{ |
ERR = httpRequest.status + ' ('+httpRequest.statusText + ')'; |
} |
} |
} |
break; |
} |
if(ERR != null){ |
// verifico se l'oggetto esiste ancora, altrimenti tralascio l'errore, dato che l'oggetto è stato distrutto |
if(contextObj){ |
hReqMason_Error(contextObj.id, ERR, 'Errore durante il caricamento dati ', ERROR) |
}else{ |
concole.error('httpRequest_handler', httpRequest, ERR); |
} |
} |
contextObj && contextObj.rspage != null && contextObj.abort(); |
return false; |
} |
//Sistemare content-type |
function hReqMason_getURL(contextObj, URL, parm, doPost){ |
%#DEBUG// console.debug('hReqMason_getURL id:'+contextObj.id + ' ' + URL); |
// make the call |
contextObj.busy = true; |
var req = contextObj.httpRequest; |
%#DEBUG <% $JSLogger->debug(q|'hReqMason_getURL id:'+contextObj.id+' Post:' + doPost + ' URL:' + URL + ' PARM:'+parm|) %>\ |
req.open(doPost ? "POST" : "GET", URL, true); |
req.setRequestHeader('Content-Type', 'multipart/form-data; charset=utf-8'); |
req.send(parm); |
} |
// Genera un id unico per le chiamate in "vecchio stile" =) |
function getUnique(){ |
return ((new Date()).getTime() + '' + Math.floor(1000 * Math.random())); |
} |
// Nuova funzione che utilizza POST + JSON |
// resa ora compatibile con la vecchia per |
// gestire anche i casi gestiti in precedenza |
// cosi' da poter fare il porting con calma |
function hReqMason_contextPOST(){ |
var URL = this.rspage; |
var parms = this.parms; |
var strParms; |
var post = null; |
var doPost = false; |
if (URL == null || URL == ''){ |
hReqMason_getURL(this, '/blank.html', null); |
return; |
} |
URL += "?C=" + this.id; |
URL += "&U=" + getUnique(); |
URL += "&envelope_response=json"; |
if (this.func != null){ |
URL += "&method=" + hReqMason_Escape(this.func); |
if (parms != null){ |
if (parms.constructor == String){ |
// single parameter |
URL += "&P=" + hReqMason_Escape('' + parms); |
}else if (parms.constructor == Array){ |
for( var i=0; i < parms.length; i++ ){ |
URL += "&P=" + hReqMason_Escape('' + parms[i]); |
} |
}else if (typeof(parms) == "object"){ // parm type |
URL = this.rspage; |
URL += "?U=" + getUnique() + "&envelope_request=json"; |
var toSend = {version:"1.1", method:hReqMason_Escape(this.func), params:parms, envelope_response:"json"}; |
doPost = true; |
post = dojo.json.stringify(toSend); |
}else{ |
my_alert('Unhandled type ' + parms + ' !', 'txt'); |
return; |
} |
} |
} |
hReqMason_getURL(this, URL, post, doPost); |
} |
// end of context constructor |
function hReqMason_GetContextID(tag){ |
var contextObj; |
// riutilizza un contenitore libero |
for (contextID in hReqMason_ContextPool){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(!contextObj.init && !contextObj.busy && contextObj.tag == tag){ |
contextObj.URL = null; |
%#DEBUG// console.debug('hReqMason_GetContextID '+ contextObj.id + ' ' + tag); |
return contextObj.id; |
} |
} |
// if we got here, there are no existing free contexts |
if ( hReqMason_ContextPoolSize <= hReqMason_ContextMaxPool ){ |
// create new context |
var contextID = "hReqMason_" + (hReqMason_ContextPoolSize + 1); |
hReqMason_ContextPool[ contextID ] = new hReqMason_ContextObj( contextID, tag ); |
hReqMason_ContextPoolSize++; |
%#DEBUG// console.debug('hReqMason_GetContextID new ' + contextID + ' ' + tag); |
return contextID; |
} else { |
my_alert( "hReqMason_ Error: context pool full", 'txt'); |
return null; |
} |
} |
// verifico se c'è attiva una chiamata con la stessa URL (rspage) |
function hReqMason_ContextFindURL(URL, tag){ |
var contextObj; |
for (var contextID in hReqMason_ContextPool){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(contextObj.busy && contextObj.URL == URL && contextObj.tag == tag){ |
%#DEBUG// console.debug('hReqMason_ContextFindURL FINDED', URL, tag, contextObj); |
return contextObj.id; |
} |
} |
// var id = hReqMason_GetContextID(tag); |
// contextObj = hReqMason_ContextPool[id]; |
%#DEBUG// console.debug('hReqMason_ContextFindURL NEW', URL, tag, contextObj); |
// return id; |
return hReqMason_GetContextID(tag); |
} |
// call a server routine from client code |
function hReqMason_Execute( rspage, callback, func, parms){ |
return hReqMason_ExecuteTimeout(rspage, 30000, DefaultTimeout, callback, func, parms, null, null, null); |
} |
// abort the request |
function hReqMason_abort(){ |
this.callStack = new Array(); |
// annullo timer timeout |
window.clearTimeout(this.EtTimeout); |
this.EtTimeout=null; |
// annullo callback |
this.EtCallback=null; |
this.busy = false; |
this.init = false; |
this.rspage = null; |
this.parms = null; |
this.func = null; |
this.URL = null; |
// annullo chiamata |
this.httpRequest.abort(); |
hReqMason_CheckPool(); |
} |
// abort all the request |
// richiamata dall'evento window close (window.onclose) per evitare che vi siano chiamate pendenti |
// che arrivano dopo che la finestra è stata chiusa |
function hReqMason_abort_all(){ |
for (var contextID in hReqMason_ContextPool){ |
hReqMason_ContextPool[contextID].abort(); |
} |
} |
// chiamata in caso di errore |
// |
function hReqMason_Error( contextID, str, str2, typeError ){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(str2 == null) |
str2 = 'ERROR from server for '; |
if(contextObj){ |
var callStack = contextObj.callStack; |
contextObj.abort(); |
if (typeError == 'AUTHFAILED'){ |
var w = 540; |
var h = 620; |
var left = (screen.width - w) / 2; |
var top = (screen.height - h) / 3; |
window.open('/welcome.html?U='+getUnique(), 'masonSqlLogon', 'width='+w+',height='+h+',top='+top+',left='+left+',directories=no,location=no,menubar=no,status=no,toolbar=no'); |
} |
// clean up and return context to pool |
var contextCall; |
while(contextCall = callStack.shift()){ //intentional assignment |
if(contextCall.timeout_callback){ |
try{ |
contextCall.timeout_callback(contextID, typeError, str, contextCall.callback_obj); |
}catch(err){ |
console.error('ERROR to execute timeout_callback:', err, str); |
my_alert_error('ERROR to execute timeout_callback: '+err.message + '\n' +contextCall.timeout_callback.toString()+ |
'\n---------------------------\ntypeError:'+typeError+' str:'+str); |
} |
}else{ |
my_alert(str2+contextObj.URL+':\n['+unescape(str)+']', 'pre'); |
} |
} |
contextObj.abort(); |
}else{ |
my_alert('ERROR (no contextObj):\n['+unescape(str)+']', 'pre'); |
} |
} |
function hReqMason_Escape( thing ){ |
var R = escape(thing); |
// Sostituzione per la corretta gestione del carattere euro |
R = R.replace(/%u20AC/g, '%A4'); |
// sostituisco simbolo '+' per evitare che venga sostituito da ' ' sul server (MASON ???) |
return R.replace(/\+/g, '%2B'); |
} |
function hReqMason_Load_Callback(str, contextID) { |
var contextObj = hReqMason_ContextPool[contextID]; |
var Dest = contextObj.obj_params.Loadobj; |
//GDO my_alert("hReqMason_Load_Callback "+contextID+' URL='+contextObj.URL+'\n'+str, 'txt'); |
hReqMason_innerHTML(Dest, str); |
var contextObj = hReqMason_ContextPool[contextID]; |
if(contextObj.obj_params.Loadcallback != null){ |
contextObj.obj_params.Loadcallback(contextObj.obj_params.Loadobj, contextID); |
contextObj.obj_params.Loadcallback = null; |
} |
} |
// recupera documento remoto e lo sostituisce nell'oggetto locale "obj" (SPAN, BODY, ecc.) |
function hReqMason_Load(obj, callback, url, params){ |
return hReqMason_LoadTimeout(obj, 30000, DefaultTimeout, callback, url, params); |
} |
// recupera documento remoto e lo sostituisce nell'oggetto locale "obj" (SPAN, BODY, ecc.) |
// supporta funzioni di callback su timeout della ricezione |
function hReqMason_LoadTimeout(obj, timeout, timeout_callback, callback, url, params){ |
// obj.innerHTML='<p style="height: 100%"></p>'; |
if(url){ |
return hReqMason_ExecuteTimeout('/lib/getDocument.mason', timeout, timeout_callback, hReqMason_Load_Callback, url, params, null, { Loadobj: obj, Loadcallback:callback}); |
} |
return null; |
} |
// funzione callback di hReqMason_ExecuteTimeout |
function hReqMason_callbackStack(str, contextID) { |
var contextObj = hReqMason_ContextPool[contextID]; |
//GDO my_alert("hReqMason_callbackStack("+contextID+","+str+")", 'txt'); |
window.clearTimeout(contextObj.EtTimeout); |
contextObj.URL = null; |
var contextCall; |
// richiamo le callback presenti nello stack |
while(contextCall = contextObj.callStack.shift()){ // intentional assignment |
%#DEBUG// console.debug('contextCall callback', contextCall); |
try{ |
contextCall.callback(str, contextID, contextCall.callback_obj); |
}catch(err){ |
console.error('ERROR to execute callback:', err, contextCall.callback, contextID, contextCall.callback_obj, str); |
my_alert_error('ERROR to execute callback: '+err.message+'\n----------\nstack:'+err.stack+'\n----------\ncallback:'+contextCall.callback.toString()+ |
'\n----------\ncontextID:'+contextID+' str:'+str); |
} |
} |
} |
// funzione di controllo dello stato di tutte le chiamate; provvede a lanciare le chiamate |
// quando le chiamate parallele sono inferiori al limite prefissato |
function hReqMason_CheckPool(){ |
// conto le chiamate attive e mi annoto la prima chiamata da attivare |
var count = 0; |
for (var contextID in hReqMason_ContextPool){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(contextObj.busy){ |
count++; |
} |
} |
for (var contextID in hReqMason_ContextPool){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(count >= hReqMason_MaxConcurrent){ |
return; |
} |
if(contextObj.init){ |
count++; |
contextObj.init = false; |
contextObj.POST(); |
} |
} |
} |
// funzione callback di hReqMason_ExecuteTimeout in caso di timeout ricezione |
function hReqMason_EtTimeout(contextID) { |
var contextObj = hReqMason_ContextPool[contextID]; |
if(contextObj){ |
// verifico se il conteggio degli intervalli è finito |
contextObj.EtTimeoutCounter -= 1; |
if(contextObj.EtTimeoutCounter>0){ |
if(!contextObj.init){ |
// chiamata in corso |
var httpRequest = contextObj.httpRequest; |
// verifico lo stato del caricamento del documento |
if(httpRequest && httpRequest.readyState == 4 && httpRequest.status != 200){ |
hReqMason_Error(contextID, 'Errore durante il caricamento della pagina code:'+httpRequest.status + '\n\n' + httpRequest.responseText, 'Error from browser ', 'ERROR'); |
return; |
} |
} |
// DEBUG// GDO window.status = 'caricamento '+contextObj.id+' '+contextObj.EtTimeoutCounter+' '+contextObj.URL; |
// ritardo un'altro intervallo |
contextObj.EtTimeout=window.setTimeout("hReqMason_EtTimeout('"+contextObj.id+"')", hReqMason_Interval); |
}else{ |
contextObj.EtTimeout = null; |
window.status = 'timeout '+contextObj.id+' '+contextObj.URL; |
hReqMason_Error(contextID, 'Errore TIMEOUT durante il caricamento', 'Errore TIMEOUT', 'TIMEOUT'); |
} |
} |
} |
// esegue il comando remoto con un timeout sulla ricezione |
// rspage - href to asp file |
// timeout - timeout for receive data |
// timeout_callback - function to call on timeout |
// callback - function to call on return |
// or null if no return needed |
// (passes returned string to callback) |
// func - sub or function name to call |
// parms - string parameter to function |
// or array of string parameters if more than one |
// tag - oggetto o tag o etichetta di riferimento per il riuso dei container nella stessa finestra |
// (usato quando si hanno più finestre IFRAME) |
// obj_params - oggetto che viene appiccicato al contextObj selezionato dalla ricerca nel pool |
// callback_obj - oggetto passato alla chiamata della callback (se ci sono delle chiamate contemporanee ogni chiamata ha il suo oggetto) |
// Restituisce l'oggetto della chiamata |
function hReqMason_ExecuteTimeout(rspage, timeout, timeout_callback, callback, func, parms, tag, obj_params, callback_obj){ |
%#DEBUG// <% $JSLogger->debug(q|'hReqMason_ExecuteTimeout rspage:'+rspage+' timeout:'+timeout+' func:'+func+' parms:'+dojo.json.stringify(parms)+' tag:'+tag|) %>\ |
var NEW_URL=rspage+'->'+func; |
if (!parms || parms.constructor == String || parms.constructor == Array){ |
NEW_URL += '(' + parms + ')'; |
}else{ |
NEW_URL += '#' + dojox.encoding.digests.MD5(dojo.json.stringify(parms), dojox.encoding.digests._base.outputTypes.Hex); |
} |
var contextID = hReqMason_ContextFindURL(NEW_URL, tag); |
var contextObj = hReqMason_ContextPool[contextID]; |
contextObj.obj_params = obj_params; |
//GDO my_alert("URL="+contextObj.URL+" NEW="+NEW_URL+" ID="+contextObj.id); |
var contextCall = { |
'contextObj': contextObj, |
'callback': callback, |
'callback_obj': callback_obj, |
'timeout_callback': timeout_callback |
}; |
// aggiungo nello stack la nuova richiesta |
contextObj.callStack.push(contextCall); |
if(contextObj.URL != NEW_URL){ |
// si tratta della prima chiamata |
contextObj.rspage = rspage; |
contextObj.func = func; |
contextObj.parms = parms; |
contextObj.URL = NEW_URL; |
contextObj.init = true; |
if(timeout != null && timeout){ |
contextObj.EtTimeoutCounter = (timeout/hReqMason_Interval)+1; |
contextObj.EtTimeout = window.setTimeout("hReqMason_EtTimeout('"+contextObj.id+"')", hReqMason_Interval); |
}else{ |
contextObj.EtTimeout = null; |
} |
hReqMason_CheckPool(); |
} |
return contextObj.id; |
} |
function DefaultTimeout(contextID, err, str){ |
var contextObj = hReqMaso |
n_ContextPool[contextID]; |
if(err == 'TIMEOUT'){ |
my_alert('Timeout ricezione dati URL ' + contextObj.URL + ' ID=' + contextID, 'txt'); |
}else{ |
my_alert('Errore ricezione dati URL ' + contextObj.URL + ' ID=' + contextIDerr+':\n'+str, 'txt'); |
} |
} |
// carica il codice HTML in "str" nell'oggetto DOM "Dest" preoccupandosi di eseguire il codice <sc*ipt> |
function hReqMason_innerHTML(destination, str){ |
destination.disabled = false; |
// distruggo eventuali widget presenti nel contenitore |
dojo.forEach(dijit.findWidgets(destination), function(widget) { |
widget.destroyRecursive(false); |
}); |
// svuoto il contenitore |
dojo.empty(destination); |
// my_alert(str,'txt'); |
// my_alert("hReqMason_innerHTML MOZ\n"+str, 'txt'); |
try{ |
destination.innerHTML=str; |
}catch(err){ |
console.error('hReqMason_innerHTML HTML', err, str); |
my_alert_error('hReqMason_innerHTML HTML', err, str); |
return; |
} |
var codelist = destination.getElementsByTagName('script'); |
// Nota: non usare direttamente codelist.length in quanto il numero di script cresce dinamicamente durante l'esecuzione |
// se ci sono errori ... |
var maxI = codelist.length; |
for(var I=0; I<maxI; I++){ |
var code = codelist[I].text |
try{ |
window.eval(code); |
}catch(err){ |
console.log('hReqMason_innerHTML CODE('+I+')', err, code); |
my_alert_error('hReqMason_innerHTML CODE('+I+')', err, code); |
return; |
} |
} |
//I=I-1; my_alert("LAST EVAL "+I+":\n"+codelist[I].text, 'pre'); |
%#DOJO dojo.addOnLoad(function(destination){ |
%#DOJO if(destination){ |
%#DOJO // parsing di eventuali widget Dojo |
%#DOJO try{ |
%#DOJO dojo.parser.parse(destination); |
%#DOJO }catch(err){ |
%#DOJO console.error('dojo.parser.parse', err, destination); |
%#DOJO my_alert_error('dojo.parser.parse', err); |
%#DOJO } |
%#DOJO } |
%#DOJO }); |
} |
/tags/2.0/htdocs/lib/databinding.js |
---|
0,0 → 1,941 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2003 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
---+ libreria DataBinding |
La libreria implementa un modello client-server per la gestione remota. |
I dati in transito si limitano a <max_form_rows> righe che vengono visualizzate nel form. |
I dati vengono collocati nella matrice <data[row,col]>, mentre le chiavi univoche nel |
database vengono collocate nel vettore <keys[row]>. |
Al caricamento del primo blocco di dati la libreria inizializza anche il seguente vettore: |
* Vettore <names[col]> con i nomi dei campi nel database |
Al caricamento dei blocchi dati vengono caricate le seguenti matrici, vettori: |
* Matrice <data[row,col]> con i dati del recordset richiesto, un record per ogni riga |
con i valori dei singoli campi disposti nella riga. |
* Vettore <keys[row]> con le chiavi univoche dei record del recordset |
Tutte le operazioni si modifica, inserimento e cancellazione tengono sincronizzati i dati tra |
il database remoto ed i dati contenuti nell'oggetto. |
---++ DataBinding Master -> Detail |
E` implementato il meccanismo che permette la sinconizzazione dei dati di una tabella padre "master" con i |
dati visualizzati di una o più tabelle figlie "detail". |
La tabella padre viene rappresentata un record alla volta (form di tipo FORM, LINEAR o TEMPLATE), |
mentre le tabelle figlie vengono rappresentate da form di tipo TABLE o DIVS ma anche FORM o LINEAR. |
Per definire le relazioni tra le tabelle vanno definite nei file di definizione dei recordset (data/<recordset>.mql) |
del padre i metodi CHILDREN e CHILDREN_FIELDS rispettivamente con l'elenco delle tabelle figlie ed elenco dei campi chiavi. |
Per ciacuna delle tabelle figlie va invece definito il metodo FATHER con il valore <idref>:<table>:<key>, dove <idref> |
è la chiave locale, <table> è il nome della tabella padre e <key> è il campo chiave della tabella padre corrispondente |
a <key>; se omesso si fa riferimento alla chiave indicata nella tabella padre |
Per attivare il meccanismo di sincronizzazione è necessario creare innanzitutto un DataBinding per ciascuna delle |
tabelle interessate per poi completare nel DataBinding figlio l'attributo .father con il riferimento al DataBinding |
del padre e nel padre l'attributo array .children[] con i riferimenti ai recordset figli. |
A seguito della configurazione iniziale, ad ogni variazione del record visualizzato nel form padre si ha conseguentemente la |
sincronizzazione delle tabelle figlie. |
</%doc> |
<%once> |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
my $GetRecordTimeout = $r->dir_config('GetRecordTimeout'); |
</%once> |
// variabile globale con i riferimenti nome --> oggetto DataBinding |
DataBinding_ContextPool = {}; |
// Oggetto DataBinding per la navigazione di dati SQL nel browser |
// |
// constructor for DataBinding object |
// Parametri: |
// prefix - prefisso da utilizzare per i nomi dei campi nell'oggetto |
// from - nome (senza .mql) della tabella |
// max_table_rows - numero di righe a disposizione nella matrice |
// |
function DataBinding(prefix, from, max_table_rows){ |
// properties |
this.max_table_rows = max_table_rows; |
this.max_rows = null; |
%#DEBUG//my_alert("DataBinding("+prefix+", "+from+", "+max_table_rows+")"); |
this.prefix = prefix; |
this.from = from; |
this.hReqMason_ID = null; |
// timeout di attesa della risposta |
this.timeout = <%$GetRecordTimeout%>; |
// vettore delle chiavi (PK) del recordset |
this.keys = []; |
// posizione nell'array della riga di una determinata chiave record |
this.pos_key = []; |
// matrice dei dati non modificati |
this.data = []; |
// matrice dei parametri aggiuntivi associati ai dati (usato per i widget htmlselect divselect ecc.) |
this.params = []; |
// matrice dei dati da modificare sul server |
this.new_data = []; |
// vettore contenente i valori di default da attribuire ai campi |
// indicati in <method FIELDS_NEW> |
this.new_fields = []; |
// vettore contenente le modalità con cui ciascun campo deve essere copiato da una duplicazione |
// 'D' --> da copiare, 'd' --> copiare solo se != '' |
// indicati in <method FIELDS_DUP> |
this.dup_fields = []; |
// determined with <method FIELDS_COPY_PASTE> |
this.cp_fields = []; |
// key of the copied row to be pasted with copy-paste method |
this.cp_key = null; |
// chiavi dei record duplicati (vedi displaybinding.js:DisplayBinding_onchangeHandler) |
this.dup_keys = []; |
// contiene i nomi dei campi nell'ordine in cui vengono forniti nella matrice (colonne) |
this.names = []; |
// vettore true/false dei campi che al salvataggio non devono essere vuoti |
this.required_fields = []; |
// contiene le descrizioni dei campi |
this.descriptions = []; |
// contiene le posizioni dei campi, individuati dal loro nome (è l'inverso di .names) |
this.pos_name = {}; |
// componente select |
this.select = ''; |
// clausola where nel formato json [ 'field', 'cond', value], ['--where', 'sql where'], ... ] |
this.json_where = ''; |
// parametri supplementali da inviare al server |
this.query_param = null; |
// clausola "order by xxx" |
this.orderby = ''; |
// posizione di inizio del recordset corrente |
// inizializzato a null; dopo la prima connessione conterrà un intero da 0 a n-1 max_records |
this.start = null; |
// oggetto DataBinding padre (per la sincronizzazione di tabelle MASTER-->DETAIL) |
this.father = null; |
// array di oggetti DataBinding figli (per la sincronizzazione di tabelle MASTER-->DETAIL) |
this.children = []; |
// matrice di chiavi per selezionare i record figli; |
// vedi <method SELECT_CHILDREN_ID> e <method CHILDREN_FIELDS> |
this.fathers_id = []; |
// riga del recordset da utilizzare quale padre delle tabelle figlie |
this.rowFather = null; |
// chiave per selezionare i record in base al codice della tabella MASTER |
// == null o '' recordset di tipo master |
// == -1 il padre non è definito (attenzione: lato server verrà restituito un figlio con elenco vuoto) |
this.father_id = null; |
// chiave per modificare i record in base al codice della tabella MASTER |
this.father_id_update = null; |
// utilizzato per anticipare la valutazione delle differenze |
this._difference = null; |
// select attivato |
this.canSelect = false; // non è implementato questo controllo !!!! |
// insert attivato |
this.canInsert = false; |
// delete attivato |
this.canDelete = false; |
// update attivato; |
this.canUpdate = false; |
// print attivato |
this.canPrint = false; |
// print all recordset attivato |
this.canPrintsel = false; |
// recordset in sola lettura |
this.readonly = true; |
// condizione di cambio stato solo lettura/scrittura |
this.changed_readonly = false; |
// matrice dei campi in sola lettura |
this.fields_ro = []; |
// vettore campi in sola lettura ma considerati in aggiornamento (tipico dei campi chiave) |
this.fields_ro_update = []; |
// definisco il comportamento quando ci sono due richieste di aggiornamento del recordset |
this.delete_previus_req = false; // se true viene annullata la richiesta in corso ed inoltrata la nuova |
// tipo di chiamata (top, up, down, inser, update, ecc.) in corso |
this.call_mode = null; |
// methods |
// Save and restore row to be copied (used by Copy-Paste) during onrequest and onchange events |
this.storeRowToCopy = DataBinding_storeRowToCopy; |
this.retrieveRowToCopy = DataBinding_retrieveRowToCopy; |
// restituisce la URL da inviare al server per ottenere la stampa in formato PDF |
this.printUrl = DataBinding_printUrl; |
// recupera i dati dal server (con inizializzazione del recordset) |
this.loadRecords = DataBinding_loadRecords; |
// lancia un metodo remoto sul server definito come CALL_REMOTE_<function> |
this.callRemote = DataBinding_callRemote; |
// posizionamento nel recordset corrente (recordset persistente nel server) |
this.gotoRecords = DataBinding_gotoRecords; |
// inizializzazione del recordset |
this.initRecordset = DataBinding_initRecordset; |
// Annulla le modifiche in corso |
this.cancelUpdate = DataBinding_cancelUpdate; |
// .type_div restituisce il tipo di form del record di posizione nel recordset "num_record" |
// alla inizializzazione è null (funzionalità disabilitata) |
this.type_div = null; |
// modifica lo stato lettura/scrittura del recordset |
this.readOnly = DataBinding_readOnly; |
// cancella i record elencati in keyList |
this.deleteRecords = DataBinding_deleteRecords; |
// stato del download in corso. Accetta un parametro, se true l'eventuale download in corso viene abortito |
this.statusDownload = DataBinding_statusDownload; |
// restituisce il valore del campo (parametri nome campo e opzionale riga) |
this.get_value = DataBinding_get_value; |
// modifica il valore del campo (parametri nome campo e opzionale riga) |
this.set_value = DataBinding_set_value; |
// Aggiorna i recordset figli |
this.updateChildren = DataBinding_updateChildren; |
// dopo un aggiornamento indica se ci sono state variazioni nel recordset sul server |
this.recordset_changed = null; |
// eventi gestiti dall'oggetto recordset |
this.onloadrecord = null; // richiama la funzione indicata quando arriva una richiesta di cambiamento del recordset |
this.ondeleterecords = null; // richiama la funzione indicata quando arriva una richiesta di cancellazione di records |
this.onrequest = null; // richiama la funzione indicata quando è iniziata una richiesta al server di cambio del recordset |
this.onprechange = null; // richiama la funzione indicata al cambio del recordset, prima che i dati siano disponibili |
this.onchange = null; // richiama la funzione indicata al cambio del recordset, quando i dati sono disponibili |
this.onchange_children = null; // richiama la funzione indicata quando tutti i recordset (padre e figli) sono stati aggiornati |
this.onpreload = null; // chiamata prima della prima inizializzazione |
this.onload = null; // chiamata dopo la prima inizializzazione |
this.onerror = null; // chiamata in caso di errore |
this.onreadonly = null; // chiamata quando cambia lo stato lettura/scrittura |
this.ondiff_recordset = null; // chiamata quando c'è una differenza nel recordset prima della trasmissione al server |
} |
// metodo readOnly |
// modifica lo stato lettura/scrittura del recordset |
// blocca ogni tentativo di inviare al server modifiche |
// se al cambio del set c'è il record corrente modificato ... provvede prima ad aggiornarlo |
// set == true/false stato readonly |
// update == null|true provvede ad aggiornare il recordset prima di cambiare lo stato, se necessario |
function DataBinding_readOnly(set, update){ |
if(set == null){ |
return this.readonly; |
} |
if(this.readonly == set){ |
this.changed_readonly = false; |
return set; |
} |
this.readonly = set; |
// funzione chiamata quando cambia lo stato lettura/scrittura |
if(this.onreadonly){ |
this.changed_readonly = true; |
this.onreadonly(set, update); |
} |
// se il recordset corrente è stato modificato prima di renderlo readonly ... provvedo ad aggiornare il record |
if((update == null || update) && set){ |
// valuto se la differenza è stata gia calcolata (prima di azzerare i campi del form durante la trasmissione) |
if(!this._difference){ |
this._difference = ArrayDiffKeys(this.keys, this.data, this.new_data, true); |
//DEBUG my_alert('DataBinding_readOnly diff '+Array2String(this._difference, 'null')); |
} |
if(!this._difference.allNull()){ |
//DEBUG my_alert('DataBinding_readOnly('+set+','+update+') father='+this.father_id+' father_id_update='+this.father_id_update+' update '+Array2String(this._difference)); |
this.gotoRecords('update'); |
} |
} |
//DEBUG my_alert('DataBinding_readOnly('+set+','+update+') father='+this.father_id+' father_id_update='+this.father_id_update); |
return set; |
} |
// funzione richiamata al termine del download |
function DataBinding_Load_Callback(str, contextID){ |
// recupera l'oggetto associato al download |
var db = DataBinding_ContextPool[contextID]; |
// se max_row è nullo questa è la prima volta che l'oggetto riceve risposte dal server |
var first_time = (db.max_rows == null); |
%#DEBUG//my_alert("Load_Callback prefix="+db.prefix+' from='+db.from+' max_table_rows='+db.max_table_rows+' str=\n\n'+str+'\n________'); |
db.hReqMason_ID = null; |
// elimino il riferimento all'eventuale record duplicato in precedenza |
db.dup_keys = []; |
// evento primo caricamento |
if(first_time && db.onpreload){ |
db.onpreload(db.call_mode, str); |
} |
// evento cambiamento dati disponibili |
if(db.onprechange){ |
db.onprechange(); |
} |
try{ |
// valuto i dati trasmessi dal server |
window.eval(str); |
}catch(err){ |
// potrebbe trattarsi di codice HTML inviato dal server (ad esempio codice di errore Mason) |
var re_htmlCode = RegExp('<html>','i'); |
if(re_htmlCode.test(str)){ |
my_alert(str, 'html'); |
}else{ |
my_alert_error("DataBinding_Load_Callback", err, str); |
} |
} |
if(first_time){ |
db.pos_name = {}; |
for(var col=0; col<db.names.length; col++){ |
db.pos_name[db.names[col]] = col; |
} |
} |
// preparo il vettore inverso delle chiavi key --> row |
for(var col=0; col<db.keys.length; col++){ |
db.pos_key[db.keys[col]] = col; |
} |
%#//DEBUG my_alert('db.data:'+Array2String(db.data,'NUL')+' db.data.length:'+db.data.length); |
if(db.data.length == 0){ |
db.data[0] = new Array(db.cols); |
db.params[0] = new Array(db.cols); |
db.keys[0] = null; |
db.fathers_id = []; |
} |
%#//DEBUG my_alert('db.data:'+Array2String(db.data,'NUL')+' db.cols:'+db.cols+' db.data.length:'+db.data.length); |
if(db.rows < db.max_table_rows){ |
// completiamo le matrici con righe nulle |
for(I=db.rows; I<db.max_table_rows; I++){ |
db.keys[I] = null; |
db.data[I] = new Array(db.cols); |
// copio i valori di default se presenti ... |
var len = db.new_fields.length; |
if(len > db.cols){ |
len = db.cols; |
} |
for(var J=0; J<len; J++){ |
db.data[I][J] = db.new_fields[J]; |
} |
} |
///my_alert(KeyArray2String(db.keys, db.data, 'null', true, 'false', db.dup_keys)); |
} |
%#//DEBUG my_alert('db.data:'+Array2String(db.data,'NUL')+' db.cols:'+db.cols+' db.data.length:'+db.data.length); |
// preparo la copia modificabile |
db.new_data = DuplicaArray(db.data); |
// forzo aggiornamento dello stato readonly corrente |
// in quanto può dipendere dallo stato dei campi correnti |
if(!db.readonly){ |
db.readonly = true; |
db.readOnly(false); |
} |
// evento primo caricamento |
if(first_time && db.onload){ |
db.onload(db.call_mode); |
} |
%#//DEBUG my_alert('db.data:'+Array2String(db.data,'NUL')+' db.cols:'+db.cols+' db.data.length:'+db.data.length); |
// evento cambiamento dati disponibili |
if(db.onchange){ |
db.onchange(); |
} |
%#//DEBUG my_alert('db.data:'+Array2String(db.data,'NUL')+' db.cols:'+db.cols+' db.data.length:'+db.data.length); |
db.updateChildren(); |
db.deferred_onload && db.deferred_onload.resolve(); |
} |
// aggiornamento delle tabelle figlie |
function DataBinding_updateChildren(row){ |
if(row == null){ |
row = this.rowFather == null ? 0 : this.rowFather; |
} |
if(this.children.length && this.fathers_id){ |
var children_id = this.fathers_id[row]; |
this.rowFather = row |
var father = this; |
require(['dojo/promise/all', 'dojo/Deferred'], function(all, Deferred){ |
// aggiorno i dati delle tabelle figlie collegate |
var list_promises = []; |
for(var I = 0; I < father.children.length; I++){ |
var child = father.children[I]; |
// aggiorno la chiave del record MASTER |
// nel caso di record nuovo il valore della chiave è null, quindi restituisco -1 |
var father_id = children_id && children_id[I]; |
child.father_id = father_id == null ? -1 : father_id; |
child.deferred_onload = new Deferred(); |
list_promises.push(child.deferred_onload.promise); |
// lancio la richiesta |
child.loadRecords('rewind'); |
} |
all(list_promises).then(function(){ |
// terminato il caricamento dei nuovi recordset nei figli |
father.onchange_children && father.onchange_children(); |
}, function(error){ |
father.onchange_children && father.onchange_children(error); |
}); |
}); |
} |
} |
// preparo una stringa con la lista dei campi in keyList in formato ['v','v',...] |
function DataBinding_paramList(keyList){ |
// preparo la stringa con la lista dei parametri in formato ['v','v',...] |
for(var I=0; I<keyList.length; I++){ |
keyList[I] = "'" + keyList[I] + "'"; |
} |
return '[' + keyList.join(',') + ']'; |
} |
// stampa del recordset |
// type: sel -> stampa della selezione corrente |
// type: recordset -> stampa del recordset filtrato |
// template: se definito identifica il report da utilizzare nella stampa |
function DataBinding_printUrl(type, keyList, report, cmdParams){ |
//DEBUG: console.log('printUrl, type='+type+', report='+report+', cmdParams='+cmdParams); |
var params = []; |
//DEBUG my_alert("DataBinding_Print "+type+' keyList='+keyLis.join(',')); |
var F='.mql?method=pdf'; |
switch(type){ |
case 'sel': |
if(report == null && !this.canPrint){ // test solo con il report standard |
return null; |
} |
if(!keyList && !keyList.length){ |
return null; |
} |
var reportList = DataBinding_paramList(keyList); |
// parametri da passare al server |
params = ['reportlist', reportList, 'name', this.prefix, 'start', |
this.start, 'rows', this.max_table_rows, |
'orderby', this.orderby, 'json_where', this.json_where, |
'father_id',this.father_id, 'father_id_update',this.father_id_update, |
'query_param',this.query_param, 'report', report]; |
break; |
case 'odt_rpt': |
if(report == null && !this.canPrint){ |
return null; |
} |
if(!keyList && !keyList.length){ |
return null; |
} |
var reportList = DataBinding_paramList(keyList); |
params = ['reportlist', reportList, 'report', report, |
'cmd_parameters', cmdParams]; |
break; |
case 'pdf_rpt': |
if(report == null && !this.canPrint){ |
return null; |
} |
if(!keyList && !keyList.length){ |
return null; |
} |
var reportList = DataBinding_paramList(keyList); |
params = ['reportlist', reportList, 'report', report, |
'cmd_parameters', cmdParams]; |
break; |
case 'xls_sel': |
if(!this.canXls){ |
return null; |
} |
if(!keyList && !keyList.length){ |
return null; |
} |
var key_list = keyList.join(','); |
// parametri da passare al server |
params = ['name', this.prefix, 'key_list', key_list, 'orderby', this.orderby, 'rows', '', |
'father_id',this.father_id ]; |
F='.xls?method=xls'; |
break; |
case 'recordset': |
if(!this.canPrintsel){ |
return null; |
} |
// parametri da passare al server |
params = ['name', this.prefix, 'start', this.start, |
'orderby', this.orderby, 'json_where', this.json_where, |
'father_id', this.father_id, 'father_id_update',this.father_id_update, |
'query_param',this.query_param, 'report', report]; |
break; |
case 'create_recordset': |
if(!this.canPrintsel){ |
return null; |
} |
// parametri da passare al server |
params = ['create', 'auto', 'name', this.prefix, 'start', this.start, |
'orderby', this.orderby, 'json_where', this.json_where, |
'father_id', this.father_id, 'father_id_update',this.father_id_update, |
'query_param',this.query_param]; |
break; |
case 'xls_recordset': |
if(!this.canXls){ |
return null; |
} |
// parametri da passare al server |
params = ['name', this.prefix, 'start', this.start, |
'orderby', this.orderby, 'json_where', this.json_where, 'rows', '', |
'father_id', this.father_id, 'father_id_update',this.father_id_update, |
'query_param',this.query_param]; |
F='.xls?method=xls'; |
break; |
default: |
return null; |
} |
var url = '<%$DataBaseUrl%>/'+this.from+F; |
for( var i=0; i < params.length; i++ ){ |
url += "&P" + "=" + escape(''+params[i]); |
} |
//DEBUG my_alert(url); |
return url; |
} |
function DataBinding_storeRowToCopy(){ |
disp = this.displayBinding; |
if(disp.cp_row !== null){ |
this.cp_key = this.keys[disp.cp_row]; |
} |
//console.log('storeRowToCopy cp_row='+disp.cp_row+', cp_key='+this.cp_key); |
return; |
} |
function DataBinding_retrieveRowToCopy(){ |
disp = this.displayBinding; |
disp.cp_row = null; |
if(this.cp_key !== null){ |
for(var R=0; R < this.max_table_rows; R++){ |
if(this.cp_key == this.keys[R]){ |
disp.cp_row = R; |
disp.cpRefreshRow(R); |
break; |
} |
} |
} |
//console.log('retrieveRowToCopy cp_row='+disp.cp_row+', cp_key='+this.cp_key); |
return; |
} |
// test stato del download in corso; |
// return false se libero |
// true se in corso |
// null se non inizializzato |
// se abort == true, viene abortito il download eventualmente in corso |
function DataBinding_statusDownload(abort){ |
if(this.hReqMason_ID){ |
var contextObj = hReqMason_ContextPool[this.hReqMason_ID]; |
if(contextObj && contextObj.busy){ |
if(abort){ |
// annullo la chiamata in corso |
contextObj.abort(); |
// e le chiamate in corso dei figli |
for(var I = 0; I < this.children.length; I++){ |
this.children[I].statusDownload(true); |
} |
} |
return true; |
}else{ |
return false; |
} |
}else{ |
return null; |
} |
} |
// elaborazione della query di selezione nel recordset |
function DataBinding_loadRecords(mode, key){ |
%#//DEBUG my_alert('DataBinding_loadRecords mode='+mode+' key='+key); |
// verifico se è stato caricato un primo recordset |
if(this.start == null){ |
return this.initRecordset(mode, key); |
} |
// forzo il ricaricamento del recordset con il terzo parametro a true |
return this.gotoRecords(mode, key, true); |
} |
// handler errore timeout su chiamata di .callRemote |
function DataBinding_Timeout_callRemote(contextID, err, str){ |
var db = DataBinding_ContextPool[contextID]; |
if(db.onerror){ |
db.onerror(err, str); |
} |
db.deferred_onload && db.deferred_onload.reject(str); |
} |
// funzione richiamata al termine della chiamata a .callRemote |
function DataBinding_callRemote_Callback(str, contextID){ |
// recupera l'oggetto associato al download da mettere a disposizione dello script inviato dal server |
window.db_context = DataBinding_ContextPool[contextID]; |
%#DEBUG// my_alert("callRemote_Callback prefix="+db.prefix+' from='+db.from+' str=\n\n'+str+'\n____'); |
if(window.db_context){ |
window.db_context.hReqMason_ID = null; |
} |
if(str){ |
try{ |
// valuto i dati trasmessi dal server |
window.eval('var db = window.db_context;\n' + str); |
}catch(err){ |
// potrebbe trattarsi di codice HTML inviato dal server (ad esempio codice di errore Mason) |
var re_htmlCode = RegExp('<html>','i'); |
if(re_htmlCode.test(str)){ |
my_alert(str, 'html'); |
}else{ |
my_alert_error("DataBinding_callRemote_Callback", err, str); |
} |
} |
} |
} |
// lancia un metodo remoto sul server definito come CALL_REMOTE_<function> |
function DataBinding_callRemote(remote_func, params, mode, win_params){ |
var call_params = {'caller':'.callRemote', |
'name':this.prefix, 'orderby': this.orderby, 'json_where': this.json_where, remote_func_params:params, |
'father_id': this.father_id, 'father_id_update':this.father_id_update, |
remote_func_name: remote_func |
}; |
if(mode == 'html'){ |
var db = this; |
require(["dojo/json"], function(json){ |
var d = new Date(); |
var url_params = { |
F: 'call_remote', |
json_params: json.stringify(call_params), |
Ver: '<%$Ver%>', |
U: d.getTime() + '' + Math.floor(1000 * Math.random()) |
}; |
var X = win_params ? win_params.X : null; |
var Y = win_params ? win_params.Y : null; |
var title = win_params ? win_params.title : null; |
masonSql_Dialog.openUrl('<%$DataBaseUrl%>/'+db.from+'.mql', url_params, X, Y, title); |
}); |
}else{ |
this.hReqMason_ID = hReqMason_ExecuteTimeout('<%$DataBaseUrl%>/'+this.from+'.mql', this.timeout, |
DataBinding_Timeout_callRemote, DataBinding_callRemote_Callback, 'call_remote', call_params); |
DataBinding_ContextPool[this.hReqMason_ID] = this; |
return this.hReqMason_ID; |
} |
} |
// posizionamento in finestra del DataBinding |
// mode: |
// up su di una finestra |
// down giù di una finestra |
// top o forward dall'ultimo record |
// bottom o rewind primo record |
// changed salva i dati solo se risultano modificati nel form |
// save salva le modifiche/inserimenti |
// reload ricarica i dati |
// insert si posiziona con almeno una riga vuota |
// <numero> salta alla posizione nel recordset indicata |
// update salva le modifiche/inserimenti e mantiene i dati visualizzati in modifica |
// nota: il recordset restituito dal server contiene solo i dati modificati/inseriti |
// key: chiave del record da ricercare nel recordset quale posizione da ritornare |
// recordset: se true forza sul server il ricaricamento del recordset permanente |
// |
function DataBinding_gotoRecords(mode, key, recordset){ |
%#//DEBUG my_alert('DataBinding_gotoRecords mode='+mode+' key='+key+' recordset='+recordset); |
// verifico se è in corso un download |
if(this.statusDownload(this.delete_previus_req) && !this.delete_previus_req){ |
//annullo se c'è in corso un download e non ho abortito il precedente download |
return false; |
} |
// chiamo la funzione utente, se definita prima di elaborare la richiesta |
if(this.onloadrecord){ |
if(!this.onloadrecord(mode, key, recordset)){ |
// interrompo la chiamata se la funzione utente ritorna 'false' |
return false; |
} |
} |
%#//DEBUG my_alert('DataBinding_gotoRecords next .onloadrecord mode='+mode+' key='+key); |
this.call_mode = mode; |
// my_alert('DataBinding_loadRecords ' + this.prefix + ' mode=' + mode + ' key=' + key); |
// tipo di caricamento finale del recordset: |
// reload = select con i record nella posizione di partenza aggiornati in base all'ordinamento dei record corrente |
// update = select mantenendo i record visualizzati |
// save = esegue un salvataggio dei record modificati |
var new_start; |
var type; |
switch(mode){ |
case 'reload': |
new_start=this.start; |
type='reload'; |
break; |
case 'update': |
new_start=this.start; |
type='update'; |
break; |
case 'changed': |
// verifico se ci sono record modificati |
if(!this._difference){ |
this._difference = ArrayDiffKeys(this.keys, this.data, this.new_data, true); |
} |
if(this._difference.allNull()){ |
this._difference = null; |
return false; |
} |
new_start=this.start; |
type='reload'; |
break; |
case 'save': |
// il metodo readOnly provvede anche all'aggiornamento del record corrente se risulta modificato |
// metto il secondo parametro per disabilitare il test |
this.readOnly(true, false); |
new_start=this.start; |
type='reload'; |
break; |
case 'bottom': |
case 'rewind': |
new_start=0; |
type='reload'; |
break; |
case 'insert': |
// campi di input in scrittura |
this.readOnly(false); |
new_start=this.max_rows-Math.floor(this.max_table_rows/4); |
type='reload'; |
// new_start=this.max_rows-this.max_table_rows+1; // lascia vuota una sola riga |
break; |
case 'top': |
case 'forward': |
//this.max_rows-this.max_table_rows; |
new_start = this.max_rows-this.max_table_rows; |
type='reload'; |
break; |
case 'up': |
new_start=this.start+this.max_table_rows; |
% if($r->dir_config('LastUpAsForward')){ |
if(new_start>=(this.max_rows-this.max_table_rows)){ |
new_start=this.max_rows-this.max_table_rows; |
} |
% } |
type='reload'; |
break; |
case 'down': |
new_start=this.start-this.max_table_rows; |
type='reload'; |
break; |
default: |
// verifico se numero |
if(/\d+/.test(mode)){ |
new_start = mode > this.max_rows+1 ? this.max_rows : mode-1; |
}else{ |
my_alert('ERROR DataBinding_loadRecords: Valore ('+mode+') per il posizionamento del record '+this.prefix+' non numerico', 'txt', 400,100); |
return false; |
} |
type='reload'; |
// end case |
} |
if(new_start<0){ |
new_start=0; |
} |
if(new_start>this.max_rows){ |
new_start=this.max_rows; |
} |
// valuto se la differenza è stata gia calcolata (prima di azzerare i campi del form durante la trasmissione) |
if(!this._difference){ |
this._difference = ArrayDiffKeys(this.keys, this.data, this.new_data, true); |
} |
var diff = KeyArray2String(this.keys, this._difference, 'undef', false, true, this.dup_keys); |
if(diff != '[]' && this.ondiff_recordset){ |
this.ondiff_recordset(diff, mode, key, recordset); |
} |
// valore da attribuire al parametro che sul server determinerà il ricaricamento del recordset persistente |
// 'new' il recordset viene rigenerato |
// 'cache' viene usato il recordset corrente |
// non definito: non viene utilizzato il recordset permanente sul server |
recordset = recordset ? 'new' : 'cache'; |
%#//DEBUG my_alert('mode:'+mode+' diff:' + diff + "\n---------data----------\n" + KeyArray2String(this.keys, this.data, 'undef', false, true, this.dup_keys) + "\n---------new----------\n" + KeyArray2String(this.keys, this.new_data, 'undef', false, true, this.dup_keys) ); |
if(diff == '[]' || mode == 'reload'){ |
if(recordset && (mode == 'forward' || mode == 'top')){ |
// con un valore negativo il server lo interpreterà come valore di start riferito alla posizione in fondo al recordset |
new_start = -this.max_table_rows; |
} |
this.hReqMason_ID=hReqMason_ExecuteTimeout('<%$DataBaseUrl%>/'+this.from+'.mql', this.timeout, |
DataBinding_TimeoutData, DataBinding_Load_Callback, 'array', |
{'caller':'gotoRecords', 'start':new_start,'type':type,'max_rows':this.max_rows,'rows': this.max_table_rows,'name':this.prefix, |
'orderby': this.orderby, 'json_where': this.json_where, 'find_key': key, 'query_param':this.query_param, |
'father_id': this.father_id, 'father_id_update':this.father_id_update, |
'select': this.select, 'recordset': recordset}); |
}else{ |
if(mode == 'insert'){ |
// aggiungo la quantità di nuove righe da inserire |
new_start += ArrayNewRowNum(this.keys, this._difference); |
} |
%#//DEBUG my_alert('call with mode='+mode+' new_start='+new_start+' type='+type+' diff=['+diff+']'); |
// invio la differenza |
this.hReqMason_ID=hReqMason_ExecuteTimeout('<%$DataBaseUrl%>/'+this.from+'.mql', this.timeout, |
DataBinding_TimeoutData, DataBinding_Load_Callback, 'array', |
{'caller':'gotoRecords', 'update':diff,'type':type,'max_rows':this.max_rows, 'name':this.prefix, 'start':new_start,'rows': this.max_table_rows, |
'orderby': this.orderby, 'json_where': this.json_where, 'find_key': key, 'query_param':this.query_param, |
'father_id': this.father_id, 'father_id_update':this.father_id_update, |
'select': this.select, 'recordset': recordset}); |
} |
this._difference = null; |
DataBinding_ContextPool[this.hReqMason_ID] = this; |
// chiamo la funzione utente, se definita |
if(this.onrequest){ |
this.onrequest(); |
} |
return true; |
} |
// richiamata in caso di timeout o di errore |
function DataBinding_TimeoutData(contextID, err, str){ |
var db = DataBinding_ContextPool[contextID]; |
// verifico se prima della richiesto lo stato del recordset era in modifica |
if(db.changed_readonly && db.readonly){ |
// ricopio i dati originali da db.data in db.new_data |
db.new_data = DuplicaArray(db.data); |
// ripristino la condizione di modifica del recordset |
db.readOnly(false); |
} |
if(db.onerror){ |
db.onerror(err, str); |
} |
// notifico nelle tabelle figlie |
for(var I = 0; I < db.children.length; I++){ |
var child = db.children[I]; |
if(child.onchange){ |
child.onchange(); |
} |
} |
db.deferred_onload && db.deferred_onload.reject(str); |
} |
function DataBinding_initRecordset(mode, key){ |
// forzo la condizione di primo record caricato |
this.max_rows = null; |
// interrompo un eventuale download in corso |
this.statusDownload(true); |
var new_start; |
switch(mode){ |
case 'reload': |
case 'update': |
case 'changed': |
case 'save': |
case 'down': |
case 'up': |
my_alert('ERROR DataBinding_initRecordset: Valore ('+mode+') per il posizionamento del record '+this.prefix+' non previsto'); |
return false; |
break; |
case 'bottom': |
case 'rewind': |
new_start=0; |
break; |
case 'top': |
case 'forward': |
new_start = 'forward'; |
break |
case 'insert': |
new_start = 'insert'; |
break; |
default: |
// verifico se numero |
if(/\d+/.test(mode)){ |
new_start = mode>this.max_rows ? this.max_rows-1 : mode-1; |
}else{ |
my_alert('ERROR DataBinding_initRecordset: Valore ('+mode+') per il posizionamento del record '+this.prefix+' non numerico', 'txt', 400,100); |
return false; |
} |
} |
//DEBUG my_alert('DataBinding_initRecordset('+mode+','+key+')'); |
//carico la tabella da visualizzare dall'inizio del recordset |
this.hReqMason_ID=hReqMason_ExecuteTimeout('<%$DataBaseUrl%>/'+this.from+'.mql', this.timeout, |
DataBinding_TimeoutData, DataBinding_Load_Callback,'array', |
{'caller':'initRecordset', 'start':new_start, 'rows':this.max_table_rows, 'name':this.prefix, |
'orderby':this.orderby, 'json_where':this.json_where, 'find_key': key, 'query_param':this.query_param, |
'father_id':this.father_id, 'father_id_update':this.father_id_update, |
'initRecordset':1, 'select': this.select, 'recordset': 'new'}); |
this.call_mode = mode; |
DataBinding_ContextPool[this.hReqMason_ID] = this; |
// download dati dal server in corso ... |
if(this.onrequest){ |
this.onrequest(); |
} |
return true; |
} |
// annulla le modifiche nel form |
// key == chiave record da cercare |
// pos == posizione nel recordset |
// se viene indicato key o pos, oltre ad annullare il record lancia il caricamento |
// del recordset puntando al record con key indicata |
function DataBinding_cancelUpdate(key, pos){ |
if(!this.readOnly()){ |
// seleziono lo stato in sola lettura |
this.readOnly(true, false); |
// ripristino la copia originaria |
this.new_data = DuplicaArray(this.data); |
if(this.start < this.max_rows && !key && !pos){ |
// avviso nuovi dati disponibili |
if(this.onchange){ |
this.onchange(); |
} |
}else{ |
%#//DEBUG my_alert("---------data----------\n" + KeyArray2String(this.keys, this.data, 'undef', false, true, this.dup_keys) + "\n---------new----------\n" + KeyArray2String(this.keys, this.new_data, 'undef', false, true, this.dup_keys) ); |
// caso di annullamento da inserimento di un nuovo record |
// mi posiziono in fondo al recordset |
if(pos){ |
this.gotoRecords(pos); |
}else{ |
this.gotoRecords('forward', key); |
} |
} |
} |
} |
// cancella i record elencati in keyList |
function DataBinding_deleteRecords(keyList){ |
//DEBUG my_alert('DataBinding_deleteRecords: ' + keyList.join(',') + '. max_table_rows='+this.max_table_rows+' start='+this.start+' max_rows='+this.max_rows); |
if(!this.canDelete || !keyList || keyList.lenght ==0){ |
return false; |
} |
// verifico caso cancellazione record in fondo al recordset |
if(this.max_table_rows == 1 && this.start >0 && this.start == (this.max_rows - 1) ){ |
this.start--; |
} |
// chiamo la funzione utente, se definita prima di elaborare la richiesta |
if(this.ondeleterecords){ |
if(!this.ondeleterecords(keyList)){ |
// interrompo la chiamata se la funzione utente ritorna 'false' |
return false; |
} |
} |
this.hReqMason_ID = hReqMason_ExecuteTimeout('<%$DataBaseUrl%>/'+this.from+'.mql', this.timeout, |
DataBinding_TimeoutData, DataBinding_Load_Callback, 'array', |
{'caller':'deleteRecords', 'delete':DataBinding_paramList(keyList), 'name':this.prefix, |
'start':this.start, 'rows': this.max_table_rows, |
'orderby':this.orderby, 'json_where':this.json_where, 'query_param':this.query_param, |
'father_id': this.father_id, 'father_id_update':this.father_id_update, |
'select': this.select, 'recordset': 'cache'}); |
DataBinding_ContextPool[this.hReqMason_ID] = this; |
// chiamo la funzione utente, se definita |
if(this.onrequest){ |
this.onrequest(); |
} |
return true; |
} |
// restituisce il valore del campo di nome 'name' e riga 'row' |
// se 'name' o 'row' sono nulli restituisce rispettivamente la riga o la colonna del dataset |
function DataBinding_get_value(name, row){ |
if(row == null){ |
var colums = []; |
var pos = this.pos_name[name]; |
for(var R=0; R<this.data.length; R++){ |
colums[R] = this.data[R][pos]; |
} |
return colums; |
}else if(name == null){ |
return this.data[row]; |
}else{ |
return this.data[row][this.pos_name[name]]; |
} |
} |
// modifica il valore del campo di nome 'name' e riga 'row' |
// se 'name' o 'row' sono nulli restituisce rispettivamente la riga o la colonna del dataset |
function DataBinding_set_value(name, row, value){ |
if(row == null){ |
var pos = this.pos_name[name]; |
for(var R=0; R<this.data.length; R++){ |
this.data[R][pos] = value[R]; |
this.new_data[R][pos] = value[R]; |
} |
}else if(name == null){ |
this.data[row] = value; |
this.new_data[row] = value; |
}else{ |
var pos = this.pos_name[name]; |
this.new_data[row][pos] = value; |
this.data[row][pos] = value; |
} |
if(this._difference){ |
this._difference = null; |
} |
} |
%# END databinding.js |
/tags/2.0/htdocs/lib/getDocument.mason |
---|
0,0 → 1,60 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
in $method va indicato il nome del componente |
in @P va indicato l'elenco dei parametri in numero pari con la convenzione di id1, value1, id2, value2, ecc. |
</%doc> |
<%attr> |
Cache_MaxAge => 12*60*60 |
</%attr> |
<%args> |
$method |
$C |
@P => () |
</%args> |
% $Global{'C'}=$C; |
% $r->headers_out->{'Cache-Control'} = 'max-age='.$m->base_comp->attr('Cache_MaxAge'); |
<%perl> |
$r->content_type('text/html'); |
# F=URL completa dei parametri |
if($method !~ m|^/|){ |
# se il percorso è relativo (senza / iniziale) impongo il percorso del componente chiamante |
$_ = $ENV{'HTTP_REFERER'}; |
s|.*//||; |
s|^[^/]*/|/|; |
s|/[^/]*$||; |
$method = $_.'/'.$method; |
} |
my $query = $method; |
$query =~ s/.*\?//; |
$method =~ s/\?.*//; |
$query = new CGI($query); |
#DEBUG $PLogger->debug(sub{ "QUERYQUERYQUERY method='$method' ",Dumper($query); }); |
my $respond_mess = $m->scomp($method, $query->Vars); |
#DEBUG $PLogger->debug(sub{ "RESPOND [$respond_mess]"; }); |
if(@Script_buffer){ |
$respond_mess .= "<!-- Script_buffer BEGIN -->\n<script>\n"; |
$respond_mess .= join('', @Script_buffer); |
@Script_buffer = (); |
$respond_mess .= "</script>\n<!-- Script_buffer END -->\n"; |
} |
$m->out($respond_mess); |
###$PLogger->debug(sub{ ('#' x 79)."\n".$respond_mess."\n".('#' x 79); }); |
</%perl> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%shared> |
</%shared> |
<%once> |
use Data::Dumper; |
use URI::Escape; |
</%once> |
/tags/2.0/htdocs/lib/report.pdf |
---|
0,0 → 1,791 |
<%doc> |
=head1 report.pdf |
=head2 Revision |
$Revision: $ |
=head2 Description |
A component for generating MasonSQL reports in PDF or ODT format. |
=head2 Arguments |
B<Argument Name> | B<Default Value> | B<Description> |
------------------------------------------------------------------------------------------------- |
$base | $r->dir_config('DataBaseUrl') | The data directory. |
$report | undef | The name of a new report file. |
$report_method | undef | A report method (rep, pdf or odt). |
$report_file | undef | A Reportman config filepath. |
$GROUP_ID | undef | Identifier of a group of records to be printed |
| | (see the report_id table). |
$report_ids | undef | An array of records to be printed. |
$landscape | undef | Deprecated. |
$orientation | PORTRAIT | Deprecated. |
$path_pdf | undef | If defined, determines ODT and PDF filepaths. |
$send_pdf | 1 | The report is transmitted with the Mason request object. |
$cups_printer | undef | If defined, instead of sending the file with $m->out(), |
| | send the file to the indicated Cups printer. |
=cut |
</%doc> |
<%init> |
if(!$Session{Dbh_report}){ |
$Session{Dbh_report} = Auth_AC::AuthCookieHandler->connect($r, $r->dir_config('ReportDBIconnect'), 1); |
} |
</%init> |
<%args> |
$base => $r->dir_config('DataBaseUrl') |
$report |
$report_method => 'rep' |
$report_file => undef |
$GROUP_ID => undef |
$report_ids => undef |
$landscape => undef |
$orientation => 'PORTRAIT' |
$path_pdf => undef |
$send_pdf => 1 |
$cups_printer => undef |
</%args> |
<%perl> |
$Session{StatusCode} = 400; |
=head2 Component Body |
The component is called from the L<dbms_library.comp|https://www.leader.it/MasonSQL/DbmsLibraryComponent> from the L<PDF|https://www.leader.it/MasonSQL/DbmsLibraryReportMethods> method. |
The procedure to print the report document: |
=over 2 |
=item 1 |
If L<send_pdf|/Arguments> is set, clear the Mason request buffer and set C<content_type> to C<text/html>. |
=item 2 |
Compose the L<temporary filepaths|/PrintPaths()> of the PDF and ODT report files. |
=item 3 |
Create a new report file using the utility determined by the L<report_method|/Arguments>. |
=over 2 |
=item a. |
When the C<report_method> is C<rep>, print the complete B<.pdf> report with Report Manager using L<GROUP_ID|/Arguments>. |
=item b. |
When the C<report_method> is C<odt>, print single B<.odt> report with ODT Reportman. |
=item c. |
When the C<report_method> is C<pdf>, print the complete B<.pdf> report with ODT Reportman using L<group_ids|/Arguments>. |
=back |
=item 4 |
Process newly created report file. |
=over 2 |
=item a. |
If the PDF report file is present print it with L<PrintPdf()|PrintPdf()>. |
=item b. |
Otherwise if ODT report file is present print it with L<SendFile()|/SendFile()>. |
=back |
=back |
=cut |
if($send_pdf){ |
$m->clear_buffer; |
$r->content_type('text/html'); |
} |
$PLogger->debug(sub{ "report.pdf ARGS:".to_json(\%ARGS); }); |
my ($PDF, $ODT) = PrintPaths($report, $path_pdf); |
if($report_method eq 'rep'){ |
my $exec = Reportman($base, $report, $report_file, $PDF, \%ARGS); |
if(system @{$exec}){ |
my $exit_value = $? >> 8; |
my $signal_num = $? & 127; |
my $dumped_core = $? & 128; |
$m->out("ERRORE: generazione report exit=[$exit_value] err=[$?]"); |
} |
}elsif($report_method eq 'odt'){ |
OdtReport($report, $report_ids->[0], $ODT, \%ARGS); |
}elsif($report_method eq 'pdf'){ |
my @pdf_reports = (); |
my @odt_reports = (); |
foreach my $REPORT_ID (@{$report_ids}){ |
PdfReport($report, $REPORT_ID, \@pdf_reports, \@odt_reports, \%ARGS); |
} |
CatPdfs(\@pdf_reports, $PDF); |
UnlinkTmpReports(\@pdf_reports, \@odt_reports); |
} |
if(-f $PDF){ |
PrintPdf($report, $cups_printer, $send_pdf, $PDF, \%ARGS); |
}elsif(-f $ODT){ |
if($send_pdf){ |
SendFile($report, $ODT, 'application/vnd.oasis.opendocument.text', 'odt'); |
} |
}else{ |
die "ERRORE: il rapporto '$report' non ha generato alcun file PDF o ODT"; |
} |
$Session{StatusCode} = 200; |
</%perl> |
<%shared> |
</%shared> |
<%once> |
use MasonSQL::Report; |
use MasonSQL::Report::OdtConv; |
=head2 Once Block |
=head3 SendFile() |
Prints the new report file: |
=over 2 |
=item 1 |
Opens the new report file for reading. |
=item 2 |
Depending on the Apache version sets the C<Cache-Control>, C<Content-transfer-encodig> and the C<Content-disposition> L<Apache::Request|http://www.masonbook.com/book/chapter-7.mhtml> attributes. |
=item 3 |
Outputs the content of the report file to the L<HTML::Mason::Request|http://www.masonbook.com/book/chapter-4.mhtml> buffer. |
Raises an error in case any undefined character was detected. |
=item 4 |
Then flushes the C<HTML::Mason::Request> buffer and deletes the report file after the file was read. |
=back |
=cut |
sub SendFile($$$$){ |
my $report = shift; |
my $file = shift; |
my $content_type = shift; |
my $extension = shift; |
sysopen SENT_FILE, $file, 'O_RDONLY' || die "sysopen $file: $!"; |
$m->clear_buffer; |
$r->content_type($content_type); |
$r->headers_out->{'Cache-Control'} = 'max-age=0'; |
$r->headers_out->{'Content-transfer-encodig'} = 'binary'; |
$r->headers_out->{'Content-disposition'} = "inline; filename=$report.$extension"; |
my $start = time; |
my $buffer; |
# leggo il file generato a blocchi di 64Kbyte |
while(my $numchar = sysread SENT_FILE, $buffer, 2^16){ |
if(undef $numchar){ |
die "sysread $file: $!"; |
}; |
$m->out($buffer); |
$m->flush_buffer; |
} |
close SENT_FILE; |
unlink $file; |
### $m->print($_); |
my $duration = time - $start; |
$PLogger->debug(sub{ "duration=$duration" }); |
return; |
} |
=head3 PrintPdf() |
Prints the created report file and handles a printing errors: |
=over 2 |
=item * |
If the C<PROTECT> argument is defined, encrypts the content of the report file using the C<qpdf> utility. |
=item * |
If the C<cups_printer> is defined, prints the report file using the C<lp> utility. |
=item * |
If the C<cups_printer> is not defined prints the report file with default subroutine L<SendFile|/SendFile()>. |
=back |
=cut |
sub PrintPdf($$$$$){ |
my $report = shift; |
my $cups_printer = shift; |
my $send_pdf = shift; |
my $PDF = shift; |
my $args = shift; |
if($args->{PROTECT}){ |
my $file_orig = $PDF.'_ORIG.pdf'; |
rename $PDF, $file_orig; |
if(! -e '/usr/bin/qpdf'){ |
die "PrintPdf ERROR /usr/bin/qpdf not exists\n"; |
} |
if(system '/usr/bin/qpdf', '--linearize', '--encrypt', '', $args->{PROTECT}, 40, '--modify=n', '--annotate=n', '--', $file_orig, $PDF){ |
my $exit_value = $? >> 8; |
if($exit_value == 3){ |
# warning da trascurare |
unlink $file_orig; |
}else{ |
my $signal_num = $? & 127; |
my $dumped_core = $? & 128; |
my $err = $? == -1 ? $! : "err:$?"; |
die "ERRORE: qpdf - [$exit_value:$signal_num:$dumped_core] $err\n"; |
} |
}else{ |
unlink $file_orig; |
} |
} |
if($cups_printer){ |
if(! -e '/usr/bin/lp'){ |
die "PrintPdf ERROR /usr/bin/lp not exists\n"; |
} |
if(!system '/usr/bin/lp', '-d', $cups_printer, $PDF){ |
$m->out("Stampa completata"); |
}else{ |
my $exit_value = $? >> 8; |
my $signal_num = $? & 127; |
my $dumped_core = $? & 128; |
my $err = $? == -1 ? $! : "err:$?"; |
$m->out("ERRORE: errore di stampa - [$exit_value:$signal_num:$dumped_core] $err"); |
} |
}elsif($send_pdf){ |
SendFile($report, $PDF, 'application/pdf', 'pdf'); |
} |
return; |
} |
=head3 UpdateReportmanConfigFile() |
The procedure to update Reportman's report configuration file: |
=over 2 |
=item 1 |
If the report configuration file is older than the C<database_directory/report_name.rep> file it updates it with the content of the later file. |
=item 2 |
During update it additionally updates the C<ADOConnectionString> with the current L<Apache config|https://www.leader.it/MasonSQL/DatabaseAccess#Apache> settings. |
=item 3 |
At the end updates the L<report_file's|/Arguments> modification time. |
=back |
=cut |
sub UpdateReportmanConfigFile($$$){ |
my $report = shift; |
my $report_in = shift; |
my $report_file = shift; |
$PLogger->debug(sub{ "UpdateReportmanConfigFile report_in=$report_in"; }); |
my (undef, undef, undef, undef, undef, undef, undef, undef, $atime_report_in, $mtime_report_in) = stat($report_in); |
if(-f $report_file){ |
# confronto le date dei due file |
my (undef, undef, undef, undef, undef, undef, undef, undef, undef, $mtime_report_file) = stat($report_file); |
if($mtime_report_in > $mtime_report_file){ |
# report esistente non aggiornato |
unlink $report_file; |
} |
} |
if(! -f $report_file){ |
open REP_IN, "<$report_in" or die "Can't open $report_in file for reading."; |
open REP_OUT, ">$report_file" or die "Cant'open $report_file file for writing."; |
my $ADO; |
while(<REP_IN>){ |
if(m/^\s+ADOConnectionString\s+=\s*$/){ |
$ADO = 1; |
last; |
} |
print REP_OUT $_; |
} |
if(!$ADO){ |
die "ERRORE: il report '$report' non contiene il parametro di connessione ADOConnectionString"; |
} |
my $ADOConnectionString = ''; |
# leggo le righe del parametro ADOConnectionString |
while(<REP_IN>){ |
if(m/^\s*'(.*)'\s*\+\s*$/){ |
$ADOConnectionString .= $1; |
}elsif(m/^\s*'(.*)'\s*$/){ |
$ADOConnectionString .= $1; |
last; |
}else{ |
die "Error parsing .rep ADOConnectionString in file $report_in"; |
} |
} |
# sostituisco alcuni parametri |
$_ = $r->dir_config('ReportmanADOserver'); |
$ADOConnectionString =~ s/;SERVER=[\w\d\.]+;/;SERVER=$_;/; |
$_ = $r->dir_config('ReportmanADOdatabase'); |
$ADOConnectionString =~ s/;DATABASE=[\w_\-\.]+;/;DATABASE=$_;/; |
$_ = $r->dir_config('ReportmanADOuser'); |
$ADOConnectionString =~ s/;USER=[\w_]+;/;USER=$_;/; |
$_ = $r->dir_config('ReportmanADOpassword'); |
$ADOConnectionString =~ s/;PASSWORD=[^;]+;/;PASSWORD=$_;/; |
print REP_OUT " ADOConnectionString = '$ADOConnectionString'\n"; |
# concludo la copia |
while(<REP_IN>){ |
print REP_OUT $_; |
} |
close REP_OUT; |
close REP_IN; |
# set mtime del file report identico all'originale |
utime $atime_report_in, $mtime_report_in, $report_file; |
} |
return; |
} |
=head3 Reportman() |
Composes a command to be passed to the printreptopdf: |
=over 2 |
=item 1 |
Verifies the L<base|/Arguments> directory. |
=item 2 |
=over 2 |
=item * |
If defined L<ReportmanADOserver|https://www.leader.it/MasonSQL/DatabaseAccess#Apache> variable, composes a Wine command. |
=item * |
If not defined L<ReportmanADOserver|https://www.leader.it/MasonSQL/DatabaseAccess#Apache> variable, composes a Kylix command. |
=back |
=item 3 |
As a commandline options, appends all argument C<name=value> pairs with an exception of the reserved arguments: |
report, |
base, |
path_pdf, |
send_pdf, |
cups_printer, |
PROTECT and |
GROUP_ID |
=back |
Synopsis for printreptopdf: |
printreptopdf 2.9a |
Prints a report manager (.rep) file to a Adobe PDF file |
Usage: printreptopdf [Options] -stdin|reportfilename [outputfilename] |
-q Quiet mode, don't show progress |
-from n Prints report from page pnum |
-to n Prints report to page pnum |
-copies n Prints pnum copies |
-u Generate not compressed pdf |
-m Generate Report Metafile Stream format |
-collate Collate the copies |
-csv Output to comma separated values |
-svg Output to scalable vector graphics format |
-ctxt Output to custom text |
-csvseparator CSV output separator |
-paramPARAMNAME=paramvalue Assign a value to a parameter |
-stdin Read from standard input instead from a file |
-text Generate text output with escape codes to print |
-textdriver driver Use the text driver for text output |
-oemconvert Force recode to oem for text output |
-html Generate Html output |
=cut |
sub Reportman($$$$$){ |
my $base = shift; |
my $report = shift; |
my $report_file = shift; |
my $PDF = shift; |
my $args = shift; |
my @EXEC = (); # comando e parametri di chiamata a Reportman |
# test $base per sicurezza |
$base = $base; |
my $test = $r->dir_config('DataBaseUrl'); |
if($base != $r->dir_config('DataBaseUrl') && $base !~ m/^$test/){ |
die "Base report corrupted ($base).\n"; |
} |
# nome report |
if(!$r->dir_config('ReportmanADOserver')){ |
# script di esecuzione di Reportman |
push @EXEC, $r->dir_config('ReportmanDir').'/printreptopdf.kylix'; |
}else{ |
# utilizzo la versione Windows di Reportman con il driver ADO che incorpora la stringa di connessione |
my $report_in = request_to_comp_path("$base/$report.rep"); |
if(-s $report_in){ |
UpdateReportmanConfigFile($report, $report_in, $report_file); |
} |
# script di esecuzione di Reportman |
push @EXEC, $r->dir_config('ReportmanDir').'/printreptopdf.wine'; |
} |
# aggiungo i vari parametri |
push @EXEC, '-q'; |
$PLogger->debug(sub{ Dumper($args); }); |
foreach my $key (keys %{$args}){ |
if($key !~ m/^report|base|path_pdf|send_pdf|cups_printer|PROTECT$/){ |
my $arg = $args->{$key}; |
if(defined $arg){ |
push @EXEC, "-param$key=$args->{$key}", |
} |
} |
} |
# aggiungo ai parametri il report |
push @EXEC, $report_file; |
# aggiungo ai parametri il file PDF |
push @EXEC, $PDF; |
$PLogger->debug(sub{ "report_params=",Dumper(\@EXEC); }); |
$PLogger->debug(sub{ Dumper(\%ENV); }); |
$PLogger->debug(sub{ "CALL ".' '.join(' ', @EXEC); }); |
return \@EXEC; |
} |
=head3 OdtReport() |
Creates the ODT report. |
Procedure to create ODT report: |
=over 2 |
=item 1 |
The CLI options for creating the report are passed to the ODT Report's L<CLI parser|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#parse_cli()> as an array. |
The required arguments are in the C<arg_name:arg_value> format. |
The required arguments: C<config_path>, C<report_name> and C<odt_filepath>. |
The rest of the arguments are L<added|/AddArgs()> to the array in the C<arg_name=arg_value> format. |
=item 2 |
L<get_odt_report()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report()> |
=item 3 |
L<get_odt_report_fields()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report_fields()> |
=item 4 |
L<get_odt_report_portions()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report_portions()> |
=item 5 |
L<make_report()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#make_report()> |
=back |
=cut |
sub OdtReport($$$$){ |
my $report = shift; |
my $REPORT_ID = shift; |
my $odt = shift; |
my $args = shift; |
$report =~ s/\//\./; |
$PLogger->debug(sub{ "OdtReport REPORT_ID=$REPORT_ID"; }); |
my @cli_options = ( |
'config_path:'.$r->dir_config('ConfigPath'), |
'report_name:'.$report, |
'odt_filepath:'.$odt |
); |
AddArgs(\@cli_options, $REPORT_ID, $args); |
my $rpt = MasonSQL::Report->new( |
OdtConvEngine => $r->dir_config('OdtConvEngine'), |
Dbh => $Session{Dbh_report}, |
TmpDir => $r->dir_config('TmpDir'), |
InputFilesArchive => $r->dir_config('InputFilesArchive'), |
Cli_options => \@cli_options |
); |
unless($rpt->make_report){ |
die "Base filename must be specified when creating ODT report!"; |
} |
if(my $out = $rpt->output){ |
$PLogger->debug(sub{ "OdtReport out=[\n$out\n]"; }); |
} |
$rpt = undef; |
return; |
} |
=head3 PdfReport() |
Creates the PDF report. |
Procedure to create PDF report: |
=over 2 |
=item 1 |
The CLI options for creating the report are passed to the ODT Report's L<CLI parser|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#parse_cli()> as an array. |
The required arguments are in the C<arg_name:arg_value> format. |
The required arguments: C<config_path>, C<report_name>, C<odt_filepath> and C<pdf_filepath>. |
The rest of the arguments are L<added|/AddArgs()> to the array in the C<arg_name=arg_value> format. |
=item 2 |
L<get_odt_report()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report()> |
=item 3 |
L<get_odt_report_fields()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report_fields()> |
=item 4 |
L<get_odt_report_portions()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#get_odt_report_portions()> |
=item 5 |
L<make_report()|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#make_report()> |
If PDF filepath is created convert it to PDF format with Unoconv or Libreoffice. |
If any attachments exist also L<append|https://www.leader.it/MasonSQL/SrcLibMasonSQLReportPm#add_attachments()> them to the converted PDF. |
=item 6 |
Push the generated report to the list of reports which will be later concatenated into one PDF. |
=back |
=cut |
sub PdfReport($$$$$){ |
my $report = shift; |
my $REPORT_ID = shift; |
my $pdf_reports = shift; |
my $odt_reports = shift; |
my $args = shift; |
my $pdf = &TmpFile("pdf_report", '.pdf'); |
my $odt = &TmpFile("odt_report", '.odt'); |
$report =~ s/\//\./; |
$PLogger->debug(sub{ "PdfReport REPORT_ID=$REPORT_ID odt=$odt pdf=$pdf report=$report" }); |
$report =~ s/\//\./; |
my @cli_options = ( |
'config_path:'.$r->dir_config('ConfigPath'), |
'report_name:'.$report, |
'odt_filepath:'.$odt, |
'pdf_filepath:'.$pdf |
); |
AddArgs(\@cli_options, $REPORT_ID, $args); |
my $rpt = MasonSQL::Report->new( |
OdtConvEngine => $r->dir_config('OdtConvEngine'), |
Dbh => $Session{Dbh_report}, |
TmpDir => $r->dir_config('TmpDir'), |
InputFilesArchive => $r->dir_config('InputFilesArchive'), |
Cli_options => \@cli_options |
); |
my $pdf_filepath = $rpt->get_pdf_filepath; |
if(my $odt_filepath = $rpt->make_report){ |
if(-z $odt_filepath){ |
die "PdfReport running make_report: $odt_filepath is empty\n"; |
} |
my $main_report = $pdf_filepath.'_main.pdf'; |
my $converter = MasonSQL::Report::OdtConv->new(Engine => $r->dir_config('OdtConvEngine')); |
$converter->convert_to_pdf($odt_filepath, $main_report); |
unlink $odt_filepath; |
$rpt->add_attachments($main_report, $pdf_filepath); |
unlink $main_report; |
}else{ |
$rpt->add_attachments('', $pdf_filepath); |
} |
if(my $out = $rpt->output){ |
$PLogger->debug(sub{ "OdtReport out=[\n$out\n]"; }); |
} |
$rpt = undef; |
push(@{$pdf_reports}, $pdf); |
push(@{$odt_reports}, $odt); |
return; |
} |
=head3 CatPdfs() |
Concatenate multiple PDFs into one PDF. |
The concatenation is made with C<pdftk> executable, with the command: |
pdftk <filepath1> <filepath2> ... <filepathN> cat output <output_filepath> |
=cut |
sub CatPdfs($$){ |
my $pdf_reports = shift; |
my $PDF = shift; |
foreach my $file (@{$pdf_reports}){ |
if(! -e $file){ |
die "CatPdfs ERROR file '$file' in list not exists\n"; |
} |
if(-z $file){ |
die "CatPdfs ERROR file '$file' in list is empty\n"; |
} |
} |
my $pdftk = '/usr/bin/pdftk'; |
if(! -e $pdftk){ |
die "CatPdfs ERROR $pdftk not exists\n"; |
} |
my @cmd = ($pdftk); |
push(@cmd, @{$pdf_reports}); |
push(@cmd, 'cat'); |
push(@cmd, 'output'); |
push(@cmd, $PDF); |
RunCmd('CatPdfs', \@cmd); |
return; |
} |
=head3 UnlinkTmpReports() |
Unlink temporary B<.pdf> and B<.odt> files. |
=cut |
sub UnlinkTmpReports($$){ |
my $pdf_reports = shift; |
my $odt_reports = shift; |
foreach my $odt (@{$odt_reports}){ |
$PLogger->debug(sub{ "unlink $odt" }); |
unlink $odt; |
} |
foreach my $pdf (@{$pdf_reports}){ |
$PLogger->debug(sub{ "unlink $pdf" }); |
unlink $pdf; |
} |
return; |
} |
=head3 RunCmd() |
L<Run|http://search.cpan.org/~toddr/IPC-Run-0.94/lib/IPC/Run.pm> command. |
Print the command output to the debug log. |
In case an error is detected, pass on the error message and die. |
=cut |
sub RunCmd($$){ |
my $name = shift; |
my $cmd = shift; |
my ($err, $out); |
#DEBUG $PLogger->debug(sub{ "run: name:$name ".Dumper($cmd); }); |
if(run $cmd, \undef, \$out, \$err){ |
if($out){ |
$PLogger->debug(sub{ "$name out=[\n$out\n]"; }); |
} |
if($err){ |
$PLogger->error(sub{ $err }); |
} |
}else{ |
my $mess_run = "ERROR '$?' Run('".(join "', '", @$cmd)."')"; |
#DEBUG print STDERR "$mess_run\nSTDOUT:[$out]\nSTDERR:[$err]\n"; |
$out =~ s/\n/ - /sg; |
$err =~ s/\n/ - /sg; |
$PLogger->error("$mess_run - STDOUT:[$out] STDERR:[$err]\n"); |
if($PLogger->level eq $DEBUG){ |
die "$mess_run - STDOUT:[$out] STDERR:[$err]\n"; |
}else{ |
die "$mess_run - Details in logs!\n"; |
} |
} |
return; |
} |
=head3 AddArgs() |
Appends all arguments (along with the REPORT_ID) to the command line with exception of the reserved arguments. The reserved arguments are: |
report, |
base, |
path_pdf, |
send_pdf, |
cups_printer and |
PROTECT |
GROUP_ID |
=cut |
sub AddArgs($$$){ |
my $cmd = shift; |
my $REPORT_ID = shift; |
my $args = shift; |
push (@{$cmd}, "REPORT_ID=$REPORT_ID"); |
foreach my $key (keys %{$args}){ |
if($key !~ m/^report|base|path_pdf|send_pdf|cups_printer|PROTECT|GROUP_ID$/){ |
my $arg = $args->{$key}; |
if(defined $arg){ |
push (@{$cmd}, "$key=$args->{$key}"); |
} |
} |
} |
return; |
} |
=head3 PrintPaths() |
Returns a newly created temporary ODT and PDF filepaths. |
In case the L<path_pdf|/Arguments> is defined it uses it for filepath instead of composing it with L<TmpDir|https://www.leader.it/MasonSQL/DatabaseAccess#Apache> directory root path. |
=cut |
sub PrintPaths($$){ |
my $report = shift; |
my $path_pdf = shift; |
my $PDF = ''; |
my $ODT = ''; |
if($path_pdf){ |
$PDF = $path_pdf; |
$ODT = $path_pdf; |
$ODT =~ s/\.pdf$/\.odt/; |
}else{ |
my $tmp_dir = $r->dir_config('TmpDir'); |
$PDF = "$tmp_dir/report.$$.pdf"; |
$ODT = "$tmp_dir/report.$$.odt"; |
} |
#DEBUG $PLogger->debug(sub{ "ODT=$ODT"; }); |
#DEBUG $PLogger->debug(sub{ "PDF=$PDF"; }); |
return ($PDF, $ODT); |
} |
=head3 TmpFile() |
Uses L<File::Temp::tempfile|http://search.cpan.org/~dagolden/File-Temp-0.2304/lib/File/Temp.pm> to create a new temporary file. |
Closes the file, to make sure it is unlocked, then returns its filepath. |
=cut |
sub TmpFile($$){ |
my $prefix = shift; |
my $suffix = shift; |
my($fh, $filepath) = tempfile( |
$prefix . '_XXXXX', |
DIR => $r->dir_config('TmpDir'), |
SUFFIX => $suffix, |
UNLINK => 0 |
); |
close $fh; |
#DEBUG $PLogger->debug(sub{ "TmpFile=$filepath"; }); |
return $filepath; |
} |
=head2 Copyright |
(C) 2003 Leader.IT di Guido Brugnara <http://www.leader.it> |
Strada della Pozzata, 41 - Villazzano |
38123 T R E N T O (ITALY) |
=head2 Authors |
Guido Brugnara <gdo@leader.it> |
=cut |
</%once> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
/tags/2.0/htdocs/lib/head_style.comp |
---|
0,0 → 1,15 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Componente utilizzato per dichiarare degli <STYLE/> tag che verranno interiti |
nell'intestazione della pagina html. |
</%doc> |
<%perl> |
push @{$Global{LoadHeader_Style}}, $m->content; |
</%perl> |
/tags/2.0/htdocs/lib/library.js |
---|
0,0 → 1,681 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2003 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%once> |
my $GetRecordTimeout = $r->dir_config('GetRecordTimeout'); |
my $GetFormTimeout = $r->dir_config('GetFormTimeout'); |
</%once> |
// libreria di funzioni generiche |
require(["dijit/Dialog", "dijit/form/Button"]); |
%#//DOJO1.8 dojo.require("dijit.Dialog"); |
%#//DOJO1.8 dojo.require("dijit.form.Button"); |
%#// VEDI http://dojotoolkit.org/reference-guide/1.8/dijit/focus.html |
%#// BEGIN DEBUG |
%#// require([ "dijit/focus" ], function(focusUtil){ |
%#// focusUtil.watch("activeStack", function(name, oldValue, newValue){ |
%#// console.debug("Focused widget + ancestors: ", newValue.join(", ")); |
%#// }); |
%#// focusUtil.on("widget-focus", function(widget){ |
%#// console.debug("Focused widget", widget); |
%#// }); |
%#// focusUtil.on("widget-blur", function(widget){ |
%#// console.debug("Blurred widget", widget); |
%#// }); |
%#// }); |
%#// END DEBUG |
require(["dojo/_base/declare", "dojo/Evented", "dijit/registry", "dojo/_base/array", "dojo/_base/fx", "dojo/dom-construct", "dojo/dom"], |
function(declare, Evented, registry, array, fx, domConstruct, dom){ |
// Nuova classe masonSql |
var MasonSql = declare(Evented, { |
version: '1.0', |
disp: {}, |
createDisplay: function(name, from, rows){ |
if(this.disp[name]){ |
var mess = "Display 'name' già esistente"; |
my_alert(mess); |
console.error(mess, this.displays[name]); |
} |
var recordset = new DataBinding(name, from, rows); |
var display = new DisplayBinding(name, recordset); |
this.disp[name] = display; |
return display; |
}, |
ready: function(obj){ |
this.emit("ready", obj); |
}, |
once: function(evt, func){ |
var handler = this.on(evt, function(data){ |
func(data); |
handler.remove(); |
}); |
}, |
%# // richiamata da /frame.html quando viene lanciato l'evento masonSql ready (al termine del caricamento e rendering dojo) |
frameLoad_Handler: function(prefix, with_children, height){ |
%# // dimensione finestra principale (solo se vi sono finestre figlie) |
var FatherMain = registry.byId('FatherMain_'+prefix); |
if(with_children){ |
var FatherMainDom = FatherMain.get("containerNode"); |
if(!height){ |
height = 0; |
var heigh_centr = 0; |
array.forEach(FatherMain.getChildren(), function(child){ |
var region = child.get("region"); |
var container = child.get("containerNode") |
if(region == 'top' || region == 'bottom'){ |
height += container.offsetHeight; |
}else if(heigh_centr < container.scrollHeight){ |
heigh_centr = container.scrollHeight |
} |
}); |
height += heigh_centr; |
} |
console.debug('Resize form ' + FatherMainDom.id + ' to ' + height + 'px'); |
% # riscontrato in Chrome e Safari la necessità di ridimensionare due volte per evitare l'attivazione delle barre di scorrimento |
% if($Session{Browser}->chrome || $Session{Browser}->webkit){ |
FatherMainDom.style.height = (height + 50).toString()+'px'; |
FatherMain.getParent().resize(); |
% } |
FatherMainDom.style.height = (height + 4).toString()+'px'; |
} |
FatherMain.getParent().resize(); |
fx.fadeOut({ |
node: dom.byId('loadingOverlay_' + prefix), |
duration: 700, |
onEnd: function(node){ |
domConstruct.destroy(node); |
} |
}).play(); |
} |
}); |
window.masonSql = new MasonSql(); |
}); |
// oggetto dojox/widget/DialogSimple per gli avvisi |
var masonSql_Dialog; |
require(["dojo/ready", "dojo/io-query", "dojox/widget/DialogSimple"], function(ready, ioQuery, DialogSimple){ |
ready(function(){ |
masonSql_Dialog = new DialogSimple({ |
title: '', |
executeScripts: true, |
renderStyles: true, |
scriptHasHooks: true, |
parseOnLoad: true, |
cleanContent: true, |
closable: true, |
ioArgs: { |
headers: { |
'MasonSql-body': '1' |
}, |
timeout: <% $r->dir_config('GetFormTimeout') %> |
} |
}); |
masonSql_Dialog.openUrl = function (url, url_params, width, height, title){ |
if(width && height){ |
this.set('style', 'width:' + width + 'px; height:' + height + 'px;'); |
} |
this.set('title', title); |
this.show(); |
if(url_params){ |
url += '?' + ioQuery.objectToQuery(url_params); |
} |
this.set('href', url).then( |
function(){ |
console.debug('downloaded', url, masonSql_Dialog); |
masonSql.ready(); |
}, |
function(err){ |
tab.set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+' id:'+masonSql_Dialog.id+' timeout:'+<% $r->dir_config('GetFormTimeout') %>+"</span>"); |
console.error('ERROR href',err , masonSql_Dialog); |
} |
); |
}; |
masonSql_Dialog.openHtml = function (html, width, height, title, timeout){ |
if(masonSql_Dialog.timer){ |
window.clearTimeout(masonSql_Dialog.timer); |
masonSql_Dialog.timer = null; |
} |
if(width && height){ |
this.set('style', 'width:' + width + 'px; height:' + height + 'px;'); |
} |
this.set('title', title); |
this.set('content', html); |
this.show(); |
if(timeout){ |
masonSql_Dialog.timer = setTimeout( function(){ |
masonSql_Dialog.hide(); |
}, timeout * 1000); |
} |
}; |
}); |
}); |
// finestra di avviso |
// str messaggio da visualizzare |
// type tipo di messaggio: html, txt, auto, alert o pre(default) |
// X, Y: dimensioni della finestra (default 300x600 |
// timeout: secondi di attesa per la chiusura della finestra |
function my_alert(str, type, X, Y, timeout){ |
if(type == 'auto'){ |
// cerco di determinare il formato di visualizzazione più adatto in base al contenuto |
var re = /<html/i; |
if(re.test(str)){ |
type = 'html'; |
}else{ |
type = 'txt'; |
} |
} |
if(type == 'alert'){ |
alert(str); |
return; |
} |
switch(type){ |
case 'html': |
break; |
case 'txt': |
str=str.replace(/</g,'<'); |
str=str.replace(/>/g,'>'); |
str=str.replace(/\n/g,'<br>\n'); |
break; |
case 'pre': |
default: |
str = '<pre>'+str+'</pre>'; |
} |
masonSql_Dialog.openHtml(str, X, Y, 'ALERT', timeout); |
} |
// numero la stringa |
function enum_text(txt){ |
var linecodes = txt.split(/\n/); |
for(var C=0; C<linecodes.length; C++){ |
linecodes[C] = '[' + C + '] ' + linecodes[C]; |
} |
return linecodes.join('\n'); |
} |
// visualizza una finestra di avviso con l'errore riscontrato |
// |
function my_alert_error(message, err, code){ |
if(err){ |
// numero il codice |
code = enum_text(code); |
var stack = err.stack; |
stack = stack.replace(/\n/gm, '\n________________________________________ stack ________________________________________\n'); |
stack = stack.replace(/\\n/gm, '\n'); |
my_alert('Error: MOZ ' + message + ' line=' + err.lineNumber + |
' message = [' + err.message + ']\n' + |
'________________________________________ STACK ________________________________________\n' + stack + '\n' + |
'________________________________________ CODE ________________________________________\n' + code, 'txt'); |
}else{ |
my_alert('Error: ' + message, 'txt'); |
} |
} |
function pageTimeoutLoad(contextID, type, str){ |
var contextObj = hReqMason_ContextPool[contextID]; |
contextObj.obj_params.Loadobj.innerHTML=''; |
if(type == 'TIMEOUT'){ |
my_alert('Timeout caricamento pagina ' + contextObj.URL); |
}else{ |
my_alert('ERRORE '+type+' pagina '+contextObj.URL+': \n['+str+']'); |
} |
} |
// funzione callback; esegue il codice passato nella chiamata dopo il caricamento della pagina |
// Loadobj è l'oggetto nel quale la pagina è stata caricata |
function pageCallbackLoad(Loadobj, contextID){ |
if(Loadobj != null){ |
var callback_code = Loadobj.Callback_code; |
var timeout = Loadobj.Callback_code_timeout; |
if(callback_code != null && callback_code != ''){ |
// riferimento globale dell'oggetto, da potersi usare nel codice da eseguire |
CurrentLoadobj = Loadobj; |
if(timeout){ |
%#DEBUG |
<% $JSLogger->debug(q|'pageCallbackLoad - setTimeout timeout:'+timeout+' code:'+callback_code|)%> |
window.setTimeout(callback_code, timeout); |
}else{ |
eval(callback_code); |
} |
} |
} |
} |
function divReload(Elem){ |
if(Elem.URL != null){ |
divLoad(Elem, Elem.URL, Elem.Params, Elem.Callback_code, Elem.Callback_code_timeout); |
}else{ |
my_alert("ERRORE: L'elemento '"+Elem.id+"' indicato non ha riferimenti alla URL da caricare", 'txt', 400, 100); |
} |
} |
// caricamento dinamico della pagina remota "page" nell'elemento "Elem" con i parametri "params" |
// e funzione di callback "callback" |
function divLoad(Elem, page, params, callback_code, timeout){ |
if(Elem){ |
dojo.forEach(dijit.findWidgets(Elem), function(widget) { |
widget.destroyRecursive(false); |
}); |
dojo.empty(Elem); |
if(page == ''){ |
//Elem.innerHTML=''; |
Elem.disabled = false; |
Elem.Callback_code_timeout = timeout; |
if(callback_code != null && callback_code != ''){ |
if(timeout){ |
%#DEBUG <% $JSLogger->debug(q|'divLoad page null - setTimeout timeout:'+timeout+' code:'+callback_code|)%> |
window.setTimeout(callback_code, timeout); |
}else{ |
eval(callback_code); |
} |
} |
}else{ |
Elem.disabled = true; |
Elem.Callback_code = callback_code; |
Elem.Callback_code_timeout = timeout; |
hReqMason_LoadTimeout(Elem, <%$GetFormTimeout%>, pageTimeoutLoad, pageCallbackLoad, page, params); |
} |
}else{ |
my_alert('ERRORE: divLoad(Elem, '+page+', '+params+') non utilizzabile in quanto non è definito l\'oggetto Elem di destinazione', 'txt', 400, 100); |
} |
} |
// provvede a caricare un tag DIV differente per ogni differente "page" e lo inserisce in "Div" |
// |
function divLoadBuffered(Div, page, params, callback_code, reload, timeout){ |
// elenco elementi gia presenti |
var elenco = Div.childNodes; |
var current = null; |
for(var i=0; i<elenco.length; i++){ |
var elem = elenco.item(i); |
if(elem.URL != null){ |
// elaboro solo gli elementi che hanno definito l'attributo "URL" |
if(elem.URL == page){ |
// trovato elemento |
current = elem; |
}else{ |
// disattivo elemento |
elem.style.display = 'none'; |
} |
} |
} |
var loaded; |
if(current == null){ |
loaded = false; |
current = document.createElement('div'); |
current.URL = page; |
current.Params = params; |
Div.appendChild(current); |
divLoad(current, page, params, callback_code, timeout); |
}else{ |
loaded = true; |
if(reload){ |
divLoad(current, page, params, callback_code); |
}else{ |
if(callback_code != null && callback_code != ''){ |
eval(callback_code); |
} |
} |
} |
// attivo l'elemento |
current.style.display = 'inline'; |
return current; |
} |
// DEPRECATED !! -legacy framework < 2013 |
function pageLoad(page, menu, params, cb_code_page, cb_code_menu, reload, timeout_page, timeout_menu){ |
if(menu){ |
my_alert("ATTENZIONE: Non è più possibile chiamare pageLoad!"); |
}else{ |
bodyLoad(page, params, cb_code_page, reload, timeout_page); |
} |
} |
// caricamento dinamico di pagina |
// ad ogni tipo di pagina caricato dispone un differente TAG di tipo <DIV> che lo contiene |
function bodyLoad(page, params, cb_code, reload, timeout){ |
cb_code = cb_code ? cb_code + ';' : ''; |
if(timeout == null){ |
timeout = 10; |
} |
if(page != null){ |
divLoad(CurrentBody, page, params, cb_code, reload, timeout); |
if(CurrentBody != null && CurrentBody.onMenuSelect){ |
CurrentBody.onMenuSelect(); |
} |
} |
} |
// manipolazione array |
// estende i metodi della classe Array |
// verifica se tutti gli elementi dell'array sono nulli |
Array.prototype.allNull = function(){ |
for(var I=0; I<this.length; I++){ |
// verifico se l'elemento a sua volta è un Array |
var elem = this[I]; |
if(Array.prototype.isPrototypeOf(elem)){ |
if(!elem.allNull()){ |
return false |
} |
}else{ |
if(elem != null){ |
return false; |
} |
} |
} |
return true; |
} |
function CreateEmptyArray(Row,Col){ |
var arr = new Array(Row); |
for(var r=0; r<Row; r++){ |
arr[r] = new Array(Col); |
} |
return arr; |
} |
function DuplicaArray(arr){ |
var N = new Array(arr.length); |
for(var R=0; R<arr.length; R++){ |
var V=arr[R]; |
N[R] = new Array(V.length); |
var D=N[R]; |
for(var C=0; C<V.length; C++){ |
D[C]=V[C]; |
} |
} |
%#//my_alert('old='+arr.length+' new='+N.length+'\nold:'+Array2String(arr, 'null')+'\nnew:'+Array2String(N, 'null')); |
return N; |
} |
// usata da ArrayDiffKeys e da ArrayDiff |
// valuta New <=> Old se c'è differenza oppure Val <> '' |
// New = nuovo dato |
// Old = dato precedente |
// Null = == true il campo con valore 'null' viene considerato uguali a '' |
// Val <> '' ritorna sempre il valore nuovo |
function Diff_values(New, Old, Null, Val){ |
// my_alert('null="'+Null+'"\nis_different='+(New != Old)+'\non TEST [[['+New+']]]\n[[['+Old+']]]'); |
var S = null; |
if(!( Null && |
(New == '' || New == null) && |
(Old == '' || Old == null) |
) || |
Val != '' |
){ |
if(New == null){ |
S = ''; |
}else{ |
S = ''+New; |
S = S.replace(/\r/g,''); |
} |
} |
// my_alert('New:'+New+' old:'+Old+' Null:'+Null+' Val:'+Val+'\n Return:'+(Val != '' ? S : ( New != Old ? S : null ))); |
return Val != '' ? S : ( New != Old ? S : null ); |
} |
// calcola una matrice di differenze; |
// Key = vettore di chiavi relative all'array |
// Old = matrice non modificata |
// New = matrice modificata |
// Null = == true i campi null vengono considerati uguali a '' |
// |
function ArrayDiffKeys(Key, Old, New, Null){ |
var Diff = CreateEmptyArray(Old.length, Old[0] && Old[0].length); |
for(var R=0; R<Old.length; R++){ |
var New_row = New[R]; |
var Old_row = Old[R]; |
var Diff_row = Diff[R]; |
// valuto se la prima colonna è vuota |
// se vuota si tratta di un nuovo campo (inserimento) |
if(Key[R]){ |
for(var C=0; C<New_row.length; C++){ |
Diff_row[C] = Diff_values(New_row[C], Old_row[C], Null, ''); |
} |
}else{ |
// valuto se c'è almeno un campo diverso; se sì: copio |
// indistintamente tutti i campi |
for(var L=0; L<New_row.length; L++){ |
var N = New_row[L]; |
N = (N == '' || N == null) ? '' : N; |
var O = Old_row[L]; |
O = (O == '' || O == null) ? '' : O; |
// se c'è almeno un campo diverso valuto tutta la riga |
if(N != O){ |
for(var C=0; C<New_row.length; C++){ |
Diff_row[C] = Diff_values(New_row[C], Old_row[C], Null, New_row[C]); |
} |
break; |
} |
} |
} |
} |
//DEBUG my_alert('ArrayDiffKeys\nKey:'+Vector2String(Key,'null')+'\nOld:'+Array2String(Old,'null')+'\nNew:'+Array2String(New,'null')+'\nDiff:'+Array2String(Diff,'null')); |
return Diff; |
} |
// calcola una matrice di differenze; |
// Old = matrice non modificata |
// New = matrice modificata |
// Null = == true i campi null vengono considerati uguali a '' |
// |
function ArrayDiff(Old, New, Null){ |
var D=CreateEmptyArray(Old.length, Old[0].length); |
for(var R=0; R<Old.length; R++){ |
var New_row=New[R]; |
var Old_row=Old[R]; |
var Diff_row=D[R]; |
for(var C=0; C<New_row.length; C++){ |
Diff_row[C] = Diff_values(New_row[C], Old_row[C], Null, ''); |
} |
} |
return D; |
} |
// valuta il numero di righe con la prima colonna vuota (record nuovi) |
function ArrayNewRowNum(Key, Data){ |
var num=0; |
for(var R=0; R<Data.length; R++){ |
var P = Data[R]; |
if(P && Key[R] == null){ |
for(var C=0; C<P.length; C++){ |
if(P[C] !='' && P[C]!=null){ |
num++; |
C=P.length; |
} |
} |
} |
} |
return num; |
} |
// restituisce una stringa rappresentazione della matrice |
// il campo non definito viene lasciato vuoto |
// Key = vettore chiavi |
// Data = matrice dei dati |
// Null = stringa di rappresentazione campi nulli |
// AllRows = ==true vengono generate anche le righe nulle |
// OnlyKey per le righe nulle viene inserito una riga con il solo campo chiave |
// DupKeys viene accodato il valore della riga corrispondente in fondo alla nuova riga restituita (usato in dbms_library.comp) |
function KeyArray2String(Key, Data, Null, AllRows, OnlyKey, DupKeys){ |
var S='['; |
var no0=false; |
for(var R=0; R<Data.length; R++){ |
var Dif=Data[R]; |
var key=Key[R]; |
var differ=false |
if(Dif){ |
var Sr; |
if(key != null){ |
Sr='[\''+key+'\''; |
}else{ |
Sr='['+Null; |
} |
for(var C=0; C<Dif.length; C++){ |
if(Dif[C] != null){ |
var V=new String(Dif[C]); |
V=V.replace(/\\/g,'\\\\'); |
V=V.replace(/'/g,"\\'");//" |
Sr+=',\''+V+'\''; |
differ=true; |
}else{ |
Sr+=','+Null; |
} |
} |
if(key == null && DupKeys[R]){ |
Sr+=','+DupKeys[R]; |
} |
if(AllRows){ |
if(OnlyKey){ |
if(differ){ |
no0 ? S+=',' : no0=true; |
S+=Sr+']'; |
}else{ |
if(key != null){ |
no0 ? S+=',' : no0=true; |
S+='[\''+key+'\']'; |
} |
} |
}else{ |
no0 ? S+=',' : no0=true; |
S+=Sr+']'; |
} |
}else{ |
if(differ){ |
no0 ? S+=',' : no0=true; |
S+=Sr+']'; |
} |
} |
} |
} |
S+=']'; |
return S; |
} |
// restituisce una stringa rappresentazione della matrice |
// Data = matrice dei dati |
// Null = stringa di rappresentazione campi nulli, se omessa 'null' |
// |
function Array2String(Data, Null){ |
if(!Data){ |
return '[ Array data null ]'; |
} |
var S = '[\n'; |
for(var R=0; R<Data.length; R++){ |
S += Vector2String(Data[R], Null) + '\n'; |
} |
S += '];'; |
return S; |
} |
// restituisce una stringa rappresentazione del vettore |
// Data = vettore dei dati |
// Null = stringa di rappresentazione campi nulli, se omessa 'null' |
// |
function Vector2String(Data, Null){ |
if(!Data){ |
return '[ Vector data null ]'; |
} |
var Sr = ' ['; |
for(var C=0; C<Data.length; C++){ |
if(Data[C] != null){ |
var V=new String(Data[C]); |
V=V.replace(/\\/g,'\\\\'); |
V=V.replace(/'/g,"\\'"); |
Sr += C==0 ? '\''+V+'\'' : ',\''+V+'\''; //" |
}else{ |
Sr += C==0 ? Null : ','+Null; |
} |
} |
return Sr + ']'; |
} |
// tabella entity HTML |
var Entities = { |
Aacute:0x00c1, aacute:0x00e1, Acirc:0x00c2, acirc:0x00e2, acute:0x00b4, AElig:0x00c6, aelig:0x00e6, Agrave:0x00c0, |
agrave:0x00e0, alefsym:0x2135, Alpha:0x0391, alpha:0x03b1, amp:0x0026, and:0x2227, ang:0x2220, Aring:0x00c5, |
aring:0x00e5, asymp:0x2248, Atilde:0x00c3, atilde:0x00e3, Auml:0x00c4, auml:0x00e4, bdquo:0x201e, Beta:0x0392, |
beta:0x03b2, brvbar:0x00a6, bull:0x2022, cap:0x2229, Ccedil:0x00c7, ccedil:0x00e7, cedil:0x00b8, cent:0x00a2, |
Chi:0x03a7, chi:0x03c7, circ:0x02c6, clubs:0x2663, cong:0x2245, copy:0x00a9, crarr:0x21b5, cup:0x222a, curren:0x00a4, |
dagger:0x2020, Dagger:0x2021, darr:0x2193, dArr:0x21d3, deg:0x00b0, Delta:0x0394, delta:0x03b4, diams:0x2666, |
divide:0x00f7, Eacute:0x00c9, eacute:0x00e9, Ecirc:0x00ca, ecirc:0x00ea, Egrave:0x00c8, egrave:0x00e8, empty:0x2205, |
emsp:0x2003, ensp:0x2002, Epsilon:0x0395, epsilon:0x03b5, equiv:0x2261, Eta:0x0397, eta:0x03b7, ETH:0x00d0, eth:0x00f0, |
Euml:0x00cb, euml:0x00eb, euro:0x20ac, exist:0x2203, fnof:0x0192, forall:0x2200, frac12:0x00bd, frac14:0x00bc, |
frac34:0x00be, frasl:0x2044, Gamma:0x0393, gamma:0x03b3, ge:0x2265, gt:0x003e, harr:0x2194, hArr:0x21d4, hearts:0x2665, |
hellip:0x2026, Iacute:0x00cd, iacute:0x00ed, Icirc:0x00ce, icirc:0x00ee, iexcl:0x00a1, Igrave:0x00cc, igrave:0x00ec, |
image:0x2111, infin:0x221e, int:0x222b, Iota:0x0399, iota:0x03b9, iquest:0x00bf, isin:0x2208, Iuml:0x00cf, iuml:0x00ef, |
Kappa:0x039a, kappa:0x03ba, Lambda:0x039b, lambda:0x03bb, lang:0x2329, laquo:0x00ab, larr:0x2190, lArr:0x21d0, |
lceil:0x2308, ldquo:0x201c, le:0x2264, lfloor:0x230a, lowast:0x2217, loz:0x25ca, lrm:0x200e, lsaquo:0x2039, |
lsquo:0x2018, lt:0x003c, macr:0x00af, mdash:0x2014, micro:0x00b5, middot:0x00b7, minus:0x2212, Mu:0x039c, mu:0x03bc, |
nabla:0x2207, nbsp:0x00a0, ndash:0x2013, ne:0x2260, ni:0x220b, not:0x00ac, notin:0x2209, nsub:0x2284, Ntilde:0x00d1, |
ntilde:0x00f1, Nu:0x039d, nu:0x03bd, Oacute:0x00d3, oacute:0x00f3, Ocirc:0x00d4, ocirc:0x00f4, OElig:0x0152, |
oelig:0x0153, Ograve:0x00d2, ograve:0x00f2, oline:0x203e, Omega:0x03a9, omega:0x03c9, Omicron:0x039f, omicron:0x03bf, |
oplus:0x2295, or:0x2228, ordf:0x00aa, ordm:0x00ba, Oslash:0x00d8, oslash:0x00f8, Otilde:0x00d5, otilde:0x00f5, |
otimes:0x2297, Ouml:0x00d6, ouml:0x00f6, para:0x00b6, part:0x2202, permil:0x2030, perp:0x22a5, Phi:0x03a6, phi:0x03c6, |
Pi:0x03a0, pi:0x03c0, piv:0x03d6, plusmn:0x00b1, pound:0x00a3, prime:0x2032, Prime:0x2033, prod:0x220f, prop:0x221d, |
Psi:0x03a8, psi:0x03c8, quot:0x0022, radic:0x221a, rang:0x232a, raquo:0x00bb, rarr:0x2192, rArr:0x21d2, rceil:0x2309, |
rdquo:0x201d, real:0x211c, reg:0x00ae, rfloor:0x230b, Rho:0x03a1, rho:0x03c1, rlm:0x200f, rsaquo:0x203a, rsquo:0x2019, |
sbquo:0x201a, Scaron:0x0160, scaron:0x0161, sdot:0x22c5, sect:0x00a7, shy:0x00ad, Sigma:0x03a3, sigma:0x03c3, |
sigmaf:0x03c2, sim:0x223c, spades:0x2660, sub:0x2282, sube:0x2286, sum:0x2211, sup1:0x00b9, sup2:0x00b2, sup3:0x00b3, |
sup:0x2283, supe:0x2287, szlig:0x00df, Tau:0x03a4, tau:0x03c4, there4:0x2234, Theta:0x0398, theta:0x03b8, thetasym:0x03d1, |
thinsp:0x2009, THORN:0x00de, thorn:0x00fe, tilde:0x02dc, times:0x00d7, trade:0x2122, Uacute:0x00da, uacute:0x00fa, |
uarr:0x2191, uArr:0x21d1, Ucirc:0x00db, ucirc:0x00fb, Ugrave:0x00d9, ugrave:0x00f9, uml:0x00a8, upsih:0x03d2, |
Upsilon:0x03a5, upsilon:0x03c5, Uuml:0x00dc, uuml:0x00fc, weierp:0x2118, Xi:0x039e, xi:0x03be, Yacute:0x00dd, |
yacute:0x00fd, yen:0x00a5, yuml:0x00ff, Yuml:0x0178, Zeta:0x0396, zeta:0x03b6, zwj:0x200d, zwnj:0x200c |
} |
// conversione testo HTML a stringa |
function Html2String(str){ |
var out = ''; |
if(str == null){ |
return; |
} |
var l = str.length; |
for(var i=0; i<l; i++){ |
var ch = str.charAt(i); |
if(ch == '&'){ |
var pos = str.indexOf(';', i+1); |
if(pos > 0){ |
var entity = str.substring(i + 1, pos); |
ch = (entity.length > 1 && entity.charAt(0) == '#') ? |
((entity.charAt(1) == 'x' || entity.charAt(1) == 'X') ? |
String.fromCharCode(eval('0'+entity.substring(1))) : |
String.fromCharCode(eval(entity.substring(1)))) : |
String.fromCharCode(Entities[entity]); |
i = pos; |
} |
} |
out += ch; |
} |
return out; |
} |
// Funzione utilizzata in dbms_library.comp method GENERIC_FIND |
// Se il widget di id id_sel non è selezionato si provvede a selezionare val |
function Set_first_if_not_selected(id, id_sel, val){ |
var sel = document.getElementById(id_sel); |
if(id.get_value()){ |
if(!sel.get_value()){ |
sel.set_value(val); |
} |
}else{ |
sel.set_value(''); |
} |
} |
/tags/2.0/htdocs/lib/autohandler |
---|
0,0 → 1,42 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
// MasonSQL Copyright:2002-2010-2008 Leader.IT di Guido Brugnara http://www.leader.it |
<%attr> |
Cache_MaxAge => 12*60*60 |
</%attr> |
<%perl> |
$r->headers_out->{'Cache-Control'} = 'max-age='.$m->base_comp->attr('Cache_MaxAge'); |
</%perl> |
% $m->call_next; # $m->comp($next); |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%shared> |
initBrowserDetect(); |
# N.B. $Ver è una variabile globale; utilizzo l'ID session |
$Ver = $Session{Session}; |
my $type = lc $m->fetch_next->name; |
$type =~ s/.*\.//; |
if($type eq 'js'){ |
$r->content_type('text/javascript'); |
}elsif($type eq 'css'){ |
$r->content_type('text/css'); |
} |
</%shared> |
<%init> |
# return if $m->cache_self(expire_in => '300 sec'[, key => "lib_$type"]); |
</%init> |
<%filter> |
# if($type eq 'js' && ! $JSLogger->level() eq $DEBUG){ |
# filtra tutti i commenti Jscript |
s|^\s*//.*$||img; |
# } |
</%filter> |
/tags/2.0/htdocs/lib/head_meta.comp |
---|
0,0 → 1,35 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Componente utilizzato per dichiarare i <META> tag che verranno inseriti |
nell'intestazione della pagina html. |
</%doc> |
<%args> |
$http_equiv => undef |
$name => undef |
$content |
</%args> |
<%perl> |
my $meta = '<meta'; |
if($name){ |
$meta .= ' name="'.$m->interp->apply_escapes($name, 'h').'"'; |
} |
if($http_equiv){ |
$meta .= ' http-equiv="'.$m->interp->apply_escapes($http_equiv, 'h').'"'; |
} |
$meta .= ' content="'.$m->interp->apply_escapes($content, 'h').'"/>'; |
my $old_meta = $Global{"Meta/${name}/${http_equiv}"}; |
if(defined $old_meta and $old_meta != $meta){ |
# se la definizione è ripetuta una seconda volta diversa |
# dalla precedente, si tratta di un errore che interrompe l'esecuzione |
die qq|ERROR: Meta $name [$old_meta] different to [$meta]"|; |
} |
$Global{"Meta/${name}/${http_equiv}"} = $meta; |
push @{$Global{LoadHeader_Meta}}, $meta; |
</%perl> |
/tags/2.0/htdocs/lib/LEGGIMI |
---|
0,0 → 1,6 |
N.B. |
Sostituire eventualmente nelle chiamata window.open(URL ..... "about:blank" con '' |
per evitare la segnalazione di sicurezza in Netscape/Mozilla |
/tags/2.0/htdocs/lib/FCKeditor_config.js |
---|
0,0 → 1,188 |
/* |
* FCKeditor - The text editor for internet |
* Copyright (C) 2003-2006 Frederico Caldeira Knabben |
* |
* Licensed under the terms of the GNU Lesser General Public License: |
* http://www.opensource.org/licenses/lgpl-license.php |
* |
* For further information visit: |
* http://www.fckeditor.net/ |
* |
* "Support Open Source software. What about a donation today?" |
* |
* File Name: fckconfig.js |
* Editor configuration settings. |
* See the documentation for more info. |
* |
* File Authors: |
* Frederico Caldeira Knabben (fredck@fckeditor.net) |
*/ |
FCKConfig.CustomConfigurationsPath = '' ; |
FCKConfig.EditorAreaCSS = FCKConfig.BasePath + 'css/fck_editorarea.css' ; |
FCKConfig.DocType = '' ; |
FCKConfig.BaseHref = '' ; |
FCKConfig.FullPage = false ; |
FCKConfig.Debug = false ; |
FCKConfig.AllowQueryStringDebug = true ; |
FCKConfig.SkinPath = FCKConfig.BasePath + 'skins/default/' ; |
FCKConfig.PreloadImages = [ FCKConfig.SkinPath + 'images/toolbar.start.gif', FCKConfig.SkinPath + 'images/toolbar.buttonarrow.gif' ] ; |
FCKConfig.PluginsPath = FCKConfig.BasePath + 'plugins/' ; |
// FCKConfig.Plugins.Add( 'autogrow' ) ; |
FCKConfig.AutoGrowMax = 400 ; |
FCKConfig.ProtectedSource.Add( /<script[\s\S]*?\/script>/gi ) ; // <SCRIPT> tags. |
//FCKConfig.ProtectedSource.Add( /<\%[\s\S]*?\%>/g ) ; // ASP style server side code <\%...\%> |
//FCKConfig.ProtectedSource.Add( /<\?[\s\S]*?\?>/g ) ; // PHP style server side code |
//FCKConfig.ProtectedSource.Add( /(<asp:[^\>]+>[\s|\S]*?<\/asp:[^\>]+>)|(<asp:[^\>]+\/>)/gi ) ; // ASP.Net style tags <asp:control> |
FCKConfig.AutoDetectLanguage = true ; |
FCKConfig.DefaultLanguage = 'it' ; |
FCKConfig.ContentLangDirection = 'ltr' ; |
FCKConfig.ProcessHTMLEntities = true ; |
FCKConfig.IncludeLatinEntities = true ; |
FCKConfig.IncludeGreekEntities = true ; |
FCKConfig.FillEmptyBlocks = true ; |
FCKConfig.FormatSource = true ; |
FCKConfig.FormatOutput = true ; |
FCKConfig.FormatIndentator = ' ' ; |
FCKConfig.ForceStrongEm = true ; |
FCKConfig.GeckoUseSPAN = false ; |
FCKConfig.StartupFocus = false ; |
FCKConfig.ForcePasteAsPlainText = false ; |
FCKConfig.AutoDetectPasteFromWord = true ; // IE only. |
FCKConfig.ForceSimpleAmpersand = false ; |
FCKConfig.TabSpaces = 0 ; |
FCKConfig.ShowBorders = true ; |
FCKConfig.SourcePopup = false ; |
FCKConfig.UseBROnCarriageReturn = false ; // IE only. |
FCKConfig.ToolbarStartExpanded = true ; |
FCKConfig.ToolbarCanCollapse = true ; |
FCKConfig.IgnoreEmptyParagraphValue = true ; |
FCKConfig.PreserveSessionOnFileBrowser = false ; |
FCKConfig.FloatingPanelsZIndex = 10000 ; |
FCKConfig.ToolbarLocation = 'In' ; |
FCKConfig.ToolbarSets["Default"] = [ |
['Source','DocProps','-','Save','NewPage','Preview','-','Templates'], |
['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'], |
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'], |
['Form','Checkbox','Radio','TextField','Textarea','Select','Button','ImageButton','HiddenField'], |
'/', |
['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'], |
['OrderedList','UnorderedList','-','Outdent','Indent'], |
['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'], |
['Link','Unlink','Anchor'], |
['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak','UniversalKey'], |
'/', |
['Style','FontFormat','FontName','FontSize'], |
['TextColor','BGColor'], |
['FitWindow','-','About'] |
] ; |
FCKConfig.ToolbarSets["Basic"] = [ |
['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About'] |
] ; |
FCKConfig.ToolbarSets["MyToolbar"] = [ |
['Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'], |
['Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'], |
['TextColor','BGColor'], |
['FitWindow','-','About'], |
['Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'], |
['OrderedList','UnorderedList','-','Outdent','Indent'], |
['JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'], |
['Link','Unlink','Anchor'], |
['Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak','UniversalKey'], |
['Style','FontFormat','FontName','FontSize'] |
] ; |
FCKConfig.ContextMenu = ['Generic','Link','Anchor','Image','Flash','Select','Textarea','Checkbox','Radio','TextField','HiddenField','ImageButton','Button','BulletedList','NumberedList','Table','Form'] ; |
FCKConfig.FontColors = '000000,993300,333300,003300,003366,000080,333399,333333,800000,FF6600,808000,808080,008080,0000FF,666699,808080,FF0000,FF9900,99CC00,339966,33CCCC,3366FF,800080,999999,FF00FF,FFCC00,FFFF00,00FF00,00FFFF,00CCFF,993366,C0C0C0,FF99CC,FFCC99,FFFF99,CCFFCC,CCFFFF,99CCFF,CC99FF,FFFFFF' ; |
FCKConfig.FontNames = 'Arial;Comic Sans MS;Courier New;Tahoma;Times New Roman;Verdana' ; |
FCKConfig.FontSizes = '1/xx-small;2/x-small;3/small;4/medium;5/large;6/x-large;7/xx-large' ; |
FCKConfig.FontFormats = 'p;div;pre;address;h1;h2;h3;h4;h5;h6' ; |
FCKConfig.StylesXmlPath = FCKConfig.EditorPath + 'fckstyles.xml' ; |
FCKConfig.TemplatesXmlPath = FCKConfig.EditorPath + 'fcktemplates.xml' ; |
FCKConfig.SpellChecker = 'ieSpell' ; // 'ieSpell' | 'SpellerPages' |
FCKConfig.IeSpellDownloadUrl = 'http://iespell.huhbw.com/ieSpellSetup220647.exe' ; |
FCKConfig.MaxUndoLevels = 15 ; |
FCKConfig.DisableObjectResizing = false ; |
FCKConfig.DisableFFTableHandles = true ; |
FCKConfig.LinkDlgHideTarget = false ; |
FCKConfig.LinkDlgHideAdvanced = false ; |
FCKConfig.ImageDlgHideLink = false ; |
FCKConfig.ImageDlgHideAdvanced = false ; |
FCKConfig.FlashDlgHideAdvanced = false ; |
// The following value defines which File Browser connector and Quick Upload |
// "uploader" to use. It is valid for the default implementaion and it is here |
// just to make this configuration file cleaner. |
// It is not possible to change this value using an external file or even |
// inline when creating the editor instance. In that cases you must set the |
// values of LinkBrowserURL, ImageBrowserURL and so on. |
// Custom implementations should just ignore it. |
var _FileBrowserLanguage = '' ; // asp | aspx | cfm | lasso | perl | php | py |
var _QuickUploadLanguage = '' ; // asp | aspx | cfm | lasso | php |
// Don't care about the following line. It just calculates the correct connector |
// extension to use for the default File Browser (Perl uses "cgi"). |
var _FileBrowserExtension = _FileBrowserLanguage == 'perl' ? 'cgi' : _FileBrowserLanguage ; |
FCKConfig.LinkBrowser = false ; |
FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ; |
FCKConfig.LinkBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70% |
FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% |
FCKConfig.ImageBrowser = false ; |
FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ; |
FCKConfig.ImageBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70% ; |
FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ; |
FCKConfig.FlashBrowser = false ; |
FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/' + _FileBrowserLanguage + '/connector.' + _FileBrowserExtension ; |
FCKConfig.FlashBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; //70% ; |
FCKConfig.FlashBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; //70% ; |
FCKConfig.LinkUpload = false ; |
FCKConfig.LinkUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage ; |
FCKConfig.LinkUploadAllowedExtensions = "" ; // empty for all |
FCKConfig.LinkUploadDeniedExtensions = ".(php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi)$" ; // empty for no one |
FCKConfig.ImageUpload = false ; |
FCKConfig.ImageUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Image' ; |
FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png)$" ; // empty for all |
FCKConfig.ImageUploadDeniedExtensions = "" ; // empty for no one |
FCKConfig.FlashUpload = false ; |
FCKConfig.FlashUploadURL = FCKConfig.BasePath + 'filemanager/upload/' + _QuickUploadLanguage + '/upload.' + _QuickUploadLanguage + '?Type=Flash' ; |
FCKConfig.FlashUploadAllowedExtensions = ".(swf|fla)$" ; // empty for all |
FCKConfig.FlashUploadDeniedExtensions = "" ; // empty for no one |
FCKConfig.SmileyPath = FCKConfig.BasePath + 'images/smiley/msn/' ; |
FCKConfig.SmileyImages = ['regular_smile.gif','sad_smile.gif','wink_smile.gif','teeth_smile.gif','confused_smile.gif','tounge_smile.gif','embaressed_smile.gif','omg_smile.gif','whatchutalkingabout_smile.gif','angry_smile.gif','angel_smile.gif','shades_smile.gif','devil_smile.gif','cry_smile.gif','lightbulb.gif','thumbs_down.gif','thumbs_up.gif','heart.gif','broken_heart.gif','kiss.gif','envelope.gif'] ; |
FCKConfig.SmileyColumns = 8 ; |
FCKConfig.SmileyWindowWidth = 320 ; |
FCKConfig.SmileyWindowHeight = 240 ; |
/tags/2.0/htdocs/lib/date.js |
---|
0,0 → 1,293 |
// =================================================================== |
/* Author: Matt Kruse <matt@mattkruse.com> |
WWW: http://www.mattkruse.com/ */ |
// |
// NOTICE: You may use this code for any purpose, commercial or |
// private, without any further permission from the author. You may |
// remove this notice from your final code if you wish, however it is |
// appreciated by the author if at least my web site address is kept. |
// |
// You may *NOT* re-distribute this code in any way except through its |
// use. That means, you can include it in your product, or your web |
// site, or any other form where the code is actually being used. You |
// may not put the plain javascript up on your site for download or |
// include it in your javascript libraries for download. |
// If you wish to share this code with others, please just point them |
// to the URL instead. |
// Please DO NOT link directly to my .js files from your site. Copy |
// the files to your server and use them there. Thank you. |
// =================================================================== |
// ------------------------------------------------------------------ |
// These functions use the same 'format' strings as the |
// java.text.SimpleDateFormat class, with minor exceptions. |
// The format string consists of the following abbreviations: |
// |
// Field | Full Form | Short Form |
// -------------+--------------------+----------------------- |
// Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits) |
// Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits) |
// Day of Month | dd (2 digits) | d (1 or 2 digits) |
// Day of Week | EE (name) | E (abbr) |
// Hour (1-12) | hh (2 digits) | h (1 or 2 digits) |
// Hour (0-23) | HH (2 digits) | H (1 or 2 digits) |
// Hour (0-11) | KK (2 digits) | K (1 or 2 digits) |
// Hour (1-24) | kk (2 digits) | k (1 or 2 digits) |
// Minute | mm (2 digits) | m (1 or 2 digits) |
// Second | ss (2 digits) | s (1 or 2 digits) |
// AM/PM | a | |
// |
// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm! |
// Examples: |
// "MMM d, y" matches: January 01, 2000 |
// Dec 1, 1900 |
// Nov 20, 00 |
// "M/d/yy" matches: 01/20/00 |
// 9/2/00 |
// "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM" |
// ------------------------------------------------------------------ |
var MONTH_NAMES=new Array('January','February','March','April','May','June','July','August','September','October','November','December','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'); |
var DAY_NAMES=new Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sun','Mon','Tue','Wed','Thu','Fri','Sat'); |
function LZ(x) {return(x<0||x>9?"":"0")+x} |
// ------------------------------------------------------------------ |
// isDate ( date_string, format_string ) |
// Returns true if date string matches format of format string and |
// is a valid date. Else returns false. |
// It is recommended that you trim whitespace around the value before |
// passing it to this function, as whitespace is NOT ignored! |
// ------------------------------------------------------------------ |
function isDate(val,format) { |
var date=getDateFromFormat(val,format); |
if (date==0) { return false; } |
return true; |
} |
// ------------------------------------------------------------------- |
// compareDates(date1,date1format,date2,date2format) |
// Compare two date strings to see which is greater. |
// Returns: |
// 1 if date1 is greater than date2 |
// 0 if date2 is greater than date1 of if they are the same |
// -1 if either of the dates is in an invalid format |
// ------------------------------------------------------------------- |
function compareDates(date1,dateformat1,date2,dateformat2) { |
var d1=getDateFromFormat(date1,dateformat1); |
var d2=getDateFromFormat(date2,dateformat2); |
if (d1==0 || d2==0) { |
return -1; |
} |
else if (d1 > d2) { |
return 1; |
} |
return 0; |
} |
// ------------------------------------------------------------------ |
// formatDate (date_object, format) |
// Returns a date in the output format specified. |
// The format string uses the same abbreviations as in getDateFromFormat() |
// ------------------------------------------------------------------ |
function formatDate(date,format) { |
format=format+""; |
var result=""; |
var i_format=0; |
var c=""; |
var token=""; |
var y=date.getYear()+""; |
var M=date.getMonth()+1; |
var d=date.getDate(); |
var E=date.getDay(); |
var H=date.getHours(); |
var m=date.getMinutes(); |
var s=date.getSeconds(); |
var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k; |
// Convert real date parts into formatted versions |
var value=new Object(); |
if (y.length < 4) {y=""+(y-0+1900);} |
value["y"]=""+y; |
value["yyyy"]=y; |
value["yy"]=y.substring(2,4); |
value["M"]=M; |
value["MM"]=LZ(M); |
value["MMM"]=MONTH_NAMES[M-1]; |
value["d"]=d; |
value["dd"]=LZ(d); |
value["E"]=DAY_NAMES[E+7]; |
value["EE"]=DAY_NAMES[E]; |
value["H"]=H; |
value["HH"]=LZ(H); |
if (H==0){value["h"]=12;} |
else if (H>12){value["h"]=H-12;} |
else {value["h"]=H;} |
value["hh"]=LZ(value["h"]); |
if (H>11){value["K"]=H-12;} else {value["K"]=H;} |
value["k"]=H+1; |
value["KK"]=LZ(value["K"]); |
value["kk"]=LZ(value["k"]); |
if (H > 11) { value["a"]="PM"; } |
else { value["a"]="AM"; } |
value["m"]=m; |
value["mm"]=LZ(m); |
value["s"]=s; |
value["ss"]=LZ(s); |
while (i_format < format.length) { |
c=format.charAt(i_format); |
token=""; |
while ((format.charAt(i_format)==c) && (i_format < format.length)) { |
token += format.charAt(i_format++); |
} |
if (value[token] != null) { result=result + value[token]; } |
else { result=result + token; } |
} |
return result; |
} |
// ------------------------------------------------------------------ |
// Utility functions for parsing in getDateFromFormat() |
// ------------------------------------------------------------------ |
function _isInteger(val) { |
var digits="1234567890"; |
for (var i=0; i < val.length; i++) { |
if (digits.indexOf(val.charAt(i))==-1) { return false; } |
} |
return true; |
} |
function _getInt(str,i,minlength,maxlength) { |
for (var x=maxlength; x>=minlength; x--) { |
var token=str.substring(i,i+x); |
if (token.length < minlength) { return null; } |
if (_isInteger(token)) { return token; } |
} |
return null; |
} |
// ------------------------------------------------------------------ |
// getDateFromFormat( date_string , format_string ) |
// |
// This function takes a date string and a format string. It matches |
// If the date string matches the format string, it returns the |
// getTime() of the date. If it does not match, it returns 0. |
// ------------------------------------------------------------------ |
function getDateFromFormat(val,format) { |
val=val+""; |
format=format+""; |
var i_val=0; |
var i_format=0; |
var c=""; |
var token=""; |
var token2=""; |
var x,y; |
var now=new Date(); |
var year=now.getYear(); |
var month=now.getMonth()+1; |
var date=1; |
var hh=now.getHours(); |
var mm=now.getMinutes(); |
var ss=now.getSeconds(); |
var ampm=""; |
while (i_format < format.length) { |
// Get next token from format string |
c=format.charAt(i_format); |
token=""; |
while ((format.charAt(i_format)==c) && (i_format < format.length)) { |
token += format.charAt(i_format++); |
} |
// Extract contents of value based on format token |
if (token=="yyyy" || token=="yy" || token=="y") { |
if (token=="yyyy") { x=4;y=4; } |
if (token=="yy") { x=2;y=2; } |
if (token=="y") { x=2;y=4; } |
year=_getInt(val,i_val,x,y); |
if (year==null) { return 0; } |
i_val += year.length; |
if (year.length==2) { |
if (year > 70) { year=1900+(year-0); } |
else { year=2000+(year-0); } |
} |
} |
else if (token=="MMM"){ |
month=0; |
for (var i=0; i<MONTH_NAMES.length; i++) { |
var month_name=MONTH_NAMES[i]; |
if (val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase()) { |
month=i+1; |
if (month>12) { month -= 12; } |
i_val += month_name.length; |
break; |
} |
} |
if ((month < 1)||(month>12)){return 0;} |
} |
else if (token=="EE"||token=="E"){ |
for (var i=0; i<DAY_NAMES.length; i++) { |
var day_name=DAY_NAMES[i]; |
if (val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase()) { |
i_val += day_name.length; |
break; |
} |
} |
} |
else if (token=="MM"||token=="M") { |
month=_getInt(val,i_val,token.length,2); |
if(month==null||(month<1)||(month>12)){return 0;} |
i_val+=month.length;} |
else if (token=="dd"||token=="d") { |
date=_getInt(val,i_val,token.length,2); |
if(date==null||(date<1)||(date>31)){return 0;} |
i_val+=date.length;} |
else if (token=="hh"||token=="h") { |
hh=_getInt(val,i_val,token.length,2); |
if(hh==null||(hh<1)||(hh>12)){return 0;} |
i_val+=hh.length;} |
else if (token=="HH"||token=="H") { |
hh=_getInt(val,i_val,token.length,2); |
if(hh==null||(hh<0)||(hh>23)){return 0;} |
i_val+=hh.length;} |
else if (token=="KK"||token=="K") { |
hh=_getInt(val,i_val,token.length,2); |
if(hh==null||(hh<0)||(hh>11)){return 0;} |
i_val+=hh.length;} |
else if (token=="kk"||token=="k") { |
hh=_getInt(val,i_val,token.length,2); |
if(hh==null||(hh<1)||(hh>24)){return 0;} |
i_val+=hh.length;hh--;} |
else if (token=="mm"||token=="m") { |
mm=_getInt(val,i_val,token.length,2); |
if(mm==null||(mm<0)||(mm>59)){return 0;} |
i_val+=mm.length;} |
else if (token=="ss"||token=="s") { |
ss=_getInt(val,i_val,token.length,2); |
if(ss==null||(ss<0)||(ss>59)){return 0;} |
i_val+=ss.length;} |
else if (token=="a") { |
if (val.substring(i_val,i_val+2).toLowerCase()=="am") {ampm="AM";} |
else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {ampm="PM";} |
else {return 0;} |
i_val+=2;} |
else { |
if (val.substring(i_val,i_val+token.length)!=token) {return 0;} |
else {i_val+=token.length;} |
} |
} |
// If there are any trailing characters left in the value, it doesn't match |
if (i_val != val.length) { return 0; } |
// Is date valid for month? |
if (month==2) { |
// Check for leap year |
if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year |
if (date > 29){ return false; } |
} |
else { if (date > 28) { return false; } } |
} |
if ((month==4)||(month==6)||(month==9)||(month==11)) { |
if (date > 30) { return false; } |
} |
// Correct hours value |
if (hh<12 && ampm=="PM") { hh=hh-0+12; } |
else if (hh>11 && ampm=="AM") { hh-=12; } |
var newdate=new Date(year,month-1,date,hh,mm,ss); |
return newdate.getTime(); |
} |
/tags/2.0/htdocs/lib/graypixel.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/logo.comp |
---|
0,0 → 1,21 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2002 Leader.IT S.r.l. <http://www.leader.it> |
# Via Trener, 10 |
# 38100 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<table align="center"> |
<tr> |
<td align="right"> |
<img src="/logo.svg" border="0" style="width:54px"> |
</td> |
<td align="left"> |
<div style="font-size:12pt">MasonSQL</div> |
<div style="font-size:10pt">Framework</div> |
</td> |
</tr> |
</table> |
/tags/2.0/htdocs/logo.svg |
---|
0,0 → 1,898 |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
<svg |
xmlns:dc="http://purl.org/dc/elements/1.1/" |
xmlns:cc="http://creativecommons.org/ns#" |
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
xmlns:svg="http://www.w3.org/2000/svg" |
xmlns="http://www.w3.org/2000/svg" |
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
version="1.1" |
viewBox="0 0 6000 5000" |
preserveAspectRatio="xMidYMid" |
id="svg2" |
inkscape:version="0.47 r22583" |
width="100%" |
height="100%" |
sodipodi:docname="logo_leader_corto_2011.svg" |
style="fill-rule:evenodd"> |
<metadata |
id="metadata764"> |
<rdf:RDF> |
<cc:Work |
rdf:about=""> |
<dc:format>image/svg+xml</dc:format> |
<dc:type |
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
<dc:title></dc:title> |
</cc:Work> |
</rdf:RDF> |
</metadata> |
<defs |
id="defs762"> |
<inkscape:perspective |
sodipodi:type="inkscape:persp3d" |
inkscape:vp_x="0 : 3000 : 1" |
inkscape:vp_y="0 : 1000 : 0" |
inkscape:vp_z="6000 : 3000 : 1" |
inkscape:persp3d-origin="3000 : 2000 : 1" |
id="perspective766" /> |
</defs> |
<sodipodi:namedview |
pagecolor="#ffffff" |
bordercolor="#666666" |
borderopacity="1" |
objecttolerance="10" |
gridtolerance="10" |
guidetolerance="10" |
inkscape:pageopacity="0" |
inkscape:pageshadow="2" |
inkscape:window-width="1280" |
inkscape:window-height="946" |
id="namedview760" |
showgrid="false" |
inkscape:zoom="0.11125147" |
inkscape:cx="3508.7467" |
inkscape:cy="2824.0781" |
inkscape:window-x="0" |
inkscape:window-y="24" |
inkscape:window-maximized="1" |
inkscape:current-layer="g14" /> |
<g |
visibility="visible" |
id="Predefinito" |
style="visibility:visible" |
transform="translate(0,-1000)"> |
<desc |
id="desc5">Master slide</desc> |
<g |
style="fill:none;stroke:none" |
id="g7"> |
<rect |
x="-14" |
y="-14" |
width="6030" |
height="6030" |
id="rect9" /> |
</g> |
</g> |
<g |
style="visibility:visible" |
id="g14" |
transform="translate(0,-1000)"> |
<desc |
id="desc16">Group</desc> |
<g |
id="g3945" |
transform="translate(8.9886455,910.88726)"> |
<g |
id="g18"> |
<desc |
id="desc20">Drawing</desc> |
<g |
id="g22"> |
<g |
style="fill:#ffc63d;stroke:none" |
id="g24"> |
<path |
d="m 4398,1623 0,-186 1069,0 0,372 -1069,0 0,-186 z" |
id="path26" /> |
</g> |
<g |
style="fill:none;stroke:none" |
id="g28"> |
<rect |
x="4384" |
y="1423" |
width="1098" |
height="401" |
id="rect30" /> |
</g> |
<g |
id="g32" /> |
</g> |
</g> |
<g |
id="g34"> |
<desc |
id="desc36">Drawing</desc> |
<g |
id="g38"> |
<g |
style="fill:#000000;stroke:none" |
id="g40"> |
<path |
d="m 3839,1808 -796,0 0,-372 1591,0 0,372 -795,0 z" |
id="path42" /> |
</g> |
<g |
style="fill:none;stroke:#000000" |
id="g44"> |
<path |
style="fill:none" |
d="m 3839,1808 -796,0 0,-372 1591,0 0,372 -795,0" |
id="path46" /> |
</g> |
<g |
id="g48" /> |
</g> |
</g> |
<g |
id="g50"> |
<desc |
id="desc52">Drawing</desc> |
<g |
id="g54"> |
<g |
style="fill:#ffc63d;stroke:none" |
id="g56"> |
<path |
d="m 2737,4527 -186,0 0,-1066 372,0 0,1066 -186,0 z" |
id="path58" /> |
</g> |
<g |
style="fill:none;stroke:none" |
id="g60"> |
<rect |
x="2537" |
y="3447" |
width="401" |
height="1095" |
id="rect62" /> |
</g> |
<g |
id="g64" /> |
</g> |
</g> |
<g |
id="g66"> |
<desc |
id="desc68">Drawing</desc> |
<g |
id="g70"> |
<g |
style="fill:#ffc63d;stroke:none" |
id="g72"> |
<path |
d="m 3849,4527 -186,0 0,-1066 372,0 0,1066 -186,0 z" |
id="path74" /> |
</g> |
<g |
style="fill:none;stroke:none" |
id="g76"> |
<rect |
x="3649" |
y="3447" |
width="401" |
height="1095" |
id="rect78" /> |
</g> |
<g |
id="g80" /> |
</g> |
</g> |
<g |
id="g82"> |
<desc |
id="desc84">Drawing</desc> |
<g |
id="g86"> |
<g |
style="fill:#ffc63d;stroke:none" |
id="g88"> |
<path |
d="m 2736,1546 -185,0 0,-1069 370,0 0,1069 -185,0 z" |
id="path90" /> |
</g> |
<g |
style="fill:none;stroke:none" |
id="g92"> |
<rect |
x="2537" |
y="463" |
width="399" |
height="1098" |
id="rect94" /> |
</g> |
<g |
id="g96" /> |
</g> |
</g> |
<g |
id="g98"> |
<desc |
id="desc100">Group</desc> |
<g |
id="g102"> |
<desc |
id="desc104">Drawing</desc> |
<g |
id="g106"> |
<g |
style="fill:#000000;stroke:none" |
id="g108"> |
<path |
d="m 1739,3029 c -222,0 -402,-180 -402,-402 0,-222 180,-402 402,-402 222,0 402,180 402,402 0,222 -180,402 -402,402 z" |
id="path110" /> |
<path |
d="m 1739,3034 c -56,0 -110,-11 -158,-32 l 2,-5 1,-4 c 48,20 100,31 155,31 l 0,5 0,5 z" |
id="path112" /> |
<path |
d="m 1581,3002 c -49,-21 -93,-50 -130,-87 l 4,-4 3,-3 c 36,36 79,65 126,85 l -1,4 -2,5 z" |
id="path114" /> |
<path |
d="m 1451,2915 c -37,-37 -66,-81 -87,-130 l 5,-2 4,-1 c 20,47 49,90 85,126 l -3,3 -4,4 z" |
id="path116" /> |
<path |
d="m 1364,2785 c -21,-48 -32,-102 -32,-158 l 5,0 5,0 c 0,55 11,107 31,155 l -4,1 -5,2 z" |
id="path118" /> |
<path |
d="m 1332,2627 c 0,-56 11,-110 32,-158 l 5,2 4,1 c -20,48 -31,100 -31,155 l -5,0 -5,0 z" |
id="path120" /> |
<path |
d="m 1364,2469 c 21,-49 50,-93 87,-130 l 4,4 3,3 c -36,36 -65,79 -85,126 l -4,-1 -5,-2 z" |
id="path122" /> |
<path |
d="m 1451,2339 c 37,-37 81,-66 130,-87 l 2,5 1,4 c -47,20 -90,49 -126,85 l -3,-3 -4,-4 z" |
id="path124" /> |
<path |
d="m 1581,2252 c 48,-21 102,-32 158,-32 l 0,5 0,5 c -55,0 -107,11 -155,31 l -1,-4 -2,-5 z" |
id="path126" /> |
<path |
d="m 1739,2220 c 56,0 110,11 158,32 l -2,5 -1,4 c -48,-20 -100,-31 -155,-31 l 0,-5 0,-5 z" |
id="path128" /> |
<path |
d="m 1897,2252 c 49,21 93,50 130,87 l -4,4 -3,3 c -36,-36 -79,-65 -126,-85 l 1,-4 2,-5 z" |
id="path130" /> |
<path |
d="m 2027,2339 c 37,37 66,81 87,130 l -5,2 -4,1 c -20,-47 -49,-90 -85,-126 l 3,-3 4,-4 z" |
id="path132" /> |
<path |
d="m 2114,2469 c 21,48 32,102 32,158 l -5,0 -5,0 c 0,-55 -11,-107 -31,-155 l 4,-1 5,-2 z" |
id="path134" /> |
<path |
d="m 2146,2627 c 0,56 -11,110 -32,158 l -5,-2 -4,-1 c 20,-48 31,-100 31,-155 l 5,0 5,0 z" |
id="path136" /> |
<path |
d="m 2114,2785 c -21,49 -50,93 -87,130 l -4,-4 -3,-3 c 36,-36 65,-79 85,-126 l 4,1 5,2 z" |
id="path138" /> |
<path |
d="m 2027,2915 c -37,37 -81,66 -130,87 l -2,-5 -1,-4 c 47,-20 90,-49 126,-85 l 3,3 4,4 z" |
id="path140" /> |
<path |
d="m 1897,3002 c -48,21 -102,32 -158,32 l 0,-5 0,-5 c 55,0 107,-11 155,-31 l 1,4 2,5 z" |
id="path142" /> |
</g> |
<g |
id="g144" /> |
</g> |
</g> |
<g |
id="g146"> |
<desc |
id="desc148">Drawing</desc> |
<g |
id="g150"> |
<g |
style="fill:#ff0000;stroke:none" |
id="g152"> |
<path |
d="m 1741,2867 c -136,0 -246,-107 -246,-240 0,-133 110,-240 246,-240 135,0 245,107 245,240 0,133 -110,240 -245,240 z" |
id="path154" /> |
</g> |
<g |
style="fill:#000000;stroke:none" |
id="g156"> |
<path |
d="m 1741,2872 c -35,0 -68,-7 -98,-19 l 2,-5 2,-4 c 29,11 60,18 94,18 l 0,5 0,5 z" |
id="path158" /> |
<path |
d="m 1643,2853 c -30,-13 -57,-31 -80,-53 l 4,-3 3,-4 c 22,21 48,39 77,51 l -2,4 -2,5 z" |
id="path160" /> |
<path |
d="m 1563,2800 c -22,-22 -41,-48 -53,-78 l 4,-2 5,-2 c 12,29 30,54 51,75 l -3,4 -4,3 z" |
id="path162" /> |
<path |
d="m 1510,2722 c -13,-29 -20,-61 -20,-95 l 5,0 5,0 c 0,32 7,63 19,91 l -5,2 -4,2 z" |
id="path164" /> |
<path |
d="m 1490,2627 c 0,-34 7,-66 20,-95 l 4,2 5,2 c -12,28 -19,59 -19,91 l -5,0 -5,0 z" |
id="path166" /> |
<path |
d="m 1510,2532 c 12,-30 31,-56 53,-78 l 4,3 3,4 c -21,21 -39,46 -51,75 l -5,-2 -4,-2 z" |
id="path168" /> |
<path |
d="m 1563,2454 c 23,-22 50,-40 80,-53 l 2,5 2,4 c -29,12 -55,30 -77,51 l -3,-4 -4,-3 z" |
id="path170" /> |
<path |
d="m 1643,2401 c 30,-12 63,-19 98,-19 l 0,5 0,5 c -34,0 -65,7 -94,18 l -2,-4 -2,-5 z" |
id="path172" /> |
<path |
d="m 1741,2382 c 34,0 67,7 97,19 l -2,5 -2,4 c -29,-11 -60,-18 -93,-18 l 0,-5 0,-5 z" |
id="path174" /> |
<path |
d="m 1838,2401 c 30,13 57,31 80,53 l -4,3 -3,4 c -22,-21 -48,-39 -77,-51 l 2,-4 2,-5 z" |
id="path176" /> |
<path |
d="m 1918,2454 c 22,22 41,48 53,78 l -4,2 -5,2 c -12,-29 -30,-54 -51,-75 l 3,-4 4,-3 z" |
id="path178" /> |
<path |
d="m 1971,2532 c 13,29 20,61 20,95 l -5,0 -5,0 c 0,-32 -7,-63 -19,-91 l 5,-2 4,-2 z" |
id="path180" /> |
<path |
d="m 1991,2627 c 0,34 -7,66 -20,95 l -4,-2 -5,-2 c 12,-28 19,-59 19,-91 l 5,0 5,0 z" |
id="path182" /> |
<path |
d="m 1971,2722 c -12,30 -31,56 -53,78 l -4,-3 -3,-4 c 21,-21 39,-46 51,-75 l 5,2 4,2 z" |
id="path184" /> |
<path |
d="m 1918,2800 c -23,22 -50,40 -80,53 l -2,-5 -2,-4 c 29,-12 55,-30 77,-51 l 3,4 4,3 z" |
id="path186" /> |
<path |
d="m 1838,2853 c -30,12 -63,19 -97,19 l 0,-5 0,-5 c 33,0 64,-7 93,-18 l 2,4 2,5 z" |
id="path188" /> |
</g> |
<g |
id="g190" /> |
</g> |
</g> |
</g> |
<g |
id="g192"> |
<desc |
id="desc194">Drawing</desc> |
<g |
id="g196"> |
<g |
style="fill:#000000;stroke:none" |
id="g198"> |
<path |
d="m 549,1444 c 153,0 305,0 459,0 -80,194 -335,529 -335,1190 0,476 92,679 158,827 2341,0 -1260,0 1081,0 54,90 191,279 274,370 -2523,0 887,1 -1637,1 C 417,3568 250,3357 250,2634 250,1920 426,1700 549,1444 z" |
id="path200" /> |
<path |
d="m 526,1433 c 5,-8 13,-14 23,-14 l 0,25 -23,-11 z" |
id="path202" /> |
<path |
d="m 549,1419 459,0 0,25 0,25 -459,0 0,-25 0,-25 z" |
id="path204" /> |
<path |
d="m 1008,1419 c 14,0 25,11 25,25 0,3 -1,7 -2,10 l -23,-10 0,-25 z" |
id="path206" /> |
<path |
d="m 1031,1454 c -20,49 -51,106 -87,176 l -22,-11 -22,-12 c 34,-68 65,-125 85,-173 l 23,10 23,10 z" |
id="path208" /> |
<path |
d="m 944,1630 c -35,69 -74,148 -110,243 l -23,-9 -24,-9 c 37,-96 77,-178 113,-248 l 22,12 22,11 z" |
id="path210" /> |
<path |
d="m 834,1873 c -37,94 -71,203 -95,328 l -25,-5 -24,-4 c 25,-129 60,-241 97,-337 l 24,9 23,9 z" |
id="path212" /> |
<path |
d="m 739,2201 c -25,126 -41,270 -41,433 l -25,0 -25,0 c 0,-167 16,-314 42,-442 l 24,4 25,5 z" |
id="path214" /> |
<path |
d="m 698,2634 c 0,118 6,219 15,307 l -25,2 -24,3 c -10,-89 -16,-192 -16,-312 l 25,0 25,0 z" |
id="path216" /> |
<path |
d="m 713,2941 c 10,87 23,160 39,224 l -25,6 -24,5 c -16,-65 -30,-141 -39,-230 l 24,-3 25,-2 z" |
id="path218" /> |
<path |
d="m 752,3165 c 15,63 32,116 50,162 l -24,9 -23,9 c -18,-48 -36,-103 -52,-169 l 24,-5 25,-6 z" |
id="path220" /> |
<path |
d="m 802,3327 c 18,47 36,87 52,124 l -23,10 -23,10 c -17,-37 -35,-78 -53,-126 l 23,-9 24,-9 z" |
id="path222" /> |
<path |
d="m 831,3486 c -10,0 -19,-6 -23,-15 l 23,-10 0,25 z" |
id="path224" /> |
<path |
d="m 831,3436 831,0 0,25 0,25 -831,0 0,-25 0,-25 z" |
id="path226" /> |
<path |
d="m 1662,3436 c 13,0 25,11 25,25 0,14 -12,25 -25,25 l 0,-25 0,-25 z" |
id="path228" /> |
<path |
d="m 1662,3486 -581,0 0,-25 0,-25 581,0 0,25 0,25 z" |
id="path230" /> |
<path |
d="m 1081,3486 c -13,0 -25,-11 -25,-25 0,-14 12,-25 25,-25 l 0,25 0,25 z" |
id="path232" /> |
<path |
d="m 1081,3436 831,0 0,25 0,25 -831,0 0,-25 0,-25 z" |
id="path234" /> |
<path |
d="m 1912,3436 c 9,0 17,5 21,12 l -21,13 0,-25 z" |
id="path236" /> |
<path |
d="m 1933,3448 c 54,89 189,276 271,366 l -18,17 -18,17 c -84,-92 -223,-283 -277,-374 l 21,-13 21,-13 z" |
id="path238" /> |
<path |
d="m 2204,3814 c 5,5 7,11 7,17 0,14 -11,25 -25,25 l 0,-25 18,-17 z" |
id="path240" /> |
<path |
d="m 2186,3856 c -97,0 -185,0 -265,0 l 0,-25 0,-25 c 80,0 168,0 265,0 l 0,25 0,25 z" |
id="path242" /> |
<path |
d="m 1921,3856 c -80,0 -152,0 -216,0 l 0,-25 0,-25 c 64,0 136,0 216,0 l 0,25 0,25 z" |
id="path244" /> |
<path |
d="m 1705,3856 c -65,0 -122,0 -172,0 l 0,-25 0,-25 c 50,0 107,0 172,0 l 0,25 0,25 z" |
id="path246" /> |
<path |
d="m 1533,3856 c -51,0 -94,0 -132,0 l 0,-25 0,-25 c 38,0 81,0 132,0 l 0,25 0,25 z" |
id="path248" /> |
<path |
d="m 1401,3856 c -38,0 -69,0 -95,0 l 0,-25 0,-25 c 26,0 57,0 95,0 l 0,25 0,25 z" |
id="path250" /> |
<path |
d="m 1306,3856 c -14,0 -25,0 -36,0 l 0,-25 0,-25 c 11,0 22,0 36,0 l 0,25 0,25 z" |
id="path252" /> |
<path |
d="m 1270,3856 c -10,0 -20,0 -28,0 l 0,-25 0,-25 c 8,0 18,0 28,0 l 0,25 0,25 z" |
id="path254" /> |
<path |
d="m 1242,3856 c -8,0 -15,0 -20,0 l -1,-25 0,-25 c 6,0 13,0 21,0 l 0,25 0,25 z" |
id="path256" /> |
<path |
d="m 1222,3856 c -3,0 -6,0 -8,0 l 0,-25 0,-25 c 2,0 5,0 7,0 l 0,25 1,25 z" |
id="path258" /> |
<path |
d="m 1214,3856 c -3,0 -5,0 -7,0 l 0,-25 0,-25 c 2,0 4,0 7,0 l 0,25 0,25 z" |
id="path260" /> |
<path |
d="m 1207,3856 c -2,0 -3,0 -4,0 l -1,-25 0,-25 c 2,0 3,0 5,0 l 0,25 0,25 z" |
id="path262" /> |
<path |
d="m 1203,3856 c -1,0 -2,0 -2,0 l 0,-25 0,-25 c 0,0 1,0 1,0 l 0,25 1,25 z" |
id="path264" /> |
<path |
d="m 1201,3856 c -1,0 -1,0 -2,0 l 0,-25 0,-25 c 0,0 1,0 2,0 l 0,25 0,25 z" |
id="path266" /> |
<path |
d="m 1199,3856 c 0,0 -1,0 -1,0 l 0,-25 0,-25 c 0,0 1,0 1,0 l 0,25 0,25 z" |
id="path268" /> |
<path |
d="m 1198,3856 c 0,0 0,0 -1,0 l 0,-25 0,-25 c 0,0 0,0 1,0 l 0,25 0,25 z" |
id="path270" /> |
<path |
d="m 1197,3856 c 0,0 0,0 0,0 l 0,-25 -1,-25 c 0,0 1,0 1,0 l 0,25 0,25 z" |
id="path272" /> |
<path |
d="m 1197,3831 -1,0 -25,0 c 0,0 2,-24 25,-25 l 1,25 0,0 z" |
id="path274" /> |
<path |
d="m 1197,3831 0,0 -1,25 c -23,0 -25,-24 -25,-25 l 25,0 1,0 z" |
id="path276" /> |
<path |
d="m 1197,3806 c 0,0 0,0 1,0 l -1,25 0,25 c 0,0 0,0 -1,0 l 1,-25 0,-25 z" |
id="path278" /> |
<path |
d="m 1198,3806 c 0,0 0,0 1,0 l 0,25 0,25 c -1,0 -1,0 -2,0 l 0,-25 1,-25 z" |
id="path280" /> |
<path |
d="m 1199,3806 c 0,0 1,0 1,0 l 0,25 0,25 c 0,0 -1,0 -1,0 l 0,-25 0,-25 z" |
id="path282" /> |
<path |
d="m 1200,3806 c 2,0 3,0 5,0 l 0,25 0,25 c -2,0 -4,0 -5,0 l 0,-25 0,-25 z" |
id="path284" /> |
<path |
d="m 1205,3806 c 2,0 4,0 6,0 l 0,25 0,25 c -2,0 -4,0 -6,0 l 0,-25 0,-25 z" |
id="path286" /> |
<path |
d="m 1211,3806 c 5,0 11,0 17,0 l 0,25 0,25 c -6,0 -12,0 -17,0 l 0,-25 0,-25 z" |
id="path288" /> |
<path |
d="m 1228,3806 c 7,0 14,0 22,0 l 0,25 0,25 c -8,0 -15,0 -22,0 l 0,-25 0,-25 z" |
id="path290" /> |
<path |
d="m 1250,3806 c 32,0 75,0 118,0 l 0,25 0,25 c -43,0 -86,0 -118,0 l 0,-25 0,-25 z" |
id="path292" /> |
<path |
d="m 1368,3806 c 43,1 86,1 118,1 l 0,25 0,25 c -33,0 -75,0 -118,-1 l 0,-25 0,-25 z" |
id="path294" /> |
<path |
d="m 1486,3807 c 8,0 15,0 22,0 l 0,25 -1,25 c -6,0 -13,0 -21,0 l 0,-25 0,-25 z" |
id="path296" /> |
<path |
d="m 1508,3807 c 6,0 12,0 16,0 l 0,25 0,25 c -4,0 -10,0 -17,0 l 1,-25 0,-25 z" |
id="path298" /> |
<path |
d="m 1524,3807 c 3,0 5,0 7,0 l 0,25 0,25 c -2,0 -4,0 -7,0 l 0,-25 0,-25 z" |
id="path300" /> |
<path |
d="m 1531,3807 c 2,0 3,0 4,0 l 0,25 0,25 c -1,0 -3,0 -4,0 l 0,-25 0,-25 z" |
id="path302" /> |
<path |
d="m 1535,3807 c 1,0 2,0 2,0 l 0,25 0,25 c -1,0 -1,0 -2,0 l 0,-25 0,-25 z" |
id="path304" /> |
<path |
d="m 1537,3807 c 1,0 1,0 1,0 l 0,25 0,25 c 0,0 -1,0 -1,0 l 0,-25 0,-25 z" |
id="path306" /> |
<path |
d="m 1538,3807 c 1,0 1,0 1,0 l 0,25 0,25 c -1,0 -1,0 -1,0 l 0,-25 0,-25 z" |
id="path308" /> |
<path |
d="m 1539,3807 c 24,0 25,24 25,25 l -25,0 0,0 0,0 0,-25 z" |
id="path310" /> |
<path |
d="m 1564,3832 c 0,0 -1,24 -25,25 l 0,-25 0,0 0,0 25,0 z" |
id="path312" /> |
<path |
d="m 1539,3857 c 0,0 0,0 0,0 l 0,-25 -1,-25 c 0,0 0,0 1,0 l 0,25 0,25 z" |
id="path314" /> |
<path |
d="m 1539,3857 c 0,0 -1,0 -1,0 l 0,-25 0,-25 c 0,0 0,0 0,0 l 1,25 0,25 z" |
id="path316" /> |
<path |
d="m 1538,3857 c 0,0 -1,0 -1,0 l 0,-25 -1,-25 c 1,0 1,0 2,0 l 0,25 0,25 z" |
id="path318" /> |
<path |
d="m 1537,3857 c -1,0 -1,0 -2,0 l 0,-25 0,-25 c 0,0 1,0 1,0 l 1,25 0,25 z" |
id="path320" /> |
<path |
d="m 1535,3857 c 0,0 -1,0 -2,0 l 0,-25 0,-25 c 1,0 1,0 2,0 l 0,25 0,25 z" |
id="path322" /> |
<path |
d="m 1533,3857 c -1,0 -3,0 -5,0 l 0,-25 0,-25 c 2,0 4,0 5,0 l 0,25 0,25 z" |
id="path324" /> |
<path |
d="m 1528,3857 c -1,0 -4,0 -6,0 l 0,-25 0,-25 c 2,0 4,0 6,0 l 0,25 0,25 z" |
id="path326" /> |
<path |
d="m 1522,3857 c -2,0 -5,0 -8,0 l 0,-25 0,-25 c 3,0 6,0 8,0 l 0,25 0,25 z" |
id="path328" /> |
<path |
d="m 1514,3857 c -6,0 -13,0 -21,0 l 0,-25 0,-25 c 8,0 15,0 21,0 l 0,25 0,25 z" |
id="path330" /> |
<path |
d="m 1493,3857 c -8,0 -17,0 -28,0 l 0,-25 0,-25 c 11,0 20,0 28,0 l 0,25 0,25 z" |
id="path332" /> |
<path |
d="m 1465,3857 c -10,0 -22,0 -35,0 l 0,-25 0,-25 c 13,0 25,0 35,0 l 0,25 0,25 z" |
id="path334" /> |
<path |
d="m 1430,3857 c -26,0 -58,0 -96,0 l 0,-25 0,-25 c 38,0 70,0 96,0 l 0,25 0,25 z" |
id="path336" /> |
<path |
d="m 1334,3857 c -37,0 -81,0 -131,0 l 0,-25 0,-25 c 50,0 94,0 131,0 l 0,25 0,25 z" |
id="path338" /> |
<path |
d="m 1203,3857 c -51,0 -108,0 -173,0 l 0,-25 0,-25 c 65,0 122,0 173,0 l 0,25 0,25 z" |
id="path340" /> |
<path |
d="m 1030,3857 c -64,0 -136,0 -216,0 l 0,-25 0,-25 c 80,0 152,0 216,0 l 0,25 0,25 z" |
id="path342" /> |
<path |
d="m 814,3857 c -80,0 -168,0 -265,0 l 0,-25 0,-25 c 97,0 185,0 265,0 l 0,25 0,25 z" |
id="path344" /> |
<path |
d="m 549,3857 c -10,0 -18,-6 -22,-14 l 22,-11 0,25 z" |
id="path346" /> |
<path |
d="M 527,3843 C 460,3710 385,3590 326,3413 l 24,-8 24,-8 c 58,175 132,293 197,424 l -22,11 -22,11 z" |
id="path348" /> |
<path |
d="m 326,3413 c -29,-89 -55,-193 -73,-320 l 25,-4 25,-3 c 17,123 42,224 71,311 l -24,8 -24,8 z" |
id="path350" /> |
<path |
d="m 253,3093 c -17,-127 -28,-277 -28,-459 l 25,0 25,0 c 0,179 10,327 28,452 l -25,3 -25,4 z" |
id="path352" /> |
<path |
d="m 225,2634 c 0,-180 11,-329 30,-455 l 24,4 25,3 c -18,125 -29,271 -29,448 l -25,0 -25,0 z" |
id="path354" /> |
<path |
d="m 255,2179 c 18,-127 45,-230 75,-320 l 23,8 24,8 c -29,87 -55,188 -73,311 l -25,-3 -24,-4 z" |
id="path356" /> |
<path |
d="m 330,1859 c 59,-177 135,-297 196,-426 l 23,11 23,11 c -62,127 -136,245 -195,420 l -24,-8 -23,-8 z" |
id="path358" /> |
</g> |
<g |
id="g360" /> |
</g> |
</g> |
<g |
id="g362"> |
<desc |
id="desc364">Drawing</desc> |
<g |
id="g366"> |
<g |
style="fill:#666699;stroke:none" |
id="g368"> |
<path |
d="m 3432,192 c 1380,0 2421,1125 2421,2452 0,1488 -1275,2375 -2421,2375 -1036,0 -1852,-715 -2087,-1198 273,0 550,0 823,0 221,188 577,541 1264,541 804,0 1759,-615 1759,-1739 0,-856 -693,-1751 -1759,-1751 -596,0 -1108,303 -1457,806 -596,3 -328,0 -636,0 0,-20 -2,-237 0,-241 C 1536,979 2319,192 3432,192 z" |
id="path370" /> |
</g> |
<g |
style="fill:#000000;stroke:none" |
id="g372"> |
<path |
d="m 3432,167 c 348,0 676,71 970,199 l -10,23 -10,22 C 4094,287 3773,217 3432,217 l 0,-25 0,-25 z" |
id="path374" /> |
<path |
d="m 4402,366 c 295,127 557,311 776,537 l -18,17 -18,18 C 4928,717 4671,536 4382,411 l 10,-22 10,-23 z" |
id="path376" /> |
<path |
d="m 5178,903 c 218,226 393,494 514,789 l -23,9 -23,9 C 5528,1421 5356,1159 5142,938 l 18,-18 18,-17 z" |
id="path378" /> |
<path |
d="m 5692,1692 c 120,295 186,617 186,952 l -25,0 -25,0 c 0,-328 -65,-644 -182,-934 l 23,-9 23,-9 z" |
id="path380" /> |
<path |
d="m 5878,2644 c 0,188 -20,366 -58,535 l -24,-6 -25,-5 c 37,-165 57,-340 57,-524 l 25,0 25,0 z" |
id="path382" /> |
<path |
d="m 5820,3179 c -37,168 -92,327 -162,474 l -22,-10 -23,-11 c 68,-144 122,-299 158,-464 l 25,5 24,6 z" |
id="path384" /> |
<path |
d="m 5658,3653 c -139,296 -336,549 -569,755 l -17,-18 -16,-19 c 228,-202 421,-450 557,-739 l 23,11 22,10 z" |
id="path386" /> |
<path |
d="m 5089,4408 c -234,206 -503,365 -786,473 l -9,-24 -9,-23 c 278,-106 542,-261 771,-463 l 16,19 17,18 z" |
id="path388" /> |
<path |
d="m 4303,4881 c -284,107 -582,163 -871,163 l 0,-25 0,-25 c 283,0 575,-55 853,-160 l 9,23 9,24 z" |
id="path390" /> |
<path |
d="m 3432,5044 c -262,0 -510,-45 -738,-121 l 8,-23 8,-24 c 223,74 466,118 722,118 l 0,25 0,25 z" |
id="path392" /> |
<path |
d="m 2694,4923 c -228,-75 -437,-180 -620,-301 l 14,-21 14,-21 c 179,119 384,222 608,296 l -8,24 -8,23 z" |
id="path394" /> |
<path |
d="m 2074,4622 c -183,-121 -341,-257 -468,-393 l 18,-17 19,-17 c 124,134 279,267 459,385 l -14,21 -14,21 z" |
id="path396" /> |
<path |
d="m 1606,4229 c -128,-137 -224,-274 -284,-397 l 23,-11 22,-11 c 58,119 152,252 276,385 l -19,17 -18,17 z" |
id="path398" /> |
<path |
d="m 1322,3832 c -1,-3 -2,-7 -2,-11 0,-14 11,-25 25,-25 l 0,25 -23,11 z" |
id="path400" /> |
<path |
d="m 1345,3796 823,0 0,25 0,25 -823,0 0,-25 0,-25 z" |
id="path402" /> |
<path |
d="m 2168,3796 c 6,0 12,2 16,6 l -16,19 0,-25 z" |
id="path404" /> |
<path |
d="m 2184,3802 c 55,47 119,104 194,163 l -16,20 -16,19 c -75,-59 -139,-117 -194,-164 l 16,-19 16,-19 z" |
id="path406" /> |
<path |
d="m 2378,3965 c 74,59 159,120 259,175 l -12,22 -12,22 c -103,-57 -190,-119 -267,-180 l 16,-19 16,-20 z" |
id="path408" /> |
<path |
d="m 2637,4140 c 100,55 214,104 345,140 l -6,24 -7,24 c -135,-37 -253,-87 -356,-144 l 12,-22 12,-22 z" |
id="path410" /> |
<path |
d="m 2982,4280 c 132,35 281,57 450,57 l 0,25 0,25 c -174,0 -328,-22 -463,-59 l 7,-24 6,-24 z" |
id="path412" /> |
<path |
d="m 3432,4337 c 198,0 405,-38 605,-112 l 9,23 9,24 c -206,76 -419,115 -623,115 l 0,-25 0,-25 z" |
id="path414" /> |
<path |
d="m 4037,4225 c 200,-74 392,-185 560,-330 l 16,19 16,19 c -172,149 -369,263 -574,339 l -9,-24 -9,-23 z" |
id="path416" /> |
<path |
d="m 4597,3895 c 167,-145 309,-324 410,-537 l 22,11 23,11 c -104,219 -251,404 -423,553 l -16,-19 -16,-19 z" |
id="path418" /> |
<path |
d="m 5007,3358 c 50,-106 90,-220 117,-343 l 24,5 25,6 c -28,126 -69,244 -121,354 l -23,-11 -22,-11 z" |
id="path420" /> |
<path |
d="m 5124,3015 c 27,-123 42,-253 42,-392 l 25,0 25,0 c 0,142 -15,277 -43,403 l -25,-6 -24,-5 z" |
id="path422" /> |
<path |
d="m 5166,2623 c 0,-211 -43,-424 -123,-625 l 23,-10 23,-9 c 83,207 127,427 127,644 l -25,0 -25,0 z" |
id="path424" /> |
<path |
d="m 5043,1998 c -81,-202 -199,-391 -350,-555 l 18,-16 18,-17 c 156,167 277,362 360,569 l -23,9 -23,10 z" |
id="path426" /> |
<path |
d="m 4693,1443 c -151,-162 -335,-299 -547,-395 l 10,-23 11,-23 c 218,99 407,240 562,408 l -18,17 -18,16 z" |
id="path428" /> |
<path |
d="M 4146,1048 C 3934,952 3695,897 3432,897 l 0,-25 0,-25 c 270,0 517,57 735,155 l -11,23 -10,23 z" |
id="path430" /> |
<path |
d="m 3432,897 c -147,0 -289,19 -424,54 l -6,-24 -7,-24 c 140,-37 286,-56 437,-56 l 0,25 0,25 z" |
id="path432" /> |
<path |
d="m 3008,951 c -135,36 -264,89 -385,157 l -12,-22 -13,-21 c 125,-71 258,-125 397,-162 l 7,24 6,24 z" |
id="path434" /> |
<path |
d="m 2623,1108 c -121,69 -235,152 -340,250 l -17,-18 -17,-18 c 108,-101 225,-187 349,-257 l 13,21 12,22 z" |
id="path436" /> |
<path |
d="m 2283,1358 c -105,98 -201,210 -288,334 l -20,-14 -21,-14 c 89,-128 187,-242 295,-342 l 17,18 17,18 z" |
id="path438" /> |
<path |
d="m 1995,1692 c -4,7 -12,11 -20,11 l 0,-25 20,14 z" |
id="path440" /> |
<path |
d="m 1975,1703 c -50,0 -93,0 -132,1 l 0,-25 0,-25 c 38,-1 82,-1 132,-1 l 0,25 0,25 z" |
id="path442" /> |
<path |
d="m 1843,1704 c -38,0 -72,0 -101,0 l 0,-25 0,-25 c 29,0 62,0 101,0 l 0,25 0,25 z" |
id="path444" /> |
<path |
d="m 1742,1704 c -29,0 -53,0 -75,0 l 0,-25 0,-25 c 21,0 46,0 75,0 l 0,25 0,25 z" |
id="path446" /> |
<path |
d="m 1667,1704 c -21,0 -38,0 -53,0 l 0,-25 0,-25 c 15,0 32,0 53,0 l 0,25 0,25 z" |
id="path448" /> |
<path |
d="m 1614,1704 c -15,0 -28,0 -38,0 l 0,-25 0,-25 c 10,0 23,0 38,0 l 0,25 0,25 z" |
id="path450" /> |
<path |
d="m 1576,1704 c -11,0 -20,0 -27,0 l 0,-25 0,-25 c 8,0 16,0 27,0 l 0,25 0,25 z" |
id="path452" /> |
<path |
d="m 1549,1704 c -16,0 -27,0 -41,0 l 0,-25 1,-25 c 13,0 25,0 40,0 l 0,25 0,25 z" |
id="path454" /> |
<path |
d="m 1508,1704 c -7,0 -15,-1 -24,-1 l 0,-25 1,-25 c 9,1 16,1 24,1 l -1,25 0,25 z" |
id="path456" /> |
<path |
d="m 1484,1703 c -9,0 -20,0 -33,0 l 1,-25 0,-25 c 13,0 23,0 33,0 l -1,25 0,25 z" |
id="path458" /> |
<path |
d="m 1451,1703 c -13,0 -28,0 -46,0 l 0,-25 0,-25 c 18,0 34,0 47,0 l 0,25 -1,25 z" |
id="path460" /> |
<path |
d="m 1405,1703 c -19,0 -40,0 -66,0 l 0,-25 0,-25 c 26,0 47,0 66,0 l 0,25 0,25 z" |
id="path462" /> |
<path |
d="m 1339,1703 c -14,0 -25,-11 -25,-25 l 25,0 0,25 z" |
id="path464" /> |
<path |
d="m 1314,1678 c 0,-13 -1,-114 -1,-181 l 25,0 25,0 c 0,67 1,168 1,181 l -25,0 -25,0 z" |
id="path466" /> |
<path |
d="m 1313,1497 c 0,-17 0,-32 0,-42 l 25,0 25,0 c 0,11 0,25 0,42 l -25,0 -25,0 z" |
id="path468" /> |
<path |
d="m 1313,1455 c 0,-3 0,-6 0,-8 l 25,1 25,0 c 0,2 0,5 0,7 l -25,0 -25,0 z" |
id="path470" /> |
<path |
d="m 1313,1447 c 0,-2 0,-4 0,-6 l 25,1 25,1 c 0,2 0,3 0,5 l -25,0 -25,-1 z" |
id="path472" /> |
<path |
d="m 1313,1441 c 1,-1 1,-1 1,-2 l 25,1 25,1 c -1,1 -1,2 -1,2 l -25,-1 -25,-1 z" |
id="path474" /> |
<path |
d="m 1314,1439 c 0,-1 0,-2 0,-2 l 25,2 25,2 c 0,0 0,0 0,0 l -25,-1 -25,-1 z" |
id="path476" /> |
<path |
d="m 1314,1437 c 0,-1 0,-1 0,-2 l 25,3 24,3 -24,-2 -25,-2 z" |
id="path478" /> |
<path |
d="m 1314,1435 c 0,0 0,-1 0,-1 l 25,4 11,1 -11,-1 -25,-3 z" |
id="path480" /> |
<path |
d="m 1314,1434 c 0,-1 0,-2 0,-2 l 25,5 4,1 -4,0 -25,-4 z" |
id="path482" /> |
<path |
d="m 1314,1432 c 1,-1 1,-2 1,-2 l 24,7 1,1 -1,-1 -25,-5 z" |
id="path484" /> |
<path |
d="m 1315,1430 c 0,-2 1,-3 2,-4 l 22,11 0,0 0,0 -24,-7 z" |
id="path486" /> |
<path |
d="m 1362,1447 c 0,0 -1,1 -1,1 l -22,-11 23,10 z" |
id="path488" /> |
<path |
d="m 1316,1427 c 50,-116 137,-254 258,-394 l 19,16 18,17 c -116,135 -201,268 -249,381 l -23,-10 -23,-10 z" |
id="path490" /> |
<path |
d="m 1574,1033 c 119,-140 272,-282 453,-411 l 15,21 14,20 c -178,126 -327,266 -445,403 l -18,-17 -19,-16 z" |
id="path492" /> |
<path |
d="m 2027,622 c 182,-128 392,-242 628,-323 l 8,23 8,24 c -230,80 -437,191 -615,317 l -14,-20 -15,-21 z" |
id="path494" /> |
<path |
d="m 2655,299 c 235,-82 496,-132 777,-132 l 0,25 0,25 c -275,0 -530,49 -761,129 l -8,-24 -8,-23 z" |
id="path496" /> |
</g> |
<g |
id="g498" /> |
</g> |
</g> |
<g |
id="g712"> |
<desc |
id="desc714">Drawing</desc> |
<g |
id="g716"> |
<g |
style="fill:#000000;stroke:none" |
id="g718"> |
<path |
d="m 4035,2800 0,1033 -372,0 0,-2066 372,0 0,1033 z" |
id="path720" /> |
</g> |
<g |
style="fill:none;stroke:#000000" |
id="g722"> |
<path |
style="fill:none" |
d="m 4035,2800 0,1033 -372,0 0,-2066 372,0 0,1033" |
id="path724" /> |
</g> |
<g |
id="g726" /> |
</g> |
</g> |
<g |
id="g728"> |
<desc |
id="desc730">Drawing</desc> |
<g |
id="g732"> |
<g |
style="fill:#000000;stroke:none" |
id="g734"> |
<path |
d="m 2921,1624 0,188 -372,0 0,-376 372,0 0,188 z" |
id="path736" /> |
</g> |
<g |
style="fill:none;stroke:#000000" |
id="g738"> |
<path |
style="fill:none" |
d="m 2921,1624 0,188 -372,0 0,-376 372,0 0,188" |
id="path740" /> |
</g> |
<g |
id="g742" /> |
</g> |
</g> |
<g |
id="g744"> |
<desc |
id="desc746">Drawing</desc> |
<g |
id="g748"> |
<g |
style="fill:#000000;stroke:none" |
id="g750"> |
<path |
d="m 2921,2881 0,952 -372,0 0,-1903 372,0 0,951 z" |
id="path752" /> |
</g> |
<g |
style="fill:none;stroke:#000000" |
id="g754"> |
<path |
style="fill:none" |
d="m 2921,2881 0,952 -372,0 0,-1903 372,0 0,951" |
id="path756" /> |
</g> |
<g |
id="g758" /> |
</g> |
</g> |
</g> |
</g> |
</svg> |
/tags/2.0/htdocs/init.comp |
---|
0,0 → 1,288 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%args> |
@P => () |
$envelope_response => 'none' |
$envelope_request => 'none' |
$json_params => undef |
</%args> |
<%once> |
use Digest::MD5 qw(md5_hex); |
use URI; |
use URI::QueryParam; |
</%once> |
<%perl> |
binmode(STDERR, ":utf8"); |
my $http_method = $r->method(); |
#DEBUG $PLogger->debug(sub { ('#' x 30)." http_method.$http_method ARGS:".Dumper(\%ARGS)}); |
if($http_method =~ /GET/i){ |
#accodo a @_ i parametri di @P provenienti da chiamate remote (vedi lib/httpRequestMason.js) |
for(my $I=0; $I<@P; $I+=2){ |
my $var = $P[$I+1]; |
# condizione di campo nullo |
$ARGS{$P[$I]} = $var eq 'undefined' ? undef : $var; |
} |
delete $ARGS{P}; |
if($json_params){ |
my $params = jsonToObj($json_params); |
foreach my $key (keys %{$params}){ |
$ARGS{$key} = $params->{$key} |
} |
} |
delete $ARGS{json_params}; |
}elsif($http_method =~ /POST|PUT|DELETE/i){ |
my $content; |
if(my $size = $r->headers_in->{'Content-length'}){ |
$r->read($content, $size); |
} |
# verifico che sia nel formato UTF-8 |
utf8::is_utf8($content) || utf8::decode($content); |
if ($envelope_request eq 'json'){ |
$PLogger->debug(sub{ "CONTENT JSON OBJECT = [$content]" }); |
if(length($content) == 0){ |
my $err = "ERRORE: Il browser ha inviato una chiamata di tipo POST senza il content\n"; |
$PLogger->warn(sub{ $err }); |
$m->put($r->dir_config('HtmlDocType').qq|\n<html><body>$err</body></html>|); |
return; |
} |
my $requestObject = jsonToObj($content); |
#DEBUG $PLogger->debug(sub{ "##################### requestObject =", Dumper($requestObject); }); |
$ARGS{method} = $requestObject->{method}; |
#DEBUG $PLogger->debug(sub{ "method=" . $ARGS{method}; }); |
if (defined $requestObject->{params}){ |
for my $param (keys %{$requestObject->{params}}){ |
#DEBUG $PLogger->debug(sub{ Dumper($requestObject->{P}{$param}); }); |
$ARGS{$param} = $requestObject->{params}{$param}; |
} |
} |
$envelope_response = $requestObject->{envelope_response} if defined $requestObject->{envelope_response}; |
}elsif($envelope_request eq 'xml'){ |
$ARGS{content} = $content; |
}elsif ($envelope_request eq 'none' || $envelope_request eq '' || !defined $envelope_request){ |
$Session{Content} = $content; |
} |
} |
$Session{envelope_response} = $envelope_response; |
#DEBUG $PLogger->info("\nURI=$ENV{REQUEST_URI}\nARGS=".Dumper(\%ARGS)); |
# numero di righe da ritornare dal recordset |
if(!defined $ARGS{rows}){ |
$ARGS{rows} = 1; |
} |
# indico un limite ragionevole nel caso venga indicato rows= |
# o superiore al limite |
if(!$ARGS{rows} || $ARGS{rows} > $r->dir_config('MaxRetrieveRows')){ |
$ARGS{rows} = $r->dir_config('MaxRetrieveRows'); |
} |
# se definito start='' pongo la partenza all'inizio |
if(!$ARGS{start}){ |
$ARGS{start} = 0; |
} |
# Utilizzato per la generazione dei dati nel formato XML <$xml_path>...</$xml_path> |
if(!$ARGS{xml_path}){ |
my $xml_path = $m->base_comp->dir_path; |
$xml_path =~ s|^/||; |
$xml_path =~ s|/.*||; |
$ARGS{xml_path} = $xml_path; |
} |
# verifico il suffisso |
my $arg; |
if($m->base_comp->name eq $m->dhandler_name){ |
# chiamata da un dhandler |
$arg = $m->dhandler_arg; |
}else{ |
$arg = $m->base_comp->path; |
# elimino dal percorso il primo livello |
$arg =~ s|/\w+/||; |
} |
my $suff = $arg; |
$suff =~ s/^.*\.//; |
if(!$suff){ |
$suff = 'mql'; |
} |
$ARGS{Suff} = $suff; |
$arg =~ s/\..*$//; |
$ARGS{Base} = $arg; |
if($suff eq 'mql'){ |
$suff = 'html'; |
} |
if(!$ARGS{method}){ |
$ARGS{method} = $suff; |
} |
if(!$ARGS{name}){ |
my $name = $arg; |
$name =~ s|/|.|g; |
$ARGS{name} = $name; |
} |
# utilizzato per verificare se c'è ripetuto conflitto nel caricamento dei record in cache |
$ARGS{conflict_on_load_records} = 0; |
# buffer dei recordset |
$ARGS{RecordsetCache} = {}; |
# metto a disposizione gli argomenti a tutti |
$Session{ARGS} = \%ARGS; |
</%perl> |
%# $PLogger->debug(sub{ '-'x40,'ARGS=',Dumper(\%ARGS), '-'x40; }); |
%# $PLogger->debug(sub{ '-'x40,'@_=',Dumper(\@_), '-'x40; }); |
%# $PLogger->debug(sub{ '#' x 70, Dumper(\%ENV), '#' x 70; }); |
%# componente di inizializzazione dell'applicazione specifica |
%# componente da includere in fondo |
<& /init.application.comp &>\ |
% # se il file richiamato è .xls, effettuo un redirect interno al file .mql corrispondente |
% if($ARGS{Suff} eq 'xls'){ |
% $r->internal_redirect($r->dir_config('DataBaseUrl').'/'.$ARGS{Base}.'.mql?'.$ENV{QUERY_STRING}); |
% $m->clear_buffer; |
% $m->abort; |
%# my $req = $m->make_subrequest( comp => $r->dir_config('DataBaseUrl').'/'.$ARGS{Base}.'.mql', args => [ %ARGS ] ); |
%# $req->exec; |
%# $m->subexec($r->dir_config('DataBaseUrl').'/'.$ARGS{Base}.'.mql'); |
% }else{ |
% $m->call_next; |
% } |
<%init> |
# mi assicuro che venga utilizzata la locale 'C' per i numeri |
use POSIX qw(locale_h); |
setlocale(LC_NUMERIC, 'C'); |
# connessione al database |
# N.B. Utilizzo Auth_AC::AuthCookieHandler anche per le connessioni con Auth_AC::AuthBasicHandler e anonime |
my $dbh = $Session{Dbh} = Auth_AC::AuthCookieHandler->connect($r); |
# Nel caso di autenticazione basic $Sess_id, $Hash saranno undef |
my ($Login, $Sess_id, $Hash) = split /:/, $Session{Auth_cookie}, 3; |
#DEBUG print STDERR "SESSION ($Login, $Sess_id, $Hash) '$ENV{HTTP_SESSION}' '$ENV{REMOTE_USER}' '".$r->user()."'\n"; |
# recupero i dati dell'Utente |
my $sth; |
my $row_user; |
if($Sess_id){ |
$sth = $dbh->prepare(q{ |
SELECT |
anagrafiche.id AS anagrafiche_id, |
rtrim(anagrafiche.nome) || ' ' || rtrim(anagrafiche.cognome) as nominativo, |
session.id AS session_id, |
rtrim(nome) || ' ' || rtrim(cognome) as nominativo, |
session.user_ip, |
session.session, |
session.session_time, |
session.previus_session_time |
FROM anagrafiche |
INNER JOIN session ON session.id_anagrafiche = anagrafiche.id |
WHERE anagrafiche.login = ? |
AND session.session = ?; |
}); |
$sth->execute($Login, $Sess_id); |
$row_user = $sth->fetchrow_hashref; |
$Session{IP} = $row_user->{user_ip}; |
}else{ |
# siamo senza la session (Auth Basic) |
$sth = $dbh->prepare(q{ |
SELECT |
id AS anagrafiche_id, |
rtrim(nome) || ' ' || rtrim(cognome) as nominativo, |
session, |
session_time, |
previus_session_time |
FROM anagrafiche |
WHERE anagrafiche.login = ?; |
}); |
$sth->execute($Login); |
$row_user = $sth->fetchrow_hashref; |
$Session{IP} = $ENV{HTTP_X_FORWARDED_HOST} ? $ENV{HTTP_X_FORWARDED_FOR} : $ENV{REMOTE_ADDR}; |
} |
$Session{Session_id} = $row_user->{session_id}; |
$Session{User_id} = $row_user->{anagrafiche_id}; |
$Session{SessionTime} = $row_user->{session_time}; |
$Session{PreviusSessionTime} = $row_user->{previus_session_time}; |
$Session{Nominativo} = $row_user->{nominativo}; |
# N.B. $Ver è una variabile globale; utilizzo l'ID session e l'indirizzo IP per definire la hash |
$Ver = $Sess_id ? md5_hex($Sess_id.$Session{IP}) : undef; |
$Session{Session} = $Sess_id; |
$sth = $dbh->prepare(q{ |
select |
gruppi.id, |
gruppi.nome |
from |
gruppi, |
anagrafiche_gruppi |
where |
gruppi.id = anagrafiche_gruppi.id_gruppi and |
anagrafiche_gruppi.id_anagrafiche = ?; |
}); |
$sth->execute($Session{User_id}); |
my @groups = (); |
while(my $row_group = $sth->fetchrow_hashref){ |
$Session{"Group_$row_group->{nome}"} = 1; |
push @groups, $row_group->{nome}; |
} |
$Session{Groups} = \@groups; |
# elaboro i permessi dell'utente |
$sth = $dbh->prepare(q{ |
select distinct |
funzioni.nome as funz, |
autorizzazioni.nome as auth |
from |
funzioni, |
gruppi, |
anagrafiche_gruppi, |
autorizzazioni, |
gruppi_funzioni |
where |
gruppi.id = anagrafiche_gruppi.id_gruppi and |
anagrafiche_gruppi.id_anagrafiche = ? and |
gruppi_funzioni.id_autorizzazioni = autorizzazioni.id and |
gruppi_funzioni.id_gruppi = gruppi.id and |
gruppi_funzioni.id_funzioni = funzioni.id |
order by funzioni.nome, autorizzazioni.nome; |
}); |
$sth->execute($Session{User_id}); |
my $prev_funz; |
while(my $row_auth = $sth->fetchrow_hashref){ |
# Albero dei permessi |
$Session{Auth}{$row_auth->{funz}}{$row_auth->{auth}} = 1; |
} |
$Session{Input_Date}=0; |
$Session{envelope_response} = $envelope_response; |
# log modifiche al database |
$Session{Logs} = $dbh->prepare(q|insert into public.logs (id_anagrafiche, table_name, id_record, field, old_value, new_value) values (?,?,?,?,?,?);|); |
#DEBUG $PLogger->debug(sub{ 'SESSION', Dumper(\%Session); }); |
initBrowserDetect(); |
</%init> |
<%filter> |
if($_){ |
if ($Session{envelope_response} eq 'json'){ |
$r->headers_out->{'X-JSON-RPC'} = 'JSONResult'; |
$_ = MasonSQL::JSONRPCUtils::json_rpc_response($_); |
}elsif($Session{envelope_response} eq 'xml'){ |
$r->headers_out->{'X-XML-RPC'} = 'XMLResult'; |
}elsif($Session{envelope_response} eq 'none' || $Session{envelope_response} eq '' || !defined($Session{envelope_response})){ |
# Non modifico nulla |
}elsif($Session{envelope_response} eq 'rest'){ |
# Non modifico nulla |
}else{ |
$_ = "<html><head><title>Envelope error!</title></head><body>Envelope type \"$Session{envelope_response}\" is not valid!</body></html>"; |
} |
}else{ |
$_ = ''; |
} |
</%filter> |
<%flags> |
inherit => '/library.comp' |
</%flags> |
%# Ultima riga senza <CR> |
/tags/2.0/htdocs/library.comp |
---|
0,0 → 1,251 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2020 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%init> |
# azzero le variabili globali |
%Global=(); |
# usata dal componente /input/select.comp per la gestione dei buffer |
$Global{SelectBufferFlag}=(); |
if($Session{Dbh}){ |
$Session{Dbh}->disconnect(); |
} |
# inizializzo i valori di sessione |
%Session=(); |
# cache per i parametri dei campi (vedi lib/dbms_library.comp - FieldFilter_from ) |
$Session{Fields_params} = {}; |
# individuazione dell'utente (autenticazioni basic, cookies, anonymous) |
my $auth_cookie = $r->user; |
my ($Login, $Sess_id, $Hash) = split /:/, $auth_cookie, 3; |
if(!defined $Login){ |
# verifico se esiste il cookie di autenticazione con Auth_AC |
if(my $cookie = Apache2::Cookie::Jar->new($r)->cookies('Auth_AC::AuthCookieHandler_Auth_AC_')){ |
$auth_cookie = Apache2::Cookie::Jar->new($r)->cookies('Auth_AC::AuthCookieHandler_Auth_AC_')->value; |
if(defined $auth_cookie){ |
# Verifico la presenza del Cookie di sessione anonima e relativa sessione nel database |
($Login, $Sess_id, $Hash) = split /:/, Auth_AC::AuthCookieHandler->authen_ses_key($r, $auth_cookie); |
} |
} |
# Nel caso di assenza di autenticazione attivo la sessione con l'utente anonimo indicato nella configurazione |
if(!defined $Login && defined $ENV{HTTP_SESSION}){ |
my $uri = URI->new( '?'.$ENV{HTTP_SESSION}); |
my $params = $uri->query_form_hash; |
# Verifico la presenza del Cookie di sessione anonima e relativa sessione nel database |
$auth_cookie = $params->{session_key}; |
if(defined $auth_cookie){ |
($Login, $Sess_id, $Hash) = split /:/, Auth_AC::AuthCookieHandler->authen_ses_key($r, $auth_cookie); |
} |
if(!$Login){ |
$Login = $r->dir_config('AnonymousGuestLogin'); |
# Creo una nuova sessione utente anonimo (anche nel caso che authen_ses_key abbia restituito undef |
$auth_cookie = Auth_AC::AuthCookieHandler->authen_cred($r, $Login, undef, undef, undef); |
$r->headers_out->{'X-Anonymous-Guest-Session'} = "session_key=$auth_cookie"; |
($Login, $Sess_id, $Hash) = split /:/, $auth_cookie; |
} |
} |
} |
$Session{Login} = $Login; |
$Session{Auth_cookie} = $auth_cookie; |
# Inizializzazione logger Log4perl |
my $PLogFilename = $r->dir_config('LogBaseDir') . $r->dir_config('ApplicationName') . '/' . $Login . '.log'; |
my $PLogName = $r->dir_config('ApplicationName') . 'Appender' . $Login; |
$Session{PLogCategory} = $r->dir_config('ApplicationName') . '::' . $Login; |
$PLogger = Log::Log4perl::get_logger($Session{PLogCategory}); |
$PLogger->level(eval '$'.$r->dir_config('PLogLevel')); |
unless (defined $Log::Log4perl::Logger::APPENDER_BY_NAME{$PLogName}){ |
$PLogger->additivity(0); |
my $user_appender = Log::Log4perl::Appender->new( |
"Log::Log4perl::Appender::File", |
name => $PLogName, |
filename => $PLogFilename |
); |
my $user_layout = Log::Log4perl::Layout::PatternLayout->new($r->dir_config('PLogPatternLayout')); |
$user_appender->layout($user_layout); |
$PLogger->add_appender($user_appender); |
} |
# Sezione JSLogger |
unless (defined $JSLogger){ |
my $check_code = <<CODE; |
if (!window.#NAME#){ |
#INIT# |
} |
CODE |
my $init_code1 = ''; |
my $init_code2 = <<CODE; |
window.#NAME# = console; |
CODE |
my $log_code = <<CODE; |
window.#NAME#.#LEVEL#('MasonSQL', #MSG#); |
CODE |
$JSLogger = MasonSQL::JSLogger->new(); |
# $JSLogger->join_separator(' + '); |
$JSLogger->set_code({ 'init' => $check_code, 'log' => $log_code}); |
$JSLogger->init_code(['init'], {init => $init_code2}); |
$JSLogger->init_code(['init', 'log'], {name => 'JSLogger', minlevel => 'DEBUG'}); |
} |
# Livello di log JavaScript |
$JSLogger->level(eval '$'.$r->dir_config('JSLogLevel')); |
</%init> |
<%perl> |
$m->call_next; |
</%perl> |
<%once> |
use Apache2::Cookie; |
use Data::Dumper; # DEBUG |
$Data::Dumper::Terse = 1; |
my $log_dir = $r->dir_config('LogDir'); |
my $conf = q( |
default_pattern = [%d] - %p - %F:%L %m%n |
log4perl.rootLogger = DEBUG, rootLogfile |
log4perl.appender.rootLogfile = Log::Log4perl::Appender::File |
log4perl.appender.rootLogfile.filename = ).$log_dir.q(/root.log |
log4perl.appender.rootLogfile.layout = Log::Log4perl::Layout::PatternLayout |
log4perl.appender.rootLogfile.layout.ConversionPattern = ${default_pattern} |
log4perl.category.masonsql = DEBUG, masonsqlLogfile |
log4perl.additivity.masonsql = 0 |
log4perl.appender.masonsqlLogfile = Log::Log4perl::Appender::File |
log4perl.appender.masonsqlLogfile.filename = ).$log_dir.q(/masonsql.log |
log4perl.appender.masonsqlLogfile.layout = Log::Log4perl::Layout::PatternLayout |
log4perl.appender.masonsqlLogfile.layout.ConversionPattern = ${default_pattern} |
); |
Log::Log4perl::init( \$conf ); |
use Log::Log4perl qw(:levels); |
use Carp; |
use Compress::Zlib; |
use HTTP::BrowserDetect; |
use DBI; |
use JSON; |
$JSON::UnMapping = 1; |
use Encode 'from_to'; |
# pulisce nella stringa gli spazi iniziali finali ed intermedi se superiori ad uno |
sub AllTrim($){ |
$_ = shift; |
s/^\s+//; |
s/\s+$//; |
s/\s+/ /g; |
return $_; |
} |
# applica alla URL la versione (per gestire la cache del browser) |
sub URL { |
my $url = shift; |
# verifico se è già presente "?" |
if($url =~ m/\?/){ |
$url .= '&'.shift; |
}else{ |
$url .= '?'.shift |
} |
return $url; |
} |
# cerca nelle varie MasonCompRoot il file specificato, ritornando il persorso completo |
sub request_to_comp_path($){ |
my($comp_name) = @_; |
foreach my $root (@{$m->interp->comp_root}) { |
my $file_name = ${$root}[1].$comp_name; |
if( -e $file_name ) { |
return $file_name; |
} |
} |
return undef; |
} |
# set link configurazione accesso database (se si utilizza Reportman versione Kylix |
if(my $BorlandConfig = $r->dir_config('BorlandConfig')){ |
my $ReportmanDir = $r->dir_config('ReportmanDir'); |
my $link = readlink $ReportmanDir.'/.borland'; |
if(! defined $link or $link ne $BorlandConfig){ |
unlink $ReportmanDir.'/.borland'; |
symlink $BorlandConfig, $ReportmanDir.'/.borland' or die "Errore nel creare il link $ReportmanDir/.borland --> $BorlandConfig\n"; |
} |
} |
# Usati per catalogare i componenti da inserire nell'intestazione della pagina <HEAD/> |
# $Global{LoadHeader_Css} = {}; |
# $Global{LoadHeader_Js} = {}; |
# $Global{LoadHeader_Meta} = {}; |
# $Global{LoadHeader_Style} = {}; |
# $Global{LoadHeader_Head} = {}; |
# $Global{LoadHeader_Body} = {}; |
# componenti di uso generale ... |
# Precarica dichiarazioni nella sezione <HEAD> del documento; utilizzata per i componenti della libreria di input |
sub LoadHeader{ |
while(my $comp = shift){ |
if($comp eq 'SELF'){ |
$comp = $m->current_comp->name; |
} |
my $name = $comp; |
my $URL = URL($comp, "Ver=$Ver"); |
# %Global è una variabile dichiarata globale; in /autohandler vengono richiamate |
# ed allegate tutte le occorrenze dell'HASH all'interno della sezione <HEAD> |
if($name =~ m/\.js$/i){ |
if(! defined $Global{'Input/'.$name}){ |
$Global{'Input/'.$name} = 1; |
push @{$Global{LoadHeader_Js}}, $name; |
} |
}elsif($name =~ m/\.css$/i){ |
if(!defined $Global{'Input/'.$name}){ |
$Global{'Input/'.$name} = 1; |
push @{$Global{LoadHeader_Css}}, qq|<link rel="stylesheet" href="$URL" type="text/css">|; |
} |
}elsif($name =~ m/\.comp$/i){ |
my $Comp = $m->fetch_comp($name); |
if(!$Comp){ |
$PLogger->error("Il componente '$name' ha provocato un errore durante il tentativo di caricamento da parte della procedura LoadHeader"); |
}else{ |
if($Comp->method_exists('HTML_HEAD')){ |
if(!defined $Global{'Head/'.$name}){ |
$Global{'Head/'.$name} = 1; |
push @{$Global{LoadHeader_Head}}, $Comp->scall_method('HTML_HEAD'); |
} |
} |
if($Comp->method_exists('HTML_BODY')){ |
if(!defined $Global{'Body/'.$name}){ |
$Global{'Body/'.$name} = 1; |
push @{$Global{LoadHeader_Body}}, "<!-- [Body/$name] -->\n".$Comp->scall_method('HTML_BODY'); |
} |
} |
if($Comp->method_exists('LIBRARY')){ |
my $list = $Comp->scall_method('LIBRARY'); |
$list =~ s/^\s+|\s+$//g; |
my @list = split /\s+/, $list; |
&LoadHeader(@list); |
} |
} |
}else{ |
if(! defined $Global{'Head/'.$name}){ |
$Global{'Head/'.$name} = 1; |
push @{$Global{LoadHeader_Head}}, $m->scomp($comp); |
} |
} |
} |
} |
use HTTP::BrowserDetect; |
sub initBrowserDetect(){ |
# verifico se gia inizializzati alcuni attributi della sessione |
if(!$Session{Browser}){ |
# individuo il tipo di browser... |
$Session{Browser} = new HTTP::BrowserDetect($r->headers_in->{'User-Agent'}); |
} |
} |
</%once> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/frame.html |
---|
0,0 → 1,474 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2012 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%once> |
my $DataBaseUrl = $r->dir_config('DataBaseUrl'); |
</%once> |
<%init> |
# cache |
if(my $expiration_time = $r->dir_config('CacheFramesExpiration')){ |
my %cache_keys = %ARGS; |
delete $cache_keys{Ver}; # la cache del server non deve essere influenzata dalla versione (usata per gestire la cache nel browser) |
$cache_keys{Groups} = $Session{Groups}; # nella cache devo tener conto anche dei gruppi che potrebbero influenzarne il contenuto |
return if $m->cache_self(expire_in => $expiration_time, key => $from.'-'.md5_hex(to_json(\%cache_keys)), busy_lock => '30 sec'); |
} |
# caricamento nella sezione <HEAD/> delle librerie |
&LoadHeader('/lib/httpRequestMason.js', '/lib/library.js', '/lib/databinding.js', '/lib/displaybinding.js'); |
</%init> |
<%args> |
$from |
$form => undef |
$children => undef # form da utilizzare per disegnare i figli |
$children_container => 'Tab' #undef # contenitore per la visualizzazione dei figli ( undef, 'Tab' oppure 'Accordion' ) |
$rows => undef # se dichiarato indica il numero di righe da visualizzare nel form (se si tratta di TABLE o DIVS) |
# il valore dichiarato nella tabella con <%method TABLE_ROWS> ha la precedenza |
$group_cols => 1 # numero di gruppi con cui suddividere la tabella, da affiancare orizzontalmente |
$rows_child => undef # se dichiarato indica il numero delle righe delle tabelle figlie |
# il valore dichiarato nella tabella figlia con <%method TABLE_ROWS> ha la precedenza |
$group_cols_child => 1 # numero di gruppi con cui suddividere le tabelle figlie, da affiancare orizzontalmente |
$find_area => undef # posizione area menu; [top, bottom, left, right] - se 'none' non viene visualizzata, se undef viene usata la definizione presente nel file |
$find_area_child => undef # posizione area menu dei figli [top] se undef non viene visualizzata - N.B. Da implementare le altre posizioni |
$find_component => undef # nome del componente utilizzato per la funzione di filtro |
# disp_* - visualizza pulsanti 1:sempre visibile, 0: mai visibile, ''|undef: dipende dai permessi attivati |
$disp_navbar => 1 # visualizza il form padre con i pulsanti << < > >> Goto[ ] di navigazione |
$disp_cancel => undef # ... pulsante annulla |
$disp_refresh => 1 # ... pulsante aggiorna |
$disp_change => undef # ... pulsante modifica |
$disp_insert => undef # ... pulsante inserimento |
$disp_dup => 1 # ... pulsante duplicazione |
$disp_save => undef # ... pulsante salva |
$disp_delete => undef # ... pulsante cancella |
$disp_print => undef # ... pulsante stampa |
$disp_xls => undef # ... pulsante espostazione XLS |
$disp_log => undef # ... pulsante visualizzazione Log |
$disp_find_print => undef # ... pulsante stampa nella sezione di ricerca |
$disp_find_xls => undef # ... pulsante espostazione XLS nella sezione di ricerca |
$find_key => undef # chiave da cercare al primo caricamento del recordset del padre |
$father_id => '' # chiave per selezionare i record in base al codice della tabella MASTER |
$father_id_update => '' # chiave per modificare i record in base al codice della tabella MASTER |
$mode => 'rewind' # posiziona il record all'inizio |
$form_include_pre => undef # nome del metodo aggiuntivo contenuto nel padre da allegate in testa al form |
$form_include_post => undef # nome del metodo aggiuntivo contenuto nel padre da allegate in coda al form |
$Detail_from => undef # visualizza nel form padre i pulsanti per aprire un form di inserimento/modifica più dettagliato |
$childrenDetail_from => undef # visualizza nei form figli i pulsanti per aprire un form di inserimento/modifica più dettagliato |
$where => undef # query di filtro da passare al recordset principale |
$pk => undef # valore della Primary key da passare come filtro |
$prefix => undef # prefisso da utilizzare nel definire i nomi dei form e dei recordset |
$MenuDescrOnRight => undef # nel menù di ricerca (quando non è di tipo top/bottom, posiziona le descrizioni dei campi a destra |
# del campo, anziché sopra (il metodo MENU_DESCR_ON_RIGHT ha la precedenza) |
$min_height => '200px' # altezza minima del form |
$height => undef |
# se sono presenti dei campi $force_<NOME> vengono utilizzati per inizializzare i valori dei campi al caricamento del primo record |
</%args> |
<%perl> |
if($from !~ m|/|){ |
# default schema |
$ARGS{from} = $from = $r->dir_config('DefaultSchema').'/'.$from; |
} |
# schema |
my($schema) = split(/\//, $from); |
my $FATHER = $m->fetch_comp("$DataBaseUrl/$from.mql"); |
$FATHER || die("Oggetto non esistente '$DataBaseUrl/$from.mql'\n"); |
if($FATHER->method_exists('PERL_EVAL_PRE')){ |
eval $FATHER->scall_method('PERL_EVAL_PRE'); |
$@ && die "PERL_EVAL_PRE error on $from: $@\n"; |
} |
if($FATHER->method_exists('MENU_DESCR_ON_RIGHT')){ |
$MenuDescrOnRight = $FATHER->scall_method('MENU_DESCR_ON_RIGHT'); |
} |
if(!$find_area){ |
$find_area = $FATHER->method_exists('FIND_AREA') ? $FATHER->scall_method('FIND_AREA') : 'left'; |
$find_area =~ s/\s+//sg; |
} |
if($find_area && !$find_component){ |
$find_component = ($find_area eq 'top' || $find_area eq 'bottom') ? 'FIND' : 'FIND_MENU'; |
} |
if(!$Detail_from && $FATHER->method_exists('DETAIL_FROM')){ |
$Detail_from = $FATHER->scall_method('DETAIL_FROM'); |
} |
if($Detail_from && $Detail_from !~ m|/|){ |
$ARGS{Detail_from} = $Detail_from = $schema.'/'.$Detail_from; |
} |
if($childrenDetail_from && $childrenDetail_from !~ m|/|){ |
$ARGS{childrenDetail_from} = $childrenDetail_from = $schema.'/'.$childrenDetail_from; |
} |
if(!defined $form && $FATHER->method_exists('FATHER_TEMPLATE')){ |
$form = $FATHER->scall_method('FATHER_TEMPLATE'); |
} |
if(!defined $form){ |
$form = 'FORM'; |
} |
if($FATHER->method_exists('FORM_TYPE')){ |
$form = $FATHER->scall_method('FORM_TYPE'); |
$form =~ s/\s+//sg; |
} |
my $father_prefix = defined $prefix ? "${prefix}_${from}" : "${form}_${from}"; |
$father_prefix =~ s|/|_|g; |
my $Recordset = $Session{Recordset} = "Rec_${father_prefix}"; |
my $Display = $Session{Display} = "Disp_${father_prefix}"; |
if(!defined $children && $FATHER->method_exists('CHILDREN_TEMPLATE')){ |
$children = $FATHER->scall_method('CHILDREN_TEMPLATE'); |
} |
if(!$children){ |
$children = 'TABLE'; |
} |
if($rows_child && ($children eq 'FORM' || $children =~ /^TEMPLATE/ || $children eq 'LINEAR')){ |
$rows_child = 1; |
} |
if(!defined $children && $FATHER->method_exists('CHILDREN_CONTAINER')){ |
$children_container = $FATHER->scall_method('CHILDREN_CONTAINER'); |
} |
$children_container = ucfirst lc $children_container; |
if($form eq 'FORM' || $form =~ /^TEMPLATE/ || $form eq 'LINEAR'){ |
$rows = 1; |
}else{ |
if($FATHER->method_exists('TABLE_ROWS')){ |
$rows = $FATHER->scall_method('TABLE_ROWS', %ARGS); |
}elsif(!$rows){ |
$rows = 10; # default value |
} |
if($FATHER->method_exists('TABLE_GROUP_COLS')){ |
# numero di gruppi con cui suddividere la tabella, da affiancare orizzontalmente |
$group_cols = $FATHER->scall_method('TABLE_GROUP_COLS', %ARGS); |
} |
} |
$ARGS{'rows'} = $rows; |
if($pk){ |
my $PK = $FATHER->scall_method('KEY', %ARGS); |
$where = "$PK = $pk"; |
if(!$father_id){ |
# in lib/dbms_library.comp verifico la condizione per evitare il test sul campo "father_id" |
$father_id = -2; |
} |
} |
my @child_names; |
if($children){ |
# valuto se la tabella ha figli |
$_ = $FATHER->scall_method('SCHEMA_CHILDREN'); |
@child_names = split /,/, $_; |
} |
</%perl> |
%# In IE deve essere dichiarato name='' |
<script> |
require(["dojo/parser", "dijit/layout/BorderContainer","dijit/layout/ContentPane"]); |
var <%$Recordset%> = new DataBinding('<%$Recordset%>', '<%$from%>', <%$rows%>); |
<%$Recordset%>.father_id = '<% $father_id %>'; |
<%$Recordset%>.father_id_update = '<% $father_id_update %>'; |
var <%$Display%> = new DisplayBinding('<%$Display%>', <%$Recordset%>); |
<%$Display%>.where = '<% $where |js%>'; |
<%$Display%>.confirmDelMessage = "<%$FATHER->call_method('CONFIRM_DEL_MESSAGE')|js%>"; |
<%$Display%>.formKeysMovement = '<% $FATHER->scall_method('FORM_KEYS_MOVEMENT') |js%>'; |
</script> |
%# nasconde la pagina durande il rendering dei componenti Dojo |
%# Vedi demo: https://dojotoolkit.org/documentation/tutorials/1.8/loading_overlay/ |
<div id="loadingOverlay_<%$father_prefix%>" class="loadingOverlay pageOverlay"></div> |
% # contenitore di padre e figli |
<div id="FatherContainer_<%$father_prefix%>" class="FatherContainer" |
data-dojo-type="dijit/layout/BorderContainer" design="headline" gutters="false" |
style="min-width:400px; min-height:<%$min_height%>; height:<% $height ? $height : '100%' %>; z-index:0; width:100%;"> |
% if($form_include_pre && $FATHER->method_exists($form_include_pre)){ |
<div id="FatherIncludePre_<%$father_prefix%>" class="FatherContent FatherIncludePre" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="top" splitter="false" > |
% $FATHER->call_method($form_include_pre, Recordset => $Recordset, Display => $Display); |
</div> |
% } |
<div id="FatherMain_<%$father_prefix%>" class="FatherMainContainer" |
data-dojo-type="dijit/layout/BorderContainer" design="headline" gutters="false" doLayout="true" |
% if(@child_names){ |
region="top" splitter="true" |
style="min-width:100px; min-height:100px; z-index:0; width:100%; height:<% @child_names ? '100px' : '100%' %>;"> |
% }else{ |
region="center" splitter="false" |
style="min-width:100px; min-height:100px; z-index:0; width:100%; height:100%;"> |
% } |
<A disabled href="#" id="anchor_<%$Display%>"></A> |
% if($FATHER->method_exists('FORM_INCLUDE_PRE')){ |
<div id="FatherFormIncludePre_<%$father_prefix%>" class="FatherContent FatherFormIncludePre" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="top" splitter="false" > |
% $FATHER->call_method('FORM_INCLUDE_PRE', Recordset => $Recordset, Display => $Display, |
% Recordset_father => undef, Display_father => undef); |
</div> |
% } |
<div id="FatherFormHeader_<%$father_prefix%>" class="FatherContent FatherFormHeader" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="top" splitter="false" > |
% $FATHER->call_method('FORM_HEADER', %ARGS, rows => $rows, Controls => 1, Recordset => $Recordset, Display => $Display); |
</div> |
<div id="FatherFindArea_<%$father_prefix%>" class="<%$find_component%> FatherContent FatherFindArea" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="<% $find_area %>" |
splitter="<% $find_area eq 'top' || $find_area eq 'bottom' ? 'false' : 'true' %>" > |
% $FATHER->call_method($find_component, %ARGS, Recordset => $Recordset, Display => $Display, DescrOnRight => $MenuDescrOnRight); |
</div> |
<div id="FatherForm_<%$father_prefix%>" class="FatherContent FatherForm" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="center" splitter="false" > |
% if($FATHER->method_exists('FIELDS_INCLUDE_PRE')){ |
% $FATHER->call_method('FIELDS_INCLUDE_PRE', Recordset => $Recordset, Display => $Display, |
% Recordset_father => undef, Display_father => undef); |
% } |
% $FATHER->call_method($form, %ARGS, rows => $rows, group_cols => $group_cols, Recordset => $Recordset, |
% Display => $Display, Header => 0, Controls => 0, Detail_from => $Detail_from); |
% if($FATHER->method_exists('FIELDS_INCLUDE_POST')){ |
% $FATHER->call_method('FIELDS_INCLUDE_POST', Recordset => $Recordset, Display => $Display, |
% Recordset_father => undef, Display_father => undef); |
% } |
</div> |
</div> |
<script> |
<%$Display%>.widgetsContainer = document.getElementById('FatherContainer_<%$father_prefix%>'); |
console.debug('frame.html FatherContainer_<%$father_prefix%>', <%$Display%>); |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
</script> |
% if($children){ |
% if(@child_names){ |
<script> |
<%perl> |
if(@child_names == 1){ |
$children_container = 'Stack'; |
} |
my %rows_child; |
my %template_child; |
for(my $col=0; $col<@child_names; $col++){ |
my $child = $child_names[$col]; |
# tabella figlia ... |
my $child_prefix = defined $prefix ? $prefix.'_'.$child : $child; |
$child_prefix =~ s|/|_|g; |
my $Recordset_child = $Session{Recordset_child} = 'RecC_'.$child_prefix; |
my $Display_child = $Session{Display_child} = 'DispC_'.$child_prefix; |
# valuto il numero di righe della tabella figlia |
my $CHILD = $m->fetch_comp("$DataBaseUrl/$child.mql"); |
$CHILD || die("Oggetto figlio di $from non esistente '$DataBaseUrl/$child.mql'\n"); |
my $rows; |
if($CHILD->method_exists('TABLE_ROWS')){ |
$rows = $CHILD->scall_method('TABLE_ROWS', %ARGS); |
} |
if(!$rows){ |
if(!($rows = $rows_child)){ |
$rows = 10; # numero di righe se non diversamente dichiarato |
} |
} |
my $child_template = $children; |
if($CHILD->method_exists('CHILD_TEMPLATE')){ |
$child_template = $CHILD->scall_method('CHILD_TEMPLATE', from => $from); |
} |
$template_child{$child} = $child_template; |
$rows_child{$child} = $child_template eq 'FORM' || $child_template =~ /^TEMPLATE/ || $child_template eq 'LINEAR' ? 1 : $rows; |
</%perl> |
var <%$Recordset_child%> = new DataBinding('<%$Recordset_child%>', '<%$child%>', <%$rows_child{$child}%>); |
var <%$Display_child%> = new DisplayBinding('<%$Display_child%>', <%$Recordset_child%>); |
<%$Recordset_child%>.father = <%$Recordset%>; |
<%$Recordset%>.children[<%$col%>] = <%$Recordset_child%>; |
<%$Display_child%>.confirmDelMessage = "<%$CHILD->call_method('CONFIRM_DEL_MESSAGE')|js%>"; |
<%$Display_child%>.formKeysMovement = '<% $CHILD->scall_method('FORM_KEYS_MOVEMENT') |js%>'; |
% } # loop @child_names |
% if($children_container){ |
require(["dijit/layout/<%$children_container%>Container"]); |
% } |
</script> |
<div id="ChildrenContainer_<%$father_prefix%>" class="ChildrenContainer" |
% if($children_container){ |
data-dojo-type="dijit/layout/<%$children_container%>Container" style="width:100%; height:100%;" |
doLayout="true" region="center" splitter="true" > |
% }else{ |
% # tabelle figlie una sotto l'altra |
data-dojo-type="dijit/layout/ContentPane" region="center" splitter="true" > |
% } |
<%perl> |
my $child_selected = $FATHER->scall_method('SCHEMA_CHILD_SELECTED'); |
for(my $col=0; $col<@child_names; $col++){ |
my $child = $child_names[$col]; |
my $child_prefix = defined $prefix ? $prefix.'_'.$child : $child; |
$child_prefix =~ s|/|_|g; |
my $Recordset_child = $Session{Reordset_child} ='RecC_'.$child_prefix; |
my $Display_child = $Session{Display_child} = 'DispC_'.$child_prefix; |
my $CHILD = $m->fetch_comp("$DataBaseUrl/$child.mql"); |
my $Description = $CHILD->scall_method($CHILD->method_exists('TITLE') ? 'TITLE' : 'DESCRIPTION', %ARGS); |
my $this_group_cols_child = $group_cols_child; |
if($CHILD->method_exists('TABLE_GROUP_COLS')){ |
# numero di gruppi con cui suddividere la tabella figlia, da affiancare orizzontalmente |
$this_group_cols_child = $CHILD->scall_method('TABLE_GROUP_COLS', %ARGS); |
} |
# inserisco nel documento la tabella figlia ... |
</%perl> |
<& .CHILD, schema => $schema, form => $template_child{$child}, rows => $rows_child{$child}, group_cols => $this_group_cols_child, from => $child, |
prefix => $child_prefix, Detail_from => $childrenDetail_from, find_area => $find_area_child, |
Recordset => $Recordset_child, Display => $Display_child, MenuDescrOnRight => $MenuDescrOnRight, |
Description => $Description, Recordset_father => $Recordset, Display_father => $Display, |
Selected => ($child eq $child_selected) |
&> |
% } # loop @child_names |
% if($children_container){ |
</div> |
% } |
% } # if(@child_names){ |
% } # if($children) |
% if($FATHER->method_exists('FORM_INCLUDE_POST')){ |
<div id="FatherFormIncludePost_<%$father_prefix%>" class="FatherContent FatherFormIncludePost" |
data-dojo-type="dijit/layout/ContentPane" region="bottom" splitter="false" > |
% $FATHER->call_method('FORM_INCLUDE_POST', Recordset => $Recordset, Display => $Display); |
</div> |
% } |
% if($form_include_post && $FATHER->method_exists($form_include_post)){ |
<div id="FatherIncludePost_<%$father_prefix%>" class="FatherContent FatherIncludePost" |
data-dojo-type="dijit/layout/ContentPane" region="bottom" splitter="false" > |
% $FATHER->call_method($form_include_post, Recordset => $Recordset, Display => $Display); |
</div> |
% } |
</div> |
%# |
%# form per la gestione di una tabella figlia |
<%def .CHILD> |
<%args> |
$schema |
$from |
$form |
$prefix |
$Recordset |
$Display |
$Recordset_father |
$Display_father |
$rows |
$group_cols |
$find_area => undef |
$Detail_from => undef |
$Description |
$MenuDescrOnRight => undef # nel menù di ricerca (quando non è di tipo top bottom, posiziona le descrizioni dei campi a destra del campo, anziché sopra |
$Selected => undef |
</%args> |
<div id="ChildContainer_<%$prefix%>" class="ChildContainer" |
style="display:none;" data-dojo-type="dijit/layout/BorderContainer" doLayout="true" |
gutters="false" title="<% $Description |h%>"<% $Selected ? ' selected="true"' : ''%>> |
<A disabled href="#" id="anchor_<%$Display%>"></A> |
<%perl> |
my $CHILD = $m->fetch_comp("$DataBaseUrl/$from.mql"); |
if($CHILD->method_exists('PERL_EVAL_PRE')){ |
eval $CHILD->scall_method('PERL_EVAL_PRE'); |
$@ && die "PERL_EVAL_PRE error on $from: $@\n"; |
} |
if($CHILD->method_exists('MENU_DESCR_ON_RIGHT')){ |
$MenuDescrOnRight = $CHILD->scall_method('MENU_DESCR_ON_RIGHT'); |
} |
if(!$Detail_from && $CHILD->method_exists('DETAIL_FROM')){ |
$Detail_from = $CHILD->scall_method('DETAIL_FROM'); |
} |
if($Detail_from && $Detail_from !~ m|/|){ |
$ARGS{Detail_from} = $Detail_from = $schema.'/'.$Detail_from; |
} |
if($CHILD->method_exists('FORM_TYPE')){ |
$form = $CHILD->scall_method('FORM_TYPE'); |
$form =~ s/\s+//sg; |
} |
if(!$find_area && $CHILD->method_exists('FIND_AREA')){ |
$find_area = $CHILD->scall_method('FIND_AREA'); |
$find_area =~ s/\s+//sg; |
} |
my $find_component = ($find_area eq 'top' || $find_area eq 'bottom') ? 'FIND' : 'FIND_MENU'; |
</%perl> |
% if($CHILD->method_exists('FORM_INCLUDE_PRE')){ |
<div id="ChildFormIncludePre_<%$prefix%>" class="ChildContent ChildFormIncludePre" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="top" splitter="false" > |
% $CHILD->call_method('FORM_INCLUDE_PRE', Recordset => $Recordset, Display => $Display, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
</div> |
% } |
% if($find_area){ |
<div id="ChildFindArea_<%$prefix%>" class="<%$find_component%> ChildContent ChildFindArea" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="<% $find_area %>" |
splitter="<% $find_area eq 'top' || $find_area eq 'bottom' ? 'false' : 'true' %>" > |
% $CHILD->call_method($find_component, %ARGS, Recordset => $Recordset, Display => $Display, DescrOnRight => $MenuDescrOnRight, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
</div> |
% } |
<div id="ChildFormHeader_<%$prefix%>" class="ChildContent ChildFormHeader" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="top" splitter="false" > |
% $CHILD->call_method('FORM_HEADER', %ARGS, Recordset => $Recordset, Display => $Display, rows => $rows, |
% Recordset_father => $Recordset_father, Display_father => $Display_father, Controls => 1); |
</div> |
<div id="ChildForm_<%$prefix%>" class="ChildContent ChildForm" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="center" splitter="true" > |
% if($CHILD->method_exists('FIELDS_INCLUDE_PRE')){ |
% $CHILD->call_method('FIELDS_INCLUDE_PRE', Recordset => $Recordset, Display => $Display, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
% } |
% $CHILD->call_method($form, %ARGS, rows => $rows, group_cols => $group_cols, Header => 0, Controls => 0, |
% Recordset => $Recordset, Display => $Display, Detail_from => $Detail_from, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
% if($CHILD->method_exists('FIELDS_INCLUDE_POST')){ |
% $CHILD->call_method('FIELDS_INCLUDE_POST', Recordset => $Recordset, Display => $Display, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
% } |
</div> |
% if($CHILD->method_exists('FORM_INCLUDE_POST')){ |
<div id="ChildFormIncludePost_<%$prefix%>" class="ChildContent ChildFormIncludePost" |
data-dojo-type="dijit/layout/ContentPane" doLayout="true" region="bottom" splitter="false" > |
% $CHILD->call_method('FORM_INCLUDE_POST', Recordset => $Recordset, Display => $Display, |
% Recordset_father => $Recordset_father, Display_father => $Display_father); |
</div> |
% } |
</div> |
<script> |
<%$Display%>.widgetsContainer = document.getElementById('ChildContainer_<%$prefix%>'); |
% $m->out(@Script_buffer); |
% @Script_buffer=(); |
</script> |
</%def> |
%# |
<script> |
<%perl> |
# se inserimento e non è attiva la barra di navigazione limito il recordset |
# ai record di id maggiore del valore presente in quel momento |
my $key = $FATHER->scall_method('KEY'); |
if(!$disp_navbar && ($find_key || $mode eq 'insert')){ |
my $from = $FATHER->scall_method('SCHEMA_FROM'); |
my $sth = $Session{'Dbh'}->prepare("select max($key) from $from;"); |
$sth->execute; |
my $max_id = $sth->fetchrow_arrayref->[0]; |
my $where; |
if($find_key && $mode eq 'insert' && $max_id){ |
$where = qq|$key = $find_key or $key > $max_id|; |
}elsif($find_key){ |
$where = qq|$key = $find_key|; |
}elsif($mode eq 'insert' && $max_id){ |
$where = qq|$key > $max_id|; |
} |
</%perl>\ |
<%$Display%>.where = '<% $where |js%>'; |
% } |
<%$Recordset%>.canDup = <% $disp_dup ? 'true' : 'false' %>; |
%#// se definiti dei valori di default iniziali per il primo inserimento ... |
% my %force; |
% foreach my $par (keys %ARGS){ |
% if($par =~ m/force_(.*)/){ |
% $force{$1} = $ARGS{$par}; |
% } |
% } |
% if(keys %force){ |
<%$Display%>.onchange_frame_force = <%$Display%>.onchange; |
<%$Display%>.onchange = function(set, update) { |
% foreach my $par (keys %force){ |
this.getField(<% str2sql_js_delimited($par) %>).set_value(<% str2sql_js_delimited($force{$par})%>); |
% } |
if(this.onchange_frame_force){ |
this.onchange_frame_force(this.call_mode); |
} |
<%$Display%>.onchange = <%$Display%>.onchange_frame_force |
} |
% } |
%#// completamento del rendering grafico ... |
masonSql.once('ready', function(tab){ |
// tab è null se si chiama il frame direttamente dal browser |
if(tab){ |
tab.displayBinding = <%$Display%>; |
} |
masonSql.frameLoad_Handler('<%$father_prefix%>', <%@child_names ? 'true' : 'false'%>, <%$FATHER->method_exists('FORM_HEIGHT') ? $FATHER->scall_method('FORM_HEIGHT') : 'null' %>); |
if(<%$Display%>.post_init()){ |
<%$Display%>.loadRecords('<%$mode%>', '<%$find_key%>'); |
} |
}); |
</script> |
/tags/2.0/htdocs/css/base.css |
---|
0,0 → 1,356 |
html, body { |
border: 0 none; |
height: 100%; |
padding: 0; |
width: 100%; |
} |
#bodyMasonSql.claro { |
font: 9pt Calibri,Arial,Helvetica,Verdana; |
} |
body { |
color: #000090; |
background-color: #FAFAFA; |
} |
p { |
margin: 1px 1px 1px 2px; |
} |
%# Copy&Paste classes |
p.ColSelectable { |
background-color:#f1f1f1; |
} |
p.ColSelected { |
background-color:#fccb9f; |
font-style: italic; |
} |
p.CopyPasteResetInvert { |
background-color:#fecccd; |
} |
p.CopyPasteDisabled { |
color:#9d9b9b; |
} |
div.FIND_MENU { |
background-color: #F5F5F5; |
} |
div.FIND { |
background-color: #F5F5F5; |
} |
.claro .MessagesNewMessage { |
background-color: #FEF7ED; |
} |
div.WinPopupDIV { |
position:absolute; |
visibility:hidden; |
background-color:white; |
} |
div.BodyHelpContainer ul, |
div.MenuHelpContainer ul { |
margin: 4px 4px 14px -15px; |
} |
div.BodyHelpContainer li, |
div.MenuHelpContainer li { |
margin: 4px 8px 4px 10px; |
} |
#bodyMasonSql.claro div.BodyHelpContainer { |
margin: 5px; |
} |
div.BodyHelpContainer p,h1,h2,h3,h4,h5,h6 { |
margin-left: 4px; |
padding-left: 4px; |
} |
div.MenuHelpContainer a:hover, |
div.BodyHelpContainer a:hover { |
background-color: #D5D0F0; |
} |
%# Riga selezionata quale padre delle tabelle figlie associate |
.selectRowFather { |
background-color: #6699CC; |
} |
%# Barra di intestazione di testata e dettaglio |
table.FormHeader { |
width:100%; |
border: 0; |
background-color:#E5E5E5; |
margin:1; |
padding:0; |
} |
.FormHeader td { |
font-size: 0.9em; |
} |
.FormHeader .record_info { |
width:150px; |
} |
%# DA VERIFICARE |
%# #bodyMasonSql.claro .ChildFormHeader, #bodyMasonSql.claro .FatherFormHeader { |
%# background-color: red; |
%# } |
div.FormHeaderDescription { |
white-space: normal; |
height: 22px; |
line-height: 11px; |
text-align: center; |
font-size: 0.95em; |
display: block; |
overflow: hidden; |
} |
%# ----- Layout ----- |
#bodyMasonSql.claro .dijitContentPane { |
padding: 0; |
margin: 0; |
background-color: #FAFAFA; |
} |
#bodyMasonSql.claro .dijitContentPane.FatherForm, #bodyMasonSql.claro .dijitContentPane.ChildForm { |
padding: 4px; |
} |
#bodyMasonSql.claro .ChildrenContainer { |
%# background-color: #F4F4F4; |
} |
%# in fondo alla finestra principale |
%#bodyMasonSql.claro .dijitContentPane |
#bodyMasonSql.claro #BottomContent { |
background-color: #F0F0F0; |
} |
#bodyMasonSql.claro .dijitSplitterV { |
background: none repeat scroll 0 0 #E5E5E5; |
width: 3px; |
} |
#bodyMasonSql.claro .dijitSplitterH { |
background: none repeat scroll 0 0 #E5E5E5; |
height: 3px; |
} |
#bodyMasonSql.claro .dijitSplitterVHover, #bodyMasonSql.claro .dijitSplitterHHover { |
background: none repeat scroll 0 0 #C9C9C9; |
} |
%# Bottoni di controllo (vedi dbms_library.comp:CONTROLS) |
#bodyMasonSql.claro .controlBtn.dijitButton { |
margin: 1px; |
} |
#bodyMasonSql.claro .controlBtn .dijitButtonNode { |
padding: 1px; |
margin:0; |
} |
#bodyMasonSql.claro .controlBtn .dijitButtonText { |
padding: 0px 0px 0px 1px; |
line-height: 9pt; |
letter-spacing:-0.4pt; |
} |
#bodyMasonSql.claro .controlBtn .dijitButtonText input { |
font-size: 0.9em; |
} |
%# Bug height in Firefox textarea |
textarea { |
overflow-x: hidden; |
} |
#bodyMasonSql.claro .recordDetailBtn { |
font-size: 0.75em; |
} |
#bodyMasonSql.claro .dijitTooltipContainer { |
padding: 1px; |
} |
#bodyMasonSql.claro .dijitCalendarEnabledDate { |
font-weight: lighter; |
} |
#bodyMasonSql.claro .dijitCalendarDateLabel { |
padding: 1px 4px 0 0; |
} |
#bodyMasonSql.claro .dijitTabChecked { |
background-color: #6699cc; |
} |
#bodyMasonSql.claro .dijitDialog { |
background-color: #ffffff; |
resize: both; |
overflow: auto; |
} |
table.FORM_form { |
border-style: none; |
margin: 0px; |
} |
table.FORM_form tr { |
line-height: 16px; |
} |
table.FORM_form td { |
padding: 0px; |
spacing: 0px; |
} |
table.TABLE_group { |
border-style: none; |
margin: 0px; |
} |
table.TABLE_group tr { |
} |
table.TABLE_group td { |
padding: 0px; |
spacing: 0px; |
} |
table.TABLE_form { |
border-style: none; |
margin: 0px; |
} |
table.TABLE_form tr { |
line-height: 16px; |
} |
table.TABLE_form td { |
padding: 0px; |
spacing: 0px; |
text-align: center; |
} |
table.TABLE_form th { |
text-align: center; |
padding: 0px; |
spacing: 0px; |
} |
tr.ROW_TABLE_D { |
%# background-color: #f9f9f9; |
} |
tr.ROW_TABLE_P { |
%# background-color: #eeeeee; |
} |
%# selezione del record |
td.ROW_TABLE_Sel, span.ROW_DIVS_Sel { |
width: 35px; |
text-align: left; |
font-size: 0.72em; |
} |
%# Copy&Paste classes |
#bodyMasonSql.claro .WidgetToCopy { |
border: 1px solid red; |
} |
#bodyMasonSql.claro .WidgetPasted { |
border: 1px solid #316ac5; |
} |
table.LINEAR_form { |
border-style: none; |
margin: 0px; |
} |
table.LINEAR_form tr { |
} |
table.LINEAR_form td { |
padding: 0px; |
spacing: 0px; |
} |
table.FIND_form { |
border-style: none; |
margin: 0px; |
width: 100%; |
border: 0px; |
} |
table.FIND_form tr { |
line-height: 16px; |
} |
table.FIND_form td { |
padding: 0px; |
spacing: 0px; |
} |
table.FIND_MENU_form { |
border-style: none; |
margin: 0px; |
border: 0px; |
} |
table.FIND_MENU_form tr { |
line-height: 16px; |
} |
table.FIND_MENU_form td { |
padding: 0px; |
spacing: 0px; |
} |
%##### pageOverlay (usato per nascondere il rendering delle pagine Dojo durante il caricamento) |
.pageOverlay { |
top: 0; |
left: 0; |
position: absolute; |
height: 100%; |
width: 100%; |
z-index: 1001; |
display: block; |
} |
.loadingOverlay { |
background: #fff url('<% $Session{'Dojo_dir'} %>/dijit/themes/claro/images/loadingAnimation.gif') no-repeat 10px 23px; |
} |
.loadingMessage { |
padding: 25px 40px; |
color: #999; |
} |
%################################ CSS per manuale database |
p.w3ref { |
font-size: 0.8em; |
font-style: italic; |
text-align: right; |
} |
p.detail { |
font-size: 0.9em; |
} |
.error { |
color: #FFFFFF; |
background-color: #FF0000; |
} |
ul.topic { |
list-style-type: upper-alpha; |
} |
li.topic { |
font-weight : bold; |
} |
tr.tr0 { |
background-color: #F0F0F0; |
} |
tr.tr1 { |
background-color: #D8D8D8; |
} |
td.col0 { |
font-weight : bold; |
width: 20%; |
} |
td.col1 { |
font-style: italic; |
width: 15%; |
} |
td.col2 { |
font-size: 1em; |
} |
%#END. |
/tags/2.0/htdocs/css/input.css |
---|
0,0 → 1,226 |
%# richiamata da /input/input.comp |
.nowrap { |
white-space: nowrap; |
} |
%# pulsanti barra in bottom.html |
input.bottom { |
font-size: 9pt; |
} |
button, input.button { |
height: 15pt; |
font-size: 9pt; |
background-color: #BCD8F4; |
background-image: linear-gradient(#FFFFFF 0px, rgba(255, 255, 255, 0) 3px, rgba(255, 255, 255, 0.75) 100%); |
background-repeat: repeat-x; |
border: 1px solid #759DC0; |
border-radius: 4px 4px 4px 4px; |
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15); |
color: #000000; |
} |
button:disabled, input.button:disabled { |
background-color: #D3D3D3; |
} |
button:hover:enabled, input.button:hover:enabled { |
background-color: #86BDF2; |
color: #000000; |
transition-duration: 0.2s; |
} |
button:active:enabled, input.button:active:enabled { |
background-color: #BCD8F4; |
} |
input.file { |
border: 1px solid #BABABA; |
height: 13pt; |
background-color: #ffffff; |
} |
.UrlComp { |
font-size: 0.86em; |
} |
input.radio { |
} |
select { |
border: 1px solid #BABABA; |
height: 13pt; |
background-color: #ffffff; |
} |
span.checkbox { |
border: 2px solid #BABABA; |
border-right-width: 1px; |
border-bottom-width: 1px; |
padding-top: 3px; |
padding-bottom: 0px; |
} |
input.time { |
width: 35px; |
text-align: center; |
} |
input.color { |
width: 67px; |
} |
input.date { |
width: 65px; |
} |
.masonSqlIcons.vAlign { |
vertical-align: bottom; |
} |
input.string { |
} |
input.numberRo { |
text-align: right; |
} |
textarea.text { |
} |
span.inputspan_c { |
border: 1px solid #BABABA; |
border-right-width: 1px; |
border-bottom-width: 1px; |
display: -moz-inline-box; |
display: inline-block; |
vertical-align: bottom; |
white-space: nowrap; |
overflow: hidden; |
} |
span.widget_span { |
padding: 0; |
margin: 0; |
display: inline-block; |
border: 1px solid transparent; |
text-align:left; |
} |
span.inputspan { |
border: 1px solid #BABABA; |
border-right-width: 1px; |
border-bottom-width: 1px; |
display: -moz-inline-box; |
display: inline-block; |
vertical-align: bottom; |
overflow: hidden; |
white-space: nowrap; |
} |
span.Files { |
border: 1px solid #BABABA; |
border-right-width: 1px; |
border-bottom-width: 1px; |
display: -moz-inline-box; |
display: inline-block; |
overflow: hidden; |
white-space: nowrap; |
} |
span.container { |
display: inline-block; |
vertical-align: bottom; |
white-space: nowrap; |
margin: 0px; |
border: 0px; |
background-color: transparent; |
} |
div.container { |
margin: 0px; |
border: 0px; |
background-color: transparent; |
} |
div.inputdiv { |
border: 1px solid #BABABA; |
border-right-width: 1px; |
border-bottom-width: 1px; |
overflow: auto; |
} |
.claro .widget { |
color: #000000; |
border: 1px solid #BABABA; |
font: 1em Calibri,Arial,Helvetica,Verdana; |
} |
.claro .widgetRo { |
background-color: #FFFFFF; |
} |
.claro .widgetRw { |
%# Giallo chiaro |
background-color: #FAFADC; |
} |
.claro .widgetRw:focus, .claro .widgetRwFocus { |
%# Giallo-verde chiaro |
background-color: #F5FADC; |
} |
.claro .widgetRoError { |
background-color: #FFF4F4; |
} |
.claro .widgetRwError { |
background-color: #FFBFBA; |
} |
.claro .widgetRwError:focus, .claro .widgetRwErrorFocus { |
background-color: #FFB4B4; |
} |
.claro .widgetRoRequired { |
background-color: #FFFFFF; |
} |
.claro .widgetRwRequired { |
%# Arancio chiaro |
background-color: #FEF5EA; |
} |
.claro .widgetRwRequired:focus, .widgetRwRequiredFocus { |
background-color: #F9F5EA; |
} |
.claro .widgetRoWait { |
background-color: #F0F0F0; |
} |
.claro .widgetRwWait { |
background-color: #D0D0D0; |
} |
%#Files.comp |
#bodyMasonSql.claro .Files_tree .dijitTreeRowSelected.dijitTreeRowHover { |
background-color: #cfe5fa; |
background-image: url("images/standardGradient.png"); |
background-image: -moz-linear-gradient(rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%); |
background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%); |
background-image: -o-linear-gradient(rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%); |
background-image: linear-gradient(rgba(255, 255, 255, 0.7) 0%, rgba(255, 255, 255, 0) 100%); |
border-color: #759dc0; |
} |
#bodyMasonSql.claro .Files_tree .dijitTreeRowHover { |
background-image: none; |
background-color: rgba(171, 214, 255, 0); |
} |
table.Files_table_history { |
border-collapse:collapse; |
} |
table.Files_table_history td { |
border: 1px solid #a0a0a0; |
} |
table.Files_table_history th { |
background-color: #e9e9e9; |
} |
tr.Files_current { |
font-weight: bold; |
} |
td.Files_alert { |
font-color: red; |
font-weight: bold; |
} |
button.Files_button { |
font-size:0.7em; |
margin: 0; |
padding: 0; |
} |
/tags/2.0/htdocs/css/divselectpopup.css |
---|
0,0 → 1,104 |
tr.DivSelect_Pari { |
background-color: #ffffff; |
} |
tr.DivSelect_Dispari { |
background-color: #f9f9f9; |
} |
tr.DivSelect { |
} |
tr.DivSelect_Pari_Hover, tr.DivSelect_Dispari_Hover { |
background-color: #E4EEF3; |
} |
tr.DivSelect_Pari_Selected, tr.DivSelect_Dispari_Selected { |
background-color: #BFD1DB; |
} |
tr.DivSelect_Pari_Selected_Hover, tr.DivSelect_Dispari_Selected_Hover { |
background-color: #B1C2CB; |
} |
td.DivSelect_Head { |
text-align: center; |
font-size: 0.94em; |
white-space: nowrap; |
} |
td.DivSelect_Column { |
margin-left: 1; |
margin-right: 1; |
font-size: 0.94em; |
white-space: nowrap; |
overflow: hidden; |
} |
td.DivSelect_Detail { |
background-color: #ececec; |
padding: 0; |
margin: 0; |
width: 28px; |
white-space: nowrap; |
overflow: hidden; |
} |
button.DivSelect_Detail { |
margin: 0; |
padding: 0; |
height: 13px; |
font-size: 0.7em; |
} |
div.DivSelect_Container { |
margin: 0px; |
background-color: #ececec; |
display: inline-block; |
white-space: nowrap; |
%# overflow-y: hidden; |
%# overflow-x: hidden; |
padding-right: 4px; |
} |
div.DivSelect_ButtonsContainer { |
white-space: normal; |
} |
div.DivSelect_TableContainer { |
padding-top: 3; |
float: left; |
height: 100; |
margin: 0px; |
border-style: none; |
overflow: auto; |
background-color: #ececec; |
} |
span.DivSelect_Info { |
line-height: 26px; |
} |
table.DivSelect_Table { |
table-layout:fixed; |
width:0; |
} |
div.DivSelect_Cursor { |
background-color: #ececec; |
margin: 0px; |
border-style: none; |
overflow: auto; |
width: 19px; |
} |
div.DivSelect_CursorContent { |
margin: 0px; |
border-style: none; |
width: 1; |
height: 1000px; |
} |
input.DivSelect_TextFilter { |
background-color: #fafadc; |
font-size: 0.96em; |
width: 100%; |
} |
span.DivSelectButton { |
border: 1px outset; |
margin-left: 1px; |
margin-right: 1px; |
border-color: #dfcdcf; |
background-color: #dfdddf; |
padding-left: 2px; |
padding-right: 2px; |
cursor: pointer; |
} |
span.DivSelectButton:hover { |
background-color: #dfddbf; |
} |
/tags/2.0/htdocs/css/htmlselectpopup.css |
---|
0,0 → 1,26 |
div.htmlselect_Body { |
display: -moz-inline-box; |
display: inline-block; |
white-space: nowrap; |
overflow-y: scroll; |
overflow-x: hidden; |
padding-right: 4px; |
} |
div.htmlselect_P, div.htmlselect_D { |
cursor:pointer; |
} |
div.htmlselect_P { |
background-color: #ffffff; |
} |
div.htmlselect_D { |
background-color:#f9f9f9; |
} |
div.htmlselect_hover { |
background-color:#E4EEF3; |
} |
div.htmlselect_selected { |
background-color:#BFD1DB; |
} |
/tags/2.0/htdocs/css/autohandler |
---|
0,0 → 1,22 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%attr> |
Cache_MaxAge => 12*60*60 |
</%attr> |
<%perl> |
$Session{'Dojo_dir'} = $JSLogger->level() eq $DEBUG ? $r->dir_config('DojoDirUrlDebug') : $r->dir_config('DojoDirUrl'); |
$r->headers_out->{'Cache-Control'} = 'max-age='.$m->base_comp->attr('Cache_MaxAge'); |
$r->content_type('text/css'); |
$m->call_next; |
</%perl> |
<%flags> |
inherit => '/library.comp' |
</%flags> |
/tags/2.0/htdocs/css/icons_controls.css |
---|
0,0 → 1,44 |
%#// Source: http://art.gnome.org/download/themes/icon/1150/ICON-UnofficialTango.tar.bz2 |
%#// Copyright: CC BY-SA |
%#// Author: "Jones Lee" <joneslee85@gmail.com> |
%#// |
%#// Generated with: http://www.instantsprite.com/ with params: Offset:0 Direction:horizontal FileType:png |
%#// |
%#// Usare con: <div class='sprite address-book-new'></div> |
%#// |
.masonSqlIcons { background: url('icons_controls.png') no-repeat top left; width: 16px; height: 16px;} |
.dijitDisabled .masonSqlIcons { background: url('icons_controlsDisabled.png') no-repeat top left; width: 16px; height: 16px; } |
.dijitDisabled.masonSqlIcons { background: url('icons_controlsDisabled.png') no-repeat top left; width: 16px; height: 16px; } |
.masonSqlIcons :disabled { background: url('icons_controlsDisabled.png') no-repeat top left; width: 16px; height: 16px; } |
%#// Position of single images |
.masonSqlIcons.calendar { background-position: 0px 0px; } |
.masonSqlIcons.cancel { background-position: -17px 0px; } |
.masonSqlIcons.change { background-position: -34px 0px; } |
.masonSqlIcons.delete { background-position: -51px 0px; } |
.masonSqlIcons.down { background-position: -68px 0px; } |
.masonSqlIcons.dup { background-position: -85px 0px; } |
.masonSqlIcons.find { background-position: -102px 0px; } |
.masonSqlIcons.forward { background-position: -119px 0px; } |
.masonSqlIcons.goto { background-position: -136px 0px; } |
.masonSqlIcons.groups { background-position: -153px 0px; } |
.masonSqlIcons.help { background-position: -170px 0px; } |
.masonSqlIcons.home { background-position: -187px 0px; } |
.masonSqlIcons.insert { background-position: -204px 0px; } |
.masonSqlIcons.labels { background-position: -221px 0px; } |
.masonSqlIcons.log { background-position: -238px 0px; } |
.masonSqlIcons.logout { background-position: -255px 0px; } |
.masonSqlIcons.messages { background-position: -272px 0px; } |
.masonSqlIcons.password { background-position: -289px 0px; } |
.masonSqlIcons.preferences { background-position: -306px 0px; } |
.masonSqlIcons.print { background-position: -323px 0px; } |
.masonSqlIcons.refresh { background-position: -340px 0px; } |
.masonSqlIcons.rewind { background-position: -357px 0px; } |
.masonSqlIcons.run { background-position: -374px 0px; } |
.masonSqlIcons.save { background-position: -391px 0px; } |
.masonSqlIcons.up { background-position: -408px 0px; } |
.masonSqlIcons.users { background-position: -425px 0px; } |
.masonSqlIcons.xls { background-position: -442px 0px; } |
.masonSqlIcons.zip { background-position: -459px 0px; } |
/tags/2.0/htdocs/css/icons_controls/pallet_ro.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/pallet_rw.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/print.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/refresh.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/save.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/users.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/preferences.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/delete.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/zip.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/password.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/labels.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/insert.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/forward.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/run.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/xls.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/down.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/messages.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/goto.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/logout.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/calendar.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/groups.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/find.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/log.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/up.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/cancel.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/change.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/rewind.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/home.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/dup.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controls/help.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/ColorPicker.css |
---|
0,0 → 1,37 |
.tundra .dojoxColorPicker:hover { |
background:#c8e4ff; |
border:1px solid #ccc; |
} |
.tundra .dojoxColorPicker { |
background:#e0ecfb; |
border:1px solid #ccc; |
} |
.claro .dojoxColorPicker:hover { |
background:#c8e4ff; |
border:1px solid #cdcdcd; |
} |
.claro .dojoxColorPicker { |
background:#e0ecfb; |
border:1px solid #cdcdcd; |
} |
.masonSqlIcons.pallet { background-position: 0px 0px; |
background-image: url('icons_controls/pallet_rw.png'); |
} |
.dijitDisabled .masonSqlIcons.pallet { |
background-image: url('icons_controls/pallet_ro.png'); |
no-repeat top left; |
width: 16px; |
height: 16px; |
} |
.dijitDisabled.masonSqlIcons.pallet { |
background-image: url('icons_controls/pallet_ro.png'); |
no-repeat top left; |
width: 16px; |
height: 16px; |
} |
.masonSqlIcons.pallet :disabled { |
background-image: url('icons_controls/pallet_ro.png'); |
no-repeat top left; |
width: 16px; |
height: 16px; |
} |
/tags/2.0/htdocs/css/main.css |
---|
0,0 → 1,8 |
<& /css/base.css &> |
<& /css/base.application.css &> |
<& /css/input.css &> |
<& /css/input.application.css &> |
<& /css/icons_controls.css &> |
<& /css/htmlselectpopup.css &> |
<& /css/divselectpopup.css &> |
<& /css/ColorPicker.css &> |
/tags/2.0/htdocs/css/icons_controls.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/menuarrow.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_actionsDisabled.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/icons_controlsDisabled.png |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/css/base.application.css |
---|
/tags/2.0/htdocs/css/menu.application.css |
---|
--- 2.0/htdocs/input/divselect.js (nonexistent) |
+++ 2.0/htdocs/input/divselect.js (revision 806) |
@@ -0,0 +1,795 @@ |
+<%doc> |
+# ---------------------------------------------------------------------- # |
+# Copyright:2002-2013 Leader.IT di Guido Brugnara <http://www.leader.it> |
+# Strada della Pozzata, 41 - Villazzano |
+# 38123 T R E N T O (ITALY) |
+# Authors: Guido Brugnara <gdo@leader.it> |
+# |
+# $Revision: $ info@leader.it |
+# ---------------------------------------------------------------------- # |
+</%doc> |
+function Input_DivSelect_set_value(value, param){ |
+ if(value == null){ |
+ value = this.Empty; |
+ } |
+ this.value = value; |
+ // parametro dato nel formato "descrizione|parametri...\n.....\n...." |
+ if(param != null){ |
+ this.set_param(param, null, value); |
+ }else{ |
+ if(value != this.Empty && this.Source){ |
+ // verifico la presenza nella cache |
+ var cache_param = this.Cache_parameters && this.Cache_parameters[value]; |
+ if(cache_param == null){ |
+ // richiedo il valore al server |
+ // hReqMason_ExecuteTimeout(rspage, timeout, timeout_callback, callback, func, parms, tag, obj_params, callback_obj) |
+ hReqMason_ExecuteTimeout( |
+ this.Source, |
+ <%$r->dir_config('GetRecordTimeout')%>, |
+ Input_DivSelect_TimeoutData, |
+ Input_DivSelect_Load_Callback, |
+ 'parameters_select', |
+ ['key', value], |
+ null, |
+ null, |
+ this |
+ ); |
+ this.set_param(null, null, value); |
+ }else{ |
+ this.set_param(cache_param); |
+ } |
+ }else{ |
+ this.set_param(null); |
+ } |
+ } |
+} |
+ |
+// Handler risposta in caso di errore o timeout |
+function Input_DivSelect_TimeoutData(contextID, type, str, Obj){ |
+ if(type == 'TIMEOUT'){ |
+ my_alert('Timeout caricamento parametri ' + Obj.id); |
+ }else{ |
+ my_alert('ERRORE caricamento parametri ' + Obj.id + ' url=' +this.contextObj.URL+': \n['+str+']'); |
+ } |
+} |
+ |
+// Handler risposta caricamento dinamico dei parametri |
+function Input_DivSelect_Load_Callback(str, contextID, Obj){ |
+ str = str.replace(/^\s+|\s+$/g, ''); |
+ Obj.set_param(str, null, Obj.get_value()); |
+ if(Obj.onloadremoteparam){ |
+ Obj.onloadremoteparam(); |
+ } |
+} |
+ |
+function Input_DivSelect_get_value(value){ |
+ return this.value; |
+} |
+ |
+function Input_DivSelect_Init(Objname, Id_Descr, from, Where, OrderBy, Insert_descr, Insert_parameters, Insert_copyfields, Empty, EmptyDescr, EmptyButton, |
+ Descr, Read, Rows, Cols, Buttons, DispTemplate, Query_param, Cache_params, Detail_from, Detail_width, Detail_height, Detail_father, Class){ |
+ var Obj = Input_Init(Objname, Descr); |
+ Obj.icon = document.getElementById('icon_' + Objname); |
+ Obj.value = null; |
+ Obj.from = from; //Nome del file da caricare (senza .mql) |
+ Obj.Source = '<%$r->dir_config('DataBaseUrl')%>/'+Obj.from+'.mql'; |
+ Obj.DisplayDescr = Input_Init('display_'+Objname, Descr); |
+ if(Id_Descr == '')Id_Descr = null; |
+ Obj.Id_Descr = Id_Descr; |
+ Obj.set_status = function(status){ |
+ var classList = this.eval_status(status); |
+ // non applico la variazione della lista delle classi se non cambia |
+ if(this.DisplayDescr.className != classList){ |
+ this.DisplayDescr.className = classList; |
+ } |
+ } |
+ Obj.Readonly = function (set) { |
+ if(set == null){ |
+ return this.readOnly; |
+ }else{ |
+ this.style.cursor = set ? 'default' : 'pointer'; |
+ this.readOnly = set; |
+ this.set_status(); |
+ var icon = this.icon; |
+ require(["dojo/dom-class"], function(domClass){ |
+ if(icon){ |
+ domClass[set ? 'add' : 'remove'](icon, 'dijitDisabled'); |
+ } |
+ }); |
+ return set; |
+ } |
+ } |
+ Obj.Where = Where; |
+ Obj.OrderBy = OrderBy; |
+ Obj.Insert_descr = Insert_descr; |
+ Obj.Insert_parameters = Insert_parameters; |
+ Obj.Insert_copyfields = Insert_copyfields; |
+ Obj.Empty = Empty; |
+ Obj.EmptyDescr = EmptyDescr; |
+ Obj.EmptyButton = EmptyButton; |
+ Obj.Rows = Rows; |
+ Obj.Cols = Cols; |
+ Obj.Buttons = Buttons; |
+ Obj.DispTemplate = DispTemplate; |
+ Obj.Query_param = Query_param; |
+ Obj.Editing = false; |
+ Obj.get_value = Input_DivSelect_get_value; |
+ Obj.set_value = Input_DivSelect_set_value; |
+ Obj.ListEqualBuffer = null; |
+ Obj.Previus = Obj.get_value(); |
+ Obj.Readonly(Read); |
+ Obj.Parameters = null; |
+ if(Cache_params){ |
+ Obj.Cache_parameters = {}; //cache dei parametri corrispondenti ai valori presenti nella lista |
+ } |
+ Obj.Detail_from = Detail_from; |
+ Obj.Detail_width = Detail_width; |
+ Obj.Detail_height = Detail_height; |
+ Obj.Detail_father = Detail_father; |
+ Obj.Class = Class; |
+ Obj.setFocus = null; |
+ // inizializzo dijit/TooltipDialog |
+ Input_DivSelect_initPopup(); |
+ return Obj; |
+} |
+ |
+// Visualizza un form di dettaglio del record selezionato |
+function Input_DivSelect_PopupDetail(mode, num_row, params){ |
+ // Obj è il widget |
+ var Obj = Input_DivSelect_Popup.Input; |
+ // apro una finestra con il dettaglio del record selezionato |
+ // costruisco un oggetto 'display' minimale con i soli elementi necessari a lanciare il form (vedi file ../lib/displaybinding.js ) |
+ var display = { |
+ prefix: Obj.id, |
+ dataBinding: Input_DivSelect_Popup.dataBinding, |
+ gotoRecords: function (mode, key, recordset){ |
+ return this.dataBinding.gotoRecords(mode, key, recordset); |
+ }, |
+ openFormDetail: DisplayBinding_openFormDetail, |
+ openFormDetailByKey: DisplayBinding_openFormDetailByKey, |
+ onclosedetail: function(save){ |
+%# // riapro il popup quando si chiude il form di dettaglio |
+ Input_DivSelect_open_list(this.prefix); |
+ } |
+ }; |
+ display.openFormDetail(mode, num_row, Obj.Detail_from || Obj.from, Obj.Detail_width, Obj.Detail_height, Obj.Descr, params); |
+} |
+ |
+// Richiamato al click di una riga dell'elenco |
+function Input_DivSelect_PopupHandler(num_row){ |
+ var dataBinding = Input_DivSelect_Popup.dataBinding; |
+ dataBinding.statusDownload(true); // interrompo l'eventuale recordset in arrivo |
+ var value; |
+ var param_list; |
+ if(num_row == null){ |
+ value=''; |
+ }else{ |
+ if(dataBinding.keys[num_row] == null){ |
+ // la riga scelta non contiene dati del recordset: ignoro |
+ return false; |
+ } |
+ param_list = dataBinding.data[num_row]; |
+ value = dataBinding.keys[num_row]; |
+%#//DEBUG alert('Selezionata riga '+num_row+'\ndi contenuto 1° colonna:' + value + ' param_list=' + param_list.join('|')); |
+ // test validità della selezione |
+ } |
+ // Obj è il widget |
+ var Obj = Input_DivSelect_Popup.Input; |
+ if(Obj.get_value() != value){ |
+ // ho un effettivo cambio del valore del widget |
+ Obj.set_value(value, param_list); |
+ window.setTimeout("document.getElementById('"+Obj.id+"').test_value()",1); |
+ Input_DivSelect_Popup.hidePopup(); |
+ if(Obj.onchange){ |
+ Obj.onchange(); |
+ } |
+ }else{ |
+ Input_DivSelect_Popup.hidePopup(); |
+ } |
+} |
+ |
+function Input_DivSelect_emptyRecordset(wait){ |
+ // .isEmpty è usata per evitare continui aggiornamenti con i campi vuoti (lampeggio) |
+ if(!this.isEmpty){ |
+ var rows = this.Table.tBodies[0].rows; |
+ // tolgo la precedente impostazione |
+ if(this.row_current != null){ |
+ rows[this.row_current].style.backgroundColor = ''; // tolgo il colore di sfondo |
+ this.row_current = null; |
+ } |
+ this.DivContainer.style.cursor = wait ? 'wait' : 'default'; |
+ for(var row=0; row<rows.length; row++){ |
+ var Row = rows[row]; |
+ Row.cells[0].firstChild.style.display = 'none'; |
+ Row.onmouseover = Row.onmouseout = null; |
+ var cols = Row.getElementsByTagName('td'); |
+ Row.style.cursor = wait ? 'wait' : 'default'; |
+ for(var col=1; col<cols.length; col++){ |
+ cols[col].innerHTML = ' '; |
+ } |
+ } |
+ } |
+ this.isEmpty = true; |
+} |
+ |
+// ridimensionamento del componente |
+function Input_DivSelect_rescaleDisplay(){ |
+ var db = this.dataBinding; |
+ // se il primo recordset è stato caricato |
+ if(db.max_rows != null){ |
+ // dimensionamento del cursore proporzionale alle righe del recordset |
+ this.DivCursorContent.style.height = Math.floor(db.max_rows / db.max_table_rows * this.DivCursor.offsetHeight).toString() + 'px'; |
+ } |
+ // dimensiono l'altezza per contenere tutta la tabella |
+ this.TableContainer.style.height = '1px'; // altrimenti in Moz./Firefox la finestra si allarga ad ogni click |
+ var height_px = (this.TableContainer.scrollHeight).toString() + 'px'; |
+ this.TableContainer.style.height = height_px |
+ this.DivCursor.style.height = height_px; |
+ // set dimensions larger, so the browser can remove cursors and recalculate dimensions |
+ this.DivContainer.style.height = (this.TableContainer.scrollHeight + 30).toString() + 'px'; |
+ this.TableContainer.style.width = (this.Table.scrollWidth + 10).toString() + 'px';; |
+ // set dimensions near limits |
+ this.DivContainer.style.height = (this.ButtonsContainer.scrollHeight + this.TableContainer.scrollHeight + 2).toString() + 'px'; |
+ // con 2 (anziché 15) è ok in Firefox |
+ this.TableContainer.style.width = (this.Table.scrollWidth + 15).toString() + 'px'; |
+ // set larghezza del contenitore, che adatta perfettamente all'occupazione in larghezza dell'oggetto |
+ // contenuto comprensiva dello spazio occupato dal cursore |
+ this.DivContainer.style.width = (this.TableContainer.offsetWidth+this.DivCursor.offsetWidth).toString() + 'px'; |
+ // riposiziono il cursore |
+ var new_scrollTop = Math.round(this.start * this.DivCursor.scrollHeight / this.dataBinding.max_rows); |
+ // my_alert('start='+this.start+' scrollHeight='+this.DivCursor.scrollHeight+' max_rows='+this.dataBinding.max_rows+'\ncambio da '+this.DivCursor.scrollTop+' new_scrollTop='+new_scrollTop); |
+ // stringo lo spazio che inizialmente ho dovuto mantenere più largo (15) perché con Chrome si deve tener contro dello scroll laterale che poi non è visibile |
+ this.TableContainer.style.width = (this.Table.scrollWidth + 2).toString() + 'px'; |
+ this.DivContainer.style.width = (this.TableContainer.offsetWidth+this.DivCursor.offsetWidth).toString() + 'px'; |
+ if(new_scrollTop != this.DivCursor.scrollTop){ |
+ // ignoro l'evento provocato dall'aggiustamento |
+ this.DivCursor.ignore_onscroll = true; |
+ // cambio ... |
+ this.DivCursor.scrollTop = new_scrollTop; |
+ // tolgo il flag dopo un po' di tempo |
+ window.setTimeout('Input_DivSelect_Popup.DivCursor.ignore_onscroll = false', 100); |
+ } |
+} |
+ |
+// inizializzazione dei componenti grafici visualizzati nel popup |
+function Input_DivSelect_initDisplay(Info, Table, Container, ButtonsContainer, TableContainer, Cursor, CursorContent){ |
+ // salvataggio dei vari oggetti grafici |
+ // this è l'oggetto dove viene visualizzato il widget |
+ this.Info = window.document.getElementById(Info); |
+ this.Table = window.document.getElementById(Table); |
+ this.DivContainer = window.document.getElementById(Container); |
+ this.ButtonsContainer = window.document.getElementById(ButtonsContainer); |
+ this.TableContainer = window.document.getElementById(TableContainer); |
+ this.DivCursor = window.document.getElementById(Cursor); |
+ this.DivCursor.old_scrollTop = this.DivCursor.scrollTop; // per calcolare le variazioni di posizione del cursore |
+ this.DivCursor.Popup = this; |
+ this.DivCursorContent = window.document.getElementById(CursorContent); |
+ |
+ this.TextFilters = []; |
+ // inizializzo i campi di input per la ricerca fulltext |
+ var cols = this.Table.tHead.rows[1].cells; |
+ for(var c=1; c<cols.length; c++){ |
+ // ricerco il primo elemento 'input' contenuto in <td/> |
+ var input_elem = cols[c].getElementsByTagName('input')[0]; |
+ // ad ogni variazione chiamo con timeout |
+ input_elem.onkeyup = function(){ |
+ Input_DivSelect_Popup.loadFilteredList(true); |
+ } |
+ // su cambiamento confermato (perdita di focus oppure con <CR>) |
+ input_elem.onchange = function(){ |
+ Input_DivSelect_Popup.loadFilteredList(false); |
+ } |
+ this.TextFilters.push(input_elem); |
+ } |
+ // diattivo se necessario la colonna dei bottoni per attivare i dettagli |
+ if(!this.Input.Detail_from){ |
+ var tHead = this.Table.tHead; |
+ tHead.rows[0].cells[0].style.display = 'none'; |
+ tHead.rows[1].cells[0].style.display = 'none'; |
+ var rows = this.Table.tBodies[0].rows; |
+ for(var row=0; row<rows.length; row++){ |
+ rows[row].cells[0].style.display = 'none'; |
+ } |
+ } |
+ |
+ // calcolo dimensioni documento cursore provvisoriamente a 10 volte il numero di righe visibili |
+ this.DivCursorContent.style.height = (this.DivCursor.offsetHeight * 10).toString() + 'px'; |
+ |
+ // ritardo in msec con cui aggiornare il recordset se si muove il cursore |
+ this.delayUpdate = 300; |
+ this.delayFilter = 300; |
+ |
+ // timer per gestire il ritardo con cui si aggiorna il recordset |
+ this.delayUpdateTimer; |
+ |
+ this.DivCursor.onclick = function(evt){ |
+ console.debug('DivCursor.onclick', evt, this); |
+ } |
+ |
+ // evento scroll del cursore |
+ var debounce_timer; |
+ this.DivCursor.onscroll = function(){ |
+ if(debounce_timer){ |
+ // annullo il precedente evento onscroll |
+ clearTimeout(debounce_timer) |
+ } |
+ var DivCursor = this; |
+ // attendo un po' prima di eseguire l'evento (debounce) |
+ debounce_timer = setTimeout(function(){ |
+ DivCursor.debounce_timer = null; |
+ if(DivCursor.ignore_onscroll){ |
+ DivCursor.ignore_onscroll = false; |
+ return false; |
+ } |
+ var Popup = DivCursor.Popup; |
+ var dataBinding = Popup.dataBinding; |
+ // ignoro l'evento se non è stato caricato completamente il primo recordset |
+ if(dataBinding.max_rows == null){ |
+ return false; |
+ } |
+ DivCursor.ignore_onscroll = true; |
+ // calcolo la nuova posizione del recordset |
+ var new_start = Math.round(DivCursor.scrollTop * dataBinding.max_rows / DivCursor.scrollHeight); |
+ if(new_start == Popup.start){ |
+ // ignoro l'evento se non cambia la posizione del recordset |
+ DivCursor.ignore_onscroll = false; |
+ return false; |
+ } |
+ // cancello il timer legato alla digitazione di caratteri di ricerca |
+ if(DivCursor.delayFilterTimer){ |
+ window.clearTimeout(DivCursor.delayFilterTimer); |
+ } |
+ // cancellando l'eventuale timer attivo |
+ if(Popup.delayUpdateTimer){ |
+ window.clearTimeout(Popup.delayUpdateTimer); |
+ Popup.delayUpdateTimer = null; |
+ } |
+ Popup.start = new_start; |
+%#//DEBUG my_alert('ccc='+DivCursor.ccc+' new start='+Popup.start+' scrollTop='+DivCursor.scrollTop+' scrollHeight='+DivCursor.scrollHeight+' max_rows='+dataBinding.max_rows); |
+ // ricalcolo la posizione esatta del cursore e lo riposiziono |
+ var new_scrollTop = Math.round(Popup.start * DivCursor.scrollHeight / dataBinding.max_rows); |
+ if(new_scrollTop != DivCursor.scrollTop){ |
+ DivCursor.scrollTop = new_scrollTop; |
+ } |
+%#//DEBUG my_alert('start='+Popup.start+' new scrollTop='+DivCursor.scrollTop+' scrollHeight='+DivCursor.scrollHeight+' max_rows='+dataBinding.max_rows); |
+ // visualizzo il range di righe selezionato |
+ Popup.updateInfo(Popup.start); |
+ // aggiorna report delle dimensioni |
+ var diff = Math.abs(DivCursor.old_scrollTop-DivCursor.scrollTop); |
+ DivCursor.old_scrollTop = DivCursor.scrollTop; |
+ // spostamento cursore: applico un ritardo |
+ if(Popup.start != dataBinding.start){ |
+%#//DEBUG my_alert('Input_DivSelect_initDisplay ccc='+DivCursor.ccc+' timer '+Popup.delayUpdate+' start='+Popup.start+' previus='+dataBinding.start); |
+ Popup.delayUpdateTimer = window.setTimeout("Input_DivSelect_Popup.dataBinding.gotoRecords(Input_DivSelect_Popup.start + 1);", Popup.delayUpdate); |
+ } |
+ DivCursor.ignore_onscroll = false; |
+ }, 60); // debounce_timer |
+ } //.onscroll |
+ |
+ // dimensionamento dei componenti e del popup (viene comunque richiamato ad ogni cambiamento dei dati visualizzati) |
+ this.rescaleDisplay(); |
+ // condizioni iniziali del recordset richiamato passando la chiave del record |
+ this.dataBinding.initRecordset('rewind', this.Input.get_value()); |
+} |
+ |
+// Template |
+require(['dojox/dtl/filter/strings', 'dojox/dtl/Context']); |
+%#DOJO1.8 dojo.require('dojox.dtl.filter.strings'); |
+%#DOJO1.8 dojo.require('dojox.dtl.Context'); |
+ |
+// filtro custom |
+%#// esempio di filtro: http://code.google.com/p/dools/source/browse/trunk/dools/docs/widget/_util.js |
+dojox.dtl.filter.strings.nbsp = function(value){ |
+ return value.replace(/\s/g, ' '); |
+}; |
+dojox.dtl.register.filters("dojox.dtl.filter", { |
+ "strings": ["nbsp"] |
+}); |
+ |
+// inizializzazione del componente popup utilizzato da divselect.comp |
+// viene anche inizializzato il dataBinding |
+function Input_DivSelect_initPopup(){ |
+ require(["dojo/ready", "dijit/TooltipDialog", "dijit/popup", "dojo/dom", "dojo/on", "dojo/_base/event"], function(ready, TooltipDialog, popup, dom, on, event){ |
+ ready(function(){ |
+ // oggetto dijit/TooltipDialog condiviso tra più componenti |
+ if(window.Input_DivSelect_Popup){ |
+ // da inizializzare una sola volta |
+ return; |
+ } |
+ var Popup = new TooltipDialog({ |
+ id: 'Input_DivSelect_Popup', |
+ onKeyUp: function(event){ |
+ if(event.keyCode == 27){ |
+ // chiudo se uso tasto <Esc> |
+ this.hidePopup(); |
+ } |
+ } |
+ }); |
+ window.Input_DivSelect_Popup = Popup; |
+ Popup.watch('focused', function(property_name, old_val, new_val){ |
+ if(!new_val){ |
+ // chiudo la lista se perdo il focus |
+ this.hidePopup(); |
+ } |
+ }); |
+ // inizializzazione recordset |
+ Popup.dataBinding = new DataBinding('Input_DivSelect_Popup_db', null, null); |
+ window.Input_DivSelect_Popup_db = Popup.dataBinding; |
+ // l'arrivo di nuove richieste annullano le precedenti |
+ Popup.dataBinding.delete_previus_req = true; |
+ |
+ // collego tra di loro i due oggetti |
+ Popup.dataBinding.Popup = Popup; |
+ |
+ // template dell'oggetto per il rendering del codice HTML |
+ Popup.templateObj = new dojox.dtl.Template('<% $m->scomp('.Input_DivSelect_template') |js%>'); |
+ |
+ // var usata per evitare continui aggiornamenti con i campi vuoti (lampeggio) |
+ Popup.isEmpty = false; |
+ |
+ // metodo per cancellare i dati contenuti nel popup |
+ Popup.emptyRecordset = Input_DivSelect_emptyRecordset; |
+ |
+ // metodo per inizializzare i componenti grafici nel popup |
+ Popup.initDisplay = Input_DivSelect_initDisplay; |
+ |
+ // metodo per ridisegnare i componenti grafici e popup |
+ Popup.rescaleDisplay = Input_DivSelect_rescaleDisplay; |
+ |
+ // chiamata quando inizia una richiesta di caricamento di un recordset |
+ Popup.dataBinding.onrequest = function (){ |
+ this.Popup.emptyRecordset(true); |
+ } |
+ |
+ Popup.dataBinding.onprechange = function (){ |
+ // ridimensiono i componenti ed il popup |
+ Input_DivSelect_Popup.rescaleDisplay(); |
+ }; |
+ |
+ // show Popup vicino al Widget (se null fa riferimento al Widget della chiamata corrente) |
+ Popup.showPopup = function(Widget){ |
+ popup.open({ |
+ popup: this, |
+ around: Widget, |
+ maxHeight: 'Infinity' |
+ }); |
+ // se cambia il widget di riferimento |
+ if(Widget != this.Widget){ |
+ // inizializzo il popup passando i nomi degli oggetti grafici |
+ this.Widget = Widget; |
+ this.initDisplay('DivSelect_Info', 'DivSelect_Table', 'DivSelect_Container', |
+ 'DivSelect_ButtonsContainer', 'DivSelect_TableContainer', 'DivSelect_Cursor', 'DivSelect_CursorContent'); |
+ // devo riaprire per ricalcolare la posizione del popup |
+ popup.open({ |
+ popup: this, |
+ around: Widget, |
+ maxHeight: 'Infinity' |
+ }); |
+ this.focus(); |
+ }else{ |
+ this.dataBinding.initRecordset('rewind', this.Input.get_value()); |
+ this.focus(); |
+ } |
+ }; |
+ |
+ // nasconde il Popup |
+ Popup.hidePopup = function(){ |
+ //interrompo eventuali download in corso |
+ this.dataBinding.statusDownload(true); |
+ popup.close(this); |
+ }; |
+ |
+ // chiamata quando il recordset richiesto è disponibile |
+ Popup.dataBinding.onchange = function (){ |
+ delayUpdateTimer = null; |
+ var Popup = this.Popup; |
+ // aggiorno lo stato |
+ Popup.start = this.start; |
+ Popup.updateInfo(this.start); |
+ var Id = Popup.Input.get_value(); // ID corrente |
+ // carico i dati in tabella |
+ var rows = Popup.Table.tBodies[0].rows; |
+ // tolgo la precedente impostazione |
+ if(Popup.row_current != null){ |
+ rows[Popup.row_current].style.backgroundColor = ''; // tolgo il colore di sfondo |
+ Popup.row_current = null; |
+ } |
+ Popup.DivContainer.style.cursor = 'default'; |
+ for(var row=0; row<this.rows; row++){ |
+ var Row = rows[row]; |
+ Row.style.cursor = 'default'; |
+ Row.onmouseover = function(){ |
+ this.className += '_Hover'; |
+ return true; |
+ } |
+ Row.onmouseout = function(){ |
+ this.className = this.className.replace(/_Hover$/, ''); |
+ return true; |
+ } |
+ // verifico se il record corrente corrisponde al campo corrente |
+ if(this.keys[row] == Id){ |
+ Popup.row_current = row; |
+ Row.isCurrent = true; |
+ // rendo visibile il record corrente della select |
+ if(Row.className.match(/_Selected/) == null){ |
+ Row.className += '_Selected'; |
+ } |
+ }else{ |
+ Row.className = Row.className.replace(/_Selected/m, ''); |
+ Row.isCurrent = false; |
+ } |
+ Row.cells[0].firstChild.style.display = ''; |
+ var cols = Row.getElementsByTagName('td'); |
+ for(var col=1; col<cols.length; col++){ |
+ var value = Popup.dataBinding.data[row][col-1]; |
+ cols[col].innerHTML = (value == '' || value == null) ? ' ' : value; |
+ } |
+ } |
+ // righe senza dati |
+ for(var row=this.rows; row<rows.length; row++){ |
+ var Row = rows[row]; |
+ Row.style.cursor = 'default'; |
+ Row.onmouseover = Row.onmouseout = null; |
+ Row.className = Row.className.replace(/_Selected/m, ''); |
+ Row.cells[0].firstChild.style.display = 'none'; |
+ var cols = Row.getElementsByTagName('td'); |
+ for(var col=1; col<cols.length; col++){ |
+ cols[col].innerHTML = ' '; |
+ } |
+ } |
+ // ridimensiono i componenti ed il popup |
+ window.setTimeout("window.setTimeout('Input_DivSelect_Popup.rescaleDisplay();', 50); Input_DivSelect_Popup.rescaleDisplay();", 20); |
+ Popup.isEmpty = false; |
+ } |
+ |
+ // richiamata da dataBinding quando si presenta un errore |
+ Popup.dataBinding.onerror = function (err, str){ |
+ this.Popup.emptyRecordset(false); |
+ if(err == 'TIMEOUT'){ |
+ my_alert('Timeout ricezione dati [' + this.prefix + ']\n il server potrebbe non essere raggiungibile.', 'txt'); |
+ }else{ |
+ my_alert(err + ': ' + str, 'txt'); |
+ } |
+ } |
+ |
+ // chiamata dopo la prima inizializzazione del recordset |
+ Popup.dataBinding.onload = function (){ |
+ // blocco la possibilità di modificare i dati |
+ this.canUpdate = this.canDelete = this.canInsert = false; |
+ // visualizzo le descrizioni dei campi |
+ var cols = this.Popup.Table.tHead.rows[0].cells; |
+ for(var c=1; c<cols.length; c++){ |
+ cols[c].innerHTML = '<b>' + this.descriptions[c-1] +'</b>'; |
+ } |
+ } |
+ |
+ // chiamata per aggiornare il filtro, in base al testo inserito |
+ // check == true se devo lanciare il timer di attesa |
+ Popup.loadFilteredList = function (check){ |
+%#//DEBUG my_alert('loadFilteredList ' + check); |
+ var db = this.dataBinding; |
+ // azzero eventuale timer attivo |
+ if(this.delayFilterTimer){ |
+ window.clearTimeout(this.delayFilterTimer); |
+ } |
+ if(check){ |
+ // il testo sta cambiando; attendo un certo lasso di tempo prima di |
+ // aggiornare il recordset in base ai nuovi parametri |
+ if(this.delayUpdateTimer){ |
+ window.clearTimeout(this.delayUpdateTimer); |
+ this.delayUpdateTimer = null; |
+ } |
+%#//DEBUG my_alert('loadFilteredList timer '+this.delayFilter); |
+ this.delayFilterTimer = window.setTimeout("Input_DivSelect_Popup.loadFilteredList(false);", this.delayFilter); |
+ return; |
+ } |
+ |
+ // provvedo ad inviare la richiesta di una nuova pagina |
+ var arr_where = []; |
+ var test; |
+ for(var I=0; I<this.TextFilters.length; I++){ |
+ var val = this.TextFilters[I].value; |
+ if(val.length > 0){ |
+ val = val.replace(/'/g, "\\'"); //" |
+ arr_where.push([db.names[I], '~*', val, 'text']); |
+ test = true; |
+ } |
+ } |
+ if(this.Input.Where){ |
+ arr_where.push(['--where-input', this.Input.Where]); |
+ test = true; |
+ } |
+ var json_where = test ? JSON.stringify(arr_where) : ''; |
+ |
+ // valuto se la condizione di ricerca è variata dalla precedente |
+ if(json_where != db.json_where || this.Input.Query_param != db.query_param){ |
+ db.query_param = this.Input.Query_param; |
+ db.json_where = json_where; |
+ this.start = 0; |
+ this.updateInfo(0); |
+ db.loadRecords('bottom'); |
+ } |
+ } |
+ |
+ // aggiorno lo stato del recordset nel display |
+ Popup.updateInfo = function (start){ |
+ var db = this.dataBinding; |
+ var max = start + db.max_table_rows; |
+ max = (max > db.max_rows) ? db.max_rows : max; |
+ this.Info.innerHTML = (start + 1) + '-' + max + '(' + db.max_rows + ')'; |
+ } |
+ |
+ // chiamata da editSingle_Handler se c'è un cambiamento |
+ // è possibile ridefinire l'handler nel caso si voglia cambiare il comportamento del widget |
+ Popup.onchangeSingle = function(key){ |
+ this.Input.set_value(key); |
+ this.hidePopup(); |
+ } |
+ |
+ // chiamata da lib/dbms_library.comp method:Input_DivSelect_Popup_EDIT_SINGLE |
+ Popup.editSingle_Handler = function(func, key, Recordset, Display){ |
+ if(func == 'save'){ |
+ // verifico se ci sono pendenti modifiche nei record figli |
+ if(Recordset.children){ |
+ for(var I = 0; I < Recordset.children.length; I++){ |
+ Recordset.children[I].readOnly(true, true); |
+ } |
+ } |
+ if(key){ |
+ // devo cambiare il valore |
+ // ATTENZIONE: codice ritardato, altrimenti XMLHttpRequest viene instanziato nella finestra che viene chiusa! |
+ window.setTimeout('Input_DivSelect_Popup.onchangeSingle("'+key+'")', 1); |
+ }else{ |
+ // si verifica quando è stato selezionato il pulsante con i dati non salvati e pertanto la chiave del record è nulla |
+ // predispongo la risposta al cambiamento verificando se c'è un record selezionabile |
+ Display.onchange = function () { |
+ var key = this.dataBinding.keys[0]; |
+ if(key){ |
+ // se effettivamente ho un record salvato cambio il valore nel campo del widget |
+ window.setTimeout('Input_DivSelect_Popup.onchangeSingle("'+key+'")', 1); |
+ window.setTimeout(' Input_DivSelect_Popup.PopupInsert.hidePopup();', 1); |
+ }else{ |
+ // chiudo il form e riapro il selettore |
+ window.setTimeout('Input_DivSelect_Popup.PopupInsert.hidePopup();',10); |
+ window.setTimeout('Input_DivSelect_Popup.popupWindow.focus();', 1); |
+ } |
+ } |
+ Display.loadRecords('save'); |
+ return; |
+ } |
+ }else{ |
+ // riapro il selettore |
+ window.setTimeout('Input_DivSelect_Popup.popupWindow.focus()', 1); |
+ } |
+ this.PopupInsert.hidePopup(); |
+ } |
+ |
+ // utilizzata per aprire il form di inserimento di un nuovo record del divselect corrente |
+ Popup.openInsert = function (){ |
+ // valori aggiuntivi da passare alla chiamata |
+ var url_params = {}; |
+ // valori forniti dalla chiamata che sovrascrivono quelli 'di default' |
+ var params = this.Input.Insert_parameters; |
+ for(var I=0; I<params.length; I+=2){ |
+ url_params[params[I]] = params[I+1]; |
+ } |
+ // copio dai campi filtro i campi compilati scelti e li passo al form di inserimento come valori iniziali |
+ var cols = this.Table.tHead.rows[1].cells; |
+ var copyfields = this.Input.Insert_copyfields; |
+ for(var c=1; c<cols.length; c++){ |
+ if(copyfields[c-1]){ |
+ // ricerco il primo elemento 'input' contenuto in <td/> |
+ var input_elem = cols[c].getElementsByTagName('input')[0]; |
+ if(input_elem.value != ''){ |
+ url_params['force_' + copyfields[c-1]] = input_elem.value; |
+ } |
+ } |
+ } |
+ Input_DivSelect_PopupDetail('insert', null, url_params); |
+ } |
+ }); |
+ }); |
+} |
+ |
+// apre la finestra per selezionare la lista |
+// richiamata dal widget quando viene selezionato dall'utente |
+function Input_DivSelect_open_list(id){ |
+ var Obj = document.getElementById(id); |
+ if(!Obj.Readonly()){ |
+ var Popup = Input_DivSelect_Popup; |
+ if(Popup.Input != Obj){ |
+ Popup.isEmpty = false; |
+ var dataBinding = Popup.dataBinding; |
+ // aggiorno il riferimento al recordset e righe del componente corrente |
+ dataBinding.from = Obj.from; |
+ // righe visibili |
+ dataBinding.max_table_rows = Obj.Rows; |
+ // clausola where (all'inizio con il solo filtro definito dalla chiamata del componente) |
+ dataBinding.json_where = JSON.stringify([['--where-input', Obj.Where]]); |
+ dataBinding.orderby = Obj.OrderBy; |
+ |
+ // parametri supplementali da inviare al server |
+ dataBinding.query_param = Obj.Query_param; |
+ Popup.Input = Obj; |
+ // preparo i dati per il template |
+ Obj._MODIFIERS = document._MODIFIERS; //eredito i modificatori per il parsing sull'oggetto Obj |
+ // purtroppo il motore del template non permette il loop su un array con incremento 2 |
+ Obj.Buttons_descr = []; |
+ Obj.Buttons_link = []; |
+ for(var I=0; I<Obj.Buttons.length; I+=2){ |
+ var J = Math.ceil(I/2); |
+ Obj.Buttons_descr[J] = Obj.Buttons[I]; |
+ Obj.Buttons_link[J] = Obj.Buttons[I+1]; |
+ } |
+ // purtroppo il motore del template non permette loop sull'incremento di una variabile |
+ Obj.Rows_array = new Array(Obj.Rows); |
+ for(var I=0; I<Obj.Rows; I++){ |
+ Obj.Rows_array[I] = I; |
+ } |
+ // riempio il popup con il codice HTML del template |
+ Popup.set('content', Popup.templateObj.render(new dojox.dtl.Context(Obj))); |
+ } |
+ if(Obj.Detail_father && Obj.displayBinding){ |
+ var db = Obj.displayBinding.dataBinding; |
+ // passo al recordset di selezione l'indicazione dell'ID del padre |
+ Popup.dataBinding.father_id = db.father_id; |
+ // e del record corrente |
+ Popup.dataBinding.child_id = db.keys[Obj.dbRow]; |
+ } |
+ Popup.showPopup(Obj); |
+ } |
+ return false; |
+} |
+%# template da utilizzare nel Popup |
+%# per la sintassi del template vedi https://docs.djangoproject.com/en/1.3/ref/templates/builtins/ |
+<%def .Input_DivSelect_template> |
+<div id="DivSelect_Container" class="{{Class}} DivSelect_Container"> |
+ <div id="DivSelect_ButtonsContainer" class="{{Class}} DivSelect_ButtonsContainer"> |
+ <span id="DivSelect_Info" class="{{Class}} DivSelect_Info"></span> |
+{% if EmptyButton.length > 0 %} |
+ <span class="{{Class}} DivSelectButton" onclick="window.Input_DivSelect_PopupHandler()">{{EmptyButton|nbsp|safe}}</span> |
+{% endif %} |
+{% if Insert_descr != null %} |
+ <span class="{{Class}} DivSelectButton" onclick="window.Input_DivSelect_Popup.openInsert()">{{Insert_descr|nbsp|safe}}</span> |
+{% endif %} |
+{% for button_link in Buttons_link %} |
+ <span class="{{Class}} DivSelectButton" onclick="{{button_link}}">{{ Buttons_descr.shift()|nbsp|safe}}</span> |
+{% endfor %} |
+ <span class="{{Class}} DivSelectButton" onclick="Input_DivSelect_Popup.hidePopup();">Annulla</span> |
+ </div> |
+ <div id="DivSelect_TableContainer" class="{{Class}} DivSelect_TableContainer"> |
+ <table id="DivSelect_Table" class="{{Class}} DivSelect_Table"> |
+ <thead> |
+ <tr class="{{Class}} DivSelect"> |
+ <td class="{{Class}} DivSelect_Detail"></td> |
+{% for col in Cols %} |
+ <td class="{{Class}} DivSelect_Head" style="width:{{col}}px;"><b></b></td> |
+{% endfor %} |
+ </tr> |
+ <tr class="{{Class}} DivSelect"> |
+ <td class="{{Class}} DivSelect_Detail"></td> |
+{% for col in Cols %} |
+ <td class="{{Class}} DivSelect_Head" style="width:{{col}}px;"> |
+ <input class="{{Class}} DivSelect_TextFilter" type="text"> |
+ </td> |
+{% endfor %} |
+ </tr> |
+ </thead> |
+ <tbody> |
+{% for datarow in Rows_array %} |
+ <tr class="{{Class}} DivSelect_{% cycle Pari,Dispari %}"> |
+ <td class="{{Class}} DivSelect_Detail"><button class="{{Class}} DivSelect_Detail" onclick="window.Input_DivSelect_PopupDetail('forward', {{forloop.counter}}-1, {})">DET</button></td> |
+ {% for datacol in Cols %} |
+ <td class="{{Class}} DivSelect_Column" onclick="window.Input_DivSelect_PopupHandler({{forloop.parentloop.counter}}-1)"> </td> |
+ {% endfor %} |
+ </tr> |
+{% endfor %} |
+ </tbody> |
+ </table> |
+ </div> |
+ <div id="DivSelect_Cursor" class="{{Class}} DivSelect_Cursor"> |
+ <div id="DivSelect_CursorContent" class="{{Class}} DivSelect_CursorContent"> |
+ </div> |
+ </div> |
+</div> |
+</%def> |
/tags/2.0/htdocs/input/file.comp |
---|
0,0 → 1,71 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# Tarcisio Fedrizzi <tarch@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Optimization: on server use query to upload field without JSON 'base64' field! |
eg. file .mql: |
<%method FIELDS>file</%method> |
<%method SELECT_FIELDS>file - 'base64' AS file</%method> |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/file.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$id |
$value => undef |
$description => '' |
$prompt => 'No file selected' |
$bgcolor => undef |
$icon => 'find' # icona da utilizzare |
$icon_del => 'delete' # icona per cancellare il file |
$readonly => undef |
$width => undef |
$style => '' |
</%args> |
<span class="container" base_class="inputspan" id="<%$id%>" style='background-color: transparent;' |
<%&ArgsOnly2HtmlTaglist( |
onkeydown => 'return Input_keydown(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
ondblclick => "Input_File_Ondblclick('$id', event);" |
)%>> |
<input id="Upload_<%$id%>" type="file" style='display: none;' |
<%&ArgsOnly2HtmlTaglist( |
onchange => "Input_File_Onchange('$id', event);" |
)%>> |
<a id="Link_<%$id%>" style="display: none" href=""></a> |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
<span base_class="inputspan" unselectable id="Display_<%$id%>" |
style="<% (defined $width ? "width:$width;" : '').(defined $bgcolor ? "background-color:$bgcolor;" : '').$style %>"></span> |
<span class="dijitInline dijitIcon masonSqlIcons <%$icon%> vAlign" id="Icon_<%$id%>"></span> |
</span> |
% $ARGS{'value'} = defined $value ? $value : ''; |
% push @Script_buffer, $m->scomp('.defer', %ARGS, icon => $icon, icon_del => $icon_del); |
<%def .defer> |
<%args> |
$id |
$value |
$description |
$icon |
$icon_del |
$prompt |
$readonly |
</%args> |
% $readonly = $readonly ? 'true' : 'false'; |
var Id_<%$id%> = Input_File_Init('<%$id%>', '<%$description|js%>', '<%$prompt|js%>', <%$readonly%>, '<%$icon%>', '<%$icon_del%>'); |
% if(defined $value){ |
Id_<%$id%>.set_value('<%$value|js%>'); |
% } |
</%def> |
/tags/2.0/htdocs/input/file.js |
---|
0,0 → 1,237 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2016 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
require(["dijit/Tooltip"]); |
function Input_File_Init(ObjName, Descr, Prompt, ReadOnly, Icon, Icon_del){ |
var Obj = Input_Init(ObjName, Descr); |
Obj.DisplayDescr = Input_Init('Display_'+ObjName, Descr); |
Obj.icon = document.getElementById('Icon_' + ObjName); |
Obj.Icon = Icon; |
if(Icon_del){ |
Obj.Icon_del = Icon_del; |
require(['dojo/_base/connect', 'dojo/_base/event'], function(connect, event){ |
connect.connect(Obj.icon, 'onclick', function(evt){ |
if(!Obj.Readonly()){ |
Obj.set_value(null); |
event.stop(evt); |
} |
}); |
}); |
} |
Obj.upload = document.getElementById('Upload_'+ObjName); |
Obj.link = document.getElementById('Link_'+ObjName); |
Obj.objName = ObjName; |
Obj.onclickHandle = null; |
Obj.add_onclick = Input_File_add_onclick; |
Obj.remove_onclick = Input_File_remove_onclick; |
Obj.set_onclick = Input_File_set_onclick; |
Obj.update_prompt = Input_File_update_prompt; |
Obj.set_value = Input_File_set_value; |
Obj.get_value = Input_File_get_value; |
Obj.set_status = Input_File_set_status; |
Obj.Readonly = Input_File_Readonly; |
Obj.file_reader = Input_File_FileReader; |
Obj.get_display = function(){ |
return Html2String(this.DisplayDescr.innerHTML); |
} |
Obj.DisplayDescr.get_display = function(){ |
return Html2String(this.innerHTML); |
} |
Obj.defaultPrompt = Prompt; |
Obj.update_prompt(Prompt); |
Obj.Tooltip_icon = new dijit.Tooltip({ |
connectId: [Obj.icon], |
showDelay: this.TooltipShowDelay, |
}); |
Obj.Readonly(ReadOnly); |
Obj.Parameters = null; |
Obj.setFocus = null; |
return Obj; |
} |
function Input_File_FileReader(){ |
if(window.FileReader) { |
var obj = this; |
var reader = new FileReader(); |
reader.onload = function(){ |
obj.upload.dataURL = reader.result; |
obj.set_value(); |
obj.widgetError = false; |
obj.set_status(); |
}; |
require(["dojo/on"], function(on){ |
on(reader, "error", function(evt){ |
var err = evt.target.error; |
my_alert(err.name+': '+err.message); |
obj.widgetError = 'Error'; |
obj.set_status(); |
}); |
}); |
return reader; |
}else{ |
Input_ErrorMessage(Event, |
'The FileReader API is not fully supported in this browser.'); |
return null; |
} |
} |
function Input_File_Ondblclick(ObjName, Event){ |
var obj = document.getElementById(ObjName); |
if(obj.file && obj.file.hasOwnProperty('base64')){ |
obj.link.href = "data:application/octet-stream;base64,"+obj.file.base64; |
obj.link.download = obj.file.filename; |
obj.link.click(); |
}else{ |
var db = obj.displayBinding.dataBinding; |
require(["dojo/io-query"], function(ioQuery){ |
var query = { |
method: 'input_file_uload', |
father_id: db.father_id, |
field: obj.name, |
value: obj.value, |
key: db.keys[obj.dbRow] |
} |
var url = '<%$r->dir_config('DataBaseUrl')%>/' + db.from + '.mql?' + ioQuery.objectToQuery(query); |
var w = 800; |
var h = 1000; |
var left = (screen.width - w) / 2; |
var top = (screen.height - h) / 3; |
window.open(url, '_blank', 'toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,copyhistory=no,width='+w+',height='+h+',top='+top+',left='+left); |
}); |
} |
} |
function Input_File_set_status(Status){ |
var classList = this.eval_status(Status); |
// non applico la variazione della lista delle classi se non cambia |
if(this.DisplayDescr.className != classList){ |
this.DisplayDescr.className = classList; |
} |
} |
function Input_File_Readonly(Set){ |
if(Set == null){ |
return this.readOnly; |
}else{ |
this.readOnly = Set; |
this.set_onclick(Set); |
this.disabled = Set; |
this.style.cursor = Set ? 'default' : 'pointer'; |
this.set_status(); |
var widget = this; |
require(["dojo/dom-class"], function(domClass){ |
domClass[Set ? 'add' : 'remove'](widget.icon, 'dijitDisabled'); |
if(widget.Icon_del){ |
domClass.replace(widget.icon, Set ? widget.Icon : widget.Icon_del, Set ? widget.Icon_del : widget.Icon); |
widget.Tooltip_icon.label = Set ? null : 'Cancella il file'; |
} |
}); |
return Set; |
} |
} |
function Input_File_set_onclick(readonly){ |
if(readonly){ |
this.remove_onclick(); |
}else{ |
this.add_onclick(); |
} |
return; |
}; |
function Input_File_remove_onclick(){ |
var handle = this.onclickHandle; |
if(handle && handle.hasOwnProperty('remove')){ |
handle.remove(); |
} |
this.onclickHandle = null; |
return; |
} |
function Input_File_add_onclick(){ |
var obj = this; |
require(["dojo/on"], function(on){ |
if(!obj.onclickHandle){ |
obj.onclickHandle = on(obj, "click", function(){ |
obj.upload.click(); |
}); |
} |
}); |
} |
function Input_File_Onchange(ObjName, Event){ |
var input = Event.target; |
var obj = document.getElementById(ObjName); |
Input_DeleteDescription(); |
obj.isChanged = false; |
if(!window.FileReader){ |
my_alert('The FileReader API is not fully supported in this browser.'); |
return Input_abortChange(obj, Event); |
} |
var inputFile = input.files[0]; |
var reader = obj.file_reader(); |
if(inputFile && reader){ |
reader.readAsDataURL(inputFile); |
obj.upload.fileName = inputFile.name; |
obj.update_prompt(inputFile.name); |
return true; |
} |
return false; |
}; |
function Input_File_update_prompt(Prompt){ |
var obj = this; |
require(["dojo/dom"], function(aspect){ |
obj.DisplayDescr.innerHTML = '<p>'+Prompt+'</p'; |
}); |
return; |
} |
function Input_File_set_value(Value, param){ |
var upload = this.upload; |
if(Value){ |
this.value = Value; |
this.file = JSON.parse(Value); |
this.update_prompt(this.file.filename); |
upload.value = ''; |
delete upload.fileName; |
delete upload.dataURL; |
}else if(upload.hasOwnProperty('fileName') && |
upload.hasOwnProperty('dataURL')){ |
var arr = upload.dataURL.split(/(:|;|,)/); |
dojo.require("dojox.encoding.digests.MD5"); |
this.file = { |
filename: upload.fileName, |
'content-type': arr[2], |
base64: arr[6], |
digest_md5: dojox.encoding.digests.MD5(arr[6]) |
}; |
this.value = JSON.stringify(this.file); |
delete upload.fileName; |
delete upload.dataURL; |
}else{ |
this.value = null; |
upload.value = ''; |
this.update_prompt(this.defaultPrompt); |
} |
if(param != null){ |
this.set_param(param); |
} |
}; |
function Input_File_get_value(){ |
if(this.value){ |
return this.value; |
}else{ |
return null; |
} |
}; |
/tags/2.0/htdocs/input/Files.js |
---|
0,0 → 1,526 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2011 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
require(["dojo/store/JsonRest", "dojo/store/Observable", "dijit/Menu", "dijit/Tree", "dijit/TooltipDialog", |
"dijit/tree/dndSource", "dojox/form/Uploader", "dojox/form/uploader/FileList", "dojo/io-query"]); |
dojo.ready(function(){ |
%#// tooltip per mostare la storia dei file |
window.Input_Files_history_dialog = new dijit.TooltipDialog({ |
id: 'Input_Files_history_dialog', |
onLoad: function(){ |
var Id = this.tree.widget.get_value(); // ID corrente |
%# // toglie barra scorrimento se non necessaria (vedi <div class="htmlselect_Body" ... ) |
this.focus(); |
}, |
onKeyUp: function(event){ |
if(event.keyCode == 27){ |
// chiudo la lista se uso tasto <Esc> |
dijit.popup.close(this); |
} |
}, |
hidePopup: function(){ |
dijit.popup.close(this); |
} |
}); |
Input_Files_history_dialog.hidePopup = function(){ |
dijit.popup.close(this); |
}; |
Input_Files_history_dialog.watch('focused', function(property_name, old_val, new_val){ |
if(!new_val){ |
Input_Files_history_dialog.hidePopup(); |
} |
}); |
}); |
function Input_Files_Init(Objname, Descr, Readonly, From, Value, Delete_if_update){ |
var Obj = Input_Init(Objname, Descr); |
Obj.From = From; |
Obj.value = Value; |
Obj.Delete_if_update = Delete_if_update; |
Obj.get_value = function (){ |
return this.value; |
}; |
Obj.set_value = function (value){ |
this.value = value; |
var store = this.tree.model; |
%# // svuoto la tree |
store.setChange({id:'/', name:'...', children: []}); |
%# // cambio tree |
store.target = "/archive/" + this.From + '/' + value; |
if(value){ |
%# // richiedo la tree al server |
store.get('/').then(function (dir){ |
store.setChange(dir) |
}); |
} |
}; |
// inizializzo i widget solo quando Dojo è pronto |
dojo.ready(function(){ |
// creo lo store |
var Store = dojo.store.JsonRest({ |
target: "/archive/" + From + '/' + Value, |
root: '/', |
mayHaveChildren: function(object){ |
return object.children != null; |
}, |
getRoot: function(onItem, onError){ |
onItem({ id: '/', name:'...', children:1}); |
}, |
getChildren: function(object, onComplete, onError){ |
// retrieve the full copy of the object |
var store = this; |
this.get(object.id).then( |
function(fullObject){ |
// copy to the original object so it has the children array as well. |
object.children = fullObject.children; |
// now that full object, we should have an array of children |
onComplete(fullObject.children); |
store.setChildrenEmpty(fullObject.children); |
}, |
function(error){ |
my_alert('ERROR getChildren:' + error.message + '<br>' + error.responseText, 'html'); |
console.debug('Error on getChildren', error); |
onError(error); |
} |
); |
}, |
setChange: function(item){ |
this.onChange(item); |
if(item.children){ |
this.onChildrenChange(item, item.children); |
this.setChildrenEmpty(item.children); |
} |
}, |
setChildrenEmpty: function(children){ |
var store = this; |
require(["dojo/_base/array"], function(array){ |
array.forEach(children, function(child, i){ |
%# // .children è nullo se non è cartella, 1: se ha figli e [] se è cartella vuota |
if(child.children && child.children.length == 0){ |
%# // toglie [+] a sinistra della cartella |
store.onChildrenChange({ id: child.id }, []); |
} |
}); |
}); |
}, |
getLabel: function(object){ |
// just get the name |
return object.name; |
}, |
pasteItem: function(child, oldParent, newParent, bCopy, insertIndex){ |
if(this.tree.widget.readOnly){ |
my_alert('Spostamento non autorizzato'); |
return false; |
} |
var dest_dir_id = this.mayHaveChildren(newParent) ? newParent.id : newParent.id.replace(/\/[^\/]*$/, ''); |
if(oldParent.id == dest_dir_id){ |
return false; |
} |
// comunico al server lo spostamento |
child.new_id = dest_dir_id + '/' + child.id.replace(/^.*\//, ''); |
child.children = null; |
var store = this; |
store.put(child).then(function(){ |
// aggiorno la cartella nell'albero |
store.get(dest_dir_id).then(function(dir){ |
store.setChange(dir) |
}); |
store.get(oldParent.id).then(function(dir){ |
store.setChange(dir) |
}); |
}); |
}, |
put: function(object, options){ |
// execute the default action |
var item = this; |
return dojo.store.JsonRest.prototype.put.apply(this, arguments).then( |
function(response){ |
if(response.error){ |
console.error('put response', response); |
my_alert((response.name ? 'File ' + response.name + ' - ' : '') + 'Errore: ' + response.error); |
}else{ |
console.debug('put response', response); |
// fire the onChildrenChange event |
item.onChildrenChange(object, object.children); |
item.setChildrenEmpty(object.children); |
// fire the onChange event |
item.onChange(object); |
if(response.info){ |
my_alert((response.name ? 'File ' + response.name + ': ' : '') + response.info); |
} |
} |
}, |
function(error){ |
my_alert('ERROR:' + error.message +'<br>'+ error.responseText, 'html'); |
console.debug('Error on put', error); |
} |
); |
}, |
remove: function(id){ |
var store = this; |
var id_dir = id.replace(/\/[^\/]*$/, ''); |
return dojo.store.JsonRest.prototype.remove.apply(this, arguments).then( |
function(response){ |
response = dojo.json.parse(response); |
if(response.error){ |
console.error('remove response', response); |
my_alert((response.name ? 'File ' + response.name + ' - ' : '') + 'Errore: ' + response.error); |
}else{ |
console.debug('remove response', response); |
// aggiorno la directory che conteneva il file cancellato |
store.get(id_dir).then(function(dir){ |
// notifico il cambiamento |
store.setChange(dir) |
}); |
if(response.info){ |
my_alert((response.name ? 'File ' + response.name + ': ' : '') + response.info); |
} |
} |
}, |
function(error){ |
my_alert('ERROR:' + error.message + '<br>' + error.responseText, 'html'); |
console.debug('Error on delete', error); |
} |
); |
} |
%# // we can also put event stubs so these methods can be |
%# // called before the listeners are applied |
%# ,onChildrenChange: function(parent, children){ |
%# // fired when the set of children for an object change |
%# console.debug('onChildrenChange', parent, children) |
%# }, |
%# onChange: function(object){ |
%# // fired when the properties of an object change |
%# console.debug('onChange', object); |
%# } |
});//Store |
// creo la tree |
var Obj_tree = new dijit.Tree({ |
model: Store, |
'class': 'Files_tree', |
autoExpand: false, |
openOnClick: true, |
persist: false, // disables use of cookies for state saving |
showRoot: true, //false, |
// define the drag-n-drop controller |
dndController: dijit.tree.dndSource, |
checkAcceptance: function(source, nodes){ |
%# console.debug('Files checkAcceptance', source, nodes); |
this.nodes_to_move = nodes; |
return nodes.length == 1; |
}, |
checkItemAcceptance: function(source, nodes, position){ |
%# console.debug('Files checkItemAcceptance', position, source, nodes); |
%# // verifico se la destinazione è compatibile |
if(this != nodes || this.nodes_to_move.length > 1)return false; |
var from = dijit.getEnclosingWidget(this.nodes_to_move[0]); |
var to_dir = dijit.getEnclosingWidget(source); |
if(!from || !to_dir)return false; |
if(!to_dir.item.children){ |
to_dir = to_dir.getParent() |
} |
var from_dir = from.getParent(); |
return from_dir != to_dir; |
} |
}, Objname + '_tree'); // Il node del widget - esiste un elemento div esistente con quel nome definito includendo Files.comp |
Store.tree = Obj_tree; |
Obj.tree = Obj_tree; |
Obj_tree.widget = Obj; |
Obj_tree.getIconClass = function(item, opened){ |
return item.type == 'trash' ? 'masonSqlIcons delete' : |
(this.model.mayHaveChildren(item) ? (opened ? 'dijitFolderOpened' : 'dijitFolderClosed') : 'dijitLeaf'); |
}; |
Obj_tree.close_popups = function(){ |
// chiudo e svuoto i pannelli aperti |
dijit.popup.close(dijit.byId('Input_Files_tree_dialog')); |
dijit.popup.close(dijit.byId('Input_Files_trash_dialog')); |
% if($Session{Group_Admins}){ |
dijit.popup.close(dijit.byId('Input_Files_delete_dialog')); |
% } |
dijit.popup.close(dijit.byId('Input_Files_upload_dialog')); |
Input_Files_history_dialog.hidePopup(); |
dijit.byId('Input_Files_files').reset(); |
%# console.debug('close_popups'); |
} |
Obj_tree.onClick = function(){ |
this.close_popups(); |
%# console.debug('Click tree'); |
}; |
Obj_tree.onDblClick = function (item) { |
this.close_popups(); |
if(!item.children){ |
this.download_item(item, 'download'); |
%# console.debug('download ...'); |
} |
}; |
Obj_tree.onClose = Obj_tree.close_popups; |
Obj_tree.onOpen = Obj_tree.close_popups; |
%# // seleziona la riga della Tree in corrispondenza delle coordinate indicate |
Obj_tree.selectedByCoord = function(coord, child){ |
var tree = this; |
require(["dojo/_base/array", "dojo/dom-geometry"], function(array, domGeom){ |
array.forEach((child || tree).getChildren(), function(tree_node, i){ |
var pos = domGeom.position(tree_node.rowNode, true); |
if(coord.x >= pos.x && coord.x <= pos.x + pos.w && coord.y >= pos.y && coord.y <= pos.y + pos.h){ |
tree.set('selectedItems', [tree_node.item]); |
return; |
} |
if(tree_node.item.children){ |
%# // chiamo ricorsivamente la Tree |
tree.selectedByCoord(coord, tree_node); |
} |
}); |
}); |
}; |
Obj_tree.open_history = function(new_ver){ |
var Obj = this.widget; |
Input_Files_history_dialog.tree = this; |
if(!new_ver){ |
%# // se è richiesto un cambio della versione corrente il popup è già aperto |
dijit.popup.open({ |
popup: Input_Files_history_dialog, |
around: this.selectedNode.contentNode |
}); |
} |
Input_Files_history_dialog.set('href','<% $r->dir_config('DataBaseUrl') %>/' + Obj.From + '.mql?' + |
dojo.objectToQuery({ |
F: 'archive_history', |
rec_id: Obj.value, |
new_ver: new_ver, |
obj_id: this.selectedNode.item.id, |
edit: Obj.Readonly() ? '' : 1 |
}) |
); |
}, |
Obj_tree.set_new_version = function(new_ver){ |
%# // cambia la versione corrente del file selezionato |
this.open_history(new_ver); |
}, |
Obj_tree.onClick = function(item, node, evt){ |
%# console.debug('Files onClick', item, node, evt); |
}, |
Obj_tree.startup(); |
var menu = dijit.byId('Input_Files_tree_menu'); |
Obj_tree.menu = menu; |
var menuChildren = menu.getChildren(); |
%# // riferimenti usati sotto (es. menu.Input_Files_rename ) |
menuChildren.forEach(function(child){ |
menu[child.id] = child; |
}); |
// when we right-click anywhere on the tree, make sure we open the menu |
menu.bindDomNode(Obj_tree.domNode); |
dojo.connect(menu, '_openMyself', this, function(e) { |
// get a hold of, and log out, the tree node that was the source of this open event |
Input_Files_TreeNodeObj = dijit.getEnclosingWidget(e.target).tree; |
Input_Files_TreeNodeObj.selectedByCoord(e.coords); |
var selected = Input_Files_TreeNodeObj.selectedNode; |
%# console.debug('Files_TreeNode menu', Input_Files_TreeNodeObj.selectedItem.id, selected); |
var widget = Input_Files_TreeNodeObj.tree.widget; |
if(!widget.get_value()){ |
dijit.popup.close(menu); |
return false; |
} |
var isWr = !widget.readOnly; |
var DEL; |
if(widget.displayBinding){ |
var db = widget.displayBinding.dataBinding; |
DEL = widget.Delete_if_update ? (db.canUpdate || db.canDelete) : db.canDelete; |
}else{ |
DEL = true; |
} |
%# console.debug('dijit.getEnclosingWidget:', selected.item.id, Input_Files_TreeNodeObj); |
menu.Input_Files_rename.set('style', {'display': (isWr && selected.indent > 0) ? '' : 'none'}); |
var isTrash = (0 == Input_Files_TreeNodeObj.selectedItem.id.search('/.<% $r->dir_config('Files_Trash_dir') %>')); |
menu.Input_Files_trash.set('style', {'display': (!isTrash && isWr && DEL && selected.indent > 0) ? '' : 'none'}); |
% if($Session{Group_Admins}){ |
menu.Input_Files_delete.set('style', {'display': (isTrash && isWr && DEL && selected.indent > 0) ? '' : 'none'}); |
% } |
menu.Input_Files_new_folder.set('style', {'display': (isWr && selected.item.children) ? '' : 'none'}); |
menu.Input_Files_download.set('style', {'display': selected.item.children ? 'none' : ''}); |
menu.Input_Files_zipDownload.set('style', {'display': selected.item.children ? '' : 'none'}); |
menu.Input_Files_tgzDownload.set('style', {'display': selected.item.children ? '' : 'none'}); |
menu.Input_Files_upload.set('style', {'display': isWr ? '' : 'none'}); |
menu.Input_Files_history.set('style', {'display': !selected.item.children ? '' : 'none'}); |
}); |
menu.open_dialog = function(){ |
var tree_dialog; |
if(this.id == 'Input_Files_rename' || this.id == 'Input_Files_new_folder'){ |
tree_dialog = dijit.byId('Input_Files_tree_dialog'); |
// comando: rename / new_folder |
tree_dialog.id_cmd = this.id; |
// nome del file |
dojo.byId('Input_Files_tree_dialog_name').value = this.id == 'Input_Files_rename' ? Input_Files_TreeNodeObj.selectedNode.item.name : ''; |
dojo.byId('Input_Files_tree_dialog_btn').innerHTML = this.id == 'Input_Files_rename' ? 'Rinomina' : 'Nuova cartella'; |
}else{ |
tree_dialog = dijit.byId(this.id + '_dialog'); |
} |
dijit.popup.open({ |
popup: tree_dialog, |
around: Input_Files_TreeNodeObj.selectedNode.contentNode |
}); |
}; |
menu.close_tree_dialog = function(){ |
var tree_dialog = dijit.byId('Input_Files_tree_dialog'); |
var new_name = dojo.byId('Input_Files_tree_dialog_name').value |
var item = Input_Files_TreeNodeObj.selectedNode.item; |
// verifico che nel nome non ci siano alcuni caratteri speciali |
var forbidden_chars = []; |
['*', ':', '|', '<', '>', '?', '/', '\\', '"'].forEach(function (c){ |
if(new_name.indexOf(c) != -1){ |
forbidden_chars.push(c); |
} |
}); |
if(forbidden_chars.length){ |
if(forbidden_chars.length == 1){ |
alert('Il carattere (' + forbidden_chars[0] + ') non può essere utilizzato nel nome'); |
}else{ |
alert('I caratteri (' + forbidden_chars.join(', ') + ') non possono essere utilizzati nel nome'); |
} |
return false; |
} |
if(tree_dialog.id_cmd == 'Input_Files_rename'){ |
%# console.debug('rename', Obj_tree.id, new_name, item); |
item.name = new_name; |
Input_Files_TreeNodeObj.tree.model.put(item).then(function(){ |
var id_dir = item.id.replace(/\/[^\/]*$/, ''); |
Input_Files_TreeNodeObj.tree.model.get(id_dir).then(function(dir){ |
// notifico il cambiamento |
Input_Files_TreeNodeObj.tree.model.setChange(dir); |
}); |
}); |
}else{ |
%# console.debug('new_folder', new_name, item); |
var id_dir = Input_Files_TreeNodeObj.selectedNode.item.id; |
Input_Files_TreeNodeObj.tree.model.add({ new_name:new_name, id:id_dir + '/' + new_name, children:1 }).then(function (){ |
// aggiorno la cartella nell'albero |
Input_Files_TreeNodeObj.tree.model.get(id_dir).then(function(dir){ |
Input_Files_TreeNodeObj.tree.model.setChange(dir); |
}); |
}); |
} |
%#// console.debug('close_dialog', this); |
dijit.popup.close(tree_dialog); |
}; |
dojo.connect(dijit.byId('Input_Files_rename'), 'onClick', menu.open_dialog); |
dojo.connect(dijit.byId('Input_Files_new_folder'), 'onClick', menu.open_dialog); |
dojo.connect(dijit.byId('Input_Files_trash'), 'onClick', menu.open_dialog); |
% if($Session{Group_Admins}){ |
dojo.connect(dijit.byId('Input_Files_delete'), 'onClick', menu.open_dialog); |
% } |
var upload_dialog = dijit.byId('Input_Files_upload_dialog'); |
dojo.connect(dojo.byId('Input_Files_upload'), 'onclick', function(){ |
var TreeObj = Input_Files_TreeNodeObj.tree; |
var node = Input_Files_TreeNodeObj.selectedNode; |
if(!node.item.children){ |
%# // è un file, seleziono la dir padre |
node = node.getParent(); |
} |
dojo.byId('Input_Files_upload_dir').value = TreeObj.widget.From + '/' + TreeObj.widget.value + node.item.id; |
dijit.popup.open({ |
popup: upload_dialog, |
around: Input_Files_TreeNodeObj.selectedNode.contentNode |
}); |
}); |
dojo.connect(dijit.byId('Input_Files_history'), 'onClick', function(evt){ |
%#DEBUG// console.debug('Input_Files_history onclick', evt); |
Input_Files_TreeNodeObj.open_history(); |
}); |
// eventi del caricamento dei file |
var uploader = dijit.byId('Input_Files_uploader'); |
dojo.connect(uploader, 'onComplete', function(params){ |
%# console.debug('uploader onComplete', unescape(dojo.toJson(params))); |
upload_dialog.domNode.style.cursor = 'default'; |
// valuto gli errori |
require(["dojo/_base/array"], function(array){ |
var mess = ''; |
array.forEach(params, function(item, i){ |
if(item.error){ |
mess += (item.name ? 'File ' + item.name + ' - ' : '') + 'Errore: ' + item.error + '\n'; |
}else if(item.info){ |
mess += (item.name ? 'File ' + item.name + ': ' : '')+ item.info + '\n'; |
} |
}); |
mess.length && my_alert(mess); |
}); |
dijit.byId(Objname + '_tree').close_popups(); |
var node = Input_Files_TreeNodeObj.selectedNode; |
if(!node.item.children){ |
%# // è un file, seleziono la dir padre |
node = node.getParent(); |
} |
Input_Files_TreeNodeObj.tree.model.get(node.item.id).then(function(dir){ |
Input_Files_TreeNodeObj.tree.model.setChange(dir); |
}); |
}); |
dojo.connect(uploader, 'onError', function(mess, err){ |
upload_dialog.domNode.style.cursor = 'default'; |
console.debug('uploader onError', mess, err); |
my_alert(mess + '\n' + err.message); |
}); |
dojo.connect(uploader, 'onBegin', function(params){ |
// cursor durante il caricamento |
upload_dialog.domNode.style.cursor = 'wait'; |
%# console.debug('uploader onBegin', unescape(dojo.toJson(params))); |
}); |
// richiamato dalla combo e da dblclick della tree |
Obj_tree.download_item = function (item, mode) { |
var id_file = item ? item.id : Input_Files_TreeNodeObj.selectedNode.item.id; |
var w = 800; |
var h = 600; |
var left = (screen.width - w) / 2; |
var top = (screen.height - h) / 3; |
var params = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable,alwaysRaised,dependent,titlebar=no,width='+w+',height='+h+',top='+top+',left='+left; |
//var url = Input_Files_TreeNodeObj.tree.model.target + mode + '.' + escape(id_file); |
var url = (item ? this.model.target : Input_Files_TreeNodeObj.tree.model.target) + id_file + '?' + mode; |
%# console.debug('download item', id_file, url); |
window.open(url, '_blank', params); |
} |
// richiamato alla conferma della cancellazione del file/dir |
Obj_tree.delete_item = function (item) { |
var id_file = item ? item.id : Input_Files_TreeNodeObj.selectedNode.item.id; |
%# console.debug('delete item', id_file); |
// cancello il file nello store remoto |
var store = Input_Files_TreeNodeObj.tree.model; |
store.remove(id_file).then(function(mess){ |
% if($Session{Group_Admins}){ |
// aggiorno il cestino |
store.get('/.<% $r->dir_config('Files_Trash_dir') %>').then(function(dir){ |
store.setChange(dir) |
}); |
% } |
%# console.debug('file deleted', mess); |
}); |
dijit.popup.close(dijit.byId('Input_Files_trash_dialog')); |
% if($Session{Group_Admins}){ |
dijit.popup.close(dijit.byId('Input_Files_delete_dialog')); |
% } |
} |
//modifico il metodo standard per provvedere alla chiusura nel menu quando cambia lo stato r/w del widget |
Obj.InputReadonly = Input_Readonly; |
Obj.Readonly = function (read){ |
read == null || this.tree.close_popups(); |
return this.InputReadonly(read); |
}; |
Obj.readOnly = !Readonly; // costringo il componente a cambiare la configurazione |
Obj.Readonly(Readonly); |
Obj.setFocus = null; |
});//dojo.ready |
}//function Input_Files_Init |
/tags/2.0/htdocs/input/url.js |
---|
0,0 → 1,76 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2009-2012 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
Input_Url_Display = null; |
function Input_Url_displayURL(open_window){ |
if(this.popup && !open_window){ |
// mostra in una finestra separata la URL contenuta nel widget |
var widget = this; |
require(["dijit/Dialog"], function(Dialog){ |
if(!Input_Url_Display){ |
Input_Url_Display = new Dialog({ |
title: widget.Descr, |
closable: true, |
timeout: <% $r->dir_config('GetFormTimeout') %>, |
content: '' |
}); |
Input_Url_Display.containerNode.style.padding = '2px 2px'; |
}else{ |
Input_Url_Display.set('content', ''); |
} |
var url = widget.base_url + widget.get_value(); |
if(!/^\w+:\/\//i.test(url)){ |
url = 'http://' + url.replace(/^\/+/, ''); |
} |
Input_Url_Display.show(); |
Input_Url_Display.set('content', '<iframe src="' + url + |
'" width="' + widget.window_width + '" height="' + widget.window_height + |
'" seamless="seamless" frameborder="0" marginwidth="0" marginheight="0"></iframe>'); |
}); |
}else{ |
var url = this.base_url + this.get_value(); |
if(!/^\w+:\/\//i.test(url)){ |
url = 'http://' + url.replace(/^\/+/, ''); |
} |
var w = this.window_width; |
var h = this.window_height; |
var left = (screen.width - w) / 2; |
var top = (screen.height - h) / 3; |
window.open(url, '_blank', 'width='+w+',height='+h+',top='+top+',left='+left+','+this.window_properties); |
} |
} |
function Input_Url_Init(Objname, base_url, popup, window_width, window_height, window_properties){ |
var Obj = document.getElementById(Objname); |
var button_url = document.getElementById(Objname + '_button_url'); |
button_url.widget = Obj; |
Obj.button_url = button_url; |
Obj.popup = popup; |
Obj.displayURL = Input_Url_displayURL; |
Obj.base_url = base_url; |
Obj.window_width = window_width; |
Obj.window_height = window_height; |
Obj.window_properties = window_properties; |
// controllo del campo al termine della modifica |
Obj.local_test = function(){ |
this.button_url.style.display = this.value.length == 0 ? 'none' : ''; |
return ''; |
}; |
Obj.onkeypress = null; |
Obj.set_value = function(value){ |
this.value = value; |
this.button_url.style.display = this.value.length == 0 ? 'none' : ''; |
}; |
button_url.style.display = Obj.value.length == 0 ? 'none' : ''; |
return Obj; |
} |
/tags/2.0/htdocs/input/form.js |
---|
0,0 → 1,151 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
// Popup |
var Input_Form_Popup; |
function Input_Form_Init(Objname, Descr, Empty, EmptyDescr, from, Where, OrderBy, formParameters, ReadOnly, popupWidth, popupHeight, DispTemplate, Query_param){ |
var Obj = Input_Init(Objname, Descr); |
Obj.icon = document.getElementById('icon_' + Objname); |
Obj.Empty = Empty; |
Obj.EmptyDescr = EmptyDescr; |
Obj.from = from; |
Obj.Source = '<%$r->dir_config('DataBaseUrl')%>/'+Obj.from+'.mql'; |
Obj.formParameters = formParameters; |
Obj.Where = Where; |
Obj.OrderBy = OrderBy; |
Obj.popupWidth = popupWidth; |
Obj.popupHeight = popupHeight; |
Obj.DisplayDescr = document.getElementById('display_'+Objname); |
Obj.DispTemplate = DispTemplate; |
Obj.Query_param = Query_param; |
Obj.setFocus = null; |
Obj.onafterupdate = function(){ |
eval(this.onchange); |
} |
// metodo per la lettura del valore del componente |
Obj.get_value = function () { |
return this.value; |
} |
Obj.set_status = function(status){ |
var classList = this.eval_status(status); |
// non applico la variazione della lista delle classi se non cambia |
if(this.DisplayDescr.className != classList){ |
this.DisplayDescr.className = classList; |
} |
} |
// metodo per il caricamento del valore del componente |
Obj.set_value = function(value, param){ |
this.value = value; |
// parametro dato nel formato "descrizione|parametri...\n.....\n...." |
if(param != null){ |
this.set_param(param); |
}else{ |
if(value != this.Empty){ |
// richiedo il valore al server |
hReqMason_ExecuteTimeout( |
this.Source, |
<%$r->dir_config('GetRecordTimeout')%>, |
Input_Form_TimeoutData, |
Input_Form_Load_Callback, |
'parameters_select', |
['key', value], |
null, |
null, |
this |
); |
}else{ |
this.set_param(null); |
} |
} |
} |
Obj.Readonly = function(set){ |
if(set == null){ |
return this.readOnly; |
}else{ |
this.disabled = set; |
this.style.cursor = set ? 'default' : 'pointer'; |
this.readOnly = set; |
this.set_status(); |
var icon = this.icon; |
require(["dojo/dom-class"], function(domClass){ |
if(icon){ |
domClass[set ? 'add' : 'remove'](icon, 'dijitDisabled'); |
} |
}); |
return set; |
} |
}; |
Obj.Readonly(ReadOnly); |
Obj.set_status(''); |
// apro una finestra con il form |
// costruisco un oggetto 'display' minimale con i soli elementi necessari a lanciare il form (vedi file ../lib/displaybinding.js ) |
Obj.display = { |
prefix: 'Input_Form_display', |
Input: Obj, |
dataBinding: new DataBinding('Input_Form_db', null, null), |
gotoRecords: function(mode, key, recordset){ |
return this.dataBinding.gotoRecords(mode, key, recordset); |
}, |
onclosedetail: function(update){ |
if(update){ |
// forzo l'aggiornamento del display nel widget (non passando i parametri essi vengono caricati dal server ...) |
this.Input.set_value(this.Input.get_value(), null); |
if(this.Input.onchange)this.Input.onchange(); |
} |
}, |
openFormDetailByKey: DisplayBinding_openFormDetailByKey |
}; |
Obj.formClick = function(){ |
if(this.Readonly()){ |
return false; |
} |
var value = this.get_value(); |
var default_params = { |
father_id: value, |
father_id_update: value, |
grandfather_id: this.displayBinding ? this.displayBinding.dataBinding.father_id : '', |
json_where: JSON.stringify([['--where-input', this.Where]]) |
}; |
// sovrascrivo con i valori forniti dalla chiamata |
for(var name in this.formParameters){ |
default_params[name] = this.formParameters[name]; |
} |
this.display.openFormDetailByKey('forward', value, this.from, this.popupWidth, this.popupHeight, Obj.Descr, default_params); |
}; |
} // Input_Form_Init |
// Handler risposta in caso di errore o timeout |
function Input_Form_TimeoutData(contextID, type, str, Obj){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(type == 'TIMEOUT'){ |
my_alert('Timeout caricamento parametri ' + Obj.id); |
}else{ |
my_alert('ERRORE caricamento parametri ' + Obj.id + ' url=' +contextObj.URL+': \n['+str+']'); |
} |
} |
// Handler risposta caricamento dinamico dei parametri |
function Input_Form_Load_Callback(str, contextID, Obj){ |
str = str.replace(/^\s+|\s+$/g, ''); |
Obj.set_param(str); |
if(Obj.onloadremoteparam){ |
Obj.onloadremoteparam(); |
} |
} |
/tags/2.0/htdocs/input/htmlselect.comp |
---|
0,0 → 1,101 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Widget htmlselect |
testo in sola lettura di descrizione e pulsante per richiamare la lista in finestra separata |
</%doc> |
<%args> |
$id # identificatore del componente nel documento HTML |
$description => '' # descrizione visualizzata nella barra |
$value => undef # valore da attribuire <option selected> dopo il caricamento della lista (funziona solo se la lista è statica o caricata nel form) |
$from # schema/nome documento ".mql" corrispondente ad una lista |
$where => undef # clausola where da applicare |
$empty => undef # lascia il primo campo della lista vuoto con "value" uguale al contenuto di $empty |
$empty_descr => '' # descrizione da visualizzare per il campo 'empty' |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$edit => undef # link all'oggetto che permette la modifica della lista |
$bgcolor => undef |
$width => '80' |
$length => 28 # numero di caratteri minimo da visualizzare |
$icon => 'find' # icona da utilizzare |
$cache_params => undef # se !undef attiva la cache sui parametri caricati |
$popup_properties => undef |
</%args> |
% $width && ($width -= 19); # spazio del bottone |
% $width < 0 && ($width = 0); |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
<%method LIBRARY>\ |
/lib/httpRequestMason.js |
/input/input.comp |
/input/htmlselect.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
%# $PLogger->debug(sub{ "htmlselect.comp",Dumper(\%ARGS); }); |
<span class="container" base_class="inputspan" id="<%$id%>" <%&Args2HtmlTaglist( |
style => 'background-color: transparent;', |
onchange => undef, |
onkeydown => 'return Input_keydown(event);', |
onclick => "return Input_HtmlSelect_open_list('$id');", |
type => undef, |
widget => undef, |
descr_sep => undef, |
from => undef, |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);')%>> |
<span id="display_<%$id%>" base_class="inputspan" unselectable <%&Args2HtmlTaglist( |
onchange => undef, |
onclick => undef, |
type => undef, |
widget => undef, |
descr_sep => undef, |
from => undef, |
style => (defined $width ? "width:${width};" : '').(defined $bgcolor ? "background-color:$bgcolor;" : '') |
)%>> </span> |
% if($icon){ |
<span class="dijitInline dijitIcon masonSqlIcons <%$icon%> vAlign" id="icon_<%$id%>"></span> |
% } |
</span> |
% push @Script_buffer, $m->scomp('.defer', %ARGS); |
<%def .defer> |
<%args> |
$id |
$value => undef |
$description => '' |
$from |
$where => undef |
$empty => undef |
$empty_descr => '' |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$edit => undef |
$id_descr => '' # identificatore campo descrizione associato del recordset da aggiornare |
$readonly => undef |
$cache_params => undef # se !undef attiva la cache sui parametri caricati |
$popup_max_width => '' |
$popup_max_height => '300px' |
</%args> |
<%perl> |
if($from !~ m|/|){ |
my $pfrom = $Session{ARGS}{from}; |
if($pfrom){ |
$from = $pfrom =~ m|^(\w+)/| ? $1.'/'.$from : 'public/'.$from; |
} |
} |
my $source = $r->dir_config('DataBaseUrl').'/'.$from.'.mql'; |
$empty = (defined $empty) ? "'$empty'" : 'null'; |
</%perl> |
var Id_<%$id%>=Input_HtmlSelect_Init('<%$id%>', '<%$id_descr%>', '<%$source|js%>', '<%$where|js%>','<%$edit|js%>', <%$empty%>, |
'<%$empty_descr|js%>', '<% $disp_template ? $disp_template : ''|js%>', '<%$description|js%>', <% $readonly ? 'true' : 'false'%>, |
<%$cache_params ? 'true' : 'false'%>, '<%$popup_max_width|js%>', '<%$popup_max_height|js%>'); |
<% &ArgsOnly2JscriptTaglist("Id_$id", onchange => undef) %> |
% if(defined $value){ |
Id_<%$id%>.set_value('<%$value|js%>'); |
% } |
</%def> |
/tags/2.0/htdocs/input/htmlselect.js |
---|
0,0 → 1,252 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_HtmlSelect_set_value(value, param){ |
if(value == null){ |
value = this.Empty; |
} |
this.value = value; |
// parametro dato nel formato "descrizione|parametri...\n.....\n...." |
if(param != null){ |
this.set_param(param, null, value); |
}else{ |
if(value != this.Empty && this.Source){ |
// verifico la presenza nella cache |
var cache_param = this.Cache_parameters && this.Cache_parameters[value]; |
if(cache_param == null){ |
// richiedo il valore al server |
// hReqMason_ExecuteTimeout(rspage, timeout, timeout_callback, callback, func, parms, tag, obj_params, callback_obj) |
hReqMason_ExecuteTimeout( |
this.Source, |
<%$r->dir_config('GetRecordTimeout')%>, |
Input_HtmlSelect_TimeoutData, |
Input_HtmlSelect_Load_Callback, |
'parameters_select', |
['key', value], |
null, |
null, |
this |
); |
this.set_param(null, null, value); |
}else{ |
this.set_param(cache_param); |
} |
}else{ |
this.set_param(null); |
} |
} |
} |
// Handler risposta in caso di errore o timeout |
function Input_HtmlSelect_TimeoutData(contextID, type, str, Obj){ |
var contextObj = hReqMason_ContextPool[contextID]; |
if(type == 'TIMEOUT'){ |
Obj.set_value(Obj.value, '--- TIMEOUT rec('+Obj.value+') ---'); |
my_alert('Timeout caricamento parametri widget id:' + Obj.id); |
}else{ |
Obj.set_value(Obj.value, '--- ERROR rec('+Obj.value+') ---'); |
my_alert('ERRORE caricamento parametri widget id:' + Obj.id + ' url=' + this.contextObj.URL+': \n['+str+']'); |
} |
} |
// Handler risposta caricamento dinamico dei parametri |
function Input_HtmlSelect_Load_Callback(str, contextID, Obj){ |
var x = hReqMason_ContextPool[contextID]; |
//console.debug('Input_HtmlSelect_Load_Callback', Obj, str, contextID, x); |
str = str.replace(/^\s+|\s+$/g, ''); |
if(str.length > 0){ |
Obj.set_value(Obj.value, str); |
} |
} |
function Input_HtmlSelect_get_value(value){ |
return this.value; |
} |
function Input_HtmlSelect_Init(Objname, Id_Descr, Source, Where, Edit, Empty, EmptyDescr, DispTemplate, Descr, Read, Cache_param, Popup_max_width, Popup_max_height){ |
var Obj = Input_Init(Objname, Descr); |
Obj.icon = document.getElementById('icon_' + Objname); |
Obj.Source = Source; //Nome del file da caricare (senza .mql) |
Obj.DisplayDescr = Input_Init('display_'+Objname, Descr); |
if(Id_Descr == '')Id_Descr = null; |
Obj.Id_Descr = Id_Descr; |
Obj.set_status = function(status){ |
//console.log('set_status id:'+this.id+' status:'+status); |
var classList = this.eval_status(status); |
//console.log('set_status id:'+this.id+' classList:'+classList); |
// non applico la variazione della lista delle classi se non cambia |
if(this.DisplayDescr.className != classList){ |
//console.log('NEW id:'+this.id+' className:'+classList); |
this.DisplayDescr.className = classList; |
} |
} |
Obj.Readonly = function (set) { |
if(set == null){ |
return this.readOnly; |
}else{ |
this.disabled = set; |
this.style.cursor = set ? 'default' : 'pointer'; |
this.readOnly = set; |
this.set_status(); |
var icon = this.icon; |
require(["dojo/dom-class"], function(domClass){ |
if(icon){ |
domClass[set ? 'add' : 'remove'](icon, 'dijitDisabled'); |
} |
}); |
return set; |
} |
} |
Obj.get_display = function(){ |
return Html2String(this.DisplayDescr.innerHTML); |
} |
Obj.DisplayDescr.get_display = function(){ |
return Html2String(this.innerHTML); |
} |
Obj.Where = Where; |
Obj.Edit = Edit; |
Obj.Empty = Empty; |
Obj.EmptyDescr = EmptyDescr; |
Obj.DispTemplate = DispTemplate; |
Obj.Editing = false; |
Obj.get_value = Input_HtmlSelect_get_value; |
Obj.set_value = Input_HtmlSelect_set_value; |
// Obj.EditingEnd = Input_HtmlSelect_EditingEnd; |
Obj.ListEqualBuffer = null; |
// Obj.LoadCallback = Input_HtmlSelect_LoadCallback; |
// Obj.LoadRemote = Input_HtmlSelect_LoadRemote; |
Obj.Previus = Obj.get_value(); |
Obj.Readonly(Read); |
Obj.Parameters = null; |
if(Obj.Cache_param){ |
Obj.Cache_parameters = {}; //cache dei parametri corrispondenti ai valori presenti nella lista |
} |
Obj.setFocus = null; |
Obj.Popup_max_width = Popup_max_width; |
Obj.Popup_max_height = Popup_max_height; |
return Obj; |
} |
function Input_HtmlSelect_Timeout(contextID, err, str){ |
// var contextObj = hReqMason_ContextPool[contextID]; |
if(err == 'TIMEOUT'){ |
my_alert('Timeout ricezione dati ' + contextID, 'txt'); |
}else{ |
my_alert(err+': '+str, 'txt'); |
} |
} |
// utilizzata per salvare il riferimento alla finestra di selezione |
// vedi: Input_HtmlSelect_open_list |
var Input_HtmlSelect_Popup; |
// Par è un array generato dal method dbms_library.comp?method=htmlselectpopup richiamato |
// nella finestra Input_HtmlSelect_Popup e serve per salvare i parametri associati |
// a ciascuna riga del componente |
function Input_HtmlSelect_PopupHandler(div){ |
require(["dojo/dom-attr"], function(domAttr){ |
var Obj = Input_HtmlSelect_Popup.Input; |
var id = domAttr.get(div, 'mql-id'); |
if(Obj.get_value() != id){ |
var str = div.innerHTML; |
str = str.replace(/\ /g, ''); |
Obj.set_value(id, str+'|'+domAttr.get(div, 'mql-parameters')); |
Input_HtmlSelect_Popup.hidePopup(); |
window.setTimeout("document.getElementById('"+Obj.id+"').test_value()",1); |
if(Obj.onchange){ |
Obj.onchange(); |
} |
}else{ |
Input_HtmlSelect_Popup.hidePopup(); |
} |
}); |
} |
function htmlselect_PD(obj, color){ |
if(color){ |
obj.className += ' htmlselect_hover'; |
}else{ |
obj.className = obj.className.match(/^\w+/)[0]; |
} |
return 1; |
} |
// apre la finestra per selezionare la lista |
function Input_HtmlSelect_open_list(id){ |
require(["dojo/ready", "dijit/TooltipDialog", "dijit/popup", "dojo/dom"], function(ready, TooltipDialog, popup, dom){ |
ready(function(){ |
var Obj = document.getElementById(id); |
if(!Obj.Readonly()){ |
if(!Input_HtmlSelect_Popup){ |
Input_HtmlSelect_Popup = new TooltipDialog({ |
id: 'Input_HtmlSelect_Popup', |
onLoad: function(){ |
var Id = Input_HtmlSelect_Popup.Input.get_value(); // ID corrente |
var Div = document.getElementById('htmlselect_Id' + Id); |
if(Div){ // Se l'elemento è presente nella lista viene colorato diversamente |
Div.className = 'htmlselect_selected'; |
Div.scrollIntoView(); // posiziono l'elemento visibile nella finestra |
} |
%# // toglie barra scorrimento se non necessaria (vedi <div class="htmlselect_Body" ... ) |
this.containerNode.firstChild.style.overflowY = 'auto'; |
// larghezza minima pari alla larghezza del widget |
this.containerNode.firstChild.style.minWidth = Obj.DisplayDescr.scrollWidth + 'px'; |
this.focus(); |
}, |
onKeyUp: function(event){ |
if(event.keyCode == 27){ |
// chiudo la lista se uso tasto <Esc> |
popup.close(this); |
} |
} |
}); |
Input_HtmlSelect_Popup.hidePopup = function(){ |
popup.close(this); |
}; |
Input_HtmlSelect_Popup.watch('focused', function(property_name, old_val, new_val){ |
if(!new_val){ |
Input_HtmlSelect_Popup.hidePopup(); |
} |
}); |
} |
var Popup = Input_HtmlSelect_Popup; |
Popup.Input = Obj; |
require(["dojo/io-query"], function(ioQuery){ |
var query = { |
method: 'htmlselectpopup', |
V: '<%$Ver%>', |
max_width: Obj.Popup_max_width, |
max_height: Obj.Popup_max_height, |
select_key: Obj.value |
}; |
if(Obj.Empty != null){ |
query.empty = Obj.Empty; |
query.empty_descr = Obj.EmptyDescr; |
} |
if(Obj.Where){ |
query.json_where = JSON.stringify([['--where-input', Obj.Where]]); |
} |
if(Obj.displayBinding){ |
var db = Obj.displayBinding.dataBinding; |
query.child_id = db.keys[Obj.dbRow]; |
query.father_id = db.father_id; |
} |
Popup.set('href', Obj.Source + '?' + ioQuery.objectToQuery(query)); |
popup.open({ |
popup: Popup, |
around: dom.byId(id) |
}); |
}); |
} |
return false; |
}); |
}); |
} |
/tags/2.0/htdocs/input/input.js |
---|
0,0 → 1,581 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
require(["dijit/Tooltip"]); |
%#DOJO1.8 dojo.require("dijit.Tooltip"); |
dijit.Tooltip.defaultPosition = ['above-centered', 'before-centered', 'after-centered', 'below-centered']; |
function Input_EscapeHTML(str){ |
str = '' + str; |
str = str.replace(/</g, '<'); |
str = str.replace(/>/g, '>'); |
str = str.replace(/\n/g, '<br>\n'); |
return str; |
} |
function Input_Init(Objname, Descr){ |
var Obj = document.getElementById(Objname); |
%#// DOJO_1.8 BEGIN - per compatibilità con masonSql versioni ante 2013 |
window['Id_' + Objname] = Obj; |
%#// DOJO_1.8 END |
Obj.Descr = Descr; |
Obj.TooltipShowDelay = <% $r->dir_config('TooltipDelay') %>; |
Obj.setTooltip = function(Descr){ |
if(!this.TooltipObj){ |
this.TooltipObj = new dijit.Tooltip({ |
connectId: [this.id], |
showDelay: this.TooltipShowDelay, |
label: Descr |
}); |
}else{ |
this.TooltipObj.label = Descr; |
} |
}; |
Obj.setTooltip(Descr); |
if(Obj.readOnly || Obj.disabled){ |
Obj.style.cursor = 'default'; |
} |
// ritorna il valore del widget |
Obj.get_value = Input_get_value; |
// ritorna il/i parametri del campo specificato |
Obj.get_param = Input_get_param; |
// funzione per definire il valore del widget |
Obj.set_value = Input_set_value; |
// funzione per definire il/i parametri |
Obj.set_param = Input_set_param; |
// valutazione stato del widget |
Obj.eval_status = Input_eval_status; |
// applico lo stile all'oggetto widget principale |
Obj.widgetStatus = ''; |
// condizione del campo in stato di errore |
Obj.widgetError = false; |
// particolari widget possono sovrascrivere il metodo |
Obj.set_status = function(status){ |
var classList = this.eval_status(status); |
%#DEBUG <% $JSLogger->debug(q|'set_status obj '+Objname+' status:' + status + ' classList:' + classList + ' className:' + this.className|) %> |
// non applico la variazione della lista delle classi se non cambia |
if(this.className != classList){ |
this.className = classList; |
} |
} |
Obj.set_display = function(){ |
// determina il valore da visualizzare del widget |
if(this.DisplayDescr){ |
if(this.contextObj){ |
this.DisplayDescr.innerHTML = '...'; |
}else if(this.Parameters){ |
var P = this.Parameters; |
P[-1] = this.get_value(); |
this.DisplayDescr.innerHTML = Input_EscapeHTML(((this.get_value() == this.Empty || this.Parameters.length == 0) ? this.EmptyDescr : |
(this.DispTemplate != '' ? eval(this.DispTemplate) : (P[0] ? P[0] : '')).replace(/^ \| \$/,'')) + ' '); |
}else if(this.get_value() == this.Empty){ |
this.DisplayDescr.innerHTML = Input_EscapeHTML(this.EmptyDescr + ' '); |
}else{ |
this.DisplayDescr.innerHTML = Input_EscapeHTML(this.get_value() + ' '); |
} |
} |
var tooltip_mess = (this.Descr != null ? this.Descr + ': ' : (this.name ? 'Campo ' + this.name +': ' : '')) + this.get_display(); |
if(this.DisplayDescr && this.DisplayDescr.setTooltip){ |
this.DisplayDescr.setTooltip(tooltip_mess); |
} |
this.setTooltip(tooltip_mess); |
} |
Obj.get_display = function(){ |
if(this.DisplayDescr){ |
return Html2String(this.DisplayDescr.innerHTML); |
}else{ |
return this.get_value(); |
} |
} |
// metodi standard |
Obj.Readonly = Input_Readonly; |
Obj.test_value = Input_test_value; |
if(Obj.getAttribute('remote_check')){ |
// definisco il metodo se lato server è definito il metodo di risposta |
Obj.remote_test = Input_remote_test; |
} |
Obj.changeKeypress = Input_changeKeypress; |
Obj.widgetKeydown = Input_widgetKeydown; |
Obj.setFocus = Input_setFocus; |
Obj.onfocus = function (){ |
%#// ritardo l'apertuta all'infinito (quasi) |
if(this.TooltipObj){ |
this.TooltipObj.close(); |
this.TooltipObj.set('showDelay', 999999999); |
} |
if(this.Widget && this.Widget.TooltipObj){ |
this.Widget.TooltipObj.close(); |
this.Widget.TooltipObj.set('showDelay', 999999999); |
} |
this.Focus = true; |
} |
Obj.onblur = function (){ |
if(Obj.isChanged){ |
require(["dojo/on"], function(on){ |
on.emit(Obj, 'change', { |
bubbles: true, |
cancelable: true |
}); |
}); |
} |
this.Focus = null; |
%#// ripristino il ritardo |
if(this.TooltipObj){ |
this.TooltipObj.close(); |
this.TooltipObj.set('showDelay', this.TooltipShowDelay); |
} |
if(this.Widget && this.Widget.TooltipObj){ |
this.Widget.TooltipObj.close(); |
this.Widget.TooltipObj.set('showDelay', this.TooltipShowDelay); |
} |
} |
return Obj; |
} |
function Input_changeKeypress(charcode){ |
// provvedo a cambiare il carattere digitato nell'ultimo evento keypress |
// dall aversione 12 di FF in poi non funziona più |
// Vedi: |
// https://bugzilla.mozilla.org/show_bug.cgi?id=749185 |
// https://bugzilla.mozilla.org/show_bug.cgi?id=751801 |
// https://bugzilla.mozilla.org/show_bug.cgi?id=751810 |
var ev = this.currentEvent; |
var target = ev.currentTarget; |
if(target == this){ |
ev.stopPropagation(); |
ev.preventDefault(); |
var value = target.value; |
var start = target.selectionStart; |
var stop = target.selectionEnd; |
target.value = value.substr(0, start) + |
String.fromCharCode(charcode) + |
value.substr(stop); |
target.setSelectionRange(start+1, start+1); |
target.isChanged = true; |
}else{ |
my_alert(this.Descr+': chiamata di .changeKeypress senza un evento keypress pendente.', 'alert'); |
} |
} |
function Input_Readonly(read){ |
if(read == null){ |
return (this.Hidden || this.style.display == 'none' || (this.dispSpan && this.dispSpan.style.display == 'none') || this.readOnly); |
}else{ |
this.readOnly = read; |
if(this.type == 'text' || this.type == 'textarea'){ |
this.style.cursor = read ? 'default' : 'text'; |
}else{ |
this.style.cursor = read ? 'default' : 'pointer'; |
} |
this.set_status && this.set_status(); |
return (this.Hidden || this.style.display == 'none' || read); |
} |
} |
function Input_Event(ev){ |
if(ev == null){ |
console.error('Input_Event without event object'); |
my_alert('Input_Event without event object', 'alert'); |
} |
ev.chCode = ev.charCode; |
ev.currentTarget.currentEvent = ev; |
ev.normalKey = !(ev.altKey || ev.ctrlKey || ev.metaKey); |
return ev.currentTarget; |
} |
function Input_abortChange(input, e){ |
if(e){ |
e.stopPropagation(); |
e.preventDefault(); |
} |
input.focus && input.focus(); |
input.select && input.select(); |
return false; |
} |
function Input_ErrorMessage(e, message){ |
var input = Input_Event(e); |
my_alert(input.Descr+': '+message, 'alert'); |
return Input_abortChange(input, e); |
} |
function Input_ViewDescription(e){ |
} |
function Input_DeleteDescription(){ |
} |
// ritorna il valore del campo specificato |
function Input_get_value(){ |
var value; |
if(this.type == 'checkbox'){ |
value = this.checked ? 1 : '' ; |
}else if(this.type == 'text' || this.type == 'textarea' || |
this.type == 'select' || this.type == 'select-multiple' || |
this.type == 'hidden'){ |
value = this.value; |
}else{ |
value = this.innerHTML; |
} |
%#DEBUG my_alert('get_value id='+this.id+' type='+this.type+' value="'+value+'"'); |
return value; |
} |
// inizializza il valore del campo selezionato |
function Input_set_value(value, param){ |
if(param != null){ |
this.set_param(param); |
} |
if(value == null){ |
value = ''; |
} |
if(this.type=='checkbox'){ |
this.checked = (value != '' && value != '0') |
}else if(this.type=='text' || this.type=='textarea' || |
this.type=='select' || this.type=='select-one' || |
this.type=='select-multiple' || |
this.type == 'hidden'){ |
this.value = value; |
}else{ |
this.innerHTML = Input_EscapeHTML(value); |
} |
if(this.set_display){ |
this.set_display(); |
} |
} |
// ritorna il/i parametri del campo specificato |
function Input_get_param(pos){ |
var param = this.Parameters; |
%#DEBUG my_alert('get_param id='+this.id+' type='+this.type+' param="'+param+'"'); |
if(pos != null){ |
if(param){ |
return param[pos]; |
}else{ |
return null; |
} |
}else{ |
return param; |
} |
} |
function Input_set_param(param, pos, key){ |
if(pos == null){ |
this.Parameters = typeof(param) == 'object' ? param : (param ? param.split('|') : null); |
}else{ |
this.Parameters[pos] = param; |
} |
if(key && this.Cache_parameters){ |
this.Cache_parameters[key] = this.Parameters; |
} |
if(this.DisplayDescr){ |
this.set_display(); |
} |
if(this.onloadparam){ |
this.onloadparam(); |
} |
} |
// verifica la validità del dato contenuto nel campo |
// se async == false ( o null) provvede a visualizzare il messaggio |
// di errore e quindi controllare il termine del controllo remoto |
function Input_test_value(async){ |
// verifica test locale |
var str_err = this.local_test == null ? '' : this.local_test(); |
if(str_err){ |
this.widgetError = 'Error'; |
this.set_status(); |
if(!async){ |
my_alert(this.Descr + ': ' + str_err + '\n', 'alert'); |
} |
return str_err; |
} |
// verifica del test remoto |
// il metodo .remote_test, se presente ritorna: |
// false se il controllo sul campo è in esecuzione |
// '' se il controllo è andato a buon fine |
// 'messaggio di errore' se il controllo è negativo, con la stringa che descrive il problema riscontrato |
// |
var str_err = (this.remote_test == null) ? '' : this.remote_test(); |
if(!async){ |
if(typeof(str_err) == 'boolean' && !str_err){ |
this.widgetError = 'Wait'; |
this.set_status(); |
window.setTimeout("Input_test_value_Handler('" + this.id + "')", 100); |
}else if (typeof(str_err) == 'string' && str_err){ |
this.widgetError = 'Error'; |
this.set_status(); |
my_alert(this.Descr + ': ' + str_err + '\n', 'auto'); |
return str_err; |
} |
} |
if(!str_err){ |
this.widgetError = false; |
} |
this.set_status(); |
return str_err; |
} |
// chiamata periodicamente da Input_test_value() o da se stessa |
// per verificare se un test remoto si è completato; |
// provvede a visualizzare l'eventuale messaggio di errore |
function Input_test_value_Handler(id){ |
var input = document.getElementById(id); |
var str_err = input.remote_test(); |
if(str_err == null){ |
// da ignorare |
return; |
} |
if(typeof(str_err) == 'boolean' && !str_err){ |
// test ancora in corso; ricontrollo tra un po' ... |
window.setTimeout("Input_test_value_Handler('" + input.id + "')", 100); |
}else{ |
if(str_err){ |
my_alert(input.Descr + ': ' + str_err + '\n', 'alert'); |
input.focus && input.focus(); |
input.select && input.select(); |
} |
} |
} |
// controllo del campo al termine della modifica |
// e: evento passato alla chiamata di onchange |
// obj: oggetto widget (opzionale), usato se si chiama .onchange manualmente .onchange(null, this) |
function Input_change(e, obj){ |
Input_DeleteDescription(); |
var input = obj ? obj : Input_Event(e); |
input.isChanged = false; |
if(input.test_value()){ |
return Input_abortChange(input, e); |
} |
input.set_display(); |
return true; |
} |
function Input_remote_test(abort){ |
if(abort){ |
this.remote_test_result = null; |
// l'eventuale download in corso viene abortito |
var contextObj = hReqMason_ContextPool[this.hReqMason_Check]; |
if(contextObj && contextObj.busy){ |
// annullo la chiamata in corso |
contextObj.abort(); |
} |
return null; |
} |
// verifico se c'è da ritornare il risultato di una precedente chiamata |
// che ha iniziato il test |
if(this.remote_test_result != null){ |
if(typeof(this.remote_test_result) != 'boolean'){ |
// test concluso; passo il risultato |
var R = this.remote_test_result; |
// e alla prossima richiesta verrà rifatto il test |
this.remote_test_result = null; |
return R; |
}else{ |
// test ancora in esecuzione |
return this.remote_test_result; |
} |
} |
// lancio la verifica sul server |
var disp = this.displayBinding; |
var db = disp.dataBinding; |
this.remote_test_result = false; // test in progress ... |
var Values = []; |
// valori attuali nel form da inviare al server per il check |
Form2Vect(disp.fields[this.dbRow], Values); |
var params = { |
KEY: db.keys[this.dbRow], |
ID_FIELD: this.id, |
FIELD: db.names[this.dbCol], |
COL: this.dbCol, |
ROW: this.dbRow, |
VALUE: this.get_value(), |
PARAM: this.get_param(), |
RECORDSET: db.prefix, |
FATHER_ID: db.father_id, |
VALUES: Values |
}; |
this.hReqMason_Check = hReqMason_ExecuteTimeout( |
'<%$r->dir_config('DataBaseUrl')%>/'+db.from+'.mql', |
5000, |
Input_check_errorHandler, |
Input_check_Handler, |
'field_check', |
params, |
null, |
null, |
this |
); |
// ... per avvisare che il test è in esecuzione |
return this.remote_test_result; |
} |
// richiamata da hReqMason quando si presenta un errore |
function Input_check_errorHandler(contextID, err, str, Obj){ |
Obj.remote_test_result = (err != 'TIMEOUT') ? err + ': ' + str : |
'Timeout ricezione verifica del campo ' + Obj.Descr + '\n il server potrebbe non essere raggiungibile.'; |
} |
function Input_check_Handler(str, contextID, Obj){ |
// sostituisco i \n in quanto l'espressione regolare per ricercare <scr*pt>...</scr*pt> non funziona se ci |
// sono in mezzo dei \n |
var str = str.replace(/\n/g, ' '); |
// verifico se la stringa contiene una sezione di codice script |
var re = /(.*)\s*<scri{1}pt>(.*)<\/scri{1}pt>\s*(.*)/i; |
if(re.test(str)){ |
str = RegExp.$1 + (RegExp.$3 ? ' ' + RegExp.$3 : ''); |
var code = RegExp.$2; |
code = code.replace(/ /g, '\n'); |
try{ |
eval(code); |
}catch(err){ |
my_alert_error('CHECK(' + Obj.name + ')', err, code); |
} |
} |
// rimetto come prima i \n |
var str = str.replace(/ /g, '\n'); |
// tolgo spazi e \n all'inizio ed alla fine |
str = str.replace(/^\s+|\s+$/, ''); |
Obj.remote_test_result = str; |
} |
// test implementazione metodo .status |
function Input_eval_status(status, check_focus){ |
// se status è null mi limito ad aggiornare gli style |
if(status != null){ |
this.widgetStatus = status; |
} |
var RoRw = this.Readonly() ? 'Ro' : 'Rw'; |
// classe differenziata per Focus |
var classFocus = check_focus && this.Focus ? 'Focus' : ''; |
// suffisso che determina quale style utilizzare in base allo stato |
var displayStatus = this.widgetError ? this.widgetError : this.widgetStatus; |
// classe di base |
var classes = ['widget']; |
// classe differenziata di base per stato attivo |
classes.push('widget' + RoRw + displayStatus + classFocus); |
// classe differenziata per classe di widget o singolo widget |
var base_class = this.getAttribute('base_class'); |
if(base_class){ |
classes.push(base_class); |
classes.push(base_class + RoRw + displayStatus + classFocus); |
var widget_class = this.getAttribute('widget_class'); |
if(widget_class){ |
classes.push(widget_class); |
} |
} |
%#DEBUG <% $JSLogger->debug(q|'eval_status obj '+this.id+' status:' + status + ' check_focus:' + check_focus + ' classList:' + classList|) %> |
return classes.join(' '); |
} |
// chiamata dall'evento keydown |
// valutati i tasti di movimento del form per la navigazione |
// il parametro widget viene passato alla chiamata quando viene reiterato l'evento su un widget in sola lettura o disabilitato (vedi avanti nella funzione stessa) |
// se wdest è definito viene utilizzato come widget di destinazione |
function Input_keydown(event){ |
var input = Input_Event(event); |
// eventuale sotto-widget |
var widget = input.Widget ? input.Widget : input; |
if(widget.displayBinding){ |
// il widget appartiene ad un form gestito da displaybinding |
if((widget.Readonly && widget.Readonly()) || (!widget.Readonly && (widget.disabled || widget.readOnly))){ |
// solo se il widget è in modifica gestisco i caratteri di navigazione |
return false; |
} |
return widget.widgetKeydown(event, input); |
}else{ |
return true; |
} |
} |
// verifica nel caso di left/right arrow se sono all'inizio o alla fine del campo selezionato |
// ritorna vero se posso fare il salto |
function Input_checkCaretLimit(widget, event){ |
if(widget.type == 'text' || widget.type == 'textarea'){ |
if(event.keyCode == 37){ // Left arrow |
// salto solo se sono con il caret all'inizio |
return (widget.selectionStart == 0); |
}else if(event.keyCode == 39){ // Right arrow |
// salto solo se sono con il caret alla fine |
return (widget.selectionStart == widget.value.length); |
} |
} |
return true; |
} |
// event: evento che ha iniziato il processo di valutazione del widget di destinazione del focus |
// this: widget corrente da abbandonare |
// display: campo del widget da abbandonare sul quale operare le variazione dell'aspetto |
// wdest: widget di destinazione |
function Input_widgetKeydown(event, display, wdest){ |
var ro = (this.Readonly && this.Readonly()) || (!this.Readonly && (this.disabled || this.readOnly)); |
// individua il widget a cui assegnare il focus |
if(!wdest){ |
wdest = DisplayBinding_getWidget(this, event); |
if(!wdest){ |
return true; |
} |
} |
if(!display){ |
display = this; |
} |
%#DEBUG <% $JSLogger->debug(q|'Input_widgetKeydown keyCode:' + event.keyCode + ' shiftKey:' + event.shiftKey + ' from id:' + display.id + ' eval to:' + wdest.id|) %> |
if(!ro && !Input_checkCaretLimit(display, event)){ |
return true; |
} |
if(!ro){ |
if(display.type == 'text' || display.type == 'textarea'){ |
display.setSelectionRange(0, 0); |
} |
event.stopPropagation(); |
event.preventDefault(); |
display.blur(); |
} |
this.Focus = null; |
if(wdest.setFocus){ |
// se il metodo è definito posso selezionare il widget individuato |
if(!wdest.setFocus(event)){ |
// se in focus del widget non è possibile, salto al widget successivo |
wdest.widgetKeydown(event); |
} |
}else{ |
// salto il widget disabilitato o in sola lettura |
wdest.widgetKeydown(event); |
} |
return false; |
} |
// focus sul widget e selezione del testo presente |
function Input_setFocus(event){ |
%#DEBUG <% $JSLogger->debug(q|'Input_setFocus keyCode:' + event.keyCode + ' shiftKey:' + event.shiftKey|) %> |
if( (this.Readonly && this.Readonly()) || |
( this.disabled || this.readOnly || this.getAttribute('tabindex') == -1 || |
this.style.display == 'none' || this.style.visibility == 'hidden' ) |
){ |
return null; |
} |
this.Focus = true; |
if(this.DisplayDescr){ |
this.DisplayDescr.focus(); |
}else{ |
// chiamo l'evento blur e ritardo l'esecuzione per il BUG http://groups.google.com/group/mozilla.dev.tech.dom/browse_thread/thread/1d36842726345123 |
this.blur(); |
window.setTimeout(function(widget){ |
widget.focus(); |
if(widget.type == 'text' || widget.type == 'textarea'){ |
// selezione del contenuto |
widget.setSelectionRange(0, widget.value.length); |
} |
}, 1, this); |
return this; |
} |
} |
/tags/2.0/htdocs/input/select.comp |
---|
0,0 → 1,177 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Widget select |
select standard HTML |
</%doc> |
<%once> |
$Global{SelectBufferFlag}=(); |
</%once> |
<%method LIBRARY>\ |
/lib/httpRequestMason.js |
/input/input.comp |
/input/select.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
%########################################################################### MAIN |
%# $PLogger->debug(sub{ "select.comp", Dumper(\%ARGS); }); |
<%args> |
$id # identificatore del componente nel documento HTML |
$description => '' # descrizione visualizzata nella barra |
$value => undef # valore da attribuire <option selected> dopo il caricamento della lista (funziona solo se la lista è statica o caricata nel form) |
$from => undef # schema/nome documento ".mql" corrispondente ad una lista |
$where => undef # clausola where da applicare |
$empty => undef # lascia il primo campo della lista vuoto con "value" uguale al contenuto di $empty |
$empty_descr => '' # descrizione da visualizzare per il campo 'empty' |
$remote => undef # caricamento della lista differito; dal server al client |
$buffer_elements => undef # se attivo viene mantenuta una cache dei dati provenienti dal server in base ai diversi valori di Where utilizzati |
$clone => undef # identificatore di lista dalla quale copiare la lista |
$buffer => undef # codice identificatore di un "buffer" in comune tra più "select.comp" di uguale lista (stesso $from) |
# più oggetti select.comp che fanno riferimento allo stesso "buffer" avranno la lista in comune (risparmi di spazio e tempo di download) |
$rows => 1 # mumero di righe nella select; se >1 viene attivata l'opzione MULTIPLE |
$edit => undef # link all'oggetto che permette la modifica della lista |
$editmessage => '***MODIFICA***' # messaggio che verrà visualizzato in fondo alla lista per richiamare con (click) |
$editwindowparam => '' # parametri da passare alla chiamata window.open() nel browser |
$sep => ';' # separatore di lista per le selezioni multiple |
@list => () # lista degli elementi |
$id_descr => '' # identificatore campo descrizione associato del recordset da aggiornare |
$readonly => undef |
$bgcolor => undef |
$width => undef |
</%args> |
<%perl> |
if($from && $from !~ m|/|){ |
my $pfrom = $Session{ARGS}{from}; |
if($pfrom){ |
$from = $pfrom =~ m|^(\w+)/| ? $1.'/'.$from : 'public/'.$from; |
} |
} |
my $source = $from ? $r->dir_config('DataBaseUrl').'/'.$from.'.mql' : undef; |
$width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
</%perl> |
<select base_class="select" id="<%$id%>" SIZE=<% $rows>1 ? qq("$rows" MULTIPLE) : '"1"' %> <%&Args2HtmlTaglist( |
onchange => 'if(this.readOnly){return this.set_curret_value()}; Input_Select_ChangeList(event);', |
onkeydown => 'return Input_keydown(event);', |
onclick => 'if(!Input_Select_onclick(event)){return false}', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => (defined $width ? "width:${width};" : '').(defined $bgcolor ? "background-color:$bgcolor;" : '') |
)%>> |
% if($edit && !$remote){ |
<option value="<%$editmessage%>"><%$editmessage%></option> |
% } |
% if(defined $empty && !$remote){ |
<option selected value="<%$empty%>" ><%$empty_descr%></option> |
% } |
% if($m->content){ |
<%$m->content%> |
% }elsif(@list){ |
% for(my $r=0; $r<@list; $r=$r+2){ |
<option value="<%$list[$r]%>" ><%$list[$r+1]%></option> |
% } |
% }elsif($remote){ |
<option selected value="<%$empty%>" >*** In caricamento ***</option> |
% }elsif(defined $source && !defined $buffer){ |
% # ricavo la lista direttamente dal server |
% $m->comp($source.':selectoptions', json_where => to_json [['--where-input', $where]]); |
% } |
</select> |
% push @Script_buffer, $m->scomp('.defer', @_, source => $source); |
<%def .defer> |
<%args> |
$id # identificatore del componente nel documento HTML |
$description => '' # descrizione visualizzata nella barra |
$value => undef # valore da attribuire <option selected> dopo il caricamento della lista (funziona solo se la lista è statica o caricata nel form) |
$source => undef # documento ".mql" corrispondente ad una lista |
$where => undef # clausola where da applicare |
$empty => undef # lascia il primo campo della lista vuoto con "value" uguale al contenuto di $empty |
$empty_descr => '' # descrizione da visualizzare per il campo 'empty' |
$remote => undef # caricamento della lista differito; dal server al client |
$buffer_elements => undef # se attivo viene mantenuta una cache dei dati provenienti dal server in base ai diversi valori di Where utilizzati |
$clone => undef # identificatore di lista dalla quale copiare la lista |
$buffer => undef # codice identificatore di un "buffer" in comune tra più "select.comp" di uguale lista (stessa $source) |
# più oggetti select.comp che fanno riferimento allo stesso "buffer" avranno la lista in comune (risparmi di spazio e tempo di download) |
$rows => 1 # mumero di righe nella select; se >1 viene attivata l'opzione MULTIPLE |
$edit => undef # link all'oggetto che permette la modifica della lista |
$editmessage => '***MODIFICA***' # messaggio che verrà visualizzato in fondo alla lista per richiamare con (click) |
$editwindowparam => '' # parametri da passare alla chiamata window.open() nel browser |
$sep => ';' # separatore di lista per le selezioni multiple |
@list => () # lista degli elementi |
$id_descr => '' # identificatore campo descrizione associato del recordset da aggiornare |
$readonly => undef |
$bgcolor => undef |
$width => '80' |
</%args> |
<%perl> |
$width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
if(defined $buffer && defined $source && !$remote && ! defined $Global{SelectBufferFlag}->{$buffer}){ |
# in-line buffer; carico la lista direttamente nel codice |
$m->comp($source.':bufferselect', C => $buffer, json_where => to_json [['--where-input', $where]]); |
} |
$empty = defined $empty ? "'$empty'" : 'null'; |
</%perl> |
var Id_<%$id%>=Input_Select_Init('<%$id%>', '<%$id_descr%>','<%$source|js%>', <% $remote ? 'true' : 'false'%>, '<%$where|js%>','<%$edit|js%>', <%$empty%>, '<%$empty_descr|js%>', |
'<%$editmessage|js%>', '<%$editwindowparam|js%>', '<%$sep|js%>', '<%$description|js%>', <% $readonly ? 'true' : 'false'%>, <%$buffer_elements ? 'true' : 'false'%>); |
% if(defined $clone){ |
% #codice per copiare la lista da altra lista |
var S = document.getElementById('<%$clone%>'); |
var D = document.getElementById('<%$id%>'); |
var I; |
for(I=0; I<S.options.length; I++){ |
var SourceOption = S.options.item(I); |
var Option = document.createElement("OPTION"); |
Option.innerHTML = SourceOption.text; |
Option.value = SourceOption.value; |
D.appendChild(Option); |
} |
% }elsif(defined $buffer && defined $source && !$remote){ |
% # inserisco il componente nella lista dei componenti di stesso buffer |
% if(!defined $Global{SelectBufferFlag}->{$buffer}){ |
var SelectBuf_<%$buffer%> = new Array(); |
% $Global{SelectBufferFlag}->{$buffer}=1; |
% } |
Id_<%$id%>.ListEqualBuffer=SelectBuf_<%$buffer%>; |
SelectBuf_<%$buffer%>.push(Id_<%$id%>); |
Id_<%$id%>.LoadCallbackID = function (strlist){ |
%#// necessario in quanto la libreria "httpRequestMason" non chiama un metodo ma una funzione e quindi manca il riferimento all'oggetto :-( |
document.getElementById('<%$id%>').LoadCallback(strlist); |
} |
% # carico la lista richiamando la funzione che popola la select (una funzione per tutte le select di uguale "buffer") |
_PopulateSelect_<%$buffer%>(Id_<%$id%>); |
% }elsif($source && $remote){ |
% if(! defined $buffer){ |
% $buffer='Buf_'.$id; |
% } |
% if(!defined $Global{SelectBufferFlag}->{$buffer}){ |
% # primo componente "select.comp"; dichiarato (fa da master agli altri) |
% # predispongo la funzione che si occupa di caricare la lista dopo il caricamento dal server |
var SelectBuf_<%$buffer%> = new Array(); |
% $Global{SelectBufferFlag}->{$buffer}=1; |
Id_<%$id%>.ListEqualBuffer=SelectBuf_<%$buffer%>; |
SelectBuf_<%$buffer%>.push(Id_<%$id%>); |
Id_<%$id%>.LoadCallbackID = function (strlist){ |
%#// necessario in quanto la libreria "httpRequestMason" non chiama un metodo ma una funzione e quindi manca il riferimento all'oggetto :-( |
document.getElementById('<%$id%>').LoadCallback(strlist); |
} |
% # chiamata al server remoto per il caricamento della lista |
Id_<%$id%>.LoadRemote(); |
% }else{ |
% # componente "select.comp" successivo al primo; non carica la lista ma clona i dati dalla "select" master |
SelectBuf_<%$buffer%>.push(Id_<%$id%>); |
Id_<%$id%>.ListEqualBuffer=SelectBuf_<%$buffer%>; |
% } |
% } |
% if(defined $value){ |
Id_<%$id%>.set_value('<%$value|js%>'); |
% }elsif($edit){ |
Id_<%$id%>.set_value('<%$editmessage|js%>'); |
% } |
</%def> |
/tags/2.0/htdocs/input/select.js |
---|
0,0 → 1,400 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
// estrae dalla select una lista degli elementi selezionati; utilizza il separatore this.Sel |
function Input_Select_get_value(){ |
if(this.multiple){ |
var elenco = new Array(); |
// individuo l'elenco dei campi selezionati |
for(var i=0; i<this.options.length; i++){ |
var elem=this.options[i]; |
var value= elem.getAttribute('value'); |
if(elem.selected && value != this.changeMess && elem.text != this.changeMess){ |
elenco.push(value); |
}else{ |
this.Editing = false; |
elem.selected = false; |
} |
} |
this.valueSelect = elenco.join(this.Sep); |
return this.valueSelect; |
}else{ |
return this.valueSelect; |
} |
} |
// usato per i riempire il tooltip del widget |
// determina una descrizione del contenuto del widget |
function Input_Select_get_display(){ |
if(this.multiple){ |
var elenco = new Array(); |
// individuo l'elenco dei campi selezionati |
for(var i=0; i<this.options.length; i++){ |
var elem=this.options[i]; |
var value= elem.getAttribute('value'); |
if(elem.selected && value != this.changeMess && elem.text != this.changeMess){ |
elenco.push(elem.text); |
}else{ |
this.Editing = false; |
elem.selected = false; |
} |
} |
return elenco.join(this.Sep); |
}else{ |
if(this.selectedIndex == -1){ |
return this.EmptyDescr; |
}else{ |
return this.options[this.selectedIndex].text; |
} |
} |
} |
// Handler risposta in caso di errore o timeout |
function Input_Select_TimeoutData(contextID, type, str, Obj){ |
if(type == 'TIMEOUT'){ |
Obj.options[Obj.selectedIndex].innerHTML = '--- TIMEOUT rec('+Obj.value+') ---'; |
my_alert('Timeout caricamento parametri ' + Obj.id); |
}else{ |
Obj.options[Obj.selectedIndex].innerHTML = '--- ERROR rec('+Obj.value+') ---'; |
my_alert('ERRORE caricamento parametri ' + Obj.id + ' url=' +this.contextObj.URL+': \n['+str+']'); |
} |
} |
// Handler risposta caricamento dinamico dei parametri |
function Input_Select_Load_Callback(str, contextID, Obj){ |
str = str.replace(/^\s+|\s+$/g, ''); |
if(str.length > 0){ |
Obj.set_param(str, null, Obj.get_value()); |
// descrizione selezionata nel widget |
Obj.options[Obj.selectedIndex].innerHTML = str; |
} |
} |
// seleziona nella select gli elementi nella lista "value"; utilizza il separatore this.Sel |
function Input_Select_set_value(value, param){ |
if(value == null){ |
value = this.Empty; |
} |
if(param != null){ |
this.set_param(param, null, value); |
}else if(this.Remote && !this.multiple){ |
if(value == this.Empty){ |
this.set_param(null, null, value); |
}else{ |
// verifico la presenza nella cache |
var cache_param = this.Cache_parameters[value]; |
if(cache_param == null){ |
// richiedo il valore al server |
// hReqMason_ExecuteTimeout(rspage, timeout, timeout_callback, callback, func, parms, tag, obj_params, callback_obj) |
hReqMason_ExecuteTimeout( |
this.Source, |
<%$r->dir_config('GetRecordTimeout')%>, |
Input_Select_TimeoutData, |
Input_Select_Load_Callback, |
'parameters_select', |
['key', value], |
null, |
null, |
this |
); |
this.set_param(null, null, value); |
}else{ |
this.set_param(cache_param); |
} |
} |
} |
var Sep=this.Sep; |
this.valueSelect=value; |
if(this.multiple){ |
value = Sep+value+Sep; |
// per attivare la lista ricerco nella stringa la chiave con il carattere o stringa di separazione ai lati |
for(var i=0; i<this.options.length; i++){ |
var elem=this.options[i]; |
elem.selected=(value.indexOf(Sep+elem.value+Sep) >= 0); |
} |
}else{ |
this.value = value; |
if(this.value != value){ |
// la selezione non era disponibile nel widget |
// aggiungo nella lista l'elemento mancante con descrizione |
// il primo parametro disponibile o con una scritta che riposta il codice |
var descr = this.get_param(0); |
if(!descr){ |
descr = this.contextObj ? '...' : 'Elemento mancante ' + value; |
} |
var O=document.createElement("OPTION"); |
O.innerHTML=descr; |
O.value=value; |
this.selected = true; |
this.appendChild(O); |
this.value = value; |
} |
} |
if(this.set_display){ |
this.set_display(); |
} |
} |
function Input_Select_EditingEnd(){ |
if(this.Edit){ |
if(this.Editing){ |
this.Editing=false; |
var elem = this.options[0]; |
if(elem.selected && elem.value == this.changeMess && elem.text == this.changeMess){ |
elem.selected=false; |
} |
return true; |
} |
return false; |
}else{ |
return null; |
} |
} |
function Input_Select_LoadCallback(strlist, noBuffer){ |
// salvo il valore attuale del componente |
var OldVal = this.get_value(); |
while(this.childNodes.length){ |
this.removeChild(this.lastChild); |
} |
if(this.Edit){ |
var O=document.createElement("OPTION"); |
O.innerHTML=this.changeMess; |
O.value=this.changeMess; |
this.appendChild(O); |
} |
if(this.Empty != null){ |
var O=document.createElement("OPTION"); |
O.innerHTML=this.EmptyDescr; |
O.value=this.Empty; |
this.selected=true; |
this.appendChild(O); |
} |
// non escludo in bufferin nella chiamata e se e' attivo il buffering dei dati provenienti dal server |
if(!noBuffer && this.buffer_elements){ |
this.buffer_elements[this.Where] = strlist; |
} |
// Sel è la variabile utilizzata nella funzione passata dal server per puntare al componente select da inizializzare |
var Sel = this; |
try{ |
eval(strlist) |
}catch(err){ |
my_alert("ERROR function Input_Select_"+this.id+"_LoadCallback ("+(err.number&0xFFFF)+':'+err.message+") source "+this.Source+" on exec code:\n"+strlist, 'txt'); |
} |
this.style.cursor='auto'; |
// se il valore del componente è presente nelle nuove opzioni lo rispristino, altrimenti no |
var Val = null; |
for(C=this.childNodes.length-1; C>0; C--){ |
if(this.childNodes[C].value == OldVal){ |
Val = OldVal; |
break; |
} |
} |
// ripristino il valore dopo l'aggiornamento della lista |
this.set_value(Val); |
// clono le option in tutte le altre "select" con stesso buffer |
for(var C=0; C<this.ListEqualBuffer.length; C++){ |
var Child = this.ListEqualBuffer[C]; |
if(Child == this){ |
// salto la select da clonare |
continue; |
} |
// salvo il valore attuale del componente |
OldVal = Child.get_value(); |
// cancello le option presenti |
while(Child.childNodes.length){ |
Child.removeChild(Child.lastChild); |
} |
// ricopio le option dalla select master |
for(I=0; I<this.options.length; I++){ |
var SourceOption = this.options.item(I); |
var Option = document.createElement("OPTION"); |
Option.innerHTML=SourceOption.innerHTML; |
Option.value=SourceOption.value; |
Child.appendChild(Option); |
} |
// se il valore del componente è presente nelle nuove opzioni lo rispristino, altrimenti no |
var Val = null; |
for(C=Child.childNodes.length-1; C>0; C--){ |
if(Child.childNodes[C].value == OldVal){ |
Val = OldVal; |
break; |
} |
} |
// ripristino il valore dopo l'aggiornamento della lista |
Child.set_value(Val); |
Child.style.cursor='auto'; |
} |
if(this.FuncCallback){ |
this.FuncCallback(); |
} |
} |
// chiama il server per scaricare la lista |
// func_callback: funzione da richiamare dopo aver completato il caricamento |
// where: filtro di selezione della lista |
function Input_Select_LoadRemote(func_callback, where){ |
this.Remote = true; |
if(where == null || where != this.Where){ |
if(where != null){ |
this.Where = where; |
} |
if(this.ListEqualBuffer){ |
for(var C=0; C<this.ListEqualBuffer.length; C++){ |
this.ListEqualBuffer[C].style.cursor='wait'; |
} |
}else{ |
this.style.cursor='wait'; |
} |
this.FuncCallback = func_callback; |
if(this.buffer_elements && this.buffer_elements[this.Where] != null){ |
this.LoadCallback(this.buffer_elements[this.Where], true); |
}else{ |
// hReqMason_ExecuteTimeout(rspage, timeout, timeout_callback, callback, func, parms, tag, obj_params, callback_obj) |
hReqMason_ExecuteTimeout( |
this.Source, |
10000, |
Input_Select_Timeout, |
this.LoadCallbackID, |
'select', |
['json_where', JSON.stringify([['--where-input', this.Where]])], |
document |
); |
} |
} |
} |
function Input_Select_EmptyList(){ |
this.Where = '--\n'; |
this.set_value(''); |
this.LoadCallback(''); |
} |
function Input_Select_Init(Objname, Id_Descr, Source, Remote, Where, Edit, Empty, EmptyDescr, changeMess, EditWindowParam, Sep, Descr, Read, Buffer_elements){ |
var Obj = Input_Init(Objname, Descr); |
Obj.Source = Source; //Nome del file da caricare (senza .mql) |
Obj.Remote = Remote; |
Obj.Where = Where; |
Obj.Edit = Edit; |
Obj.Empty = Empty; |
Obj.EmptyDescr = EmptyDescr; |
if(Buffer_elements){ |
Obj.buffer_elements = {}; |
} |
Obj.Editing = false; |
Obj.EditWindowParam = EditWindowParam; |
Obj.changeMess = changeMess; |
Obj.Sep = Sep; |
Obj.get_value = Input_Select_get_value; |
Obj.set_value = Input_Select_set_value; |
Obj.get_display = Input_Select_get_display; |
Obj.EditingEnd = Input_Select_EditingEnd; |
Obj.ListEqualBuffer = null; |
Obj.Cache_parameters = {}; //cache dei parametri corrispondenti ai valori presenti nella lista |
Obj.LoadCallback = Input_Select_LoadCallback; |
Obj.LoadRemote = Input_Select_LoadRemote; |
Obj.EmptyList = Input_Select_EmptyList; |
Obj.Readonly = Input_Select_Readonly; |
Obj.valueSelect = null; |
Obj.Readonly(Read); |
Obj.set_curret_value = function (){ |
this.set_value(this.valueSelect); |
return false; |
}; |
Obj.get_display_value = function (){ |
return (this.options[this.selectedIndex] || '').text; |
}; |
return Obj; |
} |
// chiamata da onclick |
function Input_Select_onclick(e){ |
var input = Input_Event(e); |
if(input.readOnly){ |
return false; |
} |
} |
function Input_Select_Readonly(read){ |
if(read == null){ |
return (this.Hidden || this.style.display == 'none' || (this.dispSpan && this.dispSpan.style.display == 'none') || this.readOnly); |
}else{ |
this.readOnly = read; |
this.disabled = read ? true : false; |
this.style.cursor = read ? 'default' : 'pointer'; |
this.set_status && this.set_status(); |
return (this.Hidden || this.style.display == 'none' || read); |
} |
} |
function Input_Select_Timeout(contextID, err, str){ |
// var contextObj = hReqMason_ContextPool[contextID]; |
if(err == 'TIMEOUT'){ |
my_alert('Timeout ricezione dati ' + contextID, 'txt'); |
}else{ |
my_alert(err+': '+str, 'txt'); |
} |
} |
// richiamata ad ogni variazione della lista |
function Input_Select_ChangeList(e){ |
var input = Input_Event(e); |
// alert('id="'+input.id+'" source="'+input.Source+'" edit="'+input.Edit+'" value="'+input.options[input.selectedIndex].value+'" text="'+input.options[input.selectedIndex].text+'" changeMess="'+input.changeMess+'"'); |
if(input.Edit && input.options[input.selectedIndex].value == input.changeMess |
&& input.options[input.selectedIndex].text == input.changeMess){ |
if(input.ListEqualBuffer){ |
for(var C=0; C<input.ListEqualBuffer.length; C++){ |
input.ListEqualBuffer[C].style.cursor='wait'; |
} |
}else{ |
this.style.cursor='wait'; |
} |
input.Editing = true; |
// selezionato il campo di modifica |
// alert('EDIT id='+input.id+' source='+input.Source); |
input.EditWindow = window.open(input.Edit, 'Input_Select_Window_'+input.id, input.EditWindowParam); |
// blocco l'editing della select fino a che non chiudo la finestra di editing |
input.disabled = true; |
// metto in evidenza la finestra di editing |
input.EditWindow.focus(); |
// verifico periodicamente che la finestra sia attiva e che abbia il focus |
window.setTimeout('Input_Select_TestWindowsFocus("'+input.id+'")', 2000); |
}else{ |
// aggiorno la selezione |
input.valueSelect = input.multiple ? input.get_value() : input.value; |
input.set_value(input.valueSelect); |
if(input.test_value()){ |
return Input_abortChange(input, e); |
} |
return true; |
} |
} |
// verifico periodicamente che la finestra sia attiva e che abbia il focus |
function Input_Select_TestWindowsFocus(id){ |
var input = document.getElementById(id); |
if(input.EditWindow.closed){ |
input.EditWindow=null; |
input.style.cursor='auto'; |
input.set_value(input.valueSelect); |
// componente master (primo componente con stesso buffer, corrisponde a se stesso se $buffer non è definito) |
var Sel = input.ListEqualBuffer ? input.ListEqualBuffer[0] : input; |
Sel.LoadRemote(); |
// riabilito la select |
input.disabled = false; |
input.EditingEnd(); |
window.focus(); |
}else{ |
window.setTimeout('Input_Select_TestWindowsFocus("'+input.id+'")', 200); |
} |
} |
/tags/2.0/htdocs/input/divselect.comp |
---|
0,0 → 1,141 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Widget divselect |
testo in sola lettura di descrizione e pulsante per richiamare la lista in finestra (DIV) |
separata con gestiore dei dati attraverso l'uso di databinding |
</%doc> |
<%args> |
$id # identificatore del componente nel documento HTML |
$description => '' # descrizione visualizzata nella barra |
$value => undef # valore da attribuire <option selected> dopo il caricamento della lista (funziona solo se la lista è statica o caricata nel form) |
$from # documento corrispondente ad una lista (solo il nome, senza estensione e percorso "..../data/" |
$where => '' # clausola where da applicare |
$orderby => '' # clausola 'order by' da applicare |
$empty => undef # lascia il primo campo della lista vuoto con "value" uguale al contenuto di $empty |
$empty_descr => '' # descrizione da visualizzare per il campo 'empty' |
@buttons => () # pulsanti supplementari |
$empty_button => undef # descrizione da visualizzare nel pulsante di selezione del campo vuoto |
$insert_descr => undef # descrizione pulsante inserimento nuovo record (se undef il pulsante non viene visualizzato |
@insert_parameters => () # per indicare i parametri da aggiungere nella chiamata al form di inserimento |
@insert_copyfields => () # per indicare i campi che vanno copiati dal filtro |
$bgcolor => undef |
$width => 80 |
$length => 28 # numero di caratteri minimo da visualizzare |
$rows => 20 #numero di righe da visualizzare nella selezione |
@cols => (280) # array colonne rappresentante le larghezze di ciascuna colonna |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$query_param => '' # parametro opzionale da inviare al server ad ogni chiamata del recordset |
@fetch_params => () # elenco campi da ritornare |
$icon => 'find' # icona da utilizzare |
$cache_params => undef # se !undef attiva la cache sui parametri caricati |
$Detail_from => undef # se definita viene inserito per ciascun record un bottone per richiamare un form separato per visualizzare il record |
$Detail_width => 800 # larghezza della finestra dettaglio |
$Detail_height => 600 # altezza della finestra dettaglio |
$Detail_father => 0 # se 1 al recordset della finesta di dettaglio verrà passato l'id del record da cui è stato aperta la select |
</%args> |
% $width && ($width -= 19); # spazio del bottone |
% $width < 0 && ($width = 0); |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
% $ARGS{'width'} = $width; |
<%method LIBRARY>\ |
/lib/httpRequestMason.js |
/input/input.comp |
/input/divselect.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
%# $PLogger->debug(sub{ "divselect.comp",Dumper(\%ARGS); }); |
<span class="container" base_class="inputspan" id="<%$id%>" <%&Args2HtmlTaglist( |
style => 'background-color: transparent;', |
onchange => undef, |
onclick => "return Input_DivSelect_open_list('$id');", |
type => undef, |
widget => undef, |
descr_sep => undef, |
from => undef, |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') %>> |
<span id="display_<%$id%>" base_class="inputspan" unselectable <%&Args2HtmlTaglist( |
onchange => undef, |
onclick => undef, |
type => undef, |
widget => undef, |
descr_sep => undef, |
from => undef, |
style => (defined $width ? "width:${width};" : '').(defined $bgcolor ? "background-color:$bgcolor;" : '') |
)%>> </span> |
% if($icon){ |
<span class="dijitInline dijitIcon masonSqlIcons <%$icon%> vAlign" id="icon_<%$id%>"></span> |
% } |
</span> |
% push @Script_buffer, $m->scomp('.defer', @_); |
<%def .defer> |
<%args> |
$id |
$value => undef |
$description => '' |
$from |
$where => '' |
$orderby => '' #clausola 'order by' da applicare |
$empty => undef |
$empty_descr => '' |
@buttons => () # pulsanti supplementari |
$empty_button => undef # descrizione da visualizzare nel pulsante di selezione del campo vuoto |
$insert_descr => undef # descrizione pulsante inserimento nuovo record (se undef il pulsante non viene visualizzato |
@insert_parameters => () # per indicare i parametri da aggiungere nella chiamata al form di inserimento |
@insert_copyfields => () # per indicare i campi che vanno copiati dal filtro |
$id_descr => '' # identificatore campo descrizione associato del recordset da aggiornare |
$readonly => undef |
$rows => 20 # numero di righe da visualizzare nella selezione |
@cols => (280) # array colonne rappresentante le larghezze di ciascuna colonna |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$query_param => '' # parametro opzionale da inviare al server ad ogni chiamata del recordset |
$cache_params => undef # se !undef attiva la cache sui parametri caricati |
$Detail_from => undef # se definita viene inserito per ciascun record un bottone per richiamare un form separato per visualizzare il record |
$Detail_width => 800 # larghezza della finestra dettaglio |
$Detail_height => 600 # altezza della finestra dettaglio |
$Detail_father => 0 # se 1 al recordest della finesta di dettaglio verrà passato l'id del record da cui è stato aperta la select |
$Class => '' # se definita viene aggiunta la classe negli elementi del template |
</%args> |
<%perl> |
$empty = (defined $empty) ? "'$empty'" : 'null'; |
if(!defined $empty_button){ $empty_button = $empty_descr } |
$insert_descr = (defined $insert_descr) ? "'".$m->interp->apply_escapes($insert_descr, 'js')."'" : 'null'; |
for(my $c=0; $c<@buttons; $c++){ |
$buttons[$c] = "'".$m->interp->apply_escapes($buttons[$c], 'js')."'"; |
} |
for(my $c=0; $c<@insert_parameters; $c++){ |
$insert_parameters[$c] = "'".$m->interp->apply_escapes($insert_parameters[$c], 'js')."'"; |
} |
for(my $c=0; $c<@insert_copyfields; $c++){ |
$insert_copyfields[$c] = "'".$m->interp->apply_escapes($insert_copyfields[$c], 'js')."'"; |
} |
if($from !~ m|/|){ |
my $pfrom = $Session{ARGS}{from}; |
if($pfrom){ |
$from = $pfrom =~ m|^(\w+)/| ? $1.'/'.$from : 'public/'.$from; |
} |
} |
</%perl> |
var Id_<%$id%> = Input_DivSelect_Init('<%$id%>', '<%$id_descr%>', '<%$from|js%>', '<%$where|js%>', |
'<%$orderby|js%>', <%$insert_descr%>, [<%join ',', @insert_parameters%>], |
[<%join ',', @insert_copyfields%>], |
<%$empty%>, '<%$empty_descr|js%>', '<%$empty_button|js%>', '<%$description|js%>', |
<% $readonly ? 'true' : 'false'%>, <% $rows %>, [<%join ',', @cols%>], |
[<%join ',', @buttons%>], '<% $disp_template ? $disp_template : ''|js%>', |
'<%$query_param|js%>', <%$cache_params ? 'true' : 'false'%>, |
<%defined $Detail_from ? "'".$m->interp->apply_escapes($Detail_from, 'js')."'" : 'null'%>, |
<%defined $Detail_width ? $Detail_width : 'null'%>,<%defined $Detail_height ? $Detail_height : 'null'%>, <%$Detail_father%>, '<% $Class %>'); |
<% &ArgsOnly2JscriptTaglist("Id_$id", onchange => undef) %> |
% if(defined $value){ |
Id_<%$id%>.set_value('<%$value|js%>'); |
% } |
</%def> |
/tags/2.0/htdocs/input/form.comp |
---|
0,0 → 1,65 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/form.js |
/lib/httpRequestMason.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
$width => undef |
$bgcolor => undef |
$popupWidth => 800 |
$popupHeight => 600 |
$from # documento corrispondente ad una lista (solo il nome, senza estensione e percorso "..../data/" |
$where => '' # clausola where da applicare |
$orderby => '' # clausola 'order by' da applicare |
$empty => undef # lascia il primo campo della lista vuoto con "value" uguale al contenuto di $empty |
$empty_descr => '' # descrizione da visualizzare per il campo 'empty' |
%formParameters => {} |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$query_param => '' # parametro opzionale da inviare al server ad ogni chiamata del recordset |
$icon => 'find' # icona da utilizzare |
</%args> |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
<a base_class="inputspan" id="<%$id%>" <%&Args2HtmlTaglist( |
onclick => "return this.formClick();", |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);')%>> |
<span base_class="inputspan" id="display_<%$id%>" <%&Args2HtmlTaglist( |
onclick => undef, |
style => (defined($width) ? "width:$width;" : '').(defined($bgcolor) ? "background-color:$bgcolor;" : '')) |
%>><%$value|h%> </span> |
% if($icon){ |
<span class="dijitInline dijitIcon masonSqlIcons <%$icon%> vAlign" id="icon_<%$id%>"></span> |
% } |
</a>\ |
<%perl> |
# ".jsonToObj(%formParameters)." |
if($id){ |
$empty = (defined $empty) ? "'$empty'" : 'null'; |
push @Script_buffer, "var Id_$id = Input_Form_Init('$id', '".$m->interp->apply_escapes($description, 'js'). |
"', $empty, '".$m->interp->apply_escapes($empty_descr, 'js'). |
"', '".$m->interp->apply_escapes($from, 'js')."', '".$m->interp->apply_escapes($where, 'js'). |
"', '".$m->interp->apply_escapes($orderby, 'js')."', ".objToJson(\%formParameters).", ".($readonly ? 'true':'false'). |
", $popupWidth, $popupHeight, ". |
"'".$m->interp->apply_escapes($disp_template, 'js'). |
"', '".$m->interp->apply_escapes($query_param, 'js'). |
"');\n"; |
} |
</%perl> |
/tags/2.0/htdocs/input/codfisc_pi.comp |
---|
0,0 → 1,42 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/codfisc_pi.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$size => 16 |
$trans => 'U' # U:upper - caratteri tutti maiuscoli; L: lower - caratteri tutti minuscoli |
$description => '' |
$readonly => undef |
$width => undef |
</%args> |
<%perl> |
if(!$width){ |
$width = int($size * ($trans eq 'U' ? 8.125 : 6.875)); |
} |
$width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
</%perl> |
<input <%$readonly ? 'readOnly':''%> type="text" base_class="string" id="<%$id%>" value="<%$value%>" size="<%$size%>" maxlength="<%$size%>" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_Codfisc_pi_keypress(event);', |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => defined $width ? "width:${width};" : '') |
%>> |
% if($id){ |
% push @Script_buffer, "var Id_$id = Input_Codfisc_pi_Init('$id', '".$m->interp->apply_escapes($description, 'js')."','".$m->interp->apply_escapes($trans, 'js')."');\n"; |
% } |
/tags/2.0/htdocs/input/input_group.js |
---|
0,0 → 1,239 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2017 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_group_Init(Objname, Descr, Format, Suffixes){ |
var Obj = Input_Init(Objname, Descr); |
// Format of value (Json or list separated by Type char |
if(Format.toLowerCase() == 'json'){ |
Obj.json = true; |
}else{ |
Obj.sep = Format; |
} |
// array, list of widgets suffix |
Obj.suffix = Suffixes.split(' '); |
// is arrow management active? |
Obj.active_arrows = Obj.displayBinding ? (Obj.displayBinding.formKeysMovement.search('ARROWS') != -1) : false; |
// list of widgets |
Obj.widgets = []; |
for(var pos=0; pos<Obj.suffix.length; pos++){ |
var widget = document.getElementById(Objname + '_' + Obj.suffix[pos]); |
Obj.widgets[pos] = widget; |
widget.Widget = Obj; |
widget.Widget_pos = pos; |
widget.onkeydown = Input_group_onkeydown; |
} |
Obj.onafterupdate = function(){ |
eval(this.onchange); |
} |
Obj.Input_widgetKeydown = Input_widgetKeydown; |
Obj.setFocus = Input_group_setFocus; |
Obj.set_obj = Input_group_set_obj; |
Obj.set_value = Input_group_set_value; |
Obj.get_obj = Input_group_get_obj; |
Obj.get_value = Input_group_get_value; |
Obj.local_test = Input_group_local_test; |
Obj.Readonly = Input_group_readonly; |
Obj.set_status = Input_group_set_status; |
Obj.set_display_children = Input_group_set_display_children; |
Obj.set_display = Input_group_set_display; |
Obj.set_status(); |
return Obj; |
} |
function Input_group_get_obj(){ |
var hash = {}; |
var no_empty; |
for(var pos=0; pos<this.suffix.length; pos++){ |
var val = this.widgets[pos].get_value(); |
if(val != null && val != ''){ |
hash[this.suffix[pos]] = val; |
no_empty = true; |
} |
} |
return no_empty ? hash : null; |
} |
function Input_group_get_value(){ |
if(this.json){ |
var obj = this.get_obj(); |
var val = obj ? JSON.stringify(obj) : ''; |
// return original set value if widget values are not changed |
return this.value_set == val ? this.value_orig : val; |
}else{ |
var array = []; |
var no_empty; |
for(var pos=0; pos<this.suffix.length; pos++){ |
var val = this.widgets[pos].get_value(); |
if(val != null && val != ''){ |
no_empty = true; |
} |
array.push(val); |
} |
return no_empty ? array.join(this.sep) : ''; |
} |
} |
function Input_group_set_obj(hash){ |
if(hash == null || hash == ''){ |
for(var pos=0; pos<this.suffix.length; pos++){ |
this.widgets[pos].set_value(hash); |
} |
}else{ |
for(var pos=0; pos<this.suffix.length; pos++){ |
var value = hash[this.suffix[pos]]; |
this.widgets[pos].set_value(value == null ? '' : value); |
} |
} |
this.set_display(); |
} |
function Input_group_set_value(value, param){ |
if(param != null){ |
this.set_param(param); |
} |
if(value == null || value == ''){ |
this.set_obj(value); |
}else{ |
if(this.json){ |
// save original set to return with .get_value if value are not changed |
this.value_orig = value; |
var hash = JSON.parse(value); |
if(hash == null){ |
console.error('Parsing JSON error on field ' + this.id, value, this); |
my_alert('Parsing JSON error on field ' + this.id + ' value ['+value+']'); |
this.set_obj(null); |
}else{ |
this.set_obj(hash); |
} |
// save value as parsed by .get_value (used to compare in .get_value) |
this.value_set = null; |
this.value_set = this.get_value(); |
}else{ |
var array = value.split(sep, this.suffix.length); |
for(var pos=0; pos<this.suffix.length; pos++){ |
this.widgets[pos].set_value(array[pos]); |
} |
} |
this.set_display(); |
} |
} |
function Input_group_set_display_children(){ |
for(var pos=0; pos<this.suffix.length; pos++){ |
var widget = this.widgets[pos]; |
var tooltip_text = (widget.Descr ? widget.Descr : 'Campo ' + widget.name) + ': ' + widget.get_value(); |
widget.setTooltip(tooltip_text); |
} |
} |
function Input_group_set_display(){ |
this.set_display_children(); |
} |
function Input_group_set_status(status){ |
for(var pos=0; pos<this.suffix.length; pos++){ |
this.widgets[pos].set_status(status); |
} |
} |
function Input_group_readonly(set){ |
if(set == null){ |
return this.readOnly; |
}else{ |
this.readOnly = set; |
for(var pos=0; pos<this.suffix.length; pos++){ |
this.widgets[pos].Readonly(set); |
} |
this.set_status(); |
return set; |
} |
} |
function Input_group_local_test(){ |
var error = []; |
for(var pos=0; pos<this.suffix.length; pos++){ |
var widget = this.widgets[pos]; |
if(widget.local_test != null){ |
var err = widget.local_test(); |
if(err){ |
error.push(err); |
widget.eval_status('Error'); |
Input_abortChange(widget); |
}else{ |
widget.eval_status(''); |
} |
} |
} |
if(error.length){ |
var err = error.join('\n'); |
return err.replace(/^\s+|\s+$/, ''); |
}else{ |
return ''; |
} |
} |
function Input_group_onkeydown(ev){ |
if(!ev){ |
ev = window.event; |
} |
var input = Input_Event(ev); |
var widget = input.Widget; |
if(widget.Readonly()){ |
return false; |
} |
var wdest; //widget destination |
if((ev.keyCode == 9 && !ev.shiftKey) || (ev.keyCode == 39 && widget.active_arrows) ){ // TAB o Right arrow |
for(var pos = input.Widget_pos + 1; pos < widget.widgets.length; pos++){ |
var widget = widget.widgets[pos]; |
if(widget.getAttribute('tabindex') != -1){ |
wdest = widget; |
break; |
} |
} |
}else if((ev.keyCode == 9 && ev.shiftKey) || (ev.keyCode == 37 && widget.active_arrows) ){ // Shift-TAB o Left arrow |
for(var pos = input.Widget_pos -1; pos >= 0; pos--){ |
var widget = widget.widgets[pos]; |
if(widget.getAttribute('tabindex') != -1){ |
wdest = widget; |
break; |
} |
} |
} |
if(!wdest){ |
wdest = DisplayBinding_getWidget(widget, ev); |
} |
if(!wdest){ |
return true; // propaga evento per risposta standard |
} |
return widget.Input_widgetKeydown(ev, input, wdest); |
} |
function Input_group_setFocus(ev){ |
if((ev.keyCode == 9 && ev.shiftKey) || ev.keyCode == 37 || ev.keyCode == 38){ // Shift-TAB o Left arrow o Up arrow |
// il primo widget in fondo alla lista |
var pos = this.widgets.length - 1; |
var step = -1; |
}else{ |
// il widget in cima alla lista |
var pos = 0; |
var step = 1; |
} |
// salto i widget esclusi |
while(this.widgets[pos].getAttribute('tabindex') == -1){ |
pos += step; |
if(step == 1 ? pos >= this.widgets.length : pos < 0){ |
// fuori range |
return null; |
} |
} |
var widget = this.widgets[pos]; |
return widget.setFocus(); |
} |
/tags/2.0/htdocs/input/checkbox.comp |
---|
0,0 → 1,43 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2017 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/checkbox.js |
</%method> |
<%init> |
&LoadHeader('SELF'); |
</%init> |
<%shared> |
my $checked=''; |
</%shared> |
<%args> |
$id |
$value => '' |
$description => '' |
$label_class => undef |
$readonly => undef |
$style => undef |
</%args> |
<span class="container" id="checkboxspan_<%$id%>" style="<%$style%>"> |
<input tabindex="-1" id="<%$id%>" type="checkbox" value-type="boolean" base_class="checkbox" <% $value ? 'CHECKED' : ''%> |
label_class=<%$label_class ? 'LabelChk' : ''%> |
<%&Args2HtmlTaglist( |
onmouseover => 'Input_ViewDescription(event);', |
onkeydown => 'return Input_keydown(event);', |
onclick => 'if(this.readOnly){return false}', |
onchange => 'Input_change(event);', |
onmouseout => 'Input_DeleteDescription(event);' |
)%>/>\ |
% if($label_class){ |
<label id="label_<%$id%>" for="<%$id%>" class="<%$label_class%>"/>\ |
% } |
</span> |
% push @Script_buffer, "var Id_$id = Input_Checkbox_Init('$id', '".$m->interp->apply_escapes($description, 'js')."', ".($readonly ? 'true':'false').");\n"; |
/tags/2.0/htdocs/input/checkbox.js |
---|
0,0 → 1,62 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2017 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Checkbox_Init(Objname, Descr, readOnly){ |
var Obj = Input_Init(Objname, Descr); |
var cbs = Obj.Checkboxspan = document.getElementById('checkboxspan_'+Objname); |
var lbl = document.getElementById('label_'+Objname); |
if(lbl){ |
Obj.TooltipObj = new dijit.Tooltip({ |
connectId: lbl, |
showDelay: Obj.TooltipShowDelay, |
label: Descr |
}); |
Obj.setTooltip(Descr); |
Obj.Label = lbl; |
} |
cbs.Widget = Obj; |
cbs.TooltipShowDelay = Obj.TooltipShowDelay; |
cbs.setTooltip = Obj.setTooltip; |
Obj.Readonly(readOnly); |
Obj.set_status = function(status){ |
var classList = this.eval_status(status, true); |
// non applico la variazione della lista delle classi se non cambia |
if(this.Checkboxspan.className != classList){ |
this.Checkboxspan.className = classList; |
} |
} |
Obj.set_display = function (){ |
var tooltip_text = (this.Descr ? this.Descr : 'Campo ' + this.name) + ': ' + (this.get_value() ? 'selezionato' : 'non selezionato'); |
this.setTooltip(tooltip_text); |
this.Checkboxspan.setTooltip(tooltip_text); |
} |
Obj.set_status(); |
Obj.onfocus = function (event){ |
if(event){ |
var input = Input_Event(event); |
input.Focus = true; |
input.set_status(); |
}else{ |
return false; |
} |
} |
Obj.onblur = function (event){ |
if(event){ |
var input = Input_Event(event); |
input.Focus = false; |
input.set_status(); |
}else{ |
return false; |
} |
} |
Obj.set_status(); |
return Obj; |
} |
/tags/2.0/htdocs/input/number.js |
---|
0,0 → 1,127 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Number_Init(Objname, Descr, NumDec, NumCifre, ValMax, ValMin, AllNumDec, ReturnNumDec){ |
var Obj = Input_Init(Objname, Descr); |
Obj.NumDec = NumDec; |
Obj.NumCifre = NumCifre; |
Obj.maxLength = Obj.NumCifre; |
Obj.ValMax = ValMax; |
Obj.ValMin = ValMin; |
Obj.AllNumDec = AllNumDec; |
Obj.ReturnNumDec = ReturnNumDec; |
Obj.get_value = Input_Number_get_value; |
Obj.set_value = Input_Number_set_value; |
Obj.local_test = Input_Number_test_value; |
Obj.set_status(); |
return Obj; |
} |
// metodo .local_test verifica la validità del numero presente nel campo |
function Input_Number_test_value(){ |
with(this){ |
// se il campo contiene valori non numerici viene svuotato |
if(value==" " || value=='NaN'){ |
value=''; |
}; |
if(isNaN(parseFloat(value))){ |
value = ''; |
} |
if(value != ''){ |
try{ |
if(NumDec != null){ |
var Dec = Math.pow(10, NumDec); |
var Num = '' + Math.round(Dec*value)/Dec; |
if(AllNumDec && NumDec > 0){ |
// aggiungo eventuali zeri di cifre decimali |
var pos_dec = Num.indexOf('.'); |
if(pos_dec == -1){ |
Num = '' + Num + '.'; |
pos_dec = Num.length -1; |
} |
for(I=(AllNumDec - Num.length + pos_dec + 1); I>0; I--){ |
Num += '0'; |
} |
} |
value = Num; |
} |
}catch(err){}; |
// verifico il rispetto di NumCifre |
if(value.length > NumCifre){ |
return "Il valore deve avere al massimo "+NumCifre+" cifre"; |
} |
//verifico il rispetto di ValMin e ValMax |
if(parseFloat(value) > ValMax){ |
return "Il valore deve essere minore o uguale a "+ValMax; |
} |
if(parseFloat(value) < ValMin){ |
return "Il valore deve essere maggiore o uguale a "+ValMin; |
} |
} |
} |
} |
function Input_Number_keypress(e){ |
var input = Input_Event(e); |
var charcode = e.chCode; |
//my_alert("charCode:"+charcode+" char="+String.fromCharCode(charcode)); |
if(e.normalKey && charcode){ |
var key = String.fromCharCode(charcode); |
var reValidChars = /[\-\d\.]/; |
if (!reValidChars.test(key) ) { |
// alert( "Carattere ("+key+":"+charcode+") non valido"); |
return false; |
} |
// segno meno solo se campo vuoto |
if(key == '-' && input.value.length){ |
return false; |
} |
// verifico se il punto è gia stato usato |
re = /\.(.*)/; |
if(key == '.' && input.value.search(re)!=-1){ |
return false; |
} |
} |
} |
// ritorna il valore del campo specificato |
function Input_Number_get_value(){ |
var Num = this.value; |
if(this.ReturnNumDec){ |
// conteggio le cifre decimali |
var pos_dec = Num.indexOf('.'); |
if(pos_dec == -1){ |
Num += '.'; |
pos_dec = Num.length; |
} |
for(I=(this.ReturnNumDec - Num.length + pos_dec); I>0; I--){ |
// aggiungo cifre non significative |
Num += '0'; |
} |
} |
return Num; |
} |
// inizializza il valore del campo selezionato |
function Input_Number_set_value(value, param){ |
if(param != null){ |
this.set_param(param); |
} |
this.value = value; |
var str_err = this.local_test(); |
if(str_err){ |
this.widgetError = 'Error'; |
this.set_status(); |
} |
if(this.set_display){ |
this.set_display(); |
} |
} |
/tags/2.0/htdocs/input/Files.comp |
---|
0,0 → 1,93 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2011 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# |
# widget tree filesystem |
# |
# |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/Files.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$from => undef |
$id |
$description => '' |
$readonly => undef |
$delete_if_update => 1 # abilita la cancellazione di file/cartelle con il permesso di modifica |
</%args> |
% # campo nascosto utilizzato quale contenitore per tutte le voci del componente complesso |
<span base_class="Files" id="<%$id%>"> |
<div class="container" id="<%$id%>_tree"></div> |
</span> |
<%perl> |
push @Script_buffer, "var Id_$id = Input_Files_Init('$id', '". |
$m->interp->apply_escapes($description, 'js')."', ". |
($readonly ? 'true' : 'null').", ". |
($from ? "'$from'" : 'null').", '". |
$m->interp->apply_escapes($value, 'js')."', ". |
($delete_if_update ? 'true' : 'false').");\n"; |
</%perl> |
<%shared> |
</%shared> |
<%method HTML_BODY> |
<div style="display:none" id="Input_Files_commons"> |
<div data-dojo-type="dijit/Menu" id="Input_Files_tree_menu"> |
<div id="Input_Files_download" data-dojo-type="dijit/MenuItem" onClick="Input_Files_TreeNodeObj.tree.download_item(null, 'save');">Scarica sul PC</div> |
<div id="Input_Files_zipDownload" data-dojo-type="dijit/MenuItem" onClick="Input_Files_TreeNodeObj.tree.download_item(null, 'zipSave');">Scarica ZIP sul PC</div> |
<div id="Input_Files_tgzDownload" data-dojo-type="dijit/MenuItem" onClick="Input_Files_TreeNodeObj.tree.download_item(null, 'tgzSave');">Scarica TGZ sul PC</div> |
<div id="Input_Files_rename" data-dojo-type="dijit/MenuItem">Rinomina</div> |
<div id="Input_Files_upload" data-dojo-type="dijit/MenuItem" >Carica nel server</div> |
<div id="Input_Files_new_folder" data-dojo-type="dijit/MenuItem">Nuova cartella</div> |
<div id="Input_Files_trash" data-dojo-type="dijit/MenuItem" iconClass="masonSqlIcons delete">Cestina</div> |
% if($Session{Group_Admins}){ |
<div id="Input_Files_delete" data-dojo-type="dijit/MenuItem" iconClass="dijitEditorIcon dijitEditorIconDelete">Cancella</div> |
% } |
<div id="Input_Files_history" data-dojo-type="dijit/MenuItem" iconClass="dijitEditorIcon dijitEditorIconRedo">Versioni</div> |
</div> |
<div data-dojo-type="dijit/TooltipDialog" id="Input_Files_tree_dialog"> |
<input id="Input_Files_tree_dialog_name" type="text" style="width:300px;"> |
<button id="Input_Files_tree_dialog_btn" onclick="dijit.byId('Input_Files_tree_menu').close_tree_dialog();" data-dojo-type="dijit/form/Button">OK</button> |
<button onclick="dijit.popup.close(dijit.byId('Input_Files_tree_dialog'))" data-dojo-type="dijit/form/Button">Annulla</button> |
</div> |
<div data-dojo-type="dijit/TooltipDialog" id="Input_Files_trash_dialog"> |
<div>Sei certo di voler cestinare?</div><br> |
<button id="trash_dialog_btn" onclick="Input_Files_TreeNodeObj.tree.delete_item();" data-dojo-type="dijit/form/Button">Cestina</button> |
<button onclick="dijit.popup.close(dijit.byId('Input_Files_trash_dialog'))" data-dojo-type="dijit/form/Button">Annulla</button> |
</div> |
% if($Session{Group_Admins}){ |
<div data-dojo-type="dijit/TooltipDialog" id="Input_Files_delete_dialog"> |
<div>Sei certo di voler cancellare definitivamente?</div><br> |
<button id="delete_dialog_btn" onclick="Input_Files_TreeNodeObj.tree.delete_item();" data-dojo-type="dijit/form/Button">Cancella</button> |
<button onclick="dijit.popup.close(dijit.byId('Input_Files_delete_dialog'))" data-dojo-type="dijit/form/Button">Annulla</button> |
</div> |
% } |
<div data-dojo-type="dijit/TooltipDialog" id="Input_Files_upload_dialog"> |
<form method="post" action="/archive/upload.mason" id="Input_Files_upload_form" enctype="multipart/form-data" style="width:420px;"> |
<fieldset> |
<legend>Carica nel server</legend> |
<input class="browseButton" name="uploadedfile" multiple="true" type="file" style="width:140px;" |
data-dojo-type="dojox/form/Uploader" label="Selezionare i file" id="Input_Files_uploader" /> |
<input type="button" id="remBtn" label="Svuota lista" onClick="dijit.byId('Input_Files_files').reset();" data-dojo-type="dijit/form/Button" /> |
<input type="hidden" id="Input_Files_upload_dir" name="upload_dir" /> |
<input type="submit" label="Invia al server" data-dojo-type="dijit/form/Button" id="Input_Files_submit"/> |
<button onclick="dijit.byId('Input_Files_uploader').reset();dijit.byId('Input_Files_files').reset();dijit.popup.close(dijit.byId('Input_Files_upload_dialog'))" data-dojo-type="dijit/form/Button">Annulla</button> |
<div id="Input_Files_files" data-dojo-type="dojox/form/uploader/FileList" uploaderId="Input_Files_uploader" |
headerIndex="Indice" headerType="Tipo" headerFilename="Nome file" headerFilesize="Dimensione" |
></div> |
</fieldset> |
</form> |
</div> |
</div> |
</%method> |
/tags/2.0/htdocs/input/FCKeditor.comp |
---|
0,0 → 1,52 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/lib/FCKeditor/fckeditor.js |
/input/FCKeditor.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$width => '100%' |
$height => '400' |
$editWidth => '100%' |
$editHeight => '400' |
$readonly => undef |
$bgcolor => undef |
</%args> |
%# per agganciare l'editor (verrà caricato solo alla prima occasione di modifica) |
<textarea id="<%$id%>_FCKeditor" style="display:none;"></textarea><br> |
%# usato per visualizzare quando il widget è in sola lettura |
<div disabled base_class="inputdiv" id="<%$id%>" <%&Args2HtmlTaglist( |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => 'float: none; overflow:auto; display:block; white-space: normal;'. |
(defined $bgcolor ? " background-color:$bgcolor;" : '') |
)%>>\ |
</div> |
<%perl> |
$description = $m->interp->apply_escapes($description, 'js'); |
$value = $m->interp->apply_escapes($value, 'js'); |
$width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
$height = !$height || $height =~ m/[^\d]/ ? $height : $height.'px'; |
$editWidth = !$editWidth || $editWidth =~ m/[^\d]/ ? $editWidth : $editWidth.'px'; |
$editHeight = !$editHeight || $editHeight =~ m/[^\d]/ ? $editHeight : $editHeight.'px'; |
my $ro = $readonly ? 'true' : 'false'; |
push @Script_buffer, qq| |
var Id_$id = Input_FCKeditor_Init('$id', '$value', '$description', '$width', '$height', '$editWidth', '$editHeight'); |
Id_$id.Readonly($ro) |
|; |
</%perl> |
/tags/2.0/htdocs/input/FCKeditor.js |
---|
0,0 → 1,118 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
%# Force compatible test for use with Webkit browsers (Safari) |
FCKeditor.prototype._IsCompatibleBrowser = function(){ return true }; |
function Input_FCKeditor_Init(Objname, Value, Descr, Width, Height, editWidth, editHeight){ |
var Obj = Input_Init(Objname, Descr); |
Obj.Textarea = document.getElementById(Objname + '_FCKeditor'); |
Obj.style.width = Width; |
Obj.style.height = Height; |
Obj.editWidth = editWidth; |
Obj.editHeight = editHeight; |
Obj.FCKcontainer = Obj; |
Obj.get_value = function (){ |
var value; |
if(this.SetReadonly || !this.oEditor){ |
value = this.FCKcontainer.innerHTML; |
}else{ |
value = this.oEditor.GetXHTML(true); |
} |
//alert('get_value of ' + this.id + ':' + value); |
return value; |
} |
Obj.set_value = function (value){ |
//my_alert('set_value of ' + this.id + ':' + value); |
if(this.SetReadonly || !this.oEditor){ |
this.FCKcontainer.innerHTML = value; |
}else{ |
this.oEditor.SetHTML(value, true); |
} |
} |
// stato di partenza del widget in sola lettura |
Obj.SetReadonly = true; |
// metodo per disporre in sola lettura/scrittura il widget |
Obj.Readonly = function (set) { |
//alert('Readonly from ' + this.SetReadonly + ' to ' + set); |
if(set == null){ |
// senza parametro, ritorna lo stato attuale |
return this.SetReadonly; |
} |
if(this.SetReadonly == set){ |
// già nello stato richiesto |
return set; |
} |
if(set){ |
// set in sola lettura |
if(this.oEditor){ |
// recupero il contenuto |
this.FCKcontainer.innerHTML = this.oEditor.GetXHTML(true); |
// nascondo l'editor |
this.FCKeditorFrame.style.display = 'none'; |
} |
// visualizzo il widget in lettura |
this.style.display = 'block'; |
}else{ |
// set in modifica |
this.style.display = 'none'; |
if(this.oEditor){ |
this.oEditor.SetHTML(this.FCKcontainer.innerHTML); |
this.FCKeditorFrame.style.display = 'block'; |
}else{ |
// componente FCKeditor non ancora caricato ... |
var oFCKeditor = new FCKeditor(this.id + '_FCKeditor') ; |
oFCKeditor.Width = this.editWidth; |
oFCKeditor.Height = this.editHeight; |
// alert('Width='+oFCKeditor.Width+' Height='+oFCKeditor.Height); |
oFCKeditor.BasePath = '/lib/FCKeditor/'; |
oFCKeditor.Config['CustomConfigurationsPath'] = '/lib/FCKeditor_config.js'; |
oFCKeditor.ToolbarSet = 'MyToolbar'; |
oFCKeditor.ReplaceTextarea(); // textarea utilizzata come ancora |
this.oFCKeditor = oFCKeditor; |
} |
//this.oEditor = FCKeditorAPI.GetInstance(this.id + '_FCKeditor'); |
} |
this.SetReadonly = set; |
return set; |
} |
// funzione richiamata al termine del caricamento di FCKeditor |
Obj.OnCompleteFCKeditor = function (editorInstance){ |
this.oEditor = FCKeditorAPI.GetInstance(editorInstance.Name); |
this.oEditor.SetHTML(this.FCKcontainer.innerHTML, true); |
} |
Obj.set_status(); |
Obj.set_value(Value); |
Obj.setFocus = null; |
return Obj; |
} |
// ATTENZIONE: la funzione FCKeditor_OnComplete andrà spostata in una libreria generalizzata quando |
// l'editor FCKeditor verrà utilizzato in widget differenti; per ora è dichiarato qui |
// funzione richiamata al termine del caricamento del widget |
function FCKeditor_OnComplete(editorInstance){ |
var widget_name = editorInstance.Name.replace(/_FCKeditor$/, ''); |
var widget = document.getElementById(widget_name); |
if(widget){ |
// frame che contiene l'editor |
widget.FCKeditorFrame = document.getElementById(editorInstance.Name + '___Frame'); |
if(widget.OnCompleteFCKeditor){ |
widget.OnCompleteFCKeditor(editorInstance); |
} |
} |
} |
/tags/2.0/htdocs/input/button.js |
---|
0,0 → 1,49 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Button_Init(Objname, Descr, Value, CaptionValue){ |
var Obj = Input_Init(Objname, Descr); |
// metodo per la lettura del valore del componente |
Obj.Readonly = Input_Button_Readonly; |
Obj.get_value = function () { |
return this.Value; |
} |
// metodo per il caricamento del valore del componente |
Obj.set_value = function (value, param) { |
this.Value = value; |
if(param != null){ |
this.set_param(param); |
} |
// disabilito il pulsante se non c'è valore del campo |
this.disabled = this.readOnly = (value == '' || value == null || value == false || value == 0); |
if(this.CaptionValue){ |
this.value = value; |
} |
this.set_status(); |
} |
Obj.set_value(Value); |
Obj.setFocus = null; |
Obj.CaptionValue = CaptionValue; |
return Obj; |
} |
function Input_Button_Readonly(read){ |
if(read == null){ |
return (this.Hidden || this.style.display == 'none' || (this.dispSpan && this.dispSpan.style.display == 'none') || this.readOnly); |
}else{ |
this.readOnly = read; |
this.disabled = read; |
this.style.cursor = read ? 'default' : 'pointer'; |
this.set_status && this.set_status(); |
return (this.Hidden || this.style.display == 'none' || read); |
} |
} |
/tags/2.0/htdocs/input/color.js |
---|
0,0 → 1,175 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Color_Init(Objname, Descr, ReadOnly, ConvertToHex){ |
var Obj = Input_Init(Objname, Descr); |
Obj.convertToHex = ConvertToHex; |
Obj.hexValue = '#ffffff'; |
Obj.icon = document.getElementById('icon_' + Objname); |
Obj.get_value = Input_Color_get_value; |
Obj.Readonly = Input_Color_Readonly; |
Obj.Readonly(ReadOnly); |
require(["dojo/_base/Color"], function(){ |
Obj.set_value = Input_Color_set_value; |
Obj.local_test = Input_Color_local_test; |
}); |
if(Obj.local_test()){ |
Obj.set_value(''); |
} |
return Obj; |
} |
function Input_Color_Readonly(Set){ |
if(Set == null){ |
return this.readOnly; |
}else{ |
var icon = this.icon; |
require(["dojo/dom-style", "dojo/dom-class"], function(domStyle, domClass){ |
if(icon){ |
domStyle.set(icon,'cursor', Set ? 'default' : 'pointer'); |
domClass[Set ? 'add' : 'remove'](icon, 'dijitDisabled'); |
} |
}); |
this.readOnly = Set; |
this.set_status(); |
return Set; |
} |
} |
var Input_Color_Picker; |
function Input_Color_open_color_picker(id){ |
require(["dojox/widget/ColorPicker", "dijit/popup", "dojo/dom-class","dojo/domReady!"], |
function(ColorPicker, popup, domClass){ |
if(!Input_Color_Picker){ |
Input_Color_Picker = new ColorPicker({ |
onChange: function(val){ |
if(Input_Color_Picker.Input){ |
Input_Color_Picker.Input.set_value(val); |
Input_Color_Picker.Input.onchange(); |
Input_Color_Picker.Input = null; |
popup.close(this); |
} |
} |
}, 'Input_Color_Picker'); |
Input_Color_Picker.watch('focused', function(property_name, old_val, new_val){ |
if(!new_val){ |
popup.close(this); |
} |
}); |
popup.moveOffScreen(Input_Color_Picker); |
if(Input_Color_Picker.startup && !Input_Color_Picker._started){ |
Input_Color_Picker.startup(); |
} |
} |
//console.log('Input_Color_Picker %o', Input_Color_Picker); |
var input = document.getElementById(id); |
//console.log('Color_Picker.set.value='+input.hexValue); |
Input_Color_Picker.set('value', input.hexValue); |
if(!input.readOnly){ |
popup.open({ |
popup: Input_Color_Picker, |
around: input |
}); |
Input_Color_Picker.Input = input; |
Input_Color_Picker.focus(); |
} |
}); |
return false; |
} |
function Input_Color_local_test(){ |
var value = this.value; |
//console.log('value='+value); |
value = value.replace(/\s/g,''); |
if(!value){ |
return null; |
} |
var err_str = ''; |
require(["dojo/_base/Color"], function(Color){ |
if(/^#/.test(value)){ |
if(!Color.fromHex(value)){ |
//Incorrect color code. |
err_str = "Codice del colore non corretto."; |
} |
}else if(/^rgb/.test(value)){ |
if(!Color.fromRgb(value)){ |
//Incorrect RGB value. |
err_str = "Valore RGB non corretto."; |
} |
}else{ |
if(!Color.fromString(value.toLowerCase())){ |
//Unrecognized color name. |
err_str = "Nome del colore sconosciuto."; |
} |
} |
}); |
this.set_value(value); |
//console.log('err_str='+err_str); |
return err_str ? err_str : null; |
} |
function Input_Color_set_value(Value){ |
Value = Value.replace(/\s/g,''); |
if(Value){ |
var color; |
require(["dojo/_base/Color"], function(Color){ |
if(/^#/.test(Value)){ |
color = Color.fromHex(Value); |
}else if(/^rgb/.test(Value)){ |
color = Color.fromRgb(Value); |
}else{ |
color = Color.fromString(Value.toLowerCase()); |
} |
}); |
if(color){ |
var hex = color.toHex(); |
this.hexValue = hex; |
if(this.convertToHex){ |
this.value = hex; |
}else{ |
this.value = Value; |
} |
//console.log('set_value='+this.value); |
//console.log('hexValue='+this.hexValue); |
return; |
} |
} |
this.value = null; |
this.hexValue = '#ffffff'; |
//console.log('set_value='+this.value); |
//console.log('hexValue='+this.hexValue); |
return; |
} |
function Input_Color_get_value(){ |
//console.log('get_value='+this.value); |
if(this.value){ |
return this.value; |
}else{ |
return ''; |
} |
}; |
function Input_Color_keypress(e){ |
Input_Event(e); |
var charcode = e.chCode; |
if(e.normalKey && charcode){ |
var key = String.fromCharCode(charcode); |
var validChars = /[#0-9a-z(),.\s]/i; |
if(!validChars.test(key)){ |
return false; |
} |
} |
return true; |
} |
/tags/2.0/htdocs/input/date.js |
---|
0,0 → 1,192 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Date_Init(Objname, Descr, ReadOnly){ |
var Obj = Input_Init(Objname, Descr); |
Obj.icon = document.getElementById('icon_' + Objname); |
Obj.Readonly = function (set) { |
if(set == null){ |
return this.readOnly; |
}else{ |
var icon = this.icon; |
require(["dojo/dom-style", "dojo/dom-class"], function(domStyle, domClass){ |
if(icon){ |
domStyle.set(icon,'cursor', set ? 'default' : 'pointer'); |
domClass[set ? 'add' : 'remove'](icon, 'dijitDisabled'); |
} |
}); |
this.readOnly = set; |
this.set_status(); |
return set; |
} |
} |
Obj.Readonly(ReadOnly); |
Obj.local_test = Input_Date_test_value; |
return Obj; |
} |
// oggetto calendar (dijit/Calendar) in comune per tutti i widget |
var Input_Date_Calendar; |
function Input_Date_open_cal(id){ |
require(["dojo/ready", "dijit/CalendarLite", "dijit/popup", "dojo/dom", "dojo/date/locale"], function(ready, CalendarLite, popup, dom, locale){ |
ready(function(){ |
// un solo oggetto calendar che creo al primo richiamo del componente |
if(!Input_Date_Calendar){ |
Input_Date_Calendar = new CalendarLite({ |
onChange: function(data){ |
if(Input_Date_Calendar.Input){ |
Input_Date_Calendar.Input.set_value(locale.format(data, {selector:"date", datePattern:"dd/MM/yyyy"})); |
Input_Date_Calendar.Input.onchange(); |
Input_Date_Calendar.Input = null; |
popup.close(this); |
} |
} |
}, 'Input_Date_Calendar'); |
Input_Date_Calendar.watch('focused', function(property_name, old_val, new_val){ |
if(!new_val){ |
popup.close(this); |
} |
}); |
} |
Input_Date_Calendar.Input = null; |
var input = document.getElementById(id); |
var data = input.get_value(); |
Input_Date_Calendar.set('value', data.match(/(\d\d)\/(\d\d)\/(\d\d\d\d)/) ? |
new Date(RegExp.$3, parseInt(RegExp.$2) - 1, RegExp.$1) : new Date()); |
if(!input.readOnly){ |
popup.open({ |
popup: Input_Date_Calendar, |
around: input |
}); |
Input_Date_Calendar.Input = input; |
Input_Date_Calendar.focus(); |
} |
}); |
}); |
return false; |
} |
// verifico la validità del campo data |
function Input_Date_test_value(){ |
// elimino qualunque blank nella stringa |
this.value = this.value.replace(/\s/g,''); |
if(this.value == ''){ |
return ''; |
} |
var D = new Date(); |
var Anno=D.getFullYear(); |
var Mese=D.getMonth()+1; |
var Giorno=D.getDate(); |
var re = /^\/*$/; /**/ |
if(re.test(this.value)){ |
//ok data odierna |
}else{ |
var re = /^(\d+)\/*$/; /**/ |
if(re.test(this.value)){ |
Giorno=parseInt(RegExp.$1,10); |
}else{ |
var re = /^(\d+)\/(\d+)\/*$/; /**/ |
if(re.test(this.value)){ |
Mese=parseInt(RegExp.$2,10); |
Giorno=parseInt(RegExp.$1,10); |
}else{ |
var re = /^(\d+)\/(\d+)\/(\d+)$/ ; |
if(re.test(this.value)){ |
Anno=parseInt(RegExp.$3,10); |
Mese=parseInt(RegExp.$2,10); |
Giorno=parseInt(RegExp.$1,10); |
//window.alert("Data="+RegExp.$1+"-"+RegExp.$2+"-"+RegExp.$3+" ("+Giorno+","+Mese+","+Anno+")"); |
}else{ |
return "Il formato della data non è corretto"; |
} |
} |
} |
} |
if(Anno<100){ |
if(Anno<49){ |
Anno = Anno+2000; |
}else{ |
Anno = Anno+1900; |
} |
} |
if(Anno < 1753 || Anno > 9999){ |
return "L'anno non è corretto"; |
} |
if(Mese>12 || Mese <= 0){ |
return "Il mese non è corretto ("+Mese.toString()+")"; |
} |
if(Giorno == 0){ |
return "Il giorno non è corretto"; |
} |
if(Mese==2){ |
var Bisestile = false; |
if(Anno % 4 == 0){ |
Bisestile = true; |
if(Anno % 100 == 0 ){ |
Bisestile = false; |
if(Anno % 400 == 0){ |
Bisestile=true; |
} |
} |
} |
if(Bisestile){ |
if(Giorno >29){ |
return "Il mese di febbraio ha al massimo 29 giorni"; |
} |
}else{ |
if(Giorno >28){ |
return "Il mese di febbraio ha al massimo 28 giorni"; |
} |
} |
} |
if(Giorno > 30 && (Mese == 4 || Mese == 6 || Mese == 9 || Mese == 11)){ |
return "Il mese ha al massimo 30 giorni"; |
} |
if(Giorno>31){ |
return "Il mese ha al massimo 31 giorni"; |
} |
if(Mese<=9){ |
Mese = "0"+Mese.toString(); |
} |
if(Giorno<=9){ |
Giorno = "0"+Giorno.toString(); |
} |
this.value=Giorno+'/'+Mese+'/'+Anno; |
return ''; |
} |
// filtra i tasti durante immissione in campo DATA |
function Input_Date_keypress(e){ |
var input = Input_Event(e); |
var charcode = e.chCode; |
//window.alert("charCode:"+charcode+" char="+String.fromCharCode(charcode)); |
if(e.normalKey && charcode){ |
var key = String.fromCharCode(charcode); |
if(key == '.' || key == '-'){ |
key = '/'; |
input.changeKeypress(key.charCodeAt(0)); |
} |
var reValidChars = /[\d\/]/; |
if (!reValidChars.test(key) ) { |
var input = e.currentTarget; |
if(input){ |
return false; |
}else{ |
reValidChars = /[\/\.-]/; |
if (reValidChars.test(key) ) { |
e.keyCode = 47; // '/' |
}else{ |
return false; |
} |
} |
} |
} |
} |
/tags/2.0/htdocs/input/autohandler |
---|
0,0 → 1,31 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
// MasonSQL Copyright:2002-2011 Guido Brugnara - LEADER.IT <http://www.leader.it> |
<%attr> |
Cache_MaxAge => 12*60*60 |
</%attr> |
<%perl> |
initBrowserDetect(); |
# N.B. $Ver è una variabile globale; utilizzo l'ID session |
$Ver = $Session{Session}; |
$r->headers_out->{'Cache-Control'} = 'max-age='.$m->base_comp->attr('Cache_MaxAge'); |
$m->call_next; |
</%perl> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%filter> |
if($PLogger->level() ne $DEBUG){ |
# filtra tutti i commenti Jscript |
s|^\s*//\n|\n|mg; |
s|^\s*//.+\n||mg; |
} |
</%filter> |
/tags/2.0/htdocs/input/blank.html |
---|
0,0 → 1,7 |
<%flags> |
inherit => undef # nessun parente |
</%flags> |
% $r->headers_out->{'Cache-Control'} = 'max-age=999999999'; |
<%filter> |
$_=''; |
</%filter> |
/tags/2.0/htdocs/input/image.comp |
---|
0,0 → 1,55 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# Tarcisio Fedrizzi <tarch@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/image.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$name => '' |
$description => '' |
$image_style => 'height: 100%; max-width: 400px; max-height: 100px; background-color: transparent;' |
$readonly => '' |
</%args> |
<span class="container" base_class="container" id="<%$id%>" <%&Args2HtmlTaglist( |
style => "$image_style", |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);' |
)%>> |
<label> |
<img id="Upload_Button_<%$id%>" <%&Args2HtmlTaglist( |
onerror => 'Input_Image_Onerror();', |
style => "$image_style" |
)%>> |
<input type="file" <%&Args2HtmlTaglist( |
style => 'display: none;', |
accept => 'image/*', |
onchange => "Input_Image_Onchange('$id', event);" |
)%>> |
</label> |
<img id="Img_<%$id%>" <%&Args2HtmlTaglist( |
style => "$image_style", |
ondblclick => "Input_Image_Ondblclick('$id', event);") |
%>> |
</span> |
<%perl> |
$readonly = $readonly ? 'true' : 'false'; |
my $descr = $m->interp->apply_escapes($description, 'js'); |
push @Script_buffer, qq{ |
var Id_$id = Input_Image_Init('$id', '$descr', '$readonly'); |
Id_$id.set_value('$value'); |
}; |
</%perl> |
/tags/2.0/htdocs/input/image.js |
---|
0,0 → 1,115 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2016 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Image_Init(ObjName, Descr, ReadOnly){ |
var Obj = Input_Init(ObjName, Descr); |
var img = Obj.img = document.getElementById('Img_'+ObjName); |
img.Widget = Obj; |
img.style.display = "inline"; |
var upload = Obj.upload = document.getElementById('Upload_Button_'+ObjName); |
upload.Widget = Obj; |
var reader = Obj.reader = Input_Image_FileReader(Obj); |
Obj.set_value = Input_Image_set_value; |
Obj.get_value = Input_Image_get_value; |
Obj.set_style = Input_Image_set_style; |
Obj.Readonly = Input_Image_Readonly; |
Obj.Readonly(ReadOnly); |
Obj.set_status(); |
return Obj; |
} |
function Input_Image_Readonly(Set){ |
if(Set == null){ |
return this.readOnly; |
}else{ |
this.readOnly = Set; |
this.set_style(Set); |
this.upload.src = this.img.src; |
return Set; |
} |
} |
function Input_Image_set_style(readonly){ |
if(readonly){ |
//my_alert('hide button, show image', 'alert'); |
this.img.style.display = "inline"; |
this.upload.style.display = "none"; |
}else{ |
//my_alert('show button', 'alert'); |
this.img.style.display = "none"; |
this.upload.style.display = "inline"; |
} |
return; |
}; |
function Input_Image_Ondblclick(ObjName, Event){ |
var obj = document.getElementById(ObjName); |
var popup = window.open('', '_blank'); |
popup.document.write('<body><img src="'+obj.get_value()+'"/></body>'); |
popup.document.close(); |
//my_alert('ondblclick event', 'alert'); |
return false; |
}; |
function Input_Image_FileReader(Obj){ |
if(window.FileReader){ |
var reader = new FileReader(); |
reader.onload = function(){ |
Obj.set_value(reader.result); |
}; |
require(["dojo/on"], function(on){ |
on(reader, "error", function(evt){ |
var err = evt.target.error; |
my_alert(err.name+': '+err.message); |
}); |
}); |
return reader; |
}else{ |
//The FileReader API is not fully supported in this browser.'); |
Input_ErrorMessage(Event, 'L\'API FileReader non è completamente supportato in questo browser'); |
return null; |
} |
} |
function Input_Image_Onchange(ObjName, Event){ |
var input = Event.target; |
var obj = document.getElementById(ObjName); |
Input_DeleteDescription(); |
var inputFile = input.files[0]; |
if(inputFile && obj.reader){ |
obj.reader.readAsDataURL(inputFile); |
return true; |
} |
return false; |
}; |
function Input_Image_Onerror(){ |
//Error: Image can not be loaded. |
//my_alert('Errore: L\'immagine non può essere caricato'); |
return; |
} |
function Input_Image_set_value(Value, Param){ |
if(Value == '') Value = null; |
this.value = Value; |
if(Param != null){ |
this.set_param(Param); |
} |
if(Value == null) Value = '#'; |
this.img.src = Value; |
this.upload.src = Value; |
this.set_display(); |
}; |
function Input_Image_get_value(){ |
return this.value; |
}; |
/tags/2.0/htdocs/input/date.comp |
---|
0,0 → 1,33 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
%# Viene inclusa nel tag HEAD del documento, richiama le librerie associate al componente |
<%method LIBRARY> |
/input/input.comp |
/input/date.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
</%args> |
<input type="text" value-type="date" base_class="date" id="<%$id%>" value="<%$value%>" length="10" maxlength="10" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_Date_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event, this);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') |
%>> |
<span class="dijitInline dijitIcon masonSqlIcons calendar vAlign" id="icon_<%$id%>" onClick="return Input_Date_open_cal('<%$id%>')"></span> |
% push @Script_buffer, "var Id_$id = Input_Date_Init('$id', '".$m->interp->apply_escapes($description, 'js')."', ".($readonly ? 'true':'false').");\n"; |
/tags/2.0/htdocs/input/number.comp |
---|
0,0 → 1,43 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/number.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$length => undef # numero massimo di caratteri accettati nel campo (== NumCifre se non definito) |
$size => undef # larghezza in caratteri del campo (== length se non definito) |
$NumDec => 0 # numero di decimali |
$NumCifre => 9 # numero di cifre totali |
$ValMax => 999999999999 # valore massimo de numero accettato |
$ValMin => -999999999999 # valore minimo del numero accettato |
$readonly => undef |
$AllNumDec => 0 # se >0 vengono mantenuti gli zeri nella parte decimale pari a AllNumDec cifre con AllNumDec < NumDec, atrimenti NumDec cifre |
$ReturnNumDec => 0 # numero di cifre decimali da restituire, anche se fossero degli zeri |
</%args> |
% if(!$length){$length = $NumCifre} |
% if(!$size){$size = int($length)} |
% $AllNumDec = ($NumDec && $AllNumDec && $AllNumDec > 0) ? $AllNumDec : 0; |
% if($AllNumDec > $NumDec){ $AllNumDec = $NumDec} |
<input <%$readonly ? 'readOnly':''%> type="text" value-type="numeric" base_class="number" id="<%$id%>" value="<%$value%>" size="<%$size%>" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_Number_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') |
%>> |
<script> masonSql.once('ready', function(data){<% "window.Id_$id = Input_Number_Init('$id', '".$m->interp->apply_escapes($description, 'js')."',$NumDec,$length,$ValMax,$ValMin,$AllNumDec,$ReturnNumDec);" %>});</script> |
/tags/2.0/htdocs/input/time.comp |
---|
0,0 → 1,34 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY> |
/input/input.comp |
/input/time.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
$h24_format => 1 # se '0' sara' possibile inserire piu' di 24 ore (vedi $length e $maxlength per definire i limiti delle cifre) |
$numeric_value => 0 # se 1 il formato sara' numerico con unita' di misura in ore e decimali di ora, anziche' nel formato HH:MM |
$NumCifre => 5 |
</%args> |
<input <%$readonly ? 'readOnly':''%> type="text" value-type="time" base_class="time" id="<%$id%>" value="<%$value%>" size="<%$NumCifre%>" maxlength="<%$NumCifre%>" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_Time_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') |
%>> |
% push @Script_buffer, "var Id_$id = Input_Time_Init('$id', ".($h24_format ? 'true': 'false').", ".($numeric_value ? 'true': 'false').", '".$m->interp->apply_escapes($description, 'js')."');\n"; |
/tags/2.0/htdocs/input/timestamp.comp |
---|
0,0 → 1,47 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# Tarcisio Fedrizzi <tarch@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input_group.comp |
/input/timestamp.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
</%args> |
<span class="container" value-type="timestamp" id="<% $id %>" <%&Args2HtmlTaglist( |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') |
%>> |
<& /input/date.comp, |
id => "${id}_date", |
description => $description, |
readonly => $readonly |
&> |
<& /input/time.comp, |
id => "${id}_time", |
description => $description, |
readonly => $readonly |
&> |
</span> |
<%perl> |
my $descr = $m->interp->apply_escapes($description, 'js'); |
push @Script_buffer, qq{ |
var Id_$id = Input_Timestamp_Init('$id', '$descr', $readonly); |
Id_$id.set_value('$value'); |
}; |
</%perl> |
/tags/2.0/htdocs/input/input_group.comp |
---|
0,0 → 1,19 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# |
# richiamata dai componenti per inglobare il codice in comune |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/input_group.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
/tags/2.0/htdocs/input/timestamp.js |
---|
0,0 → 1,87 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2016 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# Tarcisio Fedrizzi <tarch@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Timestamp_Init(Objname, Descr, ReadOnly){ |
var Obj = Input_group_Init(Objname, Descr, ' ', 'date time'); |
Obj.readOnly = ReadOnly; |
Obj.get_value = Input_Timestamp_get_value; |
Obj.set_value = Input_Timestamp_set_value; |
Obj.local_test = Input_Timestamp_local_test; |
Obj.group_local_test = Input_group_local_test; |
Obj.set_status(); |
return Obj; |
} |
function Input_Timestamp_get_value(default_time){ |
var date = this.widgets[0].get_value(); |
var time = this.widgets[1].get_value(); |
if(date || time){ |
if(time == ''){ |
time = default_time == null ? '00:00' : default_time; |
} |
if(time != '' && this.seconds != null && this.seconds != ''){ |
time += ':' + this.seconds; |
} |
if(date){ |
var res = date + ' ' + (time ? ' ' + time : ''); |
return res.replace(/\s+$/, ''); |
}else{ |
var today = new Date(); |
return today.getDate() + '/' + (today.getMonth()+1) + '/' + today.getFullYear() + (time ? ' ' + time : ''); |
} |
}else{ |
return ''; |
} |
} |
function Input_Timestamp_set_value(value){ |
var parsedDate = ''; |
var parsedTime = ''; |
var onlyDate = /^(\d+\/\d+\/\d+)\s*$/; |
var onlySpaces = /^\s*$/; |
if (onlySpaces.test(value)){ |
this.widgets[0].set_value(''); |
this.widgets[1].set_value(''); |
this.set_display(); |
return; |
} |
if (onlyDate.test(value)){ |
parsedDate = RegExp.$1; |
parsedTime = '00:00'; |
this.seconds = ''; |
}else{ |
var splitTimestamp = /^(\d+\/\d+\/\d+)\s+(\d+:\d+)$/; |
var splitTimestamp_sec = /^(\d+\/\d+\/\d+)\s+(\d+:\d+):(\d+)$/; |
var splitTimestamp_sec_millis = /^(\d+\/\d+\/\d+)\s+(\d+:\d+):(\d+.\d+)$/; |
if (splitTimestamp_sec.test(value) || splitTimestamp_sec_millis.test(value)){ |
parsedDate = RegExp.$1; |
parsedTime = RegExp.$2; |
this.seconds = RegExp.$3; |
}else if (splitTimestamp.test(value)){ |
parsedDate = RegExp.$1; |
parsedTime = RegExp.$2; |
this.seconds = ''; |
} |
} |
this.widgets[0].set_value(parsedDate); |
this.widgets[1].set_value(parsedTime); |
this.set_display(); |
} |
function Input_Timestamp_local_test(){ |
if(this.widgets[0].get_value() == '' && this.widgets[1].get_value() != ''){ |
var today = new Date(); |
this.widgets[0].set_value(today.getDate() + '/' + (today.getMonth()+1) + '/' + today.getFullYear()); |
} |
return this.group_local_test(); |
} |
/tags/2.0/htdocs/input/color.comp |
---|
0,0 → 1,39 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
%# Viene inclusa nel tag HEAD del documento, richiama le librerie associate al componente |
<%method LIBRARY> |
/input/input.comp |
/input/color.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
$convert_to_hex => 1 |
</%args> |
<input type="text" base_class="color" id="<%$id%>" value="<%$value%>" length="10" maxlength="30" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_Color_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event, this);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);' |
)%>> |
<span class="dijitInline dijitIcon masonSqlIcons pallet vAlign" id="icon_<%$id%>" <%&Args2HtmlTaglist( |
onclick => "return Input_Color_open_color_picker('$id')" |
)%>></span> |
% $description = $m->interp->apply_escapes($description, 'js'); |
% $readonly = $readonly ? 'true':'false'; |
% $convert_to_hex = $convert_to_hex ? 'true':'false'; |
% push @Script_buffer, "var Id_$id = Input_Color_Init('$id', '$description', '$readonly', $convert_to_hex);\n"; |
/tags/2.0/htdocs/input/document.js |
---|
0,0 → 1,127 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2016 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Document_Init(ObjName, FileName, Descr, ReadOnly, SrcPrefix){ |
var Obj = Input_Init(ObjName, Descr); |
var upload = Obj.upload = document.getElementById('Upload_'+ObjName); |
upload.Widget = Obj; |
Obj.srcPrefix = SrcPrefix; |
Obj.fileName = FileName; |
Obj.onclick_handle = {}; |
Obj.add_onclick = Input_Doc_add_onclick; |
Obj.remove_onclick = Input_Doc_remove_onclick; |
Obj.reset_title = Input_Doc_reset_title; |
Obj.set_value = Input_Doc_set_value; |
Obj.get_value = Input_Doc_get_value; |
Obj.set_style = Input_Doc_set_style; |
Obj.Readonly = Input_Doc_Readonly; |
Obj.Readonly(ReadOnly); |
Obj.set_status(); |
Obj.reset_title(); |
return Obj; |
} |
function Input_Doc_Readonly(Set){ |
if(Set == null){ |
return this.readOnly; |
}else{ |
this.readOnly = Set; |
this.set_style(Set); |
return Set; |
} |
} |
function Input_Doc_set_style(readonly){ |
if(readonly){ |
this.remove_onclick(); |
}else{ |
this.add_onclick(); |
} |
return; |
}; |
function Input_Doc_remove_onclick(){ |
var handle = this.onclick_handle; |
require(["dojo/on", "dojo/query"], function(on, query){ |
if(handle.hasOwnProperty('remove')){ |
handle.remove(); |
handle = {}; |
} |
}); |
return; |
} |
function Input_Doc_add_onclick(){ |
var iframe = this.contentDocument; |
var upload = this.upload; |
var onclick_handle = {}; |
require(["dojo/on", "dojo/query", "dojo/domReady!"], function(on, query){ |
//console.log('iframe: %o', iframe); |
onclick_handle = query("#canvasContainer", iframe).on("click", function(){ |
//console.log('evt'); |
upload.click(); |
}); |
}); |
this.onclick_handle = onclick_handle; |
return; |
} |
function Input_Doc_Onchange(ObjName, Event){ |
var input = Event.target; |
var obj = document.getElementById(ObjName); |
if(!window.FileReader){ |
my_alert('The FileReader API is not fully supported in this browser.'); |
} |
var reader = new FileReader(); |
reader.onload = function(){ |
var dataURL = reader.result; |
//console.log('dataURL='+dataURL); |
obj.set_value(dataURL); |
}; |
var file = input.files[0]; |
reader.readAsDataURL(file); |
obj.fileName = file.name; |
//console.log('file: %o', file); |
return; |
}; |
function Input_Doc_reset_title(){ |
var obj = this; |
//require(["dojo/aspect", "dojo/query", "dojo/NodeList-manipulate"], function(aspect, query){ |
require(["dojo/aspect"], function(aspect){ |
aspect.after(obj, "onload", function(){ |
obj.set_style(obj.readOnly); |
}); |
}); |
return; |
} |
function Input_Doc_set_value(Value, Param){ |
if(Value){ |
//console.log('set_value='+Value); |
//console.log('file name='+this.fileName); |
var contentLocation = this.contentWindow.location; |
//var uri = this.srcPrefix+'?title='+encodeURIComponent(this.fileName)+'#'+Value; |
var uri = this.srcPrefix+'?title='+this.fileName+'#'+Value; |
//console.log('contentLocation %o', contentLocation); |
//console.log('uri='+uri); |
contentLocation.href = uri; |
this.src = uri; |
} |
this.value = Value; |
return; |
}; |
function Input_Doc_get_value(){ |
//console.log('get_value='+this.value); |
return this.value; |
}; |
/tags/2.0/htdocs/input/document.comp |
---|
0,0 → 1,77 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# Tarcisio Fedrizzi <tarch@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/document.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$name => '' |
$description => '' |
$document_style => 'height: 100%; max-width: 800px; max-height: 600px; background-color: transparent;' |
$readonly => '' |
</%args> |
<%perl> |
my $blank_pdf = q{data:application/pdf;base64, |
JVBERi0xLjQKJcOkw7zDtsOfCjIgMCBvYmoKPDwvTGVuZ3RoIDMgMCBSL0ZpbHRlci9G |
bGF0ZURlY29kZT4+CnN0cmVhbQp4nDPQM1Qo5ypUMFAwALJMLU31jBQsTAz1LBSKUrnC |
tRTyuAIVAIcdB3IKZW5kc3RyZWFtCmVuZG9iagoKMyAwIG9iago0MgplbmRvYmoKCjUg |
MCBvYmoKPDwKPj4KZW5kb2JqCgo2IDAgb2JqCjw8L0ZvbnQgNSAwIFIKL1Byb2NTZXRb |
L1BERi9UZXh0XQo+PgplbmRvYmoKCjEgMCBvYmoKPDwvVHlwZS9QYWdlL1BhcmVudCA0 |
IDAgUi9SZXNvdXJjZXMgNiAwIFIvTWVkaWFCb3hbMCAwIDU5NSA4NDJdL0dyb3VwPDwv |
Uy9UcmFuc3BhcmVuY3kvQ1MvRGV2aWNlUkdCL0kgdHJ1ZT4+L0NvbnRlbnRzIDIgMCBS |
Pj4KZW5kb2JqCgo0IDAgb2JqCjw8L1R5cGUvUGFnZXMKL1Jlc291cmNlcyA2IDAgUgov |
TWVkaWFCb3hbIDAgMCA1OTUgODQyIF0KL0tpZHNbIDEgMCBSIF0KL0NvdW50IDE+Pgpl |
bmRvYmoKCjcgMCBvYmoKPDwvVHlwZS9DYXRhbG9nL1BhZ2VzIDQgMCBSCi9PcGVuQWN0 |
aW9uWzEgMCBSIC9YWVogbnVsbCBudWxsIDBdCi9MYW5nKGVuLVVTKQo+PgplbmRvYmoK |
CjggMCBvYmoKPDwvQ3JlYXRvcjxGRUZGMDA1NzAwNzIwMDY5MDA3NDAwNjUwMDcyPgov |
UHJvZHVjZXI8RkVGRjAwNEMwMDY5MDA2MjAwNzIwMDY1MDA0RjAwNjYwMDY2MDA2OTAw |
NjMwMDY1MDAyMDAwMzUwMDJFMDAzMT4KL0NyZWF0aW9uRGF0ZShEOjIwMTYxMjA4MTUx |
MDUxKzAxJzAwJyk+PgplbmRvYmoKCnhyZWYKMCA5CjAwMDAwMDAwMDAgNjU1MzUgZiAK |
MDAwMDAwMDIyNiAwMDAwMCBuIAowMDAwMDAwMDE5IDAwMDAwIG4gCjAwMDAwMDAxMzIg |
MDAwMDAgbiAKMDAwMDAwMDM2OCAwMDAwMCBuIAowMDAwMDAwMTUxIDAwMDAwIG4gCjAw |
MDAwMDAxNzMgMDAwMDAgbiAKMDAwMDAwMDQ2NiAwMDAwMCBuIAowMDAwMDAwNTYyIDAw |
MDAwIG4gCnRyYWlsZXIKPDwvU2l6ZSA5L1Jvb3QgNyAwIFIKL0luZm8gOCAwIFIKL0lE |
IFsgPDFFMUZBQzczRTAwRTY0RkRGRURBNUM2QjEwRjMyMkU5Pgo8MUUxRkFDNzNFMDBF |
NjRGREZFREE1QzZCMTBGMzIyRTk+IF0KL0RvY0NoZWNrc3VtIC9BRDg5MTJCRUQ2M0VE |
RjZEOUY0MjhGRDZFNDEwQkY2NQo+PgpzdGFydHhyZWYKNzM2CiUlRU9GCg==}; |
my $src_prefix = "/lib/ViewerJS/"; |
</%perl> |
<input id="Upload_<%$id%>" type="file" <%&Args2HtmlTaglist( |
style => 'display: none;', |
onchange => "Input_Doc_Onchange('$id', event);" |
)%>> |
<iframe id="<%$id%>" src="<%$src_prefix%>" <%&Args2HtmlTaglist( |
sytle => "$document_style", |
width => '700', |
height => '550', |
allowfullscreen => "", |
webkitallowfullscreen => "" |
)%>> |
</iframe> |
<%perl> |
$readonly = $readonly ? 'true' : 'false'; |
my $descr = $m->interp->apply_escapes($description, 'js'); |
unless($value){ |
$value = $blank_pdf; |
} |
$value = $m->interp->apply_escapes($value, 'js'); |
$name = $m->interp->apply_escapes($name, 'js'); |
push @Script_buffer, qq{ |
var Id_$id = Input_Document_Init('$id', '$name', '$descr', '$readonly', '$src_prefix'); |
Id_$id.set_value('$value'); |
}; |
</%perl> |
/tags/2.0/htdocs/input/button.comp |
---|
0,0 → 1,44 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/button.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$caption => 'Button_'.$id # testo del pulsante |
$caption_value => undef # se definito: il caption viene posto uguale a Value |
$description => '' |
$width => undef |
$readonly => undef |
$bgcolor => undef |
</%args> |
<%perl> |
$caption = $caption_value ? $value : $caption; |
$caption_value = $caption_value ? 'true' : 'false'; |
$width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
</%perl> |
<input type="button" disabled base_class="button" tabindex="-1" id="<%$id%>" value="<%$caption|h%>" <%&Args2HtmlTaglist( |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => (defined($width) ? "width:$width;" : '').(defined($bgcolor) ? "background-color:$bgcolor;" : '') |
) |
%>> |
<%perl> |
my $ro = $readonly ? 'true' : 'false'; |
push @Script_buffer, "var Id_$id = Input_Button_Init('$id', '".$m->interp->apply_escapes($description, 'js'). |
"', '".$m->interp->apply_escapes($value, 'js')."', $caption_value);\n". |
"Id_$id.Readonly($ro);\n"; |
</%perl> |
/tags/2.0/htdocs/input/radio.comp |
---|
0,0 → 1,29 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/radio.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$id |
$value => undef |
$description => '' |
$readonly => undef |
</%args> |
% my $name = $id; $name =~ s/_*\d*$//; |
<input <% $readonly ? 'disabled' : '' %> type="radio" <% $value ? 'CHECKED' : '' %> base_class="radio" id="<%$id%>" name="<% $name %>" <%&Args2HtmlTaglist( |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);') |
%>> |
% push @Script_buffer, "var Id_$id = Input_Radio_Init('$id', '".$m->interp->apply_escapes($description, 'js')."');\n"; |
/tags/2.0/htdocs/input/string.js |
---|
0,0 → 1,90 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_String_Init(Objname, Descr, maxLength, valid_chars, trim, trans, ignore_chars){ |
var Obj = Input_Init(Objname, Descr); |
if(maxLength == null){ |
maxLength = 999999; |
} |
Obj.maxLength = maxLength; |
Obj.validChars = new RegExp(valid_chars,''); |
Obj.ignoreChars = new RegExp(ignore_chars,''); |
Obj.trim = trim; |
Obj.trans = trans; |
Obj.local_test = Input_String_local_test; |
Obj.set_status(); |
return Obj; |
} |
// controllo del campo al termine della modifica |
function Input_String_local_test(){ |
if(this.trim.length > 0){ |
// elimino blank |
if(/^L.*/.test(this.trim)){ // all'inizio |
this.value = this.value.replace(/^\s+/,''); |
}else if(/^R.*/.test(this.trim)){ // oppure alla fine |
this.value = this.value.replace(/\s+$/,''); |
}else{ // oppure all'inizio ed alla fine |
this.value = this.value.replace(/^\s+|\s+$/,''); |
} |
} |
if(this.value.length > this.maxLength){ |
return "Caratteri immessi " + this.value.length + " maggiore del limite massimo di " + this.maxLength; |
} |
% if($r->dir_config('InputStringNoLongUTF')){ |
% # filtro i caratteri UTF multibyte (la funzione escape codifica i caratteri UTF multibyte con %uNNNN) |
var noUTF = unescape(escape(this.value).replace(/%u[\dA-Ea-e]{4}/gm,'?')); |
if(this.value != noUTF){ |
this.value = noUTF; |
return 'Rilevati caratteri non compatibili!\nI caratteri sono stati sostituiti con il carattere ?.'; |
} |
% } |
return ''; |
} |
// filtra i tasti durante immissione |
function Input_String_keypress(e){ |
var input = Input_Event(e); |
var charcode = e.chCode; |
//window.alert("charCode:"+charcode+" char="+String.fromCharCode(charcode)); |
if(e.normalKey && charcode ){ |
var key = String.fromCharCode(charcode); |
if(input.value.length >= input.maxLength){ |
return false; |
} |
if(input.trans){ |
// trasformazione dei caratteri |
var newkey; |
if(input.trans == 'U'){ |
newkey = key.toUpperCase(); |
}else if(input.trans == 'L'){ |
newkey = key.toLowerCase(); |
} |
// se il carattere è cambiato |
if(newkey != key){ |
key = newkey; |
// provvedo a cambiarlo nell'evento corrente |
input.changeKeypress(key.charCodeAt(0)); |
} |
} |
// validazione dei caratteri |
if(input.validChars.test(key)){ |
return true; |
}else{ |
// caratteri da ignorare |
if(!input.ignoreChars.test(key)){ |
Input_ErrorMessage(e, "Carattere ("+key+":"+charcode+") non valido"); |
} |
return false; |
} |
} |
} |
/tags/2.0/htdocs/input/span.comp |
---|
0,0 → 1,43 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/span.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$size => undef # parametro deprecato - è stato sostituito da $width |
$width => undef |
$bgcolor => undef |
$disp_template => undef # funzione eval per definire la descrizione (i parametri sono disponibili con P[n]) |
$empty_descr => '' # descrizione da visualizzare per il campo |
</%args> |
% # DEPRECATED |
% if(defined $size && !defined $width){ |
% $width = $size; |
% } |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
<span base_class="inputspan" id="<%$id%>" <%&Args2HtmlTaglist( |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => (defined($width) ? "width:$width;" : '').(defined($bgcolor) ? "background-color:$bgcolor;" : '') |
) |
%>><%$value|h%> </span> |
<%perl> |
if($id){ |
push @Script_buffer, "var Id_$id = Input_Span_Init('$id', '".$m->interp->apply_escapes($description, 'js')."','".$m->interp->apply_escapes($disp_template, 'js')."','".$m->interp->apply_escapes($empty_descr, 'js').", ".$m->interp->apply_escapes($value, 'js')."');\n"; |
} |
</%perl> |
/tags/2.0/htdocs/input/url.comp |
---|
0,0 → 1,38 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2009-2012 Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/string.comp |
/input/url.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$button_descr => 'VIEW', |
$id |
$description => '' |
$length => 40 |
$size => undef |
$width => undef |
$readonly => undef |
$base_url => '' |
$popup => 0 # utilizza un Popup per visualizzare la URL altrimenti usa window.open in una nuova finestra |
$window_properties => 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable,alwaysRaised,dependent,titlebar=yes' |
$window_width => 800, |
$window_height => 600 |
</%args> |
<span class="container" base_class="inputspan" id="container_<%$id%>"> |
<button class="button UrlComp" tabindex="-1" onclick="this.widget.displayURL();" |
style="display:none;" id="<% $id %>_button_url"><%$button_descr%></button> |
<& /input/string.comp, %ARGS &> |
</span> |
% push @Script_buffer, "var Id_$id = Input_Url_Init('$id', '$base_url', ".($popup ? 'true' : 'false').", $window_width, $window_height, '$window_properties');\n"; |
/tags/2.0/htdocs/input/Permission.js |
---|
0,0 → 1,137 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Permission_Init(Objname, Descr, Readonly){ |
var Obj = Input_Init(Objname, Descr); |
// nuovi metodi associati al componente complesso |
// metodo per la lettura del valore del componente |
Obj.get_value = Permission_get_value; |
// metodo per il caricamento del valore del componente |
Obj.set_value = Permission_set_value; |
// metodo per variare lo stato |
Obj.set_status = Permission_set_status; |
// metodo per disporre in sola lettura i campi |
Obj.Readonly = Permission_Readonly; |
// costruisco l'array dei checkbox |
require(["dojo/dom"], function(dom){ |
var O = Objname; |
Obj.checkboxes = { |
% my @gru; |
% for(my $row=0; $row<@{$groups}; $row++){ |
% my $group = $groups->[$row]; |
% my @per; |
% for(my $col=0; $col<@{$permissions}; $col++){ |
% my $permission = $permissions->[$col]; |
% push @per, "p$permission->[0]:dom.byId(O+':$group->[0]:$permission->[0]')"; |
% } |
% push @gru, "g$group->[0]:{".join(',', @per).'}'; |
% } |
<% join(",\n ", @gru) %> |
}; |
}); |
Obj.disabled = !Readonly; // costringo il componente a cambiare la configurazione |
Obj.Readonly(Readonly); |
Obj.setFocus = null; |
return Obj; |
} |
function Permission_get_value(){ |
var value = []; |
for(var row in this.checkboxes){ |
var cols = this.checkboxes[row]; |
for(var col in cols){ |
if(cols[col].checked){ |
value.push(row + ' ' + col); |
} |
} |
} |
if(value.length){ |
return 'perm:\n' + value.join('\n'); |
}else{ |
return 'perm:' |
} |
} |
// metodo per il caricamento del valore del componente |
function Permission_set_value(value){ |
// azzero prima tutti i checkbox |
for(var row in this.checkboxes){ |
var cols = this.checkboxes[row]; |
for(var elem in cols){ |
cols[elem].checked = false; |
} |
} |
// valuto il codice inviato dal server che provvede a cambiare i valori |
rows = value.split(/\n/); |
var prima_riga = rows.shift(); |
if(prima_riga == 'perm:'){ |
for(var row=0; row<rows.length; row++){ |
var cols = rows[row].split(/\s+/); |
if(cols[0].length && cols[1].length){ |
this.checkboxes[cols[0]][cols[1]].checked = true; |
} |
} |
return value; |
}else{ |
alert('Errore inaspettato; campo Permission con valore [value]'); |
} |
} |
function Permission_set_status(status){ |
var classList = this.eval_status(status); |
if(this._classList != classList){ |
this._classList = classList; |
for(var row in this.checkboxes){ |
var cols = this.checkboxes[row]; |
for(var elem in cols){ |
cols[elem].className = classList; |
} |
} |
} |
} |
function Permission_Readonly(set){ |
// senza parametro ritorna la condizione corrente |
if(set == null){ |
return this.disabled; |
}else{ |
if(this.disabled != set){ |
this.disabled = set; |
for(var row in this.checkboxes){ |
var cols = this.checkboxes[row]; |
for(var elem in cols){ |
cols[elem].disabled = set; |
} |
} |
this.set_status(); |
} |
return set; |
} |
} |
<%shared> |
# elenco gruppi |
my $sth = $Session{Dbh}->prepare(q|select id, nome from gruppi order by nome|); |
$sth->execute(); |
my $groups = $sth->fetchall_arrayref; |
# elenco permessi |
$sth = $Session{Dbh}->prepare(q|select id, nome from autorizzazioni order by nome|); |
$sth->execute(); |
my $permissions = $sth->fetchall_arrayref; |
undef $sth; |
</%shared> |
/tags/2.0/htdocs/input/string.comp |
---|
0,0 → 1,72 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/string.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%once> |
my $trim_default = $r->dir_config('String_TrimDefault'); |
use POSIX qw/ceil/; |
</%once> |
<%args> |
$value => '' |
$id |
$description => '' |
$length => 12 # numero massimo di caratteri accettati nel campo |
$size => undef # larghezza in caratteri del campo |
$trim => $trim_default # elimina gli spazi - R:spazi a destra, L: spazi a sinistra, |
# <qualunque altro carattere>:all'inizio e alla fine del testo |
$trans => undef # U:upper - caratteri tutti maiuscoli; L: lower - caratteri tutti minuscoli |
$width => undef |
$cols => undef |
$rows => undef |
$password => undef |
$readonly => undef |
$valid_chars => '.*' # espressione regolare (in linguaggio Jscript) per validare i singoli caratteri digitati |
$ignore_chars => '' # espressione regolare (in linguaggio Jscript) dei caratteri da ignorare |
</%args> |
% if(!$size){$size = int($length)} |
% $width = !$width || $width =~ m/[^\d]/ ? $width : $width.'px'; |
% my $style = defined $width ? "width:$width;".($width ? '' : 'display:none;') : ''; |
% if(defined $rows && $rows >1){ |
% if(!defined $cols){$cols=ceil($length/$rows)} |
<textarea <%$readonly ? 'readOnly':''%> type="text" base_class="string" id="<%$id%>" rows="<%$rows--%>" cols="<%$cols%>" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_String_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => $style) |
%>><%$value%></textarea> |
% }else{ |
<input <%$readonly ? 'readOnly':''%> type="<%$password ? 'password' : 'text'%>" base_class="string" id="<%$id%>" value="<%$value%>" size="<%$size%>" maxlength="<%$length%>" <%&Args2HtmlTaglist( |
onkeypress => 'return Input_String_keypress(event);', |
onkeydown => 'return Input_keydown(event);', |
onchange => 'Input_change(event);', |
onmouseover => 'Input_ViewDescription(event);', |
onmouseout => 'Input_DeleteDescription(event);', |
style => $style) |
%>> |
<%perl> |
} |
if($id){ |
if(!$length){ $length = 'null' } |
push @Script_buffer, "var Id_$id = Input_String_Init('$id', '".$m->interp->apply_escapes($description, 'js'). |
"', $length, '".$m->interp->apply_escapes($valid_chars, 'js'). |
"','".$m->interp->apply_escapes(uc $trim, 'js'). |
"','".$m->interp->apply_escapes(uc $trans, 'js'). |
"','".$m->interp->apply_escapes($ignore_chars, 'js'). |
"');\n"; |
} |
</%perl> |
/tags/2.0/htdocs/input/time.js |
---|
0,0 → 1,167 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
// filtra i tasti durante immissione in campo orario XX:YY |
function Input_Time_Init(Objname, h24_format, numeric_value, Descr){ |
var Obj = Input_Init(Objname, Descr); |
// ritorna il valore del widget |
Obj.get_numeric_value = Input_Time_get_numeric_value; |
Obj.get_value = Input_Time_get_value; |
// funzione per definire il valore del widget |
Obj.set_numeric_value = Input_Time_set_numeric_value; |
Obj.set_value = Input_Time_set_value; |
Obj.local_test = Input_Time_local_test; |
Obj.h24_format = h24_format; |
Obj.numeric_value = numeric_value; |
// per salvare il campo secondi, se presente, che non viene gestito dal widget (solo ore e minuti) |
Obj.seconds = null; |
Obj.set_status(); |
return Obj; |
} |
function Input_Time_local_test(){ |
var Ore; |
var Minuti; |
with(this){ |
if(value==" "){value=""}; |
if(value==""){return ''} |
var re = /^\:*$/; |
if(re.test(value)){ |
// aggiungo l'ora non definita |
var now = new Date(); |
value = now.getHours() + value; |
} |
// verifico se solo ':' |
if(value == ':'){ |
var now = new Date(); |
value = now.getHours() + ':' + now.getMinutes(); |
} |
// verifico se solo ora |
var re = /^(\d+)\:*$/; |
if(re.test(value)){ |
Ore=parseInt(RegExp.$1,10); |
Minuti=0; |
}else{ |
re = /^(\d+)\:(\d+)$/ ; |
var arr = re.exec(value); |
Ore=parseInt(RegExp.$1,10); |
Minuti=parseInt(RegExp.$2,10); |
if(isNaN(Ore) || isNaN(Minuti)){ |
return "Formato orario ("+value+") non corretto"; |
} |
} |
if(this.h24_format && Ore>24){ |
return "L'ora puo' essere al massimo 24"; |
} |
if(Minuti>59){ |
return "I minuti possono essere al massimo 59"; |
} |
if(Ore<=9){ |
Ore = "0"+Ore.toString(); |
} |
if(Minuti<=9){ |
Minuti = "0"+Minuti.toString(); |
} |
value=Ore+":"+Minuti; |
} |
return ''; |
} |
function Input_Time_keypress(e){ |
var input = Input_Event(e); |
var charcode = e.chCode; |
//window.alert("charCode:"+charcode+" char="+String.fromCharCode(charcode)); |
if(e.normalKey && charcode){ |
var key = String.fromCharCode(charcode); |
if(key == '.' || key == '-' || key == '/'){ |
key = ':'; |
input.changeKeypress(key.charCodeAt(0)); |
} |
var reValidChars = /[\d\:]/; |
if (!reValidChars.test(key) ) { |
// Input_ErrorMessage(e, "Carattere ("+key+":"+charcode+") non valido"); |
return false; |
} |
} |
} |
// ritorna il valore del campo nel formato numerico (ore e decimali di ore) |
function Input_Time_get_numeric_value(){ |
if(this.value){ |
// separo ore dai minuti |
re = /^(\d+)\:(\d+)$/ ; |
var arr = re.exec(this.value); |
var Ore = parseFloat(RegExp.$1); |
var Minuti = parseFloat(RegExp.$2); |
return (Ore + Minuti / 60.0).toFixed(4); |
}else{ |
return ''; |
} |
} |
// ritorna il valore del campo specificato |
function Input_Time_get_value(){ |
if(this.seconds == null){ |
return this.numeric_value ? this.get_numeric_value() : this.value; |
}else{ |
if(this.value){ |
return ''; |
}else{ |
// mantengo la misura dei secondi solo per evitare che non si registri una variazione del valore che non c'e' stata |
return this.value + ':' + this.seconds; |
} |
} |
} |
// inizializza il valore del campo selezionato fornito nel formato numerico (ore e decimali di ore) |
function Input_Time_set_numeric_value(value, param){ |
if(param != null){ |
this.set_param(param); |
} |
this.seconds = null; |
if(value != ''){ |
var Ore = Math.floor(value); |
var Minuti = Math.round((value - Ore) * 60); |
%# // necessario nel caso di valori simili a 12.99999888232 |
if(Minuti == 60){Minuti = 0; Ore +=1;} |
this.value = (Ore <= 9 ? '0' : '') + Ore + (Minuti <= 9 ? ':0' : ':') + Minuti; |
}else{ |
this.value = ''; |
} |
if(this.set_display){ |
this.set_display(); |
} |
} |
// inizializza il valore del campo selezionato |
function Input_Time_set_value(value, param){ |
if(this.numeric_value){ |
this.set_numeric_value(value, param); |
}else{ |
if(param != null){ |
this.set_param(param); |
} |
if(value){ |
// separo hh:mm[:ss] |
var arr = value.split(':'); |
this.value = arr[0] + ':' + arr[1]; |
this.seconds = null; |
}else{ |
this.value = value; |
this.seconds = null; |
} |
if(this.set_display){ |
this.set_display(); |
} |
} |
} |
/tags/2.0/htdocs/input/codfisc_pi.js |
---|
0,0 → 1,126 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Codfisc_pi_Init(Objname, Descr, trans){ |
var Obj = Input_Init(Objname, Descr); |
Obj.validChars = new RegExp('[a-zA-Z0-9]',''); |
Obj.local_test = Input_Codfisc_pi_test; |
Obj.trans = trans; |
Obj.set_status(); |
return Obj; |
} |
// filtra i tasti durante immissione |
function Input_Codfisc_pi_keypress(e){ |
var input = Input_Event(e); |
var charcode = e.chCode; |
// window.alert("charCode:"+charcode+" char="+String.fromCharCode(charcode)); |
if(e.normalKey && charcode){ |
var key = String.fromCharCode(charcode); |
if(input.value.length >= 16){ |
return false; |
} |
if(!input.validChars.test(key)){ |
return false; |
} |
if(input.trans){ |
// trasformazione dei caratteri |
var newkey; |
if(input.trans == 'U'){ |
newkey = key.toUpperCase(); |
}else if(input.trans == 'L'){ |
newkey = key.toLowerCase(); |
} |
// se il carattere è cambiato |
if(newkey != key){ |
key = newkey; |
// provvedo a cambiarlo nell'evento corrente |
input.changeKeypress(key.charCodeAt(0)); |
} |
} |
} |
} |
// Funzioni per il calcolo di Codice Fiscale e P.I. con licenza Public Domain rif: http://www.icosaedro.it/cf-pi/index.html |
function ControllaCF(cf){ |
var validi, i, s, set1, set2, setpari, setdisp; |
cf = cf.toUpperCase(); |
if( cf.length != 16 ) |
return "La lunghezza del codice fiscale non è\n" |
+"corretta: il codice fiscale dovrebbe essere lungo\n" |
+"esattamente 16 caratteri.\n"; |
validi = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
for( i = 0; i < 16; i++ ){ |
if( validi.indexOf( cf.charAt(i) ) == -1 ) |
return "Il codice fiscale contiene un carattere non valido `" + |
cf.charAt(i) + |
"'.\nI caratteri validi sono le lettere e le cifre.\n"; |
} |
set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
set2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
setpari = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; |
setdisp = "BAKPLCQDREVOSFTGUHMINJWZYX"; |
s = 0; |
for( i = 1; i <= 13; i += 2 ) |
s += setpari.indexOf( set2.charAt( set1.indexOf( cf.charAt(i) ))); |
for( i = 0; i <= 14; i += 2 ) |
s += setdisp.indexOf( set2.charAt( set1.indexOf( cf.charAt(i) ))); |
if( s%26 != cf.charCodeAt(15)-'A'.charCodeAt(0) ) |
return "Il codice fiscale non è corretto:\n"+ |
"il codice di controllo non corrisponde.\n"; |
return ''; |
} |
function ControllaPIVA(pi){ |
if( pi.length != 11 ) |
return "La lunghezza della partita IVA non è\n" + |
"corretta: la partita IVA dovrebbe essere lunga\n" + |
"esattamente 11 caratteri.\n"; |
validi = "0123456789"; |
for( i = 0; i < 11; i++ ){ |
if( validi.indexOf( pi.charAt(i) ) == -1 ) |
return "La partita IVA contiene un carattere non valido `" + |
pi.charAt(i) + "'.\nI caratteri validi sono le cifre.\n"; |
} |
s = 0; |
for( i = 0; i <= 9; i += 2 ) |
s += pi.charCodeAt(i) - '0'.charCodeAt(0); |
for( i = 1; i <= 9; i += 2 ){ |
c = 2*( pi.charCodeAt(i) - '0'.charCodeAt(0) ); |
if( c > 9 ) c = c - 9; |
s += c; |
} |
if( ( 10 - s%10 )%10 != pi.charCodeAt(10) - '0'.charCodeAt(0) ) |
return "La partita IVA non è valida:\n" + |
"il codice di controllo non corrisponde.\n"; |
return ''; |
} |
function Input_Codfisc_pi_test(){ |
var err; |
this.value = this.value.toUpperCase(); |
if(this.value.length == 0){ |
}else if( this.value.length == 16 ){ |
err = ControllaCF(this.value); |
}else if( this.value.length == 11 ){ |
err = ControllaPIVA(this.value); |
}else{ |
err = "Il codice introdotto non è valido:\n" + |
" - un codice fiscale deve essere lungo 16 caratteri;\n" + |
" - una partita IVA deve essere lunga 11 caratteri.\n"; |
} |
if( err > '' ){ |
return "VALORE ERRATO!\n" + err + "\nCorreggi e riprova!"; |
} |
return ''; |
} |
/tags/2.0/htdocs/input/Permission.comp |
---|
0,0 → 1,70 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2006 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# |
# blocco dati con form complesso in unico campo per gestire |
# il campo complesso "Permission" nel form dei parametri |
# |
# |
</%doc> |
<%method LIBRARY>\ |
/input/input.comp |
/input/Permission.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
$value => '' |
$id |
$description => '' |
$readonly => undef |
</%args> |
% # campo nascosto utilizzato quale contenitore per tutte le voci del componente complesso |
<div class="container" base_class="permission" id="<%$id%>"> |
% # organizzo in una tabella tutti i gruppi (righe) ed i permessi (colonne) e con dei checkbox agli incroci |
% # che rappresentano i permessi attivati |
<table border="1"> |
% # intestazioni |
<tr> |
<td></td> |
% for(my $col=0; $col<@{$permissions}; $col++){ |
<td><%$permissions->[$col]->[1]%></td> |
% } |
% for(my $row=0; $row<@{$groups}; $row++){ |
<tr> |
% my $group = $groups->[$row]; |
<td><%$group->[1]%></td> |
% for(my $col=0; $col<@{$permissions}; $col++){ |
<td><input type="checkbox" <%$readonly ? 'disabled':''%> id="<%$id.':'.$group->[0].':'.$permissions->[$col]->[0]%>"></td> |
% } |
</tr> |
% } |
</tr> |
<rd> |
<td> |
</td> |
</rd> |
</table> |
</div> |
% |
% push @Script_buffer, "var Id_$id = Input_Permission_Init('$id', '".$m->interp->apply_escapes($description, 'js')."', ".($readonly ? 'true' : 'false').");\n"; |
% |
<%shared> |
# elenco gruppi |
my $sth = $Session{Dbh}->prepare(q|select id, nome from gruppi order by nome|); |
$sth->execute(); |
my $groups = $sth->fetchall_arrayref; |
# elenco permessi |
$sth = $Session{Dbh}->prepare(q|select id, nome from autorizzazioni order by nome|); |
$sth->execute(); |
my $permissions = $sth->fetchall_arrayref; |
undef $sth; |
</%shared> |
/tags/2.0/htdocs/input/COPYRIGHT |
---|
0,0 → 1,10 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
/tags/2.0/htdocs/input/input.comp |
---|
0,0 → 1,168 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# |
# richiamata dai componenti per inglobare il codice in comune |
</%doc> |
<%method LIBRARY>\ |
/input/input.js |
</%method> |
<%init> |
LoadHeader 'SELF'; |
</%init> |
<%args> |
</%args> |
<%once> |
# filtra la stringa sostituendo i caratteri speciali che non possono essere messi tra "" |
# come parametro di un TAG Html (es <input ... mytag="may text to filter" > |
sub Tag_filter($){ |
$_ = $m->interp->apply_escapes($_[0], 'h'); |
s/\n/ /sg; |
return $_; |
} |
# Individua tra i parametri passati al metodo che chiama la funzione |
# (normalmente è /input/xxx.comp) i parametri non dichiarati esplicitamente nel metodo |
# combina i parametri dichiarati nella hash passata alla funzione con i parametri passati al metodo |
# costruisce quindi una stringa di parametri del tipo |
# parametro1="xxxxxx" parametro2="yyy y y yy " ... |
# che viene restituita. |
# per mettere davanti, dietro o sovrascrivere le definizioni passate al metodo, rispetto a quelle stabilite nell'oggetto |
# valgono le seguenti regole: |
# tag => 'bla bla bla' testo accodato |
# tag => '|bla bla bla' testo accodato |
# tag => 'bla bla bla|' testo davanti |
# tag => '|bla bla bla|' testo sostituito |
# tag => undef tag eliminato, anche se passato |
# |
sub Args2HtmlTaglist { |
my %taglist = @_; |
my $args = $m->caller_args(0); |
my $declared = $m->current_comp->declared_args; |
my $tags=''; |
foreach my $arg ( keys %{$args}){ |
if(!defined $declared->{'$'.$arg} && !defined $declared->{'@'.$arg} && !defined $declared->{'%'.$arg}){ |
my $str = $args->{$arg}; |
if(defined $taglist{$arg}){ |
if($str =~ m/^\|(.*)\|$/s){ |
$tags.=$arg.'="'.Tag_filter($1).'" '; |
}elsif($str =~ m/(.*)\|$/s){ |
$tags.=$arg.'="'.Tag_filter($1.$taglist{$arg}).'" '; |
}elsif($str =~ m/^\|(.*)/s){ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}.$1).'" '; |
}else{ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}.$str).'" '; |
} |
delete $taglist{$arg}; |
}elsif(exists $taglist{$arg}){ |
# allora il tag è undefined |
delete $taglist{$arg}; |
}else{ |
$str =~ s/^\|//; |
$str =~ s/\|$//; |
$tags.=$arg.'="'.Tag_filter($str).'" '; |
} |
} |
} |
foreach my $arg ( keys %taglist){ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}).'" '; |
} |
return $tags; |
} |
# Individua tra i parametri passati al metodo che chiama la funzione |
# (normalmente è /input/xxx.comp) i parametri dichiarati esplicitamente nel metodo |
# combina i parametri dichiarati nella hash passata alla funzione con i parametri passati al metodo |
# costruisce quindi una stringa di parametri del tipo |
# parametro1="xxxxxx" parametro2="yyy y y yy " ... |
# che viene restituita. |
# per mettere davanti, dietro o sovrascrivere le definizioni passate al metodo, rispetto a quelle stabilite nell'oggetto |
# valgono le seguenti regole: |
# tag => 'bla bla bla' testo accodato |
# tag => '|bla bla bla' testo accodato |
# tag => 'bla bla bla|' testo davanti |
# tag => '|bla bla bla|' testo sostituito |
# tag => undef tag compreso |
# |
sub ArgsOnly2HtmlTaglist { |
my %taglist = @_; |
my $args = $m->caller_args(0); |
my $declared = $m->current_comp->declared_args; |
my $tags=''; |
foreach my $arg ( keys %taglist){ |
my $str = $args->{$arg}; |
if(defined $str){ |
if(!defined $declared->{'$'.$arg} && !defined $declared->{'@'.$arg} && !defined $declared->{'%'.$arg}){ |
if($str =~ m/^\|(.*)\|$/s){ |
$tags.=$arg.'="'.Tag_filter($1).'" '; |
}elsif($str =~ m/(.*)\|$/s){ |
$tags.=$arg.'="'.Tag_filter($1.$taglist{$arg}).'" '; |
}elsif($str =~ m/^\|(.*)/s){ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}.$1).'" '; |
}else{ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}.$str).'" '; |
} |
} |
}else{ |
if(defined $taglist{$arg}){ |
$tags.=$arg.'="'.Tag_filter($taglist{$arg}).'" '; |
} |
} |
} |
return $tags; |
} |
# Individua tra i parametri passati al metodo che chiama la funzione |
# (normalmente è /input/xxx.comp) i parametri dichiarati esplicitamente nel metodo |
# combina i parametri dichiarati nella hash passata alla funzione con i parametri passati al metodo |
# costruisce quindi una stringa di parametri del tipo |
# Obj.parametro1 = function "xxxxxx"; |
# Obj.parametro2 = function "yyy y y yy " ... |
# |
# che viene restituita. |
# per mettere davanti, dietro o sovrascrivere le definizioni passate al metodo, rispetto a quelle stabilite nell'oggetto |
# valgono le seguenti regole: |
# tag => 'bla bla bla' testo accodato |
# tag => '|bla bla bla' testo accodato |
# tag => 'bla bla bla|' testo davanti |
# tag => '|bla bla bla|' testo sostituito |
# tag => undef tag compreso |
# |
sub ArgsOnly2JscriptTaglist { |
my $Obj = shift; |
my %taglist = @_; |
my $args = $m->caller_args(0); |
my $declared = $m->current_comp->declared_args; |
my $jscript=''; |
foreach my $arg ( keys %taglist){ |
my $str = $args->{$arg}; |
if(defined $str){ |
if(!defined $declared->{'$'.$arg} && !defined $declared->{'@'.$arg} && !defined $declared->{'%'.$arg}){ |
if($str =~ m/^\|(.*)\|$/s){ |
$jscript .= "$Obj.$arg = function(){\n$1\n};\n"; |
}elsif($str =~ m/(.*)\|$/s){ |
$jscript .= "$Obj.$arg = function(){\n$1".$taglist{$arg}."\n};\n"; |
}elsif($str =~ m/^\|(.*)/s){ |
$jscript .= "$Obj.$arg = function(){\n".$taglist{$arg}."$1\n};\n"; |
}else{ |
$jscript .= "$Obj.$arg = function(){\n".$taglist{$arg}."$str\n};\n"; |
} |
} |
}else{ |
if(defined $taglist{$arg}){ |
$jscript .= "$Obj.$arg = function(){\n".$taglist{$arg}."\n};\n"; |
} |
} |
} |
return $jscript; |
} |
</%once> |
/tags/2.0/htdocs/input/radio.js |
---|
0,0 → 1,16 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Radio_Init(Objname, Descr){ |
var Obj = Input_Init(Objname, Descr); |
Obj.set_status(); |
return Obj; |
} |
/tags/2.0/htdocs/input/span.js |
---|
0,0 → 1,39 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
function Input_Span_Init(Objname, Descr, DispTemplate, EmptyDescr, Value){ |
var Obj = Input_Init(Objname, Descr); |
Obj.DispTemplate = DispTemplate; |
Obj.DisplayDescr = Obj; |
Obj.EmptyDescr = EmptyDescr; |
// inizializza il valore del campo selezionato |
Obj.set_value = function (value, param){ |
%#DEBUG <% $JSLogger->debug(q|'Input_Span_Init.set_value value:"'+value+'" param:"'+param+'"'|) %> |
Obj.Value = value; |
if(param != null && param.length != 0){ |
this.set_param(param); |
}else{ |
this.Parameters = null; |
this.set_display(); |
} |
} |
Obj.set_value(Value); |
// metodo per la lettura del valore del componente |
Obj.get_value = function (){ |
return this.Value; |
} |
Obj.Readonly = function(){return true}; |
Obj.set_status(''); |
Obj.setFocus = null; |
return Obj; |
} |
/tags/2.0/htdocs/test/test_callRemote.mql |
---|
0,0 → 1,9 |
<%method CALL_REMOTE_test_callRemote> |
<%args> |
$par1 |
$par2 |
</%args> |
par1 = <% $par1 %><br> |
par2 = <% $par2 %> |
</%method> |
/tags/2.0/htdocs/test/dojo/rest/dhandler |
---|
0,0 → 1,62 |
<%args> |
</%args> |
<%flags> |
inherit => undef |
</%flags> |
<%init> |
use Data::Dumper; |
my $schema; |
my $table; |
my $id; |
my $arg = $m->dhandler_arg; |
if($arg =~ m|(\w+)/(\w+)/(\w+)|){ |
$schema = $1; |
$table = $2; |
$id = $3; |
}elsif($arg =~ m|(\w+)/(\w+)/{0,1}|){ |
$schema = $1; |
$table = $2; |
}else{ |
die "URI malformed use /schema/table/id\n"; |
} |
my $url = $r->dir_config('DataBaseUrl')."/$schema/$table.mql"; |
my $method = $r->method(); |
my $size = $r->headers_in->{'Content-length'}; |
my $content; |
$r->read($content, $size); |
if($method =~ /POST|PUT|DELETE/i){ |
$method = lc $method; |
} |
# Si veda http://www.ietf.org/rfc/rfc2616.txt |
# POST --> create |
# PUT --> update |
# DELETE --> delete |
# GET --> retrieve N.B. metodo 'select' era già utilizzato per altri scopi |
if($method eq 'POST'){ |
$ARGS{method} = 'create'; |
}elsif($method eq 'PUT'){ |
$ARGS{method} = 'update'; |
}elsif($method eq 'DELETE'){ |
$ARGS{method} = 'delete'; |
}else{ |
$ARGS{method} = 'retrieve'; |
} |
if(exists $ENV{HTTP_CONTENT_RANGE} && $ENV{HTTP_CONTENT_RANGE} =~ m/(\d+)-(\d+|\**)/){ |
my $start = $1 || 0; |
$ARGS{'start'} = $start; |
my $stop = $2; |
if(defined $stop && $stop ne '*' && $stop ne ''){ |
$ARGS{'rows'} = $stop - $start + 1; |
} |
} |
</%init> |
% print STDERR "ARGS: $schema $table $id\n"; |
% print STDERR "URL: $url\n"; |
% print STDERR Dumper(\%ARGS); |
% print STDERR "_______________CONTENT_______________\n\n"; |
% print STDERR $content; |
% print STDERR "\n______________________________________\n"; |
<%perl> |
$m->subexec($url, %ARGS, envelope_response => 'xml', envelope_request => 'xml', CRUD => 'crud'); |
#$m->subexec($url, %ARGS, envelope_response => 'xml', envelope_request => 'xml', CRUD => 'crud'); |
</%perl> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree_data.html |
---|
0,0 → 1,296 |
<%doc> |
http://dojotoolkit.org/documentation/tutorials/1.6/store_driven_tree/ |
http://dojotoolkit.org/reference-guide/dojo/store/JsonRest.html |
http://download.dojotoolkit.org/release-1.5.0/dojo-release-1.5.0/dijit/tests/tree/test_Tree_DnD.html |
http://dojotoolkit.org/reference-guide/dijit/Tree.html |
</%doc> |
% &LoadHeader($Session{'Dojo_dir'}.'/dojox/form/resources/UploaderFileList.css'); |
% &LoadHeader('/test/dojo/test_dojo_tree_data.css'); |
<script> |
dojo.require("dojo.store.JsonRest"); |
dojo.require("dojo.store.Observable"); |
dojo.require("dijit.Menu"); |
dojo.require("dijit.Tree"); |
dojo.require("dijit.TooltipDialog"); |
dojo.require("dijit.tree.dndSource"); |
dojo.require("dojox.form.Uploader"); |
dojo.require("dojox.form.uploader.plugins.HTML5"); |
dojo.require("dojox.form.uploader.FileList"); |
dojo.ready(function(){ |
Store = dojo.store.JsonRest({ |
target: "/test/dojo/test_dojo_tree_data/impianti/apparecchiature/1", |
root: '/', |
mayHaveChildren: function(object){ |
return object.children != null; |
}, |
getChildren: function(object, onComplete, onError){ |
// retrieve the full copy of the object |
this.get(object.id).then(function(fullObject){ |
// copy to the original object so it has the children array as well. |
object.children = fullObject.children; |
// now that full object, we should have an array of children |
onComplete(fullObject.children); |
}, function(error){ |
alert('ERROR:' + error.message) |
// an error occurred, log it, and indicate no children |
console.error(error); |
onComplete([]); |
}); |
}, |
getRoot: function(onItem, onError){ |
// get the root object, we will do a get() and callback the result |
this.get(this.root).then(onItem, onError); |
}, |
getLabel: function(object){ |
// just get the name |
return object.name; |
}, |
pasteItem: function(child, oldParent, newParent, bCopy, insertIndex){ |
var dest_dir_id = this.mayHaveChildren(newParent) ? newParent.id : newParent.id.replace(/\/[^\/]*$/, ''); |
if(oldParent.id == dest_dir_id){ |
return false; |
} |
// comunico al server lo spostamento |
child.new_id = dest_dir_id + '/' + child.id.replace(/^.*\//, ''); |
child.children = null; |
var store = this; |
store.put(child).then(function(){ |
// aggiorno la cartella nell'albero |
store.get(dest_dir_id).then(function(dir){ |
store.onChange(dir); |
store.onChildrenChange(dir, dir.children); |
}); |
store.get(oldParent.id).then(function(dir){ |
store.onChange(dir); |
store.onChildrenChange(dir, dir.children); |
}); |
}); |
}, |
put: function(object, options){ |
// fire the onChildrenChange event |
this.onChildrenChange(object, object.children); |
// fire the onChange event |
this.onChange(object); |
// execute the default action |
return dojo.store.JsonRest.prototype.put.apply(this, arguments); |
}, |
remove: function(id){ |
var store = this; |
var id_dir = id.replace(/\/[^\/]*$/, ''); |
dojo.store.JsonRest.prototype.remove.apply(this, arguments).then(function(){ |
// ritorna l'id della directory che conteneva il file cancellato |
store.get(id_dir).then(function(dir){ |
// notifico il cambiamento |
store.onChange(dir); |
store.onChildrenChange(dir, dir.children); |
}); |
}); |
}, |
// we can also put event stubs so these methods can be |
// called before the listeners are applied |
onChildrenChange: function(parent, children){ |
// fired when the set of children for an object change |
console.debug('onChildrenChange', parent, children) |
}, |
onChange: function(object){ |
// fired when the properties of an object change |
console.debug('onChange', object); |
} |
});//Store |
var tree = new dijit.Tree({ |
model: Store, |
autoExpand: false, |
openOnClick: true, |
showRoot: true, //false, |
// define the drag-n-drop controller |
dndController: dijit.tree.dndSource |
}, "demo_tree"); // make sure you have a target HTML element with this id |
tree.close_popups = function () { |
// chiudo e svuoto i pannelli aperti |
dijit.popup.close(dijit.byId('tree_dialog')); |
dijit.popup.close(dijit.byId('delete_dialog')); |
dijit.popup.close(dijit.byId('upload_dialog')); |
dijit.byId('files').reset(); |
// console.debug('close_popups'); |
} |
tree.onClick = function () { |
this.close_popups(); |
// console.debug('Click tree'); |
}; |
tree.onDblClick = function (item) { |
this.close_popups(); |
if(!item.children){ |
this.download_item(item, 'download'); |
console.debug('download ...'); |
} |
}; |
tree.onClose = tree.close_popups; |
tree.onOpen = tree.close_popups; |
tree.startup(); |
var menu = dijit.byId("tree_menu"); |
// when we right-click anywhere on the tree, make sure we open the menu |
menu.bindDomNode(tree.domNode); |
var TreeObj; |
dojo.connect(menu, "_openMyself", this, function(e) { |
TreeObj = e.target; |
// get a hold of, and log out, the tree node that was the source of this open event |
var tn = dijit.getEnclosingWidget(e.target); |
console.debug('dijit.getEnclosingWidget:', tn.item.id, tn); |
// mostro le voci del menu compatibili |
var children = menu.getChildren(); |
children.forEach(function(i) { |
if(i.id == 'rename' || i.id == 'delete') |
i.set('style', {'display': tn.indent > 0 ? '' : 'none'}); |
if(i.id == 'new_folder' || i.id == 'upload') |
i.set('style', {'display': tn.item.children ? '' : 'none'}); |
if(i.id == 'download') |
i.set('style', {'display': tn.item.children ? 'none' : ''}); |
}); |
}); |
menu.open_dialog = function() { |
var id_cmd = dijit.getEnclosingWidget(this).id; |
var tree_dialog = dijit.byId('tree_dialog'); |
// comando: rename / new_folder |
tree_dialog.id_cmd = id_cmd; |
// nome del file |
dojo.byId('tree_dialog_name').value = id_cmd == 'rename' ? dijit.getEnclosingWidget(TreeObj).item.name : ''; |
dojo.byId('tree_dialog_btn').innerHTML = id_cmd == 'rename' ? 'Rinomina' : 'Nuova cartella'; |
dijit.popup.open({ |
popup: tree_dialog, |
around: TreeObj |
}); |
}; |
menu.close_dialog = function() { |
var tree_dialog = dijit.byId('tree_dialog'); |
var new_name = dojo.byId('tree_dialog_name').value |
var item = dijit.getEnclosingWidget(TreeObj).item; |
// verifico che nel nome non ci siano alcuni caratteri speciali |
var forbidden_chars = []; |
['*', '<', '>', '#', '?', '/', '\\', '"', "'"].forEach(function (c){ |
if(new_name.indexOf(c) != -1){ |
forbidden_chars.push(c); |
} |
}); |
if(forbidden_chars.length){ |
if(forbidden_chars.length == 1){ |
alert('Il carattere (' + forbidden_chars[0] + ') non può essere utilizzato nel nome'); |
}else{ |
alert('I caratteri (' + forbidden_chars.join(', ') + ') non possono essere utilizzati nel nome'); |
} |
return false; |
} |
if(tree_dialog.id_cmd == 'rename'){ |
console.debug('rename', new_name, item); |
item.name = new_name; |
Store.put(item).then(function(){ |
var id_dir = item.id.replace(/\/[^\/]*$/, ''); |
Store.get(id_dir).then(function(dir){ |
// notifico il cambiamento |
Store.onChange(dir); |
Store.onChildrenChange(dir, dir.children); |
}); |
}); |
}else{ |
console.debug('new_folder', new_name, item); |
var id_dir = dijit.getEnclosingWidget(TreeObj).item.id; |
Store.add({ new_name:new_name, id:id_dir + '/' + new_name, children:1 }).then(function (){ |
// aggiorno la cartella nell'albero |
Store.get(id_dir).then(function(dir){ |
Store.onChange(dir); |
Store.onChildrenChange(dir, dir.children); |
}); |
}); |
} |
%#// console.debug('close_dialog', this); |
dijit.popup.close(tree_dialog); |
}; |
dojo.connect(dojo.byId('rename'), 'onclick', menu.open_dialog); |
dojo.connect(dojo.byId('new_folder'), 'onclick', menu.open_dialog); |
dojo.connect(dojo.byId('delete'), 'onclick', function() { |
dijit.popup.open({ |
popup: dijit.byId('delete_dialog'), |
around: TreeObj |
}); |
}); |
dojo.connect(dojo.byId('upload'), 'onclick', function() { |
var upload_dialog = dijit.byId('upload_dialog'); |
dojo.byId('upload_dir').value = 'impianti/apparecchiature/1' + dijit.getEnclosingWidget(TreeObj).item.id; |
dijit.popup.open({ |
popup: upload_dialog, |
around: TreeObj |
}); |
}); |
// eventi del caricamento dei file |
dojo.connect(dijit.byId('uploader'), 'onComplete', function(params) { |
console.debug('uploader onComplete', unescape(dojo.toJson(params))); |
dijit.byId('demo_tree').close_popups(); |
var dir = dijit.getEnclosingWidget(TreeObj).item.id; |
Store.get(dir).then(function(dir){ |
Store.onChange(dir); |
Store.onChildrenChange(dir, dir.children); |
}); |
}); |
dojo.connect(dijit.byId('uploader'), 'onError', function(params) { |
console.debug('uploader onError', dojo.toJson(params)); |
}); |
// richiamato dalla combo |
tree.download_item = function (item, mode) { |
var id_file = item ? item.id : dijit.getEnclosingWidget(TreeObj).item.id; |
console.debug('download item', id_file); |
var params = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable,alwaysRaised,dependent,titlebar=no,width=800,height=600'; |
var url = Store.target + id_file + '?' + mode; |
window.open(url, '_blank', params); |
} |
// richiamato alla conferma della cancellazione del file/dir |
tree.delete_item = function (item) { |
var id_file = item ? item.id : dijit.getEnclosingWidget(TreeObj).item.id; |
console.debug('delete item', id_file); |
// cancello il file nello store remoto |
Store.remove(id_file); // N.B. La chiamata originale non permette di gestire il timeout |
dijit.popup.close(dijit.byId('delete_dialog')); |
} |
});//dojo.ready |
</script> |
<h1>Demo: File Store</h1> |
<div id="demo_tree"></div> |
<div style="display:none"> |
<div dojoType="dijit.Menu" id="tree_menu"> |
<div id="download" dojoType="dijit.MenuItem" onClick="dijit.byId('demo_tree').download_item(null, 'save');">Scarica sul PC</div> |
<div id="rename" dojoType="dijit.MenuItem">Rinomina</div> |
<div id="upload" dojoType="dijit.MenuItem" >Carica nel server</div> |
<div id="new_folder" dojoType="dijit.MenuItem">Nuova cartella</div> |
<div id="delete" dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconDelete">Cancella</div> |
</div> |
<div data-dojo-type="dijit.TooltipDialog" id="tree_dialog"> |
<input id="tree_dialog_name" type="text" style="width:300px;"></input> |
<button id="tree_dialog_btn" onclick="dijit.byId('tree_menu').close_dialog();" dojoType="dijit.form.Button">OK</button> |
<button onclick="dijit.popup.close(dijit.byId('tree_dialog'))" dojoType="dijit.form.Button">Annulla</button> |
</div> |
<div data-dojo-type="dijit.TooltipDialog" id="delete_dialog"> |
<div>Sei certo di voler cancellare?</div><br> |
<button id="delete_dialog_btn" onclick="dijit.byId('demo_tree').delete_item();" dojoType="dijit.form.Button">Cancella</button> |
<button onclick="dijit.popup.close(dijit.byId('delete_dialog'))" dojoType="dijit.form.Button">Annulla</button> |
</div> |
<div data-dojo-type="dijit.TooltipDialog" id="upload_dialog"> |
<form method="post" action="test_dojo_tree_data/upload.mason" id="upload_form" enctype="multipart/form-data" style="width:420px;"> |
<fieldset> |
<legend>Carica nel server</legend> |
<input class="browseButton" name="uploadedfile" multiple="true" type="file" style="width:140px;" |
force="iframe" dojoType="dojox.form.Uploader" label="Selezionare i file" id="uploader" /> |
<input type="button" id="remBtn" label="Clear" onClick="dijit.byId('files').reset();" dojoType="dijit.form.Button" /> |
<input type="hidden" id="upload_dir" name="upload_dir" /> |
<input type="submit" label="Submit" dojoType="dijit.form.Button" /> |
<button onclick="dijit.byId('files').reset();dijit.popup.close(dijit.byId('upload_dialog'))" dojoType="dijit.form.Button">Annulla</button> |
<div id="files" dojoType="dojox.form.uploader.FileList" uploaderId="uploader"></div> |
</fieldset> |
</form> |
</div> |
</div> |
/tags/2.0/htdocs/test/dojo/test_dojo_events.html |
---|
0,0 → 1,23 |
<%args> |
</%args> |
Test Events: |
<hr/> |
<script> |
require(["dojo/ready", "dijit/registry", "dojo/on", "dojo/Evented", "dojo/dom-construct", "dojo/json"], |
function(ready, registry, on, Evented, domConstruct, JSON){ |
ready(function(){ |
on(registry.byId('eventBtn'), 'click', function(evt){ |
masonSql.ready({pinco: 'pallo'}); |
}); |
masonSql.on('ready', function(data){ |
console.log('Event masonSql ready data:', data); |
}); |
masonSql.on('ready', function(data){ |
domConstruct.place("<br>Event masonSql ready data:"+JSON.stringify(data), "print_area"); |
}); |
}); |
}); |
</script> |
<button data-dojo-type="dijit/form/Button" id="eventBtn" data-dojo-props="" type="button">Fire event myevent</button> |
<div id="print_area"></div> |
/tags/2.0/htdocs/test/dojo/test_dojo_Select_JsonRest.html |
---|
0,0 → 1,55 |
% my $id = 'select_'; |
% my $key = 'id'; |
% my $key_set = "4"; |
<html> |
<h2>test Dojo Select with dojo/store/JsonRest</h2> |
<br> |
S1:<div id="<% $id %>1" style="width: 150px;" data-dojo-type="dijit/form/Select" |
data-dojo-props="searchAttr:'<% $key %>', labelAttr:'nome', title:'Select S1'"></div> |
<script> |
masonSql.once('ready', function(data){ |
require(["dojo/ready", "dijit/registry", "dijit/form/Select", "dojo/store/JsonRest", "dojo/store/Observable"], |
function(parser, registry, Select, JsonRest, Observable){ |
var restStore = new JsonRest({ |
target: '/rest/public/anagrafiche', |
idProperty: '<% $key %>', |
sortParam: "sortBy" |
}); |
var observableStore = Observable(restStore); |
window.observableStore = observableStore; |
registry.byId('<% $id %>1').setStore(observableStore, 'admin2'); |
}); |
}); |
</script> |
<br> |
<br> |
<button onclick="window.Id_<% $id %>1.set_value(<% $key_set %>);">Set S1 with <% $key %>:<% $key_set %></button> |
<button onclick="document.getElementById('contenuto').value = window.Id_<% $id %>1.get_value();" >Get S1</button>:<input id="contenuto"></input> |
<button onclick="window.Id_<% $id %>1.Readonly(true);">Readonly S1</button> |
<button onclick="window.Id_<% $id %>1.Readonly(false);">No readonly S1</button> |
<br> |
<br> |
<script> |
require(["dojo/dom", "dijit/registry", "dojo/_base/array", "dojo/on", "dojo/_base/event"], function (dom, registry, array, on, event){ |
masonSql.once('ready', function(data){ |
var Obj = registry.byId('<% $id %>1'); |
Obj.get_value = function(){ |
return this.get('value'); |
}; |
Obj.set_value = function(value){ |
this.set('value', value); |
return value; |
}; |
Obj.Readonly = function(read){ |
if(read == null){ |
return this.get('readOnly'); |
}else{ |
this.set('readOnly', read); |
return read; |
} |
}; |
window.Id_<% $id %>1 = Obj; |
}); |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/dojo/test_ContentPane_href.html |
---|
0,0 → 1,62 |
<%args> |
$timeout => undef |
</%args> |
% if($timeout){ |
% sleep $timeout; |
<span class='dijitInline dijitIconBookmark'></span>Risposta dal server con ritardo di <% $ timeout%> secondi. |
% }else{ |
Test timeout in dojox/layout/ContentPane utilizzando l'attibuto <b>href</b> |
<script> |
require([ |
"dijit/dijit", |
"dojo/parser", |
"dojox/layout/ContentPane" |
]); |
</script> |
<hr/> |
% for(my $N=4; $N; $N--){ |
<div data-dojo-type="dojox.layout.ContentPane" id="test_xhr_timeout_container<% $N %>" |
parseOnLoad="true" loadingMessage="<span class='dijitInline dijitIconTask'></span>Sto caricando 1 ..." |
executeScripts="true" extractContent="true" title="Panel di test - download" doLayout="false" |
style="margin-left: 24px; width: 580px; height: 30px; padding: 10px; |
background-color: rgb(<% 200 - $N *10 %>,230,<% 200 + $N *10 %>);" ></div> |
% } |
<script> |
window.launch_download = function(id, timeout){ |
require(["dojo/ready", "dijit/registry"], function(ready, registry){ |
ready(function(){ |
var container = registry.byId(id); |
container.set('ioArgs', { |
timeout: timeout * 1000 // millisecondi |
}); |
container.set('href', '<% $ENV{SCRIPT_NAME}%>?timeout=3').then( |
function(){ |
console.log("OK! downloaded") |
}, |
function(err){ |
container.set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+' id:'+container.id+' timeout:'+timeout+"</span>"); |
console.log("ERRORE:"+err+' id:'+container.id+' timeout:'+timeout); |
} |
) |
}); |
}); |
}; |
require(["dojo/ready", "dijit/registry", "dojo/dom-construct"], function(ready, registry, domConstruct){ |
ready(function(){ |
% for(my $N=4; $N; $N--){ |
registry.byId('test_xhr_timeout_container<% $N %>').watch(function(name, oldValue, value){ |
// Do something based on the change |
var log = 'CHANGE container <% $N %> ATTRIB '+name+' from val:['+oldValue+'] to val:['+value+']' |
console.log(log); |
domConstruct.place('<div>'+log+'</div>', 'LAST', 'after') |
}); |
% } |
}); |
}); |
% for(my $N=4; $N; $N--){ |
window.launch_download('test_xhr_timeout_container<% $N %>', <% $N %>); |
% } |
</script> |
<hr id="LAST"/> |
% } # if($timeout) |
/tags/2.0/htdocs/test/dojo/test_dojo_PopupMenuItem.html |
---|
0,0 → 1,37 |
<%doc> |
</%doc> |
<script> |
dojo.require("dijit.Menu"); |
dojo.ready(function(){ |
var menu = dijit.byId("tree_menu"); |
}); |
</script> |
<h1>Demo: PopupMenuItem</h1> |
<div dojoType="dijit.Menu" id="tree_menu"> |
<div id="delete" dojoType="dijit.MenuItem" onClick="my_alert('Cancella');" iconClass="dijitEditorIcon dijitEditorIconDelete">Cancella</div> |
<div id="rename_file" dojoType="dijit.PopupMenuItem"> |
<span>Rinomina</span> |
<div data-dojo-type="dijit.TooltipDialog" data-dojo-props="title:'Rinomina'" id="rename_file_dialog"> |
<input id="rename_file_name" type="text" style="width:300px;"></input> |
<button onclick="dijit.popup.close(dijit.byId('rename_file_dialog'));">Rinomina</button> |
<script type="dojo/method" event="onOpen"> |
console.debug('Open rename_file_dialog'); |
</script> |
</div> |
</div> |
<div dojoType="dijit.MenuItem" onClick="my_alert('Download');">Scarica sul PC</div> |
<div id="upload" dojoType="dijit.MenuItem" onClick="my_alert('Carica nel server');">Carica nel server</div> |
<div id="new" dojoType="dijit.PopupMenuItem" > |
<span>Nuova cartella</span> |
<div data-dojo-type="dijit.TooltipDialog" data-dojo-props="title:'Nuova cartella'" id="new_folder_dialog"> |
<input id="new_name" type="text" style="width:300px;"></input> |
<button onclick="dijit.popup.close(dijit.byId('new_folder_dialog'));">Nuova cartella</button> |
<script type="dojo/method" event="onOpen"> |
console.debug('Open new_folder_dialog'); |
</script> |
</div> |
</div> |
</div> |
/tags/2.0/htdocs/test/dojo/test_dojo_Select.html |
---|
0,0 → 1,45 |
% my $id = 'select_1'; |
<html> |
<h2>test Dojo Select</h2> |
<script src="/input/input.comp?Ver=<% $Ver %>" type="text/javascript"></script> |
<script src="/input/input.js?Ver=<% $Ver %>" type="text/javascript"></script> |
<script> |
require(["dojo/parser", "dijit/form/Select"]); |
</script> |
<div id="<% $id %>" data-dojo-type="dijit/form/Select" style="width:100px; height:28px;"> |
<span value="TN">Tennessee</span> |
<span value="VA" selected="selected"><span class="dijitInline masonSqlIcons refresh"></span><font color="blue">Virginia</font></span> |
<span value="WA">Washington</span> |
<span type="separator"></span> |
<span value="FL">Florida</span> |
<span value="CA">California</span> |
</div> |
<hr> |
<br> |
<button onclick="window.Id_<% $id %>.set_value('FL');" >Set Florida</button> |
<button onclick="document.getElementById('contenuto').value = window.Id_<% $id %>.get_value();" >Get</button>:<input id="contenuto"></input> |
<button onclick="window.Id_<% $id %>.Readonly(true);">Disable</button> |
<button onclick="window.Id_<% $id %>.Readonly(false);">Enable</button> |
<script> |
require(["dojo/dom", "dijit/registry", "dojo/_base/array", "dojo/on", "dojo/_base/event"], function (dom, registry, array, on, event){ |
masonSql.once('ready', function(data){ |
var Obj = registry.byId('<% $id %>'); |
Obj.get_value = function(){ |
return this.get('value'); |
}; |
Obj.set_value = function(value){ |
return this.set('value', value); |
}; |
Obj.Readonly = function(read){ |
if(read == null){ |
return this.get('readOnly'); |
}else{ |
this.set('readOnly', read); |
return read; |
} |
}; |
window.Id_<% $id %> = Obj; |
}); |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/dojo/test_dojo_buttons.css |
---|
0,0 → 1,13 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
/* Test Bottoni di controllo */ |
/* |
#bodyMasonSql.claro .dijitButton .dijitButtonNode |
*/ |
#bodyMasonSql.claro .myTestBtn .dijitButtonNode { |
padding: 10px; |
} |
/tags/2.0/htdocs/test/dojo/test_dojo_tree_data/upload.mason |
---|
0,0 → 1,77 |
<%doc> |
Vedi: http://docs.dojocampus.org/dojox/form/Uploader |
Esempio: /opt/masonsql/htdocs/lib/dojo-release-1.6.1-src/dojox/form/tests/UploadFile.php.disabled |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
<%args> |
$upload_dir |
</%args> |
<%once> |
# use URI::Escape; |
sub uri_escape { return $_[0]} |
</%once> |
<%perl> |
$m->clear_buffer; |
use Data::Dumper; |
my $base_dir = $r->dir_config('DocumentRoot').'/test/dojo/test_dojo_tree_data/data'; |
my $dir = $base_dir.'/'.$upload_dir; |
if(! -d $dir){ |
die "$dir not exists.\n"; |
} |
my $table = $r->upload; # ritorna istanza APR::Request::Param::Table |
# determino il tipo di download |
my @key_files = keys %{$table}; |
my @value_files = values %{$table}; |
my $upload_type = $key_files[0]; # uploadedfileFlash, uploadedfiles[], uploadedfiles1|2|... |
#DEBUG print STDERR "upload_type:$upload_type", Dumper(\@value_files); |
#DEBUG $upload_type='uploadedfileFlash'; |
if($upload_type eq 'uploadedfileFlash'){ |
my $upload = $value_files[0]; |
#DEBUG print STDERR "uploadedfileFlash\n".Dumper($upload); |
my $name = $upload->filename; |
# verifico che il nome non contenga carateri proibiti, altrimenti li converto in '_' |
$name =~ s/[\*<>#\?\/\\'"]/_/g; |
my $file = $dir.'/'.$name; |
if(-f $file){ |
unlink $file or die sprintf "delete '%s' failed: $!", $file; |
} |
if(! $upload->link($file)){ |
print STDERR "uploadedfileFlash link error $! \n"; |
die sprintf "link 1 from '%s' failed: $!", $upload->tempname; |
} |
#DEBUG print STDERR "uploadedfileFlash linked\n".Dumper($upload); |
my $return_data = 'file='.uri_escape($upload_dir.'/'.$name).',name='.uri_escape($name).',type='.uri_escape($upload->type).',size='.$upload->size.',width=,height='; |
#DEBUG print STDERR "return_data:|$return_data|\n"; |
$m->out($return_data); |
}else{ |
my @dataObject; |
foreach my $upload (@value_files){ # istanze Apache2::Upload |
my $name = $upload->filename; |
# verifico che il nome non contenga carateri proibiti, altrimenti li converto in '_' |
$name =~ s/[\*<>#\?\/\\'"]/_/g; |
my $file = $dir.'/'.$name; |
if(-f $file){ |
unlink $file or die sprintf "delete '%s' failed: $!", $file; |
} |
$upload->link($file) or die sprintf "link 1 from '%s' failed: $!", $upload->tempname; |
push @dataObject, { |
'file' => $upload_dir.'/'.$name, |
'name' => $name, |
'type' => $upload->type, |
'size' => $upload->size, |
'width' => undef, |
'height' => undef |
}; |
} |
if($upload_type eq 'uploadedfiles[]'){ |
# HTML5 |
$m->out(JSON::objToJson(\@dataObject)); |
}else{ |
# Iframe |
$m->out('<textarea>'.JSON::objToJson(\@dataObject).'</textarea>'); |
} |
} |
</%perl> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree_data/dhandler |
---|
0,0 → 1,138 |
<%doc> |
http://dojotoolkit.org/features/1.6/object-store |
http://dojotoolkit.org/reference-guide/dojo/store/JsonRest.html |
aptitude install libfile-path-perl |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
<%once> |
use JSON; |
use IPC::Run qw(run); |
use File::Path qw(make_path remove_tree); |
</%once> |
<%init> |
my $base_dir = $r->dir_config('DocumentRoot')."/test/dojo/test_dojo_tree_data/data"; |
use Data::Dumper; |
my $arg = $r->unparsed_uri; #$r->unparsed_uri; $arg =~ s|^/test/dojo/test_dojo_tree_data/||; |
$arg =~ s|^/test/dojo/test_dojo_tree_data/||; |
utf8::decode($arg); |
my $mode_download; |
# N.B. Si usa '.' in quanto non ci sarà mai nel nome delle cartelle il carattere '.' (schema del database) |
if($arg =~ m/^(.*)\?(\w+)$/){ |
$arg = $1; |
$mode_download = $2; |
} |
print STDERR 'CALL '.$r->method()." [$arg] mode:$mode_download\n"; |
</%init> |
<%perl> |
# $arg corriponde al file o cartella presente in $base_dir/ |
my($schema, $table, $id, $path) = split /\//, $arg, 4; |
$base_dir .= "/$schema/$table/$id"; |
if(! -d $base_dir){ |
make_path $base_dir; |
} |
my $file = "$base_dir/$path"; |
$path = '/'.$path; |
my $name = $path; |
$name =~ s|^.*/||; |
my $method = $r->method(); |
if($mode_download && $method eq 'GET'){ # ------------------------------------ GET download |
die "$schema.$table:$id $path not exists" if(! -e $file); |
my $filetype; |
if($mode_download eq 'save'){ |
$filetype = 'application/octet-stream; charset=binary'; |
}else{ |
run ['/usr/bin/file', '--mime', '--brief', $file], '>', \$filetype || die "run: $!"; |
chomp $filetype; |
} |
print STDERR "DOWNLOAD [$mode_download: $filetype] $schema.$table:$id $path\n"; |
$r->content_type($filetype); |
sysopen FILE, $file, 'O_RDONLY' || die "sysopen $file: $!"; |
my $buffer; |
# leggo il file generato a blocchi di 64Kbyte |
while(my $numchar = sysread FILE, $buffer, 2^16){ |
if(undef $numchar){ |
die "sysread $file: $!"; |
}; |
$m->out($buffer); |
$m->flush_buffer; |
} |
return 200; |
}elsif($method eq 'DELETE'){ # --------------------------------------------------- DELETE |
die "$schema.$table:$id $path not exists" if(! -e $file); |
if(-d $file){ |
# run ['/bin/rm', '-r', $file] || die "run: $!"; |
remove_tree $file || die "can't delete $path: $!"; |
}else{ |
unlink $file || die "can't delete $path: $!"; |
} |
print STDERR "DELETED $schema.$table:$id $path\n"; |
return 200; |
}elsif($method eq 'PUT'){ # ------------------------------------------------------ PUT |
my $content; $r->read($content, $r->headers_in->{'Content-length'}); |
utf8::decode($content); |
print STDERR "PUT $content\n"; |
my $obj = jsonToObj($content); # {"name":"newname","id":"public/anagrafiche/1/tre/oldname"} |
# modifica del nome o creazione di una cartella? |
if($obj->{'new_name'}){ |
print STDERR "CREATE DIR $schema.$table:$id $obj->{'id'}\n"; |
make_path $base_dir.'/'.$obj->{'id'}; |
return 200; |
}else{ |
my $dir = $obj->{'id'}; |
$dir =~ s|[^/]*$||; |
if($obj->{'name'} ne '' && $obj->{'name'} ne $name){ |
die "$path not exists" if(! -e $file); |
$file = $base_dir.'/'.$obj->{'id'}; |
# verifico che il nome non contenga carateri proibiti, altrimenti li converto in '_' |
$obj->{'name'} =~ s/[\*<>#\?\/\\'"]/_/g; |
my $new = $base_dir.'/'.$dir.$obj->{'name'}; |
rename $file, $new || die "can't rename $obj->{'id'} to $obj->{'name'}: $!"; |
print STDERR "RENAMED $schema.$table:$id [$obj->{'id'}] to [$dir$obj->{'name'}]\n"; |
return 200; |
}elsif($obj->{'new_id'}){ |
rename $base_dir.'/'.$obj->{'id'}, $base_dir.'/'.$obj->{'new_id'} |
|| die "can't move $obj->{'id'} to $obj->{'new_id'}: $!"; |
print STDERR "MOVE $schema.$table:$id [$obj->{'id'}] to [$dir$obj->{'new_id'}]\n"; |
return 200; |
}else{ |
print STDERR "UNDEFINED PUT\n"; |
return 400; |
} |
} |
}elsif($method eq 'GET'){ # ---------------------------------------------------- GET |
if(-d $file){ |
print STDERR "RETURN DIR $schema.$table:$id $path\n"; |
my @children; |
my %dir_obj = ('name' => $name, 'id' => $path ); |
my $dir; |
opendir($dir, $file) || die "can't opendir $schema.$table:$id $path: $!"; |
if($path eq '/'){ |
$path = ''; |
} |
while(my $filename = readdir $dir){ |
utf8::decode($filename); |
next if($filename eq '.' || $filename eq '..'); |
my %file_obj = ( 'name' => $filename, 'id' => "$path/$filename"); |
if(-d "$file/$filename"){ |
$file_obj{'children'} = 1; |
} |
push @children, \%file_obj; |
} |
closedir $dir; |
# ordinamento con le cartelle in testa |
my @sorted = sort { $b->{'children'} cmp $a->{'children'} || uc $a->{'name'} cmp uc $b->{'name'} } @children; |
$dir_obj{'children'} = \@sorted; |
print STDERR Dumper(\%dir_obj), objToJson(\%dir_obj); |
$m->print(objToJson(\%dir_obj)); |
}else{ |
print STDERR "RETURN FILE $schema.$table:$id $path\n"; |
my %file_obj = ( 'name' => $name, 'id' => $path ); |
$m->out(objToJson(\%file_obj)); |
} |
}else{ # ---------------------------------------------------------------------- POST, ecc. |
$m->out("No method '$method' is provided"); |
exit 501; |
} |
</%perl> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree_data/prova |
---|
0,0 → 1,0 |
it |
/tags/2.0/htdocs/test/dojo/test_dojo_Select_JsonRest_Cache.html |
---|
0,0 → 1,75 |
% my $id = 'select_'; |
% my $key = 'id'; |
% my $key_set = '4'; |
<html> |
<h2>test Dojo Select with dojo/store/JsonRest</h2> |
<br> |
S1:<div id="<% $id %>1" style="width: 150px;" data-dojo-type="dijit/form/Select" data-dojo-props="labelAttr:'nome', title:'Select S1'"></div> |
S2:<div id="<% $id %>2" style="width: 150px;" data-dojo-type="dijit/form/Select" data-dojo-props="labelAttr:'nome', title:'Select S2'"></div> |
S3:<div id="<% $id %>3" style="width: 150px;" ></div> |
<script> |
masonSql.once('ready', function(data){ |
require(["dojo/ready", "dijit/registry", "dijit/form/Select", "dojo/store/Memory", "dojo/store/JsonRest", "dojo/store/Cache", "dojo/store/Observable"], |
function(parser, registry, Select, Memory, JsonRest, Cache, Observable){ |
var restStore = new JsonRest({ |
target: '/rest/public/anagrafiche', |
idProperty: '<% $key %>', |
sortParam: "sortBy" |
}); |
var memoryStore = new Memory({idProperty: '<% $key %>'}); |
var observableStore = Observable(memoryStore); |
var myStore = new Cache(restStore, observableStore); |
myStore.query(); |
registry.byId('<% $id %>1').setStore(observableStore); |
registry.byId('<% $id %>2').setStore(observableStore); |
var s3 = new Select({ |
store: observableStore, |
maxHeight: 60, |
labelAttr: 'nome', |
title: 'Select S3', |
style: 'width:100px;' |
}, '<% $id %>3'); |
window.s3 = s3; |
// var globali per debug |
window.memoryStore = memoryStore; |
window.observableStore = observableStore; |
window.myStore = myStore; |
}); |
}); |
</script> |
<br> |
<br> |
<button onclick="window.Id_<% $id %>1.set_value('<% $key_set %>');">Set S1 with <% $key %>:<% $key_set %>)</button> |
<button onclick="document.getElementById('contenuto').value = window.Id_<% $id %>1.get_value();" >Get S1</button>:<input id="contenuto"></input> |
<button onclick="window.Id_<% $id %>1.Readonly(true);">Disable S1</button> |
<button onclick="window.Id_<% $id %>1.Readonly(false);">Enable S1</button> |
<br> |
<br> |
<script> |
require(["dojo/dom", "dijit/registry", "dojo/_base/array", "dojo/on", "dojo/_base/event"], function (dom, registry, array, on, event){ |
masonSql.once('ready', function(data){ |
var Obj = registry.byId('<% $id %>1'); |
Obj.get_value = function(){ |
return this.get('value'); |
}; |
Obj.set_value = function(value){ |
this.set('value', value); |
return value; |
}; |
Obj.Readonly = function(read){ |
if(read == null){ |
return this.get('readOnly'); |
}else{ |
this.set('readOnly', read); |
return read; |
} |
}; |
window.Id_<% $id %>1 = Obj; |
}); |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/dojo/test_dojo_buttons.html |
---|
0,0 → 1,49 |
<%args> |
</%args> |
% &LoadHeader('/test/dojo/test_dojo_buttons.css'); |
Test Buttons: |
<script> |
require(["dojo/parser", "dijit/form/Button"]); |
</script> |
<hr/> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons cancel', showLabel:false, title:'Annulla le modifiche'" type="button">Annulla</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons refresh', showLabel:false, title:'Ricarica i dati dal server'" type="button">Aggiorna</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn myNav" data-dojo-props="iconClass:'masonSqlIcons rewind', showLabel:false, title:'Salta all\'inizio della selezione'" type="button">Primo</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn myNav" data-dojo-props="iconClass:'masonSqlIcons down', showLabel:false, title:'Salta alla scheda precedente'" type="button">Precedente</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn myNav" data-dojo-props="iconClass:'masonSqlIcons up', showLabel:false, title:'Salta alla scheda successiva'" type="button">Successivo</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn myNav" data-dojo-props="iconClass:'masonSqlIcons forward', showLabel:false, title:'Salta alla fine della selezione'" type="button">Ultimo</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons delete', showLabel:false, title:'Cancella la scheda'" type="button">Cancella</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons print', showLabel:false, title:'Stampa la scheda'" type="button">Stampa</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons dup', showLabel:false, title:'Esporta nel formato XLS'" type="button">XLS</button> |
<button data-dojo-type="dijit/form/Button" class="myTestBtn" data-dojo-props="iconClass:'masonSqlIcons goto', showLabel:false, title:'Salta alla posizione indicata'" type="button">Salta</button> |
<hr/> |
<button data-dojo-type="dijit/form/Button" id="disableBtn" data-dojo-props="" type="button">Disable buttons</button> |
<button data-dojo-type="dijit/form/Button" id="labelBtn" data-dojo-props="" type="button">Enable labels</button> |
<button data-dojo-type="dijit/form/Button" id="hiddenBtn" data-dojo-props="" type="button">Hidden navigations</button> |
<script> |
require(["dojo/ready", "dojo/query", "dijit/registry", "dojo/on"], function(ready, query, registry, on){ |
ready(function(){ |
on(registry.byId('disableBtn'), 'click', function(evt){ |
var disable = this.get('label') == 'Disable buttons'; |
this.set('label', (disable ? 'Enable' : 'Disable') + ' buttons' ) |
query(".myTestBtn").forEach(function(node, index, arr){ |
registry.byNode(node).set('disabled', disable); |
}); |
}); |
on(registry.byId('labelBtn'), 'click', function(evt){ |
var enable = this.get('label') == 'Enable labels'; |
this.set('label', (enable ? 'Disable' : 'Enable') + ' labels' ) |
query(".myTestBtn").forEach(function(node, index, arr){ |
registry.byNode(node).set('showLabel', enable); |
}); |
}); |
on(registry.byId('hiddenBtn'), 'click', function(evt){ |
var hidden = this.get('label') == 'Hidden navigations'; |
this.set('label', (hidden ? 'Show' : 'Hidden') + ' navigations' ) |
query(".myNav").forEach(function(node, index, arr){ |
registry.byNode(node).set('style', {display: hidden ? 'none' : ''}); |
}); |
}); |
}); |
}); |
</script> |
/tags/2.0/htdocs/test/dojo/test_dojo_Dialog.html |
---|
0,0 → 1,62 |
<h1>Demo: dojox/widget/DialogSimple</h1> |
<script> |
// Dialog Edit |
// il mio dialogo di test |
var myDialog; |
// Apre un form con maggiore dettaglio del record indicato (row: riga del record) |
function openDialog(dimX, dimY, title, url){ |
dimX = dimX || 640; |
dimY = dimY || 480; |
require(["dojo/io-query", "dojox/widget/DialogSimple", "dojo/dom-construct", "dojo/dom-style"], function(ioQuery, DialogSimple, domConstruct, domStyle){ |
if(!myDialog){ |
myDialog = new DialogSimple({ |
title: title, |
executeScripts: true, |
renderStyles: true, |
scriptHasHooks: true, |
parseOnLoad: true, |
cleanContent: true, |
closable: false, |
ioArgs: { |
headers: { |
'MasonSql-body': '1' |
}, |
timeout: <% $r->dir_config('GetFormTimeout') %> |
}, |
onLoad: function(){ |
domStyle.set(myDialog.containerNode, 'height', (myDialog.Height - myDialog.titleBar.offsetHeight - 6) + 'px'); |
} |
}); |
myDialog.containerNode.style.padding = '2px 2px'; |
domConstruct.place('<% q{ |
<span style="float:right;"> |
<button tabindex="-1" onclick="myDialog.hide()">Annulla</button> |
</span> |
} |js%>', myDialog.titleBar, 2 /* seconda posizione */); |
}else{ |
myDialog.set('content', ''); |
} |
myDialog.Height = dimY; |
myDialog.set('style', 'width:' + dimX + 'px; height:' + dimY + 'px;'); |
myDialog.show(); |
myDialog.set('href', url).then( |
function(){ |
console.debug('downloaded href' + url, myDialog); |
}, |
function(err){ |
tab.set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+' id:'+myDialog.id+' timeout:'+<% $r->dir_config('GetFormTimeout') %>+"</span>"); |
console.error('ERROR href ' + url, err , myDialog); |
} |
); |
}); |
} |
</script> |
<button onclick="openDialog(800, 600, 'form 800x600', '/test/test_string.html')">form 800x600</button> |
<button onclick="openDialog(640, 320, 'form 640x320', '/test/test_number.html')">form 640x320</button> |
<button onclick="openDialog(1000, 200, 'form 1000x200', '/test/test_date.html')">form 1000x200</button> |
/tags/2.0/htdocs/test/dojo/test_dojo_uppercase.html |
---|
0,0 → 1,29 |
%# &LoadHeader('/test/dojo/test_dojo_???.css'); |
<script> |
dojo.require("dijit.form.TextBox"); |
dojo.require("dojo.parser"); |
dojo.addOnLoad(function(){ |
dojo.parser.parse(); |
var box0 = dijit.byId("value0Box"); |
var box1 = dijit.byId("value1Box"); |
box1.set("value", box0.get("value").toUpperCase()); |
dojo.connect(box0, "onChange", function(){ |
box0.set("value", box0.get("value").toUpperCase()); |
box1.set("value", box0.get("value").toUpperCase()); |
}); |
}); |
</script> |
<h2>test Dojo Toolkit - onChange event</h2> |
<label for="value0Box">A textbox with a value:</label> |
<input id="value0Box" data-dojo-type="dijit.form.TextBox" value="Some value" data-dojo-props="intermediateChanges:true"></input> |
<br> |
<br> |
<label for="value1Box">A textbox set with Upper value<br>from the above textbox:</label> |
<input id="value1Box" data-dojo-type="dijit.form.TextBox"></input> |
<br> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree.json |
---|
0,0 → 1,46 |
{ |
identifier: 'id', |
label: 'name', |
items: [ |
{ id: 'AF', name:'Africa', type:'continent', population:'900 million', area: '30,221,532 sq km', |
timezone: '-1 UTC to +4 UTC', |
children:[{_reference:'EG'}, {_reference:'KE'}, {_reference:'SD'}] }, |
{ id: 'EG', name:'Egypt', type:'country' }, |
{ id: 'KE', name:'Kenya', type:'country', |
children:[{_reference:'Nairobi'}, {_reference:'Mombasa'}] }, |
{ id: 'Nairobi', name:'Nairobi', type:'city' }, |
{ id: 'Mombasa', name:'Mombasa', type:'city' }, |
{ id: 'SD', name:'Sudan', type:'country', |
children:{_reference:'Khartoum'} }, |
{ id: 'Khartoum', name:'Khartoum', type:'city' }, |
{ id: 'AS', name:'Asia', type:'continent', |
children:[{_reference:'CN'}, {_reference:'IN'}, {_reference:'RU'}, {_reference:'MN'}] }, |
{ id: 'CN', name:'China', type:'country' }, |
{ id: 'IN', name:'India', type:'country' }, |
{ id: 'RU', name:'Russia', type:'country' }, |
{ id: 'MN', name:'Mongolia', type:'country' }, |
{ id: 'OC', name:'Oceania', type:'continent', population:'21 million', |
children:{_reference:'AU'}}, |
{ id: 'AU', name:'Australia', type:'country', population:'21 million'}, |
{ id: 'EU', name:'Europe', type:'continent', |
children:[{_reference:'DE'}, {_reference:'FR'}, {_reference:'ES'}, {_reference:'IT'}] }, |
{ id: 'DE', name:'Germany', type:'country' }, |
{ id: 'FR', name:'France', type:'country' }, |
{ id: 'ES', name:'Spain', type:'country' }, |
{ id: 'IT', name:'Italy', type:'country' }, |
{ id: 'NA', name:'North America', type:'continent', |
children:[{_reference:'MX'}, {_reference:'CA'}, {_reference:'US'}] }, |
{ id: 'MX', name:'Mexico', type:'country', population:'108 million', area:'1,972,550 sq km', |
children:[{_reference:'Mexico City'}, {_reference:'Guadalajara'}] }, |
{ id: 'Mexico City', name:'Mexico City', type:'city', population:'19 million', timezone:'-6 UTC'}, |
{ id: 'Guadalajara', name:'Guadalajara', type:'city', population:'4 million', timezone:'-6 UTC' }, |
{ id: 'CA', name:'Canada', type:'country', population:'33 million', area:'9,984,670 sq km', |
children:[{_reference:'Ottawa'}, {_reference:'Toronto'}] }, |
{ id: 'Ottawa', name:'Ottawa', type:'city', population:'0.9 million', timezone:'-5 UTC'}, |
{ id: 'Toronto', name:'Toronto', type:'city', population:'2.5 million', timezone:'-5 UTC' }, |
{ id: 'US', name:'United States of America', type:'country' }, |
{ id: 'SA', name:'South America', type:'continent', |
children:[{_reference:'BR'}, {_reference:'AR'}] }, |
{ id: 'BR', name:'Brazil', type:'country', population:'186 million' }, |
{ id: 'AR', name:'Argentina', type:'country', population:'40 million' } |
]} |
/tags/2.0/htdocs/test/dojo/test_dojo_menu.html |
---|
0,0 → 1,91 |
% &LoadHeader('/test/dojo/test_dojo_menu.css'); |
<script> |
dojo.require("dijit.MenuBar"); |
dojo.require("dijit.PopupMenuBarItem"); |
dojo.require("dijit.Menu"); |
dojo.require("dijit.MenuItem"); |
dojo.require("dijit.PopupMenuItem"); |
dojo.require("dijit.ColorPalette"); |
dojo.addOnLoad(function(){ |
}); |
</script> |
<h2>test Dojo Toolkit - dijit.MenuBar</h2> |
<div dojoType="dijit.MenuBar" id="navMenu"> |
<div dojoType="dijit.PopupMenuBarItem"> |
<span> |
File |
</span> |
<div dojoType="dijit.Menu" id="fileMenu"> |
<div dojoType="dijit.MenuItem" onClick="alert('file 1')"> |
File #1 |
</div> |
<div dojoType="dijit.MenuItem" onClick="alert('file 2')"> |
File #2 |
</div> |
</div> |
</div> |
<div dojoType="dijit.PopupMenuBarItem"> |
<span> |
Edit |
</span> |
<div dojoType="dijit.Menu" id="editMenu"> |
<div dojoType="dijit.MenuItem" onClick="alert('edit 1')"> |
Edit #1 |
</div> |
<div dojoType="dijit.MenuItem" onClick="alert('edit 2')"> |
Edit #2 |
</div> |
</div> |
</div> |
</div> |
<br> |
<br> |
<h2>test Dojo Toolkit - dijit.Menu</h2> |
<br> |
<div dojoType="dijit.Menu" id="windowContextMenu" contextMenuForWindow="true" |
style="display: none;"> |
<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCut" |
onClick="alert('not actually cutting anything, just a test!')"> |
Cut |
</div> |
<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconCopy" |
onClick="alert('not actually copying anything, just a test!')"> |
Copy |
</div> |
<div dojoType="dijit.MenuItem" iconClass="dijitEditorIcon dijitEditorIconPaste" |
onClick="alert('not actually pasting anything, just a test!')"> |
Paste |
</div> |
<div dojoType="dijit.MenuSeparator"> |
</div> |
<div dojoType="dijit.PopupMenuItem"> |
<span> |
Enabled Submenu |
</span> |
<div dojoType="dijit.Menu" id="submenu1"> |
<div dojoType="dijit.MenuItem" onClick="alert('Submenu 1!')"> |
Submenu Item One |
</div> |
<div dojoType="dijit.MenuItem" onClick="alert('Submenu 2!')"> |
Submenu Item Two |
</div> |
</div> |
</div> |
<div dojoType="dijit.PopupMenuItem"> |
<span> |
Popup of something other than a menu |
</span> |
<div dojoType="dijit.ColorPalette"> |
</div> |
</div> |
</div> |
<span> |
Right click anywhere on the page to see this menu. |
</span> |
/tags/2.0/htdocs/test/dojo/test_dojo_Uploader.html |
---|
0,0 → 1,40 |
<%doc> |
</%doc> |
<script> |
dojo.require("dojox.form.Uploader"); |
dojo.require("dojox.form.uploader.FileList"); |
dojo.require("dojox.embed.Flash"); |
if(dojox.embed.Flash.available) { |
dojo.require("dojox.form.uploader.plugins.Flash"); |
}else{ |
dojo.require("dojox.form.uploader.plugins.IFrame"); |
} |
dojo.ready(function(){ |
var u = new dojox.form.Uploader({ |
label: "Select file", |
multiple: false, |
uploadOnSelect: true, |
url: "test_dojo_Uploader_handler.mason?upload=1" |
}, "uploader1"); |
var menu = dijit.byId(""); |
}); |
</script> |
<h1>Demo: dojox.form.Uploader</h1> |
<span id="uploader1" style="width:100px;"></span> |
<hr> |
<form method="post" action="test_dojo_Uploader_handler.mason?upload=2" id="myForm2" enctype="multipart/form-data" > |
<fieldset> |
<legend>Form Post Test</legend> |
<input class="browseButton" name="uploadedfile" multiple="true" type="file" force="iframe" dojoType="dojox.form.Uploader" label="Select Some Files" id="uploader"> |
<input type="button" id="remBtn" label="Clear" dojoType="dijit.form.Button" /> |
<input type="submit" label="Submit" dojoType="dijit.form.Button" /> |
<div id="files" dojoType="dojox.form.uploader.FileList" uploaderId="uploader"></div> |
</fieldset> |
</form> |
<textarea rows="10" cols="100"><% Dumper(\%ENV)%></textarea> |
/tags/2.0/htdocs/test/dojo/test_dojo_template.html |
---|
0,0 → 1,54 |
<script> |
dojo.require("dojo.parser"); |
dojo.require("dojox.dtl.Inline"); |
dojo.addOnLoad(function() { |
setTimeout(function(){ |
var inline = dijit.byId("inline"); |
inline.context.items.push("guava"); |
inline.render(); |
}, 1000); |
setTimeout(function(){ |
var inline = dijit.byId("inline"); |
inline.context = {items: ["lions", "tigers", "bears"]}; |
inline.render(); |
}, 2000); |
}); |
</script> |
<h2>test Dojo Toolkit - dijit.dtl.Inline</h2> |
<script type="text/html" dojoType="dojox.dtl.Inline" id="inline" context="{items: ['apple', 'banana', 'orange']}"> |
<ol> |
{% for item in items %} |
<li>{{ item }}</li> |
{% endfor %} |
</ol> |
</script> |
<br> |
<br> |
<h2>test Dojo Toolkit - dijit.dtl.ext-dojo.NodeList</h2> |
<div id="updateId"></div> |
<script> |
var Vars = { items: ["apple", "banana", "pear"] }; |
var Vars2 = { items: ["mela", "ciliegia", "cocco"] }; |
dojo.require("dojox.dtl.ext-dojo.NodeList"); |
dojo.addOnLoad(function() { |
dojo.query('#updateId').dtl("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div", Vars); |
setTimeout(function(){ |
dojo.query('#updateId').dtl("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div", Vars2); |
}, 1500); |
}); |
</script> |
<br> |
<br> |
<h2>test Dojo Toolkit - dijit.dtl.Context</h2> |
<div id="updateId2"></div> |
<script> |
dojo.require("dojox.dtl.Context"); |
var tpl = new dojox.dtl.Template("<div><ul>{% for item in items %}<li>{{ item }}</li>{% endfor %}</ul></div"); |
</script> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree_data.css |
---|
0,0 → 1,7 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
.dojoxUploaderFileListHeader { |
font-size: 8pt; |
} |
/tags/2.0/htdocs/test/dojo/test_dojo_tooltip.css |
---|
0,0 → 1,11 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
.dijitTooltipContainer { |
background: none repeat scroll 0 0 #fffafb; |
padding: 3px; |
border: 1px solid brown; |
color: blue; |
font-size: 11pt; |
} |
/tags/2.0/htdocs/test/dojo/test_dojo_Uploader_handler.mason |
---|
0,0 → 1,13 |
<%doc> |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
<%args> |
$upload => undef |
</%args> |
<%perl> |
$m->clear_buffer; |
$m->out('xxxxxxxxxxxxxxxxxxxxx'); |
</%perl> |
/tags/2.0/htdocs/test/dojo/test_dojo_UploaderMulti.html |
---|
0,0 → 1,33 |
<%doc> |
</%doc> |
<script> |
dojo.require("dojox.form.Uploader"); |
dojo.require("dojox.embed.Flash"); |
if(dojox.embed.Flash.available) { |
dojo.require("dojox.form.uploader.plugins.Flash"); |
}else{ |
dojo.require("dojox.form.uploader.plugins.IFrame"); |
} |
dojo.ready(function(){ |
var u = new dojox.form.Uploader({ |
label: "Select multiple files", |
multiple: true, |
uploadOnSelect: true, |
url: "test_dojo_UploaderMulti_handler.mason?upload=1" |
}, "uploader1"); |
var menu = dijit.byId(""); |
}); |
</script> |
<h1>Demo: dojox.form.Uploader</h1> |
<div id="uploader1"></div> |
<hr> |
<form method="post" action="test_dojo_UploaderMulti_handler.mason?upload=2" id="myForm" enctype="multipart/form-data" > |
<input name="uploadedfile" multiple="true" type="file" dojoType="dojox.form.Uploader" label="Select Some Files" id="uploader2" /> |
<input type="submit" label="Submit" dojoType="dijit.form.Button" /> |
</form> |
<hr> |
<textarea rows="10" cols="100"><% Dumper(\%ENV)%></textarea> |
/tags/2.0/htdocs/test/dojo/test_dojo_menu.css |
---|
0,0 → 1,0 |
/tags/2.0/htdocs/test/dojo/test_dojo_tooltip.html |
---|
0,0 → 1,23 |
% &LoadHeader('/test/dojo/test_dojo_tooltip.css'); |
<script> |
dojo.require("dijit.Tooltip"); |
dojo.addOnLoad(function() { |
new dijit.Tooltip({ |
connectId: ['test_input_tooltip1'], |
label: "Tooltip di <b>prova1!</b>" |
}); |
new dijit.Tooltip({ |
connectId: ['test_input_tooltip2'], |
label: "Tooltip di <b>prova2!</b>" |
}); |
}); |
</script> |
<h2>test Dojo Toolkit - dijit.Tooltip</h2> |
<input type="text" id="test_input_tooltip1"></input> |
<br> |
<input type="text" id="test_input_tooltip2"></input> |
/tags/2.0/htdocs/test/dojo/test_dojo_UploaderMulti_handler.mason |
---|
0,0 → 1,13 |
<%doc> |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
<%args> |
$upload => undef |
</%args> |
<%perl> |
$m->clear_buffer; |
$m->out('xxxxxxxxxxxxxxxxxxxxx'); |
</%perl> |
/tags/2.0/htdocs/test/dojo/test_dojo_tree.html |
---|
0,0 → 1,21 |
<html> |
<script> |
dojo.require("dojo.data.ItemFileReadStore"); |
dojo.require("dijit.Tree"); |
</script> |
<h2>test Dojo Toolkit - dijit.Tree</h2> |
<div dojoType="dojo.data.ItemFileReadStore" jsId="continentStore" url="/test/dojo/test_dojo_tree.json"></div> |
<div dojoType="dijit.tree.ForestStoreModel" jsId="continentModel" store="continentStore" |
query="{type:'continent'}" rootId="continentRoot" rootLabel="Continents" |
childrenAttrs="children"> |
</div> |
<div dojoType="dijit.Tree" id="mytree" model="continentModel" openOnClick="true"> |
<script type="dojo/method" event="onClick" args="item"> |
alert("BINGO! " + continentStore.getLabel(item) + ", population=" + continentStore.getValue(item, "population")); |
</script> |
</div> |
</html> |
/tags/2.0/htdocs/test/test_callRemote.html |
---|
0,0 → 1,8 |
<h1>Test callRemote</H1> |
<button onclick="Call();">call /test_callRemote.mql - test_callRemote</button> |
<script> |
function Call(){ |
var db = new DataBinding('Recordset', 'public/test_callRemote', 1); |
db.callRemote('test_callRemote', {par1: 'parametro uno', par2: 'parametro due'}, 'html', {title: 'Test call remote'}); |
} |
</script> |
/tags/2.0/htdocs/test/test_hReqMason.html |
---|
0,0 → 1,42 |
<H1>test:</H1> |
Valutazione libreria hReqMason_ClientMason.js |
<form name="my_form"> |
<input type="button" onClick="Go()" value="OK"> |
<script> |
//carico la tabella da visualizzare |
hReqMason_POST = false; |
start = 0; |
rows=1; |
function Go(){ |
hReqMason_ExecuteTimeout('<% $r->dir_config('DataBaseUrl') %>/logs.mql', 5000, TimeoutData, Load_Callback, 'remotesend.array',['start',start,'rows',rows,'name','test'], false); |
hReqMason_ExecuteTimeout('<% $r->dir_config('DataBaseUrl') %>/logs.mql', 5000, TimeoutData, Load_Callback2, 'remotesend.array',['start',start,'rows',rows,'name','test'], false); |
hReqMason_ExecuteTimeout('<% $r->dir_config('DataBaseUrl') %>/logs.mql', 5000, TimeoutData, Load_Callback3, 'remotesend.array',['start',start,'rows',rows,'name','test'], false); |
} |
function TimeoutData(contextID, type, str){ |
var contextObj = hReqMason_ContextPool[contextID]; |
alert('Timeout ricezione ' + contextID + ' URL='+contextObj.URL + ' type='+type + ' str='+str); |
} |
// richiamata al caricamento del form |
function Load_Callback(str, contextID){ |
var contextObj = hReqMason_ContextPool[contextID]; |
window.alert('Callback '+contextID+' URL='+contextObj.URL+' \n'+str); |
} |
// richiamata al caricamento del form |
function Load_Callback2(str, contextID){ |
var contextObj = hReqMason_ContextPool[contextID]; |
window.alert('Callback2 '+contextID+' URL='+contextObj.URL+' \n'+str); |
} |
// richiamata al caricamento del form |
function Load_Callback3(str, contextID){ |
var contextObj = hReqMason_ContextPool[contextID]; |
window.alert('Callback3 '+contextID+' URL='+contextObj.URL+' \n'+str); |
} |
</script> |
/tags/2.0/htdocs/test/test_htmlselect.html |
---|
0,0 → 1,47 |
<%args> |
</%args> |
<H1>test_htmlselect.html</H1> |
% my $editURL='/frame.html?from=siti&form=FORM'; |
Html select1: |
<& /input/htmlselect.comp, id =>'htmlSel1', |
description=>'Elenco impianti', |
value => 1, # group Admins |
buffer => 'htmlSel', |
remote => 1, |
empty => undef, |
width => '300', |
size => 5, |
source => $r->dir_config('DataBaseUrl').'/sel_gruppi.mql', |
edit => $editURL, |
empty => '-1', |
empty_descr => '-- No user --', |
editmessage => '*** Change users ***', |
editwindowparam => "height=380,width=550,location=no,menubar=no,toolbar=no,scrollbar=yes", |
onchange => q|alert('id='+this.get_value());|, |
widget => 'htmlselect' |
&> |
- <button onclick="Id_htmlSel1.Readonly(true);">Readonly</button> |
<button onclick="Id_htmlSel1.Readonly(false);">R/W</button> |
<hr> |
Html select2: |
<& /input/htmlselect.comp, id =>'htmlSel2', |
width => 140, |
popup_max_height => '80px', |
description=>'test componente htmlselect', |
empty => '', |
empty_descr => 'Nessuna selezione', |
cols => 1, |
readonly => 0, |
source => $r->dir_config('DataBaseUrl').'/autorizzazioni.mql', |
where => "nome != 'M%'", |
onchange => q|alert('BINGO\nchange htmlselect')| |
&> |
<script> |
var S1 = document.getElementById('htmlSel1'); |
var D1 = document.getElementById('display_htmlSel1'); |
var S2 = document.getElementById('htmlSel2'); |
var D2 = document.getElementById('display_htmlSel2'); |
</script> |
<%flags> |
inherit => '../autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_select.html |
---|
0,0 → 1,127 |
<%args> |
$edit => undef |
</%args> |
<H1>test_select.html</H1> |
% if($edit){ |
<script> |
var loaded = false; |
function OnFocus(){ |
if(loaded){ |
document.getElementById('edittest').focus(); |
debug('edit_focus'); |
loaded=false; |
} |
} |
window.onload=function(){ |
debug(null); |
document.body.style.backgroundColor='#aaaaff'; |
debug('load'); |
loaded=true; |
OnFocus(); |
} |
</script> |
<form name="formedit"> |
<input id="edittest" size=40 value=""> |
<br> |
<input type=button value="GO"> |
% }else{ |
<script> |
function OnFocus(){ |
} |
window.onload=function(){ |
debug(null); |
document.body.style.backgroundColor='#aaaaff'; |
debug('load'); |
loaded=true; |
} |
</script> |
% my $windowparam="height=380,width=550,location=no,menubar=no,toolbar=no,scrollbar=yes"; |
% my $editURL='/frame.html?from=gruppi&form=FORM'; |
<form name="menu"> |
Sel1:<br> |
<& /input/select.comp, id =>'Sel1', |
description=>'Elenco gruppi', |
buffer => 'Sel', |
#remote => 1, |
empty => undef, |
width => '300px', |
size => 5, |
style=>'width:400;', |
source=>$r->dir_config('DataBaseUrl').'/gruppi.mql', |
edit => $editURL, |
editmessage => '*** Modifica lista gruppi ***', |
editwindowparam => $windowparam &> |
<br> |
Sel2:<br> |
<& /input/select.comp, id =>'Sel2', |
description=>'Elenco gruppi', |
buffer => 'Sel', |
#remote => 1, |
empty=> undef, |
width => '300px', |
size => 5, |
style=>'background-color:#ffeeff; width:400;', |
source=>$r->dir_config('DataBaseUrl').'/gruppi.mql', |
edit => $editURL, |
editmessage => '*** Modifica lista gruppi ***', |
editwindowparam => $windowparam &> |
<br> |
SelS:<br> |
<& /input/select.comp, id =>'SelS', |
description=>'Elenco gruppi singola selezione', |
#remote => 1, |
buffer => 'Sel', |
empty=> '0', |
width => '300px', |
size => 1, |
style=>'background-color:#ffeffe; width:400;', |
source=>$r->dir_config('DataBaseUrl').'/gruppi.mql', |
edit => $editURL, |
editmessage => '*** Modifica lista gruppi ***', |
editwindowparam => $windowparam &> |
<br> |
<textarea id="buf" rows=1 cols=80>1738;1739;1740;1741;1742;1743</textarea> |
<br> |
<input type="button" value="get list" onClick="document.getElementById('buf').value=document.getElementById('Sel1').get_value()"> |
<br> |
<input type="button" value="set list" onClick="document.getElementById('Sel1').set_value(document.getElementById('buf').value)"> |
<br> |
<input type="button" value="disable body" onClick="document.body.disabled=true;"> |
<input type="button" value="disable form" onClick="document.menu.disabled=true;"> |
<input type="button" value="disable select" onClick="document.menu.Sel1.disabled=true;"> |
<input type="button" value="readonly select" onClick="document.menu.Sel1.Readonly(true);"> |
% } |
<br> |
<textarea id="debug" wrap rows=12 cols=12></textarea> |
</form> |
<hr> |
<p>Tessera: <%$Session{Login}%><br> |
Utente: <%$Session{Name}%></p> |
<script> |
var c=0; |
function debug(mess){ |
c++; |
var area = document.getElementById('debug'); |
if(mess){ |
area.value=area.value+mess+'['+c+'] '; |
}else{ |
area.value=''; |
c=0; |
} |
} |
window.onfocus=function(){ |
OnFocus(); |
document.body.style.backgroundColor='#ffaaff'; |
debug('focus'); |
} |
window.onblur=function(){ |
document.body.style.backgroundColor='#ffaaaa'; |
debug('blur'); |
} |
</script> |
<script> |
</script> |
<%flags> |
inherit => '../autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_select_where.html |
---|
0,0 → 1,13 |
<%args> |
$edit => undef |
</%args> |
% $Session{Auth_Admin}=1; |
<H1>test_select_where.html</H1> |
<& /input/select.comp, width=>'140', id =>'TEST', description=>'test', |
source => $r->dir_config('DataBaseUrl').'/metodi.mql', |
where => "tipo like 'P%'" |
&> |
<%flags> |
inherit => '/autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_subrequest.html |
---|
0,0 → 1,31 |
<%flags> |
inherit => undef |
</%flags> |
<html> |
<h2>test_variables.comp</h2> |
<hr> |
<% scall_component('/data/sel_gruppi.mql', F => 'selectoptions') %> |
<hr> |
</html> |
<%once> |
sub scall_component { |
my $comp = shift; |
my $content_type = $r->content_type; |
my $buffer; |
local %Session; |
local $Ver; |
local $DEBUG; |
local %Session; |
local $Ver; |
local %Global; |
local @Script_buffer; |
local %SQL; |
local $PLogger; |
local $JSLogger; |
my $req = $m->make_subrequest( comp => $comp, args => \@_, out_method => \$buffer ); |
$req->exec; |
$r->content_type($content_type); |
return $buffer; |
} |
</%once> |
/tags/2.0/htdocs/test/test_bug_array_params.html |
---|
0,0 → 1,47 |
<%doc> |
Call .../test/test_bug_array_params.html?Arr=uno&Arr=due&Arr=tre |
Using Perl 5.22 on Ubuntu 16.04+Apache2.4+mod_perl it print: |
@Array = [ 'ARRAY(0x7fadc00093e0)' ] |
%ARGS = { 'Arr' => 'ARRAY(0x7fadc00093e0)' } |
Using old perl releases: |
@Array = [ 'uno', 'due', 'tre' ] |
%ARGS = { 'Arr' => [ 'uno', 'due', 'tre' ] } |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
<%args> |
@Arr |
</%args> |
<%once> |
use Data::Dumper; |
</%once> |
<%perl> |
my @Arr2 = $r->param('Arr'); |
my $arr2 = $r->param; |
print STDERR 'From main:', Dumper($r); |
my %args; |
foreach my $key ( $r->param ) { |
my @values = $r->param($key); |
$args{$key} = @values == 1 ? $values[0] : \@values; |
} |
my $decl = $m->current_comp->declared_args; |
print STDERR "CALL \$m->request_args:", Dumper($m->{request_args}); |
my $request_args = $m->request_args; |
</%perl> |
| @Array = <% join(' | ', @Arr) %><br> |
@Array = <% Dumper(@Arr) %><br> |
| %ARGS = <% join(' | ', %ARGS) %><br> |
%ARGS = <% Dumper(\%ARGS) %><br> |
$r->param('Arr') = <% Dumper(\@Arr2) %><br> |
$r->param = <% Dumper($arr2) %><br> |
%args = <% Dumper(\%args) %><br> |
$m->current_comp->declared_args = <% Dumper($decl) %><br> |
$m->current_comp->request_args = <% Dumper($request_args) %><br> |
/tags/2.0/htdocs/test/test_divselect.html |
---|
0,0 → 1,86 |
<%args> |
$edit => undef |
</%args> |
<%perl> |
&LoadHeader( |
'/input/input.comp', '/input/divselect.comp', '/input/number.comp', |
'/input/select.comp', '/input/string.comp', '/input/htmlselect.comp', |
'/input/codfisc_pi.comp', '/input/checkbox.comp' |
); |
</%perl> |
<H1>test_divselect.html</H1> |
<H3>divselect.comp from anagrafiche</h3> |
<& /input/divselect.comp, |
width => '220', |
id =>'div_id1', |
value => 1, |
description => 'test componente divselect', |
buttons => [ MyFunc => q{alert("Bingo!")}, |
'Func 2' => q{alert("Bingo 2!")}, |
'Test RescaleDisplay' => q{Input_DivSelect_Popup.rescaleDisplay()} |
], # bottoni supplementari |
empty => '', |
empty_descr => 'Nessuna sel.', |
insert_descr => 'Nuovo utente', |
insert_parameters => [ 'form' => 'FORM' ], |
disp_template => q|P[0]+' '+P[1]+(P[2] ? ' ('+P[2]+')' : '')|, # P== array dei parametri del widget; viene eseguita una "eval" |
rows => 20, |
cols => [100, 120, 150], |
readonly => 0, |
from => 'anagrafiche', |
XXXwhere => q|cognome ~* '^[a-m]'|, |
orderby => 'lower(cognome), lower(nome)', |
query_param => 'parametro supplementale', # parametro opzionale che viene inviato al server |
XXXonchange => q|alert('BINGO\nchange divselect')| |
&> |
- <button onclick="Id_div_id1.Readonly(true);">Readonly</button> |
<button onclick="Id_div_id1.Readonly(false);">R/W</button> |
<hr> |
<H3>divselect.comp from anagrafiche con dettaglio su anagrafiche</h3> |
<& /input/divselect.comp, |
width => '140', |
id =>'div_id2', |
description => 'test anagrafiche', |
buttons => [ MyFunc => q{alert("Bingo!")}, |
'Func 2' => q{alert("Bingo 2!")} |
], # bottoni supplementari |
empty => '', |
empty_descr => 'Nessuna sel.', |
insert_descr => 'Nuovo utente', |
insert_parameters => [ 'form' => 'FORM' ], |
disp_template => q{P[0]+' '+P[1]}, # P== array dei parametri del widget; viene eseguita una "eval" |
rows => 20, |
cols => [100, 120, 150], |
readonly => 0, |
from => 'anagrafiche', |
Detail_from => 'anagrafiche', |
Detail_width => 800, |
Detail_height => 600, |
XXXwhere => q|cognome ~* '^[a-m]'|, |
orderby => 'lower(cognome), lower(nome)', |
query_param => 'parametro supplementale', # parametro opzionale che viene inviato al server |
onchange => q|alert('BINGO\nchange divselect')| |
&> |
<H3>divselect.comp from anagrafiche con dettaglio su anagrafiche</h3> |
<& /input/divselect.comp, |
width => '140', |
id =>'div_id3', |
description => 'test anagrafiche', |
empty => '', |
empty_descr => 'Nessuna sel.', |
insert_descr => 'Nuova funzione', |
insert_parameters => [ 'form' => 'FORM' ], |
disp_template => q{P[0]+' '+P[1]}, # P== array dei parametri del widget; viene eseguita una "eval" |
rows => 20, |
cols => [100, 100, 100], |
readonly => 0, |
from => 'anagrafiche', |
Detail_from => 'anagrafiche', |
Detail_width => 880, |
Detail_height => 660 |
&> |
<%flags> |
inherit => '../autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_hello.html |
---|
0,0 → 1,6 |
<html> |
<h2>test hello.comp</h2> |
<& /input/hello.comp, id => 'test1', value => 'Dipen' &> |
<br> |
</html> |
/tags/2.0/htdocs/test/test_utf8.html |
---|
0,0 → 1,4 |
<%flags> |
inherit => undef |
</%flags> |
Testo utf: àèéìòù € |
/tags/2.0/htdocs/test/test_span.html |
---|
0,0 → 1,18 |
<%args> |
$edit => undef |
</%args> |
<H1>test_span.html</H1> |
<br> |
<& /input/span.comp, id =>'Span1', description=>'Test oggetto span', |
bgcolor => 'red', width => 300, |
style => '|color:yellow; width:400px;', value => 'BINGO</SPAN>' &> |
<br> |
<script> |
function InitAll(){ |
var obj = document.getElementById('Span1'); |
obj.set_value('BENE, FUNZIONA!!!'); |
} |
window.setTimeout(InitAll,1); |
</script> |
/tags/2.0/htdocs/test/test_UpiPrinterServer.html |
---|
0,0 → 1,67 |
<!DOCTYPE html "-//W3C//DTD HTML 4.01 Transitional//EN"> |
<html> |
<%args> |
$Area_testo => "Esempio\nriga 2\nriga 3\nultima riga (€è[ò\@ò#°)"; |
</%args> |
<head> |
<title>test_UpiPrinterServer.html</title> |
</head> |
<body> |
<H1>test_UpiPrinterServer.html</H1> |
<hr> |
Testo da inviare alla stampante:<br> |
<form method="POST" action="/test/test_UpiPrinterServer.html" > |
<input type="submit" value="Stampa" > |
<br> |
<textarea name="Area_testo" rows="5" cols="80"><% $Area_testo |h%></textarea> |
<br> |
Risposta dal server:<br> |
<textarea id="Result"rows="2" cols="80"></textarea> |
</form> |
<script> |
// Se definita la funzione UpiPrinterServerHandler viene richiamata per fornire |
// il risultato della stampa. |
// Elenco dei possibili codici di stato ritornati: |
// printed | File <file< printed to <printer_name> |
// print_err_1 | Print to <printer_name> with error -1: Memory allocation error |
// print_err_2 | Print to <printer_name> with error -1: Error opening the file |
// print_err_3 | Print to <printer_name> with error -1: Error opening the printer |
// print_err_4 | Print to <printer_name> with error -1: Error startint the print job |
// print_err_5 | Print to <printer_name> with error -1: Error writing to printer |
// print_err_6 | Print to <printer_name> with error -1: Error ending the print job |
// print_err_7 | Print to <printer_name> with error -1: Error closing printer |
// remote_err_XXX | Remote server error: ...................... |
// no_print_default | No default printer is selected |
// |
function UpiPrinterServerHandler(result, comment){ |
document.getElementById('Result').value = result + ': ' + comment; |
alert(result + ': ' + comment) |
} |
</script> |
<%perl> |
if($r->method eq 'POST'){ |
# preparo il file |
my($fh, $filename) = tempfile( |
DIR => $r->dir_config('TmpDir'), |
SUFFIX => '.prn', |
UNLINK => 0 |
); |
my $file = $filename; |
$file =~ s|^.*/||; # tolgo la dir |
$file =~ s|\.prn$||; # tolgo .prn |
print $fh $Area_testo; |
close $fh; |
</%perl> |
<script src="https://localhost:22000/from_server/<% "$ENV{HTTP_HOST}/$file"%>"></script> |
% } |
<br> |
Configurazione della stampante:<br> |
<iframe src="https://localhost:22000/" width="650" height="320" frameborder="0"></iframe> |
</body> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
<%once> |
use File::Temp qw(tempfile); |
</%once> |
/tags/2.0/htdocs/test/test_keyevents.html |
---|
0,0 → 1,72 |
<html> |
<h2>test tabs e arrows key events to move up,down, left, right</h2> |
<input id="A1" type="text" value="A1" tabindex="-1"> |
<input id="A2" type="text" value="A2" tabindex="-1"> |
<input id="A3" type="text" value="A3" tabindex="-1"><br> |
<input id="B1" type="text" value="B1" tabindex="-1"> |
<input id="B2" type="text" value="B2" tabindex="-1"> |
<input id="B3" type="text" value="B3" tabindex="-1"><br> |
<input id="C1" type="text" value="C1" tabindex="-1"> |
<input id="C2" type="text" value="C2" tabindex="-1"> |
<input id="C3" type="text" value="C3" tabindex="-1"> |
<script> |
var positions = [ |
[ document.getElementById('A1'), document.getElementById('A2'), document.getElementById('A3') ], |
[ document.getElementById('B1'), document.getElementById('B2'), document.getElementById('B3') ], |
[ document.getElementById('C1'), document.getElementById('C2'), document.getElementById('C3') ] |
]; |
for(var R=0; R<positions.length;R++){ |
var row = positions[R]; |
for(var C=0; C<positions.length;C++){ |
row[C].Row = R; |
row[C].Col = C; |
} |
} |
dojo.query('input').connect('keypress', function(event){ |
// alert(this.id +': ' + event.keyCode + ' R:' + this.Row + ' C:' + this.Col); |
}); |
dojo.query('input').connect('keydown', function(event){ |
//alert(this.id +': ' + event.keyCode + ' R:' + this.Row + ' C:' + this.Col); |
var widget; |
if((event.keyCode == 9 && !event.shiftKey)){ |
// TAB |
widget = this.Col == positions[0].length - 1 ? (this.Row == positions.length - 1 ? positions[0][0] : positions[this.Row + 1][0]) : positions[this.Row][this.Col + 1]; |
}else if(event.keyCode == 9 && event.shiftKey){ |
// Shift-TAB |
widget = this.Col == 0 ? (this.Row == 0 ? positions[positions.length - 1][positions[0].length -1] : positions[this.Row - 1][positions[0].length -1]) : widget = positions[this.Row][this.Col - 1]; |
}else if(event.keyCode == 38){ // Up arrow |
// key UP |
widget = this.Row == 0 ? (this.Col == 0 ? positions[positions.length - 1][positions[0].length -1] : positions[positions.length - 1][this.Col - 1]) : positions[this.Row - 1][this.Col]; |
}else if(event.keyCode == 13 || event.keyCode == 40){ // CR o Down arrow |
widget = this.Row == positions.length - 1 ? (this.Col == positions[0].length -1 ? positions[0][0] : positions[0][this.Col + 1]) : positions[this.Row + 1][this.Col]; |
}else if(event.keyCode == 37){ // Left arrow |
// salto solo se sono con il caret all'inizio |
if(this.selectionStart == 0){ |
widget = this.Col == 0 ? (this.Row == 0 ? positions[positions.length - 1][positions[0].length -1] : positions[this.Row - 1][positions[0].length -1]) : widget = positions[this.Row][this.Col - 1]; |
}else{ |
return true; |
} |
}else if(event.keyCode == 39){ // Right arrow |
// salto solo se sono con il caret alla fine |
if(this.selectionStart == this.value.length){ |
widget = this.Col == positions[0].length - 1 ? (this.Row == positions.length - 1 ? positions[0][0] : positions[this.Row + 1][0]) : positions[this.Row][this.Col + 1]; |
}else{ |
return true; |
} |
}else{ |
return true; |
} |
widget.focus(); |
widget.setSelectionRange(0, widget.value.length); |
return false; |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/test_select_div.html |
---|
0,0 → 1,149 |
<%args> |
$edit => undef |
</%args> |
<H1>test_select_div.html</H1> |
<%flags> |
inherit => undef #'/autohandler' |
</%flags> |
<h2>Prove cursore con DIV</h2> |
% # campi da visualizzare |
% my $num_fields = 2; |
% # record da visualizzare |
% my $num_records = 8; |
% # numero dei record del recordset |
% my $max_records = 200; |
<div id="divtest" style="margin: 0px; background-color: #cccccc;"> |
<div id="divtest1" style="float:left; height:100; margin:0px; border-style: none; overflow: auto; background-color: #f0f2bf;"> |
<span id="info">. . .</span> |
<table border="1" id="table"> |
% for(my $r=0;$r<$num_records;$r++){ |
<tr onclick="selectRow(<%$r%>)"> |
% for(my $c=0;$c<$num_fields;$c++){ |
<td style="width:75px" align="center">...</td> |
% } |
</tr> |
% } |
</table> |
</div> |
<div id="divtest2" style="background-color: #cccccc; margin: 0px; border-style: none; overflow:auto; width:20px;"> |
<div id="divtest3" style="margin: 0px; border-style: none; width:1; height:1000px;"> |
</div> |
</div> |
</div> |
<hr> |
<textarea id="dmess" rows="11" cols="80"></textarea> |
<script> |
var info = document.getElementById('info'); |
var table = document.getElementById('table'); |
var divtest = document.getElementById('divtest'); |
var divtest1 = document.getElementById('divtest1'); |
var divtest2 = document.getElementById('divtest2'); |
var divtest3 = document.getElementById('divtest3'); |
var dmess = document.getElementById('dmess'); |
// dimensiono l'altezza per contenere tutta la tabella |
divtest1.style.height = divtest1.scrollHeight; |
divtest2.style.height = divtest1.scrollHeight; |
divtest.style.height = divtest1.scrollHeight;; |
divtest1.style.width = divtest1.scrollWidth; |
// set larghezza del contenitore, che adatta perfettamente all'occupazione in larghezza dell'oggetto |
// contenuto comprensiva dello spazio occupato dal cursore |
divtest.style.width = divtest1.offsetWidth+divtest2.offsetWidth; |
// calcolo dimensioni documento cursore proporzionali al n° di record |
divtest3.style.height = <%$max_records%> * divtest2.offsetHeight / <%$num_records%>; |
// posizione del recordset |
var start = 0; |
var old_start = 0; |
// ritardo in msec con cui aggiornare il recordset se si muove il cursore |
var delayUpdate = 1000; |
// timer per gestire il ritardo con cui si aggiorna il recordset |
var delayUpdateTimer; |
// evento scroll del cursore |
divtest2.onscroll = function(){ |
// calcolo la nuova posizione del recordset |
start = Math.ceil(this.scrollTop * <%$max_records%> / this.scrollHeight); |
// aggiorna report delle dimensioni |
ViewDimensions(); |
var delay; |
if(Math.abs(old_start-start) < <%$num_records%> -1){ |
// spostamento cursore lento applico un ritardo lungo se già non è stato attivato... |
delay = delayUpdate; |
// predispongo campi vuoti |
emptyRecordset(); |
}else{ |
// spostamento cursore veloce o a pagina; applico ritardo corto |
delay = delayUpdate / 5; |
// cancellando l`eventuale timer attivo |
if(delayUpdateTimer){ |
window.clearTimeout(delayUpdateTimer); |
delayUpdateTimer = null; |
} |
} |
if(!delayUpdateTimer){ |
delayUpdateTimer = window.setTimeout(changeRecordset, delay); |
} |
info.innerHTML = start + '-' + (start+<%$num_records-1%>) + '(' + <%$max_records%> + ')'; |
old_start = start; |
} |
// var usata per evitare continui aggiornamenti con i campi vuoti (lampeggio) |
var isEmpty; |
function emptyRecordset(){ |
if(!isEmpty){ |
var rows = table.getElementsByTagName('tr'); |
for(var row=0; row<rows.length; row++){ |
var cols = rows[row].getElementsByTagName('td'); |
for(var col=0; col<cols.length; col++){ |
cols[col].innerHTML = '...'; |
} |
} |
} |
isEmpty = true; |
} |
// aggiorna il recordset visualizzato; simulato con il cambio dati nelle celle pari a RxCy |
// dove x è in numero di riga e y è il numero di colonna |
function changeRecordset(){ |
delayUpdateTimer = null; |
var rows = table.getElementsByTagName('tr'); |
for(var row=0; row<rows.length; row++){ |
var cols = rows[row].getElementsByTagName('td'); |
for(var col=0; col<cols.length; col++){ |
cols[col].innerHTML = 'R'+(start+row)+'C'+col; |
} |
} |
isEmpty = false; |
} |
// stringa contenente le dimensioni degli oggetti in gioco |
// mostrata nel campo textarea |
function ViewDimensions(){ |
var mess = 'Dimensioni:\n'; |
mess += dim2str(divtest); |
mess += dim2str(divtest1); |
mess += dim2str(divtest2); |
mess += dim2str(divtest3); |
mess += dim2str(table); |
dmess.value = mess; |
} |
function selectRow(num_row){ |
var value = table.getElementsByTagName('tr')[num_row].getElementsByTagName('td')[0].innerHTML; |
alert('Selezionata riga '+num_row+'\ndi contenuto 1° colonna:' + value); |
} |
// stringa contenente le dimensioni dell'oggetto obj |
function dim2str(obj){ |
return obj.id + ': start='+start+' offsetWidth='+obj.offsetWidth+' clientWidth='+obj.clientWidth+' scrollWidth='+obj.scrollWidth+'\n' + |
' offsetHeight='+obj.offsetHeight+' clientHeight='+obj.clientHeight+' scrollHeight='+obj.scrollHeight+ |
' scrollTop='+obj.scrollTop+'\n'; |
} |
// condizioni iniziali |
divtest2.onscroll(); |
</script> |
/tags/2.0/htdocs/test/test_width_divselect_span.html |
---|
0,0 → 1,30 |
<html> |
<head> |
<title> |
test_width_divselect_comp.html |
</title> |
<link rel="stylesheet" href="/css/main.css?Ver=<%$Ver%>" type="text/css"> |
<link rel="stylesheet" href="/css/divselectpopup.css?Ver=<%$Ver%>" type="text/css"> |
<style> |
</style> |
</head> |
<body> |
<h1> |
test_width_divselect_comp.html |
</h1> |
<hr> |
<div id="DivSelect_Container" class="DivSelect_Container"> |
<div id="DivSelect_TableContainer" class="DivSelect_TableContainer"> |
<span class="INPUTSPAN" style="width:100;"> |
Super califragi listiche spiralidoso. |
</span> |
<span class="INPUTSPAN" style="width:200;"> |
SUPER PIPPO SUPER PIPPO SUPER PIPPO SUPER PIPPO SUPER PIPPO. |
</span> |
</div> |
</div> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_width_divselect_table.html |
---|
0,0 → 1,44 |
<html> |
<head> |
<title> |
test_width_divselect_comp.html |
</title> |
<link rel="stylesheet" href="/css/divselectpopup.css?Ver=<%$Ver%>" type="text/css"> |
</style> |
</head> |
<body> |
<h1> |
test_width_divselect_comp.html |
</h1> |
<hr> |
<div id="DivSelect_Container" class="DivSelect_Container"> |
<div id="DivSelect_TableContainer" class="DivSelect_TableContainer"> |
<table class="DivSelect_Table" style="table-layout:fixed; width:0;"> |
<thead> |
<tr class="DivSelect" style="max-width:300;"> |
<td class="DivSelect_Head" style="width:100;" > |
Colonna 1 |
</td> |
<td class="DivSelect_Head" style="width:200;" > |
Colonna 2 |
</td> |
</tr> |
</thead> |
<tbody> |
<tr class="DivSelect_Dispari"> |
<td class="DivSelect_Column"> |
Super califragi listiche spiralidoso. |
</td> |
<td class="DivSelect_Column"> |
SUPER PIPPO SUPER PIPPO SUPER PIPPO SUPER PIPPO SUPER PIPPO. |
</td> |
</tr> |
</tbody> |
</table> |
</div> |
</div> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_Files.html |
---|
0,0 → 1,52 |
<%args> |
$edit => undef |
$value => '31173' |
$value2 => '31175' |
</%args> |
<H1>test_Files.html</H1> |
<H3>Files.comp</h3> |
<table> |
<tr> |
<td> |
<& /input/Files.comp, |
id => 'IdWidgetFilesTest1', |
from => 'impianti/apparecchiature', |
value => $value, |
width => 400, |
height => 300, |
&> |
</td> |
<td> |
<& /input/Files.comp, |
id => 'IdWidgetFilesTest2', |
from => 'impianti/apparecchiature', |
value => $value2, |
width => 400, |
height => 300, |
&> |
</td> |
</tr> |
<tr> |
<td> |
<input id="IdWidgetFilesTest1_id" value="<%$value%>"/> |
</td> |
<td> |
<input id="IdWidgetFilesTest2_id" value="<%$value2%>"/> |
</td> |
</tr> |
</table> |
<script> |
dojo.ready(function(){ |
dojo.connect(dojo.byId('IdWidgetFilesTest1_id'), 'onchange', function(){ |
dojo.byId('IdWidgetFilesTest1').set_value(this.value); |
}); |
dojo.connect(dojo.byId('IdWidgetFilesTest2_id'), 'onchange', function(){ |
dojo.byId('IdWidgetFilesTest2').set_value(this.value); |
}); |
}); |
</script> |
<%flags> |
inherit => '/autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_width.html |
---|
0,0 → 1,85 |
<style> |
.testwidthdiv |
{ |
width: 100px; |
border: thin #000000 solid; |
white-space: nowrap; |
overflow:hidden; |
display: -moz-inline-box; |
} |
.testwidthspan |
{ |
width: 100px; |
border: thin #FF4400 solid; |
white-space: nowrap; |
overflow:hidden; |
display:block; |
display: -moz-inline-box; |
} |
</style> |
<body> |
<h1> |
test_width.html |
</h1> |
Test con overflow in div: |
<br/> |
<br/> |
<div class="testwidthdiv"> |
supercalifragilistichespiralidoso supercalifragilistichespiralidoso |
</div> |
<span class="dijitInline dijitIcon masonSqlIcons find vAlign"></span> |
</br> |
</br> |
Test con overflow in span: |
<br/> |
<br/> |
<span class="testwidthspan"> |
supercalifragilistichespiralidoso supercalifragilistichespiralidoso |
</span> |
<span class="dijitInline dijitIcon masonSqlIcons find vAlign"></span> |
<br/> |
<br/> |
Test senza overflow in div: |
<br/> |
<br/> |
<div class="testwidthdiv"> |
</div> |
<span class="dijitInline dijitIcon masonSqlIcons find vAlign"></span> |
<br/> |
<br/> |
Test senza overflow in span: |
<br/> |
<br/> |
<span class="testwidthspan"> </span> |
<span class="dijitInline dijitIcon masonSqlIcons find vAlign"></span> |
</body> |
<script> |
function getElementsByClass(searchClass,node,tag) { |
var classElements = new Array(); |
if ( node == null ) |
node = document; |
if ( tag == null ) |
tag = '*'; |
var els = node.getElementsByTagName(tag); |
var elsLen = els.length; |
var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); |
for (i = 0, j = 0; i < elsLen; i++) { |
if ( pattern.test(els[i].className) ) { |
classElements[j] = els[i]; |
j++; |
} |
} |
return classElements; |
} |
var isIE = /MSIE/; |
if (isIE.test(window.navigator.userAgent)) |
{ |
var divs = getElementsByClass("testwidthdiv", null, "div"); |
var divLen = divs.length; |
for (var i = 0; i < divLen; i++) |
{ |
divs[i].style.display = "inline"; |
} |
} |
</script> |
/tags/2.0/htdocs/test/test_upload.html |
---|
0,0 → 1,62 |
<html> |
<%args> |
$upload => 0 |
</%args> |
<%init> |
use Apache2::Upload; |
</%init> |
<h2>test Upload file</h2> |
<br> |
<FORM ACTION="/test/test_upload.html?upload=1" XXXtarget="_blank" name="upl_sens_area" |
METHOD="POST" ENCTYPE="multipart/form-data"> |
<input type="file" name="file1" lenght=25><br> |
<input type="file" name="file2" lenght=25><br> |
<input type="file" name="file3" lenght=25><br> |
<INPUT TYPE="SUBMIT" VALUE="Load all files"> |
</FORM> |
%# $m->out('Oggetto $r => ',Dumper($r)); |
% if($upload == 1){ |
% if($r->dir_config('MasonArgsMethod') eq 'CGI'){ |
% my $query = $m->cgi_object(); |
% foreach my $name qw(file1 file2 file3){ |
<hr> |
% my $fh = $query->param($name); |
% if($fh){ |
% my $type = $query->uploadInfo($fh)->{'Content-Type'}; |
% my $tempname = $query->tmpFileName($fh); |
% my $disposition = $query->uploadInfo($fh)->{'Content-Disposition'}; |
Upload <b>type:</b><%$type%> <b>file_name:</b><%$tempname%> <b>disposition:</b><%$disposition%>: |
<pre> |
% while (<$fh>) { |
% $m->out($_); |
% } |
% close($fh); |
% } |
</pre> |
% } |
<hr>end. |
<%perl> |
}else{ |
my @upload = $r->upload; |
foreach my $upload (@upload){ |
$upload = $r->upload($upload); |
$m->out('<hr>'); |
my $size = $upload->size; |
my $type = $upload->type; |
my $name = $upload->name; |
my $tempname = $upload->tempname; |
my $filename = $upload->filename; |
my $fh = $upload->fh; |
</%perl> |
Upload: <b>file:</b><%$filename%></b> <b>tempname:</b><%$tempname%> <b>name:</b><%$name%> <b>type:</b><%$type%> <b>size:</b><%$size%>: |
<pre> |
% while (<$fh>) { |
% $m->out($_); |
% } |
% close($fh); |
</pre> |
% } |
% } |
<hr>end. |
% } |
</html> |
/tags/2.0/htdocs/test/test_color.html |
---|
0,0 → 1,43 |
<h2>test color.comp</h2> |
<br> |
Color: <& /input/color.comp, |
id => 'TestColor', |
value => '12/12/2005', |
onchange => 'console.log("New color: "+this.get_value());', |
description => 'Test input color', |
convert_to_hex => 0, |
readonly => 0 |
&> |
|
<button onclick="Id_TestColor.Readonly(true); document.getElementById('button_sv').disabled = true;">Readonly</button> |
|
<button onclick="Id_TestColor.Readonly(false); document.getElementById('button_sv').disabled = false;">R/W</button> |
<br><br> |
|
<& /input/string.comp, |
id => 'ColorVal', |
description => 'Input ColorVal', |
rows => 1, |
cols => 30, |
length => 30, |
readonly => 0 |
&> |
<br><br> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get Value', |
readonly => 0, |
onclick => "var color = document.getElementById('TestColor'); document.getElementById('ColorVal').set_value(color.get_value());" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set Value', |
readonly => 1, |
onclick => "var color_val = document.getElementById('ColorVal'); document.getElementById('TestColor').set_value(color_val.get_value());" |
&> |
/tags/2.0/htdocs/test/test_document.html |
---|
0,0 → 1,339 |
<h2>Test: document.comp</h2> |
|
<& /input/document.comp, |
id => 'test_document', |
description => 'Descrizione pulsante', |
readonly => '', |
name => 'gruppi.odt', |
value => q{data:application/vnd.oasis.opendocument.text;base64,UEsDBBQAAAgAABSQd0lexjIMJwAAACcAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92 |
bmQub2FzaXMub3BlbmRvY3VtZW50LnRleHRQSwMEFAAACAAAFJB3SUJn8sGrDgAAqw4A |
ABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1JSERSAAAAxgAA |
AQAIAwAAAN+D+XIAAAMAUExURRgZIR4nMCMtOC0yPDAtOz41LjExNDE1Pzw1NDs2ODg7 |
PCc2Rys8UDY9SDBCVjpMYD9RZkM0JUI9OkhAO1VDOkRDQ0hER0pKSkRKVUVQXUxQU05U |
XFZIQFFMVVFRT19RSFhZWEdXZ0xeclNVYFZcZFpeZV1hWk1md1dhZFdlb1tiZF1kalxn |
dGBRQWZaQWVYTGFbVmBdW2dkXXVgTnZnWGloaWRrcmJuempscmpvemtwbmlzd3NrZXhz |
a3l4eFtrgVtxiWZ0hWV2iGt2gmx4hmR6k3l9hX+EfW+Cj26EmXuCiHiGln2Sn3aJon+S |
ooJtWIdyXYp4ZoN6dZJ9aZJ/fIF9gYaBepSAa5WDdJWIfJqLe4aHiISLkIaKmouOko6O |
m46QioqSmJOLh5KLkpeRipeXl4eZo4OZq4+WpIqZpIubrIuesZedpJCfsJugno6irYmj |
s5yjqZWjspemuJaqvpmjs52ptZ2tvqaTiqOYj6uVgq2chaqcj6Gbl7CYhq2hjKijmrWj |
jbaomKOjoqKkqqeopqSqq6umoKinqayqpKurq6OrsqKtuaqts62wrauyuLKmpbOrpLCu |
q7iuprGusLaxq7e2tpqswpy0xqW2xqa5xaS6yq61way6xaq6yaG10bS7w7O8y7y+wbi/ |
yLG90L3BvavD1b3Bw7vCyr/IzrXD0rXC2LHM3LvG07rH2b3J1b3L3L3M5MOrmcuxnMa1 |
qMO6s8K9usq8stK9qdS+scC/wcjCu9XGrdPCsdHFu9TMvtrHuN/NtNzKut7QvuDOv+XS |
usbGxsbM1MXR28zR08vT29PMw9HNytjPw9jOyNjSytbX18DN4MrW5Nbd5N7g3svk9NPi |
693h49vk69zo79jn9N7x++TXyOPc1uDd4Ozhz+ni2/HizPPl0fDm2vPq2/vu1/rv2/jw |
3ufn5+Xs8+/w7+Xw9OLz++zx9ez0+ev6/vDn4PLr4/Lu6ffy5vTx6/ry4vrz6v347fHx |
8fL2+fX6/Pn28/z69f7+/gAAAP///6RRzxwAAAtmSURBVHja7doNdFPVHQBwdeLc1Pk1 |
T51nQxScZzjOhNEiHTzcqNWlMKXSOEiFNvZN5JTOqhOcyxbaSsMrObGF3OmZzhB5tmXD |
uY4EZgQdh7027Su5tLGtpWmj68HkHV9NsjZLXnLP2U3aQlsKtlvBwvnfNO+8j3vvez/u |
ve9+hMvIJREuAwYwgAEMYAADGMAABjCAAQxgAONSYETO2LnQ4ciz/3o8Fo1H6BNEIjbO |
Ulla8fLEGfNSUu5pIUc3Jg+a5A82JXfiwqkIzfNvue11cuTrKSmzG8kPPiNk7d6Br6Wk |
zOkIXp2ScldHePYUMf6eUb7+hfvyis3cr3IKECtsIDqtMlFG/OoT5PBVHcHGmAP5g9/e |
6G10+ZCTlNzaGrFbEiXjvaqBeFL8B+4m5L1vkBsp45FX/n0NISV39l5LyNa7w1dOFaM0 |
64XcbMvqIqG4UG/CuXnOPC2OTpQxgz7YY08evP/RDN3s4Ixn6h5YdUfRjJYXr8cPZ625 |
k0b4dVYy3nuU8ck15MYTCcanlPHP63vp9h83TBkjFpGlbq8bExyRQxEs9WtrAk55opVq |
Bn2wF1ceXPboonqF3N76twdWbSaPvPHeMuIpLbiCFupjT5Ou9PS/HLxiafpNm4cZlzHM |
Ta/20u3NfwxeOR2aeLI0Hn7u4DKClnxLmddGGW8kGf+52iR+hTK23k/68aqnD96A624g |
5MZOQhb+4dPLsVMivVdgl5+EpwmjTdJfJx9cpm0N3vzRvHeGGXf2flWuu7yPkPCM5/3H |
bn8lUal++Bx59Cf+Q1f5E22DkN7kNnylMh1euEvvnanyk6ObmlNTd5CdqbZnShrI1oZw |
6o7fpO1Ys5lGCGTPSrMQ1y/ocy8isYJ701rIQEYi5UBmkpEB3R8wgHHeg9dJCH1jhGR3 |
P8btgXaPfFEyhKaiIq4s2tOCRNHKCVZ960XJaOIRDVFPDXIiB99ucrRC2wAGMIBBIr7p |
HSITY0jT7LG7R/9NguGeRp8zUBNkECVGomS6fCNjPpNv4muZ3JmpaOP+9DRm5pLdS5c0 |
0ImGFA35RsyVpREH7ws74mwxCRiDfb6YT/IIHULEF5AD0R5TxdlvYnY0BFgTkWQfbZO0 |
IkTpxk6zLbe1TM2bKpzm0s5esm1F3ayMBbdlq5/sWYyDKx7sZzR9iOVZjmXtxZHcB0/H |
X1P5VtemNX6GuVc1f3uWulCVodGsWsbM3xhTac6+0sWsPbF1by5hSlRMevp3Uu/TzEnL |
XsyoP6szbZyiF+6SvJkZS8W7FjK/l+b6vKnZz3YcLVSFmSWvarcsVv9Yk6teTpi8jlPR |
f8dvjutYi75Yb9fVshzWVJjMhSazrnEgP/fsN8l78cMgu626EulsJtMTJmQtNNp2lRaS |
F/hXpogR90XkmCz5IgqR6EjZH4sM5OcpIX9IjsTopUjEH2RHPKAX146fTwCLZ7+Jy43H |
HxG6/FO3+BmnH4V+ovQbH2z/yTNESYQEdZT79GGcDEVIJjnHCkMsmdtQJJpiKJlCL0xR |
9zfUgQToJ/E3GIKDp3y+UOD0yeHgH7EfSMT44uAfzHEw58BwssDovP6X7u8SGYzUbWQR |
5lA7ks+ZMr4LtSLRZBWHaozDiUr2oSbuNTPehZHsEuwCb6+gZ3mrWE+8lqZa5LS12jTr |
nVZCmi1GtxFX89r1IrJ4auzVWqE2jlwbqkQTwrvcJmLHDm0nzdVmK9wlmiwuhC2TZJSo |
ZuUvzcxk7tl7TsZAjip7Tip77erPB4+16rmpzCK2iMlf+vjCe/YUzFUtzWRyVIwqR6v5 |
ESmwqFOzVqlsc6/TsHP7yCHNek36gocyVz+UQ++UqdKoGWaAMTEL52TmaLSL53eqixfc |
cpy2Q3Uus+B7mTmZ2uXf/WxyDK9f4N0YY/7cpUFoFDvufhcNlwbmnT7eLrQmEvOyWK3O |
XJ2JBTduxA5B6bU2VWPs6BBqsGjtI0HsdiL3m9jzJs2luxZjQWyMIx9v5THWbcK839Eq |
CFhO5Grn6bmCCmyXJ9nEJxyi9BtLbpM7o85HIgG/T0ocxEacGxEtNirJiEDf52cEacT+ |
lDNGBbl/7AlJkhJPFBq+Lp8taf8XZx6aNOMSeVP1cA3e4oC20yNgURDcfJQ7MG7r4szK |
/vrKHXG74CdYcH7Cvd27KaBtcwlOErZGY4gjeqzfF7QKUeJ2kyoUtdW71iVjdxcpZk45 |
ZhLXEXoDcswp8D6rKA/ncCyZg9dmETili2uJsW6t31PtJHFBREItN0HGAcNHlUXi3rjZ |
9lQ5x61hW8xNDeONHFEZHdBypJfj9pEqznzI0Fmpc+4mXBUiwVJ/z25jL1tmJM1VXBu9 |
HDMa4rpCW0c/x1lI5UuKwUD0LPIrVVW7iG2bXvdE6VPkUNnpHHpMRVyu7ZfEZvA7dMYa |
ykZKuCKbe8r8/ERLw3DcFxN4TGdP9OsVaGmcGLc0qkKyBzXSDpe+bXy+j7m3E8mcdGbj |
wUI0jIyBqIvH3cnLmJZdyB/gBdoLYzcWKEzxhVA1PfRgZ7tXkIR28jH3Ds3BjttpDo5i |
GtHnJM1ci4/YrO5ENl0sptMoPNG2ERkzBIpExx9yDUcTBUkZjOZOTB6JaJWHUrmTW0GQ |
kwO0QF9iiOmlRkKiQy1V8oitkbE36o5VC8rpgV0yOEVJUs7TyshaHZvj6LRxg4PRQ5rC |
PG2ZJoqqkq94fVllvl5TpD6O3k/MgMIaDavKLSgc2D2idp/cdJLbM6b3LdWoPrdxY3sJ |
xEXP2wJPuWNfgf6EzTTYkTeVIb29rFixmfsShzpjVZGONRTL5ua2xOBFV7UNGbfXnNyN |
Roxo0MmqP40ZoeuKDAoyj/2XNyPlPK9TCcK4x6cqsXCsb+QgodU5MrJH8E8gy0TNnexA |
XZra4Buboe8cR2cP/uGdyER78allhOT/5/KZQZkYw8MWWkjXumJDSEBs1LYhEqzvKszb |
oGWFRgerRcN9iLcxWZP7zlgeGrGT2Pe82zEFFVeZ/HxjhZhGSn4mfrMwdfkxtPzQiq6V |
dW8sOLyofssdas+iw08ORfsgX1OszihhNeOP5/dr+gLqTM1O1U71W1/OtOmn1WmkLqua |
WTg/y2POOvpQV9Zv9yxp/r5lS8F13uVHTjFmbZ63PPXn6cLKcTNekFPEqu7LzpulTf/z |
l8JwMevyNJxqncm1oyRXLtH0KVvylSqvWoP8ef0mb81wpaoueHPBrTbOvXvcjA+zfSGL |
EenZUq5tuv8w0NQIPwyc5x8GpvIN8iWWhpdvDJoON9SGsYTpKNMj0xPjLSnw+8IVrhqx |
vx4H6BBW7kKdo/phV0vQ5GisJfRqO3YjhUcXlnGgvNO8Dr1k6jFmmjeU6nNN4XLTOCk/ |
KP1wfx4qfv4kc2Bl8e8qXus1jGrrhgP+nSwqNR1ZpyrbrmdYxWzou6CMLtSGQ+9KFpeb |
tzqxy94+gPaMk/IT9Fccs8sWj4BMuc24/WN0fNSItLkNB62SpZsXsAtxtQRd4NKIucd0 |
uyH3uGsrbvfptebEJME9aiQdkDrOFv0CzcVL3+nZtP91FEPYKvK8yAtIEBtjnPHiWlI4 |
YOh8WWdAzxypL7VtKELZQsYulGck27mLbGWkvMEXc0fcflFyVuZLPsEn+bytF11pEEUh |
F1uA/2wBDGAAAxjAAAYwgAEMYAADGMAABjCAAQxgAAMYwAAGMIABDGAAAxjAAAYwgAEM |
YAADGMAABjCAAQxgAAMYwAAGMIABDGAAAxjAAAYwgAEMYAADGMAABjCAAQxgAAMYwAAG |
MIABDGAAAxjAAAYwgAEMYAADGMAABjCAAQxgAAMYwAAGMIABDGAAAxjAAAYwgAEMYAAD |
GMAABjCAAQxgAAMYwAAGMIABDGAAAxjAAAYwgAEMYAADGMAAxsUf/gvibjzscPCkGQAA |
AABJRU5ErkJgglBLAwQUAAgICAAUkHdJAAAAAAAAAAAAAAAACwAAAGNvbnRlbnQueG1s |
7Vzrjts2Fv6/TyG46P5YQLYkX8b2Zlyk2V6RpEEzARb9U3Ak2mYjkVqKGs+kKNAH2QX6 |
Mn2RPskekpKsu2V77EySSYBJRJ5Dfjw8V4qaJ1/cBr5xg3lEGL3s2X2rZ2DqMo/Q1WXv |
zdXX5rT3xeJvT9hySVw895gbB5gK02VUwL8GcNNornsvezGnc4YiEs0pCnA0F+6chZim |
XPM89VzNpVsiced3ZlfEeW6Bb0VXZklb4EXX3WdWxHluj6NNV2ZJC0LNsy9ZV+bbyDeX |
DKQehEiQEopbn9C3l721EOF8MNhsNv3NsM/4amDPZrOB6s0AuxldGHNfUXnuAPtYThYN |
7L49SGkDLFBXfJI2D4nGwTXmnUWDBKrsanSz6qwRN6sG0bhrxDvrhiIubu/Q6769Qy/P |
GyCxbtiT6eAFdKofL55vdYEHXeeStAVRuZyEnZepqfP8jLEMqmTQBqrgOpY1GujnHPWm |
lXzDicA8R+62krvIdzOJs6BOaEBnD4DCxDdSTTPFl4KIGhicge7OiCOvceh/v3j+2l3j |
AG2JyW5ik9BIILqVDJeb0LjS8YDjkHGRCWbZ3WHCbjkZtrUI/GZzl70p6Yp7Xi0pwBkO |
wPTB8Mwbgjef9QqevF0hZiWFUG5xF4siyvvNVgbbGkiazIxBRbZOnq+yOLRkMYVFQOxK |
BIhvQ8yJ7EK+YpsXRshrvc8OGDKJXbkRCg6dYD/1GNmSaodhzAwiUCAwFBbOc9zF+MCD |
227DSeNg3rI8YslRuFE0FHX6cPXjQPaZMjxCAEhmyqUFTm+R5gDaf0SDrGEJuYC5RC42 |
Pez60eKJ9uVZs6GfJe7L3gtEV8i3ewY47ZQkIP5d2tMbtPM/JxBY1PYYr0EAy5qB/o5C |
Fv2zTKhbe0ZhcMlgrjAFAnBSnAWIFihCIlxw4zeIE6W/O8A9BTK/BlHa3jx1tCFRdMzU |
+eUiGnUSC9B1kMrR0NTqjTeUQFqJjRevG7GVCbuAu4sEDo5Bl6hdoz4eP/ugyU6SdhQL |
UDxBXFONkxmQ+lnAeoWuse+jb3gchiybNsGrPWzKrJ7MEHwB5oLgKCHeEE/mJZP+zBkT |
0HWd0iKfrMDMA8RXENMU5hyEjnj6T2sRQWbmxwEtAdONVXxJewLT7k+mkynJbJJj3yxR |
jGeT0T8ORfzlvSO2+pPxeNKGeOJYhwP++gSApxf2uA3w1BlNDwb87UkAO7N2wOPZwYCf |
ThoQA00ZLzTl0S7ZPESerpwtCRAarhn3ZCFEGcV7Q3ojS2xyOjtPaAN0Z15zjN6a11hs |
MKYmZxtIq5fIjw4FfSpnYO9wBuPJ/jufIL5/Z2D3h/Z42IrYGY0uDkb87N4RD0Ffhq3u |
a3hhD509EL+yyyBDxNGKo3CddkCDPFJSD6bm+hYjMJtsCRlLydxkumomSg2lmKytNMMv |
cSTI8s6MwBhh0A1YYU6fE7lI5oo8VJAuZHMwj2qMyDtodKahSBNkyOLnkCHD0FBuAmDP |
yvdsQZdpcjPJQU0oABFNhy53yoMNH98m3d3l7tyD3A8TUYOE7OXUGrrtEkppGiR00Sqg |
/eQzPEQ+V9KWfnasn5/p889oLxWFwv70CmoPTyZ+PXSj/FV39w0Y3e8GHKGrZ9C28Ueq |
baez9XZnuJ/0Kznd+1A122qKHEs8cnZFDk3TZJhWu2Fae0nr4vy66mKqjoxP7hw/lD2Y |
nn8PzpRANW3BEKo2e9K+BSnNWbZgdtQWyEwKZHcyn3F0tnm/wrKte5XWB6CvD28LDqq0 |
zqawD8zB2gfVR/csrUlL9jnuO+PWBU/2W+9x9c5DNlDndAHFaVc5Z78tOKjieS0Q9RD3 |
GlWt1aSmk9mFvQ/GlkJl197rY0XTx0uxPQBNGjlZrautgoWVtmsmhLwFkDb7hGJzjTW/ |
bVmf9xr0LG0l1AMZJgPkRCZfs0QhkveUiIeZXgHywzXKpB9TV8Tq5Zi5ge7L3hrRlVT7 |
hEBhUUelclZO3Ew75J0HIDQD5sH4PjfFdf4ADnaUhdF2G+pE2LS/sK71XbjGFAm896Hs |
K7ul9lk80W+w1RNx85PKt+/zJfHV8R/jl73P8ET+3WfmljriwJkbBVR2B90PVCtBU47e |
aGt1nuccvuOqEq1aYTbG3+4TVsLFvhMuZ/jC2mPCinPcc8LElXefsOLp9p3wAs9cd48J |
q2+WuqiaepMs/RllPEiin6IVHNFIXxtTb5eSweMIoiv4QLYxFX9iRYLHuOAOWSykO0s9 |
Sr5LuTmx5ixerXUsKk5RJRJ3YR1NyCIi1A0S63ND++5KTK9e6KjLKGUgwEJgbkoXrl6x |
5eThg5uO0QrLQy/V4LKYCg4ifvM6N166kqIcozXy5I22CvoYAglXyyzIIB1uk8SkdLxa |
Th0P5G1ZQmMWR8UtuOlCVRB0E2UinLeYUyUcvd3yBSRy3664vNO01QTQG51oVLYjdV41 |
VzaakvJ+LktN9yHtfZclNsmGpB3PXhZHVPlO0leUZ07ULQQKe+Zba25u1DjfMuasd03K |
qLOu7+pwZ73NyBtI1P7iAFIQresVFYxc5OM07ckNy7FP8LKGIVOpJrPNCBJt2PqIPTxZ |
JbLfsydTFqyDv6X+PHquR8/16LkePdexnmvFK/l+UoJk3qupJIF6j73NcDVWKbpHAgY9 |
ReaacfKOyUu6abWaHISUCW/kXO6WLCCe56cTydLVBFvYZIVw4vpk2Qw1c9pq9e2RvnCS |
dGTXgKbTUf5aR0xTu5Ry5Fjb2baYlbVvjijt0J91qNo4xJ6Z1XORFAuYe0Ay5czWA54U |
5uAskNV+pRfUoeYYJCe1Lbs8V6ghKI+gBCYRmoQu/RhTF5tQz28dOpMt4IfcmBc8iQ/i |
3RCxNvX3RHsW2iteKdE+Ls2yxo96dUK9GjReBk46rpl3lz3IoRZP1MdsEf6PBpNcKq42 |
GqrJI1Hoo7s0e4Jl38gVQmqlurUWf+f7oEQ6qZEYjxrsKr0AfdwoMrU8dpB/6Y/vlNjr |
pabuR6qfyV3J2hvXuksHzzqCwkDJzbldTP2nann7832Z4knMR7NFoLkhRgJ7l73RgSN/ |
vXNk58CRvy3zrdWNM3XjtNgBLaUZYJh6WJATUipRTbefriAw0SS5lye16tWF2vlQ60UJ |
Yvkth7J2F2wBHASk2SHWXIi64CKSccvO4Z06er5Vupc49u0cKvPIHHPhhF+f0d6s5jmv |
qm9kQ1s1tMvWW+WRbTt9vlPPQ9WQrnOQrALTtfxIzTNXmAUYkkLFIb/6+pLJcQzLcOyJ |
lfxMQaoVcuwKJN/XJK3ZUKH6uvGFIZmfJ+yFYYztv5bxk/FSWV5FqNtPIChlQnkdAO3O |
XYhbgvHF94jid8aff0gQ2P8FRtj2SToPlHHhWPbEtKamPbmyR3PHno8dRag6k3PmCMu6 |
BvYHfDX438X3f/7xZFDf1agl8t1I6oZA4WrUaNJbPDXcNfE9Q37oJwvD1N0AQzvvRW/x |
1+//KxgLPHfnh7llbYWIrKIMZHgY/u9jz/BJJMAqDAgsKrpBU8jJDfStVG3ODbHGhgzU |
Yb8wm/5/mAtNuU3adpZNNDVaV+broCrbnsGH0DVo9UGHOCXnMKf0arZD2+ze4psf37x6 |
9UN+1+bGr78a3/QpWLrx22/HbdPJV2jDEhRcD8uPCt+BZp0R9ehY1FAay+8v2dGQ37+O |
Hhg45S2KI2OlXRsrneZYedElVlpja/TRxcpHn5vT58PU1eotXsLGdhDlfUzV6r7BcoK8 |
58Y0fiCwogIsHyu//ECwoTy21YowTtEDgebmoUnTh0TugUAjeWg0kockKnI9EHgFhRMo |
CJERYb//YNG1AvuYgrNzjuBsQguUcMXwrL9CfAzPD6GrqtGFloNOcFpOwyYHqvtEpeVP |
W8151Fv8lDfnPQqlcyzhYoc3GuslFpcQ/Ay+PDZ2MWaLLFf3H+CCW3mG4LIha3GF8Skt |
OQ7ledcntWQPdvkTWzJRydsnteQQ5hVg0J/eovdZcXuM3vl+K/1NI41ySgj2e+eT/SqQ |
Pd8VZb+Q4zC+Zyd9xzR8b9n48PGo7P29VhrP7dnDea301+//Lei8fFVUeP2TvvWJIV5E |
hlgjYQA5gz7Bci98jAYHc5Y3Puc79gOP+tXzr14++8F4c/XVy6vvznGyAHP6bEXomebC |
ZoCIf+aTiffnC0ePvvD9nUvc74HAQRo01XnVy7SAN/STy1YHVfTHYVB2fuY5sTT3XXPu |
zAobDXSU/8WVsn/7pC+ipU/l3wi/+D9QSwcIWxQLYXEMAABSXgAAUEsDBBQACAgIABSQ |
d0kAAAAAAAAAAAAAAAAKAAAAc3R5bGVzLnhtbO1c3ZLbthW+71NomEkvOkOJpP7VXWXs |
dJo643Xd2L7OQCQkISYJDkitVn6avEzeqwd/JEiBWkpab52d+sIe4RwAB9/5wcEB6Jsf |
HpK4d49ZTmh66/h9z+nhNKQRSTe3zqeP/3Rnzg/Lv9zQ9ZqEeBHRcJfgtHDz4hDjvAed |
03whibfOjqULinKSL1KU4HxRhAua4VR3WpjcCzGVbBGDde0umM3eBX4ounbmvLW+aNV9 |
ZsFs9o4Y2nftzHkBU7P7mnbt/JDH7pq6IU0yVJCGFA8xST/fOtuiyBaDwX6/7++Hfco2 |
A38+nw8EtRQ4LPmyHYsFVxQOcIz5ZPnA7/sDzZvgAnWVj/OaIqW7ZIVZZ2hQgY60mt9v |
OlvE/aYFmnCLWGfbEMx19Q6j7uodRmbfBBXbFp3MBndAFH/dva1sgSVd5+K8NahCRrLO |
y5TcZn9KaSkq7yAdVIgbeN5oIH8b3PuT7HtGCswM9vAke4jisEScJjbQgM8fAIeL77mZ |
am7GF9068njAcEZZUQqy7h6gAJ2gdK9tkcTt7sWpmnXDosjKCuIMB+BqYOjuPcH775xa |
5DytgHlDASIMPdZFMJlx6mQH3xtwntJtQCVVUGWbMuyv6S6FRcBWoQDEDxlmhJNQLLot |
aiOYVhbTC4ZUe4UxQi2AEhxrDy2XZB2GUjfJXZKCYdJsYfSuRYs8HxY29X38ZcBpLt89 |
ID6qeYxNM3CWeodcU9gd1yjEboTDOF/eyMhWNvfkby7krXOH0g2KfacHIUyzJCQ+aIoz |
ON3/LYEwK8DrfYDVri0D/RVlNP97k1G2Or3a4LyDu8EpMIDLMpqgtMaRkSKEoHaPGBHW |
9Yhwr4Attkik29unzvckz6+Z2lwuSvNOsABfB1SuFk2svvcpJZBj4d7dh1bZmoxdhDvk |
BU6ukU6ZXas9Xj/7oM1PVLtMLLWUEV6jXazSTT2yEmnDULYloaN51W83AxfHrCCQnvJl |
5AWjnzEkCDGFjOS74WgyRiOnx+MdhIA4LinTYL4OwYXWdLGHoVyaFcK9U+ry36pLvkUR |
3bsgbY4L9+HW8fq+P/NJaqUfjukFZBkuJGXYzTMUQkrobikjXygPVJLbH53ivudrCy28 |
sI91HveI1zaqgjuG5exJsXVlor1GcW7YUYYYEsjXcBckzu+iXUH5JGBcJMJUsqI42yI9 |
gZBjxTCCJBaURcJCU3gmwYVLwANunZi5xapmXiSNMN+++YHEXI0WUssImyFYEM1ybn/t |
YpfsXO6j1exyDDCkXLlicmU2BdvhmlBtkRnMStBz8gXofpAVoi0Gx9qhDTThVDSEsCEW |
DAzn04cSIVzAxuV+xiwVq7PO6UJeg1JrgKkY+eSa0ff646zEWsuhqV+2mqIE0oQf3x1P |
zbPvGD9Yw4SYsmSQ625MWVK3pDlpSXrzzqm0VwsLXWJFqW7npN0C/NtDtsWp0JwboygC |
3IUsIg7EJCGl+B3NO9ulYbGTA/I4AquEdYMeH7d/bbduRCAQpHwSrz+aB+PKO+sukgGa |
lWv+346/TTs2zQzrWNW0PYYTRFKXH0q1AQZHTNku3zZYrnASeWYwgmaMTfOR5Y8VZdwn |
uL3BZgHGE6Ms59Z87cQuo/vG5NDS8M7PGGduQTe42PL6Ave+xyY2J5Q2/QF8KUIsclqD |
hFZejPIcxAM/qrzqeLx/YRQZ/tw6HDSUpTPXLkrKXdZk+AgNvwberysaHWxiPRbOEsQg |
1gBkmdjZJxMROyrCihYFP3R7fW82FDR5ygrB5OHfHYqbm2qpBpETpCInQPEeHfLHIk9L |
WBEJuo4qXz8/bwawUeXI58UgNbVivTBp193bkmdNr8Rvi4LWdZwKaEqQDixa1pK1VdqS |
o13eKoRyiSvnfcRpbY4A22IWo4PhKj2TfI0jXuxjre41nwZd3UtkBFtMNtuC7zTe991h |
eguZwiXrPxFnYj5kB8+uWWPQwRr9LubYeeU/InFee0Llw1IZOjPC6ih6VYQVtxSyhi7O |
NXmdIsxDl9i99qjbkqnJNt4DclY4HMIRurMaJWqKaul8sZq7ZVqGDCVdSdHZTt7AefHh |
Ca2EiPFOWskT6fPb8TWe8fAS/3O62nkgHh39mw1aRJoTWeYZ9keTYFKdrIpDBvKGmNeM |
DZ20dZ/04VwWNLszHsMNXA1xThYiOu6JfIflUftHHkvEzYh1Y+RsvSbP82hNiS6KYvwI |
nT5peFuh8POG8RuE6hgLeaJcwRm5hcaxkcnbYLwi2W9V11n7jSw7xGSTltaphvltlxdk |
fXD5cQwm3cNJ7WttKXuVnKxoHNUiiyTo0NRGLgOPYDjSkxCJ7gpZ0ztS178lxWkwxvge |
x4pdLoo3QHwsD1e7xOV3pwgEL2Hm2Y3q2gw2Jkn5uQt+ILZrrIuSaAVkoQ5+12QbtsGi |
xhaNazg+0z2O3NVB5lkQHxxj8rIAVMUZrz9U+YXQDRHVz1vHrdpV3hHjdaHZK4StywVq |
G5IdMQ5eGMajFoxHdoxHz4Hx8IVhPG7BeGzHePwcGI9eGMaTFowndownz4Hx+IVhPG3B |
eGrHePocGE9eGMazFoxndoxnz4Hx9IVhPG/BeG7HeP4cGM9eFMa+FWHfhq//HOjOXxa6 |
/RZ8+3aE+8+Cse+9MJCDFpADO8jBlSDXSSbyKS1wDkfJdE02O3VLVBJcdaZeU1rw3zYl |
+Gqt8pHNPYp3/IJdNeqOubF4cb1u9pEnZn7/zsfTTxr5ertLiNOoTUBiF1APzxGpJLBN |
03rel8+TxJXgfGI8J7DBo0apYOCqVTSShky8HedpnfG6S4xWPeri97QwJgldTThZivGb |
1ZVHbqZl855E/M21KMTxFcn7alUpkVZZVlwSdJBPLtwVLvYYp/yuOTceN51ROPL7r6zy |
8pLULkkbYsvGY+lVu1qEKEYaemE4dhscwXQy/dvZor7+H4k6O1/UV3YzcEMcx01Joems |
0iDnyFAkv3Lx+t5wpsOXfN+gSpV6FmMwkkAQqBV0j+c/VydXLbTDMs5GPrhYIEnTrwl1 |
nTIhUaSu3v9MenlqGORV4J8Ghrv3R4bZpcytLofOqWOLDa5DGbv7AxP1yLx+BRrM+E1Z |
+c3FguUEhva8AASOPJNSCd3kMWYyL+Hk0E1iWecW5M5uePf+yPIuu184RweQh3x9DfhD |
uwb89cwbhqc1oHlaNCCHbtWAIJ+hgeHTauAyuKxGpdY7PbncM+1t9ELtrcXhn8DcTvv7 |
mfCPnyDOfmsAXWyf/JQFp9YDnPnqMGWJ71iYjvKhDdaZ56y8TBCt5ZMqv/XEo0aHE1Xh |
Ukb452Pq7EcZ7NCkMM+46s3PdDZt3AtVb36OaWUd+IjCpHQVSQpj/Qqi+nxF7Ph6wV75 |
hYdB08v2jI861OnWTdBDjV59HqQYcqzfOugp+p43NQDUb9PhJAU4ig4yZ5nPLExozV+A |
W3mqAz4kBDQmZXhAEQ8Q8pQpz57VSUMJFYy/r15cy895PPHHMDK7yegFb4U31Z8OqzaO |
BT8A1599gcJK4PrByLPWPzy7htuspczyTmeHCtMD+AU/UuvXY/I5fal9/dyi9UunChrb |
4tWqxQ8riMsbWRng32/brunfDadOT7FUBQCVvwpZyxESCBBbzatMIKbyUblq5eFtObgZ |
mD8rAQ6Xdz5gxPj6jhZTVTOOyxeKkKC8xKi0JNXIkarh0XxEY9qjJcJJnSxvZBlD/K1K |
GvVKiWw72pf5QEZXdSRv5e6/EmWlMzq8bnZgdN8YAY4dJyb0qy9peWXLlS+m+BcwoDtV |
4sp0Aazqzk8ly39APIEQjXo//fLp/fs3qkqY8XJhQ4BzRHp9sUiBs7xDOU0//OdtWfNK |
IX6KzWN5E4WLkGFUULb8GaX4S++P38EYNjj+7WZg0Dgft79l4PkT15u5/uSjP1oEk4U/ |
FYyCeCPfj+b8wzfmkhR2B0iVlj//8fvNwE5Sgi9f9YRRSsvqG6BZRD6F6OCk2s+1g+BS |
0Icigl2l8IvnHoENogItepKHK0aHZf6Rv8ks4mDJpcu4QsW+7wbDj/584XmL4bw/HgbT |
aTD0wcB9fxAMB/5E6UEq/jydmC2nljI+2gjKn0Yoq6ykEfR0c+O/hln+F1BLBwituM6j |
AwwAAFpGAABQSwMEFAAICAgAFJB3SQAAAAAAAAAAAAAAAAgAAABtZXRhLnhtbI2T326b |
MBjF7/cUiPXW2CaUJBah0i6maeq0Scuk3UWO+UrcgY2MKdmeZi+z9yqYPyNtJo07n+93 |
fI4NJHfnsvCewNRSq51PA+J7oITOpMp3/rf9e7Tx79I3iX54kAJYpkVTgrKoBMu9zqpq |
Nox2fmMU07yWNVO8hJpZwXQFarKwJc1c0KCcC6l+7PyTtRXDuG3boF0F2uSYbrdb7KYT |
momZqxpTOCoTGAroE2pMA4ontm/4v6V6dllJaz0H9fhQ2sWFhER4WE90brKsuHaAjl3h |
riG3HD1JaN/63nj8xYWHfjrdbl8jTVwZqaSVvEDCALfapB+5gl/en9+WqxyKxwRfpQav |
W3W7oy4Y0pDQGJE1InRPt4zeMrINok1E3DPuc+lIMsEW1g2i8Z7G7HbjrCSerBPW8//s |
uZgN7SDrOqscZY1xmemXPf0Qkk/h+uvY5hVxaRQ/RQF1Gq5e4KM+wDkoMC71Xh4NfHYX |
jG8DGkRBeHMvVXM+fN/EhzjyFsChMvoRhMWUlOTmXSOLDIVjzN8dh4T5V6ht17K2UnhO |
t/xYABK6UXbnr/xBlCXPZ5GMoj72WS/VakHSWTM8N7w6zftOdKtNNolxNIri1PHCgpnx |
eD2OVPeS25O0UFdcdDmvyBX1cZrgiy8SX/v702dQSwcI6qkzc+0BAAA7BAAAUEsDBBQA |
CAgIABSQd0kAAAAAAAAAAAAAAAAMAAAAc2V0dGluZ3MueG1stVrfd9o6DH6/f0UP7x3Q |
dmzltN0BWjY2WjhA13P3ZhIBvjhWju0U+O+v7EDXUbKxJO5L2/yQbEnfJ8nK1ad1JE6e |
QWmO8rpSf1ernIAMMORyfl15nHRPP1Y+3fxzhbMZD6AZYpBEIM2pBmPoEX1Cr0vdTG9f |
VxIlm8g0103JItBNEzQxBrl7rfn66aZTll5ZCy6X15WFMXGzWl2tVu9W5+9Qzav1y8vL |
qru7ezRAOePzY1WlT79WhYgviuwL6WKcsrNa7aKa/l852S7ylWnOKjc7O+y2f3O1VZD+ |
OuUGImubk+1lu7TrCqlsPnNYvVitcui9X9/5Ts+3FLAJxpXdHbOJ6Y5AOa/cnDUuGlfV |
t1KOl9yHmTkoulZM7hMPzeLwmusfG+fFhH8BPl8cXna9Xjuv55M+XuBqBCGFGXQWTM5B |
72mYIgpgsnJjVAL5dPRkW+FKwz2GkCV9xoQ+WvxpxOJTLkNYQ/jWWIdjzL1D6FCb40ze |
C/eWqo3i1tg2nM/yuzIz9uofavWcTrRys9Dyvt7ILVXzqYDyweLE+kC3EzzKhIkFYW7P |
OdltNAajw+47b3x4n0/4D8RoQqL2A26ByhTipD7bYGI6KJJI7uO6LOltxGVpwH5rly4L |
DKrDa683cq6+p8cgIDAQdhVdyLH0AxdfE0zW7S1nHX6AUuTxSTW9kChmKEX/TXYdEouZ |
oUIdkwE8OM3Jt5wxZF6SSbp+kt1mwXKuMJH7RF2Wkg6SM1H42kNLSjTOfQfgUwydTv5n |
xeIFD3wt39GsTx932frhLTi3Wbh6dKDEoLoKozGYZD/hlBbuE1iboWABLFCEsM9WZahp |
xbHYDJlic+vVe6aWXVQRMxN8SKIpOJt42twIbCMAmSgrIH/CpgMSTtuZc+lB/h2ZJuwS |
jDNjtIDwcaIc+1jnP5FXxhETwoOenzxn/W/tdavYyrF9+co6gscxhEMemERlQ7uAhq5A |
ZgyjYuoBI+d4H1oe5ZRapqVTswOIDz0uwsYbTTd8xdkWJDOBK09MO7Fm8kXjY7K8gK84 |
9YJBi7kOi/UQVEC1F6WjRsMHLFAI0gJ3UWw2HRDCQrF8g90zs2gzDbYbbwk+l/Y4p3w1 |
rTCtewezGRWOPvzS0302BXG7PZHylZpAFaoQBomxlu5TghP/chCh9plMe3OJCrpcadMn |
rT1qBaTpSZ8qH+OQGbDlzwSiWNDfnkDepuJn6ZEAqavH1TcAHxWco/AQwltGWYnAVyik |
UifTinVLhmQVudRUqFl/d5gIEuHqfR+e1jAQ4RYU90DrzS78i8SwpExELb+iKnccs8BP |
2I7ZM3wWOGUvBEIGXHoKLT0C65VnmGAKyfIhMtJ8v3omP1VuLmpnlx8bOQ+NfunjR5O+ |
L451Ke+3fV7RtoZiV1nweeKmL5zQLW2V7mMDoavKHUVtAdEyY8OUhzDq2hTVSgymtF6+ |
gpREfCakA+YqfxudBakIiAc7GMXUxNghVunHq5ajvqcDsoHsCNQ+DkDtToxPj28ThiU+ |
O0C0TOsOdTNGHws+X5ySRVEkNo/lrQ2/gZItzZkcJpL6TI850R6SgBpM/yOOHKLmVlNZ |
kZ09hCKtU0c6L5FYfCTVZ3KeEAtneAZyOqODidWfIfVxnHM6wBR5NyOKjqii2jDn0hZN |
uSXcyfC37xc9vz+C6IgdDA+Y8NxqjZOpsUHWFRuqOQMiNQhb7j9//L2l7gk6Irf9sIfT |
A9J1tybsSCb6wEI/qSJRily+K/3t7zEmKsgfeC0hcOVo9StOO0wGkHkmWIS20RCjWXbz |
yZsWQf6qfGekPx1lFipm0l3szmdjTz22XJOeAH6AQorXP4RqsV6l5QZraZtCSl/mAbpH |
bKl91LfbT0O2AUfZ8xvsJwsLnMZFm0tGeeSouQzGryJrvFC2uXs5F/EAcpTUgP0MhIGk |
goCqAR/mIkUjxH1PuG7vrNa4oJ+cLG82AvQD3sKMJcKHp22LnZaZ2ePInB+SuKNMCt+x |
wXhXhZXv5lt8QPM10YbPNjaQ9BM3i3smEybadhbgwWZO5Qgos1sotoxR9rSHGih7FOaj |
H/g1XVF/EzEZHuhtXMDl7Gz6yMIRsRhK8QbqZdmsw2I7X7LsT1jUAzl8W9r6M1ixkTKo |
g7Pkv2RBO2hr6ZcGYVe5PSl6VFH15qrGPBSV+WVJ9c0HnNWsT1tv/gdQSwcIUsuRKGUG |
AAAcKwAAUEsDBBQAAAgAABSQd0kAAAAAAAAAAAAAAAAYAAAAQ29uZmlndXJhdGlvbnMy |
L21lbnViYXIvUEsDBBQAAAgAABSQd0kAAAAAAAAAAAAAAAAYAAAAQ29uZmlndXJhdGlv |
bnMyL2Zsb2F0ZXIvUEsDBBQAAAgAABSQd0kAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJh |
dGlvbnMyL3Rvb2xwYW5lbC9QSwMEFAAACAAAFJB3SQAAAAAAAAAAAAAAABgAAABDb25m |
aWd1cmF0aW9uczIvdG9vbGJhci9QSwMEFAAACAAAFJB3SQAAAAAAAAAAAAAAABwAAABD |
b25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsDBBQACAgIABSQd0kAAAAAAAAAAAAA |
AAAnAAAAQ29uZmlndXJhdGlvbnMyL2FjY2VsZXJhdG9yL2N1cnJlbnQueG1sAwBQSwcI |
AAAAAAIAAAAAAAAAUEsDBBQAAAgAABSQd0kAAAAAAAAAAAAAAAAaAAAAQ29uZmlndXJh |
dGlvbnMyL3N0YXR1c2Jhci9QSwMEFAAACAAAFJB3SQAAAAAAAAAAAAAAAB8AAABDb25m |
aWd1cmF0aW9uczIvaW1hZ2VzL0JpdG1hcHMvUEsDBBQAAAgAABSQd0kAAAAAAAAAAAAA |
AAAaAAAAQ29uZmlndXJhdGlvbnMyL3BvcHVwbWVudS9QSwMEFAAICAgAFJB3SQAAAAAA |
AAAAAAAAAAwAAABtYW5pZmVzdC5yZGbNk81ugzAQhO88hWXO2EAvBQVyKMq5ap/ANYZY |
BS/ymhLevo6TVlGkquqf1OOuRjPfjrSb7WEcyIuyqMFUNGMpJcpIaLXpKzq7Lrml2zra |
2LYrH5od8WqDpZ8qunduKjlfloUtNwxsz7OiKHia8zxPvCLB1ThxSAzGtI4ICR6NQmn1 |
5HwaOc7iCWZXUXTroJB59yA9i906qaCyCmG2Ur2HtiCRgUCNCUzKhHSDHLpOS8UzlvNR |
OcGh7eLHYL3Tg6I8YPArjs/Y3ogMpuVe4L2w7lyD33yVaHruY3p108Xx3yOUYJwy7k/q |
uzt5/+f+Ls//GeKvtHZEbEDOo2f6kOe08h9VR69QSwcItPdo0gUBAACDAwAAUEsDBBQA |
CAgIABSQd0kAAAAAAAAAAAAAAAAVAAAATUVUQS1JTkYvbWFuaWZlc3QueG1srZTBbsMg |
DIbvfYqI6xTYeppQkx4q7Qm6B2DESZHARGCq9u1HorbpNHVqtNxsY/7/k7HYbE/OFkcI |
0Xis2Bt/ZQWg9o3BrmKf+4/ynW3r1cYpNC1EktegyPcw3tKKpYDSq2iiROUgStLS94CN |
18kBkvzZL0enW3YHsGb1qpj8WmOhzPfDeepuk7Vlr+hQMfFIZCo7aIwq6dxDxVTfW6MV |
5TZxxIaPwPyekxOciIk5DPtDcl+ojI2CriHvsXvAYJzqQAzns1y0Rxr48hwfCA/kYjie |
pRvpbCEuLuuA1PKsQJQXc3nancfWdCmMmxHXQmkNFnLqg9AphL8H/z+vJ1c1JhwQeDJc |
3yvMfJZLjYemfcI4d71chrkRv/6A+htQSwcI9QcjhxwBAAA+BAAAUEsBAhQAFAAACAAA |
FJB3SV7GMgwnAAAAJwAAAAgAAAAAAAAAAAAAAAAAAAAAAG1pbWV0eXBlUEsBAhQAFAAA |
CAAAFJB3SUJn8sGrDgAAqw4AABgAAAAAAAAAAAAAAAAATQAAAFRodW1ibmFpbHMvdGh1 |
bWJuYWlsLnBuZ1BLAQIUABQACAgIABSQd0lbFAthcQwAAFJeAAALAAAAAAAAAAAAAAAA |
AC4PAABjb250ZW50LnhtbFBLAQIUABQACAgIABSQd0mtuM6jAwwAAFpGAAAKAAAAAAAA |
AAAAAAAAANgbAABzdHlsZXMueG1sUEsBAhQAFAAICAgAFJB3SeqpM3PtAQAAOwQAAAgA |
AAAAAAAAAAAAAAAAEygAAG1ldGEueG1sUEsBAhQAFAAICAgAFJB3SVLLkShlBgAAHCsA |
AAwAAAAAAAAAAAAAAAAANioAAHNldHRpbmdzLnhtbFBLAQIUABQAAAgAABSQd0kAAAAA |
AAAAAAAAAAAYAAAAAAAAAAAAAAAAANUwAABDb25maWd1cmF0aW9uczIvbWVudWJhci9Q |
SwECFAAUAAAIAAAUkHdJAAAAAAAAAAAAAAAAGAAAAAAAAAAAAAAAAAALMQAAQ29uZmln |
dXJhdGlvbnMyL2Zsb2F0ZXIvUEsBAhQAFAAACAAAFJB3SQAAAAAAAAAAAAAAABoAAAAA |
AAAAAAAAAAAAQTEAAENvbmZpZ3VyYXRpb25zMi90b29scGFuZWwvUEsBAhQAFAAACAAA |
FJB3SQAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAAAeTEAAENvbmZpZ3VyYXRpb25zMi90 |
b29sYmFyL1BLAQIUABQAAAgAABSQd0kAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAK8x |
AABDb25maWd1cmF0aW9uczIvcHJvZ3Jlc3NiYXIvUEsBAhQAFAAICAgAFJB3SQAAAAAC |
AAAAAAAAACcAAAAAAAAAAAAAAAAA6TEAAENvbmZpZ3VyYXRpb25zMi9hY2NlbGVyYXRv |
ci9jdXJyZW50LnhtbFBLAQIUABQAAAgAABSQd0kAAAAAAAAAAAAAAAAaAAAAAAAAAAAA |
AAAAAEAyAABDb25maWd1cmF0aW9uczIvc3RhdHVzYmFyL1BLAQIUABQAAAgAABSQd0kA |
AAAAAAAAAAAAAAAfAAAAAAAAAAAAAAAAAHgyAABDb25maWd1cmF0aW9uczIvaW1hZ2Vz |
L0JpdG1hcHMvUEsBAhQAFAAACAAAFJB3SQAAAAAAAAAAAAAAABoAAAAAAAAAAAAAAAAA |
tTIAAENvbmZpZ3VyYXRpb25zMi9wb3B1cG1lbnUvUEsBAhQAFAAICAgAFJB3SbT3aNIF |
AQAAgwMAAAwAAAAAAAAAAAAAAAAA7TIAAG1hbmlmZXN0LnJkZlBLAQIUABQACAgIABSQ |
d0n1ByOHHAEAAD4EAAAVAAAAAAAAAAAAAAAAACw0AABNRVRBLUlORi9tYW5pZmVzdC54 |
bWxQSwUGAAAAABEAEQBwBAAAizUAAAAA} |
&> |
<br><br> |
|
<& /input/string.comp, |
id => 'doc_val', |
description => 'input doc_val', |
rows => 16, |
cols => 128, |
length => 1048576, |
readonly => 1 |
&> |
<br><br> |
|
<& /input/button.comp, |
id => 'button_ro', |
description => 'button', |
value => 'button', |
caption => 'Readonly', |
readonly => 0, |
onclick => "var doc = document.getElementById('test_document'); var ro = !doc.Readonly(); doc.Readonly(ro); document.getElementById('doc_val').Readonly(ro); document.getElementById('button_gv').disabled = ro; document.getElementById('button_sv').disabled = ro;" |
&> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get Value', |
readonly => 1, |
onclick => "var doc = document.getElementById('test_document'); document.getElementById('doc_val').set_value(doc.get_value());" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set Value', |
readonly => 1, |
onclick => "var doc_content = document.getElementById('doc_val'); document.getElementById('test_document').set_value(doc_content.get_value());" |
&> |
/tags/2.0/htdocs/test/test_file.html |
---|
0,0 → 1,42 |
<h2>Test: file.comp</h2> |
|
<& /input/file.comp, |
id => 'test_file', |
description => 'Attached file', |
prompt => 'Please select a file', |
readonly => 1, |
name => 'gruppi.odt', |
value => q{} |
&> |
- <button onclick="Id_test_file.Readonly(true); document.getElementById('button_sv').disabled = true; document.getElementById('file_val').Readonly(true);">Readonly</button> |
<button onclick="Id_test_file.Readonly(false); document.getElementById('button_sv').disabled = false; document.getElementById('file_val').Readonly(false);">R/W</button> |
<br><br> |
|
<& /input/string.comp, |
id => 'file_val', |
description => 'input file_val', |
rows => 12, |
cols => 80, |
length => 1048576, |
readonly => 1 |
&> |
<br><br> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get Value', |
readonly => 0, |
onclick => "var file = document.getElementById('test_file'); document.getElementById('file_val').set_value(file.get_value());" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set Value', |
readonly => 1, |
onclick => "var doc_content = document.getElementById('file_val'); document.getElementById('test_file').set_value(doc_content.get_value());" |
&> |
/tags/2.0/htdocs/test/test_image.html |
---|
0,0 → 1,47 |
<h2>Test: image.comp</h2> |
|
<& /input/image.comp, |
id => 'test_image', |
description => 'Descrizione pulsante', |
readonly => '', |
value => 'data:image/gif;base64,R0lGODlhEAAQAPYAAEV50Ud70Ul90Ut90U1/00+B01GD1VeH1V2J0mWR2W+X23ub0nGZ3HOc3nSc3nmf3Xie3nmf3n+l34ODg4SEhIWFhYeHh4iIiImJiYqKioyMjI2NjY6Ojo+Pj5KSkpOTk5aWlpiYmJmZmZubm5ycnKysrLW1tbm5ubq6ury8vIGk34Ol34in2oyp2IWn4Yep4Ymp4Yut44yu4pKx5JSz5ZSz5pa05Zi05pi25pm35pq25pu35py35pu455y5552556O96KW+6aW/6afA6ajA6qvC6qvD6qzD6q3E6q7G67PI7LPI7bfM7bjM7rrN7rrO7rvO7rzP78DAwMLCwsPDw8TExMXFxcbGxsfHx8jIyMzMzM/Pz9LS0tTU1NfX193d3eLi4uTk5Ofn5+7u7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAGQALAAAAAAQABAAAAeLgGSCg4QkJCOEiYMjYGMgiomMYiePkItgWx5kGhoZliBfVx4aJV4Wlh5eVycnVFSnhDEsHldaV1eusIMwPjgtXCYZFhMTiS89UVAyC7qJLjhQQ0FLKgiQKjZQQTY+SBEGihLZQTQ9RxEFkBFMQDM4SA4ElgpLOO8OApZkCSpHQgwA9Ak6YIBAQIGBAAA7' |
&> |
<br><br> |
|
<& /input/string.comp, |
id => 'img_val', |
description => 'input img_val', |
rows => 16, |
cols => 64, |
length => 10240, |
readonly => 1 |
&> |
<br><br> |
|
<& /input/button.comp, |
id => 'button_ro', |
description => 'button', |
value => 'button', |
caption => 'Readonly', |
readonly => 0, |
onclick => "var img = document.getElementById('test_image'); var ro = !img.Readonly(); img.Readonly(ro); document.getElementById('img_val').Readonly(ro); document.getElementById('button_gv').disabled = ro; document.getElementById('button_sv').disabled = ro;" |
&> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get Value', |
readonly => 1, |
onclick => "var img = document.getElementById('test_image'); document.getElementById('img_val').set_value(img.get_value());" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set Value', |
readonly => 1, |
onclick => "var img_content = document.getElementById('img_val'); document.getElementById('test_image').set_value(img_content.get_value());" |
&> |
/tags/2.0/htdocs/test/test_errors.html |
---|
0,0 → 1,38 |
<%args> |
$err => undef |
</%args> |
<html> |
<h2>test_errors.html</h2> |
<hr> |
<pre> |
Si vuole verificare come si propagano gli errori |
Richiamare la pagina con i seguenti parametri di test: |
test_errors.html?err=500 - interrompe utilizzando $m->abort(500); |
test_errors.html?err=400 - interrompe utilizzando $m->abort(400); |
test_errors.html?err=400 - interrompe utilizzando $m->abort(200); |
test_errors.html?err=die |
test_errors.html?err=ret - interrompe utilizzando return; |
</pre> |
<h3>Parametro err: <%$err%></h3> |
<hr> |
<%perl> |
if($err =~ m/^\d+$/){ |
$m->abort($err); |
} |
if($err eq 'die'){ |
die "DIE\n"; |
} |
if($err eq 'ret'){ |
return; |
} |
</%perl> |
<br>end. |
<hr> |
<%once> |
</%once> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_string.html |
---|
0,0 → 1,33 |
<h2>test string.comp</h2> |
Test con rows => 4, cols => 20, size => 5, length => 7 |
% my $value = ".12345678901234567890\n" x 4; |
% chomp($value); |
<br> |
<& /input/string.comp, id => 'test1', rows => 4, cols => 20, value => $value &> |
<br> |
Test con rows => 1, size => 7, length => 10 |
% $value = "1234567"; |
<br> |
<& /input/string.comp, id => 'test2', rows => 1, size => 7, length => 10, value => $value &> |
<br> |
Test con Espressione regolare '[a-z]' |
<br> |
<& /input/string.comp, id => 'test3', rows => 1, size => 20, length => 20, valid_chars => '[a-z]' &> |
<br> |
Test con upperCase (trans => 'U') |
<br> |
<& /input/string.comp, id => 'test3b', rows => 1, size => 20, length => 20, trans => 'U' &> |
<br> |
Test readonly |
<br> |
<& /input/string.comp, id => 'test4', rows => 1, size => 35, readonly => 1 , value => 'WIDGET STRING IN SOLA LETTURA' &> |
<input type="button" value="change read/write" onclick="change_ro();"> |
<script> |
function change_ro(){ |
var test4 = document.getElementById('test4'); |
test4.Readonly(!test4.Readonly()); |
} |
</script> |
/tags/2.0/htdocs/test/test_FCKeditor.html |
---|
0,0 → 1,45 |
<%args> |
$edit => undef |
</%args> |
<H1>test FCKeditor.comp </H1> |
<& /input/FCKeditor.comp, |
id => 'fckedit', |
readonly => 1, |
bgcolor => 'lightgreen', |
value => q{ |
<H1>Test FCKeditor.comp</H1> |
<P> |
Compliment interested discretion estimating on stimulated apartments oh. Dear so sing when in find read of call. As distrusts behaviour abilities defective is. Never at water me might. On formed merits hunted unable merely by mr whence or. Possession the unpleasing simplicity her uncommonly. |
</P> |
}, |
width => '400px', |
height => '200px', |
editWidth => '600px', |
editHeight => '300px' |
&> |
<br> |
<& /input/button.comp, |
id => 'button_rw', |
description => 'button', |
value => 'button', |
caption => 'Modify', |
onclick => "Id_fckedit.Readonly(false); Id_button_rw.Readonly(true); Id_button_ro.Readonly(false);" |
&> |
<& /input/button.comp, |
id => 'button_ro', |
description => 'button', |
readonly => 1, |
value => 'button', |
caption => 'Readonly', |
onclick => "Id_fckedit.Readonly(true); Id_button_ro.Readonly(true); Id_button_rw.Readonly(false)" |
&> |
<%init> |
# precaricamento librerie utilizzate dai componenti caricati "OnDemand" |
&LoadHeader('/input/input.comp', '/input/button.comp', '/lib/FCKeditor/fckeditor.js', '/input/FCKeditor.js'); |
</%init>\ |
<%flags> |
inherit => '/autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_button.html |
---|
0,0 → 1,19 |
<h2>test button.comp</h2> |
<h3>Button with value = 'my value'</h3> |
<& /input/button.comp, |
id => 'test1', |
description => 'Descrizione pulsante', |
caption => 'Test button', |
value => 'my value', |
onclick => q|javascript: alert('Value=\''+this.get_value()+'\'')| |
&> |
<hr> |
<h3>Button with value = ''</h3> |
<& /input/button.comp, |
id => 'test2', |
description => 'Descrizione pulsante', |
caption => 'Test button', |
value => '' |
&> |
<br> |
/tags/2.0/htdocs/test/test_number.html |
---|
0,0 → 1,10 |
<h2>test number.comp</h2> |
<& /input/number.comp, |
id => 'test', |
NumCifre => 12, |
ValMax => 50000, |
ValMin => -5000, |
description => 'Test input numerico', |
Xonchange => "my_alert('Valore='+Input_Event(event).value,'txt', 150,50);" |
&> |
<br> |
/tags/2.0/htdocs/test/test_url.html |
---|
0,0 → 1,24 |
<h2>test url.comp</h2> |
Apre finestra: |
<& /input/url.comp, id => 'test_url', size => 35, readonly => 1 , |
value => 'https://www.leader.it', |
description => 'Sito Wed di Leader.IT network' |
&> |
- |
<input type="button" value="change read/write" onclick="change_ro();"> |
<script> |
function change_ro(){ |
var test_url = document.getElementById('test_url'); |
test_url.Readonly(!test_url.Readonly()); |
} |
</script> |
<br> |
<hr> |
<br> |
Apre popup: |
<& /input/url.comp, id => 'test_url_popup', popup => 1, size => 80, readonly => 1, |
value => 'https://www.leader.it/Portal/TecnologieUtilizzate', |
description => 'Tecnologie utilizzate' |
&> |
/tags/2.0/htdocs/test/test_form.html |
---|
0,0 → 1,39 |
<%args> |
$edit => undef |
</%args> |
<H1>test_form.html</H1> |
<H3>form.comp</h3> |
<& /input/form.comp, |
id => 'IdWidgetFormTest', |
from => '/public/anagrafiche', |
value => '7', |
popupWidth => 840, |
popupHeight => 580, |
formParameters => { |
form => 'FORM', |
disp_print => 0, |
find_area => undef, |
}, |
size => 300, |
rows => 10, |
onclick => "alert('click'); |", |
onchange => "alert('changed val:'+this.get_value());", |
empty => '', |
empty_descr => 'nessuno' |
&> |
<%init> |
# precaricamento librerie utilizzate dai componenti caricati "OnDemand" |
# servono tutti percé potrebbero essere usati dal form richiamato dal widget |
&LoadHeader('/input/input.comp', '/input/string.comp', '/input/date.comp', |
'/input/span.comp', '/input/number.comp', '/input/select.comp', '/input/url.comp', |
'/input/radio.comp', '/input/checkbox.comp', '/input/form.comp', |
'/input/select.comp', '/input/time.comp', '/input/timestamp.comp', |
'/input/button.comp', '/input/Permission.comp', '/input/Files.comp', |
'/input/htmlselect.comp', '/input/codfisc_pi.comp', |
'/input/divselect.comp', '/lib/FCKeditor/fckeditor.js', '/input/FCKeditor.js' |
); |
</%init>\ |
<%flags> |
inherit => '/autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_crud.html |
---|
0,0 → 1,125 |
<H1>Test funzioni CRUD</H1> |
Schema: <input type="text" id="schema" value=""><br> |
Object/table: <input type="text" id="table" value=""><br> |
Father key: <input type="text" id="father_key" value=""><br> |
Key: <input type="text" id="key" value=""><br> |
Format: <select id="format"> |
<option value="">XML</option> |
<option value="rest">JSON</option> |
</select><br> |
<br> |
<input type="button" value="info" id="info" onclick="do_info();"> |
<input type="button" value="numrec" id="numrec" onclick="do_numrec();"> |
<input type="button" value="newkey" id="newkey" onclick="do_newkey();"> |
<input type="button" value="retrieve" id="retrieve" onclick="do_retrieve();"> |
<input type="button" value="update" id="update" onclick="do_update();"> |
<input type="button" value="create" id="create" onclick="do_create();"> |
<input type="button" value="delete" id="delete" onclick="do_delete();"> |
<br> |
XML da inviare:<br> |
<textarea id="xml_in" rows=12 cols=120></textarea><br> |
Risposta:<br> |
Url: <span id="url">...</span><br> |
<textarea id="xml_out" rows=20 cols=120></textarea> |
<script> |
function alert_xml_out(){ |
if(http_request.readyState == 4){ |
var contenttype = http_request.getResponseHeader('Content-type'); |
var contentrange = http_request.getResponseHeader('Content-range'); |
var doc = document.getElementById('xml_out'); |
doc.style.color=''; |
doc.value = 'Status: ' + http_request.status + '\nContent-type: ' + contenttype + '\nContent-Range: ' + contentrange + '\n'; |
if(http_request.status == 200){ |
result = http_request.responseText; |
doc.value += '\n' + result; |
doc.style.color='blue'; |
}else{ |
result = http_request.responseText; |
doc.value += '\n' + result; |
doc.style.color='red'; |
} |
} |
} |
function send(mode, params, xml){ |
var schema = document.getElementById('schema').value; |
var url = '/dbms/' + (schema ? schema + '/' : '') + document.getElementById('table').value + '?' + params; |
document.getElementById('url').innerHTML = url; |
http_request = null; |
if(window.XMLHttpRequest){ |
http_request = new XMLHttpRequest(); |
}else{ |
http_request = new ActiveXObject("Msxml2.XMLHTTP"); |
} |
http_request.onreadystatechange = alert_xml_out; |
http_request.open(mode, url, true); |
http_request.setRequestHeader("Content-type", 'text/xml'); |
http_request.setRequestHeader("Content-length", xml.length); |
http_request.send(xml); |
} |
function do_info(){ |
send('GET', 'method=info', ''); |
} |
function do_newkey(){ |
send('GET', 'method=newkey', ''); |
} |
function do_numrec(){ |
var father_key = document.getElementById('father_key').value; |
if(!father_key){ |
alert('Indicare la chiave del record padre da selezionare'); |
return; |
} |
send('GET', 'method=numrec&father_key=' + father_key, ''); |
} |
function do_retrieve(){ |
var key = document.getElementById('key').value; |
var father_key = document.getElementById('father_key').value; |
if((key && father_key) || (!key && !father_key)){ |
alert('Indicare la chiave del record oppure la chiave del record padre da selezionare'); |
return; |
} |
var format = document.getElementById('format').value; |
if(format){ |
format = '&envelope_response=' + format; |
} |
if(key){ |
send('GET', 'method=retrieve&key=' + key + formay, ''); |
}else{ |
send('GET', 'method=retrieve&father_key=' + father_key + format, ''); |
} |
} |
function do_update(){ |
var key = document.getElementById('key').value; |
if(!key){ |
alert('Indicare la chiave del record da aggiornare'); |
return; |
} |
send('POST', 'method=update&key=' + key, document.getElementById('xml_in').value); |
} |
function do_create(){ |
var key = document.getElementById('key').value; |
var father_key = document.getElementById('father_key').value; |
if(key){ |
send('POST', 'method=create&key=' + key + '&father_key=' + father_key, document.getElementById('xml_in').value); |
}else{ |
send('POST', 'method=create&father_key=' + father_key, document.getElementById('xml_in').value); |
} |
} |
function do_delete(){ |
var key = document.getElementById('key').value; |
if(!key){ |
alert('Indicare la chiave del record da cancellare'); |
return; |
} |
send('GET', 'method=delete&key=' + key, ''); |
} |
</script> |
/tags/2.0/htdocs/test/test_date.html |
---|
0,0 → 1,21 |
<h2>test date.comp</h2> |
<br> |
Data: <& /input/date.comp, |
id => 'Data', |
value => '12/12/2005', |
onchange => 'alert("New date Data:"+this.get_value());', |
description => 'Test input data', |
&> |
<br> |
<br> |
Data2: <& /input/date.comp, |
id => 'Data2', |
value => '', |
onchange => 'alert("New date Data2:"+this.get_value());', |
description => 'Test input data', |
&> |
<br> |
<hr> |
<br> |
<button onclick="Id_Data.Readonly(true);">Readonly</button> |
<button onclick="Id_Data.Readonly(false);">R/W</button> |
/tags/2.0/htdocs/test/test_rest.html |
---|
0,0 → 1,134 |
<H1>Test funzioni REST con Dojo dojo/store/JsonRest</H1> |
Schema: <input type="text" id="schema" value=""><br> |
Object/table: <input type="text" id="table" value=""><br> |
Father key: <input type="text" id="father_key" value=""><br> |
Key: <input type="text" id="key" value=""><br> |
Query: <input type="text" id="query" value=""><br> |
Start record: <input type="text" id="start" value=""><br> |
Num rows: <input type="text" id="num_rows" value=""><br> |
<br> |
<input type="button" value="newkey" id="newkey" onclick="do_newkey();"> |
<input type="button" value="retrieve" id="retrieve" onclick="do_retrieve();"> |
<input type="button" value="update" id="update" onclick="do_update();"> |
<input type="button" value="create" id="create" onclick="do_create();"> |
<input type="button" value="delete" id="delete" onclick="do_delete();"> |
<br> |
JSON da inviare:<br> |
<textarea id="json_in" rows="12" cols="120"></textarea><br> |
Risposta:<br> |
Url: <span id="url">...</span><br> |
<textarea id="json_out" rows="12" cols="120"></textarea> |
<script> |
function alert_json_out(){ |
if(http_request.readyState == 4){ |
var contenttype = http_request.getResponseHeader('Content-type'); |
var doc = document.getElementById('json_out'); |
doc.style.color=''; |
doc.value = 'Status: ' + http_request.status + '\nContent-type: ' + contenttype + '\n'; |
if(http_request.status == 200){ |
result = http_request.responseText; |
doc.value += '\n' + result; |
doc.style.color='blue'; |
}else{ |
result = http_request.responseText; |
doc.value += '\n' + result; |
doc.style.color='red'; |
} |
} |
} |
function send(mode, key, params, json, headers){ |
var schema = document.getElementById('schema').value; |
if(!schema){ |
schema = 'public'; |
} |
var url = '/rest/' + schema + '/' + document.getElementById('table').value; |
if(key){ |
url += '/' + key; |
} |
if(params){ |
url += '?' + params; |
} |
document.getElementById('url').innerHTML = url; |
http_request = null; |
if(window.XMLHttpRequest){ |
http_request = new XMLHttpRequest(); |
}else{ |
http_request = new ActiveXObject("Msxml2.XMLHTTP"); |
} |
http_request.onreadystatechange = alert_json_out; |
http_request.open(mode, url, true); |
http_request.setRequestHeader("Content-type", 'text/json'); |
if(headers){ |
for(key in headers){ |
http_request.setRequestHeader(key, headers[key]); |
} |
} |
var start = document.getElementById('start').value; |
var num_rows = document.getElementById('num_rows').value; |
if(start || num_rows){ |
if(!start){ |
start = 0; |
} |
if(!num_rows){ |
num_rows = 999999999999-start; |
} |
http_request.setRequestHeader('Range', 'items=' + start + '-' + (parseInt(start) + parseInt(num_rows) - 1).toString()); |
} |
if(json){ |
http_request.setRequestHeader('Content-length', json.length); |
http_request.send(json); |
}else{ |
http_request.send(); |
} |
} |
function do_newkey(){ |
send('GET', null, 'method=newkey', null, null); |
} |
function do_retrieve(){ |
var key = document.getElementById('key').value; |
var father_key = document.getElementById('father_key').value; |
// if((key && father_key) || (!key && !father_key)){ |
// alert('Indicare la chiave del record oppure la chiave del record padre da selezionare'); |
// return; |
// } |
if(key){ |
send('GET', key, null, null, null); |
}else{ |
// send('GET', null, 'father_key=' + father_key, null, null); |
send('GET', null, null, null, null); |
} |
} |
function do_update(){ |
var key = document.getElementById('key').value; |
if(!key){ |
alert('Indicare la chiave del record da aggiornare'); |
return; |
} |
send('PUT', key, null, document.getElementById('json_in').value, { 'If-Match': '*'}); |
} |
function do_create(){ |
var key = document.getElementById('key').value; |
var father_key = document.getElementById('father_key').value; |
if(key){ |
send('PUT', key, 'father_key=' + father_key, document.getElementById('json_in').value, { 'If-None-Match': '*'}); |
}else{ |
send('PUT', null, 'father_key=' + father_key, document.getElementById('json_in').value, { 'If-None-Match': '*'}); |
} |
} |
function do_delete(){ |
var key = document.getElementById('key').value; |
if(!key){ |
alert('Indicare la chiave del record da cancellare'); |
return; |
} |
send('DELETE', key, null, null); |
} |
</script> |
/tags/2.0/htdocs/test/test_charset.html |
---|
0,0 → 1,51 |
<%args> |
$test => undef |
</%args> |
<%perl> |
use utf8; |
print STDERR 'test prima '.(utf8::is_utf8($test) ? 'utf ' : 'no utf')." [$test]\n"; |
print STDERR 'test test_charset '.(utf8::is_utf8($test) ? 'utf ' : 'no')." [$test]\n"; |
if(!$test){ |
$test = 'àèìòù'; |
}else{ |
$test .= ' is ok?'; |
} |
$m->clear_buffer; |
$r->content_type('text/html; charset=utf-8'); |
# test database |
my $dbh = Auth_AC::AuthCookieHandler->connect($r); |
$dbh->do(q{delete from public.logs where id=-1}); |
$dbh->commit; |
$dbh->do(q{insert into public.logs (id, field) values (-1, 'àèìòù') }); |
$dbh->commit; |
my $sth = $dbh->prepare(q{select field from public.logs where id=-1}); |
$sth->execute; |
my $field = $sth->fetchrow_arrayref->[0]; |
$dbh->do(q{delete from public.logs where id=-1}); |
$dbh->commit; |
</%perl> |
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
<html> |
<head> |
<title>Gestione presenze sugli impianti di depurazione</title> |
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8"> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
</head> |
<body id="bodyMasonSql" scroll=""> |
<br> |
<br> |
<h2>Dal file html: àèìòù</h2> |
<h2>Dal database: <%$field%></h2> |
<br> |
<form action="#" method="get" accept-charset="UTF-8" enctype="multipart/form-data"> |
<input name="test" value="<%$test%>"> |
<input type="submit" value="TEST"> |
</form> |
</body> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_my_alert.html |
---|
0,0 → 1,11 |
<p id="bingo">BINGO ?</p> |
<script> |
masonSql.once('ready', function(){ |
var message = 'BINGO2!, \nchiamata <b>my_alert</b><br>Test.'; |
// my_alert('1 first ' + message); |
my_alert('2 ' + message ,'html'); |
// my_alert('3 ' + message ,'txt'); |
// my_alert('4 ' + message ,'pre'); |
// my_alert('5 last ' + message ,'alert'); |
}); |
</script> |
/tags/2.0/htdocs/test/test_simulate_keypress.html |
---|
0,0 → 1,35 |
<input id="Input" type"test"><br> |
<hr> |
<button onClick="emit_key('Input', 65);">emit_key('Input', 65);</button> |
<button onClick="insert_key('Input', 65);">insert_key('Input', 65)</button> |
<script> |
function emit_key(target_name, charcode){ |
require(["dojo/on", "dojo/dom"], function(on, dom){ |
var target = dom.byId(target_name); |
// Send event |
target.focus(); |
on.emit(target, 'keydown', { |
bubbles: true, |
cancelable: true, |
// keyCode: charcode, |
charCode: charcode |
// ,keyCodeArg : charcode |
// ,charCodeArg: 0 |
}); |
}); |
} |
function insert_key(target_name, charcode){ |
require(["dojo/on", "dojo/dom"], function(on, dom){ |
var target = dom.byId(target_name); |
target.focus(); |
var evt = document.createEvent("KeyboardEvent"); |
evt.initKeyEvent("keypress", true, true, null, false, false, false, false, 0, charcode); |
target.dispatchEvent(evt); |
}); |
} |
</script> |
/tags/2.0/htdocs/test/test_json.html |
---|
0,0 → 1,146 |
<%once> |
use JSON; |
</%once> |
<%perl> |
</%perl> |
% if (!scalar(keys(%ARGS))) { |
<html> |
<head> |
<script src="/lib/library.js"> |
</script> |
<script src="/lib/httpRequestMason.js"> |
</script> |
% if(!$Session{Browser}->firefox || $Session{Browser}->version < 3.5){ |
% # non necessaria in Firefox 3.5+ (https://developer.mozilla.org/En/Using_native_JSON) |
<script src="/lib/json.js"> |
</script> |
% }else{ |
<!-- USE NATIVE JSON --> |
% } |
</script> |
<script> |
function timeoutCallback(str, contextID) |
{ |
var parsed = JSON.parse(str); |
log(dumpObj(parsed)); |
} |
function log(str) |
{ |
var visualizer = document.getElementById("visualizer"); |
visualizer.innerHTML += str; |
} |
function getObj() |
{ |
var toSend = new Object(); |
toSend.obj = eval(document.getElementById("tArea").value); |
toSend.field = document.getElementById("toMod").value; |
toSend.fValue = eval(document.getElementById("newVal").value); |
return toSend; |
} |
function dumpObj(obj) |
{ |
return dObj(obj, "Object", "\t", 0); |
} |
function dObj(obj, name, indent, depth) |
{ |
var MAX_DUMP_DEPTH = 20; |
if (depth > MAX_DUMP_DEPTH) |
{ |
return indent + name + ": <Maximum Depth Reached><br/>"; |
} |
if (typeof obj == "object") |
{ |
var child = null; |
var output = indent + name + "<br/>"; |
indent += "\t"; |
for (var item in obj) |
{ |
try |
{ |
child = obj[item]; |
} |
catch (e) |
{ |
child = "<Unable to Evaluate>"; |
} |
if (typeof child == "object" && (item != 'hReqMason_obj')) |
{ |
output += dObj(child, item, indent, depth + 1); |
} |
else |
{ |
output += indent + item + ": " + child + "<br/>"; |
} |
} |
return output; |
} |
else |
{ |
return obj; |
} |
} |
function multipleExec() |
{ |
hReqMason_Execute('/test/test_json.html', timeoutCallback, 'prova', getObj()) |
hReqMason_Execute('/test/test_json.html', timeoutCallback, 'prova', getObj()) |
hReqMason_Execute('/test/test_json.html', timeoutCallback, 'prova', getObj()) |
hReqMason_Execute('/test/test_json.html', timeoutCallback, 'prova', getObj()) |
hReqMason_Execute('/test/test_json.html', timeoutCallback, 'prova', getObj()) |
} |
</script> |
<title> |
Test JSON |
</title> |
</html> |
<body> |
<H1>test_json.html</H1> |
<form id="form" name="form"> |
<label> |
Oggetto javascript: |
</label> |
<br/> |
<textarea id="tArea" cols="50" rows="30">new (function (){this.field = "string";})();</textarea> |
<br/> |
<label> |
Campo da modificare: |
</label> |
<input type="input" id="toMod"/> |
<label> |
Valore: |
</label> |
<input type="input" id="newVal"> |
<br/> |
<div id="visualizer"></div> |
<br/> |
<input type="button" value="Submit" onClick="javascript:multipleExec();"/> |
</form> |
</body> |
</html> |
<%perl> |
} |
else |
{ |
my $content; |
$r->read($content, $r->header_in('Content-length')); |
my $obj = jsonToObj($content); |
if ($obj->{"fValue"}) |
{ |
$obj->{"obj"}{"$obj->{'field'}"} = $obj->{"fValue"}; |
} |
else |
{ |
delete $obj->{"obj"}{"$obj->{'field'}"}; |
} |
$r->content_type('text/plain'); |
$m->print(objToJson($obj)); |
} |
</%perl> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_tooltip.html |
---|
0,0 → 1,23 |
<html> |
<h2>test string.comp</h2> |
<br> |
<& /input/string.comp, id => 'test1', rows => 4, cols => 20, size => 5, length => 7 &> |
<br> |
<& /input/string.comp, id => 'test2', size => 22 &> |
<script> |
dojo.require("dijit.Tooltip"); |
new dijit.Tooltip({ |
connectId: ['test1'], |
showDelay: <% $r->dir_config('TooltipDelay') %>, |
label: '<% 'Esempio di tooltip molto lungo<br> |
che risiede su più righe<br> |
altra riga<br> |
fine ultima riga.'|js%>' |
}); |
new dijit.Tooltip({ |
connectId: ['test2'], |
showDelay: <% $r->dir_config('TooltipDelay') %>, |
label: 'Altro esempio <b>bold</b> <font color="red">RED</font>' |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/test_JST.html |
---|
0,0 → 1,48 |
<h1>Test JavaScript Dojo Templates</h1> |
<p> Vedi <b><a link="http://dojotoolkit.org/reference-guide/dojox/dtl.html">http://dojotoolkit.org/reference-guide/dojox/dtl.html</a></b></p> |
<br> |
<br> |
Template:<br> |
<textarea rows="8" cols="80"><& .template1 &></textarea><br> |
<br> |
Textarea id:result<br> |
<textarea id ="result" rows="4" cols="80">.....</textarea> |
<script> |
dojo.require('dojox.dtl.filter.strings'); |
dojo.require('dojox.dtl.Context'); |
// filtro custom vedi esempio: http://code.google.com/p/dools/source/browse/trunk/dools/docs/widget/_util.js |
var masonsql_test = { |
dtl: { |
filter: { |
js: function(/*String*/ str){ |
return str.replace(/\'/gm, '\\\'').replace(/\n/g, '\\n'); |
} |
} |
} |
}; |
dojo.provide('masonsql_test.dtl.filter'); |
dojox.dtl.register.filters('masonsql_test.dtl', { |
'filter': ['js'] |
}); |
var html = '<% $m->scomp('.template1') |js%>'; |
var MyData = { |
MyDescr: "Descrizione (\'intelligente\')\nsu più \'righe\'" |
}; |
var templateObj = new dojox.dtl.Template(html); |
var template = templateObj.render(new dojox.dtl.Context(MyData)); |
document.write(template); |
</script> |
</body> |
%# |
%# |
%# |
<%def .template1> |
<script> |
var X = '\'pippo\' e \'pluto\''; |
dojo.byId('result').value = 'BINGO! {{MyDescr|js|safe}} di '+ X; |
</script> |
</%def> |
/tags/2.0/htdocs/test/test_block.html |
---|
0,0 → 1,47 |
<html> |
<head> |
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8"> |
<title>Test</title> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
<link rel="stylesheet" href="/css/menu.css" type="text/css"> |
<meta name="AUTHOR" content="Brugnara ing. Guido - gdo@leader.it"> |
<meta name="COPYRIGHT" content="Leader.IT di Guido Brugnara; Strada della Pozzata, 41 - Villazzano; 38123 TRENTO (ITALY); info@leader.it"> |
</head> |
<body> |
<form name="main" onsubmit="return false;"> |
<hr> |
<& /input/parameters.comp, id => 'test1' &> |
<hr> |
<input type="button" name="visCampi" id="visCampi" value="Visualizza campi form 'main'" onClick="visualizzaCampi('main')"> |
</form> |
<script> |
// ritorna il valore del campo specificato |
function get_value(input){ |
if(input.type=='checkbox'){ |
return(input.checked ? 1 : 0); |
} |
if(input.get_value){ |
// se definito il metodo get_value lo utilizzo ... |
return input.get_value(); |
} |
return input.value; |
} |
function visualizzaCampi(form){ |
var Form = document.forms[form]; |
var S = "Forms is "+document.forms.length+"["; |
for(var I=0; I<document.forms.length; I++){ |
S+=document.forms[I].name+","; |
} |
S+="]\n"; |
S+="Form "+Form+" campi "+Form.elements.length+"\n\n" |
for(var I = 0; I<Form.elements.length; I++){ |
S+=" "+I+": name='"+Form.elements[I].name+"' id='"+Form.elements[I].id+ |
"' value='"+get_value(Form.elements[I])+"'\n"; |
} |
alert(S); |
} |
</script> |
</body> |
</html> |
/tags/2.0/htdocs/test/test_select_multiple.html |
---|
0,0 → 1,32 |
<html> |
<head> |
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=utf-8"> |
<title>Test</title> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
<link rel="stylesheet" href="/css/menu.css" type="text/css"> |
<meta name="AUTHOR" content="Brugnara ing. Guido - gdo@leader.it"> |
<meta name="COPYRIGHT" content="Leader.IT di Guido Brugnara; Strada della Pozzata, 41 - Villazzano; 38123 TRENTO (ITALY); info@leader.it"> |
</head> |
<body> |
<%perl> |
use Data::Dumper; |
my $par = Dumper(\%ARGS, \@_); |
</%perl> |
<form name="main"> <onsubmit="return false;"> |
<textarea rows="12" cols="50"> |
<%$par%> |
</textarea> |
<select multiple name="sel" id="sel" xonchange="alert(this.value)"> |
<option value=""></option> |
<option value="1">uno</option> |
<option value="2">due</option> |
<option value="3">tre</option> |
<option value="4">quattro</option> |
<option value="5">cinque</option> |
</select> |
<input type="submit" value="go"> |
</form> |
</body> |
</html> |
/tags/2.0/htdocs/test/test_method_return_hash.html |
---|
0,0 → 1,27 |
<HTML> |
<p><cite> |
Esempio di utilizzo di un metodo con return di una hash |
</cite></p> |
<%method TEST> |
<%args> |
$param |
</%args> |
TE\ |
% my %H = ( Pippo => 'pluto', Minny => 99); |
ST<%$param%>\ |
% return %H; |
</%perl>#]</%method>\ |
% my %Test = $m->comp('SELF:TEST', param => 1); |
% my $test = Dumper(\%Test); |
=<% $test %><br> |
% %Test = $m->current_comp->call_method('TEST', param => 2); |
% $test = Dumper(\%Test); |
=<% $test %><br> |
<p><cite> |
Qui viene intercettato l'output della chiamata: |
</cite></p> |
% my $store; |
% %Test = $m->comp({store => \$store},'SELF:TEST', param => 3); |
% $test = Dumper(\%Test); |
<% $store %>=<% $test %><br> |
</HTML> |
/tags/2.0/htdocs/test/test_textarea.html |
---|
0,0 → 1,12 |
<H1>test_select.html</H1> |
<hr> |
<form name="menu"> |
Impianto:<br> |
<& /input/string.comp, id =>'Area_testo', |
description=>'Area di testo', |
rows => 10, cols => 30, value => "Esempio\nriga 2\nriga 3\nultima riga (€è[ò@ò#°)" &> |
</form> |
<hr> |
<%flags> |
inherit => '../autohandler' |
</%flags> |
/tags/2.0/htdocs/test/test_variabile_detail.html |
---|
0,0 → 1,97 |
<%args> |
$include => undef |
</%args> |
% if($include){ |
<H1>INCLUSIONE INCLUSIONE INCLUSIONE INCLUSIONE</H1> |
<H2>INCLUSIONE INCLUSIONE INCLUSIONE INCLUSIONE</H2> |
% }else{ |
<H1>test:</H1> |
<h2>Valutazione caricamento dinamico record da campo <%'<div/>'|h%>, suddiviso in verticale da campi <%'<span/>'|h%></h2> |
<form name="my_form"> |
<div id="divs" style="background-color: #3affee;"> |
<p>Paragrafo all'interno di <b>divs</b></p> |
del testo all'interno di <b>divs</b><br> |
<div id="spans" style="background-color: #ffffff;"> |
% $Global{'Style_span.test_variabile_detail'}="border: 2px solid blue; margin:0px; padding:0px; cursor:help;"; |
% for(my $I=0; $I<5; $I++){ |
<span id="s<%$I%>" class="test_variabile_detail">span area <%$I%></span>\ |
% } |
</div> |
<div id="div_1" style="background-color: #ffffff;"> |
div_1 |
</div> |
<div id="div_2" style="background-color: #ff1faf;"> |
div_2 |
</div> |
</div> |
</form> |
<script src=""></script> |
<script> |
// test manipolazione elementi div singoli |
var div1 = document.getElementById('div_1'); |
div1.innerHTML='BINGO'; |
div1.style.backgroundColor='#a2a4a6'; |
div1.style.color='#ffffff'; |
// test gestione elenco elementi div |
var divs = document.getElementById('divs'); |
// il nome del TAG può essere indifferentemente minuscolo o maiuscolo |
var elenco = divs.getElementsByTagName('div'); |
for(var i=0; i<elenco.length; i++){ |
elenco[i].innerHTML=elenco[i].innerHTML+' ecc. ecc.'; |
} |
// test aggiunta di un nuovo elemento |
for(var i=10; i>0; i--){ |
var clone = div1.cloneNode(false); |
clone.innerHTML='<span style="color: yellow;">duplicato</span> n° '+i; |
clone.id="dup"+i; |
clone.numRecord=i; |
divs.appendChild(clone); |
} |
// test append elemento non duplicato ??? |
div1.innerHTML='BINGO test elemento non duplicato che si sposta di posizione'; |
// l'effetto in Mozilla ed IE6.0 è lo spostamento del <div> |
divs.appendChild(div1); |
// test cancellazione |
divs.removeChild(document.getElementById('div_2')); |
divs.removeChild(document.getElementById('dup6')); |
// test scambio di due <div> adiacenti |
var basso=document.getElementById('dup3'); |
basso.innerHTML=basso.innerHTML+' era basso ... test inserimento elemento di input: <select id="sel"><option>uno</option><option>due</option></select>'; |
var alto=document.getElementById('dup4'); |
alto.innerHTML=alto.innerHTML+' era alto'; |
divs.insertBefore(basso, alto); |
// test duplicazione elemento di input |
var sel=document.getElementById('sel'); |
var sel2 = sel.cloneNode(true); |
sel2.id='sel2'; |
alto.innerHTML=alto.innerHTML+'... test inserimento elemento clonato di input:'; |
alto.appendChild(sel2); |
// modifico il testo aggiungento info tra [] sull'attributo 'numRecord' |
// ed i valori di offset relativi al 'parent' |
var elenco = divs.getElementsByTagName('DIV'); |
for(var i=0; i<elenco.length; i++){ |
var elem=elenco[i]; |
elem.innerHTML=elem.innerHTML+'['+elem.numRecord+', H'+elem.offsetHeight+', L'+elem.offsetLeft+', T'+elem.offsetTop+', W'+elem.offsetWidth+']'; |
} |
divs.innerHTML=divs.innerHTML+'['+divs.numRecord+', H'+divs.offsetHeight+', L'+divs.offsetLeft+', T'+divs.offsetTop+', W'+divs.offsetWidth+']'; |
function LoadRemote(Div, Url, params){ |
Div.disabled = true; |
hReqMason_LoadTimeout(Div, 15000, pageTimeoutLoad, null, Url, params); |
} |
</script> |
<hr> |
<form> |
<input type="button" value="Includi documento remoto nel div" |
onClick="LoadRemote(document.getElementById('dup3'),'/test/test_variabile_detail.html?include=1','')"> |
</form> |
% } |
<%init> |
&LoadHeader('/lib/hReqMason_ClientMason.js'); |
</%init> |
/tags/2.0/htdocs/test/test_div_scroll2.html |
---|
0,0 → 1,61 |
<%flags> |
inherit => undef |
</%flags> |
<div id="top"> |
Riga in cima . . . . . . . . . |
</div> |
<div id="DivBody" class="INPUTDIV" style=" |
border: inset 2px #aa0e00; |
height: 100px; |
width: 600; |
overflow: auto; |
"> |
<p> |
% for(my $I=0; $I<100; $I++){ |
Pippo e Pluto vanno a spasso per la città. |
% } |
</p> |
Una riga<br> |
Due righe<br> |
Tre righe<br> |
Ultima riga. |
</div> |
<div id="bottom"> |
Riga centrale . . . . . . . . . |
</div> |
In Internet Explorer il DIV sottostante ha le barre di scorrimento bloccate. |
<div disabled id="DivBody2" style=" |
border: inset 2px; |
height: 100px; |
width: 600; |
overflow: auto; |
"> |
</div> |
<div id="bottom"> |
Riga in basso . . . . . . . . . |
</div> |
<script> |
var DivBody = document.getElementById('DivBody'); |
var DivBody2 = document.getElementById('DivBody2'); |
DivBody2.innerHTML = DivBody.innerHTML; |
function SetSize(){ |
// adatto le dimensioni |
var newHeight; |
if(document.body.clientHeight < document.body.offsetHeight){ |
newHeight = document.body.clientHeight - document.body.scrollHeight + DivBody.offsetHeight; |
}else{ |
newHeight = document.body.clientHeight - document.body.offsetHeight + DivBody.offsetHeight; |
} |
DivBody.style.height = newHeight + 'px'; |
} |
window.onload = function(){ |
// SetSize(); |
}; |
window.onresize = function(){ |
SetSize(); |
}; |
</script> |
/tags/2.0/htdocs/test/test_disabled.html |
---|
0,0 → 1,68 |
<HTML> |
<HEAD> |
<STYLE type="text/css"> |
input[disabled], input[readonly], select[disabled], select[readonly], checkbox[disabled], checkbox[readonly], textarea[disabled], textarea[readonly]{ |
background-color: #dcfcfc; |
border: #3532ff 1px solid; |
color: #ff00ff; |
cursor: default; |
} |
</STYLE> |
</HEAD> |
<BODY> |
TEST:<br> |
Disabled: <input type="text" value="PROVA TESTO DISABLED" disabled /> |
<br> |
Readonly: <input type="text" value="PROVA TESTO DISABLED" readonly /> |
<br> |
<br> |
Disabled: <input type="checkbox" checked disabled /> |
<br> |
Readonly su click: <input type="checkbox" checked onclick="return false;" /> |
<br> |
Readonly su change: <input id="checkbox_ro" type="checkbox" onchange="this.ripristina();" /> |
<br> |
<br> |
Disabled: <select disabled > |
<option >riga 1</option> |
<option >riga 2</option> |
</select> |
<br> |
Readonly: <select id="sel_ro" onclick="return false;" onchange="this.ripristina();" onclick="return false;"> |
<option value="1" >riga 1</option> |
<option value="2" >riga 2</option> |
<option value="3" selected >riga 3</option> |
</select> |
<br> |
<script> |
var sel_ro = document.getElementById('sel_ro'); |
var checkbox_ro = document.getElementById('checkbox_ro'); |
sel_ro.set_value = function (value){ |
this.widgetValue = value; |
this.value = value; |
} |
sel_ro.ripristina = function (){ |
this.value = this.widgetValue; |
} |
checkbox_ro.set_value = function (value){ |
this.widgetValue = value; |
this.checked = value; |
} |
checkbox_ro.ripristina = function (){ |
this.checked = this.widgetValue; |
} |
sel_ro.set_value(2); |
checkbox_ro.set_value(1); |
</script> |
</BODY> |
/tags/2.0/htdocs/test/test_filesystem.html |
---|
0,0 → 1,34 |
<h2>test ActiveX Scripting.FileSystemObject</h2> |
test1: <& /input/string.comp, id=>'test1', rows=>20, cols=>80 &> |
<br> |
<script> |
var test1 = document.getElementById('test1'); |
function ShowDriveList(){ |
var fso, s, n, e, x; |
fso = new ActiveXObject("Scripting.FileSystemObject"); |
e = new Enumerator(fso.Drives); |
s = ""; |
for (; !e.atEnd(); e.moveNext()){ |
x = e.item(); |
s = s + x.DriveLetter; |
s += " - "; |
if (x.DriveType == 3) |
n = x.ShareName; |
else if (x.IsReady) |
n = x.VolumeName; |
else |
n = "[L'unità non è pronta]"; |
s += n + "\n"; |
} |
return(s); |
} |
</script> |
<input type="button" value="ShowDriveList" onClick="document.getElementById('test1').value=ShowDriveList();"> |
/tags/2.0/htdocs/test/test_upload_link.html |
---|
0,0 → 1,60 |
<html> |
<%args> |
$upload => 0 |
</%args> |
<h2>test Upload link file</h2> |
<br> |
<FORM ACTION="/test/test_upload_link.html?upload=1" XXXtarget="_blank" name="upl_sens_area" |
METHOD="POST" ENCTYPE="multipart/form-data"> |
<input type="file" name="my_file" lenght=25><br> |
<INPUT TYPE="SUBMIT" VALUE="Load file"> |
</FORM> |
%# $m->out('Oggetto $r => ',Dumper($r)); |
% if($upload == 1){ |
% if($r->dir_config('MasonArgsMethod') eq 'CGI'){ |
% my $query = $m->cgi_object(); |
<hr> |
% my $fh = $query->param('my_file'); |
% if(!$fh && $query->cgi_error){ |
% die $query->cgi_error; |
% } |
% if($fh){ |
% my $type = $query->uploadInfo($fh)->{'Content-Type'}; |
% my $tempname = $query->tmpFileName($fh); |
% my $disposition = $query->uploadInfo($fh)->{'Content-Disposition'}; |
Upload <b>type:</b><%$type%> <b>tempname:</b><%$tempname%> <b>disposition:</b><%$disposition%>: |
<pre> |
% link($tempname, "$tempname.test_link") or |
% die sprintf "link from '%s' failed: $!", $query->tmpFileName($fh); |
% open TESTFILE, "<$tempname.test_link"; |
% while(<TESTFILE>){ |
% $m->out($_); |
% } |
% close(TESTFILE); |
% unlink "$tempname.test_link"; |
</pre> |
<hr>end. |
% } |
% }else{ |
% my $upload = $r->upload('my_file'); |
<hr> |
% my $size = $upload->size; |
% my $type = $upload->type; |
% my $name = $upload->name; |
% my $filename = $upload->filename; |
% my $tempname = $upload->tempname; |
% $upload->link("$tempname.test_link") or |
die sprintf "link from '%s' failed: $!", $tempname; |
Upload <b>file:</b><%$filename%></b> <b>tempname:</b><%$tempname%> <b>name:</b><%$name%> <b>type:</b><%$type%> <b>size:</b><%$size%>: |
<pre> |
% open TESTFILE, "<$tempname.test_link"; |
% while(<TESTFILE>){ |
% $m->out($_); |
% } |
% close(TESTFILE); |
% unlink "$tempname.test_link"; |
</pre> |
% } |
<hr>end. |
% } |
</html> |
/tags/2.0/htdocs/test/test_variables.html |
---|
0,0 → 1,33 |
<html> |
<h2>test_variables.comp</h2> |
Si vuole verificare come le veriabili Mason sono visibili all'interno di un metodo Mason |
<br> |
Session{Test} = '<% $Session{Test} %>'<br> |
<&SELF:METODO&> |
<hr> |
<%method METODO> |
METODO->Session{Test} = '<% $Session{Test} %>'<br> |
METODO->Session{AltreVar}->{Pippo} = '<% $Session{AltreVar}->{Pippo} %>'<br> |
METODO->Session{ARGS} = '<% Dumper($Session{ARGS}) %>'<br> |
<hr> |
<&SELF:METODO2&> |
</%method> |
<%method METODO2> |
METODO2->Session{Test} = '<% $Session{Test} %>'<br> |
METODO2->Session{AltreVar}->{Pippo} = '<% $Session{AltreVar}->{Pippo} %>'<br> |
</%method> |
<%init> |
$Session{ARGS} = \%ARGS; |
</%init> |
<%once> |
# %Session è una variabile globase. |
my %AltreVar = (Pinco => 'Pallo', Pippo => 'Pluto'); |
$Session{AltreVar} = \%AltreVar; |
$Session{Test} = 'BINGO'; |
</%once> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_checkbox.html |
---|
0,0 → 1,17 |
<html> |
<h2>test checkbox.comp</h2> |
Test: <& /input/checkbox.comp, id => 'test1', value => 1 &> |
<br> |
<br> |
Test readonly: |
<& /input/checkbox.comp, id => 'test2', readonly => 1 , value => 1 &> |
<input type="button" value="change read/write" onclick="change_ro();"> |
<script> |
function change_ro(){ |
var test2 = document.getElementById('test2'); |
test2.Readonly(!test2.Readonly()); |
} |
</script> |
</html> |
/tags/2.0/htdocs/test/test_span_focus.html |
---|
0,0 → 1,27 |
<br><br> |
<span id="test_span" |
onfocus="this.className = 'widgetRwRequiredFocus';alert('focus');" |
onkeydown="alert('keydown');" |
onblur="this.className = 'widgetRwRequired';alert('blur');" |
class="widgetRwRequired" |
>ESEMPIO DI SPAN CHE CAMBIA COLORE A SECONDA CHE SIA O MENO SELEZIONATA</span> |
<br> |
<br> |
<& /input/string.comp, id => 'input_test1' &> |
<br> |
<& /input/string.comp, id => 'input_test2' &> |
<br> |
<div id="buf" ></div> |
<script> |
window.focus(); |
var test_span = document.getElementById('test_span'); |
var buf = document.getElementById('buf'); |
window.setTimeout("test_span.focus();", 1000); |
document.onkeypress = function (evt){ |
var input = Input_Event(evt); |
buf.innerHTML = 'input:' + input.id + ' ?:' + (evt.target ? evt.target.id : document.activeElement.id) + ' keyCode:' + evt.keyCode +' chCode:' + evt.chCode +'<br>'; |
return false; |
} |
</script> |
/tags/2.0/htdocs/test/test_readOnly.html |
---|
0,0 → 1,39 |
<h2>test readOnly su componenti /input/xxxx.comp</h2> |
text: <& /input/string.comp, id => 'test1', rows => 4, cols => 20, size => 5, length => 7, value => qq{riga uno\nriga 2\nriga 3} &> |
<br> |
select: <&| /input/select.comp, id => 'test2', &> |
<option value="1">RIGA uno</option> |
<option value="2">RIGA due</option> |
<option value="3">RIGA tre</option> |
</&> |
<br> |
date: <& /input/date.comp, id => 'test3', value => '25/12/2000' &> |
<hr> |
span:<& /input/span.comp, id =>'test4', description=>'Test oggetto span', style=>'background-color:yellow; width:400;', value => '<SPAN>BINGO</SPAN>' &> |
<hr> |
check:<& /input/checkbox.comp, id => 'test5', value => 1 &> |
<hr> |
<br> |
<br> |
<script> |
var test1 = document.getElementById('test1'); |
var test2 = document.getElementById('test2'); |
var test3 = document.getElementById('test3'); |
var test4 = document.getElementById('test4'); |
var test5 = document.getElementById('test5'); |
test2.style.backgroundColor='yellow'; |
test2.set_value(2); |
test2.style.font_color='blue'; |
function set_readonly(setting){ |
test1.Readonly(setting); |
test2.Readonly(setting); |
test3.Readonly(setting); |
test4.Readonly(setting); |
test5.Readonly(setting); |
} |
window.setTimeout("set_readonly(true);", 1); |
</script> |
<input type="button" value="read" onClick="set_readonly(true);"> |
<input type="button" value="write" onClick="set_readonly(false);"> |
/tags/2.0/htdocs/test/test_timestamp.html |
---|
0,0 → 1,49 |
<h2>test_timestamp.html</h2> |
<& /input/timestamp.comp, |
id => 'test_timestamp', |
description => 'Descrizione timestamp', |
value => '', |
readonly => 1, |
onchange => "alert('onchange timestamp id:'+this.id+' value:'+this.get_value());" |
&> |
|
<& /input/string.comp, |
id => 'string', |
description => 'input string', |
length => 25, |
readonly => 1 |
&> |
<br/> |
<& /input/button.comp, |
id => 'button_ro', |
description => 'button', |
value => 'button', |
caption => 'Readonly', |
readonly => 0, |
onclick => "var ts = document.getElementById('test_timestamp'); var ro = !ts.Readonly(); ts.Readonly(ro); document.getElementById('string').Readonly(ro); document.getElementById('button_sv').disabled = ro; document.getElementById('button_gv').disabled = ro; document.getElementById('button_em').disabled = ro;" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set_value', |
onclick => "var ts = document.getElementById('test_timestamp'); if (document.getElementById('string').value != ''){ ts.set_value(document.getElementById('string').value); }" |
&> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get_value', |
onclick => "var ts = document.getElementById('test_timestamp'); if (ts.get_value() != ''){ document.getElementById('string').value = ts.get_value(); }" |
&> |
<& /input/button.comp, |
id => 'button_em', |
description => 'button', |
value => 'button', |
caption => 'Empty', |
onclick => "document.getElementById('test_timestamp').set_value(''); document.getElementById('string').value = '';" |
&> |
% push @Script_buffer, "document.getElementById('button_sv').disabled = 1;\ndocument.getElementById('button_gv').disabled = 1;\ndocument.getElementById('button_em').disabled = 1;\n"; |
/tags/2.0/htdocs/test/test_time.html |
---|
0,0 → 1,47 |
<h2>test_time.html</h2> |
<& /input/time.comp, |
id => 'test_time', |
description => 'Descrizione time', |
value => '', |
readonly => 1 |
&> |
|
<& /input/string.comp, |
id => 'string', |
description => 'input string', |
length => 25, |
readonly => 1 |
&> |
<br/> |
<& /input/button.comp, |
id => 'button_ro', |
description => 'button', |
value => 'button', |
caption => 'Readonly', |
readonly => 0, |
onclick => "var ts = document.getElementById('test_time'); var ro = !ts.Readonly(); ts.Readonly(ro); document.getElementById('string').Readonly(ro); document.getElementById('button_sv').disabled = ro; document.getElementById('button_gv').disabled = ro; document.getElementById('button_em').disabled = ro;" |
&> |
|
<& /input/button.comp, |
id => 'button_sv', |
description => 'button', |
value => 'button', |
caption => 'Set_value', |
onclick => "var ts = document.getElementById('test_time'); if (document.getElementById('string').value != ''){ ts.set_value(document.getElementById('string').value); }" |
&> |
|
<& /input/button.comp, |
id => 'button_gv', |
description => 'button', |
value => 'button', |
caption => 'Get_value', |
onclick => "var ts = document.getElementById('test_time'); if (ts.get_value() != ''){ document.getElementById('string').value = ts.get_value(); }" |
&> |
<& /input/button.comp, |
id => 'button_em', |
description => 'button', |
value => 'button', |
caption => 'Empty', |
onclick => "document.getElementById('test_time').set_value(''); document.getElementById('string').value = '';" |
&> |
% push @Script_buffer, "document.getElementById('button_sv').disabled = 1;\ndocument.getElementById('button_gv').disabled = 1;\ndocument.getElementById('button_em').disabled = 1;\n"; |
/tags/2.0/htdocs/test/test_background_color.html |
---|
0,0 → 1,61 |
<html> |
<h2>test string.comp - background color (status)</h2> |
<& /input/string.comp, |
id => 'Test1', |
rows => 4, |
cols => 20, |
length => 80 |
&> |
<br> |
<& /input/string.comp, |
id => 'Test2', |
rows => 1, |
size => 20, |
length => 7 |
&> |
<script> |
// colori sfondo widget di base |
window.status_colors = { |
Read: '#FFFFFF', |
Error: '#FFF0F0', |
Edit: '#F0FFF0', |
Alert: '#FFFFF0', |
Disabled: '#F0F0F0' |
}; |
// condizione di test con widget in sola lettura |
var Test1 = document.getElementById('Test1'); |
var Test2 = document.getElementById('Test2'); |
window.onload = function(){ |
Test1.widget_status = 'Disabled'; |
Test1.backgroundColor = '#FFF0F0'; |
Test1.Readonly(true); |
Test1.status_colors = {}; |
Test2.widget_status = 'Disabled'; |
Test2.Readonly(true); |
Test2.status_colors = {}; |
// colori sfondo modificati per il widget specifico |
Test2.status_colors.Error = '#FF9090'; |
} |
// test implemetazione metodo .status |
function Input_status(status){ |
if(status == null){ |
return this.widget_status; |
} |
this.style.backgroundColor = this.status_colors[status] ? this.status_colors[status] : window.status_colors[status]; |
} |
Test1.status = Input_status; |
Test2.status = Input_status; |
</script> |
<hr> |
<input type="button" value="Change Read/write" onclick="Test1.Readonly(!Test1.Readonly()); Test2.Readonly(!Test2.Readonly());"><br> |
<br> |
<input type="button" value="Read" onclick="Test1.status('Read'); Test2.status('Read');"><br> |
<input type="button" value="Error" onclick="Test1.status('Error'); Test2.status('Error');"><br> |
<input type="button" value="Edit" onclick="Test1.status('Edit'); Test2.status('Edit');"><br> |
<input type="button" value="Alert" onclick="Test1.status('Alert'); Test2.status('Alert');"><br> |
<input type="button" value="Disabled" onclick="Test1.status('Disabled'); Test2.status('Disabled');"><br> |
</html> |
/tags/2.0/htdocs/test/test_attributes.html |
---|
0,0 → 1,32 |
<html> |
<h2>test parameters.comp</h2> |
Utilizzo di parametri quali attributi di un metodo da ricercare anche nei componenti utilizzati al suo interno: |
<%method _attributes> |
<%args> |
$fetch_attrib => undef |
</%args> |
<%perl> |
return $ARGS{$ARGS{'fetch_attrib'}}; |
</%perl> |
</%method> |
<%method MyMethod_2> |
% my $ret = $m->comp('SELF:_attributes', fetch_continue => 0, myattrib => 'TROVATO!!!', %ARGS); |
% return $ret if $ret; |
CONTENUTO DEL METODO MyMethod_2<br> |
</%method> |
<%method MyMethod> |
% my $ret = $m->comp('SELF:MyMethod_2', param1 => 'PARAM1', param2 => 'PARAM2', %ARGS); |
% return $ret if $ret; |
CONTENUTO DEL METODO MyMethod<br> |
</%method> |
<hr> |
<& SELF:MyMethod &> |
<br> |
myattrib='<% $m->comp('SELF:MyMethod', fetch_attrib => 'myattrib') %>'<br> |
<hr> |
<br> |
/tags/2.0/htdocs/test/test_widget_status.html |
---|
0,0 → 1,86 |
<%flags> |
inherit => undef |
</%flags> |
<html> |
<head> |
<style type="text/css"> |
.widget { |
border-color: red; |
} |
.widgetRo { |
background-color: #FFFFFF; |
} |
.widgetRw { |
background-color: #F9F9FF; |
} |
.widgetRoError { |
background-color: #FFF0F0; |
} |
.widgetRwError { |
background-color: #FFC0C0; |
} |
.widgetRoAlert { |
background-color: #FFFFF0; |
} |
.widgetRwAlert { |
background-color: #FFFFC0; |
} |
.widgetRoDisabled { |
background-color: #F0F0F0; |
} |
.widgetRwDisabled { |
background-color: #D0D0D0; |
} |
.MyStyleRwError { |
background-color: #FF5070; |
} |
</style> |
</head> |
<h2>test widget_status - different style</h2> |
<textarea id="Test1" rows="4" cols="20"> |
</textarea> |
<script> |
var Test1 = document.getElementById('Test1'); |
Test1.baseClassName = 'MyStyle'; |
// test implementazione metodo .status |
Test1.set_status = function(status){ |
if(status != null){ |
this.widgetStatus = status; |
} |
// classe di base |
var className = ' widget'; |
// classe differenziata di base per stato attivo |
className += ' widget' + (this.readOnly ? 'Ro' : 'Rw') + this.widgetStatus; |
// classe differenziata per classe di widget o singolo widget |
className += ' ' + this.baseClassName + (this.readOnly ? 'Ro' : 'Rw') + this.widgetStatus; |
this.className = className; |
} |
Test1.Readonly = function(read){ |
if(read == null){ |
return this.readOnly; |
}else{ |
this.style.cursor = read ? 'default' : 'text'; |
this.readOnly = read; |
this.set_status(); |
return read; |
} |
} |
Test1.Readonly(true); // in sola lettura e |
Test1.set_status(''); // nessun stato particolare |
</script> |
<hr> |
<input type="button" value="Change Read/write" onclick="Test1.Readonly(!Test1.Readonly());"><br> |
<br> |
<input type="button" value="None" onclick="Test1.set_status('');"><br> |
<input type="button" value="Error" onclick="Test1.set_status('Error');"><br> |
<input type="button" value="Alert" onclick="Test1.set_status('Alert');"><br> |
<input type="button" value="Disabled" onclick="Test1.set_status('Disabled');"><br> |
</html> |
/tags/2.0/htdocs/test/test_button.htmls |
---|
0,0 → 1,11 |
<html> |
<h2>test button.comp</h2> |
<& /input/button.comp, |
id => 'test', |
caption => 'Test button', |
Value => 'BINGO', |
onclick => q|javascript: alert('Value=\"'+this.Value+'\"')| |
&> |
<br> |
</html> |
/tags/2.0/htdocs/test/test_div_scroll.html |
---|
0,0 → 1,38 |
<div id="top"> |
Riga top . . . . . . . . . |
</div> |
<div id="DivBody" style=" |
border: solid 2px #000e00; |
background: #fffffe; |
color:#000000; |
height: 999px; |
overflow: auto; |
"> |
% for(my $I=0; $I<300; $I++){ |
tigri fig gdh fvjhvg fdkjvbs dfkjvhbds kjfhvb ksdjfhbv ksdjfb vkjsdh fkvjh dfsvjhb dskjfhbv ksdj vkj dfsvkjs d<br> |
% } |
</div> |
<div id="bottom"> |
Riga bottom . . . . . . . . . |
</div> |
<script> |
var DivBody = document.getElementById('DivBody'); |
function SetSize(){ |
// adatto le dimensioni |
var newHeight; |
if(document.body.clientHeight < document.body.offsetHeight){ |
newHeight = document.body.clientHeight - document.body.scrollHeight + DivBody.offsetHeight; |
}else{ |
newHeight = document.body.clientHeight - document.body.offsetHeight + DivBody.offsetHeight; |
} |
DivBody.style.height = newHeight + 'px'; |
} |
window.onload = function(){ |
SetSize(); |
}; |
window.onresize = function(){ |
SetSize(); |
}; |
</script> |
/tags/2.0/htdocs/test/test_component.html |
---|
0,0 → 1,39 |
<h2>test component</h2> |
test1: |
<& /input/string.comp, |
id => 'component', |
rows => 1, |
cols => 20, |
size => 5, |
length => 7 |
&> |
<&| /input/select.comp, |
id => 'component_sel', style => 'display:none;' |
&> |
<option value="1">uno</option> |
<option value="2">due</option> |
<option value="3">tre</option> |
</&> |
<br> |
<hr> |
<br> |
<script> |
var component=document.getElementById('component'); |
component.sel=document.getElementById('component_sel'); |
component.SelectTypeInput = function (type){ |
switch(type){ |
case 'txt': |
this.style.display='inline'; |
this.sel.style.display='none'; |
break; |
case 'sel': |
this.sel.style.display='inline'; |
this.style.display='none'; |
break; |
default: |
alert("ERROR component.SelectTypeInput: type "+type+" not defined"); |
} |
} |
</script> |
<input type="button" value="TEXT" onClick="component.selectType('txt')"> |
<input type="button" value="SELECT" onClick="component.electType('sel')"> |
/tags/2.0/htdocs/test/test_get_attribute.html |
---|
0,0 → 1,16 |
<html> |
<h2>test .getAttribute('attributename')</h2> |
<input type="text" id="my_test" width="111" my_width="222" style="background-color:#fafafa;"> |
<textarea id="my_area" rows="6" cols="60"> |
</textarea> |
<script> |
var Input = document.getElementById("my_test"); |
document.getElementById("my_area").value = |
'width=' + Input.getAttribute('width') + |
' and my_width=' + Input.getAttribute('my_width') + |
'\n width:' + Input.width + ' and my_width:' + Input.my_width + |
'\n style="' + Input.getAttribute('style')+'"'; |
</script> |
</html> |
/tags/2.0/htdocs/test/test_include.include |
---|
0,0 → 1,3 |
<b>parte da includere</b> |
!INCLUDE IGNORE |
<br>parte da non includere |
/tags/2.0/htdocs/test/test_iframe.html |
---|
0,0 → 1,68 |
<%args> |
</%args> |
<html> |
<body> |
<H1>test_iframe.html</H1> |
<form name="form"> |
<input id="URL" value="https://localhost/"> |
<input value="Crea IFRAME" type="button" onClick="load_iframe(iframe, document.getElementById('URL').value); false;"> |
<input value="Info" type="button" onClick="display_messages('info'); false;"> |
</form> |
<script> |
function fnErrorTrap(sMsg,sUrl,sLine){ |
var oErrorLog = document.getElementById('oErrorLog'); |
oErrorLog.innerHTML="<b>An error was thrown and caught.</b><p>"; |
oErrorLog.innerHTML+="Error: " + sMsg + "<br>"; |
oErrorLog.innerHTML+="Line: " + sLine + "<br>"; |
oErrorLog.innerHTML+="URL: " + sUrl + "<br>"; |
return false; |
} |
window.onerror=fnErrorTrap; |
function display_messages(mess){ |
var MESS = mess + '\n'; |
MESS += 'iframe.src='+iframe.src+'\n'; |
MESS += 'iframe.readyState='+iframe.readyState+'\n'; |
MESS += 'iframe.contentWindow.readyState='+iframe.contentWindow.readyState+'\n'; |
MESS += 'iframe.contentWindow.document.body.innerHTML='+iframe.contentWindow.document.body.innerHTML+'\n'; |
alert(MESS); |
} |
function attach_event(obj, obj_descr){ |
obj.onactivate = function () { display_messages(obj_descr+' onactivate') } |
obj.onabort = function () { display_messages(obj_descr+' onabort') } |
obj.onerror = function () { display_messages(obj_descr+' onerror')} |
obj.onload = function () { display_messages(obj_descr+' onload')} |
} |
var containerName = "test"; |
var span = document.createElement('SPAN'); |
span.id = "SPAN" + containerName; |
document.body.appendChild( span ); |
var iframe = document.createElement('IFRAME'); |
iframe.name = containerName; |
iframe.height=300; |
iframe.width=600; |
span.appendChild( iframe ); |
attach_event(iframe, 'iframe'); |
attach_event(iframe.contentWindow,'iframe.contentWindow'); |
attach_event(iframe.contentWindow.document,'iframe.contentWindow.document'); |
function load_iframe(iframe, URL){ |
// iframe.location = URL; |
iframe.src = URL; |
// attach_event(iframe.contentWindow,'iframe.contentWindow'); |
// attach_event(iframe.contentWindow.document,'iframe.contentWindow.document'); |
} |
</script> |
<hr> |
<DIV ID="oErrorLog"> |
</body> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test.html |
---|
0,0 → 1,4 |
<script> |
<& /input/divselect.js &> |
</script> |
Test caricamento javascript |
/tags/2.0/htdocs/test/FCKeditor_2.3.tar.gz |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/test/test_select2.html |
---|
0,0 → 1,45 |
<%args> |
$edit => undef |
</%args> |
<H1>test_select.html</H1> |
<input type=button value="GO"> |
<script> |
</script> |
<form name="menu"> |
Sel1:<br> |
<&| /input/select.comp, id =>'Sel1', |
description=>'Elenco impianti', |
onchange => 'alert(\'BINGO\'); |', |
disabled => '1', |
buffer => 'Sel', |
#remote => 1, |
empty=>undef, |
width => '400px', |
# size => 5, |
style=>'background-color:#ffeeff; width:400;' |
&> |
<option>test 1</option> |
<option>test 2</option> |
<option>test 3</option> |
</&> |
<br> |
Sel2:<br> |
<&| /input/select.comp, id =>'Sel2', |
description=>'Elenco impianti', |
onchange => 'alert(\'BINGO\'); |', |
disabled => '1', |
buffer => 'Sel', |
#remote => 1, |
empty=>undef, |
width => '400px', |
size => 5, |
style=>'background-color:#ffeeff; width:400;' |
&> |
<option>test 1</option> |
<option>test 2</option> |
<option>test 3</option> |
</&> |
/tags/2.0/htdocs/test/test_codfisc_pi.html |
---|
0,0 → 1,8 |
<html> |
<h2>test string.comp</h2> |
<& /input/codfisc_pi.comp, |
id => 'test', |
description => 'Test inserimento P.I. o Codice Fiscale' |
&> |
<br> |
</html> |
/tags/2.0/htdocs/test/test_parameters.html |
---|
0,0 → 1,34 |
<html> |
<h2>test parameters.comp</h2> |
Esempio di chiamata di funzione(metodo) con passaggio di parametri in forma compatta dell'oggetto Object: |
<script> |
function myFunc(params_call){ |
// default values |
var params = { |
param1: 'parametro 1', |
param2: 'parametro 2', |
param3: 'parametro 3', |
param4: 'parametro 4', |
param5: 'parametro 5', |
} |
// overload params from call |
for(var elem in params_call){ |
params[elem] = params_call[elem]; |
} |
// use parameters |
document.write("<br>"); |
for(var elem in params){ |
document.write(elem+": '"+params[elem]+"'<br>"); |
} |
} |
myFunc({ |
param5: 'Palla', |
param8: 'Minny', |
param3: 'BINGO!!!' |
}); |
</script> |
</html> |
/tags/2.0/htdocs/test/test_object.html |
---|
0,0 → 1,62 |
<html> |
<head> |
</head> |
<body> |
<H1>test_object.html</H1> |
<script> |
function Constructor(id, descr){ |
this.descr = descr; |
this.id = id; |
this.alert = function(descr){ |
if(descr){ |
window.alert(this.id+' - '+descr); |
}else{ |
window.alert(this.id+' - '+this.descr); |
} |
} |
} |
function Test(){ |
alert('BINGO START'); |
} |
var OBJ = new Constructor('OBJ', 'Bingo Bongo'); |
window.setTimeout(Test,10); |
window.setTimeout(OBJ.alert,30); |
window.setTimeout(function(){OBJ.alert()},20); |
var MESS = 'BINGO STOP'; |
window.setTimeout(function(){OBJ.alert(MESS)},10); |
MESS = MESS + ' BINGONE, la variabile viene risolta all\'atto dell\'esecuzione'; |
</script> |
</body> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_XMLHttpRequest.html |
---|
0,0 → 1,95 |
<%args> |
</%args> |
<html> |
<head> |
<script src="/lib/httpRequestMason.js"></script> |
<script src="/lib/library.js"></script> |
</head> |
<body> |
<H1>test_XMLHttpRequest.html</H1> |
<form name="form" action="javascript: return false;"> |
<input id="URL" value="test.html"> |
<input value="Download" type="button" onClick="load_div(document.getElementById('URL').value); false;"> |
<input value="Info" type="button" onClick="display_messages(httpRequest, 'info'); false;"> |
</form> |
<div id="div"></div> |
<script> |
var div = document.getElementById('div'); |
var httpRequest; |
function httpRequest_onload(){ |
display_messages(this, 'httpRequest_onload'); |
return true; |
} |
function httpRequest_onerror(){ |
display_messages(this, 'httpRequest_onerror'); |
return true; |
} |
function fnErrorTrap(sMsg,sUrl,sLine){ |
var MESS = "An error was thrown and caught.\n"; |
MESS +="Error: " + sMsg + "\n"; |
MESS +="Line: " + sLine + "\n"; |
MESS +="URL: " + sUrl + "\n"; |
alert(MESS); |
return false; |
} |
window.onerror=fnErrorTrap; |
function display_messages(httpRequest, mess){ |
var MESS = mess + '\n'; |
MESS += 'httpRequest.readyState='+httpRequest.readyState+' '; |
switch(httpRequest.readyState) { |
case 1,2,3: |
MESS += 'Bad Ready State: '+httpRequest.status; |
break; |
case 4: |
if(httpRequest.status !=200) { |
MESS +='The server respond with a bad status code: '+httpRequest.status; |
} |
break; |
} |
MESS += '\n'; |
MESS += 'httpRequest.statusText='+httpRequest.statusText+'\n' |
MESS += 'httpRequest.responseText=['+httpRequest.responseText+']\n'; |
alert(MESS); |
} |
function attach_event(obj, obj_descr){ |
obj.onactivate = function () { display_messages(obj_descr+' onactivate') } |
obj.onabort = function () { display_messages(obj_descr+' onabort') } |
//obj.onerror = function () { display_messages(obj_descr+' onerror')} |
obj.onload = function () { display_messages(obj_descr+' onload')} |
} |
attach_event(window,'window'); |
function load_div(URL){ |
httpRequest = new XMLHttpRequest(); |
httpRequest.onload = httpRequest_onload; |
httpRequest.onerror = httpRequest_onerror; |
httpRequest.open('GET' ,URL ,true ); |
httpRequest.send(null); |
} |
function my_timeoutcallback(){ |
alert('my_timeoutcallback'); |
} |
function my_callback(){ |
// alert('my_callback'); |
} |
function httpRequestMasonTest(){ |
hReqMason_LoadTimeout(document.getElementById('div_test'), 5000, my_timeoutcallback, my_callback, '../test/test.html', null); |
} |
</script> |
<hr> |
<span onClick="httpRequestMasonTest()">Load httpRequestMason</span> |
<div id="div_test">oggetto da sostituire</div> |
</body> |
</html> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/test/test_content.html |
---|
0,0 → 1,14 |
<hr> |
<&| .test &>BINGO</&> |
<hr> |
% my $content = "my bingo"; |
% $m->comp({ 'content' => sub { $m->print($content) } }, '.test'); |
<hr> |
%# |
%# |
<%def .test> |
Content=[<%$m->content%>] |
<%filter> |
s/(\w+)/<font color=red>$1<\/font>/ig; |
</%filter> |
</%def> |
/tags/2.0/htdocs/AuthCookieLoginForm.html |
---|
0,0 → 1,311 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%attr> |
Cache_MaxAge => 120 |
</%attr> |
<% $r->dir_config('HtmlDocType') %> |
<html> |
<head> |
% my $Dojo_dir = $JSLogger->level() eq $DEBUG ? $r->dir_config('DojoDirUrlDebug') : $r->dir_config('DojoDirUrl'); |
<script src="<% $Dojo_dir %>/dojo/dojo.js" type="text/javascript" data-dojo-config="async: false, |
isDebug:<% $JSLogger->level() eq $DEBUG ? 'true' : 'false'%>, parseOnLoad:true, locale: 'it'"></script> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/dijit.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/document.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/claro.css" type="text/css"> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
</head> |
<body class="claro"> |
<br> |
<br> |
<& /logo.comp &> |
<%perl> |
# se il browser è adatto oppure è di una versione successiva a quelle testate ... |
my $credential_0; |
my $prev_password = ''; |
if($browserOkBeta){ |
# non si può usare %ARGS; non viene inizializzata correttamente |
# in quanto i parametri vengono passati in $ENV{REDIRECT_QUERY_STRING} |
my $query = new CGI($ENV{REDIRECT_QUERY_STRING}); |
$credential_0 = $query->param('user'); |
#DEBUG print STDERR "AuthCookieLoginForm user:$credential_0 - ", $ENV{REDIRECT_QUERY_STRING},"\n"; |
# se il form viene richiamato ripetutamente REQUEST_URI le volte successive |
# contiene il riferimento al form di login e non quello di partenza che |
# invece si trova in REDIRECT_URL |
my $RedirectURL = $ENV{REQUEST_URI}; |
#DEBUG print STDERR "AuthCookieLoginForm.html",Dumper(\%ENV); |
if($RedirectURL =~ m|^/logout.html?|){ |
my $U = int rand 1_000_000_000_000; |
$RedirectURL = "/index.html?U=$U"; |
} |
if($RedirectURL =~ m|^/AuthCookieLoginSubmit|){ |
$RedirectURL = $ENV{REDIRECT_URL}; |
} |
#DEBUG print STDERR "AuthCookieLoginForm.html",Dumper(\%ENV); |
if($RedirectURL =~ m/\?C=hReqMason_\d+/){ |
my $U = int rand 1_000_000_000_000; |
# se si tratta del caricamento di un componente redirigo la richiesta alla home page ... |
# |
#DEBUG print STDERR "LOAD ROOT U=$U\n"; |
</%perl> |
<script> |
top.open('<%$r->dir_config('BaseUrl')%>/index.html?U=<%$U%>','_self'); |
</script> |
<%perl> |
}else{ |
my $reason = $r->prev->subprocess_env('AuthCookieReason'); |
$prev_password = $r->prev->subprocess_env('AuthCookiePassword'); |
# recupero sessione utente, giorni di inattività, giorni dall'ultimo cambio password e flag di esclusione dei test di scadenza password |
my $sth = $dbh->prepare(q{ |
select date_part('day', now() - session_time) as psw_inactivity, |
date_part('day', now() - last_change_password) as change_psw_days, |
no_psw_expiration, |
concurrent_sessions |
from anagrafiche |
where login = ? |
}); |
$sth->execute($credential_0); |
my $nrows = $sth->rows; |
my($psw_inactivity, $change_psw_days, $no_psw_expiration, $concurrent_sessions) = $nrows ? @{$sth->fetchrow_arrayref} : undef; |
#DEBUG print STDERR "AuthCookieLoginForm credential_0:$credential_0 ($session, $psw_inactivity, $change_psw_days, $no_psw_expiration)\n"; |
if($nrows && !$no_psw_expiration){ |
# valuto se va richiesto il cambio password |
if(!defined $change_psw_days or $change_psw_days > $MaxPasswordDays){ |
$reason = 'change_psw'; |
} |
# valuto se si tratta di un utente assente da troppo tempo |
if($psw_inactivity and $psw_inactivity > $MaxPasswordInactivity){ |
$reason = 'psw_expiration'; |
} |
} |
</%perl> |
<script> |
function submitHandler(){ |
% if($reason eq 'change_psw'){ |
if(form.new_passwd.value != form.new_passwd2.value){ |
alert('Nuove password digitate differenti'); |
form.new_passwd.value = ''; |
form.new_passwd2.value = ''; |
return false; |
} |
% } |
form.credential_1.value = form.passwd.value; |
form.passwd.value = null; |
% if($reason eq 'change_psw'){ |
form.credential_2.value = form.new_passwd.value; |
form.new_passwd.value = null; |
form.new_passwd2.value = null; |
% } |
form.action = "/AuthCookieLoginSubmit?user=" + form.credential_0.value |
return true; |
} |
%# window.onload = function(){ |
%# window.setTimeout("document.getElementById('credential_0').value = ''; document.getElementById('password').value = '';", 1); |
%# } |
function RegistrazioneWin() { |
window.location.replace("/UserRegistrationForm.html"); |
} |
function PasswordResetWin(user) { |
window.location.replace("/UserPasswordResetForm.html"); |
} |
</script> |
<form method="POST" name="form" action="" onsubmit="return submitHandler();"> |
<input type="hidden" name="credential_1"> |
<input type="hidden" name="credential_2"> |
<input type="hidden" name="destination" value="<%$RedirectURL%>"> |
<table align="center"> |
<tr><td> |
<p align="center"> |
<br> |
<%perl> |
if(defined $credential_0) { |
$sth = $dbh->prepare(q{ |
select id,user_ip,session_inactive_time |
from session |
where id_anagrafiche = (select id |
from anagrafiche |
where login = ?) |
order by session_inactive_time desc |
limit 1 |
}); |
$sth->execute($credential_0); |
$nrows = $sth->rows; |
}; |
#if(defined $nrows and $nrows > 0){ |
if((not defined $concurrent_sessions or $concurrent_sessions == 0) and $nrows > 0) { |
my($id, $IP, $minutes) = @{$sth->fetchrow_arrayref}; |
my $time_minutes = int(time/60) - $minutes; |
</%perl> |
<h3>L'utente '<%$credential_0%>' risulta connesso dall'indirizzo <%$IP%> da <%$time_minutes%> minuti senza attività</h3> |
</p> |
<p align="center"> |
<input type="checkbox" name="credential_3" > |
Annulla sessione precedente |
</p> |
<%perl> |
} |
</%perl> |
<p align="center"> |
% my $ErrorChangePassword = $r->prev->subprocess_env('AuthCookieErrorChangePassword'); |
% if($ErrorChangePassword){ |
<% $ErrorChangePassword %><br> |
% } |
% if($reason eq 'bad_credentials'){ |
<% $r->dir_config('Auth_AC_bad_credentials_message') %> |
% }elsif($reason eq 'no_cookie'){ |
<% $r->dir_config('Auth_AC_no_cookie_message') %> |
% }elsif($reason eq 'psw_expiration'){ |
L'accesso a questo sito è stato negato!<br> |
Utente <% $credential_0 %> assente da più di <% $MaxPasswordInactivity %> giorni.<br> |
<button class="widget" onclick="PasswordResetWin('<% $credential_0 |js%>'); return false;">Richiedi una nuova password!</button> |
% }elsif($reason eq 'change_psw'){ |
Prima di poter accedere è obbligatorio cambiare la password! |
% }else{ |
L'accesso a questo sito è stato negato! |
Errore: <% $reason %>.<br> |
% } |
<br> |
</p> |
</td></tr> |
<tr><td> |
<table align="center"> |
<tr> |
<td align="right"><b>Login:</b></td> |
<td><input class="string widget widgetRwRequired" type="text" name="credential_0" id="credential_0" value="<% $reason eq 'psw_expiration' ? '' : $credential_0 %>" size="24" length="24" |
onchange="window.setTimeout('document.getElementById(\'password\').value = \'\';', 1);"></td> |
</tr> |
<tr> |
<td align="right"><b><% $reason eq 'change_psw' ? 'Vecchia password' : 'Password' %>:</b></td> |
<td><input class="string widget widgetRwRequired" type="password" name="passwd" id="password" value="<% $prev_password |js %>" size="24" length="24"></td> |
</tr> |
% if($reason eq 'change_psw'){ |
<tr> |
<td align="right"><b>Nuova password:</b></td> |
<td><input class="string widget widgetRwRequired" type="password" name="new_passwd" id="new_password" size="24" length="24"></td> |
</tr> |
<tr> |
<td align="right"><b>Ripeti nuova password:</b></td> |
<td><input class="string widget widgetRwRequired" type="password" name="new_passwd2" id="new_password2" size="24" length="24"></td> |
</tr> |
% } |
<tr> |
<td></td> |
<td align="left"> |
<input class="widget button" type="submit" value="Accesso ..."> |
</td> |
</tr> |
<tr style="height:15px;"></tr> |
% if($UserPasswordReset eq 'enable') { |
<tr> |
<td></td> |
<td style="text-align: center;"> |
<button class="widget" onclick="PasswordResetWin(); return false;">Ho dimenticato la password ...</button> |
</td> |
</tr> |
<tr style="height:5px;"></tr> |
% } |
% if($UserRegistration eq 'enable') { |
<tr> |
<td></td> |
<td style="text-align: center;"> |
<button class="widget" onclick="RegistrazioneWin(); return false;">Registrazione nuovo utente ...</button> |
</td> |
</tr> |
<tr style="height:5px;"></tr> |
% } |
</table> |
</td></tr> |
</table> |
</form> |
% } |
% } |
<& /privacy.comp &> |
% if(!$browserOk){ |
<br> |
% if($browserOkBeta){ |
<p align="center">ATTENZIONE: Browser parzialmente supportato.</p> |
% }else{ |
<h3 align="center">ATTENZIONE: Browser non compatibile con l'applicazione!</h3> |
% } |
<p align="center"> |
L'applicazione è stata collaudata con i seguenti browser: |
</p> |
<p align="center"> |
<br> |
<cite> |
Firefox Rel. 54<br> |
Chromium Rel. 59<br> |
(Supporto completo) |
<br> |
Safari 5.1, 8, 10<br> |
Microsoft Edge<br> |
Internet Explorer 10 e 11<br> |
(Supporto parziale) |
</cite> |
% if($browserOkBeta){ |
<br> |
<br> |
e probabilmente funziona correttamente anche con le versioni più recenti<br> |
ma evidentemente non è garantito il funzionamento.<br> |
<br> |
Il funzionamento dell'applicazione con supporto parziale non è garantito! |
</p> |
% }else{ |
.</p> |
<p align="center"> |
Per utilizzare l'applicazione è necessario installare uno dei browser sopra elencati.<br> |
Il funzionamento dell'applicazione con delle versioni differenti o con supporto parziale non è garantito! |
</p> |
% } |
% } |
<br/><br/> |
<& /copyright.comp &> |
</body> |
<%once> |
my $Auth_InactivityMax = $r->dir_config('Auth_InactivityMax'); |
my $UserRegistration = $r->dir_config('UserRegistration'); |
my $UserPasswordReset = $r->dir_config('UserPasswordReset'); |
</%once> |
<%init> |
# Blocco accesso per inattività se l'utente non accede da più di MaxPasswordInactivity giorni |
my $MaxPasswordInactivity = $r->dir_config('MaxPasswordInactivity'); |
# Scadenza password (in giorni) |
my $MaxPasswordDays = $r->dir_config('MaxPasswordDays'); |
# connessione al database |
my $dbh = $Session{Dbh}; |
# verifica la compatibilità del browser |
my $browser = $Session{Browser}; |
# browser verificati |
my $user_agent = $browser->user_agent; |
my $trident7 = $user_agent =~ m/Trident\/7.\d+/; |
my $browserOk = ( |
($browser->firefox && $browser->version >= 32 && $browser->version <=54) || |
($browser->chrome && $browser->version < 40) |
); |
# gamma dei browser Ok e più recenti probabilmente compatibili ma non verificati |
my $browserOkBeta = ( |
$browserOk || |
($browser->ie && $trident7) || |
$browser->edge || $browser->ie10 || $browser->ie11 || |
($browser->ie && $browser->version >= 10) || |
($browser->firefox && ($browser->version >= 15)) || |
($browser->chrome && ($browser->version >= 41) ) || |
($browser->webkit && ($browser->version >= 5) ) |
); |
### die "browserOkBeta:$browserOkBeta browserOk:$browserOk <br>trident4:$trident4 trident5:$trident5 trident6:$trident6 trident7:$trident7 <br>"." browser->ie6:".$browser->ie6." browser->ie7:".$browser->ie7." browser->ie8:".$browser->ie8." browser->ie9:".$browser->ie9." browser->ie10:".$browser->ie10." browser->ie11:".$browser->ie11." browser->ie:".$browser->ie." browser->version:".$browser->version."<br><br>".Dumper($browser); |
#DEBUG print STDERR "AuthCookieLoginForm->connect($conn, $user, $passwd)\n"; |
</%init> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
/tags/2.0/htdocs/logout.html |
---|
0,0 → 1,42 |
<%perl> |
if($Session{Session_id}){ |
$r->auth_type->logout($r); |
</%perl> |
<br> |
<br> |
<br> |
<br> |
<br> |
<br> |
<& "/home.html", logout => 1 &> |
<br> |
<br> |
<H3 align="center">Arrivederci!</H3> |
<p align="center"> |
<A HREF="<%$r->dir_config('BaseUrl')%>/index.html?U=<% int rand 1_000_000_000_000 %>" TARGET="_top">Per riaprire la sessione ...</A> </p> |
<script> |
require(["dojo/ready", "dijit/registry", "dojo/_base/array"], function(ready, registry, array){ |
ready(function(){ |
var menu = document.getElementById('TopContent'); |
if(menu){ |
// elimino il menu |
menu.innerHTML = ''; |
} |
// cancello i Tab diversi dal corrente |
var tabs = registry.byId('mainTab'); |
if(tabs){ |
array.forEach(tabs.getChildren(), function(tab){ |
if(tab != tabs.selectedChildWidget){ |
tabs.removeChild(tab); |
tab.destroyRecursive(); |
} |
}); |
} |
}); |
}); |
</script> |
% }else{ |
% # redirect alla pagina principale |
% $r->internal_redirect('/index.html'); |
% } |
/tags/2.0/htdocs/help.html |
---|
0,0 → 1,137 |
<%args> |
$method => undef |
</%args> |
% if(!defined $method){ |
<script> |
require([ |
"dijit/dijit", |
"dojo/parser", |
"dijit/layout/BorderContainer", |
"dijit/layout/ContentPane" |
]); |
</script> |
<div data-dojo-type="dijit.layout.BorderContainer" design="sidebar" persist="false" gutters="false" |
style="min-width: 1em; min-height: 1px; z-index: 0; width: 100%; height: 100%;"> |
<div data-dojo-type="dijit.layout.ContentPane" region="left" style="width: 240px;" extractContent="false" |
id="MenuHelpContainer" class="MenuHelpContainer" |
preventCache="false" preload="false" refreshOnShow="false" splitter="true" maxSize="Infinity" doLayout="false"> |
<H3 align="center">Documentazione</H3> |
<& .MenuHelp, class => 'MenuHelpContainer' &> |
</div> |
<div data-dojo-type="dijit.layout.ContentPane" region="center" extractContent="true" |
id="BodyHelpContainer" class="BodyHelpContainer" ioArgs="{timeout:<% $r->dir_config('GetFormTimeout') %>}" |
preventCache="false" preload="false" refreshOnShow="false" splitter="false" maxSize="Infinity" doLayout="false"> |
<& /help.html, method => 'Home' &> |
</div> |
</div> |
<script> |
% # richiama dalla cartella /help il testo corrispondente selezionato |
% # arg contiene il nome della funzione |
function helpLoad(arg){ |
dijit.byId('BodyHelpContainer').set('href', '/help.html?method='+arg+'&Ver=<%$Ver%>').then( null, function(err){ |
dijit.byId('BodyHelpContainer').set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+"</span>"); |
console.log('ERRORE DOWNLOAD HELP <% $method %>:'+err+' id:'+container.id+' timeout:'+timeout); |
}); |
} |
</script> |
% }else{ |
<%perl> |
my $sql = q{ |
select distinct |
f.id, |
f.descrizione, |
f.menu_contents, |
f.help, |
f.menu_father_id |
from |
funzioni as f, |
gruppi_funzioni as gf, |
anagrafiche_gruppi as ag, |
autorizzazioni as a |
where |
f.nome = ? and |
f.id = gf.id_funzioni and |
gf.id_gruppi = ag.id_gruppi and |
ag.id_anagrafiche = ? and |
gf.id_autorizzazioni = a.id and |
a.nome = 'Menu'; |
}; |
my $sth = $Session{Dbh}->prepare($sql); |
$sth->execute($method, $Session{User_id}); |
my $row_menu = $sth->fetchrow_hashref; |
if($row_menu){ |
# rendering dell'help |
</%perl> |
<H2 align="center"> |
<% $row_menu->{'descrizione'} %> |
</H2> |
<% $row_menu->{'help'} %> |
% my $list_children = $m->scomp('.MenuHelp', father => $row_menu->{'id'}, class => 'BodyHelpContainer'); |
% if($list_children){ |
<hr> |
<% $list_children %> |
% } |
% }else{ |
<div style="margin:20px;"><span class='dijitInline dijitIconError'></span> Menu '<%$method%>' sconosciuto!</div> |
% } |
% } |
%################################################################################ |
%# costruttore dell'indice - la chiamata è recorsiva |
%# |
<%def .MenuHelp>\ |
<%args> |
$liv => 0 # livello del menù (il metodo viene chiamato ricorsivamente) |
$father => undef # il padre |
$class |
</%args> |
<%perl> |
my $menucount=0; |
my $sql = q{ |
select distinct |
f.id, |
f.nome, |
f.menu_contents, |
f.menu_father_id, |
f.menu_ord, |
(select count(*) from funzioni where menu_father_id = f.id) as children |
from |
funzioni as f, |
gruppi_funzioni as gf, |
anagrafiche_gruppi as ag, |
autorizzazioni as a |
where |
} . ($father ? qq { |
f.menu_father_id = $father and |
} : q{ |
menu_father_id is null and |
}) . q{ |
f.id = gf.id_funzioni and |
gf.id_gruppi = ag.id_gruppi and |
ag.id_anagrafiche = ? and |
gf.id_autorizzazioni = a.id and |
a.nome = 'Menu' |
order by f.menu_ord; |
}; |
my $sth = $Session{Dbh}->prepare($sql); |
my $rows = $sth->execute($Session{User_id}); |
if($rows > 0){ |
$m->out(qq|<ul class="$class">|); |
while(my $row_menu = $sth->fetchrow_hashref){ |
$menucount++; |
my $nome = $m->interp->apply_escapes($row_menu->{'nome'}, 'js'); |
my $description = $m->interp->apply_escapes($row_menu->{'descrizione'}, 'h'); |
my $description2 = $m->interp->apply_escapes($row_menu->{'descrizione'}, 'js'); |
my $menu_contents = $m->interp->apply_escapes($row_menu->{'menu_contents'}, 'h'); |
$menu_contents =~ s/\s/ /gs; |
$m->out(qq|<li class="$class"><a href="javascript:helpLoad('$nome')" alt="$description"> |
$menu_contents |
</a></li> |
|); |
$m->comp('.MenuHelp', father => $row_menu->{'id'}, class => $class, liv => $liv+1); |
} |
$m->out('</ul>'); |
} |
</%perl>\ |
</%def> |
/tags/2.0/htdocs/archive/dhandler |
---|
0,0 → 1,71 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2011 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# Interfaccia CRUD utilizzata dal widget Files per gestire l'archivio |
# http://dojotoolkit.org/features/1.6/object-store |
# http://dojotoolkit.org/reference-guide/dojo/store/JsonRest.html |
# |
# Moduli Debian: |
# aptitude install libfile-path-perl |
</%doc> |
<%once> |
use JSON; |
use IPC::Run qw(run); |
use File::Path qw(make_path remove_tree); |
use URI::Escape; |
</%once> |
<%perl> |
my $base_dir = $r->dir_config('InputFilesArchive'); |
my $arg = $r->unparsed_uri; |
$arg =~ s|^/archive/||; |
utf8::is_utf8($arg) || utf8::decode($arg); |
my $mode_download; |
# N.B. Si usa '?' in quanto non ci sarà mai nel nome delle cartelle il carattere riservato |
if($arg =~ m/^(.*)\?(\w+)$/){ |
$arg = $1; |
$mode_download = $2; |
} |
$arg = uri_unescape($arg); |
# $arg corriponde al file o cartella presente in $base_dir/ |
my($schema, $table, $rec_id, $path) = split /\//, $arg, 4; |
# elimino multipli separatori di cartella |
$path =~ s/\/\/+/\//g; |
$path =~ s/^\/+|\/$//g; |
if(!length $schema || !length $table){ |
$m->out(JSON::objToJson({ |
error => "Bad URI: malformed schema/table/id ($arg)" |
})); |
}else{ |
my $method = $r->method(); |
my $obj = (); |
if($method ne 'GET' && $method ne 'DELETE'){ |
my $content; $r->read($content, $r->headers_in->{'Content-length'}); |
utf8::is_utf8($content) || utf8::decode($content); |
$obj = jsonToObj($content); |
#DEBUG print STDERR "Method:$method Path:$schema.$table:$rec_id:$path id:$obj->{'id'} new_id:$obj->{'new_id'} name:$obj->{'name'} new_name:$obj->{'new_name'} mode_download:$mode_download\n"; |
} |
my $url = $r->dir_config('DataBaseUrl')."/$schema/$table.mql"; |
$m->subexec($url, |
method => 'archive_' . lc $method, |
obj_id => $obj->{'id'}, |
obj_new_id => $obj->{'new_id'}, |
obj_name => $obj->{'name'}, |
obj_new_name => $obj->{'new_name'}, |
rec_id => $rec_id, |
mode_download => $mode_download, |
path => $path, |
PermissionGroup => 'Archive' # Gruppo per l'autorizzazione all'utilizzo dell'archiviazione documenti |
); |
} |
</%perl>\ |
<%flags> |
inherit => undef |
</%flags> |
%# Ultima riga senza <CR> |
/tags/2.0/htdocs/archive/upload.mason |
---|
0,0 → 1,179 |
<%doc> |
Vedi: http://docs.dojocampus.org/dojox/form/Uploader |
Esempio: /opt/masonsql/htdocs/lib/dojo-release-1.6.1-src/dojox/form/tests/UploadFile.php.disabled |
### Gestione delle versioni ### |
per ciascun file <FILE> viene creata una cartella di nome ./.<FILE> contenente le varie versioni di file. |
L'ultima versione o le versioni ripristinate vengono attivate con un link alla versione con il nome del file. |
Le operazioni di spostamento e cambio del nome agiscono anche sulla cartella delle versioni. |
</%doc> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%args> |
$upload_dir |
</%args> |
<%once> |
use URI::Escape; |
use Date::Calc qw(Localtime); |
use Digest::MD5; |
use JSON; |
sub Files_return_message($$){ |
my($upload_type, $respondResult) = @_; |
if($upload_type eq 'uploadedfileFlash'){ |
# Flash |
my @field; |
for my $field (keys %$respondResult){ |
push @field, $field.'='.uri_escape($respondResult->{$field}); |
} |
$m->out(join(',', @field)) |
}elsif($upload_type eq 'uploadedfiles[]'){ |
# HTML5 |
$m->out(JSON::objToJson($respondResult)); |
}else{ |
# Iframe |
$m->out('<textarea>'.JSON::objToJson($respondResult).'</textarea>'); |
} |
} |
sub Files_version_name($$$$){ |
my($version, $userid, $time, $digest) = @_; |
return sprintf('%04d-%02d-%02d_%02d:%02d:%02d.%d.%s.%s', (Localtime($time))[0..5], $version, $userid, $digest); |
} |
sub Files_archive_uploaded_file($$$$$){ |
my($Base, $rec_id, $path, $upload, $log_table_name) = @_; |
my $name = $upload->filename; |
# verifico che il nome non contenga caratteri proibiti, altrimenti li converto in '_' |
$name =~ s/[\*:|<>\?\/\\"]/_/g; |
# il "." ad inizio del nome è riservato ai file/dir nascosti |
$name =~ s/^\./_/; |
$path =~ s|^/||; |
if($path){ |
$path .= '/'; |
} |
my $file_id = "$path$name"; |
# il nome indicato nella configurazione "Files_Trash_dir" è riservato alla cartella cestino |
if($file_id eq '/'.$r->dir_config('Files_Trash_dir')){ |
$name = '_'.$name; |
$file_id = "$path$name"; |
} |
my $base_dir = $r->dir_config('InputFilesArchive')."/$Base/$rec_id/$path"; |
my $file = $base_dir.'/'.$name; |
my $v_dir = $base_dir.'/.'.$name; |
if(-d $file){ |
return { 'name' => $file_id, 'error' => 'esiste in archivio una cartella con lo stesso nome.'}; |
} |
if(-f $file && ! -d $v_dir ){ |
# attivo la gestione della versione |
mkdir $v_dir || return { 'name' => $file_id, 'error' => "create dir: $!"}; |
my(undef,undef,undef,undef,undef,undef,undef,undef,undef,$mtime) = stat($file); |
open FH, '<', $file || return { 'name' => $file_id, 'error' => "can't open: $!"}; |
binmode FH; |
my $digest = Digest::MD5->new->addfile(\*FH)->hexdigest; |
close FH; |
my $v_name = Files_version_name(1, $Session{User_id}, $mtime, $digest); |
my $v_file = "$v_dir/$v_name"; |
rename $file, $v_file || return { 'name' => $file_id, 'error' => "move file: $!"}; |
symlink ".$name/$v_name", $file || return { 'name' => $file_id, 'error' => "link 1: $!"}; |
} |
if(! -d $v_dir){ |
mkdir $v_dir || return { 'name' => "$path/.$name", 'error' => "create dir: $!"}; |
} |
# individuo i numeri di versione |
my %version; |
opendir (DIR, $v_dir) || return { 'name' => "$path/.$name", 'error' => "opendir: $!"}; |
my $v_num = 0; |
while(my $v_name = readdir(DIR)){ |
next if($v_name =~ /^\./); |
my($date, $ver, $userid, $hash) = split /\./, $v_name, 4; |
$version{$hash} = $v_name; |
$v_num = $ver > $v_num ? $ver : $v_num; |
} |
$v_num++; |
closedir(DIR); |
my $v_name = Files_version_name($v_num, $Session{User_id}, time, ''); |
my $v_file = "$base_dir/.$name/$v_name"; |
if(!$upload->link($v_file)){ |
return { 'name' => $file_id, 'error' => sprintf "upload: $!"}; |
} |
# calcolo la hash md5sum del nuovo file |
open FH, '<', $v_file || return {'name' => $file_id, 'error' => "can't open '$v_name': $!"}; |
binmode FH; |
my $digest = Digest::MD5->new->addfile(\*FH)->hexdigest; |
close FH; |
if(exists $version{$digest}){ |
unlink $v_file; |
# verifico se il file già presente è anche quello corrente |
my $v_name = $version{$digest}; |
# versione corrente |
my $v_name_curr = readlink $file; |
$v_name_curr =~ s/.*\///; |
my(undef, $ver_curr, undef, $hash_curr) = split /\./, $v_name_curr, 4; |
if($digest eq $hash_curr){ |
return {'name' => $file_id, 'info' => "Il file è già presente nell\'archivio; versione $ver_curr corrente"}; |
}else{ |
my($date, $ver, $userid, $hash) = split /\./, $v_name, 4; |
# cambio la versione corrente |
unlink $file || return {'name' => $file_id, 'error' => "unlink: $!"}; |
symlink ".$name/$v_name", $file || return {'name' => $file_id, 'error' => "link ver. $ver: $!"}; |
# save logs only if $log_table_name is defined |
$log_table_name and DB_log('update', $rec_id, { 'ARC.' => "$file_id:$ver" }, { 'ARC.' => "$file_id:$ver_curr" }, $log_table_name); |
return {'name' => $file_id, 'info' => "Il file è già presente nell\'archivio; versione $ver, resa ora corrente"}; |
} |
}else{ |
# cambio il nome del file aggiungendo la hash calcolata |
rename $v_file, $v_file.$digest || return {'name' => $file_id, 'error' => "add hash to '$v_name': $!"}; |
$v_file .= $digest; |
$v_name .= $digest; |
# cambio la versione corrente |
unlink $file || return {'name' => $file_id, 'error' => "unlink: $!"}; |
symlink ".$name/$v_name", $file || return {'name' => $file_id, 'error' => "link ver. $v_num: $!"}; |
# save logs only if $log_table_name is defined |
$log_table_name and DB_log('update', $rec_id, { 'ARC.' => "$file_id:$v_num" }, { 'ARC.' => undef }, $log_table_name); |
return {'name' => $file_id, 'type' => $upload->type, 'size' => $upload->size}; |
} |
} |
</%once> |
<%perl> |
$r->headers_out->{'Cache-Control'} = 'max-age=0'; |
$m->clear_buffer; |
use Data::Dumper; |
my $arg = $upload_dir; |
$arg =~ s|^/archive/||; |
my($schema, $table, $rec_id, $path) = split /\//, $arg, 4; |
my $Base = "$schema/$table"; |
# verifica delle autorizzazioni |
$m->comp($r->dir_config('DataBaseUrl')."/$schema/$table.mql:archive_check", |
'Base' => $Base, |
'rec_id' => $rec_id, |
'permission' => 'Insert' |
); |
my $log_table_name = $m->scomp($r->dir_config('DataBaseUrl')."/$schema/$table.mql:LOG_TABLE_NAME"); |
my $base_dir = $r->dir_config('InputFilesArchive').'/'.$upload_dir; |
my $dlist = $r->upload; # ritorna istanza APR::Request::Param::Table |
# determino il tipo di download |
my @key_files = keys %{$dlist}; |
my @value_files = values %{$dlist}; |
my $upload_type = $key_files[0]; # uploadedfileFlash, uploadedfiles[], uploadedfiles1|2|... |
#DEBUG print STDERR "upload_type:$upload_type", Dumper(\@value_files); |
#DEBUG $upload_type='uploadedfileFlash'; |
if(! -d $base_dir){ |
Files_return_message($upload_type, [{ 'error' => "$base_dir not exists"}]); |
return; |
} |
my @respondResult; |
if($upload_type eq 'uploadedfileFlash'){ |
my $upload = $value_files[0]; |
#DEBUG print STDERR "uploadedfileFlash\n".Dumper($upload); |
push @respondResult, Files_archive_uploaded_file($Base, $rec_id, $path, $upload, $log_table_name); |
}else{ |
foreach my $upload (@value_files){ # istanze Apache2::Upload |
#DEBUG print STDERR "uploadedfile \n".Dumper($upload); |
push @respondResult, Files_archive_uploaded_file($Base, $rec_id, $path, $upload, $log_table_name); |
} |
} |
Files_return_message($upload_type, \@respondResult); |
</%perl> |
/tags/2.0/htdocs/dbms/dhandler |
---|
0,0 → 1,92 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
Modifica la chiamata aggiungendo il suffisso al nome della tabella nella URI e chiamando il relativo componente |
nella catella DataBaseSql |
</%doc> |
<%args> |
$envelope_response => 'xml' |
</%args> |
<%flags> |
inherit => '/library.comp' |
</%flags> |
<%once> |
use Data::Dumper; |
</%once> |
<%perl> |
my $path = $m->dhandler_arg; |
if($path !~ m|/|){ |
$path = $r->dir_config('DefaultSchema').'/'.$path; |
} |
my $url = $r->dir_config('DataBaseUrl').'/'.$path.'.mql'; |
# il metodo 'select' era già utilizzato |
if(!$ARGS{method}){ |
$ARGS{method} = 'retrieve'; |
} |
# verifica i metodi disponibili |
if(' info keyname numrec newkey retrieve update create delete xls ' !~ m/ $ARGS{method} /){ |
die "Method $ARGS{method} is not know\n"; |
} |
if(!$ARGS{xml_path}){ |
$ARGS{xml_path} = 'dbms'; |
} |
if(!$ARGS{key}){ |
$ARGS{key} = ''; |
} |
# lista di chiavi |
if(!$ARGS{key_list}){ |
$ARGS{key_list} = $ARGS{key}; |
delete $ARGS{key} |
} |
if($ARGS{father_key}){ |
$ARGS{father_id_update} = $ARGS{father_id} = $ARGS{father_key}; |
delete $ARGS{father_key}; |
} |
# |
if($ARGS{method} eq 'xls'){ |
# nessun limite nel caso di download nel formato XLS |
if(!defined $ARGS{rows}){ |
$ARGS{rows} = -1; |
} |
if(!defined $ARGS{father_id}){ |
$ARGS{father_id} = -2; |
} |
# nome del file scaricato |
my $filename = $m->dhandler_arg; |
$filename =~ s|^dbms/||; |
$filename =~ s|/|\.|; |
$filename .= '.xls'; |
$r->headers_out->{'Cache-Control'} = 'max-age=0'; |
$r->headers_out->{'Content-disposition'} = "attachment;filename=$filename"; |
$r->headers_out->{'Content-transfer-encodig'} = 'binary'; |
}else{ |
# se viene limitato il recordset ai record figli e non viene dichiarato il limite delle righe |
# viene disabilitato il limite al numero di righe |
if(defined $ARGS{father_id} && !$ARGS{rows}){ |
$ARGS{rows} = -1; |
} |
if(!defined $ARGS{father_id} && $ARGS{rows} == -1){ |
delete $ARGS{rows}; |
} |
} |
delete $ARGS{where2}; |
# verifica sul campo where |
if(defined $ARGS{where} && $ARGS{method} ne 'retrieve'){ |
# where utilizzabile solo nelle operazioni di lettura |
delete $ARGS{where}; |
} |
if(defined $ARGS{where}){ |
my $where = ' '.$ARGS{where}.' '; |
$ARGS{where2} = $ARGS{where}; |
delete $ARGS{where}; |
} |
$m->subexec($url, %ARGS, envelope_response => $envelope_response, envelope_request => $envelope_response, PermissionGroup => 'Dbms'); |
</%perl> |
%# Ultima riga senza <CR> |
/tags/2.0/htdocs/rest/dhandler |
---|
0,0 → 1,96 |
<%doc> |
Implementa interfaccia CRUD secondo lo standard RFC-2616 |
Utilizzata con Dojo: dojo/store/JsonRest |
Autenticazione necessaria da MasonSQL |
</%doc> |
<%args> |
</%args> |
<%flags> |
inherit => '/library.comp' |
</%flags> |
<%once> |
use Data::Dumper; |
</%once> |
<%init> |
my $schema; |
my $table; |
my $id; |
my $arg = $m->dhandler_arg; |
if($arg =~ m|^(\w+)/(\w+)/(\w+)|){ |
$schema = $1; |
$table = $2; |
$id = $3; |
}elsif($arg =~ m|^(\w+)/(\w+)/{0,1}|){ |
$schema = $1; |
$table = $2; |
}else{ |
die "URI malformed use /schema/table/id\n"; |
} |
my $url = $r->dir_config('DataBaseUrl')."/$schema/$table.mql"; |
my $method = uc $r->method(); |
my $size = $r->headers_in->{'Content-length'}; |
if($size){ |
$r->read($ARGS{'content'}, $size); |
} |
if($ARGS{'father_key'}){ |
$ARGS{'father_id_update'} = $ARGS{'father_id'} = $ARGS{'father_key'}; |
delete $ARGS{'father_key'}; |
} |
# Si veda http://www.ietf.org/rfc/rfc2616.txt |
# POST --> create |
# PUT --> update |
# DELETE --> delete |
# GET --> retrieve N.B. metodo 'select' era già utilizzato per altri scopi |
if($method eq 'POST' || ($method eq 'PUT' && $ENV{HTTP_IF_NONE_MATCH} eq '*')){ |
$ARGS{method} = 'create'; |
}elsif($method eq 'PUT'){ |
$ARGS{method} = 'update'; |
}elsif($method eq 'DELETE'){ |
$ARGS{method} = 'delete'; |
}elsif($method eq 'GET'){ |
if(exists $ARGS{'newkey'}){ |
$ARGS{method} = 'newkey'; |
}else{ |
$ARGS{method} = 'retrieve'; |
} |
}else{ |
die "Unknow $method method\n"; |
} |
$ARGS{'key_list'} = $id; |
delete $ARGS{'key'}; |
delete $ARGS{'where2'}; |
# verifica sul campo where |
if(defined $ARGS{'where'} && $ARGS{method} ne 'retrieve'){ |
# where utilizzabile solo nelle operazioni di lettura |
delete $ARGS{'where'}; |
} |
if(defined $ARGS{'where'}){ |
my $where = ' '.$ARGS{'where'}.' '; |
$ARGS{'where2'} = $ARGS{'where'}; |
delete $ARGS{'where'}; |
} |
# DEBUG print STDERR "URL: $url\n"; |
# DEBUG print STDERR "ARGS: schema:$schema table:$table id:$id"; |
if(exists $ENV{HTTP_RANGE} && ($ENV{HTTP_RANGE} =~ m/items=(\d+)-(\d+|\**)/ || $ENV{HTTP_RANGE} =~ m/(\d+)-(\d+|\**)/)){ |
my $start = $1 || 0; |
$ARGS{'start'} = $start; |
my $stop = $2; |
if(defined $stop && $stop ne '*' && $stop ne ''){ |
$ARGS{'rows'} = $stop - $start + 1; |
} |
# DEBUG print STDERR "RANGE: ${start}-${stop}\n"; |
}else{ |
$ARGS{'start'} = 0; |
$ARGS{'rows'} = -1; # nessun limite al numero di righe |
} |
</%init> |
<%perl> |
$m->subexec($url, |
%ARGS, |
envelope_response => $ARGS{'envelope_response'} || 'rest', |
envelope_request => $ARGS{'envelope_request'} || 'rest', |
PermissionGroup => undef |
); |
</%perl> |
%# Ultima riga senza <CR> |
/tags/2.0/htdocs/change_password.txt |
---|
0,0 → 1,20 |
<%doc> |
# richiamato da change_password.html per effettuare il cambio password |
</%doc> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%perl> |
my $ARGS = $Session{ARGS}; |
if($ARGS->{method} ne 'change_password'){ |
die "No change_password method\n"; |
} |
my $login = $Session{Group_Admins} ? $ARGS->{Login} : $Session{Login}; |
my $password = $ARGS->{Password}; |
my $err_mess = $r->auth_type->update_password($r, $login, $password, 0); |
if($err_mess){ |
die "$err_mess\n"; |
}else{ |
$m->out('OK: Password modificata!'); |
} |
</%perl> |
/tags/2.0/htdocs/UserPasswordResetForm.html |
---|
0,0 → 1,243 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2016-2020 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Rajesh Madaye <rajeshmadaye@yahoo.com> |
# Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%args> |
$action => undef |
$user => '' |
</%args> |
<%attr> |
Cache_MaxAge => 120 |
</%attr> |
<% $r->dir_config('HtmlDocType') %> |
<%once> |
use Auth_AC::UserRegistration; |
my $LoginType = $r->dir_config('LoginType'); |
my $UserRegTypeMessage = $r->dir_config('UserRegTypeMessage'); |
my $UR = Auth_AC::UserRegistration->new(); |
</%once> |
<%init> |
$m->clear_buffer; |
# connessione al database |
my $dbh = $Session{Dbh}; |
## Functional processing |
my $form_submit_status = 0; |
if(defined $action and $action eq "true") { |
$form_submit_status = $UR->process_password_reset_form(dbh => $dbh, formdata => \%ARGS, r => $r, m => $m); |
} |
</%init> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<html> |
<head> |
% my $Dojo_dir = $JSLogger->level() eq $DEBUG ? $r->dir_config('DojoDirUrlDebug') : $r->dir_config('DojoDirUrl'); |
<script src="https://www.google.com/recaptcha/api.js?hl=it"></script> |
<script src="<% $Dojo_dir %>/dojo/dojo.js" type="text/javascript" data-dojo-config="async: false, |
isDebug:<% $JSLogger->level() eq $DEBUG ? 'true' : 'false'%>, parseOnLoad:true, locale: 'it'"></script> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/dijit.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/document.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/claro.css" type="text/css"> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
<script> |
// Code to confirm form submission acknowledgement. |
% if(defined $action and $action eq "true") { |
% if($form_submit_status) { |
%# alert("We have reset your password. Please check your email to get initial password to login"); |
alert("La password è stata modificata!\nControlla <% $UserRegTypeMessage eq 'sms' ? 'nel tuo cellulare il messaggio SMS' : 'nella posta in arrivo il messaggio' %> con la nuova password per collegarti."); |
window.location.replace('/'); |
resetHandler(); |
% } else { |
%# alert("Password reset failed. Please try again with valid input values."); |
alert("Modifica della password fallita!\nSi prega di ripetere in tentativo con dei dati validi."); |
% } |
% } |
// Code to process core functionality. |
var JSLoginType = null; |
function validateEmail() { |
var email = document.getElementById("email"); |
var atpos = email.value.indexOf("@"); |
var dotpos = email.value.lastIndexOf("."); |
var rc = false; |
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=email.length) { |
document.getElementById("divErrEmail").innerHTML = "<p>Inserisci e-mail valido</p>"; |
document.getElementById("email").className = "string widget widgetRwError"; |
document.getElementById("email").focus(); |
rc = false; |
} else { |
document.getElementById("divErrEmail").innerHTML = ""; |
document.getElementById("email").className = "string widget widgetRw"; |
rc = true; |
} |
return rc; |
} |
function validateEmpty(sourceEleId, errorEleId) { |
var element =document.getElementById(sourceEleId).value; |
var rc = false; |
element = element.replace(/^\s+|\s+$/g, ''); |
if (element.length < 1) { |
document.getElementById(errorEleId).innerHTML = "<p>Si prega di inserire il valore</p>"; |
document.getElementById(sourceEleId).className = "string widget widgetRwError"; |
rc = false; |
} else { |
document.getElementById(errorEleId).innerHTML = ""; |
document.getElementById(sourceEleId).className = "string widget widgetRw"; |
rc = true; |
} |
return rc; |
} |
function isUserExists(usrId) { |
usrId = usrId.toLowerCase(); |
var error_message = ""; |
var url = "/UserRegistrationResetCheck.txt"; |
require(["dojo/request/xhr", "dojo/dom", "dojo/dom-construct", "dojo/json", "dojo/on", "dojo/domReady!"], |
function(xhr, dom, domConst, JSON, on){ |
xhr(url, { |
handleAs: "text", |
sync: true, |
query: { "login": usrId } |
}).then(function(response){ |
error_message = response; |
}, function(err){ |
error_message = "Errore!<br>" + err.message; |
}); |
}); |
return error_message; |
} |
function isEmpty(str) { |
return (!str || 0 === str.length); |
} |
function validateUserID(sourceEleId, errorEleId) { |
var element = document.getElementById(sourceEleId).value; |
element = element.replace(/^\s+|\s+$/g, ''); |
rc = false; |
JSLoginType = "<% $LoginType %>"; |
var userIDMsg = ""; |
if(validateEmpty(sourceEleId, errorEleId)) { |
userIDMsg = isUserExists(element); |
if(isEmpty(userIDMsg)) { |
document.getElementById(errorEleId).innerHTML = ""; |
document.getElementById(sourceEleId).className = "string widget widgetRw"; |
rc = true; |
} else { |
document.getElementById(errorEleId).innerHTML = "<p>"+userIDMsg+"</p>"; |
document.getElementById(sourceEleId).className = "string widget widgetRwError"; |
document.getElementById(sourceEleId).focus(); |
} |
} |
return rc; |
} |
function validateCaptcha() { |
var rc = false; |
var captcha_value = document.getElementById("g-recaptcha-response").value; |
if(isEmpty(captcha_value)) { |
document.getElementById("divErrCaptcha").innerHTML = "<p>Si prega di risolvere i captcha</p>"; |
} else { |
document.getElementById("divErrCaptcha").innerHTML = ""; |
rc = true; |
} |
return rc; |
} |
function validateForm(){ |
var rc = false; |
if( validateUserID('login', 'divErrLogin') && |
validateCaptcha() |
) { |
rc = true; |
} |
return rc; |
} |
function submitHandler(){ |
var rc = validateForm(); |
if(rc) { |
<!-- alert("Base:" + window.location.origin); --> |
UserPasswordReset.action.value = true; |
document.UserPasswordReset.submit(); |
} |
return rc; |
} |
function resetHandler() { |
document.getElementById("login").className = "string widget widgetRw"; |
document.getElementById("divErrLogin").innerHTML = ""; |
document.getElementById("divErrCaptcha").innerHTML = ""; |
document.UserPasswordReset.reset(); |
grecaptcha.reset(); |
document.getElementById("login").focus(); |
return false; |
} |
</script> |
<style> |
table tr { |
height: 21px; |
} |
</style> |
</head> |
<body class="claro"> |
<br><br><br> |
<& '/logo.comp' &><br> |
<h2 align="center">Password Reset Form:</h2> |
<form method="POST" name="UserPasswordReset"> |
<input type="hidden" id="action" name="action" value=false> |
<table align="center" border="0"> |
<tr> |
<td></td> |
<td><BR><div class="g-recaptcha" data-sitekey=<% $r->dir_config('ReCaptchaAPISiteKey') %>></div></td> |
<td><div id="divErrCaptcha" style="color:#FF0000;"></div></td> |
</tr> |
<tr style="height:10px;"></tr> |
<tr> |
<td style="width:33%;"></td> |
<td align="center" style="width:33%; min-width:300px;"><font size="3" color="red">*</font> |
Login utente: |
<input name="login" id="login" size="30" maxlength="60" required=true onblur="validateUserID('login', 'divErrLogin')" class="string widget widgetRw" value="<%$user |js%>"> |
</td> |
<td style="width:33%;"><div id="divErrLogin" style="color:#FF0000;"></div></td> |
</tr> |
<tr style="height:10px;"></tr> |
<tr> |
<td></td> |
<td> |
<input class="widget button" type="button" value="Invio .." onclick="submitHandler()"> |
|
<input class="widget button" style="float: right;" type="button" value="Annulla" onclick="resetHandler()"> |
</td> |
</tr> |
<tr style="height:20px;"></tr> |
<tr> |
<td></td> |
<td> |
<p align="center">Note: <font size="3" color="red">*</font> indica i campi obbligatori.</p> |
</td> |
</tr> |
</table> |
</form> |
<br/> |
<br/> |
<& /copyright.comp &> |
</body> |
</html> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/menu.js |
---|
0,0 → 1,365 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%args> |
$Div |
$mainTab |
</%args> |
<%once> |
my $Timeout = $r->dir_config('GetFormTimeout'); |
</%once> |
require(["dojo/ready", "dijit", "dijit/MenuBar", "dijit/PopupMenuBarItem", "dijit/PopupMenuItem", |
"dijit/Menu", "dijit/MenuItem", "dijit/MenuBarItem", "dijit/registry", "dojo/Evented"], |
function(ready, dijit, MenuBar, PopupMenuBarItem, PopupMenuItem, Menu, MenuItem, MenuBarItem, Registry, Evented){ |
ready(function(){ |
var mainMenuBar = new MenuBar({'class':'menuMasonSql', baseClass:'menuMasonSql', popupDelay:100}); |
var mainTab = Registry.byId('<% $mainTab %>'); |
mainTab.check_readOnly = function(tab, set_ro){ |
// set_ro: force read only if data is not changed |
if(tab && tab.displayBinding){ |
var is_edit = false; |
var db = tab.displayBinding.dataBinding; |
for(var I=0; I<db.children.length; I++){ |
var db_child = db.children[I]; |
if(!db_child.readOnly()){ |
// check if there is a change in the child recordset |
var new_data = []; |
Form2Array(db_child.displayBinding.fields, new_data); |
var difference = ArrayDiffKeys(db_child.keys, db_child.data, new_data, true); |
if(!difference.allNull()){ |
is_edit = true; |
break; |
} |
} |
} |
if(!is_edit && !db.readOnly()){ |
// check if there is a change in the main recordset |
var new_data = []; |
Form2Array(db.displayBinding.fields, new_data); |
var difference = ArrayDiffKeys(db.keys, db.data, new_data, true); |
if(!difference.allNull()){ |
is_edit = true; |
} |
} |
if(is_edit){ |
my_alert('Prima di abbandonare la finestra si deve completare o annullare la modifica in corso'); |
mainTab.selectChild(tab); |
return false; |
} |
if(set_ro){ |
// force read only all recordsets |
for(var I=0; I<db.children.length; I++){ |
var db_child = db.children[I]; |
if(!db_child.readOnly()){ |
db_child.displayBinding.readOnly(true); |
} |
} |
if(!db.readOnly()){ |
db.displayBinding.readOnly(true); |
} |
} |
} |
return true; |
}; |
mainTab.watch("selectedChildWidget", function(name, oval, nval){ |
this.check_readOnly(oval); |
}); |
masonSql.mainTab = mainTab; |
var menuParameters = {}; |
// parametri del Tab |
mainTab.parameterGet = function(par_or_name){ |
if(typeof par_or_name == 'string'){ |
var par = this.menuParameters[par_or_name]; |
if(!par){ |
var err = 'Menu ' + par_or_name + ' inesistente'; |
console.error(err); |
my_alert(err); |
return null; |
} |
return par; |
} |
return par_or_name; |
} |
// metodo per attivare il Tab |
mainTab.activateMenuTab = function(par_or_name, post_handler, visible){ |
var par = this.parameterGet(par_or_name); |
if(!par)return; |
// verifico che il Tab che si abbandona non abbia recordset in modifica |
if(!this.check_readOnly(mainTab.currentTab)){ |
return; |
} |
// verifico se il tab della funzione richiesta è già caricato |
var tab = par.contentPane; |
if(tab){ |
if(!post_handler && tab.displayBinding){ |
post_handler = function(){ |
tab.displayBinding.post_init(); |
tab.displayBinding.loadRecords('rewind'); |
} |
} |
mainTab.displayMenuTab(par, visible, post_handler); |
}else{ |
console.debug('Loading ' + par.title); |
require(["dojox/layout/ContentPane"], function(ContentPane){ |
tab = new ContentPane({ |
title: par.title, |
tooltip: par.descr, |
loadingMessage: 'Caricamento ' + par.title, |
executeScripts: true, |
scriptHasHooks: true, |
parseOnLoad: true, |
closable: true, |
ioArgs: { |
headers: { |
'MasonSql-body': '1' |
}, |
timeout: <% $Timeout %> |
}, |
onClose: function(){ |
if(!mainTab.check_readOnly(this, true)){ |
return false; |
} |
masonSql.mainTab.removeChild(this); |
this._visible = null; |
return false; |
} |
}); |
tab.par = par; |
par.contentPane = tab; |
mainTab.displayMenuTab(par, visible); |
if(par.type == 'u'){ |
tab.set('href', par.cmd).then( |
function(){ |
console.debug('downloaded href', tab); |
if(post_handler){ |
masonSql.once('ready', post_handler); |
} |
masonSql.ready(tab); |
}, |
function(err){ |
tab.set('errorMessage', "<span class='dijitContentPaneError'>"+ |
"<span class='dijitInline dijitIconError'></span>"+err+' id:'+tab.id+' timeout:'+<% $Timeout %>+"</span>"); |
console.error('ERROR href',err , tab); |
} |
); |
}else{ |
tab.set('content', '<script\>'+par.cmd+'</script\>'); |
} |
}); |
} |
mainTab.currentTab = tab; |
%# BEGIN DEPRECATED |
CurrentBody = tab.containerNode; |
%# END DEPRECATED - usato da library/bodyLoad |
return tab; |
}; |
// metodo per cancellare il tab dalla memoria |
mainTab.destroyMenuTab = function(par_or_name){ |
var par = this.parameterGet(par_or_name); |
if(!par)return; |
var tab = par.contentPane; |
// verifico che la pagina da distruggere non abbia dei recordset in modifica |
if(!mainTab.check_readOnly(tab, true)){ |
return false; |
} |
if(par.contentPane){ |
par.contentPane.destroy(); |
par.contentPane = null; |
} |
return true; |
}; |
// visibilità del tab |
mainTab.displayMenuTab = function(par_or_name, visible, post_handler){ |
var par = this.parameterGet(par_or_name); |
if(!par)return; |
var tab = par.contentPane; |
if(!tab)return; |
console.debug('modeMenuTab', tab); |
if(visible == null && tab._visible == false){ |
my_alert('Menu non visibile'); |
return tab; |
} |
if(tab._visible == null && visible == null){ |
tab._visible = false; |
visible = true; |
} |
if(visible == null)visible = true; |
if(visible != tab._visible){ |
if(visible){ |
this.addChild(tab); |
}else if(tab._visible == true){ |
this.removeChild(tab); |
} |
} |
tab._visible = visible; |
if(tab._visible){ |
this.selectChild(tab); |
} |
if(post_handler){ |
post_handler(tab); |
} |
return tab; |
}; |
// Menu parameters |
<& .Menu, menu_father => 'mainMenuBar' &>\ |
mainTab.menuParameters = menuParameters; |
mainMenuBar.placeAt('<% $Div %>'); |
mainMenuBar.startup(); |
dijit.byId('<% $Div %>').getParent().resize(); |
}); |
}); |
%################# costruttore del menù - la chiamata è ricorsiva |
<%def .Menu>\ |
<%args> |
$liv => 0 # livello del menù (il metodo viene chiamato ricorsivamente) |
$father => undef # id padre (usato per la generazione del menù a tendina) |
$menu_father |
</%args> |
<%perl> |
my $menucount=0; |
my $sql = qq{ |
select distinct |
f.id, |
f.nome, |
f.descrizione, |
f.commento, |
f.menu_contents, |
f.menu_status, |
f.menu_command, |
f.menu_cmdtype, |
f.menu_icon, |
f.menu_style, |
f.menu_father_id, |
f.menu_ord, |
(select count(*) from funzioni where menu_father_id = f.id) as children |
from |
funzioni as f, |
gruppi_funzioni as gf, |
anagrafiche_gruppi as ag, |
autorizzazioni as a |
where |
} . ($father ? qq { |
f.menu_father_id = $father and |
} : q{ |
menu_father_id is null and |
}) . q{ |
f.id = gf.id_funzioni and |
gf.id_gruppi = ag.id_gruppi and |
ag.id_anagrafiche = ? and |
gf.id_autorizzazioni = a.id and |
a.nome = 'Menu' and |
f.menu_contents is not null |
order by f.menu_ord; |
}; |
my $sth = $Session{Dbh}->prepare($sql); |
#DEBUG $PLogger->debug(sub{ "execute($Session{User_id} query=[[$sql]])\n"; }); |
$sth->execute($Session{User_id}); |
while(my $row_menu = $sth->fetchrow_hashref){ |
# verifico il livello di permessi per la visualizzazione del menu |
if($Session{Auth}{$row_menu->{'nome'}}{Menu}){ |
if($menucount || $liv){ |
} |
$menucount++; |
my $command = $row_menu->{'menu_command'}; |
$command =~ s/^\s+|\s+$//gs; |
my $type = $row_menu->{'menu_cmdtype'}; |
# se non è selezionato il tipo forzo uri = '' |
if($type){ |
my $cmd = $command; |
if($type eq 'u'){ |
# alla URL aggiungo sempre 'Ver=$Ver' |
$command = $cmd . ($cmd =~ m/\?/ ? "&Ver=$Ver" : "?Ver=$Ver"); |
}elsif($type eq 'U'){ |
$type = 'u'; |
# alla URL aggiungo 'Ver=$Ver' se non fosse già presente |
if($command !~ m/[\?\&]Ver=\$Ver/){ |
# verifico se c'è già quel parametro |
$command .= $command =~ m/\?/ ? '&Ver=$Ver' : '?Ver=$Ver'; |
} |
$command = eval $cmd; |
if($@){ |
die "ERROR eval command ($type) menu $row_menu->{'nome'}\ncommand:[$cmd]\nerror:[$@]\n"; |
} |
}elsif($type eq 'J'){ |
$type = 'j'; |
$command = eval $cmd; |
if($@){ |
die "ERROR eval command ($type) menu $row_menu->{'nome'}\ncommand:[$cmd]\nerror:[$@]\n"; |
} |
} |
}else{ |
$command = ''; |
} |
my $statusText = (length($row_menu->{'menu_status'}) == 0 ) ? "Menu $row_menu->{'menu_contents'}" : $row_menu->{'menu_status'}; |
my $id_sub = $row_menu->{'nome'}; |
$id_sub =~ tr/ \./__/; |
# GDO DEPRECATED (periodo di transizione 2012-2013) |
# Se trovo type=='j' e $command contenente "pageLoad('**', '')" converto il comando in "u" |
# |
if($command =~ /^\s*pageLoad\s*\(\s*'(.*)'\s*,\s*''\s*\);{0,1}\s*$/s || |
$command =~ /^\s*pageLoad\s*\(\s*'(.*)'\s*\);{0,1}\s*$/s || |
$command =~ /^\s*pageLoad\s*\(\s*'(.*)'\s*,\s*null\s*\);{0,1}\s*$/s |
){ |
$type = 'u'; |
$command = $1; |
} |
# GDO DEPRECATED END |
</%perl> |
menuParameters['<% $row_menu->{'nome'} %>'] = { |
nome: '<% $row_menu->{'nome'} |js%>', |
title: '<% $row_menu->{'descrizione'} |js%>', |
descr: '<% $row_menu->{'commento'} |js%>', |
type: '<% $type %>', |
% if($row_menu->{'menu_icon'}){ |
iconClass: 'masonSqlIcons <% $row_menu->{'menu_icon'} %>', |
% } |
style: '<% $row_menu->{'menu_style'} %>', |
cmd: '<% $command |js%>' |
}; |
% if($row_menu->{'children'}){ |
var taskMenu_<%$id_sub%> = new Menu({}); |
<% $menu_father %>.addChild(new PopupMenu<% $liv == 0 ? 'Bar' : '' %>Item({ |
baseClass:'menuMasonSql', |
% if($row_menu->{'menu_icon'}){ |
iconClass: 'masonSqlIcons <% $row_menu->{'menu_icon'} %>', |
% } |
style: '<% $row_menu->{'menu_style'} %>', |
label: '<% $row_menu->{'menu_contents'} |js%>', |
tooltip: '<% $statusText |js%>', |
popup: taskMenu_<%$id_sub%> |
})); |
% $m->comp('.Menu', father => $row_menu->{'id'}, menu_father => "taskMenu_$id_sub", liv => $liv+1); |
% }else{ # children |
<% $menu_father %>.addChild(new Menu<% $liv == 0 ? 'Bar' : '' %>Item({ |
baseClass:'menuMasonSql', |
% if($row_menu->{'menu_icon'}){ |
iconClass: 'masonSqlIcons <% $row_menu->{'menu_icon'} %>', |
% } |
style: '<% $row_menu->{'menu_style'} %>', |
label: '<% $row_menu->{'menu_contents'} |js%>', |
tooltip: '<% $statusText |js%>', |
onClick: function(ev){ // del menu |
if(ev.ctrlKey){ |
// distruggo la pagina eventualmente presente |
if(!mainTab.destroyMenuTab('<% $row_menu->{'nome'} %>')){ |
return; |
} |
} |
mainTab.activateMenuTab('<% $row_menu->{'nome'} %>'); |
} |
})); |
% } #children |
% } |
% } |
</%def> |
/tags/2.0/htdocs/autohandler |
---|
0,0 → 1,151 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%attr> |
Cache_MaxAge => 12*60*60 # validità in cache del Browser del documento |
body_scroll => '' # TAG SCROLL dell'elemento BODY |
</%attr> |
<%once> |
use Log::Log4perl::Level; |
use POSIX qw(strftime); |
</%once> |
<%perl> |
#DEBUG $PLogger->debug(sub{ "Cache-Control max-age=".$m->base_comp->attr('Cache_MaxAge')."\n"; }); |
$r->headers_out->{'Cache-Control'} = 'max-age='.$m->base_comp->attr('Cache_MaxAge'); |
# chiamo il componente figlio in anticipo in quanto questo permette |
# di inizializzare alcune componenti del codice HTML che vanno inserite |
# nella sezione HEADER |
my $body = $m->scomp($m->fetch_next, @_); |
# L'Header MasonSql-body se true, si invia solo il corpo del documento |
# Usato in lib/library.js:bodyLoad |
my $html_head = !$r->headers_in->{'MasonSql-body'}; |
$Session{'Dojo_dir'} = $JSLogger->level() eq $DEBUG ? $r->dir_config('DojoDirUrlDebug') : $r->dir_config('DojoDirUrl'); |
if($html_head){ |
my $expiration_date = strftime "%a %b %e %H:%M:%S %Y GMT", gmtime(time + $m->base_comp->attr('Cache_MaxAge')); |
</%perl> |
<% $r->dir_config('HtmlDocType') %> |
<html> |
<head> |
<title><%$r->dir_config('ApplicationTitle')%></title> |
<& /lib/head_meta.comp, http_equiv => 'Content-Type', content => 'text/html; charset=utf-8' &>\ |
<& /lib/head_meta.comp, http_equiv => 'Content-Language', content => 'Italian' &>\ |
<& /lib/head_meta.comp, http_equiv => 'Expires', content => $expiration_date &>\ |
<& /dojo-modules.comp, Dojo_dir => $Session{'Dojo_dir'} &> |
<%perl> |
# precarico librerie necessarie |
&LoadHeader( |
'/css/main.css', '/lib/library.js', |
'/lib/httpRequestMason.js', '/lib/databinding.js', '/lib/displaybinding.js', |
); |
# caricamento di meta, style e codice javascript richiamato da LoadHeader(...) |
# caricamento include di /lib/head_meta.comp |
foreach my $meta (@{$Global{LoadHeader_Meta}}){ |
$m->out(' '.$meta."\n"); |
} |
# caricamento style |
foreach my $css (@{$Global{LoadHeader_Css}}){ |
$m->out(' '.$css."\n"); |
} |
# caricamento in-line style |
# nel code è possibile inserire definizioni stylesheet aggiuntive che verranno raccolte in questo blocco STYLE |
# sintassi: <&| /lib/head_style.comp, Name => ... &>.... { tag: val; ...} </&> |
if($Global{LoadHeader_Style}){ |
$m->out("<style type=\"text/css\">"); |
foreach my $elem (@{$Global{LoadHeader_Style}}){ |
$m->out($elem."\n"); |
} |
$m->out("</style>\n"); |
} |
</%perl> |
<link rel="shortcut icon" href="/img/icon.ico"> |
<meta name="AUTHOR" content="Brugnara Guido - gdo@leader.it"> |
<meta name="COPYRIGHT" content="Leader.IT di Guido Brugnara; Strada della Pozzata, 41 - Villazzano; 38123 TRENTO (ITALY); info@leader.it"> |
<%perl> |
my $Ver = $Session{Session}; |
if($JSLogger->level() eq $DEBUG){ |
foreach my $js (@{$Global{LoadHeader_Js}}){ |
if($js =~ m/\?/){ |
$js .= "\&Ver=$Ver"; |
}else{ |
$js .= "?Ver=$Ver"; |
} |
$m->out(qq{ <script src="$js" type="text/javascript"></script>\n}); |
} |
}else{ |
$m->out('<script type="text/javascript">'); |
foreach my $js (@{$Global{LoadHeader_Js}}){ |
$m->out("\n//---- [$js]\n"); |
$m->comp($js); |
} |
$m->out('</script>'); |
} |
</%perl> |
</head> |
<body id="bodyMasonSql" class="claro" scroll="<% $m->base_comp->attr('body_scroll') %>"> |
<script> |
require(["dojo/ready"], function(ready){ |
ready(function(){ |
if(window.masonSql){ |
window.masonSql.ready(null); |
}else{ |
console.debug('No masonSql component'); |
} |
}); |
}); |
</script> |
<%perl> |
# # caricamento librerie javascript |
# if($JSLogger->level() ne $DEBUG){ |
# $m->out('<script>'); |
# foreach my $js (@{$Global{LoadHeader_Js}}){ |
# $m->out("\n//---- [$js]\n"); |
# $m->comp($js); |
# } |
# $m->out('</script>'); |
# } |
#### ATTENZIONE BLOCCA SE NON ESISTE - DEBUG!!! |
# if(!$Global{LoadHeader_Body}){ |
# die Dumper(\%Global); |
# } |
foreach my $hbody (@{$Global{LoadHeader_Body}}){ |
$m->out("\n<!-- <HTML_BODY> -->\n"); |
$m->out($hbody); |
$m->out("\n<!-- </HTML_BODY> -->\n"); |
} |
} # if($html_head) |
</%perl> |
<%$body%>\ |
<script> |
% if(@Script_buffer){ |
// Script_buffer BEGIN |
% $m->out(@Script_buffer); |
// Script_buffer END |
% @Script_buffer = (); |
% } |
% if($html_head){ |
window.onunload = function (){ |
try{hReqMason_abort_all()}catch(err){} |
} |
</script> |
</body> |
</html> |
% } |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%shared> |
%Global=(); |
@Script_buffer = (); |
#DEBUG $PLogger->debug(sub{ "/autohandler shared\n"; }); |
# precarico i componenti figli in modo che vengano inizializzati così da influenzare |
# la sezione <head> in base agli include richiesti dai componenti |
#DEBUG $PLogger->debug(sub{ "fetch_next =>",Dumper(\@_); }); |
</%shared> |
/tags/2.0/htdocs/home.html |
---|
0,0 → 1,37 |
<%args> |
$logout => undef |
</%args> |
<br><br> |
<table width="100%"> |
<tr> |
<td width="20%"></td> |
<td align="center" width="30%"> |
<& /logo.comp &> |
</td> |
<td align="center" width="30%"> |
<& /copyright.comp &> |
</td> |
<td width="20%"></td> |
</tr> |
</table> |
<br><br> |
<%perl> |
if(!$logout){ |
# verifico se ci sono nuovi messaggi per l'utente |
my $sth = $Session{Dbh}->prepare(q{ |
SELECT count(*) |
FROM public.messages_users |
WHERE notification_time IS NULL |
AND id_anagrafiche = ?; |
}); |
$sth->execute($Session{User_id}); |
if($sth->fetchrow_arrayref->[0]){ |
# Apro il form dei messaggi utente |
</%perl> |
<script> |
masonSql.mainTab.activateMenuTab('User_messages', null, true); |
</script> |
<%perl> |
} |
} |
</%perl> |
/tags/2.0/htdocs/index.html |
---|
0,0 → 1,74 |
<%attr> |
Cache_MaxAge => 1 |
body_scroll => 'no' # in IE non visualizza la barra di scorrimento |
</%attr> |
<%args> |
$nome_body => "HomePage" |
$bottom => "bottom.html" |
</%args> |
%# META per evitare i "ragni" dei motori di ricerca |
<& /lib/head_meta.comp, name => 'ROBOTS', content => 'noindex' &>\ |
<%init> |
# precaricamento librerie utilizzate dai componenti caricati "OnDemand" |
&LoadHeader('/input/input.comp', '/input/string.comp', '/input/date.comp', |
'/input/span.comp', '/input/number.comp', '/input/select.comp', '/input/url.comp', |
'/input/radio.comp', '/input/checkbox.comp', '/input/form.comp', |
'/input/select.comp', '/input/time.comp', '/input/timestamp.comp', |
'/input/button.comp', '/input/Permission.comp', '/input/Files.comp', |
'/input/htmlselect.comp', '/input/codfisc_pi.comp', '/input/image.comp', |
'/input/file.comp', '/input/color.comp', '/input/divselect.comp', |
'/lib/FCKeditor/fckeditor.js', '/input/FCKeditor.js' |
); |
</%init>\ |
<script> |
require([ |
"dijit/dijit", |
%#DOJO "dojo/parser", |
"dijit/layout/BorderContainer", |
"dijit/layout/ContentPane", |
"dijit/layout/TabContainer" |
]); |
</script> |
<& /index.application.comp &>\ |
<div data-dojo-type="dijit.layout.BorderContainer" design="headline" persist="false" gutters="false" |
style="min-width: 200px; min-height: 100px; z-index: 0; width: 100%; height: 100%;"> |
<div data-dojo-type="dijit.layout.ContentPane" id="TopContent" style="width:100%;" extractContent="false" |
preventCache="false" preload="false" refreshOnShow="false" doLayout="true" |
region="top" splitter="false" maxSize="Infinity" > |
</div> |
<div data-dojo-type="dijit/layout/ContentPane" id="BodyContent" executeScripts="true" extractContent="true" |
preventCache="false" preload="false" refreshOnShow="false" doLayout="true" |
region="center" splitter="false" maxSize="Infinity"> |
<div data-dojo-type="dijit/layout/TabContainer" id="mainTab" style="width: 100%; height: 100%;"> |
</div> |
</div> |
<div data-dojo-type="dijit.layout.ContentPane" id="BottomContent" extractContent="false" preventCache="false" |
preload="false" refreshOnShow="false" doLayout="true" region="bottom" splitter="false" maxSize="Infinity" > |
<& $bottom, Ver => $Ver &> |
</div> |
</div> |
<script> |
<& /menu.js, Div => 'TopContent', mainTab => 'mainTab' &> |
var Body = document.getElementById('BodyContent'); |
var Top = document.getElementById('TopContent'); |
var Bottom = document.getElementById('BottomContent'); |
// Current... puntano al <DIV> corrente (vedi libreria library.js --> pageLoad) |
var CurrentBody; |
require(["dojo/ready", "dijit/registry"], function(ready, registry){ |
ready(function(){ |
// apro il Tab iniziale |
registry.byId('mainTab').activateMenuTab('<% $nome_body %>'); |
% if(my $timeout = $r->dir_config('CheckSessionInterval')){ |
window.timerSession = window.setInterval("hReqMason_ExecuteTimeout('/timerSession.html', <% $r->dir_config('GetRecordTimeout') %>, function(){}, function(){});", <% $timeout %>); |
% } |
window.onbeforeunload = function(event){ |
if(masonSql.onbeforeunload_disabled || masonSql.mainTab.currentTab.par.nome == "CloseSession"){ |
return null; |
} |
var message = "Sei certo di voler chiudere l'applicazione?"; |
event.returnValue = message; |
return message; |
}; |
}); |
}); |
</script> |
/tags/2.0/htdocs/COPYRIGHT |
---|
0,0 → 1,17 |
# --------------------------------------------------------------------------- # |
# Copyright: (C) 2003-2017 Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# E-mail: info@leader.it |
# |
# Note: The authors with the rispettive contributions are available |
# in restricted access of SVN repository at |
# https://www.leader.it/wsvn/masonsql |
# Open Source releases are free accessible on SVN repository at: |
# https://guest@www.leader.it/wsvn/masonsql/tags |
# --------------------------------------------------------------------------- # |
# |
# Double licence are available, if requested, with differents prices and conditions: |
# - Commercial licence (all releases) |
# - AGPL Affero General Public Licence Rel.1 ( http://www.affero.org/oagpl.html ) |
# (Releases 1.6 & 1.9) |
/tags/2.0/htdocs/UserRegistrationForm.html |
---|
0,0 → 1,393 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2016-2020 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Rajesh Madaye <rajeshmadaye@yahoo.com> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%args> |
$action => undef |
</%args> |
<%attr> |
Cache_MaxAge => 120 |
</%attr> |
<% $r->dir_config('HtmlDocType') %> |
<%once> |
use Auth_AC::UserRegistration; |
my $LoginType = $r->dir_config('LoginType'); |
my $UserRegTypeMessage = $r->dir_config('UserRegTypeMessage'); |
my $UR = Auth_AC::UserRegistration->new(); |
</%once> |
<%init> |
# connessione al database |
my $dbh = $Session{Dbh}; |
## Functional processing |
my $form_submit_status = 0; |
if(defined $action and $action eq "true") { |
$form_submit_status = $UR->process_registration_form(dbh => $dbh, formdata => \%ARGS, r => $r, m => $m); |
} |
</%init> |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<html> |
<head> |
% my $Dojo_dir = $JSLogger->level() eq $DEBUG ? $r->dir_config('DojoDirUrlDebug') : $r->dir_config('DojoDirUrl'); |
<script src="https://www.google.com/recaptcha/api.js?hl=it"></script> |
<script src="<% $Dojo_dir %>/dojo/dojo.js" type="text/javascript" data-dojo-config="async: false, |
isDebug:<% $JSLogger->level() eq $DEBUG ? 'true' : 'false'%>, parseOnLoad:true, locale: 'it'"></script> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/dijit.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/document.css" type="text/css"> |
<link rel="stylesheet" href="<% $Dojo_dir %>/dijit/themes/claro/claro.css" type="text/css"> |
<link rel="stylesheet" href="/css/main.css" type="text/css"> |
<script> |
// Code to confirm form submission acknowledgement. |
% if(defined $action and $action eq "true") { |
% if($form_submit_status) { |
%# alert("Thank you for registration on MasonSQL portal. Please check your <% $UserRegTypeMessage %> to get initial password to login"); |
alert("Grazie per esserti registrato!\nControlla <% $UserRegTypeMessage eq 'sms' ? 'nel tuo cellulare il messaggio SMS' : 'nella posta in arrivo il messaggio' %> con la password iniziale per collegarti."); |
window.location.replace('/'); |
resetHandler(); |
% } else { |
%# alert("Registration failed. Please try again with valid input values."); |
alert("Registrazione fallita!\nSi prega di ripetere la registrazione con dei dati validi."); |
% } |
% } |
// Code to process core functionality. |
var JSLoginType = null; |
function validateEmail() { |
var email = document.getElementById("email"); |
var atpos = email.value.indexOf("@"); |
var dotpos = email.value.lastIndexOf("."); |
var rc = false; |
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=email.length) { |
document.getElementById("divErrEmail").innerHTML = "<p>Inserisci e-mail valido</p>"; |
document.getElementById("email").className = "string widget widgetRwError"; |
//document.getElementById("email").focus(); |
rc = false; |
} else { |
document.getElementById("divErrEmail").innerHTML = ""; |
document.getElementById("email").className = "string widget widgetRw"; |
rc = true; |
} |
return rc; |
} |
function validateCellSMS() { |
var rc = false; |
% if($UserRegTypeMessage eq 'sms') { |
var cellNum = document.getElementById("cell_sms"); |
if (!validatePhoneNumber(cellNum)) { |
document.getElementById("divErrCellSMS").innerHTML = "<p>numero di telefono invalido</p>"; |
document.getElementById("cell_sms").className = "string widget widgetRwError"; |
rc = false; |
} else { |
document.getElementById("divErrCellSMS").innerHTML = ""; |
document.getElementById("cell_sms").className = "string widget widgetRw"; |
rc = true; |
}; |
% }elsif($UserRegTypeMessage eq 'email'){ |
rc = true; |
% } |
return rc; |
} |
function validatePhoneNumber(inputtxt) { |
var rc = false; |
var email = document.getElementById("cell_sms"); |
if(!isEmpty(inputtxt)) { |
var phoneno = /^([0-9]{9,11})$/; |
if(inputtxt.value.match(phoneno)) { |
rc = true; |
} else { |
rc = false; |
} |
} |
return rc; |
} |
function validateEmpty(sourceEleId, errorEleId) { |
var element =document.getElementById(sourceEleId).value; |
var rc = false; |
element = element.replace(/^\s+|\s+$/g, ''); |
if (element.length < 1) { |
document.getElementById(errorEleId).innerHTML = "<p>Si prega di inserire il valore</p>"; |
document.getElementById(sourceEleId).className = "string widget widgetRwError"; |
rc = false; |
} else { |
document.getElementById(errorEleId).innerHTML = ""; |
document.getElementById(sourceEleId).className = "string widget widgetRw"; |
rc = true; |
} |
return rc; |
} |
function isUserExists(usrId) { |
usrId = usrId.toLowerCase(); |
var is_usr_exists = ""; |
var url = window.location.origin + "/UserRegistrationLoginCheck.txt?login=" + usrId; |
require(["dojo/request/xhr", "dojo/dom", "dojo/dom-construct", "dojo/json", "dojo/on", "dojo/domReady!"], |
function(xhr, dom, domConst, JSON, on){ |
xhr(url, { |
handleAs: "text", |
sync: true, |
}).then(function(response){ |
is_usr_exists = response; |
}); |
}); |
return is_usr_exists; |
} |
function isEmpty(str) { |
return (!str || 0 === str.length); |
} |
function validateUserID(sourceEleId, errorEleId) { |
var element = document.getElementById(sourceEleId).value; |
element = element.replace(/^\s+|\s+$/g, ''); |
rc = false; |
JSLoginType = "<% $LoginType %>"; |
var userIDMsg = ""; |
if(validateEmpty(sourceEleId, errorEleId)) { |
if(JSLoginType == 'email') { |
if(validateEmail()) { |
userIDMsg = isUserExists(element); |
if(isEmpty(userIDMsg)) { |
document.getElementById(errorEleId).innerHTML = ""; |
document.getElementById(sourceEleId).className = "string widget widgetRw"; |
rc = true; |
} else { |
document.getElementById(errorEleId).innerHTML = "<p>"+userIDMsg+"</p>"; |
document.getElementById(sourceEleId).className = "string widget widgetRwError"; |
//document.getElementById(sourceEleId).focus(); |
} |
} |
} else if(JSLoginType == 'syslogin') { |
userIDMsg = isUserExists(element); |
if(isEmpty(userIDMsg)) { |
document.getElementById(errorEleId).innerHTML = ""; |
document.getElementById(sourceEleId).className = "string widget widgetRw"; |
rc = true; |
} else { |
document.getElementById(errorEleId).innerHTML = "<p>"+userIDMsg+"</p>"; |
document.getElementById(sourceEleId).className = "string widget widgetRwError"; |
//document.getElementById(sourceEleId).focus(); |
} |
} |
} |
return rc; |
} |
function validateCaptcha() { |
var rc = false; |
var captcha_value = document.getElementById("g-recaptcha-response").value; |
if(isEmpty(captcha_value)) { |
document.getElementById("divErrCaptcha").innerHTML = "<p>Si prega di risolvere i captcha</p>"; |
} else { |
document.getElementById("divErrCaptcha").innerHTML = ""; |
rc = true; |
} |
return rc; |
} |
function validateForm(){ |
var rc = false; |
if( validateEmpty('nome', 'divErrNome') && |
validateEmpty('cognome', 'divErrCognome') && |
validateEmail() && |
validateCellSMS() && |
validateCaptcha() |
) { |
var is_valid_user = null; |
if(JSLoginType === "email") { |
is_valid_user = validateUserID('email', 'divErrEmail'); |
<!-- When login type is syslogin then email will be login --> |
UserRegistration.login.value = UserRegistration.email.value; |
} else { |
is_valid_user = validateUserID('login', 'divErrLogin'); |
} |
if(is_valid_user) { |
rc = true; |
} |
} |
return rc; |
} |
function submitHandler(){ |
var rc = validateForm(); |
if(rc) { |
<!-- alert("Base:" + window.location.origin); --> |
UserRegistration.action.value = true; |
document.UserRegistration.submit(); |
} |
return rc; |
} |
function resetHandler() { |
document.getElementById("nome").className = "string widget widgetRw"; |
document.getElementById("cognome").className = "string widget widgetRw"; |
document.getElementById("email").className = "string widget widgetRw"; |
document.getElementById("login").className = "string widget widgetRw"; |
document.getElementById("cell_sms").className = "string widget widgetRw"; |
document.getElementById("divErrNome").innerHTML = ""; |
document.getElementById("divErrCognome").innerHTML = ""; |
document.getElementById("divErrEmail").innerHTML = ""; |
document.getElementById("divErrLogin").innerHTML = ""; |
document.getElementById("divErrCaptcha").innerHTML = ""; |
document.getElementById("divErrCellSMS").innerHTML = ""; |
document.UserRegistration.reset(); |
grecaptcha.reset(); |
document.getElementById("nome").focus(); |
return false; |
} |
</script> |
<style> |
table tr { |
height: 21px; |
} |
</style> |
</head> |
<body class="claro"> |
<br><br><br> |
<& /logo.comp &> |
<form method="POST" name="UserRegistration"> |
<input type="hidden" id="action" name="action" value=false> |
<h2 align="center">Modulo di registrazione nuovo utente:</h2> |
<table align="center" border="0"> |
<tr style="height:0;"> |
<td style="width:33%;"></td> |
<td></td> |
<td></td> |
<td style="width:33%;"></td> |
</tr> |
<tr> |
<td></td> |
<td align="right"><font size="3" color="red">*</font>Nome:</td> |
<td><input type="text" name="nome" id="nome" value="" size="30" maxlength="20" required=true onblur="validateEmpty('nome', 'divErrNome')" autofocus class="string widget widgetRw"></td> |
<td><div id="divErrNome" style="color:#FF0000"></div></td> |
</tr> |
<tr> |
<td></td> |
<td align="right"><font size="3" color="red">*</font>Cognome:</td> |
<td><input type="cognome" name="cognome" id="cognome" size="30" maxlength="25" required=true onblur="validateEmpty('cognome', 'divErrCognome')" class="string widget widgetRw"></td> |
<td><div id="divErrCognome" style="color:#FF0000"></div></td> |
</tr> |
% if($LoginType eq 'syslogin'){ |
<tr> |
<td></td> |
<td align="right"><font size="3" color="red">*</font>E-Mail:</td> |
<td><input name="email" id="email" size="30" maxlength="60" required=true onblur="validateEmail()" class="string widget widgetRw"></td> |
<td><div id="divErrEmail" style="color:#FF0000"></div></td> |
</tr> |
<tr> |
<td></td> |
<td align="right"><font size="3" color="red">*</font>Nome utente:</td> |
<td><input name="login" id="login" size="30" maxlength="60" required=true onblur="validateUserID('login', 'divErrLogin')" class="string widget widgetRw"></td> |
<td><div id="divErrLogin" style="color:#FF0000"></div></td> |
</tr> |
% }elsif($LoginType eq 'email'){ |
<tr> |
<td></td> |
<td align="right"><font size="3" color="red">*</font>E-Mail utente:</td> |
<td><input name="email" id="email" size="30" maxlength="60" required=true onblur="validateUserID('email', 'divErrEmail')" class="string widget widgetRw"></td> |
<td><div id="divErrEmail" style="color:#FF0000"></div></td> |
</tr> |
<tr> |
<td></td> |
<td><input name="login" id="login" size="30" maxlength="60" required=true type="hidden" ></td> |
<td><div id="divErrLogin" style="color:#FF0000" type="hidden"></div></td> |
</tr> |
% } |
% my %UserRegOptionalFields = map { $_ => 1 } split(/\s+/, $r->dir_config('UserRegOptionalFields')); |
% if($UserRegTypeMessage eq 'sms' or $UserRegOptionalFields{'cell_sms'}){ |
<tr> |
<td></td> |
<td align="right"> |
% if($UserRegTypeMessage eq 'sms') { |
<font size="3" color="red">*</font> |
% } |
 Cell. SMS: |
</td> |
<td><input type="text" name="cell_sms" id="cell_sms" value="" size="30" maxlength="20" required=true onblur="validateCellSMS()" class="string widget widgetRw"></td> |
<td><div id="divErrCellSMS" style="color:#FF0000"></div></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'codice_fiscale'}){ |
<tr> |
<td></td> |
<td align="right"> Codice Fiscale:</td> |
<td><input name="codice_fiscale" id="codice_fiscale" size="30" maxlength="16" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'descrizione'}){ |
<tr> |
<td></td> |
<td align="right"> Descrizione:</td> |
<td><input name="descrizione" id="descrizione" size="30" maxlength="60" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'indirizzo'}){ |
<tr> |
<td></td> |
<td align="right"> Indirizzo:</td> |
<td><input name="indirizzo" id="indirizzo" size="30" maxlength="60" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'provincia'}){ |
<tr> |
<td></td> |
<td align="right"> Provincia:</td> |
<td><input name="provincia" id="provincia" size="30" maxlength="2" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'citta'}){ |
<tr> |
<td></td> |
<td align="right"> Città:</td> |
<td><input name="citta" id="citta" size="30" maxlength="20" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'tele1'}){ |
<tr> |
<td></td> |
<td align="right"> Telefono:</td> |
<td><input name="tele1" id="tele1" size="30" maxlength="20" class="string widget widgetRw"></td> |
</tr> |
% } |
% if($UserRegOptionalFields{'tele2'}){ |
<tr> |
<td></td> |
<td align="right"> 2° Telefono:</td> |
<td><input name="tele2" id="tele2" size="30" maxlength="20" class="string widget widgetRw"></td> |
</tr> |
% } |
<tr> |
<td></td> |
<td colspan="2"><div class="g-recaptcha" data-sitekey=<% $r->dir_config('ReCaptchaAPISiteKey') %>></div></td> |
<td><div id="divErrCaptcha" style="color:#FF0000"></div></td> |
</tr> |
<tr style="height:10px;"></tr> |
<tr> |
<td></td> |
<td><input class="widget button" type="button" value="Invio la richiesta ..." onclick="submitHandler()"></td> |
<td><input class="widget button" style="float:right;" type="button" value="Annulla" onclick="resetHandler()"></td> |
</tr> |
</table> |
<br> |
<p align="center"> Note : <font size="3" color="red">*</font> indica i campi obbligatori.</p> |
</form> |
<br><br> |
<& /copyright.comp &> |
</body> |
</html> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/welcome.html |
---|
0,0 → 1,5 |
%# Usato da ./lib/httpRequestMason.js |
<& "/home.html" &> |
<script> |
setTimeout("window.close();", 1500); |
</script> |
/tags/2.0/htdocs/UpiPrinterServer.txt |
---|
0,0 → 1,37 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2007 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# |
# utilizzato da UpiPrinterServer per prelevare lo spool da inviare alla stampante locale |
</%doc> |
<%args> |
$file #nome del file contenente lo spool da inviare |
</%args> |
<%perl> |
if($file =~ m/\.\./){ |
$m->abort(FORBIDDEN); |
} |
my $filename = $r->dir_config('TmpDir').'/'.$file.'.prn'; |
if(!open(FILE, "<$filename")){ |
$m->abort(NOT_FOUND); |
} |
$m->clear_buffer; |
$r->content_type('application/upi-printer-server'); |
while(<FILE>){ |
$m->out($_); |
} |
close FILE; |
unlink $filename; |
</%perl> |
<%flags> |
inherit => undef |
</%flags> |
<%init> |
use Apache2::Const qw(FORBIDDEN NOT_FOUND); |
</%init> |
/tags/2.0/htdocs/UserRegistrationLoginCheck.txt |
---|
0,0 → 1,31 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%args> |
$login |
</%args> |
<%perl> |
$r->content_type('text/plain; charset=utf-8'); |
$m->clear_buffer; |
#DEBUG print STDERR "Login::[$login]\n"; |
length($login) || return; |
# verifico che la login indicata non sia già presente |
my $sth = $Session{Dbh}->prepare(q{ |
select id from public.anagrafiche where login = ? |
}); |
$sth->execute($login); |
if($sth->rows){ |
</%perl>\ |
La login (<% $login %>) è già utilizzata. |
% } |
<%perl> |
# verifico che la login indicata non sia tra quelle proibite |
$sth = $Session{Dbh}->prepare(q{ |
select id from public.reserved_login where login = ? |
}); |
$sth->execute($login); |
if($sth->rows){ |
</%perl>\ |
La login (<% $login %>) è riservata. |
% } |
%#end. |
/tags/2.0/htdocs/blank.html |
---|
0,0 → 1,7 |
<%flags> |
inherit => undef # nessun parente |
</%flags> |
% $r->headers_out->{'Cache-Control'} = 'max-age=999999999'; |
<%filter> |
$_=''; |
</%filter> |
/tags/2.0/htdocs/bottom.html |
---|
0,0 → 1,6 |
Utente: <%$Session{Login}%><% $Session{Nominativo} ? " - $Session{Nominativo}" : '' %> |
Gruppi: <% $Session{Groups} ? join(',', @{$Session{Groups}}) : 'nessuno' %> |
Connessione: <% $browser_address %> |
<%init> |
my $browser_address = $ENV{HTTP_X_FORWARDED_HOST} ? $ENV{HTTP_X_FORWARDED_FOR} : $ENV{REMOTE_ADDR}; |
</%init> |
/tags/2.0/htdocs/SMSTemplateUserRegistration.comp |
---|
0,0 → 1,21 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%method Subject>Successful Registration on MasonSQL</%method> |
<%method Body> |
<%args> |
$nome |
$baseurl |
$login |
$password |
$regActDays |
</%args> |
Dear <% $nome %>: |
Thank you for creating your account on MasonSQL. Your username is <% $login %> and password is <% $password %>. Please activate your account within next <% $regActDays %> days from today. |
Thanks, |
MasonSQL |
</%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/MailTemplatePasswordReset.comp |
---|
0,0 → 1,37 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%method Subject>Successful Password Reset on MasonSQL</%method> |
<%method Body> |
<%args> |
$nome |
$baseurl |
$login |
$password |
$regActDays |
</%args> |
_____________________________________________________ |
MasonSQL Framework |
_____________________________________________________ |
Dear user, |
your password has been reset and it must be activated within next <% $regActDays %> days from today. |
To activate the account, please use following credentials and login into MasonSQL framework. |
Login Page : <% $baseurl %> |
User Name : <% $login %> |
Password : <% $password %> |
In case there are any questions regarding MasonSQL framework please contact the administrator. |
Warm regards, |
MasonSQL Development Team |
_____________________________________________________ |
This is an auto-generated email, please DO NOT REPLY. |
Any replies to this email will be disregarded. |
_____________________________________________________ |
</%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/SMSTemplatePasswordReset.comp |
---|
0,0 → 1,21 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%method Subject>Successful Password Reset on MasonSQL</%method> |
<%method Body> |
<%args> |
$nome |
$baseurl |
$login |
$password |
$regActDays |
</%args> |
Dear <% $nome %>: |
Your password has been reset. Your username is <% $login %> and password is <% $password %>. Please activate your account within next <% $regActDays %> days from today. |
Thanks, |
MasonSQL |
</%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/MailTemplateUserRegistration.comp |
---|
0,0 → 1,38 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%method Subject>Successful Registration on MasonSQL</%method> |
<%method Body> |
<%args> |
$nome |
$baseurl |
$login |
$password |
$regActDays |
</%args> |
_____________________________________________________ |
MasonSQL Framework |
_____________________________________________________ |
Dear user <% $nome %>, |
thank you for registering at Mason based web application framework MasonSQL. |
Your account is created and must be activated within next <% $regActDays %> days from today. |
To activate the account, please use following credentials and login into MasonSQL framework: |
Login Page : <% $baseurl %> |
User Name : <% $login %> |
Password : <% $password %> |
In case there are any questions regarding MasonSQL framework please contact the administrator. |
Warm regards, |
MasonSQL Development Team |
_____________________________________________________ |
This is an auto-generated email, please DO NOT REPLY. |
Any replies to this email will be disregarded. |
_____________________________________________________ |
</%method> |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/dojo-modules.comp |
---|
0,0 → 1,13 |
%# Dojo modules |
<%args> |
$Dojo_dir => $Session{'Dojo_dir'} |
</%args> |
<script src="<% $Dojo_dir %>/dojo/dojo.js" type="text/javascript" |
data-dojo-config="async: false, isDebug:<% $JSLogger->level() eq $DEBUG ? 'true' : 'false'%>, parseOnLoad:true, locale: 'it'"> |
</script> |
<link rel="stylesheet" href="<%$Dojo_dir%>/dijit/themes/dijit.css" type="text/css"> |
<link rel="stylesheet" href="<%$Dojo_dir%>/dijit/themes/claro/document.css" type="text/css"> |
<link rel="stylesheet" href="<%$Dojo_dir%>/dijit/themes/claro/claro.css" type="text/css"> |
<link rel="stylesheet" href="<%$Dojo_dir%>/dojox/widget/Dialog/Dialog.css" type="text/css"> |
<link rel="stylesheet" href="<%$Dojo_dir%>/dojox/widget/ColorPicker/ColorPicker.css" type="text/css"> |
/tags/2.0/htdocs/UserRegistrationResetCheck.txt |
---|
0,0 → 1,27 |
<%flags> |
inherit => '/init.comp' |
</%flags> |
<%args> |
$login |
</%args> |
<%once> |
my $UserRegTypeMessage = $r->dir_config('UserRegTypeMessage'); |
</%once> |
<%perl> |
$r->content_type('text/plain; charset=utf-8'); |
$m->clear_buffer; |
# verifico che la login indicata non sia già presente |
my $sth = $Session{Dbh}->prepare(q{ |
select id, email, cell_sms from public.anagrafiche where login = ? |
}); |
$sth->execute($login); |
if($sth->rows){ |
my $user = $sth->fetchrow_hashref; |
if(!defined $user->{$UserRegTypeMessage eq 'sms' ? 'cell_sms' : 'email'}){ |
$m->out(($UserRegTypeMessage eq 'sms' ? 'numero sms' : 'indirizzo e-mail').' non definito'); |
} |
}else{ |
$m->out('Utente inesistente'); |
} |
</%perl> |
%#end. |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/htdocs/change_password.html |
---|
0,0 → 1,95 |
<%doc> |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2015 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
</%doc> |
<%attr> |
Cache_MaxAge => 120 |
</%attr> |
% my $MinPasswordChars = ''.$r->dir_config('MinPasswordChars'); |
<& '/logo.comp' &> |
<script> |
function change_password_submit_password(){ |
// campi di input password |
var passwd1 = document.getElementById('change_password_passwd1'); |
var passwd2 = document.getElementById('change_password_passwd2'); |
% if($Session{Group_Admins}){ |
var login = document.getElementById('change_password_login'); |
% } |
// verifico se le due password inserite sono uguali |
if(passwd1.value != passwd2.value){ |
alert('Le password inserite sono differenti.\nReinserire la password correttamente!'); |
passwd1.value = ''; |
passwd2.value = ''; |
return false; |
} |
if(passwd1.length < <%$MinPasswordChars%>){ |
alert('La password deve essere di almeno <%$MinPasswordChars%> caratteri'); |
psw = ''; |
return false; |
} |
%# // trasmetto la nuova password al server |
hReqMason_ExecuteTimeout( |
'/change_password.txt', |
<%$r->dir_config('GetRecordTimeout')%>, |
function (contextID, err, str){ |
// timeout |
alert(str); |
}, |
function (str, contextID){ |
// callback |
alert(str); |
}, |
'change_password', |
% if($Session{Group_Admins}){ |
{Login:login.value, Password:passwd1.value} |
% }else{ |
{Password:passwd1.value} |
% } |
); |
passwd1.value = ''; |
passwd2.value = ''; |
% if($Session{Group_Admins}){ |
if(login.value != '<%$Session{Login}%>'){ |
login.value = ''; |
} |
% } |
return false; |
} |
</script> |
<table align="center"> |
<tr><td> |
<p align="center"> |
<br><br> |
</td></tr> |
<tr><td> |
<table align="center"> |
<tr> |
<td align="right"><b>Cambio password utente:</b></td> |
% if($Session{Group_Admins}){ |
<td><input type="text" id="change_password_login" size="18" length="18" value="<%$Session{Login}%>"></td> |
% }else{ |
<td><%$Session{Login}%> <%$Session{Nominativo}%></td> |
% } |
</tr> |
<tr> |
<td align="right"><b>Password:</b></td> |
<td><input type="password" id="change_password_passwd1" size="18" length="18"></td> |
</tr> |
<tr> |
<td align="right"><b>Ripeti password:</b></td> |
<td><input type="password" id="change_password_passwd2" size="18" length="18"></td> |
</tr> |
</table> |
</td></tr> |
<tr> |
<td colspan="2" align="center"> |
<input type="button" value="Cambio password ..." onclick="change_password_submit_password();"> |
</td> |
</tr> |
</table> |
/tags/2.0/htdocs/privacy.comp |
---|
--- 2.0/htdocs/release_notes.html (nonexistent) |
+++ 2.0/htdocs/release_notes.html (revision 806) |
@@ -0,0 +1,12 @@ |
+<br> |
+<br> |
+<br> |
+<& "/logo.comp" &> |
+<H3 align="center">Release Notes</H3> |
+<p align="center"> |
+ <& /privacy.comp &> |
+</p> |
+<br> |
+<p align="center"> |
+ <& /copyright.comp &> |
+</p> |
/tags/2.0/htdocs/favicon.ico |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/timerSession.html |
---|
0,0 → 1,6 |
<%doc> |
Usato da index.html per rinnovare periodicamente il timer della sessione |
</%doc> |
<%flags> |
inherit => undef |
</%flags> |
/tags/2.0/htdocs/copyright.comp |
---|
0,0 → 1,5 |
<p style="font-size: 9pt; color: #604040;" align="center"> |
Copyright (©) framework MasonSQL: from <A href="http://www.leader.it/">Leader.IT</A> |
<br> |
<% $r->dir_config('CopyrightMessage') %> |
</p> |
/tags/2.0/htdocs/img/cerca.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/img/icon.ico |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/img/spacer.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/img/cestino.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/img/edit.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/img/add.gif |
---|
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes: |
Added: svn:mime-type |
+application/octet-stream |
\ No newline at end of property |
/tags/2.0/htdocs/index.application.comp |
---|
--- 2.0/htdocs/release_notes.application.comp (nonexistent) |
+++ 2.0/htdocs/release_notes.application.comp (revision 806) |
@@ -0,0 +1,4 @@ |
+<%doc> |
+Viene richiamata da /release_notes.comp |
+Da utilizzare per l'applicazione |
+</%doc> |
/tags/2.0/htdocs/init.application.comp |
---|
0,0 → 1,4 |
<%doc> |
Viene richiamata da /init.comp |
Da utilizzare per l'applicazione |
</%doc> |
/tags/2.0/report/Xrepmand.sh |
---|
0,0 → 1,56 |
#!/bin/bash |
# --------------------------------------------------------------------------- # |
# Copyright: (C) 2020 Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# E-mail: info@leader.it |
# |
# Note: The authors with the rispettive contributions are available |
# in restricted access of SVN repository at |
# https://www.leader.it/wsvn/masonsql |
# --------------------------------------------------------------------------- # |
# The scrpt open repmand (Reportman editor) in a virtual magnified VNC server |
# so you can open using VNC clients and use with usable font size |
if [ "$USER" != "www-data" ] |
then |
echo "$0 deve essere eseguito dall'utente www-data" >&2 |
exit 1 |
fi |
if [ ! -f ~/.vnc/passwd ] |
then |
x11vnc -storepasswd |
fi |
export DISPLAY=${1:-:1} |
[[ "$DISPLAY" =~ ^: ]] || DISPLAY=":$DISPLAY" |
SCREEN=${2:-1400x1000} |
SCALE=${3:-1.5} |
VNC_PORT=${DISPLAY#:} |
let VNC_PORT=VNC_PORT+5900 |
Xvfb $DISPLAY -screen 0 ${SCREEN}x16 & |
PID0=$! |
fluxbox & |
./repmand.sh & |
PID1=$! |
x11vnc -display $DISPLAY -rfbport $VNC_PORT -bg -xkb -scale $SCALE -reopen -rfbauth ~/.vnc/passwd -rmflag ~/.vnc/x11vnc.$$.pid -nevershared -forever |
PID2=$(cat ~/.vnc/x11vnc.$$.pid) |
let PID2=PID2+1 |
rm ~/.vnc/x11vnc.$$.pid |
echo -e "\n\nPer aprire lo schermo in rete locale: vncviewer $(hostname -f)$DISPLAY" |
trap "kill $PID0 $PID1 $PID2" SIGINT SIGTERM |
while sleep 1 |
do |
if ! ps -p $PID1 >/dev/null |
then |
kill $PID0 2>/dev/null |
kill $PID2 2>/dev/null |
exit |
fi |
done |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/report/repmand.sh |
---|
0,0 → 1,44 |
#!/bin/bash |
#Enable this setting if you have problems starting the application |
#for example in suse 7.3 starting from a vncserver |
#export CLX_USE_LIBQT=true |
#Enable this setting if you have not defined the LANG variable in your system |
#export LANG=en_US |
export LANG=it_IT.ISO-8859-15@euro |
#export LC_CTYPE="" |
export PGCLIENTENCODING=LATIN9 |
#Bug fix in some distros need LC_NUMERIC en_US or print will not work |
#That is to enable a bugfix, use it only if print does not work |
#export LC_NUMERIC=en_US |
#Use this env.variables to override language locale |
export KYLIX_DEFINEDENVLOCALES=Yes |
export KYLIX_THOUSAND_SEPARATOR=. |
export KYLIX_DECIMAL_SEPARATOR=, |
export KYLIX_DATE_SEPARATOR=/ |
export KYLIX_TIME_SEPARATOR=: |
#You can share libraries copying libs to a directory |
#for example /opt/kylixlibs and add the path to ld.so.conf |
#then run ldconfig (as root) |
DIR="/opt/masonsql/report" |
export DISPLAY |
# verifico se è definita la cartella di configurazione |
if [ ! -e "$HOME/.borland" ] |
then |
echo "Manca la cartella dei driver" |
echo "Vedi di configurarla, ad esempio con" |
echo " ln -s /opt/<MYAPPDIR>/etc/<MYHOST>.borland $HOME/.borland" |
exit 1 |
fi |
# file stampanti necessario, anche se vuoto |
[ -f /etc/printcap ] || > /etc/printcap |
#export HOME=$DIR |
#export USER=www-data |
export LD_LIBRARY_PATH=$DIR/:$DIR/rpdesigner-2_9a/:$LD_LIBRARY_PATH |
exec $DIR/rpdesigner-2_9a/repmand $* |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/report/printreptopdf.wine |
---|
0,0 → 1,17 |
#!/bin/bash |
export LANG=it_IT.UTF-8 |
export HOME=/opt/masonsql/report/www-data_home_dir |
export USER=www-data |
# ricerco la cartella di installazione |
PATH="$HOME/.wine/drive_c/" |
if [ -d "$PATH/Program Files (x86)" ] |
then |
PATH="Program Files (x86)" |
else |
PATH="Program Files" |
fi |
echo "# /usr/bin/wine \"C:\\$PATH\\Report Manager\\printreptopdf.exe\" "$* >/opt/masonsql/report/log |
/usr/bin/wine "C:\\$PATH\\Report Manager\\printreptopdf.exe" $* >>/opt/masonsql/report/log 2>&1 |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/report/printreptopdf.kylix |
---|
0,0 → 1,31 |
#!/bin/bash |
#Enable this setting if you have problems starting the application |
#for example in suse 7.3 starting from a vncserver |
#export CLX_USE_LIBQT=true |
#Enable this setting if you have not defined the LANG variable in your system |
#export LANG=en_US |
export LANG=it_IT.ISO-8859-15@euro |
export LC_CTYPE="" |
export PGCLIENTENCODING=LATIN9 |
#Bug fix in some distros need LC_NUMERIC en_US or print will not work |
#That is to enable a bugfix, use it only if print does not work |
#export LC_NUMERIC=en_US |
#Use this env.variables to override language locale |
export KYLIX_DEFINEDENVLOCALES=Yes |
export KYLIX_THOUSAND_SEPARATOR=. |
export KYLIX_DECIMAL_SEPARATOR=, |
export KYLIX_DATE_SEPARATOR=/ |
export KYLIX_TIME_SEPARATOR=: |
#You can share libraries copying libs to a directory |
#for example /opt/kylixlibs and add the path to ld.so.conf |
#then run ldconfig (as root) |
DIR=${0%/*} |
export HOME=$DIR |
export USER=www-data |
echo "# $DIR/rpservercline-2_9a/printreptopdf $*" >/opt/masonsql/report/log |
# versione 2_9a |
export LD_LIBRARY_PATH=$DIR:$LD_LIBRARY_PATH |
exec $DIR/rpservercline-2_9a/printreptopdf $* >>/opt/masonsql/report/log 2>&1 |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/report/repmandxp.sh |
---|
0,0 → 1,3 |
#!/bin/bash |
/usr/bin/wine "C:\Program Files (x86)\Report Manager\repmandxp.exe" $* |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/report/LEGGIMI |
---|
0,0 → 1,22 |
"Report Manager Designer Version 2_9a" |
Author: Toni Martir |
toni@pala.com (no free support) |
http://reportman.sourceforge.net |
INSTALLAZIONE: |
* Copiare i file della distribuzione ( rpservercline-2_9a.i386.tar.gz ) in /opt/masonsql/report/rpservercline-2_9a: |
* Modificare lo script /opt/masonsql/report/printreptopdf.sh adattando il comando che punta all'eseguibile in /opt/masonsql/report/rpservercline-2_9a/printreptopdf |
* Creare il link per eseguire da utente root i comandi di test: /root/.borland => /opt/masonsql/report/.borland |
* L'applicazione crea il link /opt/masonsql/report/.borland -> /opt/APPLICAZIONE/etc/******.borland (vedi file di conf.) alla prima connessione |
In PostgreSQL lanciare il comando: |
CREATE DOMAIN BLOB as bytea |
per la gestione delle immagini. |
/tags/2.0/lib/Auth_AC/AuthCookieHandler.pm |
---|
0,0 → 1,562 |
############################################################################################ |
package Auth_AC::AuthCookieHandler; |
use strict; |
use utf8; |
use DBI; |
use vars qw($VERSION @ISA); |
$VERSION = substr(q$Revision: 1.2 $, 10); |
use base 'Apache2_4::AuthCookie'; |
use Digest::MD5 qw(md5_hex); |
use String::Random; |
#******************************************************************************************* |
# SET DEFAULT VARIABLES |
#******************************************************************************************* |
my $secret = "Frase . . . per la cifratura segreta :-))"; |
#******************************************************************************************* |
# Set connect method to get database handler. |
#******************************************************************************************* |
sub connect { |
my($self, $r, $conn, $autocommit) = @_; |
if(!$conn){ |
$conn = $r->dir_config('DBIconnect'); |
} |
my $user; |
my $passwd; |
if($conn =~ s/user=(\w+)//i){ |
$user=$1; |
} |
if($conn =~ s/passw\w+=(\w+)//i){ |
$passwd=$1; |
} |
#DEBUG print STDERR "Auth_AC::AuthCookieHandler->connect($conn, $user, $passwd)\n"; |
my $dbh = DBI->connect($conn, $user, $passwd) |
|| die "DBI Error open database: ".DBI::errstr; |
$dbh->{HandleError} = sub { |
# Qui si puo' modificare i messaggi di errore oppure catturare gli errori e |
# quindi annullarli. |
return 0; |
}; |
$dbh->{pg_enable_utf8} = 1; |
$dbh->{RaiseError} = 1; |
$dbh->{ShowErrorStatement}=1; |
# necessario per i database e client >=7.3 e successivi in quanto si utilizzano "prepare" di query multiple |
$dbh->{'pg_server_prepare'} = 0; |
$dbh->do(q| |
set DateStyle to 'SQL, EUROPEAN'; |
set TIME ZONE LOCAL; |
set client_encoding TO 'UTF-8'; |
SET search_path TO public; |
|); |
$dbh->{AutoCommit} = $autocommit ? 1 : 0; |
return $dbh; |
} |
sub _get_dbh { |
my $self = shift; |
my(%args) = @_; |
my $r = $args{r}; |
my $dbh = undef; |
no strict; |
$dbh = $self->connect($r); |
$dbh->{AutoCommit} = 1; |
use strict; |
return $dbh; |
}; |
sub _get_anagrafiche_info { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $login = $args{login}; |
my($id, $password, $psw_inactivity, $change_psw_days, $no_psw_expiration, $concurrent_session); |
my $sth = $dbh->prepare(q{ |
select |
id, |
password, |
date_part('day', now() - session_time) as psw_inactivity, |
date_part('day', now() - last_change_password) as change_psw_days, |
no_psw_expiration, |
concurrent_sessions |
from anagrafiche |
where login=? |
}); |
if(!$sth->execute($login) || $sth->rows != 1){ |
return undef; |
} else { |
($id, $password, $psw_inactivity, $change_psw_days, $no_psw_expiration, $concurrent_session) = @{$sth->fetchrow_arrayref}; |
} |
return ($id, $password, $psw_inactivity, $change_psw_days, $no_psw_expiration, $concurrent_session); |
}; |
sub _create_session { |
my $self = shift; |
my $session = String::Random->new()->randpattern('s' x 32); |
return $session; |
}; |
sub _store_session { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $login = $args{login}; |
my $password = $args{password}; |
my $session = $args{session}; |
my $ip = $args{ip}; |
my $ua = $args{ua}; |
my $id = $args{id}; |
my $r = $args{r}; |
my $rc = 0; |
my $session_id = undef; |
my $sth = $dbh->prepare(q{ |
insert into session(id_anagrafiche, user_agent , user_ip, session, session_time, previus_session_time, session_inactive_time) |
values(?, ?, ?, ?, now(), now(), ?); |
select lastval(); |
}); |
my $res = $sth->execute($id, $ua, $ip, $session, int(time/60)); |
if($res eq '0E0'){ |
$r->subprocess_env(AuthCookiePassword => $password); |
} else { |
if($res == 1){ |
$session_id = $sth->fetchrow_arrayref->[0]; |
$rc = 1; |
$dbh->{AutoCommit} || $dbh->commit; |
}else{ |
#DEBUG print STDERR $sth->errstr; |
} |
} |
return $session_id; |
}; |
sub _store_session_history { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $id = $args{id}; |
my $rc = 0; |
my $sth = $dbh->prepare(q{ |
update anagrafiche |
set previus_session_time = session_time, |
session_time = now() |
where id = ? |
}); |
my $res = $sth->execute($id); |
if($res == 1){ |
$rc = 1; |
$dbh->{AutoCommit} || $dbh->commit; |
}else{ |
#DEBUG print STDERR $sth->errstr; |
} |
return $rc; |
}; |
sub _reset_recordset_cache { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $sid = $args{sid}; |
my $rc = 0; |
my $sth = $dbh->prepare(q{ |
delete from public.recordset_rows |
using session, recordset |
where id_recordset = recordset.id |
and recordset.id_session = session.id |
and session.id = ?; |
delete from public.recordset |
using session |
where id_session = session.id |
and session.id = ? |
}); |
$sth->execute($sid, $sid); |
$dbh->{AutoCommit} || $dbh->commit; |
return $rc; |
}; |
sub _is_session_inactive { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $r = $args{r}; |
my $sid = $args{sid}; |
my $minutes = $args{minutes}; |
my $rc = 0; |
my $inactivity_minutes = int(time/60) - $minutes; |
if($inactivity_minutes > $r->dir_config('Auth_InactivityMax')){ |
$rc = $self->_remove_session(dbh => $dbh, sid => $sid); |
$self->_reset_recordset_cache(dbh => $dbh, sid => $sid); |
} |
return $rc; |
}; |
sub _remove_session { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $sid = $args{sid}; |
my $session = $args{session}; |
my $rc = 0; |
if(defined $sid) { |
#my $sth = $dbh->prepare('update session set session = null where id = ?'); |
my $sth = $dbh->prepare('delete from session where id = ?'); |
$sth->execute($sid); |
$dbh->{AutoCommit} || $dbh->commit; |
$rc = 1; |
} elsif(defined $session) { |
my ($login, $sess_key, $mac) = split /:/, $session, 3; |
my $sth = $dbh->prepare('delete from session where session = ?'); |
$sth->execute($sess_key); |
$dbh->{AutoCommit} || $dbh->commit; |
$rc = 1; |
} |
return $rc; |
}; |
sub _update_session_timestamp { |
my $self = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $sid = $args{sid}; |
my $minutes = $args{minutes}; |
my $rc = 0; |
my $inactivity_minutes = int(time/60) - $minutes; |
if($inactivity_minutes > 0){ |
my $sth = $dbh->prepare('update session set session_inactive_time = ? where id = ?'); |
$sth->execute(int(time/60), $sid); |
$dbh->{AutoCommit} || $dbh->commit; |
$rc = 1; |
} |
return $rc; |
}; |
sub _is_authorized_user { |
my $self = shift; |
my(%args) = @_; |
my $r = $args{r}; |
my $login = $args{login}; |
my $rc = 0; |
if(my $AuthRequireUser = $r->dir_config->get('AuthRequireUser')){ |
my %users; |
foreach my $user (split /\s+/, $AuthRequireUser){ |
$users{$user} = 1; |
} |
$rc = 1 if($users{$login}); |
} else { |
# Allow all users as authorized users |
$rc = 1; |
} |
return $rc; |
}; |
sub _is_authorized_group { |
my $self = shift; |
my(%args) = @_; |
my $r = $args{r}; |
my $login = $args{login}; |
my $dbh = $args{dbh}; |
my $rc = 0; |
if(my $AuthRequireGroup = $r->dir_config->get('AuthRequireGroup')){ |
my $sth = $dbh->prepare(q{ |
select gruppi.nome |
from gruppi |
inner join anagrafiche_gruppi on anagrafiche_gruppi.id_gruppi = gruppi.id |
inner join anagrafiche on anagrafiche.id = anagrafiche_gruppi.id_anagrafiche |
where anagrafiche.login = ? |
}); |
$sth->execute($login) || die "DBI Error select groups: ".DBI::errstr; |
my %groups; |
foreach my $group (split /\s+/, $AuthRequireGroup){ |
$groups{$group} = 1; |
} |
while(my $group = $sth->fetchrow_arrayref->[0]){ |
if($groups{$group}){ |
$rc = 1; |
} |
} |
} else { |
# Allow access to all groups |
$rc = 1; |
} |
return $rc; |
}; |
sub _delete_inactive_sessions { |
my $self = shift; |
my(%args) = @_; |
my $r = $args{r}; |
my $dbh = $args{dbh}; |
my $id = $args{id}; |
my $rc = 0; |
## Delete inactive sessions for selected login |
if(defined $id) { |
my $sth = $dbh->prepare(q{ |
select id,session,session_inactive_time |
from session |
where id_anagrafiche = ? |
}); |
if($sth->execute($id)){ |
while(my $row = $sth->fetchrow_arrayref()) { |
if($row and defined $row->[0]){ |
my($session_id, $sess, $minutes) = ($row->[0], $row->[1], $row->[2]); |
## check and delete inactive sessions. |
if($self->_is_session_inactive(dbh => $dbh, sid => $session_id, minutes => $minutes, r => $r)) { |
$rc = 1; |
} |
} |
} |
} |
}; |
return $rc; |
}; |
sub _delete_all_sessions { |
my $self = shift; |
my(%args) = @_; |
my $cookie = $args{cookie}; |
my $dbh = $args{dbh}; |
my $id = $args{id}; |
my $rc = 0; |
## Delete all sessions for selected login as it's concurrent_session flag = null or false in anagrafiche |
if(defined $id) { |
my $sth = $dbh->prepare(q{ |
delete from public.session |
where id_anagrafiche = ? |
}); |
$sth->execute($id); |
$rc = 1; |
}; |
return $rc; |
}; |
sub _get_user_session_count { |
my $self = shift; |
my(%args) = @_; |
my $cookie = $args{cookie}; |
my $dbh = $args{dbh}; |
my $id = $args{id}; |
my $rc = 0; |
if(defined $id) { |
my $sth = $dbh->prepare(q{ |
select id |
from session |
where id_anagrafiche = ? |
order by session_inactive_time desc |
limit 1 |
}); |
$sth->execute($id); |
$rc = $sth->rows; |
}; |
return $rc; |
}; |
sub _get_session_id { |
my $self = shift; |
my(%args) = @_; |
my $session = $args{session}; |
my $dbh = $args{dbh}; |
my $id = undef; |
my $rc = 0; |
if(defined $session) { |
my $sth = $dbh->prepare(q{ |
select id |
from session |
where session = ? |
}); |
$sth->execute($session); |
my $row = $sth->fetchrow_arrayref; |
$id = $row->[0]; |
}; |
return $id; |
}; |
sub _logout_handler { |
my $self = shift; |
my(%args) = @_; |
my $session = $args{session}; |
my $dbh = $args{dbh}; |
my $rc = 0; |
# cancello la sessione e la cache dei recordset |
my $sid = $self->_get_session_id(dbh => $dbh, session => $session); |
$self->_remove_session(dbh => $dbh, sid => $sid); |
$self->_reset_recordset_cache(dbh => $dbh, sid => $sid); |
return $rc; |
}; |
## Overwrite logout method |
sub logout { |
my ($self,$r) = @_; |
my($dbh) = $self->_get_dbh( r => $r); |
my $cookie = $self->key($r); |
my ($login, $sess_id, $mac) = split /:/, $cookie, 3; |
$self->_logout_handler(dbh => $dbh, session => $sess_id); |
$self->SUPER::logout($r); |
} |
sub authen_cred { |
my $self = shift; |
my $r = shift; |
$r->subprocess_env; |
my($login, $password, $new_password, $force_login) = @_; |
my($dbh) = $self->_get_dbh( r => $r); |
my($id, $md5_password, $psw_inactivity, $change_psw_days, $no_psw_expiration, $concurrent_session) = $self->_get_anagrafiche_info(dbh => $dbh, login => $login); |
return undef if(not defined $md5_password); |
## Verify if password has crossed expire limit. |
if(!$no_psw_expiration) { |
return undef if(defined $psw_inactivity && $psw_inactivity > $r->dir_config('MaxPasswordInactivity')); |
if(length($new_password) == 0 and (!defined $change_psw_days or $change_psw_days > $r->dir_config('MaxPasswordDays'))){ |
$r->subprocess_env(AuthCookiePassword => $password); |
return undef; |
} |
} |
## Remove inactive sessions for current user. |
$self->_delete_inactive_sessions(dbh => $dbh, id => $id, r => $r); |
## In case of force login set true, force user to always pass user & pwd. |
my $session_count = $self->_get_user_session_count(dbh => $dbh, id => $id); |
if((not defined $concurrent_session or $concurrent_session == 0) and $session_count > 0) { |
if($r->dir_config('Auth_AC_force_login') || $force_login) { |
$self->_delete_all_sessions(dbh => $dbh, id => $id) |
} else { |
return undef; |
} |
} |
# indirizzo del mittente (valuto se c'è un reverse proxy di mezzo) |
my $browser_address = $ENV{HTTP_X_FORWARDED_HOST} ? $ENV{HTTP_X_FORWARDED_FOR} : $ENV{REMOTE_ADDR}; |
my $user_agent = $ENV{HTTP_USER_AGENT}; |
# verify if password is matching with user input value. |
return undef if(defined $password && md5_hex($password) ne $md5_password); |
# Create new session |
my $NewSess_id = $self->_create_session(); |
my $session_id = $self->_store_session(dbh => $dbh, login => $login, session => $NewSess_id, |
ip => $browser_address, ua => $user_agent, id => $id, |
r => $r, password => $password); |
return undef if(not defined $session_id); |
# If new session created then store session history in anagrafiche |
# This value later will be used to check against MaxPasswordInactivity from config file. |
$self->_store_session_history(dbh => $dbh, id => $id); |
# Set new password |
if(length $new_password) { |
my $str_err = $self->update_password($r, $login, $new_password, 0); |
if($str_err){ |
$r->subprocess_env('AuthCookieErrorChangePassword' => $str_err); |
$self->_remove_session(dbh => $dbh, sid => $session_id); |
return undef; |
} |
} |
# Create session key to pass to apache |
my $session_key = $login.':'.$NewSess_id.':'.md5_hex( $NewSess_id, $secret ); |
$self->_reset_recordset_cache(dbh => $dbh, sid => $session_id); |
#DEBUG print STDERR "SK: [$session_key]\n"; |
return $session_key; |
} |
sub authen_ses_key { |
my $self = shift; |
my $r = shift; |
my $session_key = shift; |
my($dbh) = $self->_get_dbh( r => $r); |
my ($login, $Sess_id, $mac) = split /:/, $session_key, 3; |
my $sth = $dbh->prepare('select id,session,session_inactive_time from session where session = ?'); |
if($sth->execute($Sess_id)){ |
my $row = $sth->fetchrow_arrayref; |
if($row and defined $row->[0]){ |
my($session_id, $sess, $minutes) = ($row->[0], $row->[1], $row->[2]); |
if( md5_hex( $Sess_id, $secret ) eq $mac) { |
if($self->_is_session_inactive(dbh => $dbh, sid => $session_id, minutes => $minutes, r => $r)) { |
return undef; |
} else { |
$self->_update_session_timestamp(dbh => $dbh, sid => $session_id); |
} |
## Verify authorize user and groups |
if($self->_is_authorized_user(r => $r, login => $login) and |
$self->_is_authorized_group(r => $r, login => $login, dbh => $dbh)) { |
return $session_key; |
} |
} |
} |
} |
return undef; |
} |
# Modifica della password |
# ritorna una stringa con la motivazione del mancato cambiamento password |
sub update_password { |
my($self, $r, $login, $password, $force_change_password) = @_; |
no strict; |
my $dbh = $self->connect($r); |
$dbh->{AutoCommit} = 1; |
use strict; |
if(length($login) == 0){ |
return "Indicare la login utente"; |
} |
if(length($password) == 0){ |
return "La password non può essere vuota"; |
} |
# solo se la password è in chiaro possiamo fare dei controlli sulla password |
# recupero alcuni parametri dell'utente utilizzati per valutare la congruità della password |
my $sth = $dbh->prepare(q{ |
select id, login, nome, cognome, (password = ?) as psw_is_the_same, no_change_password |
from public.anagrafiche |
where "login"=?; |
}); |
if(!$sth->execute(md5_hex($password), $login)){ |
return "Errore: ".$sth->errstr |
} |
my $user = $sth->fetchrow_hashref; |
if(!defined $user){ |
return "Utente inesistente" |
} |
if($user->{no_change_password}){ |
return "La password non può cambiare"; |
} |
if($user->{psw_is_the_same}){ |
return "La password deve cambiare"; |
} |
my $MinPasswordChars = ''.$r->dir_config('MinPasswordChars'); |
if(length($password) < $MinPasswordChars){ |
return "La password deve contenere almeno $MinPasswordChars caratteri"; |
} |
if(!($password =~ m/[A-Z]/ and $password =~ m/[0-9]/ and $password =~ m/[a-z]/)){ |
return "La password deve contenere almeno una lettera maiuscola, una minuscola e una cifra numerica"; |
} |
# verifico che i primi tre caratteri di nome e cognome non siano presenti nella password |
# della login verifico che non siano presenti i primi 4 caratteri |
if( |
length($user->{nome}) >= 3 && index(lc $password, substr(lc $user->{nome}, 0, 3)) >= 0 or |
length($user->{cognome}) >= 3 && index(lc $password, substr(lc $user->{cognome}, 0, 3)) >= 0 or |
length($user->{login}) >= 4 && index(lc $password, substr(lc $user->{login}, 0, 4)) >= 0 |
){ |
return "La password non deve contenere le iniziali del nome, del cognome o del nome utente"; |
} |
# modifica password nel database |
my $sth = $dbh->prepare(q{select public.change_password(?,?,?);}); |
my $nrows = $sth->execute($login, $password, $force_change_password); |
if($nrows == 0){ |
return "Utente inesistente"; |
}elsif($nrows != 1){ |
return "Errore: ".$sth->errstr; |
} |
$dbh->{AutoCommit} || $dbh->commit; |
return undef; |
} |
return 1; |
__END__ |
/tags/2.0/lib/Auth_AC/AuthBasicHandler.pm |
---|
0,0 → 1,122 |
package Auth_AC::AuthBasicHandler; |
use Apache2::Access (); |
use Apache2::RequestUtil (); |
use Apache2::Const -compile => qw(OK DECLINED HTTP_UNAUTHORIZED); |
use Digest::MD5 qw(md5_hex); |
# aggiorna la data si accesso |
sub Update_session($$){ |
my($dbh, $login) = shift; |
my $sth = $dbh->prepare(q{ |
update anagrafiche |
set previus_session_time = session_time, |
session_time = now() |
where login = ? |
}); |
$sth->execute($login) || die "DBI Error update session time: ".DBI::errstr; |
$dbh->{AutoCommit} || $dbh->commit; |
} |
sub handler { |
my $r = shift; |
my ($status, $password) = $r->get_basic_auth_pw; |
return $status unless $status == Apache2::Const::OK; |
if(!$password || !$r->user){ |
$r->note_basic_auth_failure; |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
my $conn = $r->dir_config('DBIconnect'); |
my $user; |
my $passwd; |
if($conn =~ s/user=(\w+)//i){ |
$user=$1; |
} |
if($conn =~ s/passw\w+=(\w+)//i){ |
$passwd=$1; |
} |
#DEBUG print STDERR "Auth_AC::AuthBasicHandler->connect($conn, $user, $passwd)\n"; |
my $dbh = DBI->connect($conn, $user, $passwd) || die "DBI Error open database: ".DBI::errstr; |
$dbh->{pg_enable_utf8} = 1; |
$dbh->{RaiseError} = 1; |
$dbh->{ShowErrorStatement}=1; |
$dbh->do(q|set client_encoding TO 'UTF-8';|); |
$dbh->{AutoCommit} = 1; |
# cerco l'utente nel database |
my $SQL = q{ |
select |
password, |
date_part('day', now() - session_time) as psw_inactivity, |
date_part('day', now() - last_change_password) as change_psw_days, |
no_psw_expiration |
from anagrafiche |
where login=? |
}; |
#DEBUG print STDERR "LOGIN SQL '$SQL' '$login'\n"; |
my $sth = $dbh->prepare($SQL); |
$sth->execute($r->user); |
if($sth eq '0E0' || $sth->rows != 1){ |
#DEBUG print STDERR "AUTHENTICATION rows=".$sth->rows." KEY=UNDEFINED\n"; |
$r->note_basic_auth_failure; |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
my($md5_password, $psw_inactivity, $change_psw_days, $no_psw_expiration) = @{$sth->fetchrow_arrayref}; |
# password time expiration |
if(!$no_psw_expiration and $psw_inactivity > $r->dir_config('MaxPasswordInactivity')){ |
# l'utente non utilizza il sistema da troppo tempo |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
# verifico la password |
if(md5_hex($password) eq $md5_password){ |
# Verifico se ci sono limitazioni all'accesso in base all'utente o gruppo |
# impostate nella configurazione in Apache con le variabili mod_perl |
# es: |
# PerlSetVar AuthRequireUser "user1 user2" |
# PerlSetVar AuthRequireGroup "pruppo1 gruppo2 gruppo3" |
# |
if(my $AuthRequireUser = $r->dir_config->get('AuthRequireUser')){ |
# verifico che l'utente sia uno degli utenti elencati |
my %users; |
foreach my $user (split /\s+/, $AuthRequireUser){ |
$users{$user} = 1; |
} |
if($users{$login}){ |
Update_session($dbh, $login); |
return Apache2::Const::OK; |
} |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
if(my $AuthRequireGroup = $r->dir_config->get('AuthRequireGroup')){ |
# verifico che l'utente appartenga ad uno dei gruppi elencati |
my $sth = $dbh->prepare(q{ |
select gruppi.nome |
from gruppi |
inner join anagrafiche_gruppi on anagrafiche_gruppi.id_gruppi = gruppi.id |
inner join anagrafiche on anagrafiche.id = anagrafiche_gruppi.id_anagrafiche |
where anagrafiche.login = ? |
}); |
$sth->execute($login) || die "DBI Error select groups: ".DBI::errstr; |
my %groups; |
foreach my $group (split /\s+/, $AuthRequireGroup){ |
$groups{$group} = 1; |
} |
while(my $group = $sth->fetchrow_arrayref->[0]){ |
if($groups{$group}){ |
Update_session($dbh, $login); |
return Apache2::Const::OK; |
} |
} |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
Update_session($dbh, $login); |
return Apache2::Const::OK; |
} |
$r->note_basic_auth_failure; |
return Apache2::Const::HTTP_UNAUTHORIZED; |
} |
1; |
/tags/2.0/lib/Auth_AC/UserRegistration.pm |
---|
0,0 → 1,352 |
package Auth_AC::UserRegistration; |
use strict; |
use warnings; |
use Data::Dumper; |
use Exporter; |
use String::Random; |
use Digest::MD5 qw(md5_hex); |
use Captcha::reCAPTCHA; |
our $VERSION = 1.00; |
our @ISA = qw(Exporter); |
our @EXPORT = qw(); |
our @EXPORT_OK = qw(); |
our %EXPORT_TAGS = (); |
######################################################################################### |
## Define global variables :: |
######################################################################################### |
my ($FALSE, $TRUE) = (0, 1); |
my $DEFAULT_GROUP_NAME = "Guest"; |
my $DEFAULT_PASSWORD_PATTERN = "Cccsssnn"; |
my $DEFAULT_MAX_REGISTERATION_TIME = 7; |
my $MAIL_UR_TEMPLATE_NAME = "/MailTemplateUserRegistration.comp"; |
my $SMS_UR_TEMPLATE_NAME = "/SMSTemplateUserRegistration.comp"; |
my $MAIL_PR_TEMPLATE_NAME = "/MailTemplatePasswordReset.comp"; |
my $SMS_PR_TEMPLATE_NAME = "/SMSTemplatePasswordReset.comp"; |
my $DEFAULT_USR_REG_TYPE_MSG = "email"; |
######################################################################################### |
## Define class methods :: Constructor |
######################################################################################### |
sub new { |
my $class = shift; |
my(%args) = @_; |
my $self = {args => \%args}; |
bless($self, $class); |
$self->_init(); |
return $self; |
} |
sub _init { |
my $self = shift; |
$self->{random} = String::Random->new(); |
$self->{captcha} = Captcha::reCAPTCHA->new(); |
$self->{userInfo} = {}; |
return 0; |
}; |
sub disp($$) { |
my($self) = shift; |
#DEBUG print STDERR ("Test Data\n"); |
return 0; |
} |
sub _get_user_data() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $usrLogin = $args{login}; |
my $user_data; |
my $query = undef; |
if($usrLogin) { |
$query = q{select login,id,email from anagrafiche where login = ?}; |
} else { |
$query = q{select login,id,email from anagrafiche}; |
}; |
my $sth = $dbh->prepare($query); |
if($usrLogin) { |
$sth->execute($usrLogin); |
} else { |
$sth->execute(); |
}; |
my $nrows = $sth->rows; |
while(my($login, $id, $email) = $sth->fetchrow_array()) { |
$user_data->{$login} = { |
id => $id, |
email => $email |
}; |
} |
return $user_data; |
} |
sub get_user_id_list() { |
my($self) = shift; |
my(%args) = @_; |
my $user_data = $self->_get_user_data(%args); |
my $uid_list = lc(join("|", keys(%$user_data))); |
return $uid_list; |
} |
sub is_uid_exists() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $login = $args{login}; |
my $user_data = $self->_get_user_data(%args); |
my $is_uid_exists = exists $user_data->{$login} ? $TRUE : $FALSE; |
return $is_uid_exists; |
} |
sub is_valid_captcha_response() { |
my($self) = shift; |
my(%args) = @_; |
my $form = $args{formdata}; |
my $r = $args{r}; |
my $response = $form->{'g-recaptcha-response'}; |
my $remoteAddr = $ENV{REMOTE_ADDR}; |
my $secretKey = $r->dir_config('ReCaptchaAPISecretKey'); |
my $rc = $FALSE; |
if(isNotEmpty($response) and isNotEmpty($remoteAddr) and isNotEmpty($secretKey)) { |
my $result = $self->{captcha}->check_answer_v2($secretKey, $response, $remoteAddr); |
if ( $result->{is_valid} ) { |
$rc = $TRUE; |
} else { |
#DEBUG print STDERR Dumper($result); |
my $error = $result->{error}; |
$rc = $FALSE; |
} |
} |
return $rc; |
} |
sub process_registration_form() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $form = $args{formdata}; |
my $rc = $FALSE; |
if($self->is_valid_captcha_response(%args)) { |
if(not $self->is_uid_exists(dbh => $dbh, login => $form->{login})) { |
if($self->_add_user(%args) and $self->_add_group(%args)) { |
if($self->send_notification("UserRegistraion", %args)) { |
$rc = $TRUE; |
} |
} |
} |
} |
return $rc; |
} |
sub process_password_reset_form() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $form = $args{formdata}; |
my $rc = $FALSE; |
if($self->is_valid_captcha_response(%args)) { |
if($self->is_uid_exists(dbh => $dbh, login => $form->{login})) { |
if($self->_update_password(%args)) { |
if($self->send_notification("PasswordReset", %args)) { |
$rc = $TRUE; |
} |
} |
} |
} |
return $rc; |
} |
sub _get_password() { |
my($self) = shift; |
my(%args) = @_; |
my $r = $args{r}; |
my $form = $args{formdata}; |
my $pwdpattern = $r->dir_config('PasswordRandPattern') || $DEFAULT_PASSWORD_PATTERN; |
my $password = $self->{random}->randpattern($pwdpattern); |
$self->{userInfo}->{$form->{login}} = $password; |
return $password; |
}; |
sub _add_user() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $form = $args{formdata}; |
my $rc = $TRUE; |
my $query = q{ |
insert into anagrafiche(nome,cognome,descrizione, |
indirizzo,provincia,citta, |
tel1,tel2,codice_fiscale, |
login,email,cell_sms) |
values(?,?,?,?,?,?,?,?,?,?,?,?) |
}; |
my $sth = $dbh->prepare($query); |
no strict; |
$sth->execute( |
$form->{nome},$form->{cognome},$form->{descrizione}, |
$form->{indirizzo},$form->{provincia},$form->{citta}, |
$form->{tel1},$form->{tel2},$form->{codice_fiscale}, |
$form->{login},$form->{email},$form->{cell_sms} |
) || die "DBI Error update session time: ". DBI::errstr; |
$dbh->{AutoCommit} || $dbh->commit; |
use strict; |
$rc = $self->_update_password(%args); |
return $rc; |
} |
sub _update_password() { |
my($self) = shift; |
my(%args) = @_; |
my $form = $args{formdata}; |
my $r = $args{r}; |
my $password = $self->_get_password(%args); |
my $rc = $TRUE; |
my $force_chnge_pass = $TRUE; |
my $str_err = Auth_AC::AuthCookieHandler->update_password($r, $form->{login}, $password, $force_chnge_pass); |
if($str_err) { $rc = $FALSE; }; |
return $rc; |
} |
sub _is_valid_group(){ |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $usrGroup = $args{param}; |
my $group_data = {}; |
my $rc = $FALSE; |
if(defined $usrGroup and $usrGroup ne '') { |
my $query = q{select id from gruppi where nome = ?}; |
my $sth = $dbh->prepare($query); |
$sth->execute($usrGroup); |
my $nrows = $sth->rows; |
my($id) = $sth->fetchrow_array(); |
if($nrows and $id) { |
$rc = $TRUE; |
} |
} |
return $rc; |
} |
sub _add_group(){ |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $form = $args{formdata}; |
my $r = $args{r}; |
my $rc = $TRUE; |
my $usrGroup = $self->_is_valid_group(dbh => $dbh, param => $r->dir_config('NewUserRegisterGroup')) ? |
$r->dir_config('NewUserRegisterGroup') : $DEFAULT_GROUP_NAME; |
my $login = $form->{login}; |
my $query = q{ |
insert into anagrafiche_gruppi(id_anagrafiche,id_gruppi) |
select anagrafiche.id, gruppi.id from anagrafiche, gruppi |
where gruppi.nome = ? and anagrafiche.login = ? |
}; |
my $sth = $dbh->prepare($query); |
$sth->execute($usrGroup,$login); |
$dbh->{AutoCommit} || $dbh->commit; |
return $rc; |
} |
sub _get_next_seq_id() { |
my($self) = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $sequence = $args{sequence}; |
my $id = 0; |
my $rc = $FALSE; |
if(defined $sequence and $sequence ne '') { |
my $query = q{select nextval(?)}; |
my $sth = $dbh->prepare($query); |
$sth->execute($sequence); |
my $nrows = $sth->rows; |
($id) = $sth->fetchrow_array(); |
if($nrows and $id) { |
$rc = $TRUE; |
} |
} |
return $id; |
} |
sub send_notification() { |
my($self) = shift; |
my $request = shift; |
my(%args) = @_; |
my $dbh = $args{dbh}; |
my $r = $args{r}; |
my $form = $args{formdata}; |
my $rc = $TRUE; |
my($subject, $message) = $self->get_template($request, %args); |
my $owner = 1; |
my $UserRegTypeMessage = $r->dir_config('UserRegTypeMessage') || $DEFAULT_USR_REG_TYPE_MSG; |
my ($email, $sms) = $UserRegTypeMessage eq "sms" ? ("false", "true") : ("true", "false"); |
### Get next sequence id. |
my $msg_seq_id = $self->_get_next_seq_id(dbh => $dbh, sequence => 'messages_id_seq'); |
### insert record into messages table. |
my $query1 = q{ |
insert into messages(id, message, owner, modification_time, transmission_time, subject, email, sms) |
values(?, ?, ?, now(), now(), ?, ?, ?) |
}; |
my $sth1 = $dbh->prepare($query1); |
$sth1->execute($msg_seq_id, $message, $owner, $subject, $email, $sms); |
### insert record into messages_users table. |
my $user_data = $self->_get_user_data(%args, login => $form->{login}); |
my $query2 = q{ |
insert into messages_users(id_messages, id_anagrafiche) |
values(?, ?) |
}; |
my $sth2 = $dbh->prepare($query2); |
$sth2->execute($msg_seq_id, $user_data->{$form->{login}}->{id}); |
### Commit database contents. |
$dbh->{AutoCommit} || $dbh->commit; |
return $rc; |
}; |
sub get_template() { |
my($self) = shift; |
my $request = shift; |
my(%args) = @_; |
my $form = $args{formdata}; |
my $r = $args{r}; |
my $m = $args{m}; |
my $password = $self->{userInfo}->{$form->{login}}; |
my $login = $form->{login}; |
my $nome = $form->{nome}; |
my $UserRegTypeMessage = $r->dir_config('UserRegTypeMessage') || $DEFAULT_USR_REG_TYPE_MSG; |
my $regActDays = $r->dir_config('MaxTimeToConfirmUserRegistration') || $DEFAULT_MAX_REGISTERATION_TIME; |
my $baseurl = sprintf("http%s://%s:%s", $ENV{HTTPS} eq 'on' ? 's' : '', $ENV{HTTP_HOST}, $ENV{SERVER_PORT}); |
$regActDays = sprintf("%02d", $regActDays); |
my $templateName = undef; |
### set template for user registraion and password reset. |
if($request eq "UserRegistraion") { |
$templateName = $UserRegTypeMessage eq "sms" ? $SMS_UR_TEMPLATE_NAME : $MAIL_UR_TEMPLATE_NAME; |
} elsif($request eq "PasswordReset") { |
$templateName = $UserRegTypeMessage eq "sms" ? $SMS_PR_TEMPLATE_NAME : $MAIL_PR_TEMPLATE_NAME; |
}; |
### set template for user registraion and password reset. |
my $template = $m->fetch_comp($templateName) or die "No component $templateName\n"; |
my $subject = $template->scall_method('Subject'); |
my $body = $template->scall_method('Body', |
nome => $nome, |
baseurl => $baseurl, |
login => $login, |
password => $password, |
regActDays => $regActDays |
); |
return ($subject, $body); |
}; |
sub isNotEmpty() { |
my($str) = @_; |
my $rc = (defined $str and $str ne "") ? $TRUE : $FALSE; |
return $rc; |
} |
1; |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/lib/MasonX/Plugin/UTF8.pm |
---|
0,0 → 1,39 |
# Copyright 2012 Tufts University |
# |
# Licensed under the Educational Community License, Version 1.0 (the "License"); |
# you may not use this file except in compliance with the License. |
# You may obtain a copy of the License at |
# |
# http://www.opensource.org/licenses/ecl1.php |
# |
# Unless required by applicable law or agreed to in writing, software |
# distributed under the License is distributed on an "AS IS" BASIS, |
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
# See the License for the specific language governing permissions and |
# limitations under the License. |
# Modified by Guido Brugnara <gdo@leader.it> to convert array (2019) |
package MasonX::Plugin::UTF8; |
use base qw(HTML::Mason::Plugin); |
use Scalar::Util qw(readonly); |
use utf8; |
sub start_request_hook { |
my ( $self, $context ) = @_; |
my $args_ref = $context->args(); |
foreach my $arg ( @{$args_ref} ) { |
return if(readonly $arg); |
if(ref $arg eq 'ARRAY'){ |
foreach my $arg_arr ( @{$arg} ) { |
my $result = utf8::decode($arg_arr); |
die unless $result; |
} |
}else{ |
my $result = utf8::decode($arg); |
die unless $result; |
} |
} |
return; |
} |
1; |
/tags/2.0/lib/MasonSQL/Escapes.pm |
---|
0,0 → 1,44 |
package MasonSQL::Escapes; |
# funzione di 'escaping' per linguaggio Javascript |
sub js_escape { |
local $_; |
$_=$_[0]; |
$$_=~s/\\/\\\\/sg; |
$$_=~s/"/\\"/sg; |
$$_=~s/\'/\\\'/sg; |
$$_=~s/\n/\\n/sg; |
$$_=~s/\t/\\t/sg; |
$$_=~s/<\/script>/<\\\/script>/sg; |
} |
# funzione di 'escaping' per linguaggio XML |
sub xml_escape { |
local $_; |
$_=$_[0]; |
$$_=~s/&/&/sg; |
$$_=~s/</</sg; |
$$_=~s/>/>/sg; |
$$_=~s/"/"/sg; #" |
$$_=~s/'/'/sg; |
$$_=~s/\t/	/sg; |
$$_=~s/\n/ /sg; |
} |
# funzione di 'escaping' per incapsulare codice (HTML e XML in un campo textarea |
sub textarea_escape { |
local $_; |
$_=$_[0]; |
$$_=~s/&/&/sg; |
$$_=~s/</</sg; |
$$_=~s/>/>/sg; |
} |
# funzione di 'escaping' per incapsulare codice multiriga |
sub multi_escape { |
local $_; |
$_=$_[0]; |
$$_=~s/\n/<br>/sg; |
} |
1; |
/tags/2.0/lib/MasonSQL/Report.pm |
---|
0,0 → 1,2009 |
package MasonSQL::Report; |
=pod |
=head1 MasonSQL::Report |
=head2 Revision |
$Revision: $ |
=head2 Description |
MasonSQL implementation of reporting. |
=head2 Included Libraries and Subroutines |
Library or Function Name | Note |
--------------------------------------------- |
Encode | |
HTML::Entities | |
DBI | |
ODF::lpOD | |
Image::Info | |
File::MimeInfo | |
DTL::Fast | |
File::Temp qw/ tempfile / | |
Cwd qw(realpath) | |
Text::Balanced | |
Data::Dumper | |
IPC::Run qw(run) | |
IPC::Run::SafeHandles | |
feature qw(say) | |
=cut |
use strict; |
use warnings; |
use feature qw(say); |
use locale; |
use POSIX qw(sprintf setlocale LC_NUMERIC); |
use Encode; |
use HTML::Entities; |
use namespace::autoclean; |
use DBI; |
use DBD::Pg qw(:pg_types); |
use ODF::lpOD; |
use Image::Info; |
use Image::Size; |
use MIME::Base64; |
use File::MimeInfo; |
use File::Temp qw/ tempfile /; |
use Cwd qw(realpath); |
use Text::Balanced; |
use Data::Dumper; |
use IPC::Run qw(run); |
use IPC::Run::SafeHandles; |
use JSON qw(from_json); |
setlocale(LC_NUMERIC, "it_IT.UTF-8"); |
use DTL::Fast; |
package DTL::Fast::Context; |
# Patch original method to ignore not defined variables |
# tracing variable path |
sub traverse |
{ |
my ( $self, $variable, $path, $source_object ) = @_; |
my $variable_original = $variable; |
foreach my $step (@$path) |
{ |
my $current_type = reftype $variable; |
if ( |
blessed($variable) |
and $variable->can($step)) |
{ |
$variable = $variable->$step(); |
} |
elsif (not defined $current_type) |
{ |
return undef; |
} |
elsif ($current_type eq 'HASH') |
{ |
$variable = $variable->{$step}; |
} |
elsif ( |
$current_type eq 'ARRAY' |
and $step =~ /^\-?\d+$/x |
) |
{ |
$variable = $variable->[$step]; |
} |
else |
{ |
return undef; |
} |
} |
while( ref $variable eq 'CODE' ) |
{ |
$variable = $variable->(); |
} |
return $variable; |
} |
package MasonSQL::Report; |
=head2 Private Variables, Global to Report Object |
Variable Name | Description |
------------------------------------------------------------------------ |
dbh | Database handle. |
cli | A key-value pairs of reserved cli options. |
cmd_parameters | A key-value pairs of command line cli options. |
odt_rpt_id | A primary key value of the selected report from |
| the public.odt_reports table. |
odt_rpt_fields | A key-value hash used for pre-rendering ODT variables. |
dtl_context | A DTL context which is global to class. |
portion | A structure containing public.odt_report_portion |
| records for the selected report. |
content | A portion ID-content pairs, that are extracted from |
| a template file. |
appendable_seq | An array of portion IDs that can be inserted into report, |
| sorted by ord field. |
| Insertable portions are of type odt_section, |
| odt_table, odt_file or pdf_report. |
attachable_seq | An array of portion IDs that can be attached as a file, |
| sorted by ord field. |
| Attachable portions are of type pdf_file or pdf_report. |
base_id | A base template portion ID. |
base_file_name | A base template file name. |
=cut |
# A names of the reserved cli options. |
my @reserved = ( |
'config_path', |
'report_name', |
'odt_filepath', |
'pdf_filepath' |
); |
sub new { |
my $class = shift; |
my %rpt = @_; |
my $self = bless \%rpt, $class; |
$self->{dtl_context} = DTL::Fast::Context->new({}); |
$self->parse_cli($self->{Cli_options}); |
$self->get_odt_report; |
$self->get_odt_report_fields; |
$self->get_odt_report_portions; |
return $self |
} |
sub say($$){ |
my $self = shift; |
my $funct = shift; |
my $str = shift; |
$self->{output} .= $str ? "\n$funct(), $str" : "\n$funct()" |
} |
sub output(){ |
my $self = shift; |
my $sent = $self->{output}; |
$self->{output} = ''; |
return $sent; |
} |
=head2 Private Static Variables |
=head3 Temporary Image Filepaths |
Variable Name | Description |
------------------------------------------------------------------------ |
@tmp_image_filepath | A list of filepaths to temporary files that get deleted |
| during destruction of Report object. |
=cut |
=head4 push_tmp_image() |
Add a new temporary image filepath to the C<tmp_image_filepath>. |
=cut |
sub push_tmp_image($){ |
my $self = shift; |
my $filepath = shift; |
push @{$self->{tmp_image_filepath}}, $filepath; |
return; |
} |
=head4 unlink_tmp_images() |
Unlink each temporary image filepath from the C<tmp_image_filepath>. |
=cut |
sub unlink_tmp_images(){ |
my $self = shift; |
$self->unlink_files($self->{tmp_image_filepath}); |
} |
=head3 Hash of Pictures |
Variable Name | Description |
------------------------------------------------------------------------ |
pictures | A hash of images added to the C<Pictures> subdirectory in |
| the B<.odt> file. It helps detect and eliminate repeated |
| updates of duplicates. |
=cut |
=head4 is_in_pictures() |
If the image file name was already updated returns 1. |
Otherwise returns 0 and saves the image name to the C<pictures> hash. |
=cut |
sub is_in_pictures($){ |
my $self = shift; |
my $picture_name = shift; |
if($self->{pictures}{$picture_name}){ |
return 1; |
}else{ |
$self->{pictures}{$picture_name} = 1; |
return 0; |
} |
} |
=head2 Interface Subroutines |
=head3 parse_cli() |
Parse input arguments, for example: |
$rpt->parse_cli(\@ARGV); |
First check if an option is L<reserved|/Private Variables, Global to Report Object> otherwise check if its L<cmd parameter|https://www.leader.it/MasonSQL/OdtReport#Parameters>. |
Reserved options contain C<:> separator, cmd parameters contain C<=> separator. |
=cut |
sub parse_cli($){ |
my $self = shift; |
my $args = shift; |
foreach (@$args){ |
if(!$self->parse_reserved($_)){ |
$self->parse_cmd_parameter($_); |
} |
} |
#DEBUG say 'cli: '.Dumper($self->{cli}); |
$self->check_mandatory_option('config_path'); |
$self->check_mandatory_option('odt_filepath'); |
} |
=head3 get_odt_report() |
Gets selected record from L<public.odt_reports|https://www.leader.it/MasonSQL/OdtReport#public.odt_reports_Table> table. |
From the table it extracts L<odt_rpt_id|/Private Variables, Global to Report Object> and C<global_parameters> field. |
The C<global_parameters> field is L<parsed|/list2cmd_parameters()> resulting parameters are stored into L<cmd_parameters|/Private Variables, Global to Report Object> hash. |
Also the reference to C<%cmd_parameters> hash is added to L<DTL context|/Private Variables, Global to Report Object> as C<ARGV> thus |
the resulting parameters are rendered as C<{{ ARGV.param_name }}>. |
Additionaly it reads the public.odt_report_fields table. The contents of this table is used for pre-rendering of the ODT simple variables. |
=cut |
sub get_odt_report(){ |
my $self = shift; |
my $params_statement = q{ |
select id,global_parameters from public.odt_reports where name = ?; |
}; |
$self->check_mandatory_option('report_name'); |
#DEBUG say "report_name=$self->{cli}{'report_name'}"; |
my $row = $self->{Dbh}->selectrow_hashref($params_statement, undef, $self->{cli}{'report_name'}); |
$self->{odt_rpt_id} = $row->{'id'}; |
$self->list2cmd_parameters($row->{'global_parameters'}); |
$self->{dtl_context}->set('ARGV' => $self->{cmd_parameters}); |
#DEBUG say "cmd_parameters=".Dumper($self->{cmd_parameters}); |
return; |
} |
=head3 get_odt_report_fields() |
Gets report's key-value pairs which are available with L<odt_rpt_fields|/Private Variables, Global to Report Object> reference. |
=cut |
sub get_odt_report_fields(){ |
my $self = shift; |
my $fields_statement = $self->{Dbh}->prepare(q{ |
select key, function as fun, format from public.odt_report_fields where id_odt_reports = ?; |
}); |
$fields_statement->execute($self->{odt_rpt_id}); |
$self->{odt_rpt_fields} = $fields_statement->fetchall_hashref('key'); |
return |
} |
=head3 get_odt_report_portions() |
Gets records from L<public.odt_report_portions|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> table belonging to the selected report from the L<public.odt_reports|https://www.leader.it/MasonSQL/OdtReport#public.odt_reports_Table> table. |
The records with empty C<type> field are skipped. |
Fields from each obtained record are stored into L<portion|/Private Variables, Global to Report Object> structure. |
If the record is base report L<base_id|/Private Variables, Global to Report Object> and L<base_file_name|/Private Variables, Global to Report Object> are also obtained. |
It is also determined whether the portions is C<appendable> or C<attachable>. |
When the base report query is defined, it retrieves the first row of the query results, then adds the base portion name with field values from the row to the DTL L<DTL context|/Private Variables, Global to Report Object>. |
=cut |
sub get_odt_report_portions(){ |
my $self = shift; |
my $statement = $self->{Dbh}->prepare(q{ |
select * from public.odt_report_portions where id_odt_reports = ?; |
}); |
$statement->execute($self->{odt_rpt_id}); |
while(my $row = $statement->fetchrow_hashref){ |
my $id = $row->{'id'}; |
if($row->{'type'}){ |
if($row->{'type'} eq 'base_report'){ |
$self->{base_id} = $id; |
$self->{base_file_name} = $self->render_string($self->truncate_blanks($row->{'file_name'})); |
if($self->{base_file_name} =~ /^\s*$/){ |
die $self->err_msg("No base_report file name, please specify base_report portion with file name."); |
} |
} |
if($row->{'type'} eq 'odt_section' || $row->{type} eq 'odt_table' || $row->{type} eq 'odt_file'){ |
$self->{portion}{appendable}{$id} = $row->{'ord'}; |
}elsif($row->{'type'} eq 'pdf_file' || $row->{type} eq 'pdf_report'){ |
$self->{portion}{attachable}{$id} = $row->{'ord'}; |
} |
$self->{portion}{type}{$id} = $row->{'type'}; |
$self->{portion}{order}{$id} = $row->{'ord'}; |
$self->{portion}{name}{$id} = $self->truncate_blanks($row->{'name'}); |
$self->{portion}{father}{$id} = $row->{'id_father'}; |
$self->{portion}{file_name}{$id} = $self->truncate_blanks(defined $row->{'file_name'} ? $row->{'file_name'} : ''); |
$self->{portion}{obj_ref}{$id} = $self->truncate_blanks(defined $row->{'obj_ref'} ? $row->{'obj_ref'} : ''); |
$self->{portion}{query}{$id} = defined $row->{'query'} ? $row->{'query'} : ''; |
#DEBUG "name($id)=$self->{portion}{name}{$id}"; |
#DEBUG "father($id)=$self->{portion}{father}{$id}"; |
#DEBUG "obj_ref{$id}=".$self->{portion}{obj_ref}{$id}; |
#DEBUG "query{$id}=".$self->{portion}{query}{$id}; |
} |
} |
#DEBUG 'portions: '.Dumper(\%portion); |
$self->set_base_context; |
return; |
} |
=head3 make_report() |
Makes the B<.odt> report document. |
Returns filepath of the main odt report. |
If it can't find the base file, it does nothing and returns an empty string. |
The procedure to make a report document: |
=over 2 |
=item 1 |
Create L<new report|/new_report()> from the L<base template|https://www.leader.it/MasonSQL/OdtReport#base_report_portion_type> file. |
=item 2 |
L<Read portions|/read_base_portions()> from the base template file. |
=item 3 |
L<Delete portions|/delete_portions()> from newly created report file. |
=item 4 |
Obtain L<sequence|/get_appendable_sequence()> in which the portions will be added to the report. |
=item 5 |
L<Generate body|/make_body()> of the report. |
=item 6 |
Finally save the report. |
=back |
=cut |
sub make_report(){ |
my $self = shift; |
unless($self->{base_file_name}){ |
return ''; |
} |
my ($report, $body) = $self->new_report($self->{cli}{'odt_filepath'}); |
$self->read_base_portions($body); |
$self->delete_portions($body); |
$self->get_appendable_sequence; |
if(my $base_name = $self->{portion}{name}{$self->{base_id}}){ |
if($self->{dtl_context}->get($base_name)){ |
$self->make_body($self->{base_id}, $report, $body); |
} |
}else{ |
$self->make_body($self->{base_id}, $report, $body); |
} |
$report->save(); |
return $self->{cli}{'odt_filepath'}; |
} |
=head3 get_pdf_filepath() |
Returns the target filepath, of the main report, that is needed by L<Unoconv|http://tech.rgou.net/en/php/converting-documents-odt-doc-to-pdf-on-php-with-unoconv-libreoffice/> or Libreoffice for conversion from B<.odt> to B<.pdf>. |
Both origin and target filepaths are passed from the L<report.pdf|https://www.leader.it/MasonSQL/ReportComponent> component where they are composed. |
=cut |
sub get_pdf_filepath(){ |
my $self = shift; |
$self->check_mandatory_option('pdf_filepath'); |
return $self->{cli}{'pdf_filepath'}; |
} |
=head3 add_attachments() |
Concatenates the report with the L<attachments|/attach_portion()>. |
The attachments are ordered by L<attachable_seq|/Private Variables, Global to Report Object> |
The concatenation is made with C<pdftk> executable, with the command: |
pdftk <filepath1> <filepath2> ... <filepathN> cat output <output_filepath> |
=cut |
sub add_attachments($$){ |
my $self = shift; |
my $main_report = shift; |
my $pdf_filepath = shift; |
my $pdftk = '/usr/bin/pdftk'; |
if(! -e $pdftk){ |
die "$pdftk not exists\n"; |
} |
my @cmd = ($pdftk); |
my @pdf_reports = (); |
if($main_report){ |
push(@cmd, $main_report); |
} |
$self->get_attachable_sequence; |
foreach my $id (@{$self->{attachable_seq}}){ |
$self->attach_portion(\@cmd, \@pdf_reports, $id); |
} |
push(@cmd, 'cat'); |
push(@cmd, 'output'); |
push(@cmd, $pdf_filepath); |
#DEBUG say "cmd=".Dumper(\@cmd); |
my $out_and_err = (); |
if(!run \@cmd, '<', \undef, '>&', \$out_and_err){ |
die "add_attachments error running ".join(' ', @cmd).": $? err:[$out_and_err]\n"; |
} |
#DEBUG say "pdftk out_and_err: $out_and_err"; |
$self->unlink_files(\@pdf_reports); |
return; |
} |
=head3 Parsing CLI and Apache Config |
=head4 parse_reserved() |
Checks if the CLI option is found in L<cli|/Private Variables, Global to Report Object> hash and, in case it does, returns 1; |
Otherwise returns 0. |
=cut |
sub parse_reserved($){ |
my $self = shift; |
my $option = shift; |
foreach (@reserved){ |
if($option =~ /$_:(.*)/){ |
$self->{cli}{$_} = $1; |
return 1; |
} |
} |
return 0; |
} |
=head4 parse_cmd_parameter() |
Checks that the input CLI option is a L<cmd parameter|https://www.leader.it/MasonSQL/OdtReport#Parameters> |
If its not a cmd parameter raises an error. |
=cut |
sub parse_cmd_parameter($){ |
my $self = shift; |
my $parameter = shift; |
if($parameter =~ /(.*)=(.*)/){ |
$self->{cmd_parameters}{$1} = $2; |
}else{ |
die $self->err_msg("Invalid format of cmd parameter $parameter"); |
} |
return; |
} |
=head4 list2cmd_parameters() |
Uses L<Text::Balanced|http://perldoc.perl.org/Text/Balanced.html> to extract L<cmd parameters|https://www.leader.it/MasonSQL/OdtReport#Parameters> from the input list. |
A cmd parameters without values will cause an error unless the value is empty string. |
The parsed cmd parameter names and values are stored in the L<cmd_parameters|/Private Variables, Global to Report Object> hash. |
=cut |
sub list2cmd_parameters($){ |
my $self = shift; |
my $list = shift; |
unless($list){ |
return; |
}else{ |
$list =~ s/\\//g; |
} |
my $sep = '\s+'; |
my $options = $list; |
my @name = Text::Balanced::extract_multiple($options, [ |
qr/$sep([\w-]+)\s*=\s*/, |
qr/^\s*([\w-]+)\s*=\s*/, |
], undef, 1); |
$options = $list; |
my @value = Text::Balanced::extract_multiple($options, [ |
sub { Text::Balanced::extract_quotelike($_[0]) }, |
qr/\s*=\s*([\w-]+)/, |
], undef, 1); |
if($#name != $#value){ |
die $self->err_msg("Invalid format of cli parameters: $list\nUse [ param1=100 ][ MyPAR='my string data' ]."); |
} |
for (my $I = 0; $I<@value; $I++){ |
$value[$I] =~ s/^("|'|`|\s)+//; |
$value[$I] =~ s/("|'|`|\s)+$//; |
$value[$I] =~ s/$sep$//; |
my $uc_name = uc $name[$I]; |
unless($self->{cmd_parameters}{$uc_name}){ |
$self->{cmd_parameters}{$uc_name} = $value[$I]; |
#DEBUG say "list2cmd_parameters($uc_name)=$value[$I]"; |
} |
} |
return; |
} |
=head4 check_mandatory_option() |
Verifies that the mandatory option is L<reserved|/parse_reserved()> and that the option exists in L<cli|/Private Variables, Global to Report Object> hash. |
Otherwise raises an error. |
=cut |
sub check_mandatory_option($){ |
my $self = shift; |
my $option = shift; |
if($self->parse_reserved($option)){ |
unless($self->{cli}{$option}){ |
die $self->err_msg("Please specify mandatory option $option, use my_option_name:my_option_value format."); |
} |
} |
return; |
} |
=head3 Handling Portions |
=head4 append_portion() |
=over 2 |
=item 1 |
Clones the L<content|/Private Variables, Global to Report Object> of the template portion; |
=item 2 |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> the cloned portion; |
=item 3 |
Appends it to the body of the document. |
=back |
=cut |
sub append_portion($$$){ |
my $self = shift; |
my $body = shift; |
my $obj_ref = shift; |
my $content_key = shift; |
if(my $portion = $self->{content}{$content_key}){ |
$portion = $portion->clone; |
$self->render_text($portion); |
$body->append_element($portion); |
return $portion; |
}else{ |
die $self->err_msg("Can't find portion, obj_ref='$obj_ref'"); |
} |
} |
=head4 attach_portion() |
=over 2 |
=item * |
If the portion type is L<pdf_file|https://www.leader.it/MasonSQL/OdtReport#pdf_file_portion_type> it constructs filepath with rendered portion's file name then attaches the filepath to the L<pdftk|/add_attachments()> command. |
=item * |
If the portion type is L<pdf_report|https://www.leader.it/MasonSQL/OdtReport#pdf_report_portion_type> it makes the pdf L<report|/make_pdf_reports()> |
then attaches the report's filepath to the L<pdftk|/add_attachments()> command. |
=back |
=cut |
sub attach_portion($$$){ |
my $self = shift; |
my $cmd = shift; |
my $pdf_reports = shift; |
my $id = shift; |
#DEBUG say "attach portion id=$id"; |
my $relative_filepath = $self->render_string($self->{portion}{file_name}{$id}); |
my $filename = $relative_filepath && $relative_filepath !~ /^\s*$/; |
if($self->{portion}{type}{$id} eq 'pdf_file'){ |
if($filename && $relative_filepath =~ /\.pdf$/){ |
push(@{$cmd}, $self->template_filepath($relative_filepath)); |
}else{ |
die $self->err_msg("Please specify .pdf filename in portion $id."); |
} |
}elsif($self->{portion}{type}{$id} eq 'pdf_report'){ |
if($filename && $relative_filepath =~ /\.odt$/){ |
my $odt_template = $self->template_filepath($relative_filepath); |
my $pdfs = $self->make_pdf_reports($odt_template, $id); |
foreach my $pdf (@$pdfs){ |
push(@{$cmd}, $pdf); |
push(@{$pdf_reports}, $pdf); |
} |
}else{ |
die $self->err_msg("Please specify .odt template filename in portion $id."); |
} |
} |
return; |
} |
=head4 delete_portions() |
Deletes all of the sections and all of the tables from the body of the current document. |
=cut |
sub delete_portions($){ |
my $self = shift; |
my $body = shift; |
my @sections = $body->get_sections(); |
foreach my $section (@sections){ $section->delete; } |
my @tables = $body->get_tables(); |
foreach my $table (@tables){ $table->delete; } |
return; |
} |
=head4 get_portion() |
Checks the portion type then, accordingly to type, uses L<get_section|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/StructuredContainer.pod#Sections> or L<get_table_by_name|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Table.pod#Table_creation_and_retrieval>. |
If the portion type does not match it raises an error although the table or the section exists. |
Unless portion type is L<odt_section|https://www.leader.it/MasonSQL/OdtReport#odt_section_portion_type> or L<odt_table|https://www.leader.it/MasonSQL/OdtReport#odt_table_portion_type> it is skipped. |
Since the C<template> can be different from base template L<comments|/remove_comments()> are preventively removed. |
=cut |
sub get_portion($$$){ |
my $self = shift; |
my $template = shift; |
my $obj_ref = shift; |
my $type = shift; |
#DEBUG say "get_portion: obj_ref=$obj_ref, type=$type"; |
my $body = $template->get_body; |
$self->remove_comments($body); |
my $portion = ''; |
if($type eq 'odt_section'){ |
$portion = $body->get_section($obj_ref) or die $self->err_msg("No matching section $obj_ref"); |
}elsif($type eq 'odt_table'){ |
$portion = $body->get_table_by_name($obj_ref) or die $self->err_msg("No matching table $obj_ref"); |
} |
#DEBUG say "got $obj_ref"; |
return $portion; |
} |
=head4 update_portion() |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> L<file_name|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> then checks whether to update the L<content|/Private Variables, Global to Report Object> hash or skip the update. |
The update is skipped if the C<file_name> is NULL, if its a base filename, if its empty string or if the template portion is already stored in the C<content> hash. |
The subroutine allways returns current L<content|/Private Variables, Global to Report Object> key. |
=cut |
sub update_portion($$){ |
my $self = shift; |
my $obj_ref = shift; |
my $id = shift; |
my $file_name = $self->render_string($self->{portion}{file_name}{$id}); |
my $key = ''; |
if($file_name && $file_name !~ /^\s+$/ && $file_name ne $self->{base_file_name}){ |
$key = $file_name . $obj_ref; |
unless($self->{content}{$key}){ |
my $template = odf_document->get($self->template_filepath($file_name)); |
$self->{content}{$key} = $self->get_portion($template, $obj_ref, $self->{portion}{type}{$id}); |
} |
#DEBUG say "key=$key"; |
return $key; |
} |
else{ |
$key = $self->{base_file_name} . $obj_ref; |
return $key; |
} |
} |
=head4 read_base_portions() |
The subroutine is called in the initial phase of the report creation: |
Reads sections and tables into L<content|/Private Variables, Global to Report Object> hash. |
=cut |
sub read_base_portions($){ |
my $self = shift; |
my $body = shift; |
my @sections = $body->get_sections(); |
foreach my $section (@sections){ |
my $key = $self->{base_file_name} . $section->get_name; |
$self->{content}{$key} = $section; |
#DEBUG say "key=$key"; |
} |
my @tables = $body->get_tables(); |
foreach my $table (@tables){ |
my $key = $self->{base_file_name} . $table->get_name; |
$self->{content}{$key} = $table; |
#DEBUG say "key=$key"; |
} |
return; |
} |
=head4 set_base_context() |
If its possible, adds the first row of the base portion to the DTL context. |
The prerequisite is availability of the L<query|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> and L<name|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> field values for the base portion and the row number set to 1. |
=cut |
sub set_base_context(){ |
my $self = shift; |
my $base_query = $self->render_string($self->{portion}{query}{$self->{base_id}}); |
#DEBUG say "base_query=[\n$base_query\n]"; |
if($base_query && $self->{portion}{name}{$self->{base_id}}){ |
my $statement = $self->{Dbh}->prepare($base_query); |
$statement->execute(); |
if($statement){ |
if(my $record = $statement->fetchrow_hashref){ |
$record->{'ROW_NUMBER'} = 1; |
$self->set_portion_context($self->{base_id}, $statement->{NAME}, $statement->{pg_type}, $record); |
} |
} |
} |
return; |
} |
=head4 set_portion_context() |
Adds the portion name with field values from record to the DTL L<DTL context|/Private Variables, Global to Report Object>. |
Previous entry in the C<DTL context> is overwritten with the current one. |
The added field values are used during rendering of the portion's L<DTL tags|https://www.leader.it/MasonSQL/OdtReport#Django_Template_Language>. |
The corresponding DTL reference can be used like this: C<{{ my_portion_name.my_field_name }}> |
In case the field is of json type the content of that field is converted to JSON tree and stored to the DTL context.For example: The property of the JSON string C<{"X": {"Y": {"Z": "DATA"}}}> can be accessed with the DTL tag C<{{ myportionname.myfieldname.X.Y.Z }}>. |
Additionally JSON tree is L<converted|/json2utf8()> to UTF8. |
=cut |
sub set_portion_context($$$$){ |
my $self = shift; |
my $id = shift; |
my $field_name = shift; |
my $field_type = shift; |
my $record = shift; |
if($self->{portion}{name}{$id}){ |
#DEBUG $self->say("set_portion_context", "$self->{portion}{name}{$id} => "); |
if($record){ |
for(my $idx = 0; $idx < @{$field_name}; $idx++){ |
my $name = $field_name->[$idx]; |
my $type = $field_type->[$idx]; |
my $field = decode_entities(defined $record->{$name} ? $record->{$name} : ''); |
if($type =~ /json/ && $field){ |
#DEBUG $self->say("set_portion_context", "field=".Dumper($field)); |
my $json = from_json($field); |
$record->{$name} = $self->json2utf8($json); |
#DEBUG say "record=".Dumper($record->{$name}); |
}else{ |
$record->{$name} = Encode::encode_utf8($field); |
} |
} |
#DEBUG $self->say("set_portion_context", "record: ".Dumper($record)); |
$self->{dtl_context}->set($self->{portion}{name}{$id} => $record); |
} |
} |
return; |
} |
=head4 json2utf8() |
Converts encoding of all strings in the json structure to UTF8. |
=cut |
sub json2utf8($){ |
my $self = shift; |
my $json = shift; |
my $ref = ref $json; |
if($ref eq 'ARRAY'){ |
for(my $idx = 0; $idx < @$json; $idx++){ |
my $val = $json->[$idx]; |
if(ref $val){ |
$self->json2utf8($val); |
}else{ |
$json->[$idx] = $val ? Encode::encode_utf8($val) : ''; |
} |
} |
}elsif($ref eq 'HASH'){ |
foreach my $key (keys %$json){ |
my $val = $json->{$key}; |
if(ref $val){ |
$self->json2utf8($val); |
}else{ |
$json->{$key} = $val ? Encode::encode_utf8($val) : ''; |
} |
} |
} |
return $json; |
} |
=head3 Handling odt_table Portions |
=head4 make_table() |
Uses the following procedure to create a new table: |
=over 2 |
=item 1 |
L<Render|https://metacpan.org/pod/DTL::Fast#render> L<obj_ref|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> field value. |
=item 2 |
Update L<content|/Private Variables, Global to Report Object> of current portion. |
=item 3 |
Clone the template table and append the new table to the body of the report. |
Use the last row from the template table as a template row. |
If the table doesn't have any rows skip to step 6. |
=item 4 |
L<Render non-repeating table header|/render_non_repeating_header()>. |
=item 5 |
Populate the table with the query results: |
=over 2 |
=item a. |
Clone the template row and append it to the new table. |
=item b. |
L<Updates images in the current row.|/update_images()> |
=item c. |
Update L<DTL context|/Private Variables, Global to Report Object> with the query results for the current row and with the current row number. |
L<Render|https://metacpan.org/pod/DTL::Fast#render> the appended row. |
=item d. |
Check if any L<children portions|/make_body()> can be added. |
=back |
=item 6 |
L<Render repeating table header|/render_repeating_header()>. |
=back |
=cut |
sub make_table($$$$){ |
my $self = shift; |
my $report = shift; |
my $body = shift; |
my $statement = shift; |
my $id = shift; |
my $obj_ref = $self->render_string($self->{portion}{obj_ref}{$id}); |
if($statement && $obj_ref){ |
#DEBUG say "make_table: $obj_ref"; |
my $content_key = $self->update_portion($obj_ref, $id); |
my $template_table = $self->{content}{$content_key}; |
unless($template_table){ |
die $self->err_msg("Can't find table: '$obj_ref'."); |
} |
my $table = $template_table->clone; |
$body->append_element($table); |
my ($length, $width) = $template_table->get_size; |
my $template_row_id = $length - 1; |
if($template_row_id >= 0){ |
my $template_row = $template_table->get_row($template_row_id); |
$table->delete_row($template_row_id); |
$self->render_non_repeating_header($table, $template_row_id); |
my $row_num = 1; |
my $name = $statement->{NAME}; |
my $type = $statement->{pg_type}; |
while(my $record = $statement->fetchrow_hashref){ |
my $row = $template_row->clone; |
$self->update_images($report, $row); |
$table->append_element($row); |
$record->{'ROW_NUMBER'} = $row_num++; |
$self->set_portion_context($id, $name, $type, $record); |
$self->render_row($row); |
$self->make_body($id, $report, $body); |
} |
} |
$self->render_repeating_header($report, $table); |
} |
return; |
} |
=head4 render_repeating_header() |
Gets L<table header|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Table.pod#Table_headers> and L<renders|https://metacpan.org/pod/DTL::Fast#render> its content. |
Also L<updates images|/update_images()>. |
=cut |
sub render_repeating_header($$){ |
my $self = shift; |
my $report = shift; |
my $table = shift; |
if(my $header = $table->get_column_header){ |
$self->render_text($header); |
$self->update_images($report, $header); |
} |
return; |
} |
=head4 render_non_repeating_header() |
L<Renders non-header rows|/render_row()> except the last one which is reserved as a template row. |
=cut |
sub render_non_repeating_header($$){ |
my $self = shift; |
my $table = shift; |
my $template_row_id = shift; |
for(my $row_id = 0; $row_id < $template_row_id; $row_id++){ |
my $row = $table->get_row($row_id); |
$self->render_row($row); |
} |
return; |
} |
=head4 render_row() |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> text in each cell in the row, consecutively one by one. |
=cut |
sub render_row($){ |
my $self = shift; |
my $row = shift; |
if($row){ |
my @cell = $row->get_cells(); |
foreach my $cell (@cell){ |
$self->render_text($cell); |
} |
} |
return; |
} |
=head3 Handling odt_section Portions |
=head4 make_section() |
Makes a query. |
For each row from the query result: |
=over 2 |
=item 1 |
Updates L<DTL context|/Private Variables, Global to Report Object> with the values from the current row and with the current row number. |
=item 2 |
Appends L<a new section|/add_section()>. |
=back |
If there is no query it still appends one section. |
=cut |
sub make_section($$$$){ |
my $self = shift; |
my $report = shift; |
my $body = shift; |
my $statement = shift; |
my $id = shift; |
if($statement){ |
my $row_num = 1; |
my $name = $statement->{NAME}; |
my $type = $statement->{pg_type}; |
while(my $record = $statement->fetchrow_hashref){ |
$record->{'ROW_NUMBER'} = $row_num++; |
$self->set_portion_context($id, $name, $type, $record); |
$self->add_section($report, $body, $id); |
} |
}else{ |
$self->add_section($report, $body, $id); |
} |
return; |
} |
=head4 add_section() |
Uses the rendered L<obj_ref|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> field value to find the section that is then appended to the body of the report document. |
Before the section is L<appended|/append_portion()> it is L<updated|/update_portion()>. |
In case the portion type is L<odt_file|https://www.leader.it/MasonSQL/OdtReport#odt_file_portion_type> the L<.odt file is appended|/append_odt_file()> to the body of the report instead of a section. |
After the section is L<appended|/append_portion()> its L<images are updated|/update_images()>. |
=cut |
sub add_section($$$){ |
my $self = shift; |
my $report = shift; |
my $body = shift; |
my $id = shift; |
if($self->{portion}{type}{$id} eq 'odt_section'){ |
if(my $obj_ref = $self->render_string($self->{portion}{obj_ref}{$id})){ |
#DEBUG $self->say("add_section", "$obj_ref"); |
my $content_key = $self->update_portion($obj_ref, $id); |
my $portion = $self->append_portion($body, $obj_ref, $content_key); |
$self->update_images($report, $portion); |
} |
}elsif($self->{portion}{type}{$id} eq 'odt_file'){ |
$self->append_odt_file($body, $id); |
} |
$self->make_body($id, $report, $body); |
return; |
} |
=head3 Handling odt_file Portions |
=head4 append_odt_file() |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> the content of the template B<.odt> file then L<appends the file|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Element.pod#Context_import> to the body of the report document. |
=cut |
sub append_odt_file($$){ |
my $self = shift; |
my $body = shift; |
my $id = shift; |
my $file_name = $self->render_string($self->{portion}{file_name}{$id}); |
if($file_name && $file_name !~ /^\s+$/){ |
#DEBUG say "append_odt_file, file_name=$file_name"; |
my $tmp_filepath = $self->tmp_file('odt_file', '.odt'); |
my $template = odf_document->get($self->template_filepath($file_name)); |
$template->save(target => $tmp_filepath); |
my $tmp_doc = odf_document->get($tmp_filepath); |
my $tmp_body = $tmp_doc->get_body; |
$self->render_text($tmp_body); |
#DEBUG say "table: ". Dumper($table->node_info); |
$body->import_children($tmp_body); |
unlink $tmp_filepath; |
} |
return; |
} |
=head3 Handling pdf_report Portions |
=head4 make_pdf_report() |
The procedure to make a pdf report: |
=over 2 |
=item 1 |
Create a new L<temporary .odt file|/tmp_file()>. |
=item 2 |
L<Create new report from portion's ODT template|/new_pdf_report()> and store it to the temporary .odt file. |
=item 3 |
Use L<Unoconv|http://tech.rgou.net/en/php/converting-documents-odt-doc-to-pdf-on-php-with-unoconv-libreoffice/> or Libreoffice |
to convert the newly created report to B<.pdf> file format. |
=item 4 |
Return the converted PDF filepath. |
=back |
=cut |
sub make_pdf_report($$){ |
my $self = shift; |
my $odt_template = shift; |
my $converter = shift; |
my $new_odt = $self->tmp_file('pdf_report', '.odt'); |
$self->new_pdf_report($odt_template, $new_odt); |
my $pdf = $self->tmp_file('pdf_report', '.pdf'); |
my $out = $converter->convert_to_pdf($new_odt, $pdf); |
#DEBUG say "convert_to_pdf out: $out"; |
unlink $new_odt; |
return $pdf; |
} |
=head4 make_pdf_reports() |
Query the database then use the query results to produce the L<pdf reports|https://www.leader.it/MasonSQL/OdtReport#pdf_report_portion_type>. |
Before making each new pdf report update the L<DTL context|/Private Variables, Global to Report Object> with current record. |
=cut |
sub make_pdf_reports($$){ |
my $self = shift; |
my $odt_template = shift; |
my $portion_id = shift; |
my $query = $self->render_string($self->{portion}{query}{$portion_id}); |
#DEBUG say "make_pdf_reports query=[\n$query\n]"; |
my @pdfs = (); |
if($query){ |
my $statement = $self->{Dbh}->prepare($query); |
$statement->execute(); |
if($statement){ |
my $row_num = 1; |
my $converter = MasonSQL::Report::OdtConv->new(Engine => $self->{OdtConvEngine}); |
while(my $record = $statement->fetchrow_hashref){ |
$record->{'ROW_NUMBER'} = $row_num++; |
$self->set_portion_context($portion_id, $statement->{NAME}, $statement->{pg_type}, $record); |
#DEBUG say 'pdf context:'.Dumper($record); |
push(@pdfs, $self->make_pdf_report($odt_template, $converter)); |
} |
} |
} |
return \@pdfs; |
} |
=head4 new_pdf_report() |
Open the portion's template file; Save the template file as a new report; |
Then L<prepare the report|/prepare_report()> and L<render its contents|/render_text()>. |
=cut |
sub new_pdf_report($$){ |
my $self = shift; |
my $odt_template = shift; |
my $new_odt = shift; |
if(my $template = odf_document->get($odt_template)){ |
$template->save(target => $new_odt); |
}else{ |
die $self->err_msg("Can't find template file '$odt_template'"); |
} |
my ($report, $body) = $self->prepare_report($new_odt); |
$self->update_images($report, $body); |
$self->render_text($body); |
$report->save; |
# Make second pass, with render_report(), in case the report contains forms |
# tags which don't seem to be supported by ODF::lpOD. |
$self->render_report($report, $new_odt); |
# Following save is not needed since it is called in the render_report(). |
#$report->save; |
return; |
} |
=head4 render_report() |
L<Render|https://metacpan.org/pod/DTL::Fast#render> the newly created ODT template file. |
=cut |
sub render_report($$){ |
my $self = shift; |
my $report = shift; |
my $new_odt = shift; |
my @parts = (CONTENT, STYLES); |
my %xml = (); |
foreach my $part_name (@parts){ |
my $part = $report->get_part($part_name); |
my $xml = $part->serialize; |
my $rendered = $self->render_string($xml); |
#DEBUG say "xml{$part_name}: {$rendered}"; |
$xml{$part_name} = $rendered; |
} |
# Must save and reopen here. |
# Following code is a workaround for set_part() function. |
$report->save; |
$report = odf_document->get($new_odt); |
my @tmp_file = (); |
foreach my $part_name (@parts){ |
#$report->set_part($part_name, $xml); |
my $tmp_filepath = $self->tmp_file($part_name, '.xml', $xml{$part_name}); |
$report->del_part($part_name); |
$report->add_file($tmp_filepath, path => $part_name); |
push (@tmp_file, $tmp_filepath); |
} |
$report->save(); |
foreach my $tmp_filepath (@tmp_file){ |
unlink $tmp_filepath; |
} |
return; |
} |
=head3 Text Processing |
=head4 remove_comments() |
Removes all L<comments|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/TextElement.pod#Annotation_retrieval> from the report document. |
=cut |
sub remove_comments($){ |
my $self = shift; |
my $body = shift; |
my @comments = $body->get_annotations(); |
foreach my $comment (@comments){ |
$comment->delete; |
} |
return; |
} |
=head4 truncate_blanks() |
Removes white spaces from the beginning and from the end of the string. |
=cut |
sub truncate_blanks($){ |
my $self = shift; |
my $string = shift; |
if($string){ |
$string =~ s/^\s+//; |
$string =~ s/\s+$//; |
} |
return $string; |
} |
=head3 DTL Rendering |
=head4 clean_dtl_tags() |
Remove the text-spans from the xml's DTL tags. |
Use the regular expressions to list the DTL tags. |
Loop over the found tags: |
=over 2 |
=item 1 |
Count the number of text-spans inside the tag. |
=item 2 |
If the tag contains any text-spans remove them. |
=item 3 |
=over 2 |
=item * |
If the number of text-spans, inside the tag, is odd simply remove all text-spans from it. |
=item * |
If the number of text-spans, inside the tag, is even extract one of the spans to the left or to the right of the tag. |
=back |
=back |
=cut |
sub clean_dtl_tags($){ |
my $self = shift; |
my $xml = shift; |
my $span_regex = '(<|<\/)text:span[^>]*>'; |
my $any_spans = '('.$span_regex.')*'; |
my @part = (); |
$part[0] = '{'.$any_spans; |
$part[1] = '({|%)([^%}]*'.$any_spans.'[^%}]*)(%|})'; |
$part[2] = $any_spans.'}'; |
my $tag_regex = join('', @part); |
#DEBUG say "tag_regex=$tag_regex"; |
my $span_beginning = '<text:span[^>]*>'; |
my $span_ending = '<\/text:span[^>]*>'; |
$xml =~ s/<text:s\/>//g; |
$xml =~ s/<text:soft-page-break\/>//g; |
foreach my $dirty ($xml =~ m/($tag_regex)/sg){ |
unless(defined $dirty){ |
next; |
} |
my @spans = ($dirty =~ m/$span_regex/g); |
if(@spans){ |
my $cleaned = ''; |
if(@spans % 2){ |
if($dirty =~ /^[^<]*($span_ending)/){ |
my $keep_span = $1; |
$cleaned = $dirty =~ s/$span_regex//gr; |
$cleaned .= $keep_span; |
#DEBUG say "with span ending=$cleaned"; |
}elsif($dirty =~ /($span_beginning)[^>]*$/){ |
my $keep_span = $1; |
$cleaned = $dirty =~ s/$span_regex//gr; |
$cleaned = $keep_span.$cleaned; |
#DEBUG say "with span beginning=$cleaned"; |
}else{ |
die "Bad regex."; |
} |
}else{ |
$cleaned = $dirty =~ s/$span_regex//gr; |
#DEBUG say "even, cleaned=$cleaned"; |
} |
$xml =~ s/\Q$dirty\E/$cleaned/g; |
} |
} |
return $xml; |
} |
=head4 pre_render_variables() |
Find all simple variables inside the text element. |
Simple variables are identified in the xml with 'variable-set' tag. |
For each variable: |
=over 2 |
=item 1 |
Obtain the variable name. |
=over 2 |
=item a. |
First look for variable name in the L<odt_rpt_fields|/> hash. |
If the variable name is stored there, L<update|/set_variable()> with it the variable value. |
=item b. |
Then look for the variable name in the DTL hash. |
If the variable name is found in the DTL hash, L<update|/set_variable()> with it the variable value. |
=back |
=back |
=cut |
sub pre_render_variables($){ |
my $self = shift; |
my $text_element = shift; |
foreach my $var ($text_element->get_fields('variable-set')){ |
my $var_type = $var->get_attribute('office:value-type'); |
if(my $var_name = $var->get_attribute('text:name')){ |
my $var_value = ''; |
my $field = $self->{odt_rpt_fields}{$var_name}; |
if(defined $field && defined $field->{fun}){ |
$var_value = $self->render_string(Encode::encode_utf8(decode_entities($field->{fun}))); |
}elsif(my $dtl_value = $self->{dtl_context}->get($var_name)){ |
$var_value = $dtl_value; |
} |
my $var_format = ''; |
if(defined $field && defined $field->{format}){ |
$var_format = $self->render_string(Encode::encode_utf8(decode_entities($field->{format}))); |
#DEBUG say "var_name=$var_name, var_type=$var_type, var_value=$var_value"; |
} |
$self->set_variable($var, $var_type, $var_value, $var_format); |
} |
} |
return; |
} |
=head4 set_variable() |
Sets variable's attributes with new values. Handles simple variables of all available data types: |
'string', 'float', 'currency', 'percentage', 'boolean', 'date' and 'time'. |
For the types 'date' and 'time' there's the workaround: |
Their types are changed to 'string'; |
The public.odt_report_field.format field value is used as a formatting string. |
=cut |
sub set_variable($$$$){ |
my $self = shift; |
my $var = shift; |
my $type = shift; |
my $value = shift; |
my $format = shift; |
my $v = check_odf_value($value, $type); |
unless(defined $v){ |
return undef; |
} |
if($type eq 'date' || $type eq 'time' || $type eq 'string'){ |
$value = $format ? sprintf($format, $value) : $value; |
}elsif($type eq 'boolean'){ |
$v = odf_boolean($v); |
$var->set_attribute('office:boolean-value', $v); |
$var->set_attribute('text:formula', "ooow:$v"); |
}else{ |
unless($v){ |
$v = 0; |
} |
unless($value){ |
$value = 0; |
} |
if($type eq 'float'){ |
$var->set_attribute('office:value', sprintf("%f", $v)); |
$var->set_attribute('text:formula', "ooow:".sprintf("%f", $value)); |
}elsif($type eq 'currency'){ |
$v = sprintf("%f", $v); |
$var->set_attribute('office:value', $v); |
$var->set_attribute('text:formula', "ooow:$v"); |
}elsif($type eq 'percentage'){ |
$v /= 100; |
$v = sprintf("%f", $v); |
$var->set_attribute('office:value', $v); |
$var->set_attribute('text:formula', "ooow:$v"); |
} |
} |
$var->set_text($value); |
return $v; |
} |
=head4 render_string() |
Uses L<DTL|https://www.leader.it/MasonSQL/OdtReport#Django_Template_Language> to L<render|https://metacpan.org/pod/DTL::Fast#render> an input string. |
=cut |
sub render_string($){ |
my $self = shift; |
my $str = shift; |
my $tpl = DTL::Fast::Template->new($str); |
my $rendered = $tpl->render($self->{dtl_context}); |
return $rendered; |
} |
=head4 render_text() |
L<Renders|/render_list()> all object's L<headings|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/TextElement.pod#get_headings> and L<paragraphs|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/TextElement.pod#get_paragraphs>. |
=cut |
sub render_text($){ |
my $self = shift; |
my $object = shift; |
if($object){ |
my @headings = $object->get_headings(); |
$self->render_list($object, \@headings); |
my @paragraphs = $object->get_paragraphs(); |
$self->render_list($object, \@paragraphs); |
} |
} |
=head4 render_list() |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> text from each element in the input list. |
Steps performed on each element: |
=over 2 |
=item 1 |
Firstly, L<pre-render variables|/pre_render_variables()> inside the element's xml. |
=item 2 |
Secondly, serialize the element and L<decode its entities>. |
=item 3 |
Thirdly, clean the text-spans out of the DTL tags contained in the element's xml. |
=item 4 |
Fourthly, render the xml. |
=item 5 |
Fifthly, create a new element from the rendered xml. |
=item 6 |
Finally, replace the element with the new rendered element. |
=back |
=cut |
sub render_list($$){ |
my $self = shift; |
my $object = shift; |
my $list = shift; |
foreach my $text_element (@{$list}){ |
$self->pre_render_variables($text_element); |
my $xml = decode_entities($text_element->serialize); |
$xml =~ s/office:value-type=("|')(date|time)("|')/office:value-type="string"/g; #workaround |
$xml = $self->clean_dtl_tags($xml); |
my $rendered = $self->render_string($xml); |
$rendered =~ s/\t/<text:tab\/>/gs; |
$rendered =~ s/\r{0,1}\n/<text:line-break\/>/gs; |
if(my $new_p = odf_element->create($rendered)){ |
#DEBUG say 'new_xml: '.$new_p->serialize(); |
$object->insert_element($new_p, before => $text_element); |
$text_element->delete(); |
} |
} |
return; |
} |
=head4 render_header_footer() |
Accesses the L<page styles|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Style.pod#Page_styles>; |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> text elements found in L<page header and page footer|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Style.pod#Page_headers_and_footers>. |
=cut |
sub render_header_footer($){ |
my $self = shift; |
my $report = shift; |
foreach my $page_style ($report->get_styles('master page')){ |
$self->render_text($page_style); |
} |
return; |
} |
=head3 Rendering Images |
=head4 delete_old_images() |
Deletes any previously existing image linked to the frame. |
=cut |
sub delete_old_images($$){ |
my $self = shift; |
my $report = shift; |
my $frame = shift; |
my @images = $frame->get_elements('draw:image'); |
for(my $idx = 0; $idx < @images; $idx++){ |
my $old_link = ($images[$idx])->get_uri; |
$report->del_part($old_link); |
} |
return; |
} |
=head4 conv_um2mm() |
Convert a distance (with differentes units to millimeters |
=cut |
# See https://help.libreoffice.org/Common/Conversion_of_measurement_units |
sub conv_um2mm($){ |
my $val_um = shift; |
$val_um =~ m/^([\.\d]+)\s*(mm|cm|in|"|pi|pt)$/; |
my $val = $1; |
my $um = $2; |
if($um eq 'mm'){ |
return $val_um; |
}elsif($um eq 'cm'){ |
return $val*10; |
}elsif($um eq 'in' || $um eq '"'){ |
return $val*25.4; |
}elsif($um eq 'pi'){ |
return $val*25.4/6.0; |
}elsif($um eq 'pt'){ |
return $val*25.4/72.0; |
}else{ |
die "conv_um2mm: unknow value '$val_um'"; |
} |
} |
=head4 render_image() |
Replaces the image with the content of its L<DTL tag|https://www.leader.it/MasonSQL/OdtReport#Django_Template_Language>. |
Rendering steps: |
=over 2 |
=item 1 |
Store the image content to a temporary file. If the image is already added to the C<Pictures> directory inside B<.odt> report file, skip all following steps. |
=item 2 |
Detect the image mime type. |
=item 3 |
Add the temporary image file to the C<Pictures> directory. |
=item 4 |
Delete template images from the C<Pictures> directory. |
=item 5 |
Add the temporary image file to the L<tmp_image_filepath|/Private Static Variables> list, to be deleted when object gets destroyed. |
=item 6 |
Link newly created image to the existing frame. The frame size doesn't change. |
=back |
=cut |
sub render_image($$$$){ |
my $self = shift; |
my $report = shift; |
my $img = shift; |
my $image_name = shift; |
my $content = shift; |
my $frame = $img->get_parent; |
my($frame_x,$frame_y) = $frame->get_size; |
$frame_x = conv_um2mm($frame_x); |
$frame_y = conv_um2mm($frame_y); |
my $frame_ratio = $frame_x / $frame_y; |
#DEBUG $self->say("render_image", "image_name=$image_name, content=$content"); |
if($content =~ m/^data:(\w+\/\w+);base64,(.+)/){ |
my $mime = $1; |
$content = $2; |
$img->set_content($content); |
$content = decode_base64 $content; |
}elsif(my $image_type = (Image::Info::image_type(\$content))->{file_type}){ |
#DEBUG $self->say("render_image", "image_type=$image_type"); |
$image_name .= ".".lc $image_type; |
unless($self->is_in_pictures($image_name)){ |
my $tmp_filepath = "$self->{TmpDir}/$image_name"; |
open (my $tmp_fh, '>', $tmp_filepath) or die $self->err_msg("Could not open file: $tmp_filepath for writing."); |
binmode $tmp_fh; |
print $tmp_fh $content; |
close $tmp_fh; |
my $mime_type = mimetype($tmp_filepath); |
#DEBUG $self->say("render_image", "mime_type=$mime_type"); |
$report->add_image_file($tmp_filepath, type => $mime_type); |
$self->push_tmp_image($tmp_filepath); |
} |
my $link = "Pictures/$image_name"; |
$img->set_uri($link); |
}else{ |
die $self->err_msg("Unknown image type!"); |
} |
my($image_x, $image_y) = imgsize(\$content); |
if($image_y && $image_x){ |
# con immagini di tipo SVG la funzione imgsize non ritorna le dimensioni |
# nel caso di immagini SVG non è necessario scalare l'immagine |
my $image_ratio = $image_x / $image_y; |
if($image_ratio > $frame_ratio){ # image is wider |
$frame_y *= $frame_ratio / $image_ratio; |
}else{ |
$frame_x *= $image_ratio / $frame_ratio; |
} |
} |
# The image remains confined in the frame without deformation |
$frame->set_size(sprintf('%.4fmm', $frame_x), sprintf('%.4fmm', $frame_y)); |
return; |
} |
=head4 process_image() |
Adds the image to the C<Pictures> directory inside the B<.odt> report file. A name of the new image is C<< <portion name>_<image name>_<number of row>.<suffix> >> . If the DTL tag is empty or the ROW_NUMBER is missing (indicates empty query) the subroutine simply removes the image frame. After initial processing of the image the image is L<rendered|/render_image()>. |
=cut |
sub process_image($$$$){ |
my $self = shift; |
my $report = shift; |
my $frame = shift; |
my $portion_name = shift; |
my $field_name = shift; |
#DEBUG $self->say("process_image", "portion_name=$portion_name, field_name=$field_name"); |
if(my $row_number = $self->{dtl_context}->get("${portion_name}.ROW_NUMBER")){ |
my $image_name = "${portion_name}_${field_name}_$row_number"; |
#DEBUG $self->say("process_image", "row_number=$row_number, image_name=$image_name"); |
$self->delete_old_images($report, $frame); |
if(my $content = $self->{dtl_context}->get("${portion_name}.$field_name")){ |
my $img = $frame->get_image; |
$self->render_image($report, $img, $image_name, $content); |
return; |
} |
} |
$frame->delete; |
return; |
} |
=head4 update_images() |
L<Updates|/process_image()> each image, in object's headers and paragraphs, which contains a L<DTL tag|https://www.leader.it/MasonSQL/OdtReport#Django_Template_Language> in its name. The DTL tag must be in a C<< #<portion_name>.<field_name> >> form. |
=cut |
sub update_images($$){ |
my $self = shift; |
my $report = shift; |
my $object = shift; |
my @texts = $object->get_headings(); |
push(@texts, $object->get_paragraphs()); |
foreach my $text_element (@texts){ |
foreach my $frame ($text_element->get_frames){ |
my $frame_name = $frame->get_name; |
if($frame_name && $frame_name =~ m/^#(\w+)\.([a-zA-Z0-9_.]+)$/){ |
$self->process_image($report, $frame, $1, $2); |
} |
} |
} |
return; |
} |
=head3 Ordering |
=head4 get_appendable_sequence() |
Sorts the L<appendable|/get_odt_report_portions()> portion IDs into L<appendable_seq|/Private Variables, Global to Report Object> list, ordered according to L<ord|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> field. |
=cut |
sub get_appendable_sequence(){ |
my $self = shift; |
#DEBUG say 'input order: '.Dumper(\%{$self->{portion}{obj_ref}}); |
my @appendable_seq = sort { $self->{portion}{appendable}{$a} <=> $self->{portion}{appendable}{$b} } keys %{$self->{portion}{appendable}}; |
$self->{appendable_seq} = \@appendable_seq; |
#DEBUG say 'sort order:'; |
#DEBUG foreach (@appendable_seq){ |
#DEBUG say "$_=>$self->{portion}{order}{$_}"; |
#DEBUG } |
return; |
} |
=head4 get_attachable_sequence() |
Sorts the L<attachable|/get_odt_report_portions()> portion IDs into L<attachable_seq|/Private Variables, Global to Report Object> list, ordered according to L<ord|https://www.leader.it/MasonSQL/OdtReport#public.odt_report_portions_Table> field. |
=cut |
sub get_attachable_sequence(){ |
my $self = shift; |
#DEBUG say 'input order: '.Dumper(\%{$self->{portion}{obj_ref}}); |
my @attachable_seq = sort { $self->{portion}{attachable}{$a} <=> $self->{portion}{attachable}{$b} } keys %{$self->{portion}{attachable}}; |
$self->{attachable_seq} = \@attachable_seq; |
#DEBUG say 'sort order:'; |
#DEBUG foreach (@attachable_seq){ |
#DEBUG say "$_=>$self->{portion}{order}{$_}"; |
#DEBUG } |
return; |
} |
=head3 Determing Inheritance |
=head4 find_children() |
Returns an ordered list of portion IDs of children portions. |
It returns only portions that can be appended to the body of the report document. |
=cut |
sub find_children($){ |
my $self = shift; |
my $father_id = shift; |
my @children = (); |
#DEBUG say "father_id=$father_id"; |
#DEBUG say "base_id=$self->{base_id}"; |
foreach my $child_id (@{$self->{appendable_seq}}){ |
if($self->{portion}{appendable}{$child_id}){ |
if($self->{portion}{father}{$child_id}){ |
if($self->{portion}{father}{$child_id} eq $father_id){ |
push (@children, $child_id); |
} |
}elsif($father_id == $self->{base_id}){ |
push (@children, $child_id); |
} |
} |
} |
#DEBUG say "children: ".Dumper(\@children); |
return \@children; |
} |
=head3 Making Report |
=head4 make_body() |
Is a recursive subroutine. It is initally called from L<make_report|/make_report()> when the father ID is the base portion ID. |
If first finds sibling portions then for each siblings then: |
=over 2 |
=item 1 |
L<Renders|https://metacpan.org/pod/DTL::Fast#render> portion's query string. |
=item 2 |
Makes the query. |
=item 3 |
=over 2 |
=item a. |
If the portion type is L<odt_section|https://www.leader.it/MasonSQL/OdtReport#odt_section_portion_type> or L<odt_file|https://www.leader.it/MasonSQL/OdtReport#odt_file_portion_type> L<makes a new section|/make_section()>. |
=item b. |
If the portion type is L<odt_table|https://www.leader.it/MasonSQL/OdtReport#odt_table_portion_type> L<makes a new table|/make_table()>. |
=back |
=back |
The subroutine is recursively called from L<make_table|/make_table()> or from L<add_section|/add_section()>. |
=cut |
sub make_body($$$); |
sub make_body($$$){ |
my $self = shift; |
my $father_id = shift; |
my $report = shift; |
my $body = shift; |
my $siblings = $self->find_children($father_id); |
foreach my $id (@$siblings){ |
my $statement = (); |
my $query = $self->truncate_blanks($self->render_string($self->{portion}{query}{$id})); |
if($query){ |
#DEBUG $self->say("make_body", "query=[\n$query\n]"); |
$statement = $self->{Dbh}->prepare($query); |
$statement->execute(); |
} |
my $type = $self->{portion}{type}{$id}; |
if($type eq 'odt_section' || $type eq 'odt_file'){ |
$self->make_section($report, $body, $statement, $id); |
}elsif($type eq 'odt_table'){ |
$self->make_table($report, $body, $statement, $id); |
} |
} |
return; |
} |
=head4 new_report() |
Open the base template file; Save it as a new report; |
Then L<prepare the report|/prepare_report()> and return its references. |
=cut |
sub new_report($){ |
my $self = shift; |
my $new_odt = shift; |
if(my $base_template = odf_document->get($self->template_filepath($self->{base_file_name}))){ |
$base_template->save(target => $new_odt); |
}else{ |
die $self->err_msg("Can't find base template file '$self->{base_file_name}'"); |
} |
return $self->prepare_report($new_odt); |
} |
=head4 prepare_report() |
Remove L<comments|/remove_comments()> from the entire document. |
Initially L<Update images|/update_images()> only in STYLES part. |
L<Render header and footer|/render_header_footer()>. |
=cut |
sub prepare_report($){ |
my $self = shift; |
my $new_odt = shift; |
my $report = odf_document->get($new_odt); |
my @parts = (CONTENT, STYLES); |
foreach my $part_name (@parts){ |
my $body = $self->get_bodypart($report, $part_name); |
$self->remove_comments($body); |
} |
my $styles = $self->get_bodypart($report, STYLES); |
$self->update_images($report, $styles); |
$self->render_header_footer($report); |
return ($report, $report->get_body); |
} |
=head3 Accessing Document |
=head4 get_bodypart() |
Gets body of the required L<part|http://search.cpan.org/~jmgdoc/ODF-lpOD-1.121/lpOD/Document.pod#Access_to_individual_document_parts> of the document. |
=cut |
sub get_bodypart($$){ |
my $self = shift; |
my $document = shift; |
my $part_name = shift; |
my $content = $document->get_part($part_name); |
return $content->get_body; |
} |
=head3 Accessing File System |
=head4 unlink_files() |
Unlinks files from the input list of filepaths. |
=cut |
sub unlink_files($){ |
my $self = shift; |
my $list_of_files = shift; |
foreach my $file (@{$list_of_files}){ |
unlink $file; |
} |
return; |
} |
=head4 template_filepath() |
Constructs the filepath of a template file. |
The root directory for the template files of the specific report is: C<< <InputFilesArchive>/public/odt_reports/<odt_report_id>/ >> directory. |
A file name of the template file must contain relative path to the template root directory. |
The subroutine also validates that: |
=over 2 |
=item * |
The checked filepath exists. |
=item * |
The checked file is not empty. |
=item * |
The file is accessable for reading. |
=back |
=cut |
sub template_filepath($){ |
my $self = shift; |
my $template_file_name = shift; |
unless($self->{odt_rpt_id}){ |
die $self->err_msg("Uninitialized odt_rpt_id."); |
} |
my $dir = "$self->{InputFilesArchive}/public/odt_reports/$self->{odt_rpt_id}/"; |
my $filepath = realpath("$dir/$template_file_name"); |
unless($filepath){ |
die $self->err_msg("$template_file_name not present in the Template Files directory, please upload it."); |
} |
my $testpath = "\'$filepath\'"; |
if(-s $testpath){ |
die $self->err_msg("$template_file_name has zero size, please specify relative filepath to a valid file."); |
} |
if(-r $testpath){ |
die $self->err_msg("$template_file_name file is not readable, please enable access to the file."); |
} |
#DEBUG say "template_filepath=$filepath"; |
return $filepath; |
} |
=head4 tmp_file() |
Uses L<File::Temp::tempfile|http://search.cpan.org/~dagolden/File-Temp-0.2304/lib/File/Temp.pm> to create a new temporary file. |
If there is content it stores it to the temporary file. |
Then closes the file, to make sure it is unlocked, finally returns its filepath. |
=cut |
sub tmp_file($$$$){ |
my $self = shift; |
my $prefix = shift; |
my $suffix = shift; |
my $content = shift; |
my($fh, $filepath) = tempfile( |
$prefix . '_XXXXX', |
DIR => $self->{TmpDir}, |
SUFFIX => $suffix, |
UNLINK => 0 |
); |
if($content){ |
print $fh $content; |
} |
close $fh; |
#DEBUG say "tmp_filepath=$filepath"; |
return $filepath; |
} |
=head3 Error Handling |
=head4 err_msg() |
The subroutine formats every die message of this module so their detection is made easier. |
=cut |
sub err_msg($){ |
my $self = shift; |
my $err_msg = shift; |
return "Error: $err_msg"; |
} |
=head3 Destructor |
=head4 DEMOLISH() |
Closes down the database connection during the object's destruction. |
=cut |
sub DEMOLISH{ |
my $self = shift; |
$self->unlink_tmp_images(); |
return; |
} |
=head2 Copyright |
(C) 2003 Leader.IT di Guido Brugnara <http://www.leader.it> |
Strada della Pozzata, 41 - Villazzano |
38123 T R E N T O (ITALY) |
=head2 Authors |
Guido Brugnara |
Janez Stangelj |
=cut |
1; |
/tags/2.0/lib/MasonSQL/SMS.pm |
---|
0,0 → 1,93 |
#!/usr/bin/perl -w |
#********************************************************************************** |
# Package created to work with SMS |
#********************************************************************************** |
package MasonSQL::SMS; |
use utf8; |
use strict; |
use warnings; |
use Data::Dumper; |
use JSON; |
use Encode qw(encode decode); |
use Carp; |
use Data::Dumper; |
sub new { |
my $class = shift; |
my(%args) = @_; |
my $self = { args => \%args }; |
bless($self, $class); |
if($args{text}){ |
$self->text(delete $args{text}); |
} |
return $self; |
} |
# restituisce o prepara la stringa |
# codifica la stringa sostituendo i caratteri non ammessi con "?" e calcola il numero di messaggi SMS necessari alla trasmissione |
# vedasi tabella codifica https://en.wikipedia.org/wiki/GSM_03.38#GSM_7-bit_default_alphabet_and_extension_table_of_3GPP_TS_23.038_/_GSM_03.38 |
sub text { |
my($self, $str, $max_length) = @_; |
if(!defined $str){ |
return $self->{text}; |
} |
my $gsm0338 = encode('gsm0338', $str); |
# Attenzione: length ritorna la lunghezza in byte, ovvero i caratteri rappresentati con ESC + codice vengono conteggiati 2 |
my $len = length $gsm0338; |
# default max lenght |
$max_length //= $self->{args}{max_length}; |
if(defined $max_length && $len > $max_length){ |
# taglio la stringa mettendo in fondo " ..." per far comprendere al destinatario che il messaggio è stato tagliato |
$gsm0338 = substr($gsm0338, 0, $max_length -4); |
# verifico se l'ultimo carattere è ESC (carattere speciale che occupa 2 byte tagliato a metà) |
if(ord(substr($gsm0338, -1, 1)) == 27){ |
$gsm0338 = substr $gsm0338, 0, length($gsm0338) - 1; |
} |
$gsm0338 .= ' ...'; |
$len = length $gsm0338; |
} |
# Calcolo il costo del messaggio |
my $cost = 1; |
if($len > 160){ |
# numero di SMS necessari per trasmettere il messaggio |
$cost = int((152+$len)/153); |
} |
# purtroppo encode('utf8', ...) non codifica correttamente il carattere @ (0x00) quando è seguito da un'altro \0x00 o da ESC. |
# sono costretto a interpretare il carattere \0x00 separatamente ... |
my $text; |
while(1){ |
my $zpos = index $gsm0338, "\0"; |
if($zpos == -1){ |
$text .= decode('gsm0338', $gsm0338); |
last; |
}else{ |
my $left = substr $gsm0338, 0, $zpos; |
$text .= decode('gsm0338', $left).'@'; |
$gsm0338 = substr $gsm0338, $zpos + 1; |
} |
length($gsm0338) || last; |
} |
$self->{gsm0338} = $gsm0338; |
$self->{text} = $text; |
$self->{cost} = $cost; |
return $text; |
} |
# Ritorna il testo del messaggio codificato gsm0338 |
sub gsm0338 { |
my $self = shift; |
return $self->{gsm0338}; |
} |
# Ritorna il costo dell'SMS |
sub cost { |
my $self = shift; |
return $self->{cost}; |
} |
# Ritorna o modifica |
1; |
/tags/2.0/lib/MasonSQL/Report/OdtConv.pm |
---|
0,0 → 1,164 |
package MasonSQL::Report::OdtConv; |
use strict; |
use warnings; |
use IPC::Run; |
use IPC::Run::SafeHandles; |
use File::Basename; |
use File::Copy qw(move); |
## |
# OdtConv class wrapper |
# |
# @author Rafael Goulart <rafaelgou@gmail.com> |
# @see http://tech.rgou.net/ |
## |
sub new { |
my $class = shift; |
my %rpt = @_; |
return bless \%rpt, $class; |
} |
## |
# Basic converter method |
# |
# @param string $origin_filepath Origin File Path |
# @param string $output_format Format to export To |
# @param string $output_filepath Output directory path |
## |
sub convert($$$){ |
my $self = shift; |
my $origin_filepath = shift; |
my $output_filepath = shift; |
my $output_format = shift; |
my ($err, $out); |
if($self->{Engine} eq 'unoconv'){ |
my @cmd = ( |
'/usr/bin/unoconv', |
'--format' => $output_format, |
# '-e' => 'MaxImageResolution=300', |
# '-e' => 'ReduceImageResolution=0', |
# '-e' => 'Quality=90', |
'--output' => $output_filepath, |
$origin_filepath |
); |
#DEBUG print "cmd: ".join(' ', @cmd); |
# Sometimes unoconv abort with error at startup, but if you rerun ... it work well!!! |
my $count = 4; |
my $timeout = 1; |
while(1){ |
if($timeout != 1){ |
sleep $timeout; |
} |
$count--; |
$timeout *= 2; |
if(run(\@cmd, \undef, \$out, \$err, init => sub { |
$ENV{LANG} = 'it_IT@UTF8'; |
$ENV{LC_NUMERIC} = 'it_IT@UTF8'; |
}) |
){ |
if(! -e $output_filepath || -z $output_filepath){ |
if($count <= 0){ |
die "unoconv error $? file output is empty or not exists cmd:[".(join ' ', @cmd)."] out:[$out] err:[$err]\n"; |
}else{ |
next; |
} |
} |
if($out){ |
return "unoconv convert out=[\n$out]"; |
} |
return ''; |
} |
if($count <= 0){ |
die "unoconv run error $? cmd:[".(join ' ', @cmd)."] out:[$out] err:[$err]\n"; |
} |
} |
}elsif($self->{Engine} eq 'libreoffice'){ |
# purtroppo libreoffice non permette di generare il file con un nome diverso da quello cotituito dal nome del file .odt sostituito da .$output_format |
my($odt_name, $odt_dirs, $odt_suffix) = fileparse($origin_filepath, qr/\.[^.]*/); |
$odt_suffix =~s/^\.//; |
my($out_name, $out_dirs, $out_suffix) = fileparse($output_filepath, qr/\.[^.]*/); |
$out_suffix =~s/^\.//; |
my $outdir = $odt_dirs eq $out_dirs && $out_suffix eq $output_format ? $out_dirs : $odt_dirs; |
my @cmd = ( |
'/usr/bin/libreoffice', |
'--headless', |
'--convert-to' => $output_format, |
'--outdir' => $outdir, |
$origin_filepath |
); |
my $outfile = "$outdir/$odt_name.$output_format"; |
#DEBUG print "cmd: ".join(' ', @cmd); |
# Sometimes libreoffice abort with error at startup, but if you rerun ... it work well!!! |
my $count = 4; |
my $timeout = 1; |
while(1){ |
if($timeout != 1){ |
sleep $timeout; |
} |
$count--; |
$timeout *= 2; |
if(run(\@cmd, \undef, \$out, \$err, init => sub { |
$ENV{LANG} = 'it_IT@UTF8'; |
$ENV{LC_NUMERIC} = 'it_IT@UTF8'; |
}) |
){ |
if(! -e $outfile || -z $outfile){ |
if($count <= 0){ |
die "libreoffice error $? file output $outfile is empty or not exists cmd:[".(join ' ', @cmd)."] out:[$out] err:[$err]\n"; |
}else{ |
next; |
} |
} |
if($outfile ne $output_filepath){ |
move $outfile, $output_filepath || die "libreoffice move error $? from $outfile to $output_filepath\n"; |
} |
if(! -e $output_filepath || -z $output_filepath){ |
if($count <= 0){ |
die "libreoffice error $? file moved is empty or not exists cmd:[".(join ' ', @cmd)."] out:[$out] err:[$err]\n"; |
}else{ |
next; |
} |
} |
if($out){ |
return "libreoffice convert out=[\n$out]"; |
} |
return ''; |
} |
if($count <= 0){ |
die "libreoffice run error $? cmd:[".(join ' ', @cmd)."] out:[$out] err:[$err]\n"; |
} |
} |
}else{ |
die "OdtConv Engine '$self->{Engine}' non exists\n"; |
} |
} |
## |
# Convert to PDF |
# |
# @param string $origin_filepath Origin File Path |
# @param string $output_filepath Output directory path |
## |
sub convert_to_pdf($$){ |
my $self = shift; |
my $origin_filepath = shift; |
my $output_filepath = shift; |
return $self->convert($origin_filepath, $output_filepath, 'pdf'); |
} |
## |
# Convert to TXT |
# |
# @param string $origin_filepath Origin File Path |
# @param string $output_filepath Output directory path |
## |
sub convert_to_txt($$){ |
my $self = shift; |
my $origin_filepath = shift; |
my $output_filepath = shift; |
return $self->convert($origin_filepath, $output_filepath, 'txt'); |
} |
1; |
/tags/2.0/lib/MasonSQL/JSONRPCUtils.pm |
---|
0,0 → 1,39 |
package MasonSQL::JSONRPCUtils; |
use strict; |
#use JSON; |
use JSON -support_by_pp; |
sub json_rpc_response{ |
my $content = shift || return; |
my $json_response = {'version' => '1.1', |
'result' => $content |
}; |
return JSON::objToJson($json_response, {allow_unknown => 1, allow_blessed => 1, convert_blessed => 1}); |
} |
sub json_rpc_error_response{ |
my $content = shift || return; |
my $message = shift || return; |
my $code = shift || 500; |
my $timestamp = shift; |
if(!$timestamp){ |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
$timestamp = sprintf "%4d-%02d-%02d %02d:%02d:%02d", $year+1900,$mon+1,$mday,$hour,$min,$sec; |
} |
my $json_response = {'version' => 1.1, |
'error' => {'name' => 'JSONRPCError', |
'code' => $code, |
'timestamp' => $timestamp, |
'message' => $message, |
'error' => $content |
} |
}; |
return JSON::objToJson($json_response, {allow_unknown => 1, allow_blessed => 1, convert_blessed => 1}); |
} |
1; |
/tags/2.0/lib/MasonSQL/ApacheHandler.pm |
---|
0,0 → 1,21 |
# Handler per la gestione customizzata degli errori di mason |
package MasonSQL::ApacheHandler; |
use strict; |
use HTML::Mason::ApacheHandler; |
# preparo |
sub handler { |
my $r = shift; |
my $return = eval { HTML::Mason::ApacheHandler->handler($r) }; |
if(my $error = $@){ |
# l'oggetto $error viene poi utilizzato in /lib/error.comp |
$r->pnotes( error => $error ); |
$r->filename( $r->document_root . '/lib/error.comp'); |
return HTML::Mason::ApacheHandler->handler($r); |
} |
return $return; |
} |
1; |
/tags/2.0/lib/MasonSQL/CompRootHandler.pm |
---|
0,0 → 1,31 |
# utilizzato in Apache 1.3 |
# |
package MasonSQL::CompRootHandler; |
use strict; |
use Apache::Constants qw(:common); |
use Apache::File; |
use DirHandle (); |
sub handler { |
my $r = shift; |
# verifico se il file è presente nei percorsi definiti nell'ordine |
my @MasonCompRoot = $r->dir_config->get('MasonCompRoot'); |
foreach my $root (@MasonCompRoot){ |
my($name, $dir) = split /\s*=>\s*/, $root, 2; |
(defined $name) or die "Configurazione inaspettatata di MasonCompRoot '$root'\n"; |
if(-e $dir.$r->uri){ |
# se esiste il file nel percorso lo seleziono per il download |
$r->filename($dir.$r->uri); |
last; |
} |
} |
my $fh = Apache::File->new($r->filename) or return FORBIDDEN; |
$r->send_fd($fh); |
close $fh; |
return OK; |
} |
1; |
__END__ |
/tags/2.0/lib/MasonSQL/CompRootHandler2.pm |
---|
0,0 → 1,34 |
# Usato in pache 2.0 e 2.2 |
# |
package MasonSQL::CompRootHandler2; |
use strict; |
### Per Apache2spostati nel file di configurazione di Apache |
#use Apache::Constants qw(:common); |
#use Apache::File; |
#use DirHandle (); |
### Per Apache2 |
use Apache2::Const qw(FORBIDDEN OK); |
sub handler { |
my $r = shift; |
# verifico se il file è presente nei percorsi definiti nell'ordine |
my @MasonCompRoot = $r->dir_config->get('MasonCompRoot'); |
foreach my $root (@MasonCompRoot){ |
my($name, $dir) = split /\s*=>\s*/, $root, 2; |
(defined $name) or die "Configurazione inaspettatata di MasonCompRoot '$root'\n"; |
if(-e $dir.$r->uri){ |
# se esiste il file nel percorso lo seleziono per il download |
$r->filename($dir.$r->uri); |
$r->sendfile($dir.$r->uri); |
return OK; |
} |
} |
return FORBIDDEN; |
} |
1; |
__END__ |
/tags/2.0/lib/MasonSQL/JSLogger.pm |
---|
0,0 → 1,232 |
package MasonSQL::JSLogger; |
use Data::Dumper; |
use strict; |
use warnings; |
use vars qw(%LEVELS %VAL2LEVEL); |
no strict qw(refs); |
use constant ALL_INT => 0; |
use constant DEBUG_INT => 10000; |
use constant INFO_INT => 20000; |
use constant WARN_INT => 30000; |
use constant ERROR_INT => 40000; |
use constant FATAL_INT => 50000; |
use constant OFF_INT => (2 ** 31) - 1; |
sub new{ |
my $class = shift; |
my $current_level = shift; |
$current_level = OFF_INT unless defined $current_level; |
my $self = {'level' => $current_level, 'log_sub' => \&_log_level, 'code' => {}, 'to_dump' => ['init', 'log'], 'join_separator' => ''}; |
bless $self, $class; |
return $self; |
} |
sub to_dump{ |
my $self = shift; |
my $to_dump = shift; |
unless (defined $to_dump){ |
return $self->{'to_dump'}; |
}else{ |
$self->{'to_dump'} = $to_dump; |
} |
} |
sub join_separator{ |
my $self = shift; |
my $separator = shift; |
unless (defined $separator){ |
return $self->{'join_separator'}; |
}else{ |
$self->{'join_separator'} = $separator; |
} |
} |
sub log_sub{ |
my $self = shift; |
my $log_sub = shift; |
if (defined $log_sub){ |
$self->{'log_sub'} = $log_sub; |
}else{ |
return $self->{'log_sub'}; |
} |
} |
sub add_level{ |
my $level = shift || return; |
my $value = shift; |
return unless defined $value; |
return if defined $LEVELS{$level} or defined $VAL2LEVEL{$value}; |
$level = uc $level; |
$LEVELS{$level} = $value; |
$VAL2LEVEL{$value} = $level; |
*{__PACKAGE__ . "::$level"} = $value; |
_create_log_level_methods($level); |
} |
sub delete_level{ |
my $level = shift; |
return unless defined $level; |
return unless is_valid($level); |
return if is_predefined($level); |
$level = lc (($level =~ m/^[0-9]+$/o) ? $VAL2LEVEL{$level} : $level); |
my $uLevel = uc $level; |
delete $VAL2LEVEL{$LEVELS{$uLevel}}; |
delete $LEVELS{$uLevel}; |
delete ${__PACKAGE__ . "::"}{"$uLevel"}; |
delete ${__PACKAGE__ . "::"}{"$level"}; |
delete ${__PACKAGE__ . "::"}{"is_$level"}; |
} |
add_level('DEBUG', DEBUG_INT); |
add_level('ALL', ALL_INT); |
add_level('INFO', INFO_INT); |
add_level('WARN', WARN_INT); |
add_level('ERROR', ERROR_INT); |
add_level('FATAL', FATAL_INT); |
add_level('OFF', OFF_INT); |
sub _create_log_level_methods{ |
my $level = shift || return; |
my $uLevel = uc $level; |
$level = lc $level; |
*{__PACKAGE__ . "::$level"} = sub { |
my $self = shift; |
$self->{'log_sub'}->($self, $level, @_) if defined $LEVELS{uc $level}; |
}; |
*{__PACKAGE__ . "::is_$level"} = sub { |
$_[0]->_is_level($uLevel) if defined $LEVELS{$uLevel}; |
}; |
} |
sub is_predefined{ |
my $level = shift; |
return unless defined $level; |
return unless is_valid($level); |
$level = ($level =~ m/^[0-9]+$/o) ? $VAL2LEVEL{$level} : uc $level; |
return $level =~ m/^ALL|DEBUG|INFO|WARN|ERROR|FATAL|OFF$/o; |
} |
sub is_valid{ |
my $level = shift; |
return unless defined $level; |
$level = uc $level; |
if ($level =~ m/[A-Z]+/o){ |
return defined $LEVELS{$level}; |
}else{ |
return defined $VAL2LEVEL{$level}; |
} |
} |
sub set_code{ |
my $self = shift; |
my $codes = shift || return; |
for my $code (keys %$codes){ |
unless ($codes->{$code}){ |
delete $self->{'code'}{lc $code} if defined $self->{'code'}{lc $code}; |
}else{ |
$self->{'code'}{lc $code} = $codes->{$code}; |
} |
} |
} |
sub init_code{ |
my $self = shift; |
my $types = shift || return; |
my $toSubstitute = shift || return; |
my $uSubs = ""; |
my $sRegex; |
for my $subs (keys %{$toSubstitute}){ |
$uSubs = uc $subs; |
$sRegex = qr/#$uSubs#/; |
for my $type (@$types){ |
$type = lc $type; |
if (defined $self->{'code'}{$type}){ |
$self->{'code'}{$type} =~ s/$sRegex/$toSubstitute->{$subs}/g; |
} |
} |
} |
} |
sub dump_code{ |
my $self = shift; |
my $types = shift || return; |
my $toSubstitute = shift || return; |
my $code = ""; |
my $uSubs = ""; |
for my $type (@$types){ |
$type = lc $type; |
$code .= $self->{'code'}{$type} || ""; |
} |
return "" if $code eq ''; |
for my $subs (keys %{$toSubstitute}){ |
$uSubs = uc $subs; |
$code =~ s/#$uSubs#/$toSubstitute->{$subs}/g; |
} |
return $code; |
} |
sub _log_level{ |
my $self = shift; |
my $level = shift || return; |
if (&{__PACKAGE__ . "::is_$level"}($self)){ |
my $msgarr = [map { (ref $_ eq "CODE") ? $_->() : $_ } @_]; |
my $msg = join($self->{'join_separator'}, @$msgarr); |
$msg =~ s/</</go; |
$self->dump_code($self->{'to_dump'}, {'level' => $level, 'msg' => $msg}); |
} |
} |
sub _is_level{ |
my $self = shift; |
my $level = shift || return; |
return $self->{'level'} <= $LEVELS{$level}; |
} |
sub level{ |
my $class = shift; |
my $level = shift; |
if (defined $level){ |
$class->{'level'} = ($level =~ m/^[0-9]+$/o) ? $level : $LEVELS{uc $level} if is_valid($level); |
}else{ |
return $class->{'level'}; |
} |
} |
1; |
/tags/2.0/etc/apache2.masonsql.conf |
---|
0,0 → 1,442 |
# ---------------------------------------------------------------------- # |
# Copyright:2002-2010 Leader.IT di Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# ---------------------------------------------------------------------- # |
# Configurazione apache2 framework MasonSQL |
DocumentRoot /opt/masonsql/htdocs/ |
# Mod_perl ... |
PerlSwitches -w |
PerlOptions +GlobalRequest |
DefaultType text/html |
AddDefaultCharset UTF-8 |
# Dojo Toolkit |
PerlSetVar DojoDirUrl "/lib/dojo-release-1.13.0" |
PerlSetVar DojoDirUrlDebug "/lib/dojo-release-1.13.0-src" |
# HTML 5 |
PerlSetVar HtmlDocType '<!DOCTYPE HTML>' |
# reportman http://reportman.sourceforge.net |
# percorso per l'esecuzione del programma di creazione dei report di stampa |
PerlSetVar ReportmanDir /opt/masonsql/report |
# Connessione al database se si utilizza ADO (disabilitare ponendo ReportmanADOserver "0") |
PerlSetVar ReportmanADOserver "127.0.0.1" |
PerlSetVar ReportmanADOdatabase "masonsql" |
PerlSetVar ReportmanADOuser "report" |
PerlSetVar ReportmanADOpassword "<password>" |
# Report engine (pdf|odt|rep) |
PerlSetVar DefaultReportEngine "pdf" |
# ODT conversion engine (libreoffice|unoconv) |
PerlSetVar OdtConvEngine "libreoffice" |
# Filtro l'input dei campi testo sostituendo i caratteri UTF multibyte con ? e mostrando un avviso ("0" se disabilitato) |
PerlSetVar InputStringNoLongUTF "0" |
# Archivio per allegati |
PerlSetVar InputFilesArchive "/opt/masonsql/archive" |
# Cartella TMP |
PerlSetVar TmpDir /opt/masonsql/tmp |
# Cartella Log |
PerlSetVar LogDir /opt/masonsql/log |
# Mason ... |
<Perl> |
use CGI qw(-private_tempfiles); |
$CGI::TempFile::TMPDIRECTORY = '/opt/masonsql/tmp'; |
# set locale 'C' per i numeri |
### DA SISTEMARE!!! |
# use POSIX qw(locale_h); |
# setlocale(LC_NUMERIC, 'C'); |
### DA SISTEMARE!!! |
# enable extended warnings logged in the error_log file |
# use Carp (); $SIG{__WARN__} = \&Carp::cluck; |
# disable error log in Apache log file |
$SIG{__WARN__} = sub {}; |
# percordo di ricerca dei package |
use lib '/opt/masonsql/lib'; |
use DirHandle (); |
</Perl> |
# Configurazione cache (richiede package "libchi-perl" o modulo Perl "CHI") |
PerlSetVar MasonDataCacheApi "chi" |
PerlSetVar MasonDataCacheDefaults "{driver => 'FastMmap'}" |
# Attivo la cache del componente /frames.html |
#PerlSetVar CacheFramesExpiration "18 hours" |
#PerlSetVar CacheFramesExpiration "999 years" |
# Disabilitata |
PerlSetVar CacheFramesExpiration "0" |
PerlSetVar MasonPreamble "use utf8;" |
PerlAddVar MasonPlugins "MasonX::Plugin::UTF8" |
PerlSetVar MasonArgsMethod mod_perl |
PerlModule JSON::XS; |
PerlModule JSON; |
PerlModule ModPerl::Registry |
PerlModule Apache2::Request |
PerlModule Apache2::Status |
PerlModule Apache2::RequestRec |
PerlModule Apache2::RequestIO |
PerlModule Apache2::ServerUtil |
PerlModule Apache2::RequestUtil |
PerlModule Apache2::Log |
PerlModule Apache2::Directive |
PerlModule Apache2::Const |
PerlModule APR::Table |
PerlModule Apache2::SubRequest |
PerlModule Apache2::Upload |
PerlModule Apache2::AuthCookie |
PerlModule Apache2_4::AuthCookie |
PerlModule Apache::DBI |
PerlModule Data::Dumper |
PerlModule XML::Simple |
PerlModule Auth_AC::AuthCookieHandler |
# Inclusione di un modulo per la gestione dei messaggi conformi (il piu' possibile) allo standard. |
PerlModule MasonSQL::JSONRPCUtils |
PerlModule MasonSQL::CompRootHandler2 |
PerlModule MasonSQL::ApacheHandler |
# cartella dove posizionare i log |
PerlSetVar LogBaseDir /var/log/apache2/ |
# Livelli di Log: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL |
# Livello di log lato server |
PerlSetVar PLogLevel INFO |
# Livello di log lato client |
PerlSetVar JSLogLevel OFF |
# Layout nei log |
PerlSetVar PLogPatternLayout "[%d] - %p - %F:%L %m%n" |
PerlSetVar MasonDataDir /opt/masonsql/mason |
# Necessario per evitare che Mason preformatti l'errore ritornato in conseguenza di un die |
PerlSetVar MasonErrorMode fatal |
PerlSetVar DataBaseUrl /data |
# Default schema in database (default on PostgreSQL) |
PerlSetVar DefaultSchema public |
# Massimo numero di righe in una chiamata al recordset |
PerlSetVar MaxRetrieveRows 65536 |
# Timeout (msec) ricezione della risposta alle operazioni di gestione del recordset |
PerlSetVar GetRecordTimeout 10000 |
# Intervallo (msec) per il rinnovo della connessione al server (se 0 è disabilitato) |
PerlSetVar CheckSessionInterval 600000 |
# se 1 utilizza (key=1 or k=2 ...) altrimenti utilizza (key in (1,2,...)) |
PerlSetVar SqlWhereKeyListOr 0 |
PerlSetVar GetFormTimeout 15000 |
PerlSetVar USEpgstattuple 0 |
#PerlSetVar PrintNextValQuery "select nextval('public.report_id_seq')" |
PerlSetVar MasonAllowGlobals $DEBUG |
# database handler |
PerlAddVar MasonAllowGlobals %Session |
PerlAddVar MasonAllowGlobals $Ver |
PerlAddVar MasonAllowGlobals %Global |
PerlAddVar MasonAllowGlobals @Script_buffer |
PerlAddVar MasonAllowGlobals %SQL |
PerlModule MasonSQL::Escapes |
PerlSetVar MasonEscapeFlags "xml => \&MasonSQL::Escapes::xml_escape" |
PerlAddVar MasonEscapeFlags "js => \&MasonSQL::Escapes::js_escape" |
PerlAddVar MasonEscapeFlags "textarea => \&MasonSQL::Escapes::textarea_escape" |
PerlAddVar MasonEscapeFlags "multi => \&MasonSQL::Escapes::multi_escape" |
PerlModule Safe |
PerlModule HTML::Mason |
#PerlModule CGI |
#PerlModule Archive::Zip |
# Caratteri minimi per la password |
# N.B. dal 1°gen2004 il Codice sulla Privacy impone almeno 8 caratteri |
PerlSetVar MinPasswordChars 8 |
# Scadenza password (in giorni) |
PerlSetVar MaxPasswordDays 180 |
# Blocco accesso per inattività |
PerlSetVar MaxPasswordInactivity 180 |
# Comportamento componente String.comp nell'eliminazione dei caratteri "blank" dopo la modifica del campo |
# se il parametro non viene eslicitamente indicato. Possibili valori: Right|Left|All Se non dichiarato |
# non viene applicato |
#PerlSetVar String_TrimDefault "All" |
# Se 1 Nella navigazione delle tabelle, saltando di pagina in pagina, |
# nell'ultima verrà mostrato l'ultimo record in fondo alla tabella |
PerlSetVar LastUpAsForward 0 |
PerlSetVar Auth_AC_Path / |
# Tempo di inattività (minuti) dopo la quale la sessione scade |
PerlSetVar Auth_InactivityMax 240 |
# Scadenza dei cookie autenticazione |
PerlSetVar Auth_AC_SessionTimeout +4h |
PerlSetVar Auth_AC_Expires +4h |
# Protegge il token di autenticazione dall'essere visivile da Javascript (se il browser implementa questa limitazione) |
PerlSetVar Auth_AC_HttpOnly 1 |
# Autenticazione solo da connessione HTTPS |
PerlSetVar Auth_AC_Secure 1 |
PerlSetVar Auth_AC_LoginScript /AuthCookieLoginForm.html |
PerlAddAuthzProvider dwarf Auth_AC::AuthCookieHandler->dwarf |
PerlAddAuthzProvider myuser Auth_AC::AuthCookieHandler->authz_handler |
PerlSetVar AuthCookieDebug 0 |
PerlSetVar Auth_AC_bad_credentials_message "L'accesso a questo sito è stato negato. (bad_credentials).<br>Si prega di inserire nome e password:" |
PerlSetVar Auth_AC_no_cookie_message "Si prega di inserire nome e password:" |
# se 1 forza sempre la login |
PerlSetVar Auth_AC_force_login 0 |
# Tempo di attesa (in msec) prima di mostrare il tooltip nei widget |
PerlSetVar TooltipDelay 800 |
PerlSetVar CopyrightMessage "Copyright (©) Guido Brugnara <gdo@leader.it><br>License: Affero G.P.L. rel.1" |
PerlSetVar ApplicationName masonsql |
PerlSetVar ApplicationTitle "MasonSql framework" |
# nome dell'agent che verrà mostrato al server SMTP |
PerlSetVar MailXMailer "MasonSql" |
# E-mail mittente di sistema |
PerlSetVar MailFrom "no-reply@masonsql" |
# server di destinazione della posta |
PerlSetVar MailSmtpServer "localhost" |
# Porta del servizio SMTP da contattare |
PerlSetVar MailPortServer "25" |
# Numero massimo di mail trasmesse per collegamento al server SMTP |
PerlSetVar MailMax4Connection "100" |
# Mantiene la connessione aperta quando trasmette più messaggi |
PerlSetVar MailSmtpKeepConnection "0" |
# DEBUG: se configurata, forza tutte le mail generate dal framework verso questo indirizzo |
# PerlSetVar MailForceTo "debug@mydomain" |
# Tipo di autenticazione (PLAIN, ...) |
PerlSetVar AuthType "PLAIN" |
# Utente per autenticazione SMTP |
PerlSetVar MailAuthid "userauth@dominio" |
# Password autenticazione SMTP |
PerlSetVar MailAuthpwd "*********" |
# nome dell'agent che verrà mostrato al server HTTP del servizio di invio SMS |
PerlSetVar SMSagent "MasonSql" |
# SMSPlatform: piattaforma che identifica il protocollo usato dal fornitore del servizio SMS |
# attualmente sono supportati "SMStrend.it" e "Comilio.it" |
PerlSetVar SMSPlatform "0" |
# SMSfrom: massimo 16 caratteri numerici per un numero di telefono in formato internazionale oppure 11 caratteri |
# alfanumerici per una stringa di testo (Es: "+123456789012345" oppure "Azienda_Spa"). |
PerlSetVar SMSfrom "MasonSql" |
# Lunghezza massima del messaggio (con 160 si ha la trasmissione di un solo SMS, altrimenti un SMS ogni 153 caratteri) |
PerlSetVar SMSmaxLength 160 |
# SMSurl: indirizzo del server fornitore del servizio per l'invio di messaggi SMS |
PerlSetVar SMSurl "https://www.smstrend.net/Trend" |
# Prefisso internazionale da aggiungere ai n° di cellulare che ne fossero sprovvisti (codice del paese a due cifre) |
PerlSetVar SMSNationPrefix "39" |
# Utente dell'abbonamento al servizio |
PerlSetVar SMSAuthid "myuserauth@dominio" |
# Passord di accesso al servizio |
PerlSetVar SMSAuthpwd "********" |
# Abilita(1)/Disabilita(0) l'invio di SMS quando il mittente corrisponde al destinatario |
PerlSetVar SMSsendToHimself "0" |
# Caricamento modulo che gestisce il logger JS. |
PerlModule MasonSQL::JSLogger; |
PerlAddVar MasonAllowGlobals $PLogger |
PerlAddVar MasonAllowGlobals $JSLogger |
PerlModule SQL::Dialects::ANSI |
# Widget Files.comp |
# Nome della cartella su disco del cestino (senza il punto iniziale) |
# Attenzione: vanno modificati i nomi delle cartelle cestino esistenti! |
PerlSetVar Files_Trash_dir "Trash" |
# Nome del cestino da mostrare nel widget |
PerlSetVar Files_Trash_name "Cestino" |
################################################################################################ |
### Nuove informazioni di registrazione utente |
################################################################################################ |
# Registrazione Utente abilitato / disabilitato |
# [enable] : Attivare la funzione di registrazione di auto |
# [disable] : Disattivare la funzione di registrazione di auto |
PerlSetVar UserRegistration "enable" |
# reimpostazione della password di abilitazione / disabilitazione. |
# [enable] : Attivare la funzione di reimpostazione password |
# [disable] : funzione di reset della password Disabilitare |
PerlSetVar UserPasswordReset "enable" |
# Utente tipo di registrazione |
# [syslogin] : Molteplici login ID univoco può essere associato a singola e-mail id |
# [email] : Unico id-mail verrà utilizzato come ID di accesso |
PerlSetVar LoginType "syslogin" |
# Registrazione Utente nome del gruppo predefinito |
# [Guest] : il nome del gruppo valido verrà assegnata al nuovo utente registrato |
# [Admins] : il nome del gruppo valido verrà assegnata al nuovo utente registrato |
PerlSetVar NewUserRegisterGroup "Guest" |
# Tipo di notifica per l'utente |
# [email] : email di notifica verrà inviata se è stato dato valido e-mail id. |
# [sms] : sms di notifica verrà inviata se è stato dato sms valido. |
PerlSetVar UserRegTypeMessage "email" |
# Utente registrato modello di password casuali |
# c Qualsiasi carattere minuscolo Latina [a-z] |
# C Qualsiasi carattere maiuscolo latino [A-Z] |
# n Qualsiasi cifre [0-9] |
# ! Un carattere di punteggiatura [~`!@$%^&*()-_+={}[]|\:;"'.<>?/#,] |
# . Qualsiasi dei precedenti |
# s Un personaggio "sale" [A-Za-z0-9./] |
# b Qualsiasi dati binari |
PerlSetVar PasswordRandPattern "Cccsssnn" |
# Il tempo massimo per la nuova conferma dell'utente in giorni |
# [days] number of days in digits (ie 7, 15, 30, 60) |
PerlSetVar MaxTimeToConfirmUserRegistration 7 |
# reCaptcha Google chiavi API registrati |
# 1. registrare il tuo dominio per le chiavi API reCAPTCHA (https://www.google.com/recaptcha/admin) |
# 2. Impostare la chiave del sito e la chiave segreta sotto |
PerlSetVar ReCaptchaAPISecretKey 'YOUR-REGISTERED-SECRET-KEY' |
PerlSetVar ReCaptchaAPISiteKey 'YOUR-REGISTERED-SITE-KEY' |
# List of active optional fields (fields defined in table public.anagrafiche). |
# Available fields: cell_sms codice_fiscale descrizione indirizzo provincia citta tele1 tele2 |
# PerlSetVar UserRegOptionalFields 'descrizione indirizzo' |
# |
################################################################################################ |
<Directory "/srv/www/icons"> |
Options -Indexes -MultiViews |
Require all granted |
SetHandler default-handler |
</Directory> |
# autenticazione Auth_AC::AuthCookieHandler |
<Location /AuthCookieLoginForm.html > |
Require all granted |
Satisfy Any |
</Location> |
<Location /AuthCookieLoginSubmit > |
AuthType Auth_AC::AuthCookieHandler |
AuthName Auth_AC_ |
SetHandler perl-script |
Require all granted |
PerlResponseHandler Auth_AC::AuthCookieHandler->login |
</Location> |
# link accessibili senza autorizzazione |
<LocationMatch ^(/AuthCookieLoginSubmit|/UpiPrinterServer.txt|/css/|/favicon.ico|/img/icon.ico|/UserRegistration|/UserPasswordResetForm)> |
Require all granted |
Satisfy Any |
</LocationMatch> |
# link accessibili con autenticazione Auth_AC::AuthCookieHandler |
<LocationMatch "^/" > |
DirectoryIndex index.html |
Options +Indexes -MultiViews |
AuthType Auth_AC::AuthCookieHandler |
AuthName Auth_AC_ |
PerlAuthenHandler Auth_AC::AuthCookieHandler->authenticate |
Require valid-user |
</LocationMatch> |
# link accessibili con autenticazione basic |
<LocationMatch "^/dbms/{0,1}" > |
PerlAuthenHandler Auth_AC::AuthBasicHandler |
AuthType basic |
AuthName "MasonSQL Authentication" |
Require valid-user |
SetOutputFilter DEFLATE |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
# link interfaccia CRUD (rest) |
<LocationMatch "^/rest/{0,1}" > |
SetOutputFilter DEFLATE |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
# GDO TEST BEGIN |
<LocationMatch "^/test/dojo/test_dojo_tree_data/" > |
Options Indexes |
DirectoryIndex dhandler |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
# GDO TEST END |
<Location /> |
Options -Indexes -MultiViews |
</Location> |
<LocationMatch "(\.ico|\.gif|\.jpg|\.png|\.jpeg)$" > |
SetHandler perl-script |
PerlHandler MasonSQL::CompRootHandler2 |
</LocationMatch> |
<LocationMatch "(\.mql|\.xml|\.xsd|\.mason|\.html|\.txt|\.css|\.js|\.xls)$" > |
SetOutputFilter DEFLATE |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
<LocationMatch "(\.m7m|\.pdf|\.zip)$" > |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
<LocationMatch "(\.mas|\.pm|handler|\.comp|^CVS|\.svn|\.META|~)$" > |
SetHandler perl-script |
PerlHandler "sub { use Apache2::Const qw(HTTP_NOT_FOUND); return Apache2::Const::HTTP_NOT_FOUND }" |
</LocationMatch> |
<LocationMatch "^/archive/" > |
Options Indexes |
DirectoryIndex dhandler |
SetHandler perl-script |
PerlHandler MasonSQL::ApacheHandler |
</LocationMatch> |
# escludo la cartella del componente dall'essere interpretata da Mason |
<Location /lib/FCKeditor > |
SetHandler default-handler |
Options Indexes MultiViews |
</Location> |
# escludo le cartelle di Dojo Toolkit dall'essere interpretate da Mason e dalla necessità dell'utente |
<LocationMatch "^/lib/dojo-release-"> |
SetHandler default-handler |
Options Indexes MultiViews |
Require all granted |
Satisfy Any |
</LocationMatch> |
# escludo le cartelle di firebug-lite dall'essere interpretate da Mason |
<LocationMatch "^/lib/firebug-lite"> |
SetHandler default-handler |
Options Indexes MultiViews |
</LocationMatch> |
<LocationMatch ^(/logo.png)> |
Require all granted |
Satisfy Any |
</LocationMatch> |
# ... END Mason. |
<Files ~ "^\.ht"> |
Require all denied |
</Files> |
# End. |
/tags/2.0/etc/unoconvd |
---|
0,0 → 1,46 |
#!/bin/sh |
### BEGIN INIT INFO |
# Provides: unoconvd |
# Required-Start: $network |
# Required-Stop: $network |
# Default-Start: 2 3 5 |
# Default-Stop: |
# Description: unoconvd - Converting documents to PDF by unoconv |
### END INIT INFO |
set -e |
. /lib/lsb/init-functions |
NAME="unoconv" |
DAEMON="/usr/bin/unoconv" |
DAEMON_ARGS="--listener" |
PIDFILE=/var/run/$NAME.pid |
USER="www-data" |
GROUP="www-data" |
test -x $DAEMON || exit 0 |
case "$1" in |
start) |
log_daemon_msg "Starting $NAME server" $NAME |
start-stop-daemon --start --quiet --chuid $USER:$GROUP --background --exec $DAEMON --name $NAME -- $DAEMON_ARGS |
pgrep -f 'python[1-9]* /usr/bin/unoconv --listener' >$PIDFILE |
;; |
stop) |
log_daemon_msg "Stopping $NAME server" $NAME |
start-stop-daemon --stop --quiet --user $USER --group $GROUP --pidfile $PIDFILE |
;; |
status) |
status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? |
;; |
restart) |
$0 stop |
sleep 1 |
$0 start |
sleep 1 |
;; |
*) |
log_success_msg "Usage: $0 {start|stop|restart|status}" |
exit 1 |
;; |
esac |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/bin/cronjobs |
---|
0,0 → 1,586 |
#!/usr/bin/perl |
# ---------------------------------------------------------------------- # |
# Copyright: (C) 2012 Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata,41 |
# 38123 T R E N T O (ITALY) |
# Authors: Guido Brugnara <gdo@leader.it> |
# |
# $Revision: $ info@leader.it |
# |
# Dual Licence: |
# Affero G.P.L. Version 1, 03-2002 http://www.affero.org/oagpl.html |
# Comercial - call for details <gdo@leader.it> |
# ---------------------------------------------------------------------- # |
# eseguito periodicamente da cron (vedi file /etc/crontab) |
# |
# * * * * * www-data /opt/masonsql/bin/cronjobs <file di configurazione> |
# |
# provvede all'invio dei messaggi email e sms in coda |
use strict; |
use Sys::RunAlone silent => 1; # mi assicuro che un solo script sia in esecuzione |
use utf8; |
use Encode; |
use Carp; |
binmode STDOUT, ':utf8'; |
use Data::Dumper; |
use DBI; |
use POSIX (); |
use File::MimeInfo::Magic; |
use IO::Scalar; |
use lib '/opt/masonsql/lib'; |
# global variables |
# [$execTime] timestamp quando eseguire il processo in formato HHMM vale a dire (0005, 0945, 1600 è pari a 12:05, 09:45, 16:00 PM) |
my $execTime = ['0005']; |
# file di configurazione dell'applicazione |
my $file_conf = $ARGV[0] || die "Manca il parametro del nome del file di configurazione\n"; |
sub read_config($){ |
my $file_conf = shift; |
# lettura dei parametri di configurazione |
open my $file_params, "<$file_conf"; |
my %params; |
while(<$file_params>){ |
chomp; |
if(m/^\s*Include\s+(.*)\s*$/){ |
my $file = $1; |
if($file =~ m/^"(.*)"$/){ |
$file = $1; |
$file =~ s/""/"/gs; |
} |
%params = (%params, &read_config($file)); |
}elsif(m/^\s*PerlSetVar\s+([\w_]+)\s+(.*)\s*$/){ |
my $name = $1; |
my $str = $2; |
if($str =~ m/^"(.*)"$/){ |
$str = $1; |
$str =~ s/""/"/gs; |
} |
$params{$name} = $str |
} |
} |
close $file_params; |
return %params; |
} |
my %params = read_config($file_conf); |
use MasonSQL::SMS; |
my $SMS = new MasonSQL::SMS( max_length => $params{SMSmaxLength} ); |
# autenticazione DBI |
# 'DBIconnect' => 'dbi:Pg:dbname=DBMS;user=USER;password=******', |
if($params{DBIconnect} !~ m/(.*);\s*user=(.*);\s*password=(.*)$/){ |
die "Param DBIconnect malformed\n"; |
} |
my $dbh = DBI->connect($1, $2, $3) |
or die "Cannot connect to database $1\n$DBI::errstr\n"; |
$dbh->{pg_enable_utf8} = 1; |
$dbh->{RaiseError} = 1; |
$dbh->{ShowErrorStatement} = 1; |
# necessario per i database e client >=7.3 e successivi in quanto si utilizzano "prepare" di query multiple |
$dbh->{'pg_server_prepare'} = 0; |
$dbh->do(q{ |
set client_encoding TO 'UTF-8'; |
set DateStyle to 'SQL, EUROPEAN'; |
}); |
$dbh->{AutoCommit} = 1; |
if($params{MailSmtpServer}){ |
#use Net::SMTP; |
{ # new Nov 17, 2016 - rel 0.903 is DEPRECATED! |
no warnings qw(deprecated); |
use Mail::Sender; |
} |
$Mail::Sender::NO_X_MAILER = 1; |
my $countMail = 0; |
my $sender; |
my $paramsSender = { |
#debug => \*STDERR, |
#debug_level => 4, |
client => $params{Auth_AC_Domain} || `hostname -f`, |
from => encode('MIME-Header', $params{MailFrom}), |
smtp => $params{MailSmtpServer}, |
port => $params{MailPortServer}, |
auth => $params{AuthType} eq 'NONE' ? undef : uc $params{AuthType}, |
authid => $params{MailAuthid}, |
authpwd => $params{MailAuthpwd}, |
keepconnection => $params{MailSmtpKeepConnection} || 0, |
on_errors => 'code' |
}; |
# aggiornamento messaggi di posta elettronica elaborati |
my $sth_email_message = $dbh->prepare(q{ |
update public.messages_users |
set email_result = $1, |
log = CASE WHEN log is null THEN 'MAIL ' || $1 ELSE log || E'\nMAIL ' || $1 END |
where id = $2 |
}); |
# verifico se ci sono messaggi da inviare per posta elettronica |
my $sth_messages = $dbh->prepare(q{ |
select |
messages.id as messages_id, |
messages_users.id, |
messages.subject, |
CASE |
WHEN messages_users.user_message is not null THEN messages_users.user_message |
WHEN messages_users.user_short_message is not null THEN messages_users.user_short_message |
WHEN messages.message is not null THEN messages.message |
ELSE messages.short_message |
END as body, |
anagrafiche.nome as nome_to, |
anagrafiche.cognome as cognome_to, |
anagrafiche.email as email_to, |
coalesce(owner.nome, 'Gestore del sistema') as nome_from, |
owner.cognome as cognome_from, |
owner.email as email_from |
from public.messages_users |
inner join public.messages on messages.id = messages_users.id_messages |
inner join public.anagrafiche on anagrafiche.id = messages_users.id_anagrafiche |
left join public.anagrafiche owner on owner.id = messages.owner |
where messages.transmission_time is not null |
and messages.email |
and messages_users.notification_time is null |
and ( messages_users.email_result is null |
or messages_users.email_result ~* E'ERR - [^\\d]*4\\d\\d[^\\d^\\w]' |
) |
order by messages_users.id; |
}); |
$sth_messages->execute; |
while(my $message = $sth_messages->fetchrow_hashref){ |
#DEBUG print Dumper($message); |
my $email_result; |
if($message->{'email_to'}){ |
if($params{MailMax4Connection} && $countMail >= $params{MailMax4Connection}){ |
$countMail = 0; |
# chiudo la connessione al server SMTP |
$sender->Close(1); |
$sender = undef; |
} |
if(!ref $sender){ |
$sender = new Mail::Sender($paramsSender); |
if(!ref $sender){ |
die 'ERROR TO CREATE MAIL CONNECTION: '.$Mail::Sender::Error,"\n"; |
} |
} |
my $ContentType = mimetype(new IO::Scalar \$message->{'body'}); |
my $mailto = $params{MailForceTo} |
? encode('MIME-Header', qq|"$message->{'nome_to'} $message->{'cognome_to'} force to"|)." <$params{MailForceTo}>" |
: encode('MIME-Header', qq|"$message->{'nome_to'} $message->{'cognome_to'}"|)." <$message->{'email_to'}>"; |
$sender->Body({ |
charset => 'UTF-8', |
encoding => '8BIT', |
ctype => $ContentType |
}); |
my $From = encode('MIME-Header', qq|"Per conto di $message->{'nome_from'} $message->{'cognome_from'}"|)." <$params{MailFrom}>"; |
my %headers = ( |
'Sender' => $From, |
'X-Mailer' => "$params{MailXMailer} $message->{'messages_id'}-$message->{'id'}" |
); |
if($message->{'email_from'}){ |
$headers{'Reply-To'} = encode('MIME-Header', qq|"$message->{'nome_from'} $message->{'cognome_from'}"|)." <$message->{'email_from'}>"; |
} |
$sender->MailMsg({ |
subject => encode('MIME-Header', $params{MailForceTo} ? $message->{'id'}.' '.$message->{'subject'} : $message->{'subject'}), |
from => $From, |
to => $mailto, |
msg => encode('utf8', $message->{'body'}), |
headers => \%headers |
}); |
$email_result = $sender->{'error'} ? "ERR - $sender->{'error_msg'} ($sender->{'error'})" : 'OK - Inviato'; |
$sender->ClearErrors(); |
$countMail++; |
}else{ |
$email_result = 'KO - No mail address'; |
} |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
my $datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
#DEBUG die "$countMail++: $email_result il $datetime\n"; |
$sth_email_message->execute("$email_result il $datetime", $message->{'id'}); |
} # while message di posta elettronica |
if($sender){ |
$sender->Close(1); |
$sender = undef; |
} |
} # if($params{MailSmtpServer}){ |
#--------------------------------------------------------------------------- SMS |
if($params{SMSPlatform}){ |
use JSON; |
use LWP::UserAgent; |
use HTTP::Request; |
use HTTP::Request::Common; |
use HTTP::Request::JSON; |
my $SMSagent = LWP::UserAgent->new( |
agent => $params{SMSagent} |
); |
$SMSagent->timeout($params{SMStimeout} || 10); |
# query aggiornamento stato |
my $sth_sms_message = $dbh->prepare(q{ |
update public.messages_users |
set sms_result = $1, |
log = CASE WHEN log IS NULL THEN 'SMS ' || $1 ELSE log || E'\nSMS ' || $1 END, |
sms_cost = CASE WHEN $2::smallint IS NULL THEN sms_cost WHEN $2::smallint = 0 THEN NULL ELSE $2::smallint END |
where id = $3 |
}); |
# pulisce un documento HTML dai tab |
sub clean_html($){ |
$_ = shift; |
s/\n+/ /gs; |
s/\<\/[\w+]+\>/; /isg; |
s/\<[\w+]+\>/ /isg; |
s/\s+/ /gs; |
s/\s;/;/gs; |
s/^\s+|;*\s*$//gs; |
s/;+/;/gs; |
return $_; |
} |
#---------------------------------- SMS STATUS |
my $sth_messages = $dbh->prepare(q{ |
select |
messages_users.id, |
sms_result |
from public.messages_users |
inner join public.messages on messages.id = messages_users.id_messages |
where messages.sms and substr(sms_result::text, 1, 3) = 'SMS' -- use index messages_users_sms_result |
order by messages_users.id; |
}); |
$sth_messages->execute; |
while(my $message = $sth_messages->fetchrow_hashref){ |
my $message_id = $message->{'id'}; |
if(lc $params{SMSPlatform} eq 'comilio.it'){ |
my($sms, $old_status, $old_date, $old_time, $sms_id, $old_description) = split /\s/, $message->{'sms_result'}, 6; |
# get message status |
# eg. SMS|TOSERVER|2018-01-31|12:00:00|F9BC589E9F2140F1BFA34D825C962F40|messaggio inviato al server |
my $http_req = HTTP::Request->new(GET => $params{SMSurl}."/message/$sms_id"); |
$http_req->authorization_basic($params{SMSAuthid}, $params{SMSAuthpwd}); |
my $response = $SMSagent->request($http_req); |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
my $datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
my $json_response = eval { from_json $response->content }; |
if($response->is_error){ |
if($json_response && exists $json_response->{error}){ |
$sth_sms_message->execute("ERR - ERROR $datetime $sms_id $json_response->{error}", undef, $message_id); |
}else{ |
$sth_sms_message->execute("ERR - HTTP $datetime $sms_id (".$response->code.') '.clean_html($response->error_as_HTML), undef, $message_id); |
} |
}else{ |
if(!defined $json_response || !defined $json_response->[0]->{status}){ |
$sth_sms_message->execute("ERR - JSON $datetime $sms_id (".$response->content.') ', undef, $message_id); |
}else{ |
my $status = $json_response->[0]->{status}; |
if(ref($json_response) eq 'ARRAY' and length(@{$json_response}) == 0){ |
$status = 'Deleted'; |
} |
if($json_response->[0]->{deliver_timestamp}){ |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime $json_response->[0]->{deliver_timestamp}; |
$datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
} |
if($status eq 'Deleted'){ |
$sth_sms_message->execute("ERR - DELETED $datetime $sms_id messaggio non presente nel database del gestore", undef, $message_id); |
}elsif($status eq 'Scheduled'){ |
$sth_sms_message->execute("SMS SCHEDULED $datetime $sms_id messaggio pianificato per l'invio, non ancora inviato", undef, $message_id); |
}elsif($status eq 'Enqueued'){ |
$sth_sms_message->execute("SMS ENQUEUED $datetime $sms_id messaggio in attesa di invio", undef, $message_id); |
}elsif($status eq 'Sent'){ |
$sth_sms_message->execute("OK - SENT $datetime $sms_id messaggio inviato senza notifica di ricezione", undef, $message_id); |
}elsif($status eq 'Delivering'){ |
$sth_sms_message->execute("SMS DELIVERING $datetime $sms_id messaggio inviato in attesa di notifica di ricezione", undef, $message_id); |
}elsif($status eq 'Delivered'){ |
$sth_sms_message->execute("OK - DELIVERED $datetime $sms_id messaggio inviato e ricezione notificata", undef, $message_id); |
}elsif($status eq 'ErrorGeneric'){ |
$sth_sms_message->execute("ERR - GENERIC $datetime $sms_id errore di invio", undef, $message_id); |
}elsif($status eq 'ErrorPrefix'){ |
$sth_sms_message->execute("ERR - PREFIX $datetime $sms_id errore nel prefisso del destinatario", undef, $message_id); |
}elsif($status eq 'ErrorRecipient'){ |
$sth_sms_message->execute("ERR - RECIPIENT $datetime $sms_id errore nel numero del destinatario", undef, $message_id); |
}elsif($status eq 'FloodRecipient'){ |
$sth_sms_message->execute("ERR - FLOOD_RECIPIENT $datetime $sms_id non inviato per flooding ai danni di un destinatario", undef, $message_id); |
}elsif($status eq 'FloodUser'){ |
$sth_sms_message->execute("ERR - FLOOD_USER $datetime $sms_id non inviato per flooding causato dall'utente Comilio", undef, $message_id); |
}elsif($status eq 'Lost'){ |
$sth_sms_message->execute("ERR - LOST $datetime $sms_id nessuna informazione ricevuta dalla rete dopo 48h", undef, $message_id); |
}elsif($status eq 'NoInfo'){ |
$sth_sms_message->execute("ERR - NOINFO $datetime $sms_id nessuna informazione sullo status del messaggio", undef, $message_id); |
}else{ |
$sth_sms_message->execute("ERR - ??? $datetime $sms_id stato '$status' sconosciuto", undef, $message_id); |
} |
} |
} |
}elsif(lc $params{SMSPlatform} eq 'smstrend.it'){ |
my($sms, $old_status, $old_date, $old_time, $old_description) = split /\s/, $message->{'sms_result'}, 4; |
# compatibilità precedente versione, priva del parametro old_date |
if($old_date !~ m/^\d+/){ |
$old_description = "$old_date $old_time $old_description"; |
$old_date = undef; |
$old_time = undef; |
} |
my $response = $SMSagent->post($params{SMSurl}.'/SMSSTATUS', { |
'login' => $params{SMSAuthid}, |
'password' => $params{SMSAuthpwd}, |
'order_id' => 'T'.$message_id |
}); |
# viene restituito: |
# OK; - se order_id non presente (ad esempio dopo 30 gg) |
# OK;%2B393487284422|WAIT4DLVR|; |
# OK;%2B393487284422|DLVRD|20120708085046; |
# OK;%2B393334365401|DLVRD|20180411141105;%2B393334365401|DLVRD|20180411211910; |
# |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
my $datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
if($response->is_error){ |
$sth_sms_message->execute("ERR - HTTP $datetime (".$response->code.') '.clean_html($response->error_as_HTML), undef, $message_id); |
}else{ |
# Valuto soltanto il primo messaggio |
my @params = split /;/, $response->content; #/ |
my $ok = shift @params; |
if($ok eq 'OK'){ |
my $smsparams = shift @params; |
if(!$smsparams){ |
# order_id non più presente (ad esempio dopo 30 gg) |
$sth_sms_message->execute("KO - SMS ERASE $datetime eliminato [$old_status $old_date $old_time $old_description]", undef, $message_id); |
}else{ |
my($recipient_number, $status, $delivery_date) = split /\|/, $smsparams; |
if($delivery_date =~ m/^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/){ |
$datetime = "$3/$2/$1 $4:$5:$6"; |
} |
my $old_datetime = "$old_date $old_time"; |
if($status eq 'SCHEDULED'){ |
$sth_sms_message->execute("SMS SCHEDULED $datetime messaggio posticipato, non ancora inviato", undef, $message_id); |
}elsif($status eq 'SENT'){ |
$sth_sms_message->execute("SMS SENT $datetime messaggio inviato, non attende delivery", undef, $message_id); |
}elsif($status eq 'DLVRD'){ |
$sth_sms_message->execute("OK - SMS $datetime consegnato", undef, $message_id); |
}elsif($status eq 'ERROR'){ |
$sth_sms_message->execute("SMS ERROR $datetime errore nella consegna dell'SMS (Es. numero non esistente)", undef, $message_id); |
}elsif($status eq 'TIMEOUT'){ |
$sth_sms_message->execute("KO - SMS TIMEOUT $datetime l'operatore non ha fornito informazioni sull'SMS entro 48 ore", undef, $message_id); |
}elsif($status eq 'TOOM4NUM'){ |
$sth_sms_message->execute("KO - SMS TOOM4NUM $datetime troppi SMS per lo stesso destinatario nelle ultime 24 ore", undef, $message_id); |
}elsif($status eq 'TOOM4USER'){ |
$sth_sms_message->execute("KO - SMS TOOM4USER $datetime troppi SMS inviati dall'utente nelle ultime 24 ore", undef, $message_id); |
}elsif($status eq 'UNKNPFX'){ |
$sth_sms_message->execute("KO - SMS UNKNPFX $datetime prefisso SMS non valido o sconosciuto", undef, $message_id); |
}elsif($status eq 'UNKNRCPT'){ |
$sth_sms_message->execute("KO - SMS UNKNRCPT $datetime numero di telefono del destinatario non valido o sconosciuto", undef, $message_id); |
}elsif($status eq 'WAIT4DLVR'){ |
$sth_sms_message->execute("SMS WAIT4DLVR $datetime messaggio inviato, in attesa di delivery", undef, $message_id); |
}elsif($status eq 'WAITING'){ |
$sth_sms_message->execute("SMS WAITING $datetime messaggio in attesa, non ancora inviato", undef, $message_id); |
}elsif($status eq 'UNKNOWN'){ |
$sth_sms_message->execute("SMS UNKNOWN $datetime stato sconosciuto", undef, $message_id); |
}else{ |
$sth_sms_message->execute("ERR - SMS ??? $datetime ".$response->content, undef, $message_id); |
} |
} |
}else{ |
$sth_sms_message->execute("ERR - SMS ??? $datetime ".$response->content, undef, $message_id); |
} |
} |
}else{ |
$sth_sms_message->execute('KO - No SMS platform '.$params{SMSPlatform}, undef, $message_id); |
} |
} |
#---------------------------------- SMS SEND |
# verifico se ci sono messaggi SMS da inviare |
my $sth_messages = $dbh->prepare(q{ |
select |
messages_users.id, |
messages.subject, |
CASE |
WHEN messages_users.user_short_message is not null THEN messages_users.user_short_message |
WHEN messages.short_message is not null THEN messages.short_message |
WHEN messages_users.user_message is not null THEN messages_users.user_message |
ELSE messages.message |
END as body, |
anagrafiche.nome as nome_to, |
anagrafiche.cognome as cognome_to, |
anagrafiche.cell_sms as sms_to, |
owner.nome as nome_from, |
owner.cognome as cognome_from, |
owner.cell_sms as sms_from |
from public.messages_users |
inner join public.messages on messages.id = messages_users.id_messages |
inner join public.anagrafiche on anagrafiche.id = messages_users.id_anagrafiche |
inner join public.anagrafiche owner on owner.id = messages.owner |
where messages.transmission_time is not null |
and messages.sms and messages_users.sms_result is null |
order by messages_users.id; |
}); |
$sth_messages->execute; |
while(my $message = $sth_messages->fetchrow_hashref){ |
$message->{subject} =~ s/\n+$//s; |
$message->{body} =~ s/^\n+//s; |
my $sms_message = "$message->{subject}\n\n$message->{body}"; |
$sms_message =~ s/^\n+|\n+$//sg; |
#DEBUG warn Dumper($message); |
if(!$params{SMSsendToHimself} && $message->{'id'} eq $message->{'owner_id'}){ |
# scarto l'invio di SMS a se stessi |
$sth_sms_message->execute('OK - No SMS to himself', undef, $message->{'id'}); |
next; |
} |
if(!$message->{'sms_to'}){ |
# scarto se non è definito l'indirizzo SMS del destinatario |
$sth_sms_message->execute('KO - No SMS number', undef, $message->{'id'}); |
next; |
} |
# Normalizzo i numeri cellulari |
$message->{'sms_to'} =~ s/\s|_|-|\///sg; |
if($message->{'sms_to'} =~ m/^00/ and length($message->{'sms_to'}) > 10){ |
# prefisso nel formato +NN |
$message->{'sms_to'} =~ s/^00/\+/; |
} |
if(length($message->{'sms_to'}) < 16){ |
# aggiungo il prefisso internazionale |
$message->{'sms_to'} = '+'.$params{SMSNationPrefix}.$message->{'sms_to'}; |
} |
if($message->{'sms_from'} !~ m/^\s*$/){ |
$message->{'sms_from'} =~ s/\s|_|-|\///sg; |
if($message->{'sms_from'} =~ m/^00/ and length($message->{'sms_from'}) > 10){ |
# prefisso nel formato +NN |
$message->{'sms_from'} =~ s/^00/\+/; |
} |
if(length($message->{'sms_from'}) < 16){ |
# aggiungo il prefisso internazionale |
$message->{'sms_from'} = '+'.$params{SMSNationPrefix}.$message->{'sms_from'}; |
} |
}else{ |
$message->{'sms_from'} = $params{SMSfrom}; |
} |
# normalizzazione del messaggio SMS e costo (numero di messaggi da trasmettere) |
my $sms_message = $SMS->text($sms_message); |
my $sms_cost = $SMS->cost; |
if(lc $params{SMSPlatform} eq 'comilio.it'){ |
my $http_req_json = HTTP::Request::JSON->new(POST => $params{SMSurl}.'/message'); |
$http_req_json->authorization_basic($params{SMSAuthid}, $params{SMSAuthpwd}); |
$http_req_json->json_content({ |
message_type => 'SmartPro', |
phone_numbers => [ $message->{'sms_to'} ], |
sender_string => $message->{'sms_from'}, |
text => $sms_message |
}); |
my $response = $SMSagent->request($http_req_json); |
# viene restituito un JSON { "message_id":"123xyz" } |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
my $datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
my $json_response = eval { from_json $response->content }; |
if($response->is_error){ |
if($json_response && exists $json_response->{error}){ |
$sth_sms_message->execute("ERR - REST $datetime $json_response->{error}", undef, $message->{'id'}); |
}else{ |
$sth_sms_message->execute('ERR - HTTP ('.$response->code.') '.clean_html($response->error_as_HTML), undef, $message->{'id'}); |
} |
}else{ |
if(defined $json_response->{message_id}){ |
$sth_sms_message->execute("SMS TOSERVER $datetime $json_response->{message_id} messaggio inviato al server", $sms_cost, $message->{'id'}); |
}elsif($json_response->{error}){ |
$sth_sms_message->execute("ERR - SMS TOSERVER $datetime $json_response->{error}", undef, $message->{'id'}); |
}else{ |
$sth_sms_message->execute('ERR - SMS TOSERVER $datetime ['.$response->content.']', undef, $message->{'id'}); |
} |
} |
}elsif(lc $params{SMSPlatform} eq 'smstrend.it'){ |
my $response = $SMSagent->post($params{SMSurl}.'/SENDSMS', { |
'login' => $params{SMSAuthid}, |
'password' => $params{SMSAuthpwd}, |
'message_type' => 'GP', |
'recipient' => $message->{'sms_to'}, |
'message' => $sms_message, |
'sender' => $message->{'sms_from'}, |
'order_id' => 'T'.$message->{'id'} |
}); |
# viene restituito "OK|<order_id>|1" |
# |
my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); |
my $datetime = sprintf '%02i/%02i/%04i %02i:%02i:%02i', $mday, $mon+1, $year+1900, $hour, $min, $sec; |
if($response->is_error){ |
$sth_sms_message->execute('ERR - HTTP ('.$response->code.') '.clean_html($response->error_as_HTML), undef, $message->{'id'}); |
}else{ |
my($ok, $order_id, $quant) = split /\|/, $response->content; |
if($ok eq 'OK' && $order_id eq 'T'.$message->{'id'} && $quant == 1){ |
$sth_sms_message->execute("SMS TOSERVER $datetime messaggio inviato al server", $sms_cost, $message->{'id'}); |
}else{ |
$sth_sms_message->execute('ERR - SMS TOSERVER $datetime ['.$response->content.']', undef, $message->{'id'}) |
} |
} |
}else{ |
$sth_sms_message->execute('KO - No SMS platform '.$params{SMSPlatform}, undef, $message->{'id'}); |
} |
} # while message SMS |
} # if($params{SMSPlatform}){ |
# Disabilito gli utenti registrati che non si sono collegati entro MaxTimeToConfirmUserRegistration giorni |
if($params{MaxTimeToConfirmUserRegistration}) { |
my $sth_users = $dbh->prepare(q{ |
SELECT anagrafiche.id |
FROM public.anagrafiche |
WHERE last_change_password IS NULL |
AND session_time is NOT NULL |
AND previus_session_time IS NULL |
AND to_number(to_char(now() - session_time, 'DD'), '99') > ? |
AND anagrafiche.id NOT IN ( |
SELECT session.id_anagrafiche |
FROM session |
) |
AND login IS NOT NULL |
AND password IS NOT NULL |
AND session IS NULL |
AND descrizione IS NULL |
AND indirizzo IS NULL |
AND provincia IS NULL |
AND citta IS NULL |
AND tel1 IS NULL; |
}); |
$sth_users->execute($params{MaxTimeToConfirmUserRegistration}); |
if($sth_users->rows > 0){ |
my $delete = 1; |
while(my $data = $sth_users->fetchrow_arrayref){ |
my $id_user = $data->[0]; |
# Verifico che non ci siano logs di quell'utente |
my $sth_logs = $dbh->prepare(q{ |
SELECT count(*) |
FROM logs |
WHERE id_anagrafiche = ?; |
}); |
$sth_logs->execute($id_user); |
next if($sth_logs->fetchrow_arrayref->[0]); |
# Verifico che ci sia un solo messaggio inviato all'utente e che quel messaggio |
# sia stato inviato solo a lui |
my $sth_mess = $dbh->prepare(q{ |
SELECT messages.id, |
(SELECT count(*) FROM messages_users WHERE messages_users.id_messages = messages.id) AS num |
FROM messages |
INNER JOIN messages_users ON messages_users.id_messages = messages.id |
WHERE messages_users.id_anagrafiche = ? |
}); |
my $num_mess = $sth_mess->execute($id_user); |
next if($num_mess != 1); |
my($id_message, $num_mess2) = $sth_mess->fetchrow_array; |
next if($num_mess2 > 1); |
# Cancello utente |
my $sth_del = $dbh->prepare(q{ |
DELETE FROM messages_users WHERE id_messages = $1; |
DELETE FROM messages WHERE id = $1; |
DELETE FROM anagrafiche_gruppi WHERE id_anagrafiche = $2; |
DELETE FROM anagrafiche WHERE id = $2; |
}); |
$sth_del->execute($id_message, $id_user); |
### Commit database contents. |
$dbh->{AutoCommit} || $dbh->commit; |
} |
} |
} # if($params{MaxTimeToConfirmUserRegistration}) |
# end necessario per Sys::RunAlone |
__END__ |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/utility/convert_iso-8859-15_to_utf-8.sh |
---|
0,0 → 1,32 |
#!/bin/bash |
if [ "$1" != "--CONVERT" ] |
then |
find ./ -type f -exec /opt/masonsql/utility/convert_iso-8859-15_to_utf-8.sh --CONVERT {} \; |
exit |
fi |
shift 1 |
F=$1 |
#echo CHECK $F |
# cartelle da escludere |
[ -z "${F%%*/jquery*}" ] && exit |
[ -z "${F%%*/FCKeditor/*}" ] && exit |
[ -z "${F%%*/bin/*}" ] && exit |
# estensioni del file |
[ -z "${F%%*.txt}" -o -z "${F%%*.htm}" -o -z "${F%%*.html}" -o -z "${F%%*.js}" \ |
-o -z "${F%%*.comp}" -o -z "${F%%*.css}" -o -z "${F%%*.pl}" -o -z "${F%%*.pm}" \ |
-o -z "${F%%*.include}" -o -z "${F%%*.mql}" -o -z "${F%%*handler}" \ |
-o -z "${F%%*APPUNTI}" -o -z "${F%%*.mason}" -o -z "${F%%*.conf}" ] || exit |
[ -f "$F.ISO-8859-15" ] && exit |
echo "CONVERT $F" |
cp -a "$F" "$F.ISO-8859-15" |
iconv --from-code=ISO-8859-15 --to-code=UTF-8 "$F.ISO-8859-15" > "$F" |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/utility/sql/create_logs_report.sql |
---|
0,0 → 1,71 |
-- Table: logs_report |
-- DROP TABLE logs_report; |
CREATE TABLE logs_report |
( |
id integer NOT NULL DEFAULT nextval(('logs_report_seq'::text)::regclass), -- Primary key |
"timestamp" timestamp without time zone NOT NULL, -- Data e ora della modifica |
table_name character varying(63) NOT NULL, -- Nome della tabella |
report character varying, -- Riepilogo delle variazioni |
id_anagrafiche integer, -- Utente responsabile della modifica |
id_record integer NOT NULL, -- ID record modificato |
CONSTRAINT logs_report_pkey PRIMARY KEY (id), |
CONSTRAINT logs_report_id_anagrafiche FOREIGN KEY (id_anagrafiche) |
REFERENCES anagrafiche (id) MATCH SIMPLE |
ON UPDATE RESTRICT ON DELETE RESTRICT |
) |
WITH ( |
OIDS=FALSE |
); |
ALTER TABLE logs_report |
OWNER TO postgres; |
GRANT ALL ON TABLE logs_report TO postgres; |
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE logs_report TO heidix; |
GRANT SELECT ON TABLE logs_report TO report; |
COMMENT ON TABLE logs_report |
IS 'Report delle operazioni di variazione dei dati effettuati dall''interfaccia Web'; |
COMMENT ON COLUMN logs_report.id IS 'Primary key'; |
COMMENT ON COLUMN logs_report."timestamp" IS 'Data e ora della modifica'; |
COMMENT ON COLUMN logs_report.table_name IS 'Nome della tabella'; |
COMMENT ON COLUMN logs_report.report IS 'Riepilogo delle variazioni'; |
COMMENT ON COLUMN logs_report.id_anagrafiche IS 'Utente responsabile della modifica'; |
COMMENT ON COLUMN logs_report.id_record IS 'ID record modificato'; |
-- Index: logs_report_id_anagrafiche |
-- DROP INDEX logs_report_id_anagrafiche; |
CREATE INDEX logs_report_id_anagrafiche |
ON logs_report |
USING btree |
(id_anagrafiche); |
-- Index: logs_report_id_record |
-- DROP INDEX logs_report_id_record; |
CREATE INDEX logs_report_id_record |
ON logs_report |
USING btree |
(id_record); |
-- Index: logs_report_table |
-- DROP INDEX logs_report_table; |
CREATE INDEX logs_report_table |
ON logs_report |
USING btree |
(table_name COLLATE pg_catalog."default"); |
-- Index: logs_report_timestamp |
-- DROP INDEX logs_report_timestamp; |
CREATE INDEX logs_report_timestamp |
ON logs_report |
USING btree |
("timestamp"); |
/tags/2.0/utility/sql/odt_report_tables.sql |
---|
0,0 → 1,78 |
CREATE SEQUENCE public.odt_reports_id_seq |
INCREMENT 1 |
MINVALUE 1 |
MAXVALUE 2147483647 |
START 1 |
CACHE 1; |
ALTER TABLE public.odt_reports_id_seq |
OWNER TO postgres; |
GRANT ALL ON SEQUENCE public.odt_reports_id_seq TO postgres; |
GRANT ALL ON SEQUENCE public.odt_reports_id_seq TO masonsql; |
CREATE SEQUENCE public.odt_report_portions_id_seq |
INCREMENT 1 |
MINVALUE 1 |
MAXVALUE 2147483647 |
START 1 |
CACHE 1; |
ALTER TABLE public.odt_report_portions_id_seq |
OWNER TO postgres; |
GRANT ALL ON SEQUENCE public.odt_report_portions_id_seq TO postgres; |
GRANT ALL ON SEQUENCE public.odt_report_portions_id_seq TO masonsql; |
CREATE TABLE public.odt_reports |
( |
id integer NOT NULL DEFAULT nextval('odt_reports_id_seq'::regclass), |
name character varying(255), |
description character varying(100), |
comment character varying(1024), |
cmd_parameters character varying(255), |
global_parameters character varying(255), |
CONSTRAINT odt_reports_pkey PRIMARY KEY (id), |
CONSTRAINT odt_reports_name UNIQUE (name) |
); |
ALTER TABLE public.odt_reports |
OWNER TO postgres; |
GRANT ALL ON TABLE public.odt_reports TO postgres; |
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE public.odt_reports TO masonsql; |
GRANT SELECT ON TABLE public.odt_reports TO report; |
CREATE TABLE public.odt_report_portions |
( |
id integer NOT NULL DEFAULT nextval('odt_report_portions_id_seq'::regclass), |
name character varying(20), |
id_odt_reports integer NOT NULL, |
id_father integer, |
ord integer NOT NULL, |
query character varying(10240), |
type character varying(30), |
file_name character varying(45), |
obj_ref character varying(70), |
CONSTRAINT odt_report_portions_pkey PRIMARY KEY (id), |
CONSTRAINT odt_report_portions_id_father FOREIGN KEY (id_father) |
REFERENCES public.odt_report_portions (id) MATCH SIMPLE |
ON UPDATE NO ACTION ON DELETE NO ACTION, |
CONSTRAINT odt_report_portions_id_odt_reports FOREIGN KEY (id_odt_reports) |
REFERENCES public.odt_reports (id) MATCH SIMPLE |
ON UPDATE NO ACTION ON DELETE NO ACTION |
); |
ALTER TABLE public.odt_report_portions |
OWNER TO postgres; |
GRANT ALL ON TABLE public.odt_report_portions TO postgres; |
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE public.odt_report_portions TO masonsql; |
GRANT SELECT ON TABLE public.odt_report_portions TO report; |
CREATE TABLE public.odt_report_fields |
( |
id serial NOT NULL, |
id_odt_reports integer NOT NULL, |
key character varying(100), |
function character varying(1024), |
format character varying(256), |
CONSTRAINT odt_report_fields_pkey PRIMARY KEY (id), |
CONSTRAINT odt_report_fields_id_odt_reports FOREIGN KEY (id_odt_reports) |
REFERENCES public.odt_reports (id) MATCH SIMPLE |
ON UPDATE NO ACTION ON DELETE NO ACTION |
); |
ALTER TABLE public.odt_report_fields OWNER TO postgres; |
GRANT ALL ON TABLE public.odt_report_fields TO postgres; |
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE public.odt_report_fields TO masonsql; |
GRANT SELECT ON TABLE public.odt_report_fields TO report; |
ALTER SEQUENCE public.odt_report_fields_id_seq MAXVALUE 2147483647; |
GRANT ALL ON SEQUENCE public.odt_reports_id_seq TO masonsql; |
/tags/2.0/utility/sql/pg_dump.masonsql.template.sql |
---|
0,0 → 1,1709 |
-- |
-- PostgreSQL database dump |
-- |
SET statement_timeout = 0; |
SET client_encoding = 'UTF8'; |
SET standard_conforming_strings = off; |
SET check_function_bodies = false; |
SET client_min_messages = warning; |
SET escape_string_warning = off; |
-- |
-- Name: plpgsql; Type: PROCEDURAL LANGUAGE; Schema: -; Owner: postgres |
-- |
CREATE PROCEDURAL LANGUAGE plpgsql; |
ALTER PROCEDURAL LANGUAGE plpgsql OWNER TO postgres; |
SET search_path = public, pg_catalog; |
SET default_tablespace = ''; |
SET default_with_oids = false; |
-- |
-- Name: anagrafiche; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE anagrafiche ( |
id integer NOT NULL, |
nome character varying(20), |
cognome character varying(25), |
descrizione character varying(60), |
indirizzo character varying(60), |
provincia character varying(2), |
citta character varying(20), |
tel1 character varying(20), |
tel2 character varying(20), |
cell_sms character varying(20), |
codice_fiscale character(16), |
login character varying(60), |
password character(32), |
session character varying(60), |
email character varying(60), |
session_time timestamp without time zone, |
previus_session_time timestamp without time zone |
); |
ALTER TABLE public.anagrafiche OWNER TO postgres; |
-- |
-- Name: TABLE anagrafiche; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON TABLE anagrafiche IS 'Anagrafiche persone'; |
-- |
-- Name: COLUMN anagrafiche.session_time; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN anagrafiche.session_time IS 'Istante di login dell''utente'; |
-- |
-- Name: COLUMN anagrafiche.previus_session_time; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN anagrafiche.previus_session_time IS 'Istante della precedente login dell''utente'; |
-- |
-- Name: anagrafiche_gruppi; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE anagrafiche_gruppi ( |
id integer NOT NULL, |
id_anagrafiche integer NOT NULL, |
id_gruppi integer NOT NULL |
); |
ALTER TABLE public.anagrafiche_gruppi OWNER TO postgres; |
-- |
-- Name: TABLE anagrafiche_gruppi; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON TABLE anagrafiche_gruppi IS 'Relazioni di appartenenza delle anagrafiche ai gruppi'; |
-- |
-- Name: anagrafiche_gruppi_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE anagrafiche_gruppi_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.anagrafiche_gruppi_id_seq OWNER TO postgres; |
-- |
-- Name: anagrafiche_gruppi_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE anagrafiche_gruppi_id_seq OWNED BY anagrafiche_gruppi.id; |
-- |
-- Name: anagrafiche_gruppi_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('anagrafiche_gruppi_id_seq', 3, true); |
-- |
-- Name: anagrafiche_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE anagrafiche_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.anagrafiche_id_seq OWNER TO postgres; |
-- |
-- Name: anagrafiche_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE anagrafiche_id_seq OWNED BY anagrafiche.id; |
-- |
-- Name: anagrafiche_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('anagrafiche_id_seq', 3, true); |
-- |
-- Name: autorizzazioni; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE autorizzazioni ( |
id integer NOT NULL, |
nome character varying(16) NOT NULL, |
descrizione character varying(60), |
commento character varying(240) |
); |
ALTER TABLE public.autorizzazioni OWNER TO postgres; |
-- |
-- Name: autorizzazioni_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE autorizzazioni_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.autorizzazioni_id_seq OWNER TO postgres; |
-- |
-- Name: autorizzazioni_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE autorizzazioni_id_seq OWNED BY autorizzazioni.id; |
-- |
-- Name: autorizzazioni_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('autorizzazioni_id_seq', 10, true); |
-- |
-- Name: funzioni; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE funzioni ( |
id integer NOT NULL, |
descrizione character varying(60), |
commento character varying(240), |
nome character varying(16) NOT NULL, |
menu_contents character varying(24), |
menu_status character varying(64), |
menu_ord smallint, |
menu_command character varying(1024), |
menu_cmdtype character(1), |
menu_father_id integer, |
help character varying |
); |
ALTER TABLE public.funzioni OWNER TO postgres; |
-- |
-- Name: funzioni_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE funzioni_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.funzioni_id_seq OWNER TO postgres; |
-- |
-- Name: funzioni_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE funzioni_id_seq OWNED BY funzioni.id; |
-- |
-- Name: funzioni_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('funzioni_id_seq', 19, true); |
-- |
-- Name: gruppi; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE gruppi ( |
id integer NOT NULL, |
nome character varying(16), |
descrizione character varying(60), |
commento character varying(240) |
); |
ALTER TABLE public.gruppi OWNER TO postgres; |
-- |
-- Name: gruppi_and_anagrafiche; Type: VIEW; Schema: public; Owner: postgres |
-- |
CREATE VIEW gruppi_and_anagrafiche AS |
SELECT (- gruppi.id) AS id, gruppi.nome AS descrizione FROM gruppi UNION SELECT anagrafiche.id, (COALESCE(((anagrafiche.nome)::text || ' '::text), ''::text) || COALESCE((anagrafiche.cognome)::text, ''::text)) AS descrizione FROM anagrafiche WHERE (anagrafiche.login IS NOT NULL) ORDER BY 1; |
ALTER TABLE public.gruppi_and_anagrafiche OWNER TO postgres; |
-- |
-- Name: gruppi_funzioni; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE gruppi_funzioni ( |
id integer NOT NULL, |
id_funzioni integer NOT NULL, |
id_gruppi integer NOT NULL, |
id_autorizzazioni integer NOT NULL |
); |
ALTER TABLE public.gruppi_funzioni OWNER TO postgres; |
-- |
-- Name: gruppi_funzioni_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE gruppi_funzioni_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.gruppi_funzioni_id_seq OWNER TO postgres; |
-- |
-- Name: gruppi_funzioni_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE gruppi_funzioni_id_seq OWNED BY gruppi_funzioni.id; |
-- |
-- Name: gruppi_funzioni_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('gruppi_funzioni_id_seq', 396, true); |
-- |
-- Name: gruppi_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE gruppi_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.gruppi_id_seq OWNER TO postgres; |
-- |
-- Name: gruppi_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE gruppi_id_seq OWNED BY gruppi.id; |
-- |
-- Name: gruppi_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('gruppi_id_seq', 4, true); |
-- |
-- Name: gruppi_modifica; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE gruppi_modifica ( |
id integer NOT NULL, |
id_gruppo integer NOT NULL, |
id_gruppo_modifica integer NOT NULL |
); |
ALTER TABLE public.gruppi_modifica OWNER TO postgres; |
-- |
-- Name: gruppi_modifica_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE gruppi_modifica_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.gruppi_modifica_id_seq OWNER TO postgres; |
-- |
-- Name: gruppi_modifica_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE gruppi_modifica_id_seq OWNED BY gruppi_modifica.id; |
-- |
-- Name: gruppi_modifica_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('gruppi_modifica_id_seq', 1, false); |
-- |
-- Name: logs; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE logs ( |
id integer NOT NULL, |
"timestamp" timestamp without time zone DEFAULT now(), |
table_name character varying(63), |
old_value character varying, |
new_value character varying, |
id_anagrafiche integer, |
field character varying(63), |
id_record integer |
); |
ALTER TABLE public.logs OWNER TO postgres; |
-- |
-- Name: TABLE logs; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON TABLE logs IS 'Log operazioni di inserimento, modifica e cancellazione effettuati dall''interfaccia Web |
'; |
-- |
-- Name: COLUMN logs.id; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.id IS 'Primary key'; |
-- |
-- Name: COLUMN logs."timestamp"; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs."timestamp" IS 'Data e ora della modifica'; |
-- |
-- Name: COLUMN logs.table_name; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.table_name IS 'Nome della tabella'; |
-- |
-- Name: COLUMN logs.old_value; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.old_value IS 'Valore del campo prima della modifica'; |
-- |
-- Name: COLUMN logs.new_value; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.new_value IS 'Valore del campo dopo la modifica'; |
-- |
-- Name: COLUMN logs.id_anagrafiche; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.id_anagrafiche IS 'Utente responsabile della modifica'; |
-- |
-- Name: COLUMN logs.field; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN logs.field IS 'Nome del campo'; |
-- |
-- Name: logs_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE logs_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.logs_id_seq OWNER TO postgres; |
-- |
-- Name: logs_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE logs_id_seq OWNED BY logs.id; |
-- |
-- Name: logs_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('logs_id_seq', 1, true); |
SET default_with_oids = true; |
-- |
-- Name: messages; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE messages ( |
id integer NOT NULL, |
message character varying NOT NULL, |
owner integer NOT NULL, |
modification_time timestamp without time zone NOT NULL, |
transmission_time timestamp without time zone |
); |
ALTER TABLE public.messages OWNER TO postgres; |
-- |
-- Name: messages_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE messages_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.messages_id_seq OWNER TO postgres; |
-- |
-- Name: messages_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE messages_id_seq OWNED BY messages.id; |
-- |
-- Name: messages_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('messages_id_seq', 1, false); |
SET default_with_oids = false; |
-- |
-- Name: messages_users; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE messages_users ( |
id integer NOT NULL, |
id_messages integer NOT NULL, |
id_anagrafiche integer NOT NULL, |
notification_time timestamp without time zone |
); |
ALTER TABLE public.messages_users OWNER TO postgres; |
-- |
-- Name: messages_users_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE messages_users_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.messages_users_id_seq OWNER TO postgres; |
-- |
-- Name: messages_users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE messages_users_id_seq OWNED BY messages_users.id; |
-- |
-- Name: messages_users_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('messages_users_id_seq', 1, false); |
-- |
-- Name: recordset; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE recordset ( |
id integer NOT NULL, |
id_anagrafiche integer, |
name character varying(64) NOT NULL, |
size integer, |
block integer, |
query_numrec character varying, |
query_records character varying, |
query_where character varying, |
query_find_records character varying |
); |
ALTER TABLE public.recordset OWNER TO postgres; |
-- |
-- Name: TABLE recordset; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON TABLE recordset IS 'Tabella per rendere persistenti i recordset utilizzati sul browser. |
Le righe precaricate (con la chiave del record) sono inserite nella tabella recordset_rows.'; |
-- |
-- Name: COLUMN recordset.name; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN recordset.name IS 'Nome del recordset. |
Corrisponde a .prefix indicato nell''oggetto databinding corrispondente che a sua volta corrisponde a $Recordset nel framework MasonSql'; |
-- |
-- Name: COLUMN recordset.block; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN recordset.block IS 'Dimensione del blocco utilizzato per il caricamento delle chiavi.'; |
-- |
-- Name: recordset_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE recordset_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.recordset_id_seq OWNER TO postgres; |
-- |
-- Name: recordset_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE recordset_id_seq OWNED BY recordset.id; |
-- |
-- Name: recordset_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('recordset_id_seq', 1, true); |
-- |
-- Name: recordset_rows; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE recordset_rows ( |
id integer NOT NULL, |
id_recordset integer NOT NULL, |
num_row integer NOT NULL, |
id_record integer |
); |
ALTER TABLE public.recordset_rows OWNER TO postgres; |
-- |
-- Name: TABLE recordset_rows; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON TABLE recordset_rows IS 'Chiavi recordset (vedi tabella recordset). |
Utilizzata nella gestione dei recordset persistenti. |
'; |
-- |
-- Name: COLUMN recordset_rows.num_row; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN recordset_rows.num_row IS 'Riga nel recordset'; |
-- |
-- Name: COLUMN recordset_rows.id_record; Type: COMMENT; Schema: public; Owner: postgres |
-- |
COMMENT ON COLUMN recordset_rows.id_record IS 'Chiave del record'; |
-- |
-- Name: recordset_rows_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE recordset_rows_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.recordset_rows_id_seq OWNER TO postgres; |
-- |
-- Name: recordset_rows_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE recordset_rows_id_seq OWNED BY recordset_rows.id; |
-- |
-- Name: recordset_rows_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('recordset_rows_id_seq', 1, true); |
-- |
-- Name: report_id; Type: TABLE; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE TABLE report_id ( |
id integer NOT NULL, |
key integer NOT NULL, |
group_id integer NOT NULL |
); |
ALTER TABLE public.report_id OWNER TO postgres; |
-- |
-- Name: report_id_id_seq; Type: SEQUENCE; Schema: public; Owner: postgres |
-- |
CREATE SEQUENCE report_id_id_seq |
START WITH 1 |
INCREMENT BY 1 |
NO MAXVALUE |
NO MINVALUE |
CACHE 1; |
ALTER TABLE public.report_id_id_seq OWNER TO postgres; |
-- |
-- Name: report_id_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres |
-- |
ALTER SEQUENCE report_id_id_seq OWNED BY report_id.id; |
-- |
-- Name: report_id_id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres |
-- |
SELECT pg_catalog.setval('report_id_id_seq', 1, true); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE anagrafiche ALTER COLUMN id SET DEFAULT nextval('anagrafiche_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE anagrafiche_gruppi ALTER COLUMN id SET DEFAULT nextval('anagrafiche_gruppi_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE autorizzazioni ALTER COLUMN id SET DEFAULT nextval('autorizzazioni_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE funzioni ALTER COLUMN id SET DEFAULT nextval('funzioni_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE gruppi ALTER COLUMN id SET DEFAULT nextval('gruppi_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE gruppi_funzioni ALTER COLUMN id SET DEFAULT nextval('gruppi_funzioni_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE gruppi_modifica ALTER COLUMN id SET DEFAULT nextval('gruppi_modifica_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE logs ALTER COLUMN id SET DEFAULT nextval('logs_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE messages ALTER COLUMN id SET DEFAULT nextval('messages_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE messages_users ALTER COLUMN id SET DEFAULT nextval('messages_users_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE recordset ALTER COLUMN id SET DEFAULT nextval('recordset_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE recordset_rows ALTER COLUMN id SET DEFAULT nextval('recordset_rows_id_seq'::regclass); |
-- |
-- Name: id; Type: DEFAULT; Schema: public; Owner: postgres |
-- |
ALTER TABLE report_id ALTER COLUMN id SET DEFAULT nextval('report_id_id_seq'::regclass); |
-- |
-- Data for Name: anagrafiche; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY anagrafiche (id, nome, cognome, descrizione, indirizzo, provincia, citta, tel1, tel2, sell_sms, codice_fiscale, login, password, session, email, session_time, previus_session_time) FROM stdin; |
3 Guest Guest \N \N \N \N \N \N \N \N guest 19ad89bc3e3c9d7ef68b89523eff1987 \N \N \N \N |
1 admin \N \N \N \N \N \N \N \N \N admin 8c31523d0c7e79c2594854a2fe62d3b5 172009872beb234c8bac09961375b8b4 10.115.1.2 21228904 \N 2010-05-13 08:52:34.868345 2010-05-13 07:51:40.19512 |
\. |
-- |
-- Data for Name: anagrafiche_gruppi; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY anagrafiche_gruppi (id, id_anagrafiche, id_gruppi) FROM stdin; |
1 1 1 |
3 3 4 |
\. |
-- |
-- Data for Name: autorizzazioni; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY autorizzazioni (id, nome, descrizione, commento) FROM stdin; |
8 Xls Download dati in formato XLS L'autorizzazione se concessa permette all'utente di scaricare i dati in formato XLS |
4 Delete Cancellazione dei dati \N |
2 Select Lettura dei dati \N |
7 Insert Inserimento nuovi valori \N |
1 Menu Menu attivo La voce di menù viene resa disponibile |
5 Print Stampa record corrente \N |
6 PrintSel Stampa selezione dei record \N |
3 Update Modifica dei dati \N |
9 Dbms Interfaccia scambio dati /dbms L'autorizzazione se concessa permette all'utente di scambiare dati attraverso l'interfaccia /dbms |
10 Log Visualizzazione delle modifiche nel tempo Visualizza le modifiche apportate nel tempo con indicazione dell'utente |
\. |
-- |
-- Data for Name: funzioni; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY funzioni (id, descrizione, commento, nome, menu_contents, menu_status, menu_ord, menu_command, menu_cmdtype, menu_father_id, help) FROM stdin; |
3 Help \N Help ? Help 900 \N \N \N Menu principale Help. |
7 Home Page \N HomePage Home Page Ricarica Home Page 10 "pageLoad('home.html?Ver=$Ver', '')" J 14 Home Page. |
12 Ricarica form corrente \N Reload Ricarica Ricarica form corrente 30 divReload(CurrentMenu); divReload(CurrentBody); j 3 Viene ricaricata dal server la funzione corrente. |
4 Cambio password \N ChangePass Cambio password \N 90 "pageLoad('change_password.html?Ver=$Ver', '')" J 14 Help funzione Cambio password |
8 Autorizzazioni \N ListAuth Tipi autorizzazioni Autorizzazioni 20 "pageLoad('table.html?Ver=$Ver&from=autorizzazioni', '')" J 17 Classificazione delle autorizzazioni attribuibili ai gruppi a cui appartengono gli utenti.<br />\n<br />\n<ul>\n <li>\n <p align="left"><strong>Nome autorizzazione: </strong><span style=""></span></p>\n </li>\n <li>\n <p align="left"><strong>Descrizione: </strong>Descrizione autorizzazione<br />\n </p>\n </li>\n <li>\n <p align="left"><strong>Commento: </strong>Commento di utilizzo libero</p>\n </li>\n</ul> |
9 Tabella funzioni \N Funzioni Funzioni e autorizz. Tabella funzioni dell'applicazione e autorizzazioni applicate 30 "pageLoad('table.html?Ver=$Ver&from=funzioni&children=TABLE&rows_child=10', '')" J 17 Definizione dei menù dell'applicazione e relativi permessi e documentazione.<br />\n<br />\n<ul>\n <li>\n <p align="left"><strong>Nome: </strong>Nome univoco della funzione. Al nome vengono associati i profili dei permessi usati anche nel codice. E' quindi importante non modificare il codice se non si è in grado di modificare anche i riferimenti nel codice dell'applicazione<span style=""></span></p>\n </li>\n <li>\n <p align="left"><strong>Descrizione: </strong>Descrizione della funzione</p>\n </li>\n <li>\n <p align="left"><strong>Commento: </strong>Commento di utilizzo libero</p>\n </li>\n <li>\n <p align="left"><strong>Ord: </strong>Numero che determina l'ordine con cui le varie voci di menù compaiono<br />\n </p>\n </li>\n <li>\n <p align="left"><strong>Menu: </strong>Nome del menù che appare nell'applicazione<strong><br />\n </strong></p>\n </li>\n <li>\n <p align="left"><strong>Menu padre: </strong>Nome della funziona padre. La voce comparirà nel menù sotto la voce del padre indicato. E' possibile indicare come padre delle voci di menù che a voro volta hanno un padre.<br />\n </p>\n </li>\n <li>\n <p align="left"><strong>Menu avviso: </strong>Titolo del menù<strong><br />\n </strong></p>\n </li>\n <li>\n <p align="left"><strong>Tipo comando: </strong></p>\n <ul>\n <li><strong>Link WEB: </strong>Il contenuto del campo <em>Comando Menu</em> verrà interpretato come link ad una pagina HTML<br />\n </li>\n <li><strong>Link WEB - applicando eval Perl: </strong>Al contenuto del campo viene applicata la funzione eval sul Server; utile per elaborare dei valori <em>(es. la variabile $Ver verrà sostituita con il numero di versione)</em><br />\n </li>\n <li><strong>Client Javascript: </strong>Il contenuto del campo <em>Comando Menu</em> verrà interpretato come codice javascript sul browser.<br />\n </li>\n <li><strong>Client Javascript</strong><strong> - applicando eval Perl: </strong>Al contenuto del campo viene applicata la funzione eval sul Server.</li>\n </ul>\n </li>\n <li>\n <p align="left"><strong>Comando Menu: </strong>Il comando, intepretato in funzione del campo <em>Tipo comando</em>.<strong><br />\n </strong></p>\n </li>\n <li>\n <p align="left"><strong>Permessi: </strong>Tabella di assegnazione dei permessi. In colonna vengono inseriti i vari tipi di autorizzazioni, mentre in riga troviamo le definizioni dei vari gruppi.<br />\n </p>\n </li>\n <li>\n <p align="left"><strong>Help: </strong>Documentazione della funzione a disposizione dell'utente. L'help dell'applicazione viene costruito assemblando la documentazione delle funzioni a cui l'utente ha accesso in base ai gruppi a cui appartiene.<strong><br />\n </strong></p>\n </li>\n</ul> |
1 Modifiche nel database Registrazione modifiche nel database da parte degli Utenti Logs Log database Registrazione modifiche nel database da parte degli Utenti 999 "pageLoad('table.html?Ver=$Ver&from=logs', '')" J 17 Visualizza il registro delle mondifiche effettuate dagli utenti nel database. |
14 Home Raggruppamento homed Home Home Home page applicazione SIDAL 1 \N \N \N <h1 align="center">Introduzione</h1>\n<p>Questo programma permette la gestione integrata ....<br />\n</p>\n<span style="font-size: 10pt; font-family: Symbol;"></span> |
2 Chiusura sessione \N CloseSession Esci Chiude sessione di lavoro 999 "logout.html?Ver=$Ver" U 14 Chiusura sessione. |
16 Tabella anagrafiche persone \N Anagrafiche Anagrafica utenti Tabella anagrafiche utenti 10 "pageLoad('/table.html?Ver=$Ver&from=anagrafiche&form=FORM&children=TABLE&rows_child=5', '')" J 17 <h1 align="center">Anagrafica utenti</h1>\n<p align="justify">Archivio degli Utenti che accedono all'applicazione.</p>\n<p align="justify">Solo l'Utente con diritti di amministratore è in grado di modificare i dati degli Utenti.</p>\n<p align="justify">I campi dell'archivio, visualizzati nel “form”, sono:</p>\n<ul>\n <li>\n <p align="justify"><strong>Nome:</strong> Nome di battesimo dell'utente </p>\n </li>\n <li>\n <p align="left"><strong>Cognome:</strong> Cognome dell'Utente</p>\n </li>\n <li>\n <p align="left"><strong>C.F.:</strong> Codice fiscale; necessario se l'Utente è abilitato a firmare i Rapporti di prova, infatti viene utilizzato per la verifica del certificato di firma che deve quindi combaciare, assieme al Nome e Cognome.</p>\n </li>\n <li>\n <p align="left"><strong>Indirizzo:</strong> Indirizzo di reperibilità</p>\n </li>\n <li>\n <p align="left"><strong>Provincia:</strong></p>\n </li>\n <li>\n <p align="left"><strong>Città:</strong></p>\n </li>\n <li>\n <p align="left"><strong>Telefono:</strong></p>\n </li>\n <li>\n <p align="left"><strong>2° Telefono:</strong></p>\n </li>\n <li>\n <p align="left"><strong>Indirizzo e-mail:</strong></p>\n </li>\n <li>\n <p align="left"><strong>Login:</strong> codice di accesso all'applicazione; Deve essere un codice univoco diverso quindi per ciascun Utente</p>\n </li>\n <li>\n <p align="left"><strong>Password: </strong>password di almeno 8 caratteri. La password viene salvata nel database cifrata in modo da impedire la lettura anche all'Amministratore che può eventualmente cambiarla se l'Utente dovesse dimenticarla</p>\n </li>\n <li>\n <p align="left"><strong>parametri su:</strong> Numero di righe da visualizzare della tabella dei parametri del form dei campioni prelevati</p>\n </li>\n <li>\n <p align="left"><strong>in tabella:</strong> Se selezionato, i dati dei parametri dei Campioni prelevati, verranno allineati in formato tabella</p>\n </li>\n <li>\n <p align="left" style="margin-bottom: 0cm;"><strong>Gruppi a cui appartiene l'utente: </strong>Lista dei gruppi a cui l'utente può appartenere:<br />\n </p>\n <ul>\n <li><strong>Admins: </strong>Amministratori dell'applicazione</li>\n <li><strong>Guesti</strong>: Utenti ospiti (sol alettura)</li>\n </ul>\n </li>\n</ul> |
13 Manuale di riferimento Visualizza un Help dell'applicazione HelpMain Help Help Analisi Chimiche 1 "pageLoad('/help.html?F=Home&Ver=$Ver', '/help.html?Ver=$Ver')" J 3 <span style="cursor: auto;" id="Father_FORM_funzioni">L'help dell'applicazione viene costruito assemblando la documentazione delle funzioni a cui l'utente ha accesso in base ai gruppi a cui appartiene.<br />\nLe varie funzioni vengono organizzate in un menù ad albero visibile a sinistra, con il dettaglio visualizzato sulla destra.<br />\nLa documentazione è modificabile dagli utenti abilitati dalla funzione <em>Funzioni e autorizz.</em></span> |
17 Impostazione delle autorizzazioni \N Autorizzazioni Autorizzazioni Impostazione delle autorizzazioni 5 \N \N \N <div align="center"><font size="5"><span style="cursor: auto;" id="Father_autorizzazioni"><strong><strong>Autorizzazioni<br />\n<br />\n</strong></strong></span></font>\n<div align="left">\n<ul>\n <li><font size="5"><span style="cursor: auto;" id="Father_autorizzazioni"><strong><strong><font size="2">Nome autorizzazione: </font></strong></strong><font size="2">Nome dell'autorizzazione</font><strong><strong><font size="2"> <br />\n </font></strong></strong></span></font></li>\n</ul>\n<ul>\n <li><font size="5"><span style="cursor: auto;" id="Father_autorizzazioni"><strong><strong><font size="2">Descrizione: </font></strong></strong><font size="2">Descrizione dell'autorizzazione<br />\n </font></span></font></li>\n</ul>\n<ul>\n <li><font size="5"><span style="cursor: auto;" id="Father_autorizzazioni"><strong><strong><font size="2">Commento: </font></strong></strong><font size="2">Eventuale commento<br />\n </font></span></font></li>\n</ul>\n<font size="5"><span style="cursor: auto;" id="Father_autorizzazioni"></span></font></div>\n</div> |
6 Note di release e Copyright \N Release Release Note di release e Copyright 20 "pageLoad('release_notes.html?Ver=$Ver', '')" J 3 Note di release: ................<br />\n<br />\n<br />\n<br />\n<br />\n<div align="center"><br />\nFramework MasonSQL<br />\nCopyright (©):<br />\nGuido Brugnara <gdo@leader.it><br />\nLicenza G.P.L. Rel.2 <br />\n</div>\n<strong></strong> |
10 Tabella gruppi \N Gruppi Gruppi Tabella gruppi 10 "pageLoad('/table.html?Ver=$Ver&from=gruppi&children=TABLE&rows_child=10', '')" J 17 <div align="center"><font size="4"><font size="5">GRUPPI</font><strong><br />\n<br />\n</strong></font></div>\nDefinizione dei gruppi a cui possono appartenere gli utenti che accedono all'applicazione.<br />\n<br />\n<ul>\n <li>\n <p align="left"><strong>Nome: </strong>Nome del gruppo<span style=""></span></p>\n </li>\n <li>\n <p align="left"><strong>Descrizione: </strong>Descrizione del gruppo</p>\n </li>\n <li>\n <p align="left"><strong>Commento: </strong>Commento di utilizzo libero</p>\n </li>\n <li>\n <p align="left"><strong>Utenti del gruppo:</strong> Elenco degli utenti che appartengono al gruppo<span style="cursor: auto;" id="Child_gruppi_modifica"></span></p>\n </li>\n <li>\n <p align="left"><span style="cursor: auto;" id="Child_gruppi_modifica"><strong><strong>Gruppi modificabili: </strong></strong>Elenco dei gruppi che utenti appartenenti al gruppo in testata possono attribuire ad altri utenti.</span></p>\n </li>\n</ul>\n<br />\n<span style="cursor: auto;" id="Child_gruppi_anagrafiche"><strong><strong>Utenti del gruppo</strong></strong></span><br />\nL'ambiente di base codifica i seguenti gruppi che non devono essere alterati:<br />\n<ul>\n <li>\n <p align="left"><strong>Admins:</strong> Gruppo <em>admin</em> di base dell'applicazione. E' un gruppo speciale che ha tutti i diritti.</p>\n </li>\n</ul>\n<br />\n<span style="cursor: auto;" id="Child_gruppi_modifica"><strong><strong>Gruppi modificabili<br />\n</strong></strong></span>\n<ul>\n <li>EnteAccett: Gruppo Accettazione Ente</li>\n</ul>\n<ul>\n <li>EnteAdmin: Gruppo Amministratore ditta gestione</li>\n</ul>\n<ul>\n <li>EnteChimico: Gruppo Chimico ditta gestione</li>\n</ul>\n<ul>\n <li>EntePrelievo: Gruppo Tecnico prelievo ditta gestione</li>\n</ul>\n<ul>\n <li>EnteResp: Gruppo Responsabile ditta gestione</li>\n</ul>\n<ul>\n <li>EnteUser: Utente ditta gestione</li>\n</ul>\n<ul>\n <li>PatAdmin: Gruppo Amministratore PAT</li>\n</ul>\n<ul>\n <li>PatChimico: Chimico PAT</li>\n</ul>\n<ul>\n <li>PatUser: Utente PAT</li>\n</ul>\n<br />\n<br />\n<br />\n<span style="cursor: auto;" id="Child_gruppi_modifica"><strong><strong></strong></strong></span> |
18 Messaggi ed avvisi di sistema \N Messages Messaggi Messaggi ed avvisi di sistema \N "pageLoad('table.html?Ver=$Ver&from=messages&form=FORM', '')" J 17 Gestione messaggi agli utenti |
19 Messaggi inviati all'utente \N User_messages Messaggi Messaggi inviati all'utente \N "pageLoad('table.html?Ver=$Ver&from=user_messages&form=DIVS', '')" J 14 Messaggi inviati all'utente |
\. |
-- |
-- Data for Name: gruppi; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY gruppi (id, nome, descrizione, commento) FROM stdin; |
1 Admins Amministratori Utenti amministratori |
4 Guest Utenti ospiti (sola lettura) \N |
\. |
-- |
-- Data for Name: gruppi_funzioni; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY gruppi_funzioni (id, id_funzioni, id_gruppi, id_autorizzazioni) FROM stdin; |
331 13 1 1 |
332 13 4 1 |
333 14 1 1 |
334 14 4 1 |
335 17 1 1 |
336 17 4 1 |
337 7 1 1 |
338 7 4 1 |
339 10 1 4 |
340 10 1 7 |
341 10 1 1 |
342 10 1 5 |
343 10 1 6 |
344 10 1 2 |
345 10 1 3 |
346 10 1 8 |
347 10 4 1 |
348 10 4 2 |
349 16 1 4 |
350 16 1 7 |
351 16 1 1 |
352 16 1 5 |
353 16 1 6 |
354 16 1 2 |
355 16 1 3 |
356 16 4 1 |
357 16 4 2 |
360 8 1 4 |
361 8 1 7 |
362 8 1 1 |
363 8 1 2 |
364 8 1 3 |
365 8 1 8 |
366 9 1 4 |
367 9 1 7 |
368 9 1 1 |
369 9 1 2 |
370 9 1 3 |
371 9 1 8 |
372 12 1 1 |
373 12 4 1 |
374 4 1 1 |
375 4 4 1 |
376 3 1 1 |
377 3 4 1 |
381 2 1 1 |
382 2 4 1 |
383 1 1 1 |
384 1 1 2 |
385 1 1 8 |
386 18 1 4 |
387 18 1 7 |
388 18 1 1 |
389 18 1 2 |
390 18 1 3 |
391 19 1 1 |
392 19 1 2 |
393 19 4 1 |
394 19 4 2 |
395 6 1 1 |
396 6 4 1 |
\. |
-- |
-- Data for Name: gruppi_modifica; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY gruppi_modifica (id, id_gruppo, id_gruppo_modifica) FROM stdin; |
\. |
-- |
-- Data for Name: logs; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY logs (id, "timestamp", table_name, old_value, new_value, id_anagrafiche, field, id_record) FROM stdin; |
\. |
-- |
-- Data for Name: messages; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY messages (id, message, owner, modification_time, transmission_time) FROM stdin; |
\. |
-- |
-- Data for Name: messages_users; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY messages_users (id, id_messages, id_anagrafiche, notification_time) FROM stdin; |
\. |
-- |
-- Data for Name: recordset; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY recordset (id, id_anagrafiche, name, size, block, query_numrec, query_records, query_where, query_find_records) FROM stdin; |
\. |
-- |
-- Data for Name: recordset_rows; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY recordset_rows (id, id_recordset, num_row, id_record) FROM stdin; |
\. |
-- |
-- Data for Name: report_id; Type: TABLE DATA; Schema: public; Owner: postgres |
-- |
COPY report_id (id, key, group_id) FROM stdin; |
\. |
-- |
-- Name: anagrafiche_gruppi_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY anagrafiche_gruppi |
ADD CONSTRAINT anagrafiche_gruppi_pkey PRIMARY KEY (id); |
-- |
-- Name: anagrafiche_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY anagrafiche |
ADD CONSTRAINT anagrafiche_pkey PRIMARY KEY (id); |
-- |
-- Name: autorizzazioni_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY autorizzazioni |
ADD CONSTRAINT autorizzazioni_pkey PRIMARY KEY (id); |
-- |
-- Name: funzioni_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY funzioni |
ADD CONSTRAINT funzioni_pkey PRIMARY KEY (id); |
-- |
-- Name: gruppi_funzioni_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY gruppi_funzioni |
ADD CONSTRAINT gruppi_funzioni_pkey PRIMARY KEY (id); |
-- |
-- Name: gruppi_modifica_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY gruppi_modifica |
ADD CONSTRAINT gruppi_modifica_pkey PRIMARY KEY (id); |
-- |
-- Name: gruppi_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY gruppi |
ADD CONSTRAINT gruppi_pkey PRIMARY KEY (id); |
-- |
-- Name: id_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY messages_users |
ADD CONSTRAINT id_pkey PRIMARY KEY (id); |
-- |
-- Name: logs_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY logs |
ADD CONSTRAINT logs_pkey PRIMARY KEY (id); |
-- |
-- Name: messages_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY messages |
ADD CONSTRAINT messages_pkey PRIMARY KEY (id); |
-- |
-- Name: recordset_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY recordset |
ADD CONSTRAINT recordset_pkey PRIMARY KEY (id); |
-- |
-- Name: recordset_rows_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY recordset_rows |
ADD CONSTRAINT recordset_rows_pkey PRIMARY KEY (id); |
-- |
-- Name: report_id_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres; Tablespace: |
-- |
ALTER TABLE ONLY report_id |
ADD CONSTRAINT report_id_pkey PRIMARY KEY (id); |
-- |
-- Name: anagrafiche_id_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX anagrafiche_id_idx ON recordset USING btree (id_anagrafiche); |
-- |
-- Name: fki_logs_id_anagrafiche; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX fki_logs_id_anagrafiche ON logs USING btree (id_anagrafiche); |
-- |
-- Name: fki_recordset_anagrafiche; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX fki_recordset_anagrafiche ON recordset USING btree (id_anagrafiche); |
-- |
-- Name: fki_recordset_rows; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX fki_recordset_rows ON recordset_rows USING btree (id_recordset); |
-- |
-- Name: logs_id_anagrafiche; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX logs_id_anagrafiche ON logs USING btree (id_anagrafiche); |
-- |
-- Name: logs_table; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX logs_table ON logs USING btree (table_name); |
-- |
-- Name: logs_timestamp; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX logs_timestamp ON logs USING btree ("timestamp"); |
-- |
-- Name: messages_date; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX messages_date ON messages USING btree (modification_time); |
-- |
-- Name: messages_owner; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX messages_owner ON messages USING btree (owner); |
-- |
-- Name: messages_users_id_anagrafiche; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX messages_users_id_anagrafiche ON messages_users USING btree (id_anagrafiche); |
-- |
-- Name: messages_users_id_messages; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX messages_users_id_messages ON messages_users USING btree (id_messages); |
-- |
-- Name: messages_users_notification_time; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX messages_users_notification_time ON messages_users USING btree (notification_time); |
-- |
-- Name: prefix_idx; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX prefix_idx ON recordset USING btree (name); |
-- |
-- Name: recordset_rows_id_record; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX recordset_rows_id_record ON recordset_rows USING btree (id_record); |
-- |
-- Name: recordset_rows_id_recordset; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX recordset_rows_id_recordset ON recordset_rows USING btree (id_recordset); |
-- |
-- Name: recordset_rows_num_row; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE INDEX recordset_rows_num_row ON recordset_rows USING btree (num_row); |
-- |
-- Name: recordset_rows_unique; Type: INDEX; Schema: public; Owner: postgres; Tablespace: |
-- |
CREATE UNIQUE INDEX recordset_rows_unique ON recordset_rows USING btree (id_recordset, id_record); |
-- |
-- Name: anagrafiche_gruppi_id_anagrafiche; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY anagrafiche_gruppi |
ADD CONSTRAINT anagrafiche_gruppi_id_anagrafiche FOREIGN KEY (id_anagrafiche) REFERENCES anagrafiche(id) ON UPDATE RESTRICT ON DELETE CASCADE; |
-- |
-- Name: anagrafiche_gruppi_id_gruppi; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY anagrafiche_gruppi |
ADD CONSTRAINT anagrafiche_gruppi_id_gruppi FOREIGN KEY (id_gruppi) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE CASCADE; |
-- |
-- Name: gruppi_funzioni_id_autorizzazioni; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY gruppi_funzioni |
ADD CONSTRAINT gruppi_funzioni_id_autorizzazioni FOREIGN KEY (id_autorizzazioni) REFERENCES autorizzazioni(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: gruppi_funzioni_id_funzioni; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY gruppi_funzioni |
ADD CONSTRAINT gruppi_funzioni_id_funzioni FOREIGN KEY (id_funzioni) REFERENCES funzioni(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: gruppi_funzioni_id_gruppi; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY gruppi_funzioni |
ADD CONSTRAINT gruppi_funzioni_id_gruppi FOREIGN KEY (id_gruppi) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: gruppi_modifica_id_gruppo; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY gruppi_modifica |
ADD CONSTRAINT gruppi_modifica_id_gruppo FOREIGN KEY (id_gruppo) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: gruppi_modifica_id_gruppo_modifica; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY gruppi_modifica |
ADD CONSTRAINT gruppi_modifica_id_gruppo_modifica FOREIGN KEY (id_gruppo_modifica) REFERENCES gruppi(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: logs_id_anagrafiche; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY logs |
ADD CONSTRAINT logs_id_anagrafiche FOREIGN KEY (id_anagrafiche) REFERENCES anagrafiche(id) ON UPDATE RESTRICT ON DELETE RESTRICT; |
-- |
-- Name: messages_users_messages; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY messages_users |
ADD CONSTRAINT messages_users_messages FOREIGN KEY (id_messages) REFERENCES messages(id) ON UPDATE RESTRICT ON DELETE CASCADE; |
-- |
-- Name: recordset_anagrafiche; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY recordset |
ADD CONSTRAINT recordset_anagrafiche FOREIGN KEY (id_anagrafiche) REFERENCES anagrafiche(id) ON DELETE CASCADE; |
-- |
-- Name: recordset_rows; Type: FK CONSTRAINT; Schema: public; Owner: postgres |
-- |
ALTER TABLE ONLY recordset_rows |
ADD CONSTRAINT recordset_rows FOREIGN KEY (id_recordset) REFERENCES recordset(id) ON DELETE CASCADE; |
-- |
-- Name: public; Type: ACL; Schema: -; Owner: postgres |
-- |
REVOKE ALL ON SCHEMA public FROM PUBLIC; |
REVOKE ALL ON SCHEMA public FROM postgres; |
GRANT ALL ON SCHEMA public TO postgres; |
GRANT USAGE ON SCHEMA public TO PUBLIC; |
-- |
-- Name: anagrafiche; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE anagrafiche FROM PUBLIC; |
REVOKE ALL ON TABLE anagrafiche FROM postgres; |
GRANT ALL ON TABLE anagrafiche TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE anagrafiche TO masonsql; |
GRANT SELECT ON TABLE anagrafiche TO report; |
-- |
-- Name: anagrafiche_gruppi; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE anagrafiche_gruppi FROM PUBLIC; |
REVOKE ALL ON TABLE anagrafiche_gruppi FROM postgres; |
GRANT ALL ON TABLE anagrafiche_gruppi TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE anagrafiche_gruppi TO masonsql; |
GRANT SELECT ON TABLE anagrafiche_gruppi TO report; |
-- |
-- Name: anagrafiche_gruppi_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE anagrafiche_gruppi_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE anagrafiche_gruppi_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE anagrafiche_gruppi_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE anagrafiche_gruppi_id_seq TO masonsql; |
-- |
-- Name: anagrafiche_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE anagrafiche_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE anagrafiche_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE anagrafiche_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE anagrafiche_id_seq TO masonsql; |
-- |
-- Name: autorizzazioni; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE autorizzazioni FROM PUBLIC; |
REVOKE ALL ON TABLE autorizzazioni FROM postgres; |
GRANT ALL ON TABLE autorizzazioni TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE autorizzazioni TO masonsql; |
GRANT SELECT ON TABLE autorizzazioni TO report; |
-- |
-- Name: autorizzazioni_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE autorizzazioni_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE autorizzazioni_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE autorizzazioni_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE autorizzazioni_id_seq TO masonsql; |
-- |
-- Name: funzioni; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE funzioni FROM PUBLIC; |
REVOKE ALL ON TABLE funzioni FROM postgres; |
GRANT ALL ON TABLE funzioni TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE funzioni TO masonsql; |
GRANT SELECT ON TABLE funzioni TO report; |
-- |
-- Name: funzioni_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE funzioni_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE funzioni_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE funzioni_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE funzioni_id_seq TO masonsql; |
-- |
-- Name: gruppi; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE gruppi FROM PUBLIC; |
REVOKE ALL ON TABLE gruppi FROM postgres; |
GRANT ALL ON TABLE gruppi TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE gruppi TO masonsql; |
GRANT SELECT ON TABLE gruppi TO report; |
-- |
-- Name: gruppi_and_anagrafiche; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE gruppi_and_anagrafiche FROM PUBLIC; |
REVOKE ALL ON TABLE gruppi_and_anagrafiche FROM postgres; |
GRANT ALL ON TABLE gruppi_and_anagrafiche TO postgres; |
GRANT SELECT ON TABLE gruppi_and_anagrafiche TO report; |
GRANT SELECT ON TABLE gruppi_and_anagrafiche TO masonsql; |
-- |
-- Name: gruppi_funzioni; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE gruppi_funzioni FROM PUBLIC; |
REVOKE ALL ON TABLE gruppi_funzioni FROM postgres; |
GRANT ALL ON TABLE gruppi_funzioni TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE gruppi_funzioni TO masonsql; |
GRANT SELECT ON TABLE gruppi_funzioni TO report; |
-- |
-- Name: gruppi_funzioni_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE gruppi_funzioni_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE gruppi_funzioni_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE gruppi_funzioni_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE gruppi_funzioni_id_seq TO masonsql; |
-- |
-- Name: gruppi_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE gruppi_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE gruppi_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE gruppi_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE gruppi_id_seq TO masonsql; |
-- |
-- Name: gruppi_modifica; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE gruppi_modifica FROM PUBLIC; |
REVOKE ALL ON TABLE gruppi_modifica FROM postgres; |
GRANT ALL ON TABLE gruppi_modifica TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE gruppi_modifica TO masonsql; |
GRANT SELECT ON TABLE gruppi_modifica TO report; |
-- |
-- Name: gruppi_modifica_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE gruppi_modifica_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE gruppi_modifica_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE gruppi_modifica_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE gruppi_modifica_id_seq TO masonsql; |
-- |
-- Name: logs; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE logs FROM PUBLIC; |
REVOKE ALL ON TABLE logs FROM postgres; |
GRANT ALL ON TABLE logs TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE logs TO masonsql; |
GRANT SELECT ON TABLE logs TO report; |
-- |
-- Name: logs_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE logs_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE logs_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE logs_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE logs_id_seq TO masonsql; |
-- |
-- Name: messages; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE messages FROM PUBLIC; |
REVOKE ALL ON TABLE messages FROM postgres; |
GRANT ALL ON TABLE messages TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE messages TO masonsql; |
GRANT SELECT ON TABLE messages TO report; |
-- |
-- Name: messages_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE messages_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE messages_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE messages_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE messages_id_seq TO masonsql; |
-- |
-- Name: messages_users; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE messages_users FROM PUBLIC; |
REVOKE ALL ON TABLE messages_users FROM postgres; |
GRANT ALL ON TABLE messages_users TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE messages_users TO masonsql; |
GRANT SELECT ON TABLE messages_users TO report; |
-- |
-- Name: messages_users_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE messages_users_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE messages_users_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE messages_users_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE messages_users_id_seq TO masonsql; |
-- |
-- Name: recordset; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE recordset FROM PUBLIC; |
REVOKE ALL ON TABLE recordset FROM postgres; |
GRANT ALL ON TABLE recordset TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE recordset TO masonsql; |
-- |
-- Name: recordset_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE recordset_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE recordset_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE recordset_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE recordset_id_seq TO masonsql; |
-- |
-- Name: recordset_rows; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE recordset_rows FROM PUBLIC; |
REVOKE ALL ON TABLE recordset_rows FROM postgres; |
GRANT ALL ON TABLE recordset_rows TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE recordset_rows TO masonsql; |
-- |
-- Name: recordset_rows_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE recordset_rows_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE recordset_rows_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE recordset_rows_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE recordset_rows_id_seq TO masonsql; |
-- |
-- Name: report_id; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON TABLE report_id FROM PUBLIC; |
REVOKE ALL ON TABLE report_id FROM postgres; |
GRANT ALL ON TABLE report_id TO postgres; |
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE report_id TO masonsql; |
GRANT SELECT ON TABLE report_id TO report; |
-- |
-- Name: report_id_id_seq; Type: ACL; Schema: public; Owner: postgres |
-- |
REVOKE ALL ON SEQUENCE report_id_id_seq FROM PUBLIC; |
REVOKE ALL ON SEQUENCE report_id_id_seq FROM postgres; |
GRANT ALL ON SEQUENCE report_id_id_seq TO postgres; |
GRANT SELECT,UPDATE ON SEQUENCE report_id_id_seq TO masonsql; |
-- |
-- PostgreSQL database dump complete |
-- |
CREATE TABLE logs_report |
( |
id integer NOT NULL DEFAULT nextval(('logs_report_seq'::text)::regclass), -- Primary key |
"timestamp" timestamp without time zone NOT NULL, -- Data e ora della modifica |
table_name character varying(63) NOT NULL, -- Nome della tabella |
report character varying(64000), -- Riepilogo delle variazioni |
id_anagrafiche integer, -- Utente responsabile della modifica |
id_record integer NOT NULL, -- ID record modificato |
CONSTRAINT logs_report_pkey PRIMARY KEY (id ), |
CONSTRAINT logs_report_id_anagrafiche FOREIGN KEY (id_anagrafiche) |
REFERENCES anagrafiche (id) MATCH SIMPLE |
ON UPDATE RESTRICT ON DELETE RESTRICT |
) |
WITH ( |
OIDS=FALSE |
); |
ALTER TABLE logs_report |
OWNER TO postgres; |
GRANT ALL ON TABLE logs_report TO postgres; |
GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE logs_report TO masonsql; |
GRANT SELECT ON TABLE logs_report TO report; |
COMMENT ON TABLE logs_report IS 'Report delle operazioni di variazione dei dati effettuati dall''interfaccia Web'; |
COMMENT ON COLUMN logs_report.id IS 'Primary key'; |
COMMENT ON COLUMN logs_report."timestamp" IS 'Data e ora della modifica'; |
COMMENT ON COLUMN logs_report.table_name IS 'Nome della tabella'; |
COMMENT ON COLUMN logs_report.report IS 'Riepilogo delle variazioni'; |
COMMENT ON COLUMN logs_report.id_anagrafiche IS 'Utente responsabile della modifica'; |
COMMENT ON COLUMN logs_report.id_record IS 'ID record modificato'; |
-- Index: logs_report_id_anagrafiche |
-- DROP INDEX logs_report_id_anagrafiche; |
CREATE INDEX logs_report_id_anagrafiche |
ON logs_report |
USING btree |
(id_anagrafiche ); |
-- Index: logs_report_id_record |
-- DROP INDEX logs_report_id_record; |
CREATE INDEX logs_report_id_record |
ON logs_report |
USING btree |
(id_record ); |
-- Index: logs_report_table |
-- DROP INDEX logs_report_table; |
CREATE INDEX logs_report_table |
ON logs_report |
USING btree |
(table_name ); |
-- Index: logs_report_timestamp |
-- DROP INDEX logs_report_timestamp; |
CREATE INDEX logs_report_timestamp |
ON logs_report |
USING btree |
("timestamp" ); |
GRANT SELECT ON TABLE funzioni TO report; |
GRANT SELECT ON TABLE gruppi_funzioni TO report; |
GRANT SELECT ON TABLE autorizzazioni TO report; |
/tags/2.0/utility/sql/backuppc_cmd |
---|
0,0 → 1,109 |
#!/bin/bash |
# Utility per effettuare il backup di PostgreSQL con BackupPC ( http://backuppc.sourceforge.net/ ) |
# |
# Data del backup |
DATE="$(date +%Y-%m-%d)" |
# Esce immediatamente in caso di errore |
set -e |
# Versione del database |
PSQL_VER="$1" |
# Comando Pre / Post |
CMD="$2" |
if [ "$CMD" != "Pre" -a "$CMD" != "Post" ] |
then |
echo "ERROR: Command '$CMD' is not 'Pre' or 'Post'." >&2 |
exit 2 |
fi |
# Cartella base dell'archivio PostgreSQL |
PSQL_DIR="/var/lib/postgresql/$PSQL_VER" |
if [ ! -d "$PSQL_DIR" ] |
then |
echo "ERROR: Directory $PSQL_DIR inexistent." >&2 |
exit 1 |
fi |
if [ ! -d "$PSQL_DIR/archive" ] |
then |
mkdir "$PSQL_DIR/archive" |
chown postgres.postgres "$PSQL_DIR/archive" |
chmod 700 "$PSQL_DIR/archive" |
fi |
# tolgo l'eventuale "/" in fondo al nome della share |
SHARE="${3%/}" |
# Lanciato da BackuPC con la seguente configurazione |
# $Conf{BackupFilesExclude} = { |
# '/var/lib/postgresql/$PSQL_VER/main' => [ |
# '/pg_xlog/', |
# '/postmaster.opts', |
# '/postmaster.pid' |
# ], |
# '/' => [ |
# '/var/lib/postgresql/$PSQL_VER/' |
# ] |
# }; |
# $Conf{RsyncShareName} = [ |
# '/', |
# '/var/lib/postgresql/$PSQL_VER/main', |
# '/var/lib/postgresql/$PSQL_VER/archive' |
# ]; |
# $Conf{DumpPreShareCmd} = '$sshPath -q -x -l root $host /opt/masonsql/utility/sql/backuppc_cmd $PSQL_VER Pre $share'; |
# $Conf{DumpPostShareCmd} = '$sshPath -q -x -l root $host /opt/masonsql/utility/sql/backuppc_cmd $PSQL_VER Post $share'; |
# |
# Da creare |
# mkdir /var/lib/postgresql/$PSQL_VER/archive |
# chown postgres.postgres /var/lib/postgresql/$PSQL_VER/archive |
# chmod 700 /var/lib/postgresql/$PSQL_VER/archive |
# Configurazione nel file /etc/postgresql/$PSQL_VER/main/postgresql.conf |
# wal_level = archive |
# archive_command = 'test ! -f /var/lib/postgresql/$PSQL_VER/backup_in_progress || (test ! -f /var/lib/postgresql/$PSQL_VER/archive/%f && cp %p /var/lib/postgresql/$PSQL_VER/archive/%f)' |
# archive_mode = on |
# Da eseguire dopo modifica file: |
# /etc/init.d/postgresql restart |
# |
# See: http://www.postgresql.org/docs/$PSQL_VER/static/continuous-archiving.html |
# |
# Ripristino |
# Dopo aver recuperato gli archivi: |
# Togliere eventuali file da /var/lib/postgresql/$PSQL_VER/main/pg_xlog/ |
# Verificare che non esista il file /var/lib/postgresql/$PSQL_VER/backup_in_progress - se esiste vuol dire che l'ultimo backup |
# ha avuto problemi, quindi verificare i log in backuppc! |
# Se non ci sono problemi: |
# Copiare i file da /var/lib/postgresql/$PSQL_VER/archive/* a /var/lib/postgresql/$PSQL_VER/main/pg_xlog/ |
# Modificare pg_hba.conf per impedire l'accesso agli utenti |
# Copiare /usr/share/postgresql/$PSQL_VER/recovery.conf.sample in /var/lib/postgresql/$PSQL_VER/main/recovery.conf |
# Modificare la riga: |
# restore_command = 'cp /var/lib/postgresql/$PSQL_VER/archive/%f %p' |
# Lanciare postgresql e attendere il ripristino (il file recovery.conf viere rinominato in recovery.done) |
# Verificare il contenuto del database |
# Ripristinare gli accessi in pg_hba.conf e rilanciare il server |
# |
# Share del database |
if [ "$SHARE" = "$PSQL_DIR/main" ] |
then |
cd "$PSQL_DIR" |
if [ "$CMD" = "Pre" ] |
then |
touch $PSQL_DIR/backup_in_progress |
echo "SELECT pg_start_backup('BackupPC_${DATE}');" | su -c 'psql postgres' postgres |
fi |
if [ "$CMD" = "Post" ] |
then |
rm $PSQL_DIR/backup_in_progress |
echo "SELECT pg_stop_backup();" | su -c 'psql postgres' postgres |
fi |
fi |
# Cancello i file archivio dopo averli copianti nella share .../archive |
if [ "$SHARE" = "$PSQL_DIR/archive" -a "$CMD" = "Post" -a ! -f $PSQL_DIR/backup_in_progress ] |
then |
rm $PSQL_DIR/archive/* |
fi |
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |
/tags/2.0/utility/sql/roles.sql |
---|
0,0 → 1,5 |
-- Utenti utilizzati nel framework |
CREATE ROLE masonsql LOGIN PASSWORD '<password>' NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE; |
CREATE ROLE report LOGIN PASSWORD '<password>' NOSUPERUSER INHERIT NOCREATEDB NOCREATEROLE; |
/tags/2.0/utility/sql/create_database.sql |
---|
0,0 → 1,2 |
-- Creazione del database per il framework MasonSql |
create database masonsql ENCODING = 'UTF8' LC_COLLATE = 'it_IT.UTF-8' LC_CTYPE = 'it_IT.UTF-8' TEMPLATE=template0; |
/tags/2.0/utility/UpiPrinterServer/UpiPrinterServer.pl |
---|
0,0 → 1,451 |
# Copyright 2007 Guido Brugnara <gdo@leader.it> |
# |
# Il programma è distribuito con licenza duale: |
# Commerciale oppure GPL (http://www.gnu.org/copyleft/gpl.html). |
# |
# L'autore è disponibile ad integrare le modifiche proposte da Terzi solo se il |
# contributo viene rilasciato con licenza Perl Artistic Licence al fine di |
# garantire all'autore la possibilità di applicare la licenza duale alla nuova |
# versione. |
my $release = '0.15'; |
$|=1; |
use Win32; |
use Win32::Daemon; |
use Win32::EventLog; |
use Win32::TieRegistry; |
use IO::Select; |
use URI::Escape; |
use LWP::UserAgent; |
use HTML::Entities; |
use HTTP::Status; |
use HTTP::Daemon::SSL; |
use Win32::Printer::Direct; |
use Win32::Printer::Enum; |
my %print_errors = ( |
-1 => 'Memory allocation error', |
-2 => 'Error opening the file', |
-3 => 'Error opening the printer', |
-4 => 'Error startint the print job', |
-5 => 'Error writing to printer', |
-6 => 'Error ending the print job', |
-7 => 'Error closing printer' |
); |
use Data::Dumper; |
use File::Temp qw(tempfile); |
my $nameService = 'UpiPrinterServer'; |
# Nome del server HTTP che viene inviato al client |
sub HTTP::Daemon::product_tokens { |
"$nameService Rel:$release"; |
} |
# Chiave di registry del servizio |
$RegistryKeyName = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\$nameService"; |
# nome della stampante di default |
$DefaultPrinterName = ''; |
# path file certificati |
$CertsPath = ''; |
my $PORTNO = 22000; # porta di ascolto del server HTTPS |
my $LOOP_PERIOD = 20; # millisecondi di intervallo per la verifica di chiamate pendenti |
my $COUNT=0; # conteggio delle chiamate |
# invio i messaggi di errore e warn al file Log di Windows |
use Win32::EventLog::Carp { Source => $nameService }; |
my $Select = IO::Select->new(); |
# cartella certificati nello stesso percorso dell'eseguibile |
$CertsDefaultDir = $0; |
$CertsDefaultDir =~ s/[^\\]*$//; |
$CertsDefaultDir .= 'certs'; |
if($ARGV[0] eq '-install'){ |
use Win32::GUI::Carp 'warningsToDialog'; |
# visualizza immediatamente il warning |
$Win32::GUI::Carp::ImmediateWarnings = 1; |
%Hash = ( |
machine => '', |
name => $nameService, |
display => 'UPI Printer Server', |
path => $^X, |
user => '', |
pwd => '', |
description => 'Server stampa via HTTPS', |
parameters =>"\"$0\"", |
); |
if($0 =~ m/\.exe/i){ |
$Hash{'path'} = $0; |
$Hash{'parameters'} = ''; |
} |
if(Win32::Daemon::CreateService(\%Hash)){ |
# modifico nel Registry la configurazione del servizio |
my $RegistryKeyService = new Win32::TieRegistry $RegistryKeyName or die "Can't access $RegistryKeyName key: $^E\n"; |
# con 0x110 l'applicazione può interagire con il desktop |
$RegistryKeyService->SetValue('Type', '0x010', REG_DWORD) or die "Error on set Type entry: $^E\n"; |
# imposto la chiave per la stampate di default |
$RegistryKeyService->SetValue('DefaultPrinterName', '', REG_SZ) or die "Error on set DefaultPrinterName entry: $^E\n"; |
# chiave percorso certificati |
my $CertsDir = $ARGV[1] eq '-certs' ? $ARGV[2] : $CertsDefaultDir; |
$RegistryKeyService->SetValue('CertsPath', $CertsDir, REG_SZ) or die "Error on set CertsPath entry: $^E\n"; |
# lancio il servizio |
use Win32::Service; |
Win32::Service::StartService('', $nameService); |
warn "Servizio $nameService attivato!\n"; |
}else{ |
warn "Attivazione servizio $nameService fallito!:\n" . Win32::FormatMessage( Win32::Daemon::GetLastError() ) . "\n"; |
} |
exit; |
}elsif($ARGV[0] eq '-remove'){ |
use Win32::GUI::Carp 'warningsToDialog'; |
# visualizza immediatamente il warning |
$Win32::GUI::Carp::ImmediateWarnings = 1; |
my $name = $nameService; |
# fermo il servizio prima di disinstallarlo |
use Win32::Service; |
Win32::Service::StopService('', $nameService); |
if( Win32::Daemon::DeleteService('', $name ) ) { |
warn "Servizio $nameService disinstallato.\n"; |
} else { |
warn "Disattivazione servizio $nameService fallito:\n" . Win32::FormatMessage( Win32::Daemon::GetLastError() ) . "\n"; |
} |
exit; |
}elsif($ARGV[0] eq '-debug'){ |
# esecuzione demone da riga di comando (si presuppone che i parametri nel registry siano presenti) |
InitVariables(); |
openHTTPS(); |
while(1){ |
runningHTTPS(); |
} |
closeHTTPS(); |
exit; |
} |
# EVENTLOG_ERROR_TYPE: An Error event is being logged. |
# EVENTLOG_WARNING_TYPE: A Warning event is being logged. |
# EVENTLOG_INFORMATION_TYPE: An Information event is being logged. |
# |
sub Log($;$) { |
my ($mess,$type) = @_; |
defined $type or $type = EVENTLOG_INFORMATION_TYPE; |
my $EventLog = new Win32::EventLog( $nameService ) || die $!; |
$EventLog->Report({ EventType => $type, |
Strings => $mess, |
}) || die $!; |
} |
# MB_ICONSTOP "X" in a red circle |
# MB_ICONQUESTION question mark in a bubble |
# MB_ICONEXCLAMATION exclamation mark in a yellow triangle |
# MB_ICONINFORMATION "i" in a bubble |
# |
sub Die($;$){ |
my ($mess, $type) = @_; |
Log $mess; |
AlertFork $mess, $type; |
die $mess."\n"; |
} |
sub Alert($;$){ |
my ($mess, $type) = @_; |
defined $type or $type = MB_ICONEXCLAMATION; |
Log $mess; |
Win32::MsgBox($mess, $type, $nameService); |
} |
sub AlertFork($;$){ |
my ($mess, $type) = @_; |
defined $type or $type = MB_ICONEXCLAMATION; |
if(!defined(my $pid = fork)){ |
Win32::MsgBox("Error to start kild process", MB_ICONEXCLAMATION, "UPI Printer Server"); |
die "Error to start kild process"; |
}else{ |
if($pid == 0){ |
# processo figlio |
Alert($mess, $type); |
exit; |
} |
} |
} |
sub openHTTPS(){ |
my $SSL_key_file = $CertsPath.'\server-key.pem'; |
my $SSL_cert_file = $CertsPath.'\server-cert.pem'; |
# verifico la presenza dei certificati |
if(! -e $SSL_key_file){ |
Die "File $SSL_key_file don't exist\n"; |
} |
if(! -e $SSL_cert_file){ |
Die "File $SSL_cert_file don't exist\n"; |
} |
my $daemon = new HTTP::Daemon::SSL( |
LocalAddr => '127.0.0.1', |
SSL_key_file => $SSL_key_file, |
SSL_cert_file => $SSL_cert_file, |
LocalPort => $PORTNO |
); |
if(!$daemon){ |
Die("HTTPS server: error on open [$@]\n"); |
} |
$Select->add($daemon); |
Log "Start local HTTPS server on port $PORTNO\n"; |
} |
sub closeHTTPS(){ |
for my $daemon ($Select->handles){ |
$Select->remove($daemon); |
undef $daemon; |
} |
Log "Stop local HTTPS server on port $PORTNO\n"; |
} |
sub runningHTTPS(){ |
if(my @ready = $Select->can_read(int($LOOP_PERIOD * 0.1))){ |
foreach my $daemon (@ready){ |
$COUNT++; |
if(my $connect = $daemon->accept){ |
$connect->autoflush(1); |
my $from = $connect->peerhost; |
if($from ne '127.0.0.1'){ |
# solo le chiamate locali vengono accettate |
$connect->send_error(RC_FORBIDDEN); |
}else{ |
my $request = $connect->get_request(1); |
if(!$request){ |
# in IE con SSL alla richiesta del certificato non attendibile non è definito l'oggetto request |
next; |
} |
my $url = $request->url; #->path; |
my $content = $request->content; |
my $method = $request->method; |
if($url =~ m|^/printers$|i || $url =~ m|^/set_default/.*|i || $url =~ m|^/$|){ |
if($url =~ m|^/set_default/(.*)|i){ |
$DefaultPrinterName = uri_unescape($1); |
# imposto la chiave per la stampate di default |
my $RegistryKeyService = new Win32::TieRegistry $RegistryKeyName or die "Can't access $RegistryKeyName key: $^E\n"; |
$RegistryKeyService->SetValue('DefaultPrinterName', $DefaultPrinterName, REG_SZ) or die "Error on set DefaultPrinterName entry: $^E\n"; |
undef $RegistryKeyService; |
} |
my $message = qq| |
<html> |
<head><title>UPI Printer Server - Lista stampanti disponibili</title></head> |
<body> |
<h1>UPI Printer Server</h1> |
<h2>Lista stampanti disponibili</h2> |
<p>Selezionare la stampante che si desidera venga utilizzata (<cite>default</cite>):</p> |
<ul> |
|; |
my @printers = Printers(); |
foreach my $printer (@printers){ |
$message .= '<li><A href="/set_default/' . uri_escape($printer->{PrinterName}) . '">' |
. encode_entities($printer->{PrinterName}) . "</A></li>\n"; |
} |
$message .= qq| |
</ul> |
<p>Attuale stampante selezionata (<cite>default</cite>): <b>| . |
encode_entities($DefaultPrinterName) . q|</b></p> |
</body> |
<script> |
//document.domain = 'leader.it'; |
</script> |
</html> |
|; |
$message =~ s/^\s+//m; |
my $response = HTTP::Response->new(RC_OK, 'List printers'); |
$response->header( 'Content-Type' => 'text/html'); |
$response->content($message); |
$connect->send_response($response); |
}elsif($url =~ m|^/print/(.*)|i || $url =~ m|^/print$|i){ |
my $printer_name = $1 ? uri_unescape($1) : $DefaultPrinterName; |
if($printer_name){ |
if($request->method eq 'POST'){ |
my ($fh, $file_name) = tempfile(); |
# copio dal buffer nel file temporaneo. |
print $fh $request->content; |
close $fh; |
my $err = Printfile($printer_name, $file_name); |
if($err == 1){ |
my $response = HTTP::Response->new(RC_ACCEPT, 'Print OK'); |
$response->header( 'Content-Type' => 'text/plain'); |
$response->content('Print OK'); |
$connect->send_response($response); |
}else{ |
$connect->send_error(RC_INTERNAL_SERVER_ERROR, "Print to $printer_name with error $err: $print_errors{$err}") |
} |
}else{ |
$connect->send_error(RC_METHOD_NOT_ALLOWED, 'Only POST method is allowed'); |
} |
}else{ |
$connect->send_error(RC_NOT_FOUND, 'No default printer'); |
} |
}elsif($url =~ m|^/from_server/([\w\.]+)/(\w+)/(.+)$|i || $url =~ m|^/from_server/([\w\.]+)/(\w+)|i){ |
my $file = $2; |
my $URL = "https://$1/UpiPrinterServer.txt?file=$file"; |
my $printer_name = $3 ? uri_unescape($3) : $DefaultPrinterName; |
if($printer_name){ |
# effettuo la chiamata indicata |
my $user_agent = LWP::UserAgent->new; |
$user_agent->agent($daemon->product_tokens); |
$user_agent->timeout(5); |
my $user_request = HTTP::Request->new(GET => $URL); |
my $user_response = $user_agent->request($user_request); |
if($user_response->is_success){ |
my ($fh, $file_name) = tempfile(); |
# copio dal buffer nel file temporaneo. |
print $fh $user_response->content; |
close $fh; |
my $err = Printfile($printer_name, $file_name); |
if($err == 1){ |
$connect->send_response(Response('printed', "File $file printed to $printer_name")); |
}else{ |
my $code = -$err; |
$connect->send_response(Response("print_err_$code", "Print to $printer_name with error $err: $print_errors{$err}")); |
} |
}else{ |
$connect->send_response(Response('remote_err_'.$user_response->code, 'Remote server error: '.$user_response->status_line."\n")); |
} |
}else{ |
$connect->send_response(Response('no_print_default', 'No default printer is selected')); |
} |
}else{ |
$connect->send_error(RC_NOT_FOUND, 'Command mismatch'); |
} |
} |
$connect->close; |
}else{ |
Log "Error to connect: $@\n"; |
} |
} |
} |
} |
# prepara la risposta da inviare |
sub Response($$){ |
my($status, $status_mess) = @_; |
$status =~ s/'/\\'/sg; |
$status_mess =~ s/'/\\'/sg; |
$status_mess =~ s/\n/\\n/sg; |
my $response = HTTP::Response->new(RC_ACCEPT, 'Print OK'); |
$response->header( 'Content-Type' => 'text/plain'); |
$response->content(qq| |
if(UpiPrinterServerHandler){ |
UpiPrinterServerHandler('$status', '$status_mess'); |
}else{ |
alert('printed!\\nFile $file printed to $printer_name'); |
} |
|); |
return $response; |
} |
#---------------------------------------------- Callbacks |
sub Callback_Running { |
my( $Event, $Context ) = @_; |
# Note that here you want to check that the state |
# is indeed SERVICE_RUNNING. Even though the Running |
# callback is called it could have done so before |
# calling the "Start" callback. |
if( SERVICE_RUNNING == Win32::Daemon::State() ) |
{ |
# ... process your main stuff here... |
# ... note that here there is no need to |
# change the state |
# AlertFork('Running '.$count++.' ...'); |
runningHTTPS(); |
# AlertFork("Running $count."); |
} |
} |
sub InitVariables(){ |
# impostazione stampate di default |
my $RegistryKeyService = new Win32::TieRegistry $RegistryKeyName or die "Can't access $RegistryKeyName key: $^E\n"; |
$DefaultPrinterName = $RegistryKeyService->GetValue('DefaultPrinterName'); |
# Path cartella dei certificati |
$CertsPath = $RegistryKeyService->GetValue('CertsPath'); |
undef $RegistryKeyService; |
} |
sub Callback_Start { |
my( $Event, $Context ) = @_; |
# Initialization code |
# ...do whatever you need to do to start... |
#AlertFork('Callback_Start ...'); |
InitVariables(); |
openHTTPS(); |
$Context->{last_state} = SERVICE_RUNNING; |
Win32::Daemon::State( SERVICE_RUNNING ); |
#AlertFork('Callback_Start.'); |
} |
sub Callback_Pause { |
my( $Event, $Context ) = @_; |
#AlertFork('Callback_Pause ...'); |
closeHTTPS(); |
$Context->{last_state} = SERVICE_PAUSED; |
Win32::Daemon::State( SERVICE_PAUSED ); |
#AlertFork('Callback_Pause.'); |
} |
sub Callback_Continue { |
my( $Event, $Context ) = @_; |
#AlertFork('Callback_Continue ...'); |
openHTTPS(); |
$Context->{last_state} = SERVICE_RUNNING; |
Win32::Daemon::State( SERVICE_RUNNING ); |
#AlertFork('Callback_Continue.'); |
} |
sub Callback_Stop { |
my( $Event, $Context ) = @_; |
#AlertFork('Callback_Stop ...'); |
closeHTTPS(); |
$Context->{last_state} = SERVICE_STOPPED; |
Win32::Daemon::State( SERVICE_STOPPED ); |
# We need to notify the Daemon that we want to stop callbacks and the service. |
Win32::Daemon::StopService(); |
#AlertFork('Callback_Stop.'); |
} |
Win32::Daemon::RegisterCallbacks( { |
start => \&Callback_Start, |
running => \&Callback_Running, |
stop => \&Callback_Stop, |
pause => \&Callback_Pause, |
continue => \&Callback_Continue, |
} ); |
%Context = ( |
last_state => SERVICE_STOPPED, |
start_time => time(), |
); |
if(! defined $ENV{'USERNAME'}){ |
Win32::Daemon::StartService(undef, $LOOP_PERIOD); |
}else{ |
warn qq| |
Utilizzare il parametro -install per installare il servizio |
oppure -remove per disinstallarlo. |
Aggiungere una seconda opzione [-certs <percorso>] per |
indicare la cartella contenente i certificati SSL del server |
(default: $CertsDefaultDir) |
In caso di errore è possibile lanciare il server con l'opzione |
[-debug] da riga di comando (si presuppone che il servizio |
sia installato e che i parametri siano stati configurati nel |
registry). |
|; |
} |
exit; |
/tags/2.0/utility/UpiPrinterServer/INSTALLAZIONE.txt |
---|
0,0 → 1,67 |
UpiPrinterServer versione 0.15 |
PREREQUISITI |
--------------------------------------------------------------- |
Il driver è stato verificato su Windows XP SP2. |
Verificare che sul browser utilizzato (Internet Explorer o Mozilla Firefox) |
sia installato il certificato che autentica il servizio: |
Per Internet Explorer: |
- aprire la pagina web https://srl.leader.it/ca.leader.it/ca.leader.it.cert.der |
- selezionare [Apri] nella maschera che compare |
- installare il certificato con il pulsante che compare nella maschera |
successiva |
- confermare tutte le successive maschere fino a conclusione |
Per FireFox: |
- aprire la pagina web https://srl.leader.it/ca.leader.it/ca.leader.it.cert.der |
- selezionare [Accetta questo certificato in modo permanente] e |
confermare |
- scegliere la voce [Dai fiducia a questo CA per l'identificazione dei siti |
WEB] e confermare |
AGGIORNAMENTO |
--------------------------------------------------------------- |
Per aggiornare è necessario prima disinstallare e |
successivamente installare. |
DISINSTALLAZIONE |
--------------------------------------------------------------- |
Eseguire il comando di disinstallazione: |
C:\Programmi\UpiPrinterServer\UpiPrinterServer.exe -remove |
Cancellare la cartella C:\Programmi\UpiPrinterServer |
INSTALLAZIONE |
--------------------------------------------------------------- |
Spostare la cartella UpiPrinterServer contenuta nel file |
UpiPrinterServer.zip nella cartella del PC: C:\Programmi |
Eseguire il comando di installazione: |
C:\Programmi\UpiPrinterServer\UpiPrinterServer.exe -install |
Verificare che il servizio "UpiPrinterServer" sia attivo: |
https://localhost:22000 |
Selezionare la stampante desiderata per la stampa dalla pagina Web visualizzata. |
Verificare se il servizio lavora utilizzando la pagina di test: |
https://sois.provincia.tn.it/test/test_UpiPrinterServer.html |
/tags/2.0/utility/UpiPrinterServer/LEGGIMI.txt |
---|
0,0 → 1,85 |
UpiPrinterServer versione 0.15 |
Installare il Perl di ActiveState 5.8.8 Build 822 |
Repository utilizzati per reperire i package installati: |
ppm rep add theoryx5.uwinnipeg.ca http://theoryx5.uwinnipeg.ca/ppms/ |
ppm rep add trouchelle.com http://trouchelle.com/ppm/ |
ppm rep add www.bribes.org http://www.bribes.org/perl/ppm |
#ppm rep add "ActiveState PPM2 Repository" #http://ppm.ActiveState.com/cgibin/PPM/ppmserver-5.8-windows.pl?urn:/PPMServer |
#ppm rep down "ActiveState Package Repository" |
#ppm rep down "ActiveState Package Repository" |
#ppm rep down "ActiveState Package Repository" |
#ppm rep down "ActiveState Package Repository" |
http://ppm4.activestate.com/MSWin32-x86/5.8/822/package.xml |
Package da installare oltre la base standard di ActiveState: |
#ppm install Net_SSLeay.pm |
ppm install Net-SSLeay |
ppm install HTTP-Daemon-SSL |
ppm install Win32-Printer |
ppm install Win32-EventLog-Carp |
ppm install Win32-GUI-Carp |
# http://www.roth.net/perl/Daemon/ |
ppm install http://www.roth.net/perl/packages/win32-daemon.ppd |
L'applicazione è reperibile nel repository SVN: |
https://svn.leader.it/wsvn/masonsql/utility/UpiPrinterServer/ |
COMPILAZIONE |
--------------------------------------------------------------- |
Installare i package per la compilazione |
ppm install Getopt-ArgvFile |
ppm install PAR-Packer |
# Se si vuole offuscare il codice: |
ppm install B-Deobfuscate |
utilizzare lo script di compilazione: |
compile.bat UpiPrinterServer |
Verrà creato il file: UpiPrinterServer.exe |
INSTALLAZIONE |
--------------------------------------------------------------- |
Creare la cartella "C:\Programmi\UpiPrinterServer" |
Copiare nella cartella il file "UpiPrinterServer.exe" e la |
cartella "certs" contenente i certificati: |
server-cert.pem |
server-key.pem |
Eseguire il comando di installazione: |
C:\Programmi\UpiPrinterServer\UpiPrinterServer.exe -install |
Verificare che il servizio "UpiPrinterServer" sia attivo: |
Selezionare la stampante dalla pagina Web: |
https://localhost:22000 |
e selezionando dalla pagina il link della stampante desiderata. |
Verificare se il servizio lavora utilizzando https://<SERVER>/test/test_UpiPrinterServer.html |
Per disinstallare il servizio: |
C:\Programmi\UpiPrinterServer\UpiPrinterServer.exe -remove |
Per verificare il servizio nel caso si blocchi durante l'utilizzo. |
Assicurarsi che il servizio "Upi Printer Server" sia fermo; lanciare da una console il comando: |
C:\Programmi\UpiPrinterServer\UpiPrinterServer.exe -debug |
e utilizzare il servizio. |
/tags/2.0/utility/UpiPrinterServer/compile.bat |
---|
0,0 → 1,8 |
REM compila il file .pl in .exe |
REM NOTA: le DLL ssleay32.dll e libeay32.dll non si trovano in C:/WINDOWS/system32 copiarle da C:\Perl\site\lib\auto\Net\SSLeay\ |
perl -x -S pp -B -f Bleach -f Obfuscate --gui -p -l C:/WINDOWS/system32/ssleay32.dll -l C:/WINDOWS/system32/libeay32.dll -o %1.par %1.pl |
parl -B -O./%1.exe %1.par |
del %1.par |
/tags/2.0/utility/UpiPrinterServer/certs/server-cert.pem |
---|
0,0 → 1,16 |
-----BEGIN CERTIFICATE----- |
MIIChjCCAe8CCQDL59rbpzVtpTANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMC |
SVQxETAPBgNVBAgTCFRyZW50aW5vMRIwEAYDVQQKEwlMZWFkZXIuSVQxGTAXBgNV |
BAsTEFBvbG8gVGVjbm9sb2dpY28xFTATBgNVBAMTDGNhLmxlYWRlci5pdDEgMB4G |
CSqGSIb3DQEJARYRc3VwcG9ydEBsZWFkZXIuaXQwHhcNMDcwNTAyMDk1OTI2WhcN |
MDkwNTAxMDk1OTI2WjCBhTELMAkGA1UEBhMCSVQxETAPBgNVBAgTCFRyZW50aW5v |
MRIwEAYDVQQKEwlMZWFkZXIuSVQxGTAXBgNVBAsTEFBvbG8gVGVjbm9sb2dpY28x |
EjAQBgNVBAMTCWxvY2FsaG9zdDEgMB4GCSqGSIb3DQEJARYRc3VwcG9ydEBsZWFk |
ZXIuaXQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALAD3+y9vCaorWUtIfb+ |
UCAh5lLDGporU6WcN1xsEAfRxACM6YeKdLRqsulOGrIPRpqiGE87NNTe+20gTvRi |
WuBCAkDXf7QegnTPhJ+Jsg9XnjlGs+hAIRDQ7zY0C7KqQ0hMWoPpJ72viObk9XcR |
3uQS4fGMpiFAWc1UhfJtzXcnAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAfI51q/ZP |
UihpTTaIsOZY62x00OdqRN5YpTyHx1gkkte3kXq7A50Pm0b2qLcYSeR9smUVoH9p |
bKCqrqyUBbpAqkBAPJzTj2jg1K0ZUscMaeuZ/B3/SY0GmJfuwgyEhHnqXYOPMJyT |
y4DYA4/zT1F+IgZ1HOOzfqtAI6mCV/2mC24= |
-----END CERTIFICATE----- |
/tags/2.0/utility/UpiPrinterServer/certs/server-key.pem |
---|
0,0 → 1,15 |
-----BEGIN RSA PRIVATE KEY----- |
MIICWwIBAAKBgQCwA9/svbwmqK1lLSH2/lAgIeZSwxqaK1OlnDdcbBAH0cQAjOmH |
inS0arLpThqyD0aaohhPOzTU3vttIE70YlrgQgJA13+0HoJ0z4SfibIPV545RrPo |
QCEQ0O82NAuyqkNITFqD6Se9r4jm5PV3Ed7kEuHxjKYhQFnNVIXybc13JwIDAQAB |
AoGAO8mFJVApeeQvyb8z20b1BoUdTB1zisyOxCE0+NLH+y/4aMt0g5K3I5Veojri |
fHsN23aV1UviHTCErMOdrgs+nH97r/0mH2R8X1T3BqF8Y0oi7rx6vF63FePm3Nlk |
hxSCREIwcOIFFFxTABMXbpozAS6J68tNETjC8gScAY08fCECQQDmlevxGWzYuQyG |
4sY+QGH3q3dv4AEf/D3Af9nNFDBnaC9LlHKLsc2rnZETPJVbuIYS2TfwY09sclbr |
9jBnE+oXAkEAw2o4wvSYaLzc72Zu7Qp3ymObhEOpMXgQxeI/hd/TNXFkmSycpZ+K |
OYoQcGdofraVXbYbDuq8UykVbFJeknLVcQJAIlCjWTD4ctQvGg+7gt4f9jStRJfo |
cvMd2XztU8iyX2Ew0KWZ2lIukmCTi3JTo9+1DC8JVRviYPgvGVR85YogJwJAE6D8 |
2KBnGsY1zxpT9B2EEOFWgr+lJCHyVV43kUP9XDXqq/QuO/i9krAKnK/WcDv43vPm |
3eW4SwYqb7oKY92DEQJAHCAHKwZ7KwPL40ZviRYJgcd8oqIm3VfLxYHiHLduzGZc |
EsQe+I9LObfAJjiiwYvonyVbro0koR9dmeJ6quTeOA== |
-----END RSA PRIVATE KEY----- |
/tags/2.0/COPYRIGHT |
---|
0,0 → 1,14 |
# --------------------------------------------------------------------------- # |
# Copyright: (C) 2003-2017 Guido Brugnara <http://www.leader.it> |
# Strada della Pozzata, 41 - Villazzano |
# 38123 T R E N T O (ITALY) |
# E-mail: info@leader.it |
# |
# Note: The authors with the rispettive contributions are available |
# in restricted access of SVN repository at |
# https://www.leader.it/wsvn/masonsql |
# --------------------------------------------------------------------------- # |
# |
Double licence are available, if requested, with differents prices and conditions: |
- AGPL Affero General Public Licence Rel.1 ( http://www.affero.org/oagpl.html ) |
- Commercial licence |
/tags/2.0/doc/MasonSQL_CRUD.txt |
---|
0,0 → 1,416 |
MasonSQL - interfaccia CRUD - versione 1.6.1 |
Nel documento viene descritta l'interfaccia per lo scambio dei dati per le classiche operazioni di Creazione(Create), Lettura(Retrieve), Aggiornamento(Update) e Cancellazione(Delete). |
L'interfaccia di comunicazione tra il client di accesso ed il server è disponibile esclusivamente con il protocollo standard HTTPS, con autenticazione basic. |
Per esigenze di compatibilità con le versioni precedenti di MasonSQL e per agevolare lo sviluppo dei client di accesso sono stati utilizzati esclusivamente i metodi di accesso GET e POST. |
Nella URI viene codificata la classe dell'oggetto che si vuole leggere, modificare, ecc. |
Esempi: |
https://masonsql.leader.it/dbms/campionamenti |
https://masonsql.leader.it/dbms/parametri |
https://masonsql.leader.it/dbms/formulari/siti |
Nella URL (Uniform Resource Locator) della chiamata viene codificato anche il metodo richiesto e la chiave univoca dell'oggetto richiesto. |
Esempi: |
https://masonsql.leader.it/dbms/campionamenti?method=update&key=12 |
https://masonsql.leader.it/dbms/parametri?key=888 |
https://masonsql.leader.it/dbms/parametri?method=select&key=23 |
https://masonsql.leader.it/dbms/campionamenti?method=delete&key=4 |
https://masonsql.leader.it/dbms/parametri?method=newkey |
https://masonsql.leader.it/dbms/parametri?method=insert&key=33 |
https://masonsql.leader.it/dbms/campionamenti?method=xls |
Ciascuna chiamata è di tipo atomico, o "stateless"; ovvero si conclude con una operazione completata con la risposta del server; non richiede successive interazioni. |
Unica eccezione, se così si può dire impropriamente, è data dal metodo "newkey" che ritorna una chiave utilizzabile per l'inserimento successivo di un nuovo oggetto. |
Se la chiave non viene poi utilizzata per inserire un nuovo oggetto, ciò non costituisce un problema. |
I dati degli oggetti (record delle tabelle) vengono scambiati nel formato XML con charset UTF-8. |
Per compatibilità con le versioni precedenti di MasonSQL lo schema utilizzato per la risposta è il seguente: |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="retrieve" user="administrator" timestamp="28/04/2010 07:45:17.997114 CEST" start="0" rows="1" max_rows="1529"> |
<campionamenti id="..." ... /> |
</dbms> |
Il TAG <dbms ... > identifica il percorso iniziale della URI e racchiude il TAG il cui nome identifica la classe dell'oggetto (il nome della tabella è rappresentato nel formato "schema.tabella" con un punto come separatore ). |
Nel TAG <dbms ... > sono definiti alcuni attributi: |
method - metodo richiesto |
user - corrisponde all'utente che ha effettuato la richiesta |
timestamp - data di riferimento della transazione. |
Attributi presenti solo con method=retrieve: |
start - offset del primo record restituito |
rows - numero di record restituiti |
max_rows - numero dei record elaborati |
Nella URI il nome della tabella da "schema.tabella" viene codificato con "schema/tabella". |
In mancanza di indicazione dello schema si intende che la tabella è presente nello schema di "default" (Schema: "public"). |
ATTENZIONE: Nelle operazioni di modifica ed inserimento è obbligatorio utilizzare il TAG corrispondente all'oggetto identificato nella URI. |
I campi della tabella vengono rappresentati nello schema XML utilizzando parametri del TAG: |
Esempio: |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="retrieve" user="administrator" timestamp="28/04/2010 07:48:19.200846 CEST" start="0" rows="1" max_rows="1"> |
<campionamenti stato_rapporto="firmato" data_ingresso="01/01/2010" persona_prelievo="1135" |
persona_responsabile3="" id_laboratorio="12" data_inizio_prova="01/01/2010" |
persona_responsabile2="" stato="Completato" durata_prelievo="" id="1136" |
id_tipi_campionamenti="514" osservazioni="" persona_responsabile="41" id_sito="41" |
data_fine_prova="09/10/2000" codice="[555444/03]" ora_prelievo="11:40" |
data_prelievo="03/10/2000" id_rapporto="1114"/> |
</dbms> |
I parametri (campi della tabella) contenenti caratteri riservati e/o proibiti (Es: '<' '&' <CR> ) devono essere codificati (Es: '<' '&' '\n'). |
Gestione dei permessi |
L'interfaccia è accessibile con autenticazione basic (password protetta dal canale cifrato SSL del protocollo HTTPS). |
L'utente che accede eredita i diritti in base ai gruppi di appartenenza, così come gestiti nelle applicazioni. Se l'utente appartiene ad una ditta di gestione o ad un laboratorio avrà diritto di accedere agli oggetti inerenti, così come accade attraverso l'interfaccia nel browser. |
NOME CHIAVE |
Le classi di oggetti (le tabelle) utilizzano come chiave univoca un campo che non ha un nome univoco ma può cambiare in ciascuna tabella, anche se è comunque un parametro di progetto e quindi non cambia nel tempo. |
Il nome di "default" è "id", ma per esser certi è possibile reperire il nome della chiave univoca utilizzata nell'oggetto utilizzando il metodo "keyname": |
https://masonsql.leader.it/dbms/campionamenti?method=keyname |
Verrà restituito il seguente documento XML contenente il nome del campo chiave: |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="keyname" user="admin" timestamp="28/04/2010 12:03:10" > |
<campionamenti keyname="id" /> |
</dbms> |
In caso di errore il server risponderà con errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
INFO |
Con il metodo "info" viene restituito un documento XML contenenete una serie di informazioni utili sull'oggetto. |
https://masonsql.leader.it/dbms/campionamenti?method=info |
Verrà restituito il seguente documento XML: |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="info" user="admin" timestamp="28/04/2010 12:00:00" > |
<campionamenti keyname="id" log="0" delete="1" print="1" insert="1" dbms="1" xls="1" |
printsel="1" update="1" select="1" father_name="" father_id_name="" father_key_name="" > |
<field size="4" name="id" type="integer" descr="" primary_key="1" notnull="1" /> |
<field size="4" name="id_sito" type="integer" descr="Sito prelievo" notnull="1" /> |
<field size="4" name="data_prelievo" type="date" descr="Data di prelievo" /> |
...... |
<field size="500" name="osservazioni" type="character" descr="Osservazioni" /> |
<child field="id" table="parametri" key="id_campione" /> |
<relation field="persona_responsabile" table="anagrafiche" /> |
<relation field="id_sito" table="siti" /> |
...... |
<relation field="cod_campionamenti" table="cod_campionamenti" key="codice" /> |
</campionamenti> |
</dbms> |
<field/> identifica le caratteristiche di un attributo |
<child/> identifica la relazione con un oggetto figlio (relazione n:1) |
<relation/> identifica la relazione con un diverso oggetto (relazione 1:n) |
Attenzione che <child/> e <relation/> compaiono se nella dichiarazione degli oggetti vengono descritte le rispettive relazioni (metodi ENTITY_CHILDREN e ENTITY_RELATIONS). |
NUMERO DEI RECORD PRESENTI |
Con il metodo "numrec" viene restituito un documento XML contenente la quantità di record presente in archivio che l'utente può recuperare. |
https://masonsql.leader.it/dbms/campionamenti?method=numrec |
Metodo della chiamata: GET |
Parametri: |
method => 'numrec' |
father_key => 'FFFF' - chiave univoca del "padre" (obbligatoria se l'oggetto ha un padre) |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<dbms method="numrec" user="admin" timestamp="28/04/2010 12:00:00" > |
<campionamenti numrec="1780" /> |
</dbms> |
LETTURA |
La URL per effettuare una operazione di lettura di un oggetto è costruita nel modo seguente: |
https://masonsql.leader.it/dbms/parametri?method=retrieve&key=NNNN |
oppure |
https://masonsql.leader.it/dbms/parametri?method=retrieve&father_key=NNNN |
E' possibile inoltre ricercare più oggetti utilizzando la seguente forma |
https://masonsql.leader.it/dbms/parametri?method=retrieve&rows=10&where=campione like 'mycode%' |
Attenzione: Nell'esempio i caratteri come ad esempio lo spazio nella URL vanno convertiti (lo spazio viene convertito con %20). |
Per maggior chiarezza questi caratteri vengono mostrati nell'esempio senza conversione, anche perché alcuni browser ne permettono l'utilizzo in quanto effettuano la conversione prima della trasmissione al server. |
Metodo della chiamata: GET |
Parametri: |
method => 'retrieve' |
key => 'NNNN' - chiave univoca dell'oggetto da recuperare (generalmente è un numero naturale) |
father_key => 'FFFF' - chiave univoca del "padre" |
rows => 'RRR' - Numero di righe di record da ritornare |
(quando non si utilizza il parametro 'key', limitato a 65536) |
start => 'SSS' - Posizione da cui mostrare i dati (0 corrisponde alla prima riga) |
where => "codice='XXX'" - query di ricerca limitata agli operatori di confronto =, !=, <, >, <=, >=, like, *~ e l'operatore "and" |
Esempi: |
https://masonsql.leader.it/dbms/parametri?key=888 |
https://masonsql.leader.it/dbms/parametri?method=retrieve&key=23 |
https://masonsql.leader.it/dbms/parametri?method=retrieve&father_key=700 |
https://masonsql.leader.it/dbms/parametri?method=retrieve&father_key=700&where=cod_campionamenti='biogas' |
La risposta del server sarà un documento XML contenente il record richiesto (con parametro "key") o i record collegati all'oggetto "padre" oppure il risultato della query di ricerca. |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="retrieve" user="admin" timestamp="28/04/2010 12:00:00" start="0" rows="2" max_rows="1801"> |
<parametri parametro="Quantità media dei liquami" risultato="22" id_campione="11111" ord="0" |
id_metodo="321" um="mc/h" cod_parametri="Qmedia" incertezza="" tipo="N" metodo="Portata" |
parametro_metodo="" id="24335" sinal="0" valore="20" /> |
<parametri parametro="Coefficente Rip. Portata" risultato="0.17" id_campione="11111" ord="1" |
id_metodo="313" um="." cod_parametri="coeff_ripp" incertezza="" tipo="K" metodo="CoeffRPot" |
parametro_metodo="" id="243334" valore="0.2225" /> |
</dbms> |
In caso di errore il server risponderà con errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
La chiave del padre è obbligatoria se è dichiarato il padre. |
Per accedere ad un intero set di record di grande dimensione, maggiore del limite imposto a rows di 65536 record utilizzare il parametro start. |
Per recuperare gli ultimi record del recordset, utilizzare il metodo "numrec" per conoscere il numero di record presenti e poi eseguire un metodo retrieve con start = numrec - rows. |
NUOVA CHIAVE |
E' possibile inserire un nuovo oggetto sia fornendo la chiave univoca oppure non fornendo la chiave univoca. |
Nel primo caso è possibile reperire una chiave univoca utilizzabile effettuando una chiamata (GET) con URI la classe dell'oggetto (la tabella) e con metodo newkey: |
https://masonsql.leader.it/dbms/campionamenti?method=newkey |
Verrà restituito il seguente documento XML contenente il codice univoco utilizzabile per inserire un nuovo documento: |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="newkey" user="admin" timestamp="28/04/2010 12:00:00" > |
<campionamenti key="1136" keyname="id" /> |
</dbms> |
In caso di errore il server risponderà con errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
CREAZIONE |
La URL per effettuare l'operazione di inserimento di un nuovo oggetto è costruita nel modo seguente: |
https://masonsql.leader.it/dbms/campionamenti?method=create&key=NNNN&father_key=FFFF |
Metodo della chiamata: POST |
Parametri: |
method => 'create' |
key => 'NNNN' chiave univoca del nuovo oggetto (parametro opzionale) |
father_key => 'FFFF' chiave univoca dell'oggetto "padre" (parametro opzionale) |
Esempi: |
https://masonsql.leader.it/dbms/campionamenti?method=create&key=1136 |
https://masonsql.leader.it/dbms/parametri?method=create&key=1137&father_key=12 |
https://masonsql.leader.it/dbms/parametri?method=create&father_key=120 |
<dbms> |
<campionamenti stato_rapporto="firmato" persona_prelievo="134" |
id_tipi_campionamenti="491" osservazioni="" persona_responsabile="241" id_sito="101" /> |
</dbms> |
Nel caso non venga fornita la chiave univoca il server inserirà un nuovo record attribuendo una chiave univoca reperibile nel documento contenente il record creato. |
I campi non forniti resteranno vuoti oppure inizializzati con i valori di "default" se previsti. |
ATTENZIONE: Si sconsiglia di effettuare creazioni senza la chiave univoca in quanto in caso di problemi nella comunicazione c'è il rischio di inserire più record uguali, oppure di non conoscere la chiave del record appena inserito. |
La risposta del server sarà un documento XML contenente il record generato |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="create" user="admin" timestamp="28/04/2010 12:00:00" > |
<campionamenti stato_rapporto="firmato" ... id="1136" /> |
</dbms> |
In caso di errore il server risponderà con errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
MODIFICA |
La URL per effettuare una operazione di lettura di un oggetto è costruita nel modo seguente: |
https://masonsql.leader.it/dbms/parametri?method=update&key=NNNN |
Metodo della chiamata: POST |
Parametri: |
method => 'update' |
key => 'NNNN' chiave univoca dell'oggetto da recuperare (generalmente è un numero naturale) |
Esempio: |
https://masonsql.leader.it/dbms/campionamenti?method=update&key=123 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms> |
<campionamenti stato_rapporto="firmato" ... id="123" /> |
</dbms> |
I campi non forniti non verranno modificati. |
La risposta del server sarà un documento XML contenente il record modificato |
Esempio: |
Codice: 200 OK |
Content-Type: text/xml; charset=utf-8 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="update" user="admin" timestamp="28/04/2010 12:00:00" > |
<campionamenti data_ingresso="02/03/2010" codice="AX400/2" id="123" |
osservazioni="Commento\nsu\npiù\nrighe" /> |
</dbms> |
In caso di errore il server risponderà con errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
CANCELLAZIONE |
La URL per effettuare una operazione di cancellazione di un oggetto è costruita nel modo seguente: |
https://masonsql.leader.it/dbms/parametri?method=delete&key=NNNN |
Metodo della chiamata: GET |
Parametri: |
method => 'delete' |
key => 'NNNN' chiave univoca dell'oggetto da recuperare (generalmente è un numero naturale) |
Esempio: |
https://masonsql.leader.it/dbms/parametri?method=delete&key=23 |
<?xml version="1.0" encoding="utf-8"?> |
<dbms method="delete" user="admin" timestamp="28/04/2010 12:00:00" > |
<parametri id="23" /> |
</dbms> |
La risposta del server sarà OK (200) con invio di un documento XML contenente i record cancellati, oppure errore (400) accompagnato da un documento contenente il messaggio dell'errore. |
Nel caso si faccia riferimento a record inesistenti o non accessibili dall'utente autenticato essi non verranno riportati nel documento XML di risposta. |
XLS |
La URL per effettuare il download di un file nel formato XLS contenente i record selezionati è costruita nel modo seguente: |
https://masonsql.leader.it/dbms/parametri?method=xls |
Metodo della chiamata: GET |
Parametri: |
method => 'xls' |
key => 'NNNN' - chiave univoca dell'oggetto da recuperare (generalmente è un numero naturale) |
father_key => 'FFFF' - chiave univoca del "padre" |
rows => 'RRR' - Numero di righe di record da ritornare |
(quando non si utilizza il parametro 'key', limitato a 65536) |
start => 'SSS' - Posizione da cui mostrare i dati (0 corrisponde alla prima riga) |
where => "codice='XXX'" - query di ricerca limitata agli operatori di confronto =, !=, <, >, <=, >=, like, *~ e l'operatore "and" |
PERMESSI DI ACCESSO |
L'accesso ai metodi e lle cassli degli oggetti/tabelle è controllato dall'autorizzazione "Dbms" per tutti i metodi e dalle autorizzazioni "Select", "Update", "Insert" e "Delete" per gli omonimi metodi. |
Tramite il metodo "info" è possibile verificare le autorizzazioni concesse sugli oggetti/tabelle. |
MESSAGGI DI ERRORE |
In caso di errore nella richiesta, violazione dei diritti o nella risposta del database il messaggio di errore viene inviato al client con errore "400 Bad Request" ed un documento XML contenente l'errore e, se abilitato il livello di debug, anche lo stack-trace dell'errore nel codice: |
<error user="administrator" timestamp="28/04/2010 13:10:22.434 CEST" > |
<message>No access to record or record not exists</message> |
<debug row="1"> |
Stack: [/opt/masonsql/htdocs/lib/my_library.comp:300], [/usr/local/share/perl ...n.comp:1112]\n |
</debug> |
</error> |
Di seguito alcuni messaggi di errore, tra i più significativi: |
No Dbms permission | L'utente non ha diritto di accesso alla funzionalità |
No insert permission | L'utente non ha diritto di inserire nuovi oggetti |
No delete permission | L'utente non ha diritto di cancellare oggetti |
No update permission | L'utente non ha diritto di modificare oggetti |
No father retrieve permission | L'utente non ha diritto di leggere il padre |
No related 'OOO' retrieve permission | L'utente non ha diritto di leggere l'oggetto collegato 'OOO' |
No father record retrieve | L'utente non ha diritto di leggere lo specifico oggetto padre |
No related 'OOO' record retrieve | L'utente non ha diritto di leggere lo specifico oggetto collegato 'OOO' |
No key param | Manca nella richiesta il parametro 'key' |
No multiple key in param key | E' stato fornito un elenco di chiavi nella richiesta |
No record retrieve or record not exists | L'oggetto fornito non esiste o non si hanno sufficienti diritti di accesso all'oggetto |
Delete record return N rows | La cancellazione dell'oggetto ha restituito un numero di oggetti diverso da uno |
No father_id param with father 'FATHER' | Manca il parametro father_id relativo all'oggetto PADRE |
No father_id == -1 | La chiave di valore "-1" è riservata dal framework e se utilizzata genera errore |
No key == -1 | La chiave di valore "-1" è riservata dal framework e se utilizzata genera errore |
Defined father_id param without father definition | Fornito il parametro father_id nella chiamata di un oggetto senza padre |
Key already used | In inserimento, la chiave fornita è già utilizzata (non è detto che l'utente abbia comunque accesso a quell'oggetto) |
Key greater last key | In inserimento, la chiave fornita è maggiore dell'ultima chiave generata |
No content | Chiamata POST senza contenuto |
Malformed xml content: no <dbms> tag | Il documento trasmesso non contiene il blocco XML: <dbms ... >....</dbms> |
Errori segnalati relativi al campo 'where', utilizzabile con il metodo 'retrieve': |
Utilizzo della parola riservata '***' non autorizzata |
Utilizzo dell'operatore '$value' non autorizzato |
Utilizzo del campo '***' non autorizzato |
Utilizzo della funzione '***' non autorizzata |
Errore di sintassi: termine '***' sconosciuto |
Errore di sintassi: manca un delimitatore di stringa |
Errore di sintassi: mancante/i N parentesi di chiusura |
Errore di sintassi: parentesi di chiusura senza la corrispondente parentesi di apertura |
___ |
TEST & DEBUG |
Per valutare il comportamento dell'interfaccia è possibile utilizzare la pagina html: |
https://masonsql.leader.it/test/test_crud.html |
E' possibile indicare lo schema, tabella, chiave ed il documento XML (per "update" e "insert") su cui eseguire le operazioni di: info, numrec, newkey, update, insert e delete. Viene restituito il record di risposta nel riquadro sottostante. |
Nota: Il documento è stato creato utilizzando il charset UTF-8. |
-------------------------------------------------------------------------------- |
/tags/2.0 |
---|
Property changes: |
Added: svn:mergeinfo |
Merged /branches/janez/copy_paste:r302-303 |
Merged /branches/karan/masonsql_apache2.4:r346-386 |
Merged /masonsql_self_registration:r201-223 |
Merged /masonsql_session_management:r264-293 |
Merged /branches/rajesh/session_management:r294-305,357-358 |