Changeset 5514


Ignore:
Timestamp:
02/14/12 16:52:04 (12 years ago)
Author:
acoutinho
Message:

Ticket #2434 - Implementacao anexos, acls e delegacao de participantes

Location:
trunk
Files:
11 added
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/expressoCalendar/setup/default_records.inc.php

    r5341 r5514  
    2828                $oProc->query("ALTER TABLE calendar_signature ADD CONSTRAINT fk_calendar_signature_calendar_espec FOREIGN KEY (calendar_id) REFERENCES calendar (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;"); 
    2929                 
    30                 //calendar_signature_alarm 
     30        //calendar_signature_alarm 
    3131                $oProc->query("ALTER TABLE calendar_signature_alarm ADD CONSTRAINT fk_calendar_signature_alarm_calendar_signature FOREIGN KEY (calendar_signature_id) REFERENCES calendar_signature (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;"); 
    3232                 
     
    3737                $oProc->query("INSERT INTO calendar_object_type( \"id\", \"name\") VALUES ('1','VEVENT');"); 
    3838                $oProc->query("INSERT INTO calendar_class( \"id\", \"name\") VALUES ('1','Public'),('2','Private'),('3','Confidential');"); 
    39                 $oProc->query("INSERT INTO calendar_participant_status( \"id\", \"name\") VALUES ('1','CONFIRMED'),('2','TENTATIVE'),('3','CANCELLED'),('4','UNANSWERED');"); 
     39                $oProc->query("INSERT INTO calendar_participant_status( \"id\", \"name\") VALUES ('1','CONFIRMED'),('2','TENTATIVE'),('3','CANCELLED'),('4','UNANSWERED'),('5', 'DELEGATED');"); 
    4040                 
    4141?> 
  • trunk/expressoCalendar/setup/tables_current.inc.php

    r5441 r5514  
    3131                                'type' => array('type' => 'varchar','precision' => '50','nullable' => False), 
    3232                                'name' => array('type' => 'varchar','precision' => '255','nullable' => False), 
    33                                 'size' => array('type' => 'varchar','precision' => '255','nullable' => False) 
     33                                'size' => array('type' => 'varchar','precision' => '255','nullable' => False), 
     34                                'owner' => array('type' => 'int', 'precision' => '8','nullable' => True) 
    3435                        ), 
    3536                        'pk' => array('id'), 
     
    3839                        'uc' => array() 
    3940                ), 
    40                  
    41          
    42                  
     41                                 
    4342                'calendar' => array( 
    4443            'fd' => array( 
     
    136135                'user_info_id' => array(  'type' => 'int', 'precision' => '8', 'nullable' => False), 
    137136                'object_id' => array(  'type' => 'int', 'precision' => '8', 'nullable' => True), 
    138                 'delegated_to' => array( 'type' => 'int', 'precision' => '8','default' => 0, 'nullable' => False), 
     137                'delegated_from' => array( 'type' => 'int', 'precision' => '8','default' => 0, 'nullable' => False), 
    139138                'is_organizer' => array( 'type' => 'int', 'precision' => '2', 'default' => 0, 'nullable' => False), 
    140139                'is_external' => array( 'type' => 'int', 'precision' => '2', 'default' => 0, 'nullable' => False), 
    141                 'participant_status_id' => array( 'type' => 'int', 'precision' => '8', 'nullable' => false , 'default' => 4) 
     140                'participant_status_id' => array( 'type' => 'int', 'precision' => '8', 'nullable' => false , 'default' => 4), 
     141                                'acl' => array('type' => 'varchar', 'precision' => '10' ,'default' => 'r', 'nullable' => False), 
     142                                'receive_notification' => array( 'type' => 'int', 'precision' => '2', 'default' => 1, 'nullable' => False) 
    142143            ), 
    143144            'pk' => array('id'), 
  • trunk/expressoMail1_2/inc/class.db_functions.inc.php

    r5509 r5514  
    410410                                $_REQUEST['params']['calendar'] = $params['selected']; 
    411411                                $_REQUEST['readable'] = $params['readable'] ? true : false; 
    412                                 $_REQUEST['analize'] = isset($params['readable']) ? true : false; 
     412                $_REQUEST['analize'] = isset($params['analize']) ? true : false; 
    413413                                $_REQUEST['params']['status'] = $params['status']; 
    414414                                $_REQUEST['params']['owner'] = $_SESSION['phpgw_info']['expressomail']['user']['account_id']; 
     415                                if(isset($params['acceptedSuggestion'])){ 
     416                                        $_REQUEST['params']['acceptedSuggestion'] = $params['acceptedSuggestion']; 
     417                                        $_REQUEST['params']['from'] = $params['from']; 
     418                                } 
     419                                 
    415420                                ob_start(); 
    416421                                include_once(PHPGW_INCLUDE_ROOT.'/prototype/converter.php'); 
  • trunk/expressoMail1_2/js/main.js

    r5506 r5514  
    36333633                        closeOnEscape: true 
    36343634                }); 
    3635                 $.ajax({ 
    3636                         url: "controller.php?action="+import_url+'&from_ajax=true&id_user='+User.me.id+'&readable=true&cirus_delimiter='+cyrus_delimiter+'&analize=true', 
    3637                         async: false, 
    3638                         success: function(data){ 
    3639                                 data = connector.unserialize(data); 
    3640  
    3641  
    3642                                 var createDialog = function(typeImport, propaget){ 
    3643  
    3644                                         if(typeImport == '1'){ 
    3645                                                 $("#select-agenda").html(''); 
    3646                                                 for(var calendario in Calendar.calendarIds){ 
    3647                                                         var doc = document .createElement("OPTION"); 
    3648                                                         doc.value = Calendar.signatures[parseInt(calendario)].calendar.id; 
    3649                                                         doc.innerHTML = Calendar.signatures[parseInt(calendario)].calendar.name; 
    3650                                                         $("#select-agenda").append(doc); 
    3651                                                        
    3652                                                 }; 
    3653                                                 $("#import-dialog" ).dialog({ 
    3654                                                     buttons: { 
    3655                                                         Cancel: function() { 
    3656                                                                 $( this ).dialog( "close" ); 
    3657                                                         }, 
    3658                                                         "Importar" : function(){ 
    3659  
    3660                                                              $.ajax({ 
    3661                                                                      url: "controller.php?action="+import_url+'&from_ajax=true&selected='+$("#select-agenda option:selected").val()+'&status='+$("#select-status option:selected").val(), 
    3662                                                                      success: function(msg){ 
    3663  
    3664                                                                             var alt = ( (msg = connector.unserialize(msg)) == "ok") ? "Importado com sucesso para " : "Ocorreu um erro ao importar o evento para a agenda "; 
    3665                                                                             alert( alt + $("#select-agenda option:selected").text() ); 
    3666                                                                     } 
    3667                                                                 }); 
    3668                                                          
    3669                                                                                                                         $( this ).dialog( "close" ); 
    3670                                                                                                                 } 
    3671                                                     } 
    3672                                                  });                                     
    3673  
    3674                                         }else if(data == '4'){ 
    3675                                             alert('Seu evento já se encontra atualizado'); 
    3676                                             return; 
    3677                                         }else if(data == '3'){ 
    3678                                            $.ajax({ 
    3679                                                         url: "controller.php?action="+import_url+'&from_ajax=true&selected=true', 
    3680                                                         success: function(msg){ 
    3681                                                         alert( ( ( connector.unserialize(msg)) == "ok") ? "Seu evento foi removido " : "Ocorreu um erro ao remover o evento" ); 
    3682                                                         } 
    3683                                                 }); 
    3684                                                 return; 
    3685                                         } 
    3686                                         else if(data == '5'){ 
    3687                                                 $.ajax({ 
    3688                                                         url: "controller.php?action="+import_url+'&from_ajax=true&selected=true', 
    3689                                                         success: function(msg){ 
    3690                                                         alert( ( ( connector.unserialize(msg)) == "ok") ? "Atualizado com sucesso " : "Ocorreu um erro ao atualizar o evento" ); 
    3691                                                         } 
    3692                                                 }); 
    3693                                                 return; 
    3694                                         }else { 
    3695                                                 up = true; 
    3696                                                 $("#select-agenda").css("display", "none"); 
    3697                                                 $("#import-dialog" ).children("p:first-child").css("display", "none"); 
    3698                                                 $("#import-dialog" ).dialog({ 
    3699                                                         height: 160, 
    3700                                                         title: 'Atualizar Evento', 
    3701                                                         buttons: { 
    3702                                                             Cancel: function() { 
    3703                                                                     $( this ).dialog( "close" ); 
    3704                                                             }, 
    3705                                                            "Atualizar": function() { 
    3706                                                                  
    3707                                                                 $.ajax({ 
    3708                                                                      url: "controller.php?action="+import_url+'&from_ajax=true&selected='+$("#select-agenda option:selected").val()+'&status='+$("#select-status option:selected").val(), 
    3709                                                                      success: function(msg){ 
    3710                                                                             alert( ( (msg = connector.unserialize(msg)) == "ok") ? "Atualizado com sucesso para " : "Ocorreu um erro ao atualizar o evento" ); 
    3711                                                                     } 
    3712                                                                 }); 
    3713                                                          
    3714                                                                 $( this ).dialog( "close" ); 
    3715                                                         } 
    3716                                                     } 
    3717                                                 }); 
    3718                                         $(".ui-dialog-buttonpane").find(".ui-button:last").children().html("Atualizar");                 
    3719                                         }; 
    3720                                         $( "#import-dialog" ).dialog( "open" );  
    3721                                 }; 
    3722                                 createDialog(data, true); 
     3635                $.ajax({ 
     3636                        url: "controller.php?action="+import_url+'&from_ajax=true&id_user='+User.me.id+'&readable=true&cirus_delimiter='+cyrus_delimiter+'&analize=true', 
     3637                        async: false, 
     3638                        success: function(data){ 
     3639                                        data = connector.unserialize(data); 
     3640 
     3641 
     3642                                        var createDialog = function(typeImport, propaget){ 
     3643                                                         
     3644                                                switch(parseInt(typeImport)){ 
     3645                                                case 1: 
     3646                                                        $("#select-agenda").html(''); 
     3647                                                                for(var calendario in Calendar.calendarIds){ 
     3648                                                                                var doc = document .createElement("OPTION"); 
     3649                                                                                doc.value = Calendar.signatures[parseInt(calendario)].calendar.id; 
     3650                                                                                doc.innerHTML = Calendar.signatures[parseInt(calendario)].calendar.name; 
     3651                                                                                $("#select-agenda").append(doc); 
     3652                                                                           
     3653                                                                }; 
     3654                                                                $("#import-dialog" ).dialog({ 
     3655                                                                        buttons: { 
     3656                                                                                Cancel: function() { 
     3657                                                                                                $( this ).dialog( "close" ); 
     3658                                                                                }, 
     3659                                                                                "Importar" : function(){ 
     3660 
     3661                                                                                         $.ajax({ 
     3662                                                                                                         url: "controller.php?action="+import_url+'&from_ajax=true&selected='+$("#select-agenda option:selected").val()+'&status='+$("#select-status option:selected").val(), 
     3663                                                                                                         success: function(msg){ 
     3664 
     3665                                                                                                                        var alt = ( (msg = connector.unserialize(msg)) == "ok") ? "Importado com sucesso para " : "Ocorreu um erro ao importar o evento para a agenda "; 
     3666                                                                                                                        alert( alt + $("#select-agenda option:selected").text() ); 
     3667                                                                                                        } 
     3668                                                                                                }); 
     3669                                                                                 
     3670                                                                                        $( this ).dialog( "close" ); 
     3671                                                                                } 
     3672                                                                        } 
     3673                                                                 }); 
     3674                                                        break; 
     3675                                                case 2: 
     3676                                                        $.ajax({ 
     3677                                                                url: "controller.php?action="+import_url+'&from_ajax=true&selected=true', 
     3678                                                                success: function(msg){ 
     3679                                                                        alert( ( ( connector.unserialize(msg)) == "ok") ? "Seu evento foi removido " : "Ocorreu um erro ao remover o evento" ); 
     3680                                                                } 
     3681                                                        }); 
     3682                                                        return; 
     3683                                                        break; 
     3684                                                case 4: 
     3685                                                        alert('Seu evento já se encontra atualizado'); 
     3686                                                        return; 
     3687                                                        break; 
     3688                                                case 5: 
     3689                                                        $.ajax({ 
     3690                                                                url: "controller.php?action="+import_url+'&from_ajax=true&selected=true', 
     3691                                                                success: function(msg){ 
     3692                                                                alert( ( ( connector.unserialize(msg)) == "ok") ? "Atualizado com sucesso " : "Ocorreu um erro ao atualizar o evento" ); 
     3693                                                                } 
     3694                                                        }); 
     3695                                                        return; 
     3696                                                        break; 
     3697                                                case 6: 
     3698                                                        var acceptedSuggestion = confirm("Deseja atualizar o evento de acordo com a sugestão ?"); 
     3699                                                        $.ajax({ 
     3700                                                                url: "controller.php?action="+import_url+'&from_ajax=true&id_user='+User.me.id+'&selected=true&cirus_delimiter='+cyrus_delimiter+'&acceptedSuggestion='+acceptedSuggestion+"&from="+document.getElementById('from_values_'+currentTab).value, 
     3701                                                                success: function(msg){ 
     3702                                                                        if(acceptedSuggestion) 
     3703                                                                                alert( ( ( connector.unserialize(msg)) == "ok") ? "Evento atualizado com sucesso " : "Ocorreu um erro ao atualizar o evento" ); 
     3704                                                                } 
     3705                                                        }); 
     3706                                                        return; 
     3707                                                        break; 
     3708                                                default: 
     3709                                                        up = true; 
     3710                                                        $("#select-agenda").css("display", "none"); 
     3711                                                        $("#import-dialog" ).children("p:first-child").css("display", "none"); 
     3712                                                        $("#import-dialog" ).dialog({ 
     3713                                                                height: 160, 
     3714                                                                title: 'Atualizar Evento', 
     3715                                                                buttons: { 
     3716                                                                        Cancel: function() { 
     3717                                                                                $( this ).dialog( "close" ); 
     3718                                                                        }, 
     3719                                                                   "Atualizar": function() { 
     3720                                                                                 
     3721                                                                                $.ajax({ 
     3722                                                                                         url: "controller.php?action="+import_url+'&from_ajax=true&selected='+$("#select-agenda option:selected").val()+'&status='+$("#select-status option:selected").val(), 
     3723                                                                                         success: function(msg){ 
     3724                                                                                                        alert( ( (msg = connector.unserialize(msg)) == "ok") ? "Atualizado com sucesso para " : "Ocorreu um erro ao atualizar o evento" ); 
     3725                                                                                        } 
     3726                                                                                }); 
     3727                                                                                $( this ).dialog( "close" ); 
     3728                                                                        } 
     3729                                                                } 
     3730                                                        }); 
     3731                                                        $(".ui-dialog-buttonpane").find(".ui-button:last").children().html("Atualizar"); 
     3732                                                } 
     3733                                                $( "#import-dialog" ).dialog( "open" );  
     3734                                                                                                                                 
     3735                                        }; 
     3736                                        createDialog(data, true); 
    37233737                                 
    37243738                }}); 
  • trunk/prototype/Sync.php

    r5437 r5514  
    6464                    if( isset( $dt[$linkName] ) ) 
    6565                    { 
    66                             if( $notArray = Controller::isConcept( $linkName ) ) 
     66                            if( $notArray = Controller::isConcept( $concept, $linkName ) ) 
    6767                                    $dt[$linkName] = array( $dt[$linkName] ); 
    6868 
  • trunk/prototype/api/controller.php

    r5437 r5514  
    11<?php 
     2 
    23 
    34if( !defined( 'ROOTPATH' ) ) 
     
    2526        static $includes = array(); 
    2627        static $tx = array(); 
     28        static $isConcept = array(); 
    2729        static $txID = 0; 
    2830        static $wallet; 
     
    150152 
    151153        //TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados 
    152         public static function links( $concept = false ) 
    153         { 
     154        public static function links( $concept = false, $linkage = false ) 
     155        { 
     156             
     157 
    154158            if( !isset(self::$config[ $concept ]) ) 
    155159              self::$config[ $concept ] = self::loadConfig( $concept ); 
    156160 
    157             return( isset(self::$config[ $concept ]['links']) ?  
    158                           self::$config[ $concept ]['links'] : array() ); 
    159         } 
    160  
    161         public static function isConcept( $concept ) 
     161            $links = array(); 
     162            self::$isConcept[ $concept ] = array(); 
     163 
     164            if( isset(self::$config[ $concept ][ 'model.hasOne' ]) ) 
     165                foreach( self::$config[ $concept ][ 'model.hasOne' ] as $linkName => $linkTarget ) 
     166                { 
     167                    list( $target, $link ) = explode( '.', $linkTarget ); 
     168 
     169                    if( $linkage === $linkName ) 
     170                        $return = $link; 
     171 
     172                    $links[$linkName] = $target; 
     173                    self::$isConcept[ $concept ][ $linkName ] = true; 
     174                } 
     175            if( isset(self::$config[ $concept ][ 'model.depends' ]) ) 
     176                foreach( self::$config[ $concept ][ 'model.depends' ] as $linkName => $linkTarget ) 
     177                { 
     178                    list( $target, $link ) = explode( '.', $linkTarget ); 
     179 
     180                     if( $linkage === $linkName ) 
     181                        $return = $link; 
     182 
     183                    $links[$linkName] = $target; 
     184                    self::$isConcept[ $concept ][ $linkName ] = true; 
     185                } 
     186            if( isset(self::$config[ $concept ][ 'model.hasMany' ]) ) 
     187                foreach( self::$config[ $concept ][ 'model.hasMany' ] as $linkName => $linkTarget ) 
     188                { 
     189                    list( $target, $link ) = explode( '.', $linkTarget ); 
     190 
     191                     if( $linkage === $linkName ) 
     192                        $return = $link; 
     193 
     194                    $links[$linkName] = $target; 
     195                } 
     196 
     197            return( isset($return) ? $return : $links ); 
     198        } 
     199 
     200        public static function isConcept( $concept, $linkName ) 
    162201        {  
    163             if( isset( self::$config[ $concept ] ) &&  
    164                 self::$config[ $concept ] ) 
    165                 return( true ); 
    166                 else 
    167                 return file_exists( ROOTPATH."/config/$concept.ini" ); 
     202            if( !isset( self::$isConcept[ $concept ] ) ) 
     203                self::links( $concept ); 
     204 
     205            return( isset(self::$isConcept[ $concept ][ $linkName ]) ); 
    168206        } 
    169207 
     
    576614 
    577615                $postpone = array(); 
     616                $linkNames = array(); 
    578617 
    579618                if( $data ) 
     
    585624                        if( isset( $data[$linkName] ) && is_array( $data[$linkName] ) ) 
    586625                        { 
    587                             if( self::isConcept( $linkName ) ) 
     626                                if( self::isConcept( $URI['concept'], $linkName ) ) 
    588627                                    $data[$linkName] = self::put( array( 'concept' => $linkTarget ), $data[$linkName], &$txIds ); 
    589628                            else 
    590                                     $postpone[$linkTarget] = $data[$linkName]; 
     629                            { 
     630                                    $postpone[ $linkTarget ] =  $data[$linkName]; 
     631                                    $linkNames[ $linkTarget ] = $linkName; 
     632                            } 
    591633                        } 
    592634                    } 
     
    609651                            $value = array( 'id' => $value ); 
    610652 
    611                           $value[ $URI['concept'] ] = $URI['id']; 
    612  
     653                          $value[ self::links( $URI['concept'], $linkNames[ $linkTarget ] ) ] = $URI['id']; 
     654   
    613655                          self::put( array( 'concept' => $linkTarget ), $value, &$txIds ); 
    614656                      } 
     
    658700 
    659701Controller::$cache = Controller::loadCache(); 
    660 ?> 
     702// ?> 
  • trunk/prototype/api/datalayer.js

    r5437 r5514  
    44arrayName = /^([A-z0-9-_]+)\[\]$/; 
    55startsDoubleDot = /^:/; 
     6isIframe = /^iframe.*/; 
     7FILE = 'files'; 
    68// cached_urls = {}; 
    79 
     
    1315//            return; 
    1416//        alert( options.url + " dentro" ); 
    15           jqXHR.abort();  
    16  
    17           var callback = ( options.success || options.complete || $.noop ); 
     17 
     18           var callback = ( options.success || options.complete || $.noop ); 
     19 
     20          if( isIframe.test( options.dataType ) || options.data instanceof FormData ) 
     21          {     
     22              res = internalUrl.exec( options.url ); 
     23 
     24              var data = {}; 
     25 
     26              data[ res[1] ] = DataLayer.form( options.fileInput.parents( 'form' ), options.fileInput ); 
     27 
     28              options.formData = DataLayer.serializeForm( data ); 
     29 
     30              callback = function( data ){ 
     31 
     32                    //coutinho, escreva seu codigo aqui. 
     33 
     34                    return callback( DataLayer.encode( res[2], data ) ); 
     35 
     36              } 
     37 
     38              options.url = DataLayer.dispatchPath + 'post.php'; 
     39 
     40              if( options.data instanceof FormData ) 
     41              { 
     42                  options.data = new FormData(); 
     43 
     44                  $.each(options.formData, function (index, field) { 
     45                            options.data.append(field.name, field.value); 
     46                        }); 
     47                   
     48                  $.each(options.files, function (index, file) { 
     49                            options.data.append(options.paramName, file); 
     50                        }); 
     51              } 
     52 
     53              return( true ); 
     54          } 
     55 
     56          jqXHR.abort(); 
    1857 
    1958          switch( options.type.toUpperCase() ) 
     
    62101                        //TODO: check the type for conversion 
    63102                        DataLayer.receive,  
    64                         false, { 'formData': $this.serializeArray(),  'fileInput': fileInputs } ); 
     103                        false, { 'formData': $this.serializeArray(),  'fileInput': fileInputs, 'paramName': FILE + '[]' } ); 
    65104 
    66105        return( false ); 
     
    79118 
    80119          case 'POST': 
    81         DataLayer.put( res[1], data ); 
     120                DataLayer.put( res[1], data ); 
    82121        } 
    83122 
     
    93132 
    94133    links: {}, 
     134    nestedLinks: {}, 
    95135    concepts: {}, 
    96136    listeners: {}, 
     
    216256    }, 
    217257 
    218     form: function( target ){ 
    219  
    220         var params = {}, $this = $(target); 
     258    form: function( target, fileInputs ){ 
     259 
     260        var params = {}, $this = $(target), inputArray = $this.serializeArray(); 
    221261 
    222262        if( !$this.is( "form" ) ) 
    223263            $this = $this.parents( "form" ); 
    224  
    225         $.each( $this.serializeArray(), function( i, el ){ 
     264                 
     265        if( fileInputs ) 
     266                fileInputs.each( function( i, el ){ 
     267 
     268              inputArray[ inputArray.length ] = { name: $(this).prop("name"), value: FILE + i }; 
     269 
     270                }); 
     271 
     272        $.each( inputArray, function( i, el ){ 
    226273 
    227274            if( newName = arrayName.exec( el.name ) ) 
     
    242289        return this.decode( $this.attr( "action" ), params ); 
    243290    }, 
     291         
     292        serializeForm: function( data, level ){ 
     293         
     294                var formData = []; 
     295         
     296                for( key in data ) 
     297                { 
     298                        var value = data[key]; 
     299 
     300                        if( level !== undefined ) 
     301                                key = level+'['+key+']'; 
     302 
     303                        if( $.isArray(value) || $.isPlainObject(value) ) 
     304                                formData = formData.concat( this.serializeForm( value, key ) ); 
     305                        else 
     306                                formData[ formData.length ] = { name: key, value: value }; 
     307                } 
     308                 
     309                return( formData ); 
     310        }, 
    244311 
    245312    blend: function( action, data ){ 
     
    307374        if( bothSides || !oneSide ) 
    308375        { 
    309             var result = false, links = this.links( concept ),  
     376            var result = false, links = this.links( concept ), nestedLinks = this.links( concept, true ),  
    310377            current = this.check( concept ) || {}, ids = []; 
    311378 
     
    333400                                    el = { id: el }; 
    334401 
    335                                 var nestedLinks = _this.links( links[link], true ); 
    336                                  
     402                                //removido pois o mesmo esta gerando inconsistencia em tudo 
     403//                              if( DataLayer.isConcept( links[link], nestedLinks[link] ) ) 
    337404                                if( isConcept ) 
    338405                                { 
    339                                     el[ nestedLinks[concept] ] = el[ nestedLinks[concept] ] || []; 
    340                                     el[ nestedLinks[concept] ].push( key ); 
     406                                    el[ nestedLinks[link] ] = el[ nestedLinks[link] ] || []; 
     407                                    el[ nestedLinks[link] ].push( key ); 
    341408                                } 
    342409                                else 
    343                                     el[ nestedLinks[concept] ] = key; 
     410                                    el[ nestedLinks[link] ] = key; 
    344411 
    345412                                if( isRef && ( !current[ key ] || !current[ key ][ link ] ||  
     
    393460        var bothSides = (typeof oneSide === "undefined"), 
    394461 
    395         links = this.links( concept ), ids = [], 
     462        links = this.links( concept ), nestedLinks = this.links( concept, true ), ids = [], 
    396463 
    397464        current = this.check( concept, id ); 
     
    399466        if( !current ) return; 
    400467         
    401         if( id ) 
     468        if( typeof id === "string" ) 
    402469            current.id = id; 
    403470 
     
    420487                    continue; 
    421488 
    422                 var nestedLinks = this.links( links[link], true ); 
    423  
    424489                if( isConcept = this.isConcept( concept, link ) ) 
    425490                    current[i][link] = [ current[i][link] ]; 
     
    429494                        el = DataLayer.storage.cache[links[link]][el]; 
    430495 
    431                         if( notArrayNested = ( $.type( el[ nestedLinks[concept] ] ) !== "array" ) ) 
    432                             el[ nestedLinks[concept] ] = [ el[nestedLinks[concept]] ]; 
    433  
    434                         el[ nestedLinks[concept] ] = $.grep( el[ nestedLinks[concept] ], function( nested, iii ){ 
     496                        if( notArrayNested = ( $.type( el[ nestedLinks[link] ] ) !== "array" ) ) 
     497                            el[ nestedLinks[link] ] = [ el[nestedLinks[link]] ]; 
     498 
     499                        el[ nestedLinks[link] ] = $.grep( el[ nestedLinks[link] ], function( nested, iii ){ 
    435500                            return ( currentId !== nested ); 
    436501                        }); 
    437502 
    438503                        if( notArrayNested ) 
    439                             el[ nestedLinks[concept] ] = el[ nestedLinks[concept] ][0] || false; 
    440                         if(!el[ nestedLinks[concept] ] || !el[ nestedLinks[concept] ].length) 
    441                                 delete el[ nestedLinks[concept] ]; 
     504                            el[ nestedLinks[link] ] = el[ nestedLinks[link] ][0] || false; 
     505                        if(!el[ nestedLinks[link] ] || !el[ nestedLinks[link] ].length) 
     506                                delete el[ nestedLinks[link] ]; 
    442507                }); 
    443508            } 
     
    905970 
    906971            this.links[ concept ] =  result['links'] || {}; 
     972 
     973           this.nestedLinks[ concept ] = result['nestedLinks'] || {}; 
    907974        } 
    908975 
    909976        if( reverse ) 
    910977        { 
    911             var reverted = {}, llinks = this.links[ concept ]; 
    912      
    913             for( var key in llinks ) 
    914                 reverted[ llinks[key] ] = key; 
    915  
    916             return( reverted ); 
     978            return( this.nestedLinks[ concept ] ); 
    917979        } 
    918980 
     
    10141076 
    10151077            if( result && bothSides && (!filter ||  
    1016                                                                         !filter.criteria ||  
    1017                                                                         !filter.criteria.format) ) 
     1078                                        !filter.criteria ||  
     1079                                        !filter.criteria.format) ) 
    10181080            { 
    10191081              var newResult = []; 
     
    10321094    }, 
    10331095     
    1034      
    1035     filter: function( base, filter ){ 
     1096    filter: function( base, filter, criteria ){ 
    10361097       
     1098        if( !$.isArray( filter || [] ) ) 
     1099            filter = filter.filter || false; 
     1100 
     1101        if( !filter ) 
     1102            return( base ); 
     1103 
    10371104        var filtered = []; 
    10381105       
    1039 //      var operator = filter.shift(); 
    1040        
    1041         /*for( var key in base ) 
    1042         { 
    1043             switch( operator ) 
    1044             { 
    1045                 case 'AND': 
    1046                   for( var i = 0, current = true; i < filter.length && current; i++ ) 
    1047                     current = this.compare( '&', current, this.compare( base[key], filter[i] ) ); 
    1048                 break; 
    1049                 case 'OR': 
    1050                   for( var i = 0, current = false; i < filter.length && !current; i++ ) 
    1051                     current = this.compare( '|', current, this.compare( base[key], filter[i] ) ); 
    1052                 break; 
    1053                 case 'IN': 
    1054                   for( var i = 0, current = false; i < filter[1].length && !current; i++ ) 
    1055                     current = this.compare( '|', current, this.compare( base[key], [ '=', filter[0], filter[1][i] ] ) ); 
    1056                 break; 
    1057                 default : current = this.compare( operator, base[key], ); 
    1058             } 
    1059         */     
    1060 //          if( !noGroup ) 
    1061 //              for( var i = 0, current = original; i < filter.length && ( current === original ); i++ ) 
    1062 //                  current = this.compare( operator, current, this.compare( base[key], filter[i] ) ); 
    1063  
    1064 //          if( current ) 
    1065 //              filtered[ filtered.length ] = key; 
    1066 //      } 
     1106        for( var key in base ) 
     1107            if( this.storage.filter( base[key], filter ) ) 
     1108                filtered[ filtered.length ] = key; 
    10671109 
    10681110        return( filtered ); 
     
    10731115      switch( operator ) 
    10741116      { 
    1075           case '*':  return  RegExp( "*" + base + "*" ).test( test ); 
    1076           case '^':  return  RegExp( "^" + base +  "" ).test( test ); 
    1077           case '$':  return  RegExp( ""  + base + "$" ).test( test ); 
    1078  
    1079           case '&': return ( base && test ); 
    1080           case '|': return ( base || test ); 
     1117          case '*':  return RegExp( ".*" + test + ".*" ).test( base ); 
     1118          case '^':  return RegExp( "^" + test +  ".*" ).test( base ); 
     1119          case '$':  return RegExp( ".*"  + test + "$" ).test( base ); 
     1120 
     1121          case '&':  return ( base && test ); 
     1122          case '|':  return ( base || test ); 
    10811123 
    10821124          case '=':  return ( base == test ); 
     
    10951137//     }, 
    10961138 
    1097     check: function( namespace, keys ){ 
     1139    check: function( namespace, filter ){ 
    10981140 
    10991141        if( !namespace ) 
     
    11021144        var result = this.storage.get( namespace ); 
    11031145 
    1104         if( !keys || !result ) 
     1146        if( !filter || !result ) 
    11051147          return( result || false ); 
     1148 
     1149        var keys = DataLayer.copy( filter ); 
    11061150 
    11071151        if( notArray = $.type(keys) === "string" ) 
    11081152            keys = [ keys ]; 
    11091153        else if( $.type(keys) !== "array" ) 
    1110             keys = this.filter( result, keys.filter ); 
     1154                keys = this.filter( result, keys.filter, keys.criteria ); 
    11111155 
    11121156        var res = []; 
     
    11361180            delete this.cache[key]; 
    11371181 
     1182        }, 
     1183         
     1184        filter: function( base, filter ){ 
     1185       
     1186            var bool, op = filter.shift(); 
     1187 
     1188            switch( op ) 
     1189            { 
     1190                case 'IN': 
     1191                  for( var i = 0, f = []; i < filter[1].length || !(filter = f); i++ ) 
     1192                      f[i] = [ '=', filter[0], filter[1][i] ]; 
     1193                case 'OR': 
     1194                    op = '|'; 
     1195                    bool = false; 
     1196                break; 
     1197                case 'AND':  
     1198                    op = '&'; 
     1199                    bool = true; 
     1200                break; 
     1201                default : return DataLayer.compare( op, base[ filter[0] ], filter[1] ); 
     1202            } 
     1203             
     1204            for( var strict = bool;  
     1205 
     1206                filter.length && ( strict ? bool : !bool );  
     1207             
     1208                bool = DataLayer.compare( op, bool, this.filter( base, filter.shift() ) ) ); 
     1209 
     1210            return( bool ); 
    11381211        } 
    11391212    }, 
     
    24312504//       } 
    24322505// } 
     2506 
     2507// internalUrl = /^([A-z0-9-_]+)(:[A-z0-9-_]+)?$/; 
     2508// internalUri = /^([a-zA-Z0-9-_]+)\(([a-zA-Z0-9-_]+)\):\/\/(.*)|([a-zA-Z0-9-_]+):\/\/(.*)$/; 
     2509// isGeneratedId = /^\d+\(javascript\)$/; 
     2510// arrayName = /^([A-z0-9-_]+)\[\]$/; 
     2511// startsDoubleDot = /^:/; 
     2512// FILE = 'files'; 
     2513// // cached_urls = {}; 
     2514//  
     2515// $.ajaxPrefilter(function( options, originalOptions, jqXHR ){ 
     2516//  
     2517//       if( options.url != 'undefined' && internalUrl.test( options.url ) ){ 
     2518//  
     2519// //     if( !cached_urls[options.url] ) 
     2520// //         return; 
     2521// //     alert( options.url + " dentro" ); 
     2522//        jqXHR.abort();  
     2523//  
     2524//        var callback = ( options.success || options.complete || $.noop ); 
     2525//  
     2526//        switch( options.type.toUpperCase() ) 
     2527//        { 
     2528//          case 'GET': 
     2529//                return callback( DataLayer.get( options.url, /*false,*/ options.data ) ); 
     2530//  
     2531//          case 'POST': 
     2532//                return callback( DataLayer.put( options.url, options.data ) ); 
     2533//        } 
     2534//  
     2535//        //return( false ); 
     2536//  
     2537// //     options.url = params[1]; 
     2538// //     options.data = ( options.data || "" ) + "&" + params[2]; 
     2539//       } 
     2540//  
     2541// }); 
     2542//  
     2543// // $("a").live("click", function( event ){ 
     2544// //  
     2545// //     event.preventDefault(); 
     2546// //  
     2547// //     $.ajax({ 
     2548// //  
     2549// //    
     2550// //  
     2551// //     }); 
     2552// //  
     2553// // }); 
     2554//  
     2555// $("form").live( "submit", function( event ){ 
     2556//  
     2557//     var $this = $(this), action = $this.attr('action'), res = false, 
     2558//      
     2559//     method = $this.attr( 'method' ), 
     2560//      
     2561//     fileInputs = $this.find('input[type="file"]'); 
     2562//      
     2563//     if( fileInputs.length && !$this.is('[enctype="multipart/form-data"]') ) 
     2564//     { 
     2565//      event.preventDefault(); 
     2566//       
     2567//      var formData = $this.serializeArray(), callback = DataLayer.receive; 
     2568//        
     2569//      if( res = internalUrl.exec( action ) ) 
     2570//      { 
     2571//          var data = {}, action = res[1]; 
     2572//  
     2573//          data[action] = DataLayer.form( this, fileInputs ); 
     2574//  
     2575//          formData = DataLayer.serializeForm( data ); 
     2576//              
     2577//              action = DataLayer.dispatchPath + 'post.php'; 
     2578//          callback = $.noop; 
     2579//      } 
     2580//  
     2581//      DataLayer.send( action,  
     2582//                      [ method, 'iframe json' ], {},  
     2583//                      //TODO: check the type for conversion 
     2584//                      callback,  
     2585//                      false, { 'formData': formData,  'fileInput': fileInputs, 'paramName': FILE + '[]' } ); 
     2586//  
     2587//      return( false ); 
     2588//     } 
     2589//      
     2590//     if( res = internalUrl.exec( action ) ) 
     2591//     { 
     2592//      event.preventDefault(); 
     2593//  
     2594//      var data = DataLayer.form( this ); 
     2595//       
     2596//      switch( method.toUpperCase() ) 
     2597//      { 
     2598//        case 'GET': 
     2599//              DataLayer.get( res[0], data ); 
     2600//  
     2601//        case 'POST': 
     2602//              DataLayer.put( res[1], data ); 
     2603//      } 
     2604//  
     2605//      return( false ); 
     2606//     } 
     2607//  
     2608//     return( true ); 
     2609// }); 
     2610//  
     2611// this.storage = new $.store(); 
     2612//  
     2613// DataLayer = { 
     2614//  
     2615//     links: {}, 
     2616//     concepts: {}, 
     2617//     listeners: {}, 
     2618//     encoders: {}, 
     2619//     decoders: {}, 
     2620//     templates: {}, 
     2621//     criterias: {}, 
     2622//     tasks: [], 
     2623//  
     2624//     render: function( templateName, data, filter, formatter, force ){ 
     2625//  
     2626//      if( $.isFunction( filter ) ) 
     2627//      { 
     2628//          force = formatter; 
     2629//          formatter = filter; 
     2630//          filter = false; 
     2631//      } 
     2632//  
     2633//      if( typeof data === "string" ) 
     2634//      { 
     2635//          data = this.get( data, filter, force ) || {}; 
     2636//      } 
     2637//       
     2638//      var formatting = function( template ){ 
     2639//  
     2640//            if( template === false ) return( false ); 
     2641//  
     2642//            if( template ) 
     2643//                DataLayer.templates[ templateName ] = new EJS({ text: template, cache: false }); 
     2644//  
     2645//            var html = DataLayer.templates[ templateName ].render( { data: data } ); 
     2646//  
     2647//            if( !formatter ) 
     2648//                return( html ); 
     2649//  
     2650//            return formatter( html ); 
     2651//      } 
     2652//  
     2653//      if( this.templates[ templateName ] ) 
     2654//      { 
     2655//          return formatting(); 
     2656//      } 
     2657//  
     2658//      return this.send( DataLayer.templatePath + templateName, 'get', false, formatting, !!!formatter ); 
     2659//     }, 
     2660//      
     2661//     send: function( url, type, data, callback, sync, extraOptions ){ 
     2662//        
     2663//        var result = false, fired = false; 
     2664//        
     2665//        var envelope = { 
     2666//  
     2667//            'async': ( typeof sync !== "undefined" ? !sync : !!callback ), 
     2668//            'url': url, 
     2669//            'success': function( dt, textStatus, jqXHR ){ 
     2670//  
     2671//                  if( callback ) 
     2672//                  { 
     2673//                      fired = true; 
     2674//                      result = callback( dt, textStatus, jqXHR ); 
     2675//                  } 
     2676//                  else 
     2677//                      result = dt; 
     2678//  
     2679//              }, 
     2680//            'complete': function( jqXHR, textStatus ){ 
     2681//  
     2682//                if( !fired && callback ) 
     2683//                    result = callback( false, textStatus, jqXHR ); 
     2684//  
     2685//            }, 
     2686//  
     2687//            'type': $.isArray( type ) ? type[0] : type, 
     2688//            'data': data 
     2689//  
     2690//          }; 
     2691//  
     2692//        if( $.isArray( type ) && type[1] ) 
     2693//            envelope['dataType'] = type[1]; 
     2694//  
     2695//        if( extraOptions ) 
     2696//            envelope = $.extend( envelope, extraOptions ); 
     2697//  
     2698//        $.ajax( envelope ); 
     2699//        
     2700//        return( result ); 
     2701//     }, 
     2702//      
     2703//     dispatch: function( dispatcher, data, callback, isPost, dataType ){ 
     2704//        
     2705//       return this.send( this.dispatchPath + dispatcher + ".php",  
     2706//                      [ ( isPost ? 'post' : 'get' ), dataType || 'json' ], 
     2707//                      data, 
     2708//                      callback ); 
     2709//  
     2710// //       $.ajax({ 
     2711// //         'async': !!callback, 
     2712// //         'url': this.dispatchPath + dispatcher + ".php", 
     2713// //         'type': ( isPost ? 'post' : 'get' ), 
     2714// //         'dataType': 'json', 
     2715// //         'data': data, 
     2716// //         'success': function( dt, textStatus, jqXHR ){ 
     2717// //  
     2718// //               if( callback ) 
     2719// //               { 
     2720// //                   fired = true; 
     2721// //                   callback( dt, textStatus, jqXHR ); 
     2722// //               } 
     2723// //               else 
     2724// //                   result = dt; 
     2725// //  
     2726// //           }, 
     2727// //         'complete': function( jqXHR, textStatus ){ 
     2728// //  
     2729// //             if( !fired && callback ) 
     2730// //                 callback( false, textStatus, jqXHR ); 
     2731// //  
     2732// //         }/*, 
     2733// //         'processData': false*/ 
     2734// //     }); 
     2735//  
     2736//       //return( result ); 
     2737//     }, 
     2738//  
     2739//     form: function( target, fileInputs ){ 
     2740//  
     2741//      var params = {}, $this = $(target), inputArray = $this.serializeArray(); 
     2742//  
     2743//      if( !$this.is( "form" ) ) 
     2744//          $this = $this.parents( "form" ); 
     2745//               
     2746//      if( fileInputs ) 
     2747//              fileInputs.each( function( i, el ){ 
     2748//  
     2749//            inputArray[ inputArray.length ] = { name: $(this).prop("name"), value: FILE + i }; 
     2750//  
     2751//              }); 
     2752//  
     2753//      $.each( inputArray, function( i, el ){ 
     2754//  
     2755//          if( newName = arrayName.exec( el.name ) ) 
     2756//              el.name = newName[1]; 
     2757//          else if( !params[ el.name ] ) 
     2758//              return( params[ el.name ] = el.value ); 
     2759//  
     2760//          params[ el.name ] = params[ el.name ] || []; 
     2761//  
     2762//          if( $.type(params[ el.name ]) !== "array" ) 
     2763//              params[ el.name ] = [ params[ el.name ] ]; 
     2764//  
     2765//          params[ el.name ].push( el.value ); 
     2766//      }); 
     2767//  
     2768// //   alert(dump(params)); 
     2769//  
     2770//      return this.decode( $this.attr( "action" ), params ); 
     2771//     }, 
     2772//       
     2773//      serializeForm: function( data, level ){ 
     2774//       
     2775//              var formData = []; 
     2776//       
     2777//              for( key in data ) 
     2778//              { 
     2779//                      var value = data[key]; 
     2780//  
     2781//                      if( level !== undefined ) 
     2782//                              key = level+'['+key+']'; 
     2783//  
     2784//                      if( $.isArray(value) || $.isPlainObject(value) ) 
     2785//                              formData = formData.concat( this.serializeForm( value, key ) ); 
     2786//                      else 
     2787//                              formData[ formData.length ] = { name: key, value: value }; 
     2788//              } 
     2789//               
     2790//              return( formData ); 
     2791//      }, 
     2792//  
     2793//     blend: function( action, data ){ 
     2794//  
     2795// //   if( notArray = (!$.isArray(data)) ) 
     2796// //       data = [ data ]; 
     2797//  
     2798//      var form = $('form[action="'+action+'"]'); 
     2799//  
     2800//      form.get(0).reset(); 
     2801//  
     2802//      var named = form.find( 'input[name]' ); 
     2803//  
     2804//      for( var name in data ) 
     2805//      { 
     2806//          named.filter( '[name="'+name+'"]' ).val( data[name] ); 
     2807//      } 
     2808//     }, 
     2809//  
     2810//   
     2811//      
     2812//     put: function( concept, filter, data, oneSide ){ 
     2813//        
     2814//       ///////////////////////////// normalize //////////////////////////////// 
     2815//      if( arguments.length == 2 ) 
     2816//      { 
     2817//          data = filter; 
     2818//          filter = false; 
     2819//      } 
     2820//      if( typeof data === "undefined" || 
     2821//          $.type(data) === "boolean" ) 
     2822//      { 
     2823//          oneSide = data; 
     2824//          data = filter; 
     2825//          filter = false; 
     2826//      } 
     2827//       
     2828//      if( !concept || !data ) 
     2829//          return( false ); 
     2830//  
     2831//      var decoder = "", id = false, bothSides = (typeof oneSide === "undefined"), notArray, res; 
     2832//       
     2833//      if( $.type(filter) === "string" ) 
     2834//      { 
     2835//          id = filter; 
     2836//          filter = false; 
     2837//      } 
     2838//  
     2839//      if( id ) 
     2840//          data.id = id; 
     2841//  
     2842//      if( notArray = ( $.type( data ) !== "array" ) ) 
     2843//          data = [ data ]; 
     2844//  
     2845//      if( res = internalUrl.exec( concept ) ) 
     2846//      { 
     2847//          //TODO: verificar se a decodificaçao deve ser feita em cada item do array 
     2848//          data = this.decode( concept, data ); 
     2849//          concept = res[1]; 
     2850//          decoder = res[2]; 
     2851//      } 
     2852//  
     2853//       //////////////////////////////////////////////////////////////////////// 
     2854//  
     2855//      if( bothSides || !oneSide ) 
     2856//      { 
     2857//          var result = false, links = this.links( concept ),  
     2858//          current = this.check( concept ) || {}, ids = []; 
     2859//  
     2860//          for( var i = 0; i < data.length; i++ ) 
     2861//          { 
     2862//              var key = ids[ ids.length ] = data[i].id || this.generateId( concept ), updateSet = {}; 
     2863//  
     2864//              ////////////////////////////// linkage /////////////////////////////////     
     2865//              for( var link in links ) 
     2866//              { 
     2867//                  if( data[i][link] ) 
     2868//                  { 
     2869//                      var isConcept = false; 
     2870//                     
     2871//                      if( isConcept = this.isConcept( concept, link ) ) 
     2872//                          data[i][link] = [ data[i][link] ]; 
     2873//  
     2874//                      var _this = this; 
     2875//  
     2876//                      $.each( data[i][link], function( ii, el ){ 
     2877//  
     2878//                              var isRef = false; 
     2879//  
     2880//                              if( isRef = ($.type(el) === "string") ) 
     2881//                                  el = { id: el }; 
     2882//  
     2883//                              var nestedLinks = _this.links( links[link], true ); 
     2884//                              //removido pois o mesmo esta gerando inconsistencia em tudo 
     2885//                              //if( DataLayer.isConcept( links[link], nestedLinks[concept] ) ) 
     2886//                              if( isConcept ) 
     2887//                              { 
     2888//                                  el[ nestedLinks[link] ] = el[ nestedLinks[link] ] || []; 
     2889//                                  el[ nestedLinks[link] ].push( key ); 
     2890//                              } 
     2891//                              else 
     2892//                                  el[ nestedLinks[link] ] = key; 
     2893//  
     2894//                              if( isRef && ( !current[ key ] || !current[ key ][ link ] ||  
     2895//                                             (isConcept ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) ) 
     2896//                              { 
     2897//                                  updateSet[ links[link] ] = updateSet[ links[link] ] || []; 
     2898//                                  updateSet[ links[link] ].push( el ); 
     2899//                              } 
     2900//                              else if( !isRef ) 
     2901//                                  data[i][link][ii] = _this.put( links[link], el, oneSide ); 
     2902//                          }); 
     2903//  
     2904//                      if( isConcept ) 
     2905//                          data[i][link] = data[i][link][0]; 
     2906//                  } 
     2907//              } 
     2908//              ////////////////////////////////////////////////////////////////////////// 
     2909//  
     2910//              if( data[i].id ) 
     2911//                  data[i] = this.merge( current[ data[i].id ], data[i] ); 
     2912//  
     2913//               current[ key ] = data[i]; 
     2914//  
     2915//              if( bothSides ) 
     2916//                this.report( concept, key, data[i] ); 
     2917//          } 
     2918//  
     2919//          this.store( concept, current ); 
     2920//  
     2921//          for( var setKey in updateSet ) 
     2922//          { 
     2923//              if( bothSides ) 
     2924//                  for( var i = 0; i < updateSet[ setKey ].length; i++ ) 
     2925//                    this.report( setKey, updateSet[ setKey ][i].id, updateSet[ setKey ][i] ); 
     2926//                   
     2927//              DataLayer.put( setKey, updateSet[ setKey ], false ); 
     2928//          } 
     2929//      } 
     2930//  
     2931//      if( oneSide )  
     2932//          this.commit( concept, ids/*, true */); 
     2933//  
     2934//      this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', true ); 
     2935//  
     2936//      return( notArray ? ids[0] : ids ); 
     2937//  
     2938//     }, 
     2939//      
     2940//     remove: function( concept, id, oneSide ){ 
     2941//        
     2942//      var bothSides = (typeof oneSide === "undefined"), 
     2943//  
     2944//      links = this.links( concept ), ids = [], 
     2945//  
     2946//      current = this.check( concept, id ); 
     2947//  
     2948//      if( !current ) return; 
     2949//       
     2950//      if( id ) 
     2951//          current.id = id; 
     2952//  
     2953//      if( notArray = ( $.type( current ) !== "array" ) ) 
     2954//          current = [ current ]; 
     2955//  
     2956//      for( var i = 0; i < current.length; i++ ) 
     2957//      { 
     2958//          var currentId = ids[ ids.length ] = current[i].id; 
     2959//  
     2960//          if( bothSides ) 
     2961//            this.report( concept, currentId, false ); 
     2962//  
     2963//          if( bothSides || !oneSide ) 
     2964//            this.del( concept, currentId ); 
     2965//  
     2966//          for( var link in links ) 
     2967//          { 
     2968//              if( !current[i][link] ) 
     2969//                  continue; 
     2970//  
     2971//              var nestedLinks = this.links( links[link], true ); 
     2972//  
     2973//              if( isConcept = this.isConcept( concept, link ) ) 
     2974//                  current[i][link] = [ current[i][link] ]; 
     2975//  
     2976//              $.each( current[i][link], function( ii, el ){ 
     2977//  
     2978//                      el = DataLayer.storage.cache[links[link]][el]; 
     2979//  
     2980//                      if( notArrayNested = ( $.type( el[ nestedLinks[link] ] ) !== "array" ) ) 
     2981//                          el[ nestedLinks[link] ] = [ el[nestedLinks[link]] ]; 
     2982//  
     2983//                      el[ nestedLinks[link] ] = $.grep( el[ nestedLinks[link] ], function( nested, iii ){ 
     2984//                          return ( currentId !== nested ); 
     2985//                      }); 
     2986//  
     2987//                      if( notArrayNested ) 
     2988//                          el[ nestedLinks[link] ] = el[ nestedLinks[link] ][0] || false; 
     2989//                      if(!el[ nestedLinks[link] ] || !el[ nestedLinks[link] ].length) 
     2990//                              delete el[ nestedLinks[link] ]; 
     2991//              }); 
     2992//          } 
     2993//      } 
     2994//  
     2995//      if( oneSide ) 
     2996//          this.commit( concept, ids ); 
     2997//  
     2998//      this.broadcast( concept, oneSide ? 'server' : bothSides ? 'serverclient' : 'client', false ); 
     2999//     }, 
     3000//      
     3001//     report: function( concept, id, data ) 
     3002//     {       
     3003//      var current = this.check( ':current', concept ) || {}; 
     3004//  
     3005//      if( !current[ id ] ) 
     3006//          current[ id ] = this.check( concept, id ) || {}; 
     3007//       
     3008//      this.store( ':current', concept, current ); 
     3009//  
     3010//      var diff = this.diff( current[ id ], data ); 
     3011//  
     3012//      var diffs = this.check( ':diff', concept ) || {}; 
     3013//  
     3014//      if( diffs[ id ] ) 
     3015//          diff = this.merge( diffs[ id ], diff ); 
     3016//  
     3017//      if( !diff || !$.isEmptyObject( diff ) ) 
     3018//          diffs[ id ] = diff; 
     3019//  
     3020//      this.store( ':diff', concept, diffs ); 
     3021//     }, 
     3022//  
     3023// //     enqueue: function( queueName, concept, id, data ){ 
     3024// //  
     3025// //   var queue = this.check( ':' + queueName, concept ) || {}; 
     3026// //  
     3027// //  
     3028// //     }, 
     3029// //      
     3030// //     dequeue: function( queueName, concept, id ){ 
     3031// //  
     3032// //    
     3033// //  
     3034// //     }, 
     3035//      
     3036//      
     3037//      
     3038//     rollback: function( concept, ids ){ 
     3039//        
     3040//      var queue = this.prepareQ( 'current', concept, ids ); 
     3041//  
     3042//      ids = []; 
     3043//  
     3044//      for( var id in queue ) 
     3045//      { 
     3046//           this.put( concept, id, queue[id], false ); 
     3047//  
     3048//           ids[ ids.length ] = id; 
     3049//      } 
     3050//  
     3051//      this.clearQ( concept, ( ids.length ? ids : false ) ); 
     3052//  
     3053//      this.broadcast( concept, 'revert' ); 
     3054//        
     3055//     }, 
     3056//      
     3057//     prepareQ: function( queueName, concept, ids ){ 
     3058//        
     3059//       var notArray = false; 
     3060//        
     3061//       if( notArray = ($.type(concept) !== "array") ) 
     3062//        concept = [ concept ]; 
     3063//        
     3064//       var q = {}; 
     3065//        
     3066//       for( var i = 0; i < concept.length; i++ ) 
     3067//       { 
     3068//        var queue = this.check( ':' + queueName, concept[i] || false ); 
     3069//         
     3070//        if( !queue ) continue; 
     3071//  
     3072//        if( ids ) 
     3073//        { 
     3074//            if( $.type(ids) !== "array" ) 
     3075//                ids = [ ids ]; 
     3076//  
     3077//            var filtered = {}; 
     3078//  
     3079//            for( var ii = 0; ii < ids.length; ii++ ) 
     3080//            { 
     3081//                filtered[ ids[ii] ] = queue[ ids[ii] ]; 
     3082//            } 
     3083//  
     3084//            queue = filtered; 
     3085//        } 
     3086//  
     3087//        q[ concept[i] ] = queue; 
     3088//       } 
     3089//        
     3090//       return( notArray ? q[ concept[0] ] : q ); 
     3091//     }, 
     3092//      
     3093//     clearQ: function( concept, ids ){ 
     3094//        
     3095//              var current = this.check( ':current', concept || false ); 
     3096//      var diffs = this.check( ':diff', concept || false ); 
     3097//  
     3098//      if( !ids ) 
     3099//          current = diffs = {}; 
     3100//      else 
     3101//      { 
     3102//          if( notArray = ($.type(ids) !== "array") ) 
     3103//            ids = [ ids ]; 
     3104//  
     3105//          for( var i = 0; i < ids.length; i++ ) 
     3106//          { 
     3107//              delete current[ ids[i] ]; 
     3108//              delete diffs[ ids[i] ]; 
     3109//          } 
     3110//      } 
     3111//  
     3112//      this.store( ':current', concept, current ); 
     3113//      this.store( ':diff', concept, diffs ); 
     3114//     }, 
     3115//  
     3116//     commit: function( concept, ids, callback ){ 
     3117//        
     3118//      var queue = this.prepareQ( 'diff', concept, ids ); 
     3119//  
     3120//      this.sync( queue, !$.isArray(concept) && concept || false, callback ); 
     3121//     }, 
     3122//      
     3123//     sync: function( queue, concept, callback ){ 
     3124//  
     3125//      if( !queue || $.isEmptyObject( queue ) ) 
     3126//          return; 
     3127//  
     3128//      if( concept ) 
     3129//      { 
     3130//        var helper = {};  
     3131//        helper[concept] = queue;  
     3132//        queue = helper; 
     3133//      } 
     3134//  
     3135//      var data = {}, URIs = {}; 
     3136//  
     3137//      for( var concept in queue ) 
     3138//          for( var id in queue[concept] ) 
     3139//          { 
     3140//              data[ this.URI( concept, id ) ] = queue[concept][id]; 
     3141//              URIs[ this.URI( concept, id ) ] = { concept: concept, id: id }; 
     3142//          } 
     3143//  
     3144//      if( $.isEmptyObject( data ) ) 
     3145//          return; 
     3146//  
     3147//      this.dispatch( "Sync", data, function( data, status, jqXHR ){ 
     3148//  
     3149// //       switch( status ) 
     3150// //       { 
     3151// //         case "error": 
     3152// //         case "parsererror": 
     3153// //           return DataLayer.rollback( concept, URI ); 
     3154// //         case "success": 
     3155// //           return DataLayer.commit(); 
     3156// //         case "timeout": 
     3157// //         case "notmodified": 
     3158// //       } 
     3159//  
     3160//          var received = DataLayer.receive( data ); 
     3161//  
     3162//          for( var URI in URIs ) 
     3163//              if( typeof received[URI] !== "undefined" ) 
     3164//                  DataLayer.clearQ( URIs[URI].concept, URIs[URI].id ); 
     3165//  
     3166//          if( callback ) 
     3167//              callback( received ); 
     3168//  
     3169// //       for( var URI in data ) 
     3170// //       {  
     3171// //           var parsed = DataLayer.parseURI( URI ), 
     3172// //     
     3173// //           concept = parsed[1], id = parsed[3]; 
     3174// //  
     3175// //           if( $.type(data[URI]) === "string" ) 
     3176// //           { 
     3177// //             //TODO:threat the exception thrown 
     3178// //             DataLayer.rollback( concept, id ); 
     3179// //             delete URIs[ URI ]; 
     3180// //             continue; 
     3181// //           } 
     3182// //  
     3183// //           if( data[URI] === false ){ 
     3184// //             DataLayer.remove( concept, id, false ); 
     3185// //             continue; 
     3186// //           } 
     3187// //  
     3188// //           if( id !== data[URI].id ) 
     3189// //             DataLayer.move( concept, id, data[URI].id ); 
     3190// //            
     3191// //           DataLayer.put( concept, id, data[URI], false ); 
     3192// //       } 
     3193// //        
     3194// //       for( var URI in URIs ) 
     3195// //            DataLayer.clearQ( URIs[URI].concept, URIs[URI].id ); 
     3196// //        
     3197// //       if( callback ) 
     3198// //           callback(); 
     3199//  
     3200//      }, true ); 
     3201//  
     3202//     }, 
     3203//      
     3204//     receive: function( data ){ 
     3205//        
     3206//      var received = {}; 
     3207//       
     3208//          for( var URI in data ) 
     3209//          {  
     3210//              var parsed = DataLayer.parseURI( URI ), 
     3211//     
     3212//          concept = parsed[4], id = parsed[5]; 
     3213//  
     3214//          received[ URI ] = data[ URI ]; 
     3215//  
     3216//              if( $.type(data[URI]) === "string" ) 
     3217//              { 
     3218//                //TODO:threat the exception thrown 
     3219//                DataLayer.rollback( concept, id ); 
     3220//                continue; 
     3221//              } 
     3222//  
     3223//              if( data[URI] === false ){ 
     3224//                DataLayer.remove( concept, id, false ); 
     3225//                continue; 
     3226//              } 
     3227//  
     3228//              if( id !== data[URI].id ) 
     3229//                DataLayer.move( concept, id, data[URI].id ); 
     3230//               
     3231//              DataLayer.put( concept, id, data[URI], false ); 
     3232//          } 
     3233//           
     3234//      return( received ); 
     3235//           
     3236//     }, 
     3237//      
     3238//     unique: function( origArr ){  
     3239//  
     3240//      var newArr = []; 
     3241//        
     3242//      for ( var x = 0; x < origArr.length; x++ ) 
     3243//      { 
     3244//              var found = false; 
     3245//          for ( var y = 0; !found && y < newArr.length; y++ )  
     3246//              if ( origArr[x] === newArr[y] )   
     3247//                found = true; 
     3248//  
     3249//          if ( !found )  
     3250//              newArr[ newArr.length ] = origArr[x]; 
     3251//      } 
     3252//  
     3253//      return newArr; 
     3254//     }, 
     3255//  
     3256//     merge: function( current, data ){ 
     3257//        
     3258//      return this.copy(  data, current ); 
     3259//  
     3260// //   return $.extend( current, data ); 
     3261//  
     3262//     }, 
     3263//      
     3264//     // clone objects, skip other types. 
     3265//     clone: function(target) { 
     3266//          if ( typeof target == 'object' ) { 
     3267//                  Clone.prototype = target; 
     3268//                  return new Clone(); 
     3269//          } else { 
     3270//                  return target; 
     3271//          } 
     3272//     }, 
     3273//        
     3274//     // Shallow Copy  
     3275//     shallowCopy: function(target) { 
     3276//          if (typeof target !== 'object' ) { 
     3277//                  return target;  // non-object have value sematics, so target is already a copy. 
     3278//          } else { 
     3279//                  var value = target.valueOf(); 
     3280//                  if (target != value) {  
     3281//                          // the object is a standard object wrapper for a native type, say String. 
     3282//                          // we can make a copy by instantiating a new object around the value. 
     3283//                          return new target.constructor(value); 
     3284//                  } else { 
     3285//                          // ok, we have a normal object. If possible, we'll clone the original's prototype  
     3286//                          // (not the original) to get an empty object with the same prototype chain as 
     3287//                          // the original.  If just copy the instance properties.  Otherwise, we have to  
     3288//                          // copy the whole thing, property-by-property. 
     3289//                          if ( target instanceof target.constructor && target.constructor !== Object ) {  
     3290//                                  var c = clone(target.constructor.prototype); 
     3291//        
     3292//                                  // give the copy all the instance properties of target.  It has the same 
     3293//                                  // prototype as target, so inherited properties are already there. 
     3294//                                  for ( var property in target) {  
     3295//                                          if (target.hasOwnProperty(property)) { 
     3296//                                                  c[property] = target[property]; 
     3297//                                          }  
     3298//                                  } 
     3299//                          } else { 
     3300//                                  var c = {}; 
     3301//                                  for ( var property in target ) c[property] = target[property]; 
     3302//                          } 
     3303//                           
     3304//                          return c; 
     3305//                  } 
     3306//          } 
     3307//     }, 
     3308//  
     3309//     // entry point for deep copy. 
     3310//     // source is the object to be deep copied. 
     3311//     // depth is an optional recursion limit. Defaults to 256. 
     3312//     // deep copy handles the simple cases itself: non-objects and object's we've seen before. 
     3313//     // For complex cases, it first identifies an appropriate DeepCopier, then delegate the details of copying the object to him. 
     3314//     copy: function(source, result, depth) { 
     3315//        
     3316//          // null is a special case: it's the only value of type 'object' without properties. 
     3317//          if ( source === null ) return null; 
     3318//  
     3319//          // All non-objects use value semantics and don't need explict copying. 
     3320//          if ( typeof source !== 'object' ) return source; 
     3321//  
     3322//          if( !depth || !(depth instanceof RecursionHelper) ) depth = new RecursionHelper(depth); 
     3323//  
     3324//          var cachedResult = depth.getCachedResult(source); 
     3325//  
     3326//          // we've already seen this object during this deep copy operation 
     3327//          // so can immediately return the result.  This preserves the cyclic 
     3328//          // reference structure and protects us from infinite recursion. 
     3329//          if ( cachedResult ) return cachedResult; 
     3330//  
     3331//          // objects may need special handling depending on their class.  There is 
     3332//          // a class of handlers call "DeepCopiers"  that know how to copy certain 
     3333//          // objects.  There is also a final, generic deep copier that can handle any object. 
     3334//          for ( var i=0; i<this.comparators.length; i++ ) { 
     3335//  
     3336//                  var comparator = this.comparators[i]; 
     3337//  
     3338//                  if ( comparator.can(source) ) { 
     3339//       
     3340//                          // once we've identified which DeepCopier to use, we need to call it in a very 
     3341//                          // particular order: create, cache, populate.  This is the key to detecting cycles. 
     3342//                          // We also keep track of recursion depth when calling the potentially recursive 
     3343//                          // populate(): this is a fail-fast to prevent an infinite loop from consuming all 
     3344//                          // available memory and crashing or slowing down the browser. 
     3345//        
     3346//                          if( !result ) 
     3347//                              // Start by creating a stub object that represents the copy. 
     3348//                              result = comparator.create(source); 
     3349//                          else if( !comparator.can(result) ) 
     3350//                              throw new Error("can't compare diferent kind of objects."); 
     3351//  
     3352//                          // we now know the deep copy of source should always be result, so if we encounter 
     3353//                          // source again during this deep copy we can immediately use result instead of 
     3354//                          // descending into it recursively.   
     3355//                          depth.cacheResult(source, result); 
     3356//  
     3357//                          // only DeepCopier.populate() can recursively deep copy.  So, to keep track 
     3358//                          // of recursion depth, we increment this shared counter before calling it, 
     3359//                          // and decrement it afterwards. 
     3360//                          depth.depth++; 
     3361//                          if ( depth.depth > depth.maxDepth ) { 
     3362//                                  throw new Error("Exceeded max recursion depth in deep copy."); 
     3363//                          } 
     3364//  
     3365//                          // It's now safe to let the comparator recursively deep copy its properties. 
     3366//                          var returned = comparator.populate( function(source, result) { return DataLayer.copy(source, result, depth); }, source, result ); 
     3367//       
     3368//                              if(returned) 
     3369//                                      result = returned; 
     3370//  
     3371//                          depth.depth--; 
     3372//  
     3373//                          return result; 
     3374//                  } 
     3375//          } 
     3376//          // the generic copier can handle anything, so we should never reach this line. 
     3377//          throw new Error("no DeepCopier is able to copy " + source); 
     3378//     }, 
     3379//  
     3380//     // publicly expose the list of deepCopiers. 
     3381//     comparators: [], 
     3382//  
     3383//     // make deep copy() extensible by allowing others to  
     3384//     // register their own custom Comparators. 
     3385//     registerComparator: function(comparatorOptions) { 
     3386//  
     3387//        // publicly expose the Comparator class. 
     3388//        var comparator = { 
     3389//  
     3390//            // determines if this Comparator can handle the given object. 
     3391//            can: function(source) { return false; }, 
     3392//      
     3393//            // starts the deep copying process by creating the copy object.  You 
     3394//            // can initialize any properties you want, but you can't call recursively 
     3395//            // into the copy(). 
     3396//            create: function(source) { }, 
     3397//  
     3398//            // Completes the deep copy of the source object by populating any properties 
     3399//            // that need to be recursively deep copied.  You can do this by using the 
     3400//            // provided deepCopyAlgorithm instance's copy() method.  This will handle 
     3401//            // cyclic references for objects already deepCopied, including the source object 
     3402//            // itself.  The "result" passed in is the object returned from create(). 
     3403//            populate: function(deepCopyAlgorithm, source, result) {} 
     3404//        }; 
     3405//  
     3406//        for ( var key in comparatorOptions ) comparator[key] = comparatorOptions[key]; 
     3407//  
     3408//        this.comparators.unshift( comparator ); 
     3409//     }, 
     3410//   
     3411//     diff: function( base, toDiff ){ 
     3412//  
     3413//      if( typeof base === 'undefined' || $.isEmptyObject(base) ) 
     3414//          return( toDiff ); 
     3415//  
     3416//      if( toDiff === false ) 
     3417//          return( false ); 
     3418//  
     3419//      toDiff = $.extend( {}, toDiff ); 
     3420//  
     3421//      for( var key in toDiff ) 
     3422//      { 
     3423//          switch( $.type(toDiff[key]) ) 
     3424//          { 
     3425//            case 'object':  
     3426//              if( $.isEmptyObject(toDiff[key] = this.diff( base[key], toDiff[key] )) ) 
     3427//                delete toDiff[key]; 
     3428//            break; 
     3429//            case 'array': 
     3430//              if( base[key] && !(toDiff[key] = $.grep( toDiff[key], function( el, i ){ return( $.inArray( el, base[key] ) === -1 ); } )).length ) 
     3431//                delete toDiff[key]; 
     3432//            break; 
     3433//            default: 
     3434//              if( base[key] == toDiff[key] ) 
     3435//                delete toDiff[key]; 
     3436//          } 
     3437//      } 
     3438//  
     3439//      return( toDiff ); 
     3440//  
     3441//     }, 
     3442//      
     3443//     links: function( concept, reverse ){ 
     3444//  
     3445//      if( !this.links[ concept ] ) 
     3446//      { 
     3447//          var result = this.dispatch( "links", { concept: concept } ) || false; 
     3448//  
     3449//          if( !result ) 
     3450//              return( false ); 
     3451//  
     3452//          this.concepts[ concept ] = $.extend( this.concepts[ concept ] || {},  
     3453//                                               result['concepts'] || {} ); 
     3454//  
     3455//          this.links[ concept ] =  result['links'] || {}; 
     3456//          this.nestedLinks[ concept ] = result['nestedLinks'] || {}; 
     3457//      } 
     3458//  
     3459//      if( reverse ) 
     3460//      { 
     3461//          return( this.nestedLinks[ concept ] ); 
     3462// //       var reverted = {}, llinks = this.links[ concept ]; 
     3463// //      
     3464// //       for( var key in llinks ) 
     3465// //           reverted[ llinks[key] ] = key; 
     3466// //  
     3467// //       return( reverted ); 
     3468//      } 
     3469//  
     3470//      return( this.links[ concept ] ); 
     3471//  
     3472//     }, 
     3473//      
     3474//     isConcept: function( concept, attr ){ 
     3475//        
     3476//      if( typeof this.concepts[concept] === "undefined" ) 
     3477//      { 
     3478//          this.links( concept ); 
     3479//      } 
     3480//  
     3481//      return !!this.concepts[ concept ][ attr ]; 
     3482//     }, 
     3483//      
     3484//     URI: function( concept, URI, context ){ 
     3485//        
     3486//      if( res = internalUrl.exec( concept ) ) 
     3487//          concept = res[1]; 
     3488//       
     3489//      context = context ? "(" + context + ")" : ""; 
     3490//        
     3491//      if( URI ) 
     3492//          return( concept + context + "://" + URI ); 
     3493//      else 
     3494//          return( concept ); 
     3495//        
     3496//     }, 
     3497//      
     3498//     parseURI: function( URI ){ 
     3499//  
     3500//      return internalUri.exec( URI ) || false; 
     3501//  
     3502//     }, 
     3503//      
     3504//      
     3505//     
     3506//      
     3507//     generateId: function( concept ){ 
     3508//        
     3509//      var newId = this.counter + "(javascript)"; 
     3510//        
     3511//      this.store( ":counter", (this.counter++) + "" ); 
     3512//       
     3513//      return( newId ); 
     3514//     }, 
     3515//     
     3516//  
     3517//     
     3518//  
     3519//     get: function( concept, /*URI, */filter, oneSide ){ 
     3520//  
     3521//      ///////////////////////////// normalize //////////////////////////////// 
     3522//      if( arguments.length == 2 && $.type(filter) === "boolean" ) 
     3523//      { 
     3524//          oneSide = filter; 
     3525//          filter = false; 
     3526//      } 
     3527//       
     3528//      var encoder = false, id = false, bothSides = (typeof oneSide === 'undefined'), res; 
     3529//       
     3530//      if( $.type(filter) === "string" ) 
     3531//      { 
     3532//          id = filter; 
     3533//          filter = false; 
     3534//      } 
     3535//  
     3536//      filter = filter || false; 
     3537//  
     3538//      if( !concept ) 
     3539//          return( false ); 
     3540//  
     3541//      if( res = internalUrl.exec( concept ) ) 
     3542//      { 
     3543//          encoder = concept; 
     3544//          concept = res[1]; 
     3545//  
     3546//          if( filter ) 
     3547//              filter = this.criteria( encoder, filter ); 
     3548//      } 
     3549//       
     3550//      if ( $.type(filter) === "array" ) 
     3551//      { 
     3552//          filter = { filter: filter, criteria: false }; 
     3553//      } 
     3554//       
     3555//      ////////////////////////////////////////////////////////////////////////// 
     3556//       
     3557//      var result = false; 
     3558//  
     3559//      if( bothSides || !oneSide ) 
     3560//          result = this.check( concept, id || filter ); 
     3561//  
     3562//      if( !result && (bothSides || oneSide) ) 
     3563//      { 
     3564//          result = this.request( concept, id || filter.filter, filter.criteria ); 
     3565//  
     3566//          if( result && bothSides && (!filter ||  
     3567//                                      !filter.criteria ||  
     3568//                                      !filter.criteria.format) ) 
     3569//          { 
     3570//            var newResult = []; 
     3571//           
     3572//            for( var i = 0; i < result.length; i++ ) 
     3573//                newResult[i] = $.extend( {}, result[i] ); 
     3574//  
     3575//            this.put( concept, id, newResult, false ); 
     3576//          } 
     3577//      } 
     3578//  
     3579//      if( /*result &&*/ encoder ) 
     3580//          result = this.encode( encoder, result, filter ); //TODO: retirar o filtro no método encode 
     3581//  
     3582//      return( result ); 
     3583//     }, 
     3584//      
     3585//     filter: function( base, filter, criteria ){ 
     3586//        
     3587//      var filtered = []; 
     3588//        
     3589//      for( var key in base ) 
     3590//      { 
     3591// //       if( !noGroup ) 
     3592// //           for( var i = 0, current = original; i < filter.length && ( current === original ); i++ ) 
     3593// //               current = this.compare( operator, current, this.compare( base[key], filter[i] ) ); 
     3594//  
     3595//          if( this.storage.filter( base[key], filter ) ) 
     3596//              filtered[ filtered.length ] = key; 
     3597//      } 
     3598//  
     3599//      return( filtered ); 
     3600//     }, 
     3601//      
     3602//     compare: function( operator, base, test ){ 
     3603//        
     3604//       switch( operator ) 
     3605//       { 
     3606//        case '*':  return RegExp( ".*" + test + ".*" ).test( base ); 
     3607//        case '^':  return RegExp( "^" + test +  ".*" ).test( base ); 
     3608//        case '$':  return RegExp( ".*"  + test + "$" ).test( base ); 
     3609//  
     3610//        case '&':  return ( base && test ); 
     3611//        case '|':  return ( base || test ); 
     3612//  
     3613//        case '=':  return ( base == test ); 
     3614//        case '<=': return ( base <= test ); 
     3615//        case '>=': return ( base >= test ); 
     3616//        case '>':  return ( base <  test ); 
     3617//        case '<':  return ( base >  test ); 
     3618//       } 
     3619//        
     3620//     }, 
     3621//      
     3622// //     clone: function( object ){ 
     3623// //  
     3624// //   new { prototype: object }; 
     3625// //  
     3626// //     }, 
     3627//  
     3628//     check: function( namespace, keys ){ 
     3629//  
     3630//      if( !namespace ) 
     3631//          return( false ); 
     3632//  
     3633//      var result = this.storage.get( namespace ); 
     3634//  
     3635//      if( !keys || !result ) 
     3636//        return( result || false ); 
     3637//  
     3638//      if( notArray = $.type(keys) === "string" ) 
     3639//          keys = [ keys ]; 
     3640//      else if( $.type(keys) !== "array" ) 
     3641//          keys = this.filter( result, keys.filter, keys.criteria ); 
     3642//  
     3643//      var res = []; 
     3644//  
     3645//      for( var i = 0; i < keys.length; i++ ) 
     3646//          res[ res.length ] = result[keys[i]]; 
     3647//  
     3648//      return( notArray ? res[0] || false : res.length ? res : false ); 
     3649//     }, 
     3650//  
     3651//     storage: { 
     3652//        
     3653//      cache: {}, 
     3654//        
     3655//      set: function( key, value ){ 
     3656//  
     3657//          this.cache[key] = value; 
     3658//  
     3659//      }, 
     3660//      get: function( key ){ 
     3661//  
     3662//          return DataLayer.copy( this.cache[key] ); 
     3663//  
     3664//      }, 
     3665//      del: function( key ){ 
     3666//  
     3667//          delete this.cache[key]; 
     3668//  
     3669//      }, 
     3670//       
     3671//      filter: function( base, filter ){ 
     3672//        
     3673//          var bool, op = filter.shift(); 
     3674//  
     3675//          switch( op ) 
     3676//          { 
     3677//              case 'IN': 
     3678//                for( var i = 0, f = []; i < filter[1].length || !(filter = f); i++ ) 
     3679//                    f[i] = [ '=', filter[0], filter[1][i] ]; 
     3680//              case 'OR': 
     3681//                  op = '|'; 
     3682//                  bool = false; 
     3683//              break; 
     3684//              case 'AND':  
     3685//                  op = '&'; 
     3686//                  bool = true; 
     3687//              break; 
     3688//              default : return DataLayer.compare( op, base[ filter[0] ], filter[1] ); 
     3689//          } 
     3690//           
     3691//          for( var strict = bool;  
     3692//  
     3693//              filter.length && ( strict ? bool : !bool );  
     3694//           
     3695//              bool = DataLayer.compare( op, bool, this.filter( base, filter.shift() ) ) ); 
     3696//  
     3697//          return( bool ); 
     3698//      } 
     3699//     }, 
     3700//  
     3701//     flush: function(){ 
     3702//  
     3703//     }, 
     3704//      
     3705//     restore: function(){ 
     3706//        
     3707//     }, 
     3708//  
     3709//     store: function( namespace, key, data ){ 
     3710//  
     3711//      if( !data ) 
     3712//        return this.storage.set( namespace, key ); 
     3713//  
     3714//      var res = this.check( namespace ) || {}; 
     3715//  
     3716//      res[key] = data; 
     3717//  
     3718//      return this.storage.set( namespace, res ); 
     3719//     }, 
     3720//  
     3721//     del: function( namespace, key ){ 
     3722//        
     3723//      if( !key ) 
     3724//        return this.storage.del( namespace ); 
     3725//  
     3726//      var res = this.check( namespace ) || {}; 
     3727//  
     3728//      delete res[key]; 
     3729//  
     3730//      return this.storage.set( namespace, res ); 
     3731//        
     3732//     }, 
     3733//      
     3734//      move: function( concept, oldId, newId ){ 
     3735//  
     3736//      this.put( concept, newId, this.check( concept, oldId ), false ); 
     3737//  
     3738//      this.remove( concept, oldId, false ); 
     3739//     }, 
     3740//      
     3741//  
     3742//      
     3743//      
     3744//      
     3745//     request: function( concept, filter, criteria ){ 
     3746//  
     3747//       var id = false, criteria = criteria || {}; 
     3748//  
     3749//       if( $.type(filter) === "string" ) 
     3750//       { 
     3751//        id = filter; 
     3752//        filter = false; 
     3753//       } 
     3754//  
     3755//       return this.dispatch( "request", {  
     3756//  
     3757//        concept: concept || '', 
     3758//        id: id || '', 
     3759//        filter: filter || '', 
     3760//        criteria: criteria || '', 
     3761//        service: criteria.service || '', 
     3762//        properties: criteria.properties || '' 
     3763//  
     3764//       } ); 
     3765//     }, 
     3766//  
     3767//      
     3768//     //         sync: function( data, callback ){ 
     3769// //  
     3770// //   if( !data || $.isEmptyObject( data ) ) 
     3771// //       return; 
     3772// //        
     3773// //   this.send( "Sync", data, function( data, status, jqXHR ){ 
     3774// //  
     3775// // //            switch( status ) 
     3776// // //            { 
     3777// // //              case "error": 
     3778// // //              case "parsererror": 
     3779// // //                return DataLayer.rollback( concept, URI ); 
     3780// // //              case "success": 
     3781// // //                return DataLayer.commit(); 
     3782// // //              case "timeout": 
     3783// // //              case "notmodified": 
     3784// // //            } 
     3785// //  
     3786// //       if( callback ) 
     3787// //       { 
     3788// //           var result = callback( data, status, jqXHR ); 
     3789// //  
     3790// //           if( result === false ) 
     3791// //               return; 
     3792// //           else if( typeof result != "undefined" ) 
     3793// //               data = result; 
     3794// //       } 
     3795// //  
     3796// //       for( var URI in data ) 
     3797// //       {  
     3798// //           var parsed = DataLayer.parseURI( URI ),  
     3799// //     
     3800// //           concept = parsed[1], /*URI = parsed[3],*/ 
     3801// //  
     3802// //           links = DataLayer.links( concept ); 
     3803// //  
     3804// //           for( var linkName in links ) 
     3805// //           { 
     3806// //               var subURI = data[URI][linkName]; 
     3807// //  
     3808// //               if( subURI && data[subURI] ) 
     3809// //               { 
     3810// //                   data[URI][linkName] = DataLayer.put( linkName, subURI, data[subURI], false ); 
     3811// //  
     3812// //                   delete( data[subURI] ); 
     3813// //               } 
     3814// //           } 
     3815// //  
     3816// //           DataLayer.put( concept, URI, data[URI], false ); 
     3817// //       } 
     3818// //   }, true ); 
     3819// //  
     3820// //     }, 
     3821//  
     3822// //     report: function( concept, URI, data, sync ) 
     3823// //     { 
     3824// //   var current = this.dequeue( 'current', concept, URI ); 
     3825// //  
     3826// //   if( !current ) 
     3827// //       this.enqueue( 'current', concept, URI, ( current = this.check( concept, URI ) || {} ) ); 
     3828// //  
     3829// //   var diff = this.diff( current, data ); 
     3830// //  
     3831// //   if( !diff ) 
     3832// //       this.dequeue( 'current', concept, URI, true ); 
     3833// //   else 
     3834// //       this.enqueue( 'diff', concept, URI, diff ); 
     3835// //    
     3836// //   if( sync ) 
     3837// //       this.commit( concept, URI, function(){  
     3838// //  
     3839// //           DataLayer.set( concept, URI, data, false ); 
     3840// //  
     3841// //       }); 
     3842// //     }, 
     3843//      
     3844// //     enqueue: function( type, concept, URI, obj ){ 
     3845// //        
     3846// //   //var newURI = this.URI( concept, URI ); 
     3847// //    
     3848// //   if( !this.queue[type] ) 
     3849// //       this.queue[type] = {}; 
     3850// //  
     3851// //   if( !this.queue['all'] ) 
     3852// //       this.queue['all'] = {}; 
     3853// //    
     3854// //   if( !this.queue[type][concept] ) 
     3855// //       this.queue[type][concept] = {}; 
     3856// //    
     3857// //   if( !this.queue['all'][type] ) 
     3858// //       this.queue['all'][type] = {}; 
     3859// //    
     3860// //   if( !this.queue['all'][type][/*new*/URI] ) 
     3861// //       this.queue[type][concept][URI] = this.queue['all'][type][/*new*/URI] = obj; 
     3862// //  
     3863// //   this.store( ':queue', this.queue ); 
     3864// //     }, 
     3865// //      
     3866// //     dequeue: function( type, concept, URI, remove ){ 
     3867// //        
     3868// //       ///////////////////////////// normalize //////////////////////////////// 
     3869// //   if( arguments.length < 4 && $.type(URI) === 'boolean' ) 
     3870// //   { 
     3871// //       remove = URI; 
     3872// //       URI = false; 
     3873// //   } 
     3874// //   if( arguments.length < 3 && $.type(concept) === 'boolean' ) 
     3875// //   { 
     3876// //       remove = concept; 
     3877// //       concept = false; 
     3878// //   } 
     3879// //       ////////////////////////////////////////////////////////////////////////// 
     3880// //        
     3881// //   if( !this.queue[type] || !this.queue['all'] ) 
     3882// //       return( false ); 
     3883// //    
     3884// //   if( !concept ) 
     3885// //   { 
     3886// //       var obj = this.queue['all'][type]; 
     3887// //        
     3888// //       if( remove ) 
     3889// //       { 
     3890// //           delete this.queue['all'][type]; 
     3891// //           delete this.queue[type]; 
     3892// //       } 
     3893// //  
     3894// //       this.store( ':queue', this.queue ); 
     3895// //       return( obj ); 
     3896// //   } 
     3897// //  
     3898// //   if( !this.queue[type][concept] ) 
     3899// //       return( false ); 
     3900// //    
     3901// //   if( !URI ) 
     3902// //   { 
     3903// //       var obj = this.queue[type][concept]; 
     3904// //  
     3905// //       if( remove ) 
     3906// //       { 
     3907// //           var URIs = this.queue[type][concept]; 
     3908// //  
     3909// //           for( var subURI in URIs ) 
     3910// //                delete this.queue['all'][type][subURI]; 
     3911// //  
     3912// //           delete this.queue[type][concept]; 
     3913// //       } 
     3914// //  
     3915// //       this.store( ':queue', this.queue ); 
     3916// //       return( obj ); 
     3917// //   } 
     3918// //  
     3919// // //        var newURI = URI ? this.URI( concept, URI ) : concept; 
     3920// //    
     3921// //   var obj = this.queue['all'][type][/*new*/URI]; 
     3922// //    
     3923// //   if( remove ) 
     3924// //   { 
     3925// //       delete this.queue['all'][type][/*new*/URI]; 
     3926// //       delete this.queue[type][concept][URI]; 
     3927// //   } 
     3928// //  
     3929// //   this.store( ':queue', this.queue ); 
     3930// //   return( obj ); 
     3931// //     }, 
     3932//      
     3933//            //TODO: definir a 'usage' desta função e refatora-la 
     3934// //     set: function( concept, filter, data, oneSide ){ 
     3935// //  
     3936// //   ///////////////////////////// normalize //////////////////////////////// 
     3937// //   if( arguments.length == 2 ) 
     3938// //   { 
     3939// //       data = filter; 
     3940// //       filter = false; 
     3941// //   } 
     3942// //   if( $.type(data) === "boolean" ) 
     3943// //   { 
     3944// //       oneSide = data; 
     3945// //       data = filter; 
     3946// //       filter = false; 
     3947// //   } 
     3948// //    
     3949// //   if( !concept || !data ) 
     3950// //       return( false ); 
     3951// //  
     3952// //   var decoder = "", URI = false, bothSides = (typeof oneSide === "undefined"); 
     3953// //    
     3954// //   if( $.type(filter) === "string" ) 
     3955// //   { 
     3956// //       URI = filter; 
     3957// //       filter = false; 
     3958// //   } 
     3959// //  
     3960// //   if( res = internalUrl.exec( concept ) ) 
     3961// //   { 
     3962// //       //TODO: verificar se a decodificaçao deve ser feita em cada item do array 
     3963// //       data = this.decode( concept, data ); 
     3964// //       concept = res[1]; 
     3965// //       decoder = res[2]; 
     3966// //   } 
     3967// //   /////////////////////////////////////////////////////////////////////////// 
     3968// //  
     3969// //   if( bothSides || oneSide ) 
     3970// //       this.report( concept, URI, data, !bothSides ); 
     3971// //  
     3972// //   if( bothSides || !oneSide ) 
     3973// //   { 
     3974// //       if( URI ) 
     3975// //       { 
     3976// //         var helper = {};  
     3977// //         helper[URI] = data;  
     3978// //         data = helper; 
     3979// //       } 
     3980// //  
     3981// //       for( var URI in data ) 
     3982// //       { 
     3983// //           var current = this.check( concept, URI ) || {}; 
     3984// //  
     3985// //           data[URI] = this.merge( current, data[URI] ); 
     3986// //  
     3987// //           this.store( concept, URI, data[URI] ); 
     3988// //       } 
     3989// //  
     3990// //   } 
     3991// //  
     3992// //   this.broadcast( concept, oneSide ? 'client' : 'server' ); 
     3993// //  
     3994// //   return( true ); 
     3995// //     }, 
     3996// //     put: function( concept, URI, data, oneSide ){ 
     3997// //        
     3998// //       ///////////////////////////// normalize //////////////////////////////// 
     3999// //   if( $.type(URI) !== "string" && arguments.length < 4 ) 
     4000// //   { 
     4001// //       oneSide = data; 
     4002// //       data = URI; 
     4003// //       URI = false; 
     4004// //   } 
     4005// //       //////////////////////////////////////////////////////////////////////// 
     4006// //        
     4007// //       ////////////////////////////// linkage ///////////////////////////////// 
     4008// //   var result = false, links = this.links( concept ); 
     4009// //  
     4010// //   for( var link in links ) 
     4011// //   { 
     4012// //       if( data[link] ) 
     4013// //       { 
     4014// //           if( $.isArray( data[link] ) ) 
     4015// //           { 
     4016// //               data[link] = this.put( links[link], data[link].URI, data[link], oneSide ); 
     4017// //           } 
     4018// //           else if( $.isObject( data[link] ) ) 
     4019// //           { 
     4020// //               $.each( data[link], function( i, el ){ 
     4021// //  
     4022// //                     data[link][i] = this.put( links[link], el.URI, el, oneSide ); 
     4023// //  
     4024// //               }); 
     4025// //           } 
     4026// //       } 
     4027// //   } 
     4028// //       ////////////////////////////////////////////////////////////////////////// 
     4029// //      
     4030// //   if( typeof data.URI === "undefined" ) 
     4031// //   { 
     4032// //       URI = this.add( concept, data, oneSide ); 
     4033// //   } 
     4034// //   else if( data.URI === false ) 
     4035// //   { 
     4036// //       status = this.remove( concept, URI, oneSide ); 
     4037// //   } 
     4038// //   else 
     4039// //   { 
     4040// //       status = this.set( concept, URI, data, oneSide ); 
     4041// //   } 
     4042// //  
     4043// //   if( URI && data.URI && URI !== data.URI ) 
     4044// //       this.move( concept, URI, data.URI ); 
     4045// //  
     4046// //   return( data.URI || URI ); 
     4047// //  
     4048// //     }, 
     4049//      
     4050//     //     add: function( concept, data, oneSide ){ 
     4051// //        
     4052// //       ///////////////////////////// normalize //////////////////////////////// 
     4053// //   if( !concept || !data ) 
     4054// //       return( false ); 
     4055// //  
     4056// //   if( res = internalUrl.exec( concept ) ) 
     4057// //   { 
     4058// //       //TODO: verificar se a decodificaᅵᅵo deve ser feita em cada item do array 
     4059// //       data = this.decode( concept, data ); 
     4060// //       concept = res[1]; 
     4061// //       decoder = res[2]; 
     4062// //   } 
     4063// //  
     4064// //   var bothSides = (typeof oneSide === "undefined"), uris = []; 
     4065// //  
     4066// //   if( notArray = $.type(data) !== "array" ) 
     4067// //       data = [ data ]; 
     4068// //       ////////////////////////////////////////////////////////////////////////// 
     4069// //  
     4070// //   for( var i = 0; i < data.length; i++ ) 
     4071// //   { 
     4072// //       var URI = uris[i] = this.generateURI( concept ); 
     4073// //  
     4074// //       this.set( concept, URI, data[i], oneSide ); 
     4075// //   } 
     4076// //  
     4077// //   return( notArray ? uris[0] : uris ); 
     4078// //     }, 
     4079// //      put: function( concept, data ){ 
     4080// //  
     4081// //   var decoder = ""; 
     4082// //  
     4083// //   if( res = internalUrl.exec( concept ) ) 
     4084// //   { 
     4085// //       data = this.decode( concept, data ); 
     4086// //       concept = res[1]; 
     4087// //       decoder = res[2]; 
     4088// //   } 
     4089// //  
     4090// //   var New = [], Update = [], uris = []; 
     4091// //  
     4092// //   if( notArray = $.type(data) !== "array" ) 
     4093// //       data = [ data ]; 
     4094// //    
     4095// //   for( var i = 0; i < data.length; i++ ) 
     4096// //   { 
     4097// //       if( !data[i].URI ) 
     4098// //       { 
     4099// //           uris[ uris.length ] = data[i].URI = this.create( concept, data[i] ); 
     4100// //           New[ New.length ] = data[i]; 
     4101// //           continue; 
     4102// //       } 
     4103// //  
     4104// //       for( var key in data[i] ) 
     4105// //           if( klass = this.isReference( concept, key, data[i][key] ) ) 
     4106// //                 data[i][key] = this.put( klass + decoder, data[i][key] ); 
     4107// //  
     4108// //       Update[ Update.length ] = this.update( concept, data[i].URI, data[i] ); 
     4109// //   } 
     4110// //  
     4111// //   this.report( concept, { "created": New, "updated": Update }); 
     4112// //  
     4113// //   return( notArray ? uris[0] : uris ); 
     4114// //     }, 
     4115// //     merge: function( concept, current, data ){ 
     4116// //  
     4117// //   current = current || {}; 
     4118// //  
     4119// //   for( var key in data ) 
     4120// //       current[key] = (klass = this.isReference( concept, key, data[key] )) ?  
     4121// //                      this.merge( klass, current[key], data[key] ) : data[key]; 
     4122// //  
     4123// //   return( current ); 
     4124// //     }, 
     4125// //  
     4126// //     isReference: function( concept, key, value ){ 
     4127// //  
     4128// //       return( ($.type(value) === "object" ||  
     4129// //          $.type(value) === "array" )? this.links[concept][key] : false ); 
     4130// //  
     4131// //     }, 
     4132// //      
     4133// //     set: function( concept, data, URI, mergeable ){ 
     4134// //    
     4135// //   if( URI ) 
     4136// //   { 
     4137// //       var res = this.get( concept, true ) || {}; 
     4138// //        
     4139// //       if( mergeable ) 
     4140// //           data = this.merge( res[URI] || {}, data ); 
     4141// //  
     4142// //       res[URI] = data; 
     4143// //  
     4144// //       data = res; 
     4145// //   } 
     4146// //  
     4147// //   return this.store( concept, data ); 
     4148// //     },     
     4149// //  
     4150// //     create: function( concept, data ){ 
     4151// //  
     4152// //       if( notArray = ($.type(data) !== "array") ) 
     4153// //       data = [ data ]; 
     4154// //  
     4155// //       var uris = []; 
     4156// //  
     4157// //       for( var i = 0; i < data.length; i++ ) 
     4158// //       { 
     4159// //     uris[ uris.length ] = data[i].URI = "javascript://" + (this.counter + i); 
     4160// //  
     4161// //     this.set( concept, data[i], data[i].URI ); 
     4162// //       } 
     4163// //   
     4164// //       this.set( ":counter", (this.counter += data.length) ); 
     4165// //  
     4166// //       return notArray ? uris[0] : uris; 
     4167// //     }, 
     4168// //  
     4169// //     update: function( concept, URI, data ) 
     4170// //     { 
     4171// //   var target = this.check( concept, URI ) || {}; 
     4172// //  
     4173// //   target = this.merge( concept, target, data ); 
     4174// //  
     4175// //   if( target.URI !== URI ) 
     4176// //       this.remove( concept, URI ); 
     4177// //  
     4178// //   this.set( concept, target, target.URI ); 
     4179// //  
     4180// //   return( target ); 
     4181// //     }, 
     4182// //  
     4183// //     remove: function( concept, URI ){ 
     4184// //  
     4185// //   if( !URI ) 
     4186// //       return this.storage.del( concept ); 
     4187// //  
     4188// //   var res = this.check( concept ); 
     4189// //  
     4190// //   delete res[URI]; 
     4191// //    
     4192// //   this.set( concept, res ); 
     4193// //     }, 
     4194// //  
     4195// //     del: function( concept, URI ){ 
     4196// //  
     4197// //   this.remove( concept, URI ); 
     4198// //  
     4199// //   this.report( concept, { "deleted": { 'URI': URI } }); 
     4200// //     }, 
     4201// //  
     4202// //     report: function( concept, changes ){ 
     4203// //  
     4204// //       this.broadcast( concept, changes.created, changes.updated, changes.deleted ); 
     4205// //  
     4206// //   if( changes.created ) 
     4207// //       this.sync( concept, changes.created, 'create' ); 
     4208// //   if( changes.updated ) 
     4209// //       this.sync( concept, changes.updated, 'update' ); 
     4210// //   if( changes.deleted ) 
     4211// //       this.sync( concept, changes.deleted, 'delete' ); 
     4212// //  
     4213// //     }, 
     4214// //  
     4215// //  
     4216// //    sync: function( concept, data, type ){ 
     4217// //  
     4218// //   if( $.type(data) !== "array" ) 
     4219// //       data = [ data ]; 
     4220// //  
     4221// //   $.each( data, function( i, el ){ 
     4222// //  
     4223// //      DataLayer.send( concept, el, type ); 
     4224// //  
     4225// //   }); 
     4226// //  
     4227// //     }, 
     4228// //      
     4229// //      
     4230// //      
     4231// //      
     4232// //  
     4233// //     request: function( concept, URI, filter ){ 
     4234// //  
     4235// // //       if( startsDoubleDot.test(concept) ) 
     4236// // //          return( false ); 
     4237// //  
     4238// //       filter = filter || {}; 
     4239// //  
     4240// //       if( URI ) 
     4241// //   filter.URI = URI; 
     4242// //  
     4243// //       return this.send( concept, filter, "read", true ); 
     4244// //  
     4245// //     }, 
     4246// //  
     4247// //     send: function( concept, data, type, wait ){ 
     4248// //  
     4249// //       switch( type ) 
     4250// //       { 
     4251// //   case "create": type = "POST"; break; 
     4252// //   case "update": type = "PUT"; break; 
     4253// //   case "delete": type = "DELETE"; break; 
     4254// //   case "read": type = "GET"; break; 
     4255// //       } 
     4256// //  
     4257// //       var url = this.basePath + concept; 
     4258// //  
     4259// //       var result = [], notArray = false; 
     4260// //  
     4261// // //      alert( data.URI ); 
     4262// //  
     4263// //       if( data.URI && data.URI.indexOf("javascript://") !== 0 ) 
     4264// //     url += "/" + data.URI; 
     4265// //  
     4266// //       var callback = function( dt, textStatus, jqXHR ){ 
     4267// //  
     4268// //       if( notArray = (!$.isArray( dt )) ) 
     4269// //           dt = [ dt ]; 
     4270// //  
     4271// //       $.each( dt, function( i, el ){ 
     4272// //  
     4273// //           if( !el || !el.URI ) 
     4274// //               return; 
     4275// //  
     4276// //           if( data.URI ) 
     4277// //               el = DataLayer.update( concept, data.URI, el ); 
     4278// //           else 
     4279// //               DataLayer.set( concept, el, el.URI ); 
     4280// //  
     4281// //           result[ result.length ] = el; 
     4282// //           DataLayer.broadcast( concept ); 
     4283// //     }); 
     4284// //       }; 
     4285// //  
     4286// //       $.ajax({ 
     4287// //         'async': ( !wait ), 
     4288// //         'url': url, 
     4289// //         'type': type, 
     4290// //         'success': callback, 
     4291// //         'dataType': 'json', 
     4292// //         'data': data/*, 
     4293// //         'processData': false*/ 
     4294// //     }); 
     4295// //  
     4296// //       return( notArray ? result[0] || false : result ); 
     4297// //     }, 
     4298//      
     4299//      
     4300//     generateURI: function( concept ){ 
     4301//        
     4302//      return this.URI( concept, this.generateId( concept ), "javascript" ); 
     4303//  
     4304//     }, 
     4305//      
     4306//  
     4307//     broadcast: function( concept, status, diff ){ 
     4308//  
     4309//      if( this.listeners[ concept ] ) 
     4310//          for( var i = 0;  
     4311//              i < this.listeners[ concept ].length;  
     4312//              this.listeners[ concept ][ i++ ]( status, diff ) ); 
     4313//     }, 
     4314//  
     4315//     listen: function( concept, listener ){ 
     4316//  
     4317//      this.register( "listeners", concept, listener ); 
     4318//  
     4319//     }, 
     4320//  
     4321//     codec: function( concept, namespace, codec ){ 
     4322//  
     4323//      if( codec.encoder ) 
     4324//          this.encoder( concept, namespace, codec.encoder ); 
     4325//      if( codec.decoder ) 
     4326//          this.decoder( concept, namespace, codec.decoder ); 
     4327//      if( codec.criteria ) 
     4328//          this.register( "criterias", concept + ":" + namespace, codec.criteria ); 
     4329//  
     4330//     }, 
     4331//  
     4332//     encoder: function( concept, namespace, encoder ){ 
     4333//  
     4334//      this.register( "encoders", concept + ":" + namespace, encoder ); 
     4335//  
     4336//     }, 
     4337//  
     4338//     encode: function( encoder, data, filter ){ 
     4339//  
     4340//      if( this.encoders[ encoder ] ) 
     4341//          for( var i = 0; 
     4342//              i < this.encoders[ encoder ].length; 
     4343//              data = this.encoders[ encoder ][ i++ ]( data, filter ) ); 
     4344//  
     4345//      return( data ); 
     4346//     }, 
     4347//  
     4348//     decoder: function( concept, namespace, decoder ){ 
     4349//  
     4350//      this.register( "decoders", concept + ":" + namespace, decoder ); 
     4351//  
     4352//     }, 
     4353//  
     4354//     decode: function( decoder, data ){ 
     4355//  
     4356//      if( this.decoders[ decoder ] ) 
     4357//          for( var i = 0; 
     4358//              i < this.decoders[ decoder ].length; 
     4359//              data = this.decoders[ decoder ][ i++ ]( data ) ); 
     4360//  
     4361//      return( data ); 
     4362//     }, 
     4363//  
     4364//     criteria: function( codec, filter ){ 
     4365//  
     4366//      if( this.criterias[ codec ] ) 
     4367//          for( var i = 0; 
     4368//              i < this.criterias[ codec ].length; 
     4369//              filter = this.criterias[ codec ][ i++ ]( filter ) ); 
     4370//  
     4371//      return( filter ); 
     4372//  
     4373//     }, 
     4374//  
     4375//     register: function( kind, concept, deployable ){ 
     4376//  
     4377//       if( arguments.length < 3 ) 
     4378//       { 
     4379//        deployable = concept; 
     4380//        concept = kind; 
     4381//        kind = 'global'; 
     4382//       } 
     4383//  
     4384//       if( !this[ kind ][ concept ] ) 
     4385//          this[ kind ][ concept ] = []; 
     4386//  
     4387//      this[ kind ][ concept ][ this[ kind ][ concept ].length ] = deployable; 
     4388//  
     4389//     }, 
     4390//      
     4391//     start: function(){ 
     4392//  
     4393//      var timer = function(){ 
     4394//  
     4395//            setTimeout( timer, 1 ); 
     4396//  
     4397//            var now = parseInt( $.now() / 1000 ); 
     4398//  
     4399//            var tasks = DataLayer.tasks[ now ]; 
     4400//  
     4401//            if( !tasks ) return; 
     4402//  
     4403//            for( var i = 0; i < tasks.length; i++ ) 
     4404//            { 
     4405//                var result = tasks[i].task( now ); 
     4406//  
     4407//                if( tasks[i].factor ) 
     4408//                DataLayer.schedule( tasks[i].task, tasks[i].factor ); 
     4409//            } 
     4410//        
     4411//            delete DataLayer.tasks[ now ]; 
     4412//      }; 
     4413//  
     4414//      setTimeout( timer, 1 ); 
     4415//     }, 
     4416//      
     4417//     task: function( timestamp, task, factor ) 
     4418//     { 
     4419//      if( !this.tasks[ timestamp ] ) 
     4420//          this.tasks[ timestamp ] = []; 
     4421//  
     4422//      this.tasks[ timestamp ][ this.tasks[ timestamp ].length ] = { task: task, factor: factor || false }; 
     4423//     }, 
     4424//  
     4425//     schedule: function( task, time ){ 
     4426//  
     4427//      time = time || 1; 
     4428//       
     4429//      var index = parseInt( $.now() / 1000 ) + time; 
     4430//  
     4431//      this.task( index, task, time ); 
     4432//     }, 
     4433//      
     4434//     poll: function( concept, time ){ 
     4435//        
     4436//       this.schedule( function( now ){ 
     4437//    
     4438//        DataLayer.commit( concept ); 
     4439//  
     4440//      }, time || 5 ); 
     4441//     }, 
     4442//      
     4443//     init: function(){ 
     4444//        
     4445//      this.counter = parseInt( this.get( ":counter", false ) ) || 0; 
     4446//  
     4447//      if( !this.dispatchPath ) 
     4448//          this.dispatchPath = "../../"; 
     4449//  
     4450//      if( !this.templatePath ) 
     4451//          this.templatePath = ""; 
     4452//  
     4453//      if( !this.basePath ) 
     4454//          this.basePath = this.dispatchPath + "REST.php?q="; 
     4455//  
     4456//      this.schedule( function( now ){ 
     4457//  
     4458//          DataLayer.flush(); 
     4459//  
     4460//      }); 
     4461//  
     4462//      this.start(); 
     4463//     } 
     4464// } 
     4465//  
     4466// // the re-usable constructor function used by clone(). 
     4467// function Clone() {} 
     4468//  
     4469// //Recursion Helper 
     4470// function RecursionHelper(){ this.clear(); }; 
     4471//  
     4472// RecursionHelper.prototype = { 
     4473//    
     4474//      constructor: RecursionHelper, 
     4475//  
     4476//      // copiedObjects keeps track of objects already copied by this 
     4477//      // deepCopy operation, so we can correctly handle cyclic references. 
     4478//      copiedObjects: [], 
     4479//  
     4480//      depth: 0, 
     4481//  
     4482//      maxDepth: 256, 
     4483//  
     4484//      //reset the recursion helper cache 
     4485//      clear: function(){ 
     4486//              this.copiedObjects = []; 
     4487//              this.depth = 0; 
     4488//      }, 
     4489//  
     4490//      // add an object to the cache.  No attempt is made to filter duplicates; 
     4491//      // we always check getCachedResult() before calling it. 
     4492//      cacheResult: function(source, result) { 
     4493//              this.copiedObjects.push([source, result]); 
     4494//      }, 
     4495//  
     4496//      // Returns the cached copy of a given object, or undefined if it's an 
     4497//      // object we haven't seen before. 
     4498//      getCachedResult: function(source) { 
     4499//  
     4500//              for ( var i=0; i<this.copiedObjects.length; i++ ) { 
     4501//                      if ( this.copiedObjects[i][0] === source ) { 
     4502//                              return this.copiedObjects[i][1]; 
     4503//                      } 
     4504//              } 
     4505//  
     4506//              return undefined; 
     4507//      } 
     4508// }; 
     4509//  
     4510// // Generic Object copier 
     4511// // the ultimate fallback DeepCopier, which tries to handle the generic case.  This 
     4512// // should work for base Objects and many user-defined classes. 
     4513// DataLayer.registerComparator({ 
     4514//      can: function(source) { return true; }, 
     4515//  
     4516//      create: function(source) { 
     4517//              if ( source instanceof source.constructor ) { 
     4518//                      return DataLayer.clone(source.constructor.prototype); 
     4519//              } else { 
     4520//                      return {}; 
     4521//              } 
     4522//      }, 
     4523//  
     4524//      populate: function(deepCopy, source, result) { 
     4525//              for ( var key in source ) { 
     4526//                      if ( source.hasOwnProperty(key) ) { 
     4527//                              result[key] = deepCopy(source[key], result[key]); 
     4528//                      } 
     4529//              } 
     4530//              return result; 
     4531//      } 
     4532// }); 
     4533//  
     4534// // Array copier 
     4535// DataLayer.registerComparator({ 
     4536//      can: function(source) { 
     4537//              return ( source instanceof Array ); 
     4538//      }, 
     4539//  
     4540//      create: function(source) { 
     4541//              return new source.constructor(); 
     4542//      }, 
     4543//  
     4544//      populate: function(deepCopy, source, result) { 
     4545//              for ( var i=0; i<source.length; i++) { 
     4546//                      result.push( deepCopy(source[i], result[i]) ); 
     4547//              } 
     4548//              result =  DataLayer.unique( result ) 
     4549//              return result; 
     4550//      } 
     4551// }); 
     4552//  
     4553// // Date copier 
     4554// DataLayer.registerComparator({ 
     4555//      can: function(source) { 
     4556//              return ( source instanceof Date ); 
     4557//      }, 
     4558//  
     4559//      create: function(source) { 
     4560//              return new Date(source); 
     4561//      } 
     4562// }); 
     4563//  
     4564// // HTML DOM Node copier 
     4565// DataLayer.registerComparator({ 
     4566//  
     4567//      // function to detect Nodes.  In particular, we're looking 
     4568//      // for the cloneNode method.  The global document is also defined to 
     4569//      // be a Node, but is a special case in many ways. 
     4570//      can: function(source) {  
     4571//         
     4572//        if ( window.Node ) { 
     4573//                return source instanceof Node; 
     4574//        } else { 
     4575//                // the document is a special Node and doesn't have many of 
     4576//                // the common properties so we use an identity check instead. 
     4577//                if ( source === document ) return true; 
     4578//                return ( 
     4579//                        typeof source.nodeType === 'number' && 
     4580//                        source.attributes && 
     4581//                        source.childNodes && 
     4582//                        source.cloneNode 
     4583//                ); 
     4584//        }  
     4585//       }, 
     4586//  
     4587//       create: function(source) { 
     4588//            // there can only be one (document). 
     4589//            if ( source === document ) return document; 
     4590//  
     4591//            // start with a shallow copy.  We'll handle the deep copy of 
     4592//            // its children ourselves. 
     4593//            return source.cloneNode(false); 
     4594//       }, 
     4595//        
     4596//       diff: function(base, source){ 
     4597//       
     4598//       }, 
     4599//  
     4600//       populate: function(deepCopy, source, result) { 
     4601//            // we're not copying the global document, so don't have to populate it either. 
     4602//            if ( source === document ) return document; 
     4603//  
     4604//            // if this Node has children, deep copy them one-by-one. 
     4605//            if ( source.childNodes && source.childNodes.length ) { 
     4606//                    for ( var i=0; i<source.childNodes.length; i++ ) { 
     4607//                            var childCopy = deepCopy(source.childNodes[i], result.childNodes[i] || false ); 
     4608//                            result.appendChild(childCopy); 
     4609//                    } 
     4610//            } 
     4611//              return result; 
     4612//       } 
     4613// }); 
     4614//  
     4615// DataLayer.init(); 
     4616//  
     4617// // setTimeout(function(){ 
     4618// //   
     4619// //      
     4620// //  
     4621// // }, 1000 ); 
     4622//  
     4623// // var DataLayer = { 
     4624// //  
     4625// //     get: function( concept, filter ){ 
     4626// //  
     4627// //   var data = this.storage.get( concept ); 
     4628// //  
     4629// //   if( !filter ) 
     4630// //       return( data ); 
     4631// //  
     4632// //   return this.filter( data, filter ); 
     4633// //     }, 
     4634// //      
     4635// //     filter:function( data, filter ){ 
     4636// //        
     4637// //   if( filter.charAt ) 
     4638// //       filter = { URI: filter }; 
     4639// //    
     4640// //   var filtered = []; 
     4641// //  
     4642// //   $.each(data, function(i, obj){ 
     4643// //      
     4644// //       for( var attr in filter ) 
     4645// //           if( filter[attr] !== obj[attr] ) 
     4646// //               return( true ); 
     4647// //  
     4648// //       filtered[i] = obj; 
     4649// //   }); 
     4650// //  
     4651// //   return( filtered ); 
     4652// //     }, 
     4653// //  
     4654// //     find: function( concept, filter, callback ){ 
     4655// //  
     4656// //   var data = this.get( concept, filter );  
     4657// //  
     4658// //   if( data ) 
     4659// //       return callback( data ); 
     4660// //  
     4661// //   //TODO: register callback like a weak listener 
     4662// //  
     4663// // //        $.ajax({  
     4664// // //              type: 'GET', 
     4665// // //              data: $.param( filter ), 
     4666// // //              success: callback,   
     4667// // //              url: BASE_PATH + filter.URI || concept 
     4668// // //        }); 
     4669// //   this.report( concept, filter ); 
     4670// //     }, 
     4671// //  
     4672// //     put: function( concept, data, filter ){ 
     4673// //  
     4674// //   var beforeDiff = this.store( concept, $.extend({},data) ); 
     4675// //  
     4676// //   this.report( concept, data, filter, beforeDiff ); 
     4677// //     }, 
     4678// //      
     4679// //      
     4680// //     /*var data = { 
     4681// //                   startTime: $.now(), 
     4682// //                   endTime: $.now() + 1800000, 
     4683// //                   summary: "meu querido evento", 
     4684// //                   description: "desc do evento", 
     4685// //                   location: "prognus software livre", 
     4686// //                   class: 1, 
     4687// //                   calendar: 1, 
     4688// //                   category: 1, 
     4689// //                   participants: [ {  
     4690// //                                      user: { isExternal: true, mail: "user7@prognus.org", name: "user7" } 
     4691// //                                 },{  
     4692// //                                      user: "1003" 
     4693// //                                 } ] 
     4694// //  
     4695// //             };*/ 
     4696// //      
     4697// //  
     4698// //     merge:function( data, target ){ 
     4699// //        
     4700// //   var diff = { New: {}, Update:{}, Delete: {} }; 
     4701// //        
     4702// //   for( var key in data ) 
     4703// //   { 
     4704// //       if( !target[ key ] ) 
     4705// //           diff.New[ key ] = target[ key ] = data[ key ]; 
     4706// //  
     4707// //        
     4708// //      
     4709// //   } 
     4710// //        
     4711// //     } 
     4712// //  
     4713// //     store: function( concept, data, filter ){ 
     4714// //  
     4715// //   if( !data.spline ) 
     4716// //       data = [ data ]; 
     4717// //  
     4718// //   var target = this.storage.get( concept ); 
     4719// //    
     4720// //   var diff = { New: {}, Update:{}, Delete: {} }; 
     4721// //  
     4722// //   for( var i = 0; i < data.length; i++ ) 
     4723// //   { 
     4724// //       if( data[i].URI && target[ data[i].URI ] ) 
     4725// //       { 
     4726// //           diff.Update[ data[i].URI ] = this.merge( target[ data[i].URI ], data[i] ); 
     4727// //       } 
     4728// //       else 
     4729// //       { 
     4730// //           diff.New[] = data[i]; 
     4731// //       } 
     4732// //   } 
     4733// //  
     4734// //    
     4735// //  
     4736// //   this.broadcast( concept, data ); 
     4737// //  
     4738// //   if( filter ) 
     4739// //       target = this.filter( target, filter ); 
     4740// //  
     4741// //   if( target ) 
     4742// //       data = $.extend( target, data ); 
     4743// //  
     4744// //   this.storage.set( concept, data ); 
     4745// //  
     4746// // //        return; 
     4747// //     }, 
     4748// //      
     4749// //     set: function( concept, data, filter ){ 
     4750// //  
     4751// //        
     4752// //  
     4753// //     }, 
     4754// //  
     4755// //     post: function( concept, data, filter, isNew ){ 
     4756// //  
     4757// //   var callback = function(  ){ DataLayer.store( concept, data, filter ) }; 
     4758// //  
     4759// //   //TODO: register callback like a weak listener 
     4760// //  
     4761// //   this.report( concept, data, filter, isNew ); 
     4762// //     }, 
     4763// //      
     4764// //     report: function( concept, filter, postData, isNew ){ 
     4765// //        
     4766// //   $.ajax({  
     4767// //           type: postData ? isNew ? 'POST' : 'PUT' : 'GET', 
     4768// //           data: postData || $.param( filter ), 
     4769// //           success: function( data ){ DataLayer.broadcast( concept ) }, 
     4770// //           url: BASE_PATH + filter.URI || concept 
     4771// //     }); 
     4772// //     }, 
     4773// //      
     4774// //     del:function( concept, filter ){ 
     4775// //  
     4776// //        
     4777// //  
     4778// //     } 
     4779// //      
     4780// //     broadcast: function( concept, data ){ 
     4781// //  
     4782// //    
     4783// //  
     4784// //     }, 
     4785// //  
     4786// //     pool: function(){ 
     4787// //        
     4788// //     }, 
     4789// // 
     4790// //     refresh: function(){ 
     4791// //        
     4792// //     } 
     4793// // }; 
     4794//  
     4795// //  
     4796// // DataLayer = { 
     4797// //    
     4798// //     get: function( concept, filter ){ 
     4799// //  
     4800// //   var data = this.storage.get( concept ); 
     4801// //  
     4802// //   if( !filter ) 
     4803// //       return( data ); 
     4804// //  
     4805// //   if( filter.charAt ) 
     4806// //       filter = { URI: filter }; 
     4807// //    
     4808// //   var filtered = []; 
     4809// //  
     4810// //   $.each(data, function(i, obj){ 
     4811// //      
     4812// //       for( var attr in filter ) 
     4813// //           if( filter[attr] !== obj[attr] ) 
     4814// //               return( true ); 
     4815// //  
     4816// //       filtered[i] = obj; 
     4817// //   }); 
     4818// //  
     4819// //   return( filtered ); 
     4820// //     }, 
     4821// //  
     4822// //     find: function( concept, filter, callback ){ 
     4823// //  
     4824// //   var data = this.get( concept, filter );  
     4825// //  
     4826// //   if( data ) 
     4827// //       return callback( data ); 
     4828// //  
     4829// //    $.ajax({  
     4830// //         type: 'GET',  
     4831// //         data: $.param( filter ), 
     4832// //         success: callback,   
     4833// //         url: filter.URI || concept 
     4834// //   }); 
     4835// //     }, 
     4836// //  
     4837// //     put: function( concept, data, filter ){ 
     4838// //  
     4839// //   var target = this.get( concept, filter ); 
     4840// //  
     4841// //   if( target ) 
     4842// //       data = $.extend( target, data ); 
     4843// //        
     4844// //   this.storage.set( concept, data ); 
     4845// //    
     4846// //   //diff 
     4847// //     }, 
     4848// //      
     4849// //     post: function( concept, data, filter ){ 
     4850// //  
     4851// //    
     4852// //  
     4853// //     }, 
     4854// //      
     4855// //     pool: function(){ 
     4856// //        
     4857// //     }, 
     4858// //      
     4859// //     queue: function(){ 
     4860// //        
     4861// //     }, 
     4862// //      
     4863// //     dequeue: function(){ 
     4864// //        
     4865// //     }, 
     4866// //      
     4867// //     refresh: function(){ 
     4868// //        
     4869// //     } 
     4870// // } 
     4871//  
     4872// // var DataLayer = { 
     4873//    
     4874// //       cache: {}, 
     4875//    
     4876// //       get: function( concept, location ){ 
     4877//       
     4878//         /* if( location ) 
     4879//          {*/ 
     4880// //           var schema = $.data( this.cache, concept + ':schema' ); 
     4881// //           var uri = []; 
     4882// //  
     4883// //           $.each( schema, function( i, addrs ){ 
     4884// //                 uri[ uri.length ] = location[addrs]; 
     4885// //           }); 
     4886//  
     4887//              /*var filter = [], result = false; 
     4888//  
     4889//              while( !(result = $.data( this.cache, uri.join( '.' ) )) || !(uri = uri.join('.')) ) 
     4890//                filter[ filter.length ] = uri.pop(); 
     4891//    
     4892//              if( !filter.length ) 
     4893//              { 
     4894//                  var indexes = $.data( this.cache, uri + ':indexes' ); 
     4895//  
     4896//                  if( indexes ) 
     4897//                      Array.prototype.concat.apply( result, indexes ); 
     4898//                   
     4899//                  return( result ); 
     4900//              } 
     4901//  
     4902//              for( var i = 0; i < result.length; i++ ) 
     4903//              { 
     4904//                   
     4905//              } 
     4906//  
     4907//              if( result.length ) 
     4908//                  return( result ); 
     4909//          }*/ 
     4910//  
     4911// //       var data = $.data( this.cache, concept ); 
     4912//  
     4913// //       if( !data ) 
     4914// //           $.ajax( ); 
     4915//  
     4916// //       return( data ); 
     4917// //       }, 
     4918//        
     4919// //       data: function(){ 
     4920// //  
     4921// //      
     4922// //  
     4923// //       } 
     4924// //        
     4925// //       search: function( concept, filter ){ 
     4926// //  
     4927// //     var schema = $.data( this.cache, concept + ':schema' ); 
     4928// //     var uri = []; 
     4929// //  
     4930// //     $.each( schema, function( i, addrs ){ 
     4931// //           uri[ uri.length ] = location[addrs]; 
     4932// //     }); 
     4933// //       } 
     4934// //       put: function( concept, data, location ){ 
     4935//  
     4936// //       if( location ) 
     4937// //       { 
     4938// //           var schema = $.data( this.cache, concept + ':schema'); 
     4939// //           var uri = []; 
     4940//  
     4941// //           $.each( schema, function( i, addrs ){ 
     4942// //                 uri[ uri.length ] = location[addrs]; 
     4943// //           }); 
     4944//  
     4945// //           var result = false, filter = []; 
     4946//  
     4947// //           while( !(result = $.data( this.cache, uri.join('.')) ) 
     4948// //               filter[ filter.length ] = uri.pop(); 
     4949//  
     4950// //           $.data( this.cache, ' 
     4951//  
     4952// //       } 
     4953//  
     4954// //           var model = this.storage.get( concept ); 
     4955// //  
     4956// //           $.each( model, function( i, o ){ 
     4957// //               $.each( location, function( ii, attr ){ 
     4958// //                    if( o[ii] === attr ) 
     4959// //                       return( false ); 
     4960// //               });  
     4961// //           }); 
     4962//  
     4963// //       return $.data( this.cache, concept, data ); 
     4964//  
     4965// //       }, 
     4966// //       del: function( concept, location ){ 
     4967// //  
     4968// //       if( location ) 
     4969// //       { 
     4970// //           var schema = $.data( this.cache, 'concepts', concept ); 
     4971// //           var uri = []; 
     4972// //  
     4973// //           $.each( schema, function( i, addrs ){ 
     4974// //                 uri[ uri.length ] = location[addrs]; 
     4975// //           }); 
     4976// //  
     4977// //           concept = uri.join( '.' ); 
     4978//  
     4979// //           var model = this.storage.get( concept ); 
     4980// //  
     4981// //           $.each( model, function( i, o ){ 
     4982// //               $.each( location, function( ii, attr ){ 
     4983// //                    if( o[ii] === attr ) 
     4984// //                       return( false ); 
     4985// //               });  
     4986// //           }); 
     4987// //       } 
     4988// //        
     4989// //    
     4990// //       $.removeData( this.cache, concept ); 
     4991// //       } 
     4992// // } 
  • trunk/prototype/config/alarm.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar_alarm 
    33 
    4 [links] 
    5 participant = participant 
     4[model.depends] 
     5participant = participant.alarm 
    66 
    77[before.find] 
  • trunk/prototype/config/attachment.ini

    r5399 r5514  
    11service = PostgreSQL 
     2PostgreSQL.concept = attachment 
     3 
     4[model.hasOne] 
     5schedulable = schedulable.attachments 
    26 
    37[before.create] 
    4 beginWork = services/PostgreSQL.php 
    58encodeCreateAttachment = modules/calendar/interceptors/DBMapping.php 
    69 
     10[after.delete] 
     11deleteAttachmentDependences = modules/calendar/interceptors/DBMapping.php 
    712 
    8 [after.create] 
    9 endWork = services/PostgreSQL.php 
     13[PostgreSQL.mapping] 
     14id = "id" 
     15source = "source" 
     16type = "type" 
     17name = "name" 
     18size = "size" 
     19 
  • trunk/prototype/config/calendar.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar 
    33 
    4 [links] 
    5 signatures = calendarSignature 
     4[model.hasMany] 
     5signatures = calendarSignature.calendar 
    66 
    77[before.create] 
  • trunk/prototype/config/calendarSignature.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar_signature 
    33 
    4 [links] 
    5 calendar = calendar 
    6 calendarSignatureAlarms = calendarSignatureAlarm 
     4[model.hasMany] 
     5calendarSignatureAlarms = calendarSignatureAlarm.calendarSignature 
     6[model.depends] 
     7calendar = calendar.signatures 
    78 
    89[before.delete] 
  • trunk/prototype/config/calendarSignatureAlarm.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar_signature_alarm 
    33 
    4 [links] 
    5 calendarSignature = calendarSignature 
     4[model.depends] 
     5calendarSignature = calendarSignature.calendarSignatureAlarms 
    66 
    77[after.find] 
  • trunk/prototype/config/participant.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar_participant 
    33 
    4 [links] 
    5 user = user 
    6 schedulable = schedulable 
    7 alarms = alarm 
     4[model.hasOne] 
     5delegatedFrom = participant.delegateTo 
     6delegateTo = participant.delegatedFrom 
     7 
     8[model.hasMany] 
     9alarms = alarm.participant 
     10 
     11[model.depends] 
     12user = user.participants 
     13schedulable = schedulable.participants 
    814 
    915[after.commit] 
     
    1218[PostgreSQL.mapping] 
    1319id = id 
    14 delegatedTo = delegated_to 
     20delegatedFrom = delegated_from 
    1521isOrganizer = is_organizer 
    1622isExternal = is_external 
     
    1824schedulable = object_id 
    1925user = user_info_id 
     26acl = acl 
     27receiveNotification = receive_notification 
  • trunk/prototype/config/repeat.ini

    r5437 r5514  
    11service = PostgreSQL 
    22 
    3 [links] 
    4 schedulable = schedulable 
     3[model.depends] 
     4schedulable = schedulable.repeat 
    55 
  • trunk/prototype/config/schedulable.ini

    r5437 r5514  
    22PostgreSQL.concept = calendar_object 
    33 
    4 [links] 
    5 participants = participant 
    6 repeat = repeat 
     4[model.hasMany] 
     5participants = participant.schedulable 
     6attachments = schedulableToAttachment.schedulable 
     7         
     8[model.hasOne] 
     9repeat = repeat.schedulable 
    710 
    811[before.create] 
  • trunk/prototype/config/user.ini

    r5437 r5514  
    99PostgreSQL.concept = calendar_ex_participant 
    1010 
    11 [links] 
    12 participants = participant 
     11[model.hasMany] 
     12participants = participant.user 
    1313 
    1414[PostgreSQL.before.create] 
  • trunk/prototype/converter.php

    r5415 r5514  
    33require_once 'api/controller.php'; 
    44 
    5 $method =  $_REQUEST['analize'] ? 'analize' : 'parse'; 
     5$method =  isset($_REQUEST['analize']) && $_REQUEST['analize'] ? 'analize' : 'parse'; 
    66 
    77$args = Controller::call( $method, 
     
    99                          array( 'service' => $_REQUEST['type'] ), 
    1010 
    11                           isset( $_FILES['data'] ) ? file_get_contents( $_FILES['data']['tmp_name'] ) : $_REQUEST['data'], 
     11                          isset( $_FILES['files'] ) ? file_get_contents( $_FILES['files']['tmp_name'][0], $_FILES['files']['size'][0] ) : $_REQUEST['data'], 
    1212 
    1313                          $_REQUEST['params'] ); 
    1414 
    15 if(!$_REQUEST['readable']) 
     15if( !$_REQUEST['readable']) 
    1616        require_once 'Sync.php'; 
    1717else 
  • trunk/prototype/links.php

    r5399 r5514  
    1515{ 
    1616    $concepts = array(); 
     17    $nestedLinks = array(); 
    1718 
    1819    foreach( $link as $linkName => $linkTarget ) 
    19          if( Controller::isConcept( $linkName ) ) 
     20    { 
     21         if( Controller::isConcept( $concept, $linkName ) ) 
    2022            $concepts[ $linkName ] = true; 
    2123 
    22     $return[ $target ] = array( 'concepts' => $concepts, 'links' => $link ); 
     24          $nestedLinks[ $linkName ] = Controller::links( $concept, $linkName ); 
     25    } 
     26 
     27    $return[ $target ] = array( 'concepts' => $concepts, 'links' => $link, 'nestedLinks' => $nestedLinks ); 
    2328} 
    2429 
  • trunk/prototype/modules/calendar/constants.php

    r5415 r5514  
    55define('STATUS_CONFIRMED', 1); 
    66define('STATUS_ACCEPTED', 1); 
    7 define('STATUS_TENATIVE', 2); 
     7define('STATUS_TENTATIVE', 2); 
    88define('STATUS_DECLINED', 3); 
    99define('STATUS_CANCELLED', 3); 
     
    2929define('ICAL_ACTION_NONE', 4); 
    3030define('ICAL_ACTION_REPLY', 5); 
     31define('ICAL_ACTION_SUGGESTION', 6); 
    3132 
    3233?> 
  • trunk/prototype/modules/calendar/css/layout.css

    r5417 r5514  
    211211} 
    212212 
    213 .new-event-win fieldset.block-add-attendee-permissions {  
    214         width: 220px;  
    215         float:left;  
    216         margin: 105px 0 0 10px; 
    217 } 
     213.new-event-win ul.attendee-permissions-list, li.attendee-permissions-list{text-align: left;} 
     214 
     215li.attendee-permissions-list input{width: 20px !important; margin: 3px 0 0 0; !important} 
     216 
     217p.request-update{display: inline; position: relative; top: 2px;} 
     218 
     219 
     220p.request-update label{width: 150px !important;} 
    218221 
    219222.new-event-win .menu-addevent { 
     
    221224} 
    222225 
    223 fieldset.block-add-attendee .add-attendee-search { max-width: 200px; margin: 5px;} 
    224 fieldset.block-add-attendee .add-attendee-search input { max-width: 170px; } 
     226fieldset.block-add-attendee .add-attendee-search { max-width: 250px; margin: 5px;} 
     227fieldset.block-add-attendee .add-attendee-search input { max-width: 215px; width: 215px;} 
    225228fieldset.block-add-attendee .search-result-list { width: 255px; max-height: 215px; overflow: auto;} 
    226229fieldset.block-add-attendee .search-result-list .ui-widget-content { border: none;} 
     
    256259.attendees-list .me select.status { margin:10px 5px 5px 5px; } 
    257260.attendees-list .me .add-attendee-search { max-width: 155px; width:155px; display: inline; padding: 0; margin: 10px 0 5px 0;} 
     261 
     262.attendees-list .me .add-attendee-options { max-height: 16px; height:16px;  max-width: 50px; width:50px; display: inline; padding: 0; margin: 0 0 5px 0;} 
     263.attendees-list .me .add-attendee-options-read { max-height: 16px; height:16px;  max-width: 16px; width:16px; display: inline; padding: 0; margin: 0 0 5px 0;} 
     264 
     265.attendees-list .me .add-attendee-options-button {position: absolute; top: 171px;} 
     266.attendees-list .hover-attendee { background-color: #DFEFFC;} 
     267/* 
     268.attendees-list .attendee-options-button-edit { position: absolute; top:0; right:25px;} 
     269.attendees-list .attendee-options-button-key { position: absolute; top:0; right:45px;} 
     270.attendees-list .attendee-options-button-delegate { position: absolute; top:0; right:65px;} 
     271*/ 
     272 
     273.attendee-options{ position: absolute; top: 0; left: 300px; background-color: white; z-index: 100; width: 90px; background-color: #FFF; padding: 0 5px 0 3px; text-align: right;} 
     274.attendees-list .not-attendee { height:16px; } 
     275 
     276.list-delegates{margin: 0 0 0 25px;} 
     277 
     278.status-delegate{position: absolute; left:3px;} 
     279 
    258280.attendees-list .me .add-attendee-search input { max-width: 125px; } 
    259 .attendees-list li.organizer {margin-bottom: 3px;} 
     281.attendees-list li.organizer, .attendees-list li.me-delegated {margin-bottom: 3px;} 
    260282.attendees-list .organizer .button.swap { 
    261283        float: right; 
    262284        margin-top: -1.5em; 
    263285} 
     286 
     287.name-status-delegated{text-decoration: line-through; padding: 0 0 0 18px;} 
     288.name-status-delegated-delegated{text-decoration: line-through; padding: 0 0 0 12px;} 
     289.name-status-delegated-none{ padding: 0 0 0 12;} 
     290 
     291.name-status{padding: 0 0 0 18px;} 
     292 
     293.name-special{padding: 0 0 0 33px;} 
     294.name-special-delegated{text-decoration: line-through; padding: 0 0 0 33px;} 
     295 
     296.open-delegate{position: absolute; left: 20px; display: block; cursor: hand;} 
     297.space-status{position: absolute; left: 20px; display: block;} 
     298.space-special{position: absolute; left: 35px; display: block;} 
     299.space-special-delegated{position: absolute; left: 20px; display: block;} 
     300 
     301.attendee-permissions-change{background-image: url(../../../plugins/jquery/images/ui-icons_f9bd01_256x240.png) !important;} 
     302.attendee-permissions-change-button{border: 1px solid #79B7E7 !important; background: #F5F8F9 !important; font-weight: bold !important; color: #E17009 !important;} 
     303 
     304.attendee-permissions-conflict{opacity: 0.5} 
    264305 
    265306dd.attendee-list ul.attendee-list li { 
     
    275316dd.attendee-list ul.attendee-list li label.name, 
    276317dd.attendee-list ul.attendee-list li label.mail { 
    277         width: 6000px; 
    278         min-width: 6000px; 
     318        width: 99999px; 
     319        min-width: 99999px; 
    279320        vertical-align: middle; 
    280321} 
    281322dd.attendee-list ul.attendee-list li label[title=''] { display:none } 
     323/* 
    282324dd.attendee-list ul.attendee-list li .button.close { 
    283325        position: absolute; 
    284     right: 0; 
     326    right: 5px; 
    285327    top: 0; 
    286328} 
    287  
     329*/ 
    288330/* 
    289331.attendees-list li .ui-icon-float-right { 
     
    482524} 
    483525 
     526.button.add.button-add-attachment{margin: -9px 0 0 8px;} 
     527.button.upload{margin-bottom: 4px;} 
     528div.fileupload-buttonbar{padding: 0.2em 0.5em } 
     529.archive-error{color: #F00;} 
     530 
     531.progress.in-progress{width: 100px; height: 12px;} 
     532 
     533 
     534.lbl-archive-nome, .lbl-archive-size{font-weight: bold !important;} 
     535.lbl-archive-nome{width:40px !important;} 
     536.row.fileupload-buttonbar{margin-top: -14px; padding: 0.2em 0.7em;} 
     537 
     538.archive-nome{width: 73px;} 
     539.archive-nome label{display: block; position: absolute; left: 136px; top: 194px;} 
     540.archive-size{min-width:100px; max-width:100px;} 
     541 
     542 
    484543.input-group.date-info input { 
    485544        width: 100px; 
  • trunk/prototype/modules/calendar/css/style.css

    r5511 r5514  
    9090 
    9191.ui-dialog .ui-dialog-content { padding: 0; } 
    92 .new-event-win form.form-addevent { padding: 10px; } 
     92.new-event-win div.div-addevent { padding: 0; width: 700px; border: 0;} 
     93.new-event-win form.form-addevent { padding: 9px; } 
    9394 
    9495.expresso-calendar-container input[type="text"] { height: 18px; } 
  • trunk/prototype/modules/calendar/export.php

    r5399 r5514  
    3131       $eventsIds[] = $eventLink['schedulable']; 
    3232 
    33     $events = Controller::find(array('concept' => 'schedulable') , false , array('filter' => array('IN','id',$eventsIds) , 'deepness' => '2' )); 
     33    $events = Controller::find(array('concept' => 'schedulable') , false , array('filter' => array('IN','id',$eventsIds) , 'deepness' => '2' ));         
    3434    $ics = Controller::format( array( 'service' => 'iCal' ) , $events , array('defaultTZI' => $calendar['timezone']) ); 
    3535 
     
    4545{     
    4646    $event = Controller::read(array('concept' => 'schedulable' , 'id' => $params['event'])); 
     47        $attachmentRelation = Controller::find( array( 'concept' => 'schedulableToAttachment' ) , false ,array( 'filter' => array('=', 'schedulable'  ,  $event['id']) ));  
     48        if(is_array($attachmentRelation)){ 
     49                $attachments = array(); 
     50                foreach($attachmentRelation as $key => $value) 
     51                        if(isset($value['attachment']) || !!$value['attachment']) 
     52                                $attachments[$key]  = $value['attachment']; 
     53                //Pega os anexos sem source 
     54                $event['attachments'] = Controller::find( array( 'concept' => 'attachment' ) , false ,array( 'filter' => array('IN', 'id' , $attachments) ));  
     55        } 
     56                 
    4757    $ics = Controller::format( array( 'service' => 'iCal' ) , array($event) , array('defaultTZI' => $event['timezone']) ); 
    4858     
  • trunk/prototype/modules/calendar/interceptors/DBMapping.php

    r5462 r5514  
    4040        }   
    4141         
     42        public function encodeCreateSuggestion( &$uri , &$params , &$criteria , $original ){                     
     43        $params['dtstamp'] = (isset($params['dtstamp'])) ? $params['dtstamp'] :time().'000';           
     44    }    
     45         
    4246        public function encodeUpdateAlarm( &$uri , &$params , &$criteria , $original ){ 
    4347            if(isset($params['type'])) 
     
    4650         
    4751    public function encodeCreateAttachment( &$uri , &$params , &$criteria , $original ){ 
    48         $params['source'] = base64_encode( $params['source'] ); 
     52         
     53                if(!isset($params['source'])) return false; 
     54                 
     55                if(isset($_FILES[$params['source']])) 
     56                        if(isset($params['id'])) 
     57                                $params =  array_merge($_FILES[$params['source']], array('id' => $params['id'])); 
     58                        else 
     59                                $params =  $_FILES[$params['source']]; 
     60                 
     61                //$params['source'] = base64_encode( $params['source'] );        
     62                 
    4963        } 
     64 
    5065/////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
    5166         
     
    145160    public function createCalendarToSchedulable( &$uri , &$result , &$criteria , $original ){            
    146161 
    147        Controller::create(array('concept' => 'calendarToSchedulable'), array('calendar' => $original['properties']['calendar'], 'schedulable' => $result['id'] )); 
    148              
    149    }    
     162                Controller::create(array('concept' => 'calendarToSchedulable'), array('calendar' => $original['properties']['calendar'], 'schedulable' => $result['id'] )); 
     163 
     164   } 
     165 
     166        public function createCreateSchedulableToAttachment( &$uri , &$params , &$criteria , $original ){                
     167                if(array_key_exists('attachments', $original['properties']))     
     168                        foreach($original['properties']['attachments'] as $key => $value){                               
     169                                if(isset($params['id'])) 
     170                                        Controller::create(array('concept' => 'schedulableToAttachment'), array('attachment' => $value['attachment'], 'schedulable' => $params['id'] )); 
     171                        } 
     172        } 
    150173      
    151174    //TODO: Remover apos suporte a deepness na api  
     
    172195                    }        
    173196                    $result[$i]['participants'] = $participants; 
    174                 }                
     197                 
     198                                        $attachmentRelation = Controller::find( array( 'concept' => 'schedulableToAttachment' ) , false ,array( 'filter' => array('=', 'schedulable'  ,  $v['id']) ));  
     199                                        if(is_array($attachmentRelation)){ 
     200                                                $attachments = array(); 
     201                                                foreach($attachmentRelation as $key => $value) 
     202                                                        if(isset($value['attachment']) || !!$value['attachment']) 
     203                                                                $attachments[$key]  = $value['attachment']; 
     204                                                //Pega os anexos sem source 
     205                                                $result[$i]['attachments'] = Controller::find( array( 'concept' => 'attachment' ) , array('id', 'name', 'type', 'size') ,array( 'filter' => array('IN', 'id' , $attachments) ));  
     206                                        } 
     207                                 
     208                                }                
    175209                 
    176210           } 
     
    294328        } 
    295329    } 
     330 
     331    public function decodeFindAttachment( &$uri , &$result , &$criteria , $original ){           
     332                if(isset($result)) 
     333                foreach($result as $key => &$value) 
     334                        $value['source'] = base64_decode($value['source']); 
     335    } 
     336 
    296337         
    297338        public function decodeSignatureAlarmType( &$uri , &$result , &$criteria , $original ){   
     
    389430        } 
    390431         
    391      } 
     432     }  
     433          
     434        public function deleteAttachmentDependences( &$uri , &$params , &$criteria , $original ){ 
     435 
     436                if(isset($original['URI']['id'])) 
     437                        Controller::delete(array('concept' => 'schedulableToAttachment', null , array('filter' => array('=' , 'attachment' , $original['URI']['id'])))); 
     438    } 
    392439 
    393440    public function createDefaultSignature( &$uri , &$result , &$criteria , $original ){ 
  • trunk/prototype/modules/calendar/interceptors/Notifications.php

    r5437 r5514  
    88{ 
    99     
    10     /** 
     10        public function formatNotification(&$uri , &$params , &$data , $original){       
     11                switch ($params['type']) { 
     12                        case 'suggestion': 
     13                                self::formatSuggestion($params);     
     14                                break; 
     15                        case 'suggestionResponse': 
     16                                self::formatSuggestionResponse($params);     
     17                                break; 
     18                        }  
     19        } 
     20         
     21         
     22        /** 
    1123    * Analisa o commit do conceito participant e encaminha cada participant para seu devido metodo de notrificação 
    1224    * 
     
    1931    */ 
    2032    public function commitParticipant(&$uri , &$result , &$data , $original) 
    21     {     
     33    {                            
    2234        if(Config::regGet('noAlarm') !== false) return; //Escapa notificações caso a flag de noAlarm esteja ativa. 
    23                
     35                 
    2436        $organizers = array(); //Cache Organizadores 
    2537        $schedulables = array(); //Cache Schedulables 
    26          
     38 
    2739        foreach ($data as $i => $concept)  
    2840        { 
     
    3951                foreach ($schedulables[ $concept['id'] ]['participants'] as $i => $v) //salva em $organizers as informações do organizador       
    4052                    if(($v['isOrganizer'] === '1') && ($organizers[$concept['id']] = $v) ) break; 
    41             } 
     53                        }else if($concept['concept'] === 'schedulableToAttachment') 
     54                        { 
     55                                $relationAttachment = Controller::find( array( 'concept' => 'schedulableToAttachment' ) , false ,array( 'filter' => array('=', 'id' , $concept['id'])));                         
     56                                                         
     57                                 
     58                                         
     59                                foreach($relationAttachment as $key => $value){ 
     60                                        if(!array_key_exists('attachments',$schedulables[$value['schedulable']])) 
     61                                                $schedulables[$value['schedulable']]['attachments'] = array(); 
     62 
     63                                        $temp = Controller::find( array( 'concept' => 'attachment' ) , false ,array( 'filter' => array('=', 'id' , $value['attachment']))); 
     64                                        array_push($schedulables[$value['schedulable']]['attachments'] , $temp[0]);                              
     65                                } 
     66                        } 
    4267        } 
    4368         
    4469        if( isset( $created ) ) 
    4570        { 
    46            $psCreated =  Controller::find(array('concept' => 'participant'), false , array('deepness' => '1' , 'filter' => array('IN', 'id' , $created ))); 
    47            foreach ($psCreated as $i => $pCreated)    
     71           $psCreated =  Controller::find(array('concept' => 'participant'), false , array('deepness' => '1' , 'filter' => array('IN', 'id' , $created )));                 
     72                   foreach ($psCreated as $i => $pCreated)    
    4873           {     
    4974               if($pCreated['isOrganizer'] == '1') continue; //escapa organizador 
     
    5277                
    5378               $organizer = isset( $organizers[$pCreated['schedulable']] ) ? $organizers[ $pCreated['schedulable'] ] : self::getOrganizer( $pCreated['schedulable'] ); 
    54                 
     79                            
     80                                if($pCreated['delegatedFrom'] != 0){ 
     81                                        self::participantDelegated( $pCreated , $schedulable , $organizer);     
     82                                        continue; 
     83                                } 
     84                            
    5585               switch ($pCreated['status'])  
    5686               { 
     
    6898        { 
    6999            $psUpdated  = Controller::find(array('concept' => 'participant'), false , array('deepness' => '1' , 'filter' => array('IN', 'id' , $updated ))); 
    70             foreach ($psUpdated as $i => $pUpdated)    
    71             { 
     100                        foreach ($psUpdated as $i => $pUpdated)    
     101            {                    
    72102                if($pUpdated['isOrganizer'] == '1') continue; //escapa organizador 
    73103                $schedulable = isset( $schedulables[$pUpdated['schedulable']] ) ? $schedulables[ $pUpdated['schedulable'] ] : Controller::read( array('concept' => 'schedulable', 'id' => $pUpdated['schedulable']) , false , array('deepness' => '2')); 
     
    77107                    if(($v['isOrganizer'] === '1') && ($organizer = $v) ) break; 
    78108                     
    79                  
    80                 if( $pUpdated['status'] != STATUS_UNANSWERED) 
    81                 self::participantStatusChange( $pUpdated['id'] , $schedulable , $organizer , $pUpdated['status'] );     
     109                if($pUpdated['delegatedFrom'] != 0){ 
     110                                        self::participantDelegatedStatusChange( $pUpdated , $schedulable , $organizer , $pUpdated['status'] );     
     111                }else if( $pUpdated['status'] != STATUS_UNANSWERED && $pUpdated['status'] != STATUS_DELEGATED) 
     112                                        self::participantStatusChange( $pUpdated['id'] , $schedulable , $organizer , $pUpdated['status'] );     
    82113            } 
    83114        } 
    84115    } 
    85      
    86  
    87     /** 
    88     * Monta o email de convite que sera enviado ao participant 
    89     * 
    90     * @license    http://www.gnu.org/copyleft/gpl.html GPL 
    91     * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) 
    92     * @sponsor    Caixa Econômica Federal 
    93     * @author     Cristiano Corrêa Schmidt 
    94     * @return     void 
    95     * @access     public 
    96     */ 
    97     public static function participantCreated( &$partID , &$schedulable ) 
    98     { 
     116         
     117        public function formatSuggestion(&$params){ 
     118             
     119                $schedulable =  Controller::read(  array( 'concept' => 'schedulable' , 'id' => $params['schedulable'] ) , null , array('deepness' => '2') ) ; 
     120                 
     121                foreach ($schedulable['participants'] as $i => $v) //salva em $organizer as informações do organizador       
     122            if(($v['isOrganizer'] === '1') && ($organizer = $v) ) break; 
     123                 
     124                $method = 'COUNTER'; 
     125                $notificationType = 'Sugestão de horário'; 
     126                $part = 'other'; 
     127                 
     128                $schedulableReference = $schedulable; 
     129                 
     130                $referenceSuggestion = array( 'startTime' => $params['startTime'], 
     131                                                                        'endTime' => $params['endTime'], 
     132                                                                        'allDay' => $params['allDay'] 
     133                                                                ); 
     134                $schedulable = array_merge($schedulable, $referenceSuggestion); 
     135                 
     136                self::mountStruture(false, $schedulable, false , $data,  $subject, $ical, $part, $method, $notificationType); 
     137                        
     138 
     139                $timezone = new DateTimeZone('UTC'); 
     140                $sTime = new DateTime( '@'.(int)($schedulableReference['startTime'] / 1000) , $timezone ); 
     141                $eTime =  new DateTime( '@'.(int)($schedulableReference['endTime'] / 1000) , $timezone );  
     142            
     143                if(isset($schedulableReference['timezone'])) 
     144                { 
     145                        $sTime->setTimezone(new DateTimeZone($schedulableReference['timezone'])); 
     146                        $eTime->setTimezone(new DateTimeZone($schedulableReference['timezone'])); 
     147                } 
     148 
     149                $data['nowStartDate'] = date_format( $sTime , 'd/m/Y'); 
     150        $data['nowStartTime'] = ($schedulableReference['allDay']) ? '' : date_format( $sTime , 'H:i'); 
     151        $data['nowEndDate'] = date_format( $eTime , 'd/m/Y'); 
     152        $data['nowEndTime'] = ($schedulableReference['allDay']) ? '' :  date_format( $eTime , 'H:i'); 
     153                $data['userRequest'] = Config::me('uid'); 
     154                 
     155                $params['attachments'][] = $ical; 
     156                $params['isHtml'] = true;                          
     157                $params['body'] = parseTPL::load_tpl( $data ,ROOTPATH.'/modules/calendar/templates/notify_suggestion_body.tpl'); 
     158                $params['subject'] = parseTPL::load_tpl( $subject ,ROOTPATH.'/modules/calendar/templates/notify_subject.tpl');; 
     159                $params['from'] = Config::me('mail');    
     160                $params['to'] = $organizer['user']['mail']; 
     161                 
     162        }   
     163         
     164        public function formatSuggestionResponse(&$params){      
     165                $schedulable = $params['schedulable']; 
     166                foreach ($schedulable['participants'] as $i => $v) {//salva em $organizer as informações do organizador       
     167            if($v['isOrganizer'] === '1') $organizer = $v; 
     168                        if($v['user']['mail'] == Config::me('mail')) $me = $v; 
     169                } 
     170                $method = 'DECLINECOUNTER'; 
     171                $notificationType = 'Sugestão de horário'; 
     172                $part = 'other'; 
     173                 
     174                $schedulable['participants'] = array(); 
     175                array_push($schedulable['participants'], $me, $organizer); 
     176                 
     177                self::mountStruture(false, $schedulable, false , $data,  $subject, $ical, $part, $method, $notificationType); 
     178                 
     179                if($params['status'] == 'DECLINECOUNTER') 
     180                        $data['status'] = 'não pode ser aceito'; 
     181                         
     182                $params['attachments'][] = $ical; 
     183                $params['isHtml'] = true;                          
     184                $params['body'] = parseTPL::load_tpl( $data ,ROOTPATH.'/modules/calendar/templates/notify_suggestion_response_body.tpl'); 
     185                $params['subject'] = parseTPL::load_tpl( $subject ,ROOTPATH.'/modules/calendar/templates/notify_subject.tpl');; 
     186                $params['to'] = $params['from']; 
     187                $params['from'] = Config::me('mail');    
     188        } 
     189         
     190         
     191        public static function _getAttendeeById($attendeId, $schedulable){ 
     192                foreach ($schedulable['participants'] as $id => $dv)  
     193                        if($dv['id'] == $attendeId ) 
     194                                return $dv; 
     195        } 
     196         
     197        /** 
     198    * Prepara para criação de email de delegação 
     199    * 
     200    * @license    http://www.gnu.org/copyleft/gpl.html GPL 
     201    * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) 
     202    * @sponsor    Caixa Econômica Federal 
     203    * @author     Adriano Coutinho da Silva 
     204    * @return     void 
     205    * @access     public 
     206    */ 
     207        public static function participantDelegated( &$partID , &$schedulable , &$organizer){ 
     208         
     209                $delegatedParams = array(); 
     210                 
     211                $delegatedFrom = self::_getAttendeeById($partID['delegatedFrom'], $schedulable); 
     212                $delegatedParams['delegatedFrom'] = $delegatedFrom['user']['uid']; 
     213                 
     214                self::participantCreated( $partID['id'] , $schedulable , STATUS_DELEGATED, $delegatedParams );           
     215                 
     216                $delegatedTo = self::_getAttendeeById($partID['id'], $schedulable); 
     217                $delegatedParams['delegated'] = $delegatedTo['user']['uid']; 
     218                 
     219                self::participantStatusChange( $partID['delegatedFrom'] , $schedulable , $organizer , STATUS_DELEGATED, $delegatedParams ); 
     220        } 
     221         
     222        /** 
     223    * Monta o email de resposta que sera enviado ao delegatedFrom 
     224    * 
     225    * @license    http://www.gnu.org/copyleft/gpl.html GPL 
     226    * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) 
     227    * @sponsor    Caixa Econômica Federal 
     228    * @author     Cristiano Corrêa Schmidt 
     229    * @return     void 
     230    * @access     public 
     231    */ 
     232    public static function participantDelegatedStatusChange( &$partID , &$schedulable, $organizer, &$type = false){ 
     233         
     234                $delegatedParams = array(); 
     235                                         
     236                $delegated = self::_getAttendeeById($partID['id'], $schedulable); 
     237                $delegatedParams['delegated'] = $delegated['user']['uid'];               
     238                 
     239                switch($partID['status']){ 
     240            case STATUS_ACCEPTED: 
     241                $delegatedParams['status'] = 'aceitou'; 
     242            break; 
     243            case STATUS_TENTATIVE: 
     244                $delegatedParams['status'] = 'marcou como tentativa'; 
     245            break; 
     246            case STATUS_CANCELLED: 
     247                $delegatedParams['status'] = 'rejeitou'; 
     248            break; 
     249                        case STATUS_DELEGATED: 
     250                                $delegatedParams['status'] = 'delegou para um novo participante'; 
     251            break; 
     252                } 
     253                        //notifica o organizador a resposta do delegado 
     254                        self::participantStatusChange( $partID['delegatedFrom'] , $schedulable , $organizer , $type, $delegatedParams ); 
     255         
     256                        $method = 'REQUEST'; 
     257                        $notificationType = 'Resposta Delegação';  
     258                        $part = 'attendees'; 
     259                        self::mountStruture($partID['delegatedFrom'], $schedulable, $type , $data,  $subject, $ical, $part, $method, $notificationType ); 
     260                         
     261                        $data = array_merge($data, $delegatedParams); 
     262                         
     263            self::sendMail($data, $ical , $part['user']['mail'] , $subject , 'notify_response_delegated_status_body'); 
     264        
     265    } 
     266 
     267        public static function mountStruture( $partID , &$schedulable, $type = false, &$data, &$subject, &$ical, &$part = false, &$method, &$notificationType, $regSet = false) { 
     268                 
     269                if( (Config::regGet('ical://'.$schedulable['id'].'/'.$method) === false) || ($method == 'CANCEL') ) //Verifica se o ical ja não esta no reg 
     270                { 
     271                        $schedulable['URI']['concept'] = 'schedulable'; 
     272                        $ical['source'] = Controller::format( array( 'service' => 'iCal' ) , array($schedulable) , array('method' => $method) );   
     273                        $ical['type'] = 'text/calendar'; 
     274                        $ical['name'] = 'calendar.ics'; 
     275                        if($regSet) 
     276                                Config::regSet('ical://'.$schedulable['id'].'/'.$method, $ical); 
     277                } 
     278                else 
     279                        $ical = Config::regGet('ical://'.$schedulable['id'].'/'.$method); 
    99280         
    100            $part = false; 
    101            if( Config::regGet('ical://'.$schedulable['id'].'/REQUEST') === false ) //Verifica se o ical ja não esta no reg 
    102            { 
    103                   $schedulable['URI']['concept'] = 'schedulable'; 
    104                   $ical['source'] = Controller::format( array( 'service' => 'iCal' ) , array($schedulable) , array('method' => 'REQUEST') );   
    105                   $ical['type'] = 'text/calendar'; 
    106                   $ical['name'] = 'calendar.ics'; 
    107                   Config::regSet('ical://'.$schedulable['id'].'/REQUEST', $ical); 
    108            } 
    109            else 
    110                 $ical = Config::regGet('ical://'.$schedulable['id'].'/REQUEST'); 
    111          
    112            $timezone = new DateTimeZone('UTC'); 
    113            $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , $timezone ); 
    114            $eTime =  new DateTime( '@'.(int)($schedulable['endTime'] / 1000) , $timezone );  
     281                        $timezone = new DateTimeZone('UTC'); 
     282                        $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , $timezone ); 
     283                        $eTime =  new DateTime( '@'.(int)($schedulable['endTime'] / 1000) , $timezone );  
    115284            
    116            if(isset($schedulable['timezone'])) 
    117            { 
    118                $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    119                $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    120            } 
     285                        if(isset($schedulable['timezone'])) 
     286                        { 
     287                                $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
     288                                $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
     289                        } 
    121290             
    122            $attList = '<UL> '; 
    123            foreach ($schedulable['participants'] as $i => $v)   
    124            {    
    125                 if($part === false && $v['id'] == $partID) 
    126                    $part = $v; 
    127  
    128                 $attList .= ' <LI> '. (isset($v['user']['name']) ? $v['user']['name'] : $v['user']['mail']) ; 
    129            } 
    130            $attList .= '</UL>'; 
    131                              
    132            $data = array(     'startDate' =>  date_format( $sTime , 'd/m/Y') , 
     291                        $data = array(     'startDate' =>  date_format( $sTime , 'd/m/Y') , 
    133292                              'startTime' =>  ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i') , 
    134293                              'endDate' =>  date_format( $eTime , 'd/m/Y') , 
     
    136295                              'eventTitle' =>  $schedulable['summary'], 
    137296                              'eventLocation' =>  $schedulable['location'], 
    138                               'timezone' =>  ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC' , 
    139                               'participants' =>  $attList); 
    140              
    141              $subject['notificationType'] = 'Convite de Calendario'; 
    142              $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
    143              $subject['startDate'] = date_format( $sTime , 'd/m/Y'); 
    144              $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i'); 
    145              $subject['endDate'] = date_format( $eTime , 'd/m/Y'); 
    146              $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i'); 
    147              $subject['participant'] = Config::me('uid'); 
    148   
    149              self::sendMail($data, $ical , $part['user']['mail'] , $subject , 'notify_create_body'); 
     297                              'timezone' =>  ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC'); 
     298                        $temp = $part; 
     299                        $part = false; 
     300                        switch($temp){ 
     301                                case 'attendees': 
     302                                        $attList = '<UL> '; 
     303                                        foreach ($schedulable['participants'] as $i => $v)   
     304                                        {                
     305                                                if($part === false && $v['id'] == $partID) 
     306                                                   $part = $v; 
     307 
     308                                                $attList .= ' <LI> '. (isset($v['user']['name']) ? $v['user']['name'] : $v['user']['mail']) ; 
     309                                        } 
     310                                        $attList .= '</UL>'; 
     311                                        $data['participants'] = $attList; 
     312                                break; 
     313                                case 'me': 
     314                                        $part = self::_getAttendeeById($partID, $schedulable); 
     315                                        $data['participant'] = isset($part['user']['name']) ? $part['user']['name'] : $part['user']['mail']; 
     316                                break; 
     317                                case 'othersAttendees': 
     318                                        $data['participants'] = '<UL> '; 
     319                                        foreach ($schedulable['participants'] as $ii => $participant){ 
     320                                                if(Config::me('mail') !== $participant['user']['mail']) 
     321                                                        $part[] = $participant['user']['mail']; 
     322                                         
     323                                        $data['participants'] .= ' <LI> '. (isset($participant['user']['name']) ? $participant['user']['name'] : $participant['user']['mail']) ; 
     324                                        } 
     325                                break; 
     326                        }          
     327                        $subject['notificationType'] = $notificationType; 
     328                        $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
     329                        $subject['startDate'] = date_format( $sTime , 'd/m/Y'); 
     330                        $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i'); 
     331                        $subject['endDate'] = date_format( $eTime , 'd/m/Y'); 
     332                        $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i'); 
     333                        $subject['participant'] = Config::me('uid'); 
     334        } 
     335         
     336         
     337    /** 
     338    * Monta o email de convite que sera enviado ao participant 
     339    * 
     340    * @license    http://www.gnu.org/copyleft/gpl.html GPL 
     341    * @author     Consórcio Expresso Livre - 4Linux (www.4linux.com.br) e Prognus Software Livre (www.prognus.com.br) 
     342    * @sponsor    Caixa Econômica Federal 
     343    * @author     Cristiano Corrêa Schmidt 
     344    * @return     void 
     345    * @access     public 
     346    */ 
     347    public static function participantCreated( &$partID , &$schedulable, $type = false, $delegatedParams = false) 
     348    {    
     349                $method = 'REQUEST'; 
     350                $notificationType = 'Convite de Calendario';  
     351                $part = 'attendees'; 
     352                self::mountStruture($partID, $schedulable, $type , $data,  $subject, $ical, $part, $method, $notificationType, true); 
     353         
     354                if($delegatedParams) 
     355                        $data = array_merge($data, $delegatedParams); 
     356                                          
     357                 self::sendMail($data, $ical , $part['user']['mail'] , $subject , !$delegatedParams  ? 'notify_create_body' : 'notify_create_delegated_body' ); 
    150358        
    151359    } 
     
    161369    * @access     public 
    162370    */ 
    163     public static function participantStatusChange( &$partID , &$schedulable , &$organizer , $type ) 
    164     { 
    165         $part = false; 
    166          
    167         foreach ($schedulable['participants'] as $i => $v) //salva em $part as informações do participant a ser notificado      
    168             if(($v['id'] == $partID) && ($part = $v) ) break; 
    169              
    170         if( Config::regGet('ical://'.$schedulable['id'].'/REPLY') === false ) //Verifica se o ical ja não esta no reg 
    171         { 
    172                   $schedulable['URI']['concept'] = 'schedulable'; 
    173                   $ical['source'] = Controller::format( array( 'service' => 'iCal' ) , array($schedulable) , array('method' => 'REPLY' , 'participant' => $partID) );   
    174                   $ical['type'] = 'text/calendar'; 
    175                   $ical['name'] = 'calendar.ics'; 
    176                   Config::regSet('ical://'.$schedulable['id'].'/REPLY', $ical); 
    177          } 
    178          else 
    179             $ical = Config::regGet('ical://'.$schedulable['id'].'/REPLY'); 
    180          
    181          
    182         $timezone = new DateTimeZone('UTC'); 
    183         $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , $timezone ); 
    184         $eTime =  new DateTime( '@'.(int)($schedulable['endTime'] / 1000) , $timezone );  
    185          
    186         if(isset($schedulable['timezone'])) 
    187         { 
    188             $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    189             $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    190         } 
    191          
    192         $data = array('startDate' =>  date_format( $sTime , 'd/m/Y') , 
    193                           'startTime' =>  ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i') , 
    194                           'endDate' =>  date_format( $eTime , 'd/m/Y') , 
    195                           'endTime' =>  ($schedulable['allDay']) ? '' :  date_format( $eTime , 'H:i') , 
    196                           'eventTitle' =>  $schedulable['summary'], 
    197                           'eventLocation' =>  $schedulable['location'], 
    198                           'timezone' =>  ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC' , 
    199                           'participant' =>  (isset($part['user']['name']) ? $part['user']['name'] : $part['user']['mail']) ); 
    200            
    201         $subject['notificationType'] = 'Convite Aceito'; 
    202         $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
    203         $subject['startDate'] = date_format( $sTime , 'd/m/Y'); 
    204         $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i'); 
    205         $subject['endDate'] = date_format( $eTime , 'd/m/Y'); 
    206         $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i'); 
    207         $subject['participant'] = Config::me('uid'); 
    208            
     371    public static function participantStatusChange( &$partID , &$schedulable , &$organizer , $type, $delegatedParams = false ) 
     372    {    
     373        $method = 'REPLY'; 
     374                $notificationType = 'Convite Aceito'; 
     375                $part = 'me'; 
     376                 
     377                self::mountStruture($partID, $schedulable, $type , $data,  $subject, $ical, $part, $method, $notificationType, true ); 
     378                        
     379                if($delegatedParams){ 
     380                        $data = array_merge($data, $delegatedParams); 
     381                        $tplDelegated = 'notify_delegated_status_body'; 
     382                } 
     383 
    209384       switch($type) 
    210385       { 
    211386            case STATUS_ACCEPTED: 
    212                 $tpl =   'notify_accept_body'; 
     387                $tpl =   !$delegatedParams ? 'notify_accept_body' : $tplDelegated; 
    213388                $subject['notificationType'] = 'Convite Aceito'; 
    214389            break; 
    215             case STATUS_TENATIVE: 
    216                 $tpl =   'notify_attempt_body'; 
     390            case STATUS_TENTATIVE: 
     391                $tpl =   !$delegatedParams ? 'notify_attempt_body' : $tplDelegated; 
    217392                $subject['notificationType'] = 'Convite  aceito provisoriamente'; 
    218393            break; 
    219394            case STATUS_CANCELLED: 
    220                 $tpl =   'notify_reject_body'; 
     395                $tpl =   !$delegatedParams ? 'notify_reject_body' : $tplDelegated; 
    221396                $subject['notificationType'] = 'Convite rejeitado'; 
     397            break; 
     398                        case STATUS_DELEGATED: 
     399                                if($delegatedParams) 
     400                                        $data = array_merge($data, $delegatedParams); 
     401                $tpl =   'notify_delegated_body'; 
     402                $subject['notificationType'] = 'Convite delegado'; 
    222403            break; 
    223404 
     
    264445       if((Config::regGet('noAlarm') === false) && (self::futureEvent( $schedulable['startTime'] , $schedulable['rangeEnd']))) 
    265446       { 
    266            $schedulable['URI']['concept'] = 'schedulable';  
    267            $timezone = new DateTimeZone('UTC'); 
    268            $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , $timezone ); 
    269            $eTime =  new DateTime( '@'.(int)($schedulable['endTime'] / 1000) , $timezone );  
    270             
    271            if(isset($schedulable['timezone'])) 
    272            { 
    273                $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    274                $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    275            } 
    276             
    277            $data =  array('startDate' =>  date_format( $sTime , 'd/m/Y') , 
    278                               'startTime' =>  ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i') , 
    279                               'endDate' =>  date_format( $eTime , 'd/m/Y') , 
    280                               'endTime' =>  ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i') , 
    281                               'eventTitle' =>  $schedulable['summary'], 
    282                               'eventLocation' =>  $schedulable['location'], 
    283                               'timezone' =>  ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC'); 
    284                                
    285             
    286            $ical['source'] = Controller::format( array( 'service' => 'iCal' ) , array($schedulable) , array('method' => 'CANCEL'));   
    287            $ical['type'] = 'text/calendar'; 
    288            $ical['name'] = 'calendar.ics'; 
    289             
    290            foreach ($schedulable['participants'] as $ii => $participant) 
    291                 if(Config::me('mail') !== $participant['user']['mail']) 
    292                     $to[] = $participant['user']['mail']; 
    293                      
    294              $subject['notificationType'] = 'Cancelamento de Calendario'; 
    295              $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
    296              $subject['startDate'] = date_format( $sTime , 'd/m/Y'); 
    297              $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i'); 
    298              $subject['endDate'] = date_format( $eTime , 'd/m/Y'); 
    299              $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i'); 
    300              $subject['participant'] = Config::me('uid');      
     447                        $method = 'CANCEL'; 
     448                        $notificationType = 'Cancelamento de Calendario'; 
     449                        $part = 'othersAttendees'; 
     450                        self::mountStruture($uri['id'], $schedulable, false , $data,  $subject, $ical, $part, $method, $notificationType ); 
    301451                 
    302            if(count($to) > 0) 
    303             self::sendMail($data, $ical , implode(',' , $to) ,$subject, 'notify_cancel_body'); 
     452           if(count($part) > 0) 
     453            self::sendMail($data, $ical , implode(',' , $part) ,$subject, 'notify_cancel_body'); 
    304454       } 
    305455    } 
     
    323473       if((Config::regGet('noAlarm') === false) && (self::futureEvent( $schedulable['startTime'] , $schedulable['rangeEnd']))) 
    324474       {   
    325            $schedulable['URI']['concept'] = 'schedulable';  
    326            $timezone = new DateTimeZone('UTC'); 
    327            $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , $timezone ); 
    328            $eTime =  new DateTime( '@'.(int)($schedulable['endTime'] / 1000) , $timezone );  
    329             
    330            if(isset($schedulable['timezone'])) 
    331            { 
    332                $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    333                $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    334            } 
    335             
    336            $data =  array('startDate' =>  date_format( $sTime , 'd/m/Y') , 
    337                               'startTime' => ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i') , 
    338                               'endDate' =>  date_format( $eTime , 'd/m/Y') , 
    339                               'endTime' => ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i') , 
    340                               'eventTitle' =>  $schedulable['summary'], 
    341                               'eventLocation' =>  $schedulable['location'], 
    342                               'timezone' =>  ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC'); 
    343  
    344            $ical['source'] = Controller::format( array( 'service' => 'iCal' ) , array($schedulable) , array('method' => 'CANCEL'));   
    345            $ical['type'] = 'text/calendar'; 
    346            $ical['name'] = 'calendar.ics'; 
    347             
    348              $subject['notificationType'] = 'Cancelamento de Calendario'; 
    349              $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
    350              $subject['startDate'] = date_format( $sTime , 'd/m/Y'); 
    351              $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format( $sTime , 'H:i'); 
    352              $subject['endDate'] = date_format( $eTime , 'd/m/Y'); 
    353              $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format( $eTime , 'H:i'); 
    354              $subject['participant'] = Config::me('uid'); 
    355                            
    356            self::sendMail($data, $ical , $participant['user']['mail'] , $subject , 'notify_cancel_body');   
     475                        $method = 'CANCEL'; 
     476                        $notificationType = 'Cancelamento de Calendario'; 
     477                        $part = 'others'; 
     478                        self::mountStruture(false, $schedulable, false , $data,  $subject, $ical, $part, $method, $notificationType ); 
     479                                             
     480                        self::sendMail($data, $ical , $participant['user']['mail'] , $subject , 'notify_cancel_body');   
    357481        } 
    358482    } 
     
    369493    */ 
    370494    public function updateEvent( &$uri , &$params , &$criteria , $original  ) 
    371     { 
    372         
    373        $schedulableOld =  Controller::read( array( 'concept' => 'schedulable' , 'id' => $uri['id'] ) , null , array('deepness' => '2') ) ;       
     495    {        
     496       $schedulableOld =  Controller::find( array( 'concept' => 'schedulable' , 'id' => $uri['id'] ) , null , array('deepness' => '2') ) ;       
    374497       $schedulable = $schedulableOld; 
    375498       $alt = false; 
    376         
    377        
     499 
    378500       foreach ($params as $i => $v) //Verifica se ouve alteração no evento 
    379501           if( isset( $schedulableOld[$i] ) && $schedulableOld[$i] != $v && $i != 'participants') 
     
    384506            
    385507       if ( ($alt === true) && (Config::regGet('noAlarm') === false) && (self::futureEvent($schedulable['startTime'], $schedulable['rangeEnd'])) )  
    386        { 
    387             $schedulable['URI']['concept'] = 'schedulable'; 
    388             $ical['source'] = Controller::format(array('service' => 'iCal'), array($schedulable), array('method' => 'REQUEST')); 
    389             $ical['type'] = 'text/calendar'; 
    390             $ical['name'] = 'calendar.ics'; 
    391  
    392             $timezone = new DateTimeZone('UTC'); 
    393             $sTime = new DateTime('@' . (int) ($schedulable['startTime'] / 1000), $timezone); 
    394             $eTime = new DateTime('@' . (int) ($schedulable['endTime'] / 1000), $timezone); 
    395  
    396             if (isset($schedulable['timezone'])) { 
    397                 $sTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    398                 $eTime->setTimezone(new DateTimeZone($schedulable['timezone'])); 
    399             } 
    400             ///Montando lista de participantes 
    401             $attList = '<UL> '; 
    402             foreach ($schedulable['participants'] as $ii => $participant) 
    403                 $attList .= ' <LI> ' . (isset($participant['user']['name']) ? $participant['user']['name'] : $participant['user']['mail']); 
    404             $attList .= ' </UL>'; 
    405             ///////////////////////// 
    406  
    407             $data = array('startDate' => date_format($sTime, 'd/m/Y'), 
    408                 'startTime' => ($schedulable['allDay']) ? '' : date_format($sTime, 'H:i'), 
    409                 'endDate' => date_format($eTime, 'd/m/Y'), 
    410                 'endTime' => ($schedulable['allDay']) ? '' : date_format($eTime, 'H:i'), 
    411                 'eventTitle' => $schedulable['summary'], 
    412                 'eventLocation' => $schedulable['location'], 
    413                 'timezone' => ($schedulable['timezone']) ? $schedulable['timezone'] : 'UTC', 
    414                 'participants' => $attList 
    415             ); 
    416  
    417  
    418             foreach ($schedulable['participants'] as $ii => $participant) 
    419                 if (Config::me('mail') !== $participant['user']['mail']) 
    420                     $to[] = $participant['user']['mail']; 
    421  
    422             $subject['notificationType'] = 'Modificação de Calendario'; 
    423             $subject['eventTitle'] = mb_convert_encoding($schedulable['summary'],'ISO-8859-1','ISO-8859-1,UTF-8'); 
    424             $subject['startDate'] = date_format($sTime, 'd/m/Y'); 
    425             $subject['startTime'] = ($schedulable['allDay']) ? '' : date_format($sTime, 'H:i'); 
    426             $subject['endDate'] = date_format($eTime, 'd/m/Y'); 
    427             $subject['endTime'] = ($schedulable['allDay']) ? '' : date_format($eTime, 'H:i'); 
    428             $subject['participant'] = Config::me('uid'); 
    429               
    430             if ( isset($to) && count($to) > 0) 
    431                 self::sendMail($data, $ical, implode(',', $to), $subject, 'notify_modify_body'); 
     508       {                         
     509                        $method = 'REQUEST'; 
     510                        $notificationType = 'Modificação de Calendario';  
     511                        $part = 'othersAttendees'; 
     512                        self::mountStruture($partID, $schedulable, $type , $data,  $subject, $ical, $part, $method, $notificationType); 
     513 
     514            if ( isset($part) && count($part) > 0) 
     515                self::sendMail($data, $ical, implode(',', $part), $subject, 'notify_modify_body'); 
    432516        } 
    433517    } 
  • trunk/prototype/modules/calendar/js/calendar.codecs.js

    r5468 r5514  
    2929                this.preferenceIds = pref.ids; 
    3030    } 
     31} 
     32 
     33constantsParticipant = { 
     34        'o' : 'organization', 
     35        'w' : 'write', 
     36        'p' : 'participationRequired', 
     37        'i' : 'inviteGuests', 
     38        'r' : 'read' 
    3139} 
    3240 
     
    333341}); 
    334342 
     343DataLayer.codec( "suggestion", "duration", { 
     344 
     345    decoder: function( evtObj ){ 
     346                if( notArray = $.type(evtObj) !== "array" ) 
     347                        evtObj = [ evtObj ]; 
     348 
     349 
     350 
     351                var meAttendee = function(attendees){ 
     352                        for(var i = 0; i < attendees.length; i++) 
     353                                if(DataLayer.get('participant', attendees[i]).user == User.me.id) 
     354                                        return attendee; 
     355                }; 
     356 
     357                var res = $.map(evtObj, function( form ){        
     358                        return { 
     359                                participant : meAttendee(form.attendee),  
     360                                startTime: Timezone.getDateUTC(Date.parseExact(form.startDate + (!!form.allDay ? " 00:00": " "+$.trim(form.startHour)) , formatString ), tzId).getTime(), 
     361                                endTime:  parseInt(Timezone.getDateUTC(Date.parseExact(form.endDate + ( !!form.allDay ? " 00:00": " "+$.trim(form.endHour)), formatString ), tzId).getTime()) + (!!form.allDay ? 86400000 : 0) , 
     362                                allDay: ( !!form.allDay ? 1 : 0 ), 
     363                                schedulable: form.idEvent 
     364                        } 
     365                });      
     366         
     367 
     368        return notArray ? res[0] : res; 
     369        }, 
     370         
     371        encoder: function( evtObj ){} 
     372         
     373}); 
     374 
     375DataLayer.codec( "attachment", "detail", { 
     376   
     377        decoder: function(evtObj){ 
     378         
     379                if( notArray = $.type(evtObj) !== "array" ) 
     380                        evtObj = [ evtObj ]; 
     381 
     382                var res = $.map(evtObj, function( form){ 
     383                        return [$.map(form.files , function( files){ 
     384                                        return { source: files }; 
     385                                })]; 
     386                }); 
     387        return notArray ? res[0] : res; 
     388        }, 
     389       
     390        encoder: function(){} 
     391 
     392       
     393}); 
     394 
    335395DataLayer.codec( "schedulable", "preview", { 
    336396 
     
    348408                                id: form.idEvent, 
    349409                                calendar: form.calendar, 
    350                                 participants : [{ 
    351                                         user: User.me.id, 
    352                                         status: form.status, 
    353                                         id: form.meId, 
    354                                         isOrganizer: 0, 
    355                                         alarms: typeof(form.alarmTime) != 'undefined' ?  
    356                                                 $.map( form.alarmTime || [], function( alarmTime, i ){ 
    357  
    358                                                         if( alarmTime === "" ) 
    359                                                                 return( null ); 
    360  
    361                                                         return !!form.alarmId[i] ? 
    362                                                                 { type: form.alarmType[i], unit: form.alarmUnit[i], time: form.alarmTime[i], id: form.alarmId[i] } :  
    363                                                                 { type: form.alarmType[i],unit: form.alarmUnit[i], time: form.alarmTime[i] }; 
    364                                                 }) : [] 
    365                                         }] 
     410                                participants : $.map(form.attendee, function( attendee, i ){ 
     411                                        if(isNaN(attendee)){ 
     412                                                return{ 
     413                                                        id: attendee, 
     414                                                        acl: form.attendeeAcl[i], 
     415                                                        delegatedFrom: !!form.delegatedFrom[i] ? form.delegatedFrom[i] : 0, 
     416                                                        isOrganizer: (form.attendee_organizer == attendee ? 1 : 0 ), 
     417                                                        isExternal: !!parseInt(form.attendeeType[i]) ? 1 : 0, 
     418                                                        acl: form.attendeeAcl[i].replace('o', '') 
     419                                                }; 
     420                                        }else{ 
     421                                                if(DataLayer.get('participant', attendee).user == User.me.id){ 
     422                                                        var me = { 
     423                                                                user: User.me.id, 
     424                                                                status: form.status, 
     425                                                                id: attendee, 
     426                                                                isOrganizer: 0, 
     427                                                                receiveNotification : (!!form.receiveNotification ? 1 : 0), 
     428                                                                alarms: typeof(form.alarmTime) != 'undefined' ?  
     429                                                                        $.map( form.alarmTime || [], function( alarmTime, i ){ 
     430 
     431                                                                                if( alarmTime === "" ) 
     432                                                                                        return( null ); 
     433 
     434                                                                                return !!form.alarmId[i] ? 
     435                                                                                        { type: form.alarmType[i], unit: form.alarmUnit[i], time: form.alarmTime[i], id: form.alarmId[i] } :  
     436                                                                                        { type: form.alarmType[i],unit: form.alarmUnit[i], time: form.alarmTime[i] }; 
     437                                                                        }) : [] 
     438                                                        }; 
     439                                                         
     440                                                        if(form.startDate){ 
     441                                                                var tzId =  DataLayer.get('schedulable', form.idEvent).timezone || User.preferences.timezone, 
     442                                                                formatString = ( typeof form.allDay !== "undefined" && !!form.allDay )? pref.dateFormat+" HH:mm" : pref.dateFormat + " " + pref.hourFormat; 
     443                                                                 
     444                                                                DataLayer.put('notification', { 
     445                                                                        participant: me.id, 
     446                                                                        type: 'suggestion', 
     447                                                                        startTime: Timezone.getDateUTC(Date.parseExact(form.startDate + (!!form.allDay ? " 00:00": " "+$.trim(form.startHour)) , formatString ), tzId).getTime(), 
     448                                                                        endTime:  parseInt(Timezone.getDateUTC(Date.parseExact(form.endDate + ( !!form.allDay ? " 00:00": " "+$.trim(form.endHour)), formatString ), tzId).getTime()) + (!!form.allDay ? 86400000 : 0) , 
     449                                                                        allDay: ( !!form.allDay ? 1 : 0 ), 
     450                                                                        schedulable: form.idEvent 
     451                                                                }); 
     452                                                         
     453                                                        } 
     454                                                        return me; 
     455                                                }else return(null); 
     456                                        }; 
     457                                }) 
    366458                        } 
    367459                }); 
    368                  
    369460                return notArray ? res[0] : res; 
    370461    }, 
     
    381472        statusLabels = [ '', 'accepted', 'tentative', 'cancelled', 'unanswered', 'delegated' ]; 
    382473         
     474        var delegateAttendee = {}; 
     475         
    383476        for( var i = 0; i < statusLabels.length; i++ ) 
    384477                statusParticipants[ statusLabels[i] ] = 0; 
    385  
    386         var isOrganizer = 1; 
    387478         
    388479        var res = $.map(evtObj, function( objEvent ){                    
    389480                     
    390                         var participantInfo = {}, me = DataLayer.copy(User.me); 
     481                        var participantInfo = {}, delegatedFrom = {}, me = DataLayer.copy(User.me); 
     482                         
     483                        var constantAcl = function(acl){ 
     484                                var returns = {}; 
     485                                for (var i in constantsParticipant){ 
     486                                        returns[constantsParticipant[i]] = acl.indexOf(i) >= 0 ? true : false 
     487                                } 
     488                                return returns; 
     489                        }; 
    391490                                                 
    392491                    return { 
     
    406505                            endHour: dateCalendar.formatDate(Timezone.setDateTimezone(new Date(parseInt(objEvent.endTime)), objEvent.timezone, objEvent.calendar), User.preferences.hourFormat), 
    407506                            allDay: !!parseInt( objEvent.allDay ), 
    408           //                            attachments: this.decode( "attachment:detail", form ), 
     507                                attachments: $.map(objEvent.attachments || [], function( attachment, i ){ 
     508                                        var attach = DataLayer.get('schedulableToAttachment', attachment, false); 
     509                                        attach.name = attach.name.length < 10 ?  attach.name : ( attach.name.substr(0, 6) + attach.name.substr( attach.name.length-4, attach.name.length)); 
     510                                         
     511                                        return attach; 
     512                                }),                                              
    409513                            attendee: $.map(objEvent.participants || [], function( participant, i ){                                             
     514                                         
     515                                        if(delegateAttendee[participant]) 
     516                                                return(null); 
    410517                                         
    411518                                        var attend = DataLayer.get('participant', participant); 
     
    416523                                        if( attend.user.id ===  me.id ){ 
    417524                                            participantInfo.user = { 
     525                                                        id: attend.id, 
    418526                                                        status : attend.status, 
     527                                                        delegatedFrom: attend.delegatedFrom, 
     528                                                        acl: attend.acl, 
     529                                                        receiveNotification : attend.receiveNotification, 
    419530                                                        alarms : $.map(attend.alarms || [], function( alarm ){ 
    420531                                                                return DataLayer.get('alarm', alarm); 
     
    422533                                                }; 
    423534                                                me.id = attend.id; 
    424                                                 return(null); 
     535                                                return(null); 
    425536                                        }; 
    426537                                         
     
    429540                                                name: attend.user.name != 'false' ? attend.user.name : '', 
    430541                                                mail: attend.user.mail, 
    431                                                 isExternal: attend.isExternal 
     542                                                status : attend.status, 
     543                                                isExternal: attend.isExternal, 
     544                                                acl: attend.acl, 
     545                                                delegatedFrom: attend.delegatedFrom 
    432546                                        }; 
    433547                                         
     548                                        if(!!parseInt(attend.delegatedFrom)){ 
     549                                                delegatedFrom[attend.delegatedFrom] = DataLayer.copy(person); 
     550                                                return(null); 
     551                                        } 
     552                                         
    434553                                        if( !!parseInt(attend.isOrganizer )){ 
    435                                                 isOrganizer = ((attend.user.id == User.me.id) || (!!!attend.user)) ? 1 : 0; 
    436554                                            participantInfo.organizer = DataLayer.copy(person); 
    437555                                                return(null); 
     
    441559                                }), 
    442560                            organizer: participantInfo.organizer || me, 
    443                             alarms: !!participantInfo.user ?  participantInfo.user.alarms : [], 
    444                             status: !!participantInfo.user ? participantInfo.user.status :  1, 
    445                             me: me, 
    446                                 isOrganizer: isOrganizer, 
     561                            alarms: !!participantInfo.user ? participantInfo.user.alarms : [], 
     562                            status: !!participantInfo.user ? participantInfo.user.status : 1, 
     563                                acl: !!participantInfo.user ? constantAcl(participantInfo.user.acl) : constantAcl('rowi'), 
     564                            me: !!participantInfo.user ? DataLayer.merge(participantInfo.user, me) : DataLayer.merge(me, {acl: 'rowi', delegatedFrom: 0, receiveNotification: 1}), 
     565                                delegatedFrom: delegatedFrom, 
    447566                                statusParticipants: statusParticipants 
    448567                        }; 
    449                 }); 
    450  
     568                });      
    451569        return notArray ? res[0] : res; 
    452570    } 
     
    485603                              description: form.description, 
    486604                              timezone: tzId, 
     605                                  attachments: $.map(form.attachment || [], function( attachment, i ){ 
     606                                                return {attachment: attachment} 
     607                                  }), 
    487608                              participants: $.map( form.attendee || [], function( attendee, i ){ 
    488609 
     
    495616                                                if( participant.user === User.me.id ){ 
    496617                                                        return DataLayer.merge({ 
    497                                                                 isOrganizer: ( !i ? 1 : 0 ), 
     618                                                                id: attendee, 
     619                                                                isOrganizer: (form.attendee_organizer == attendee ? 1 : 0 ), 
     620                                                                acl: form.attendee_organizer == attendee ? (form.attendeeAcl[i].indexOf('o') < 0 ? form.attendeeAcl[i]+'o' : form.attendeeAcl[i]) : form.attendeeAcl[i].replace('o', ''), 
    498621                                                                alarms: participant.alarms = $.map( form.alarmTime || [], function( alarmTime, i ){ 
    499622                                                                                if( alarmTime === "" ) 
     
    502625                                                                                                                                        { type: form.alarmType[i],unit: form.alarmUnit[i], time: form.alarmTime[i] }; 
    503626                                                                        }), 
    504                                                                 status: form.status 
    505                                                         }, !!form.idEvent ? {id: attendee} : {user: participant.user});                                                  
     627                                                                status: !!form.status ? form.status : 3 
     628                                                                }, form.delegatedFrom[i] != '0' ? {delegatedFrom: form.delegatedFrom[i]} : {});                                                  
    506629                                                }else{ 
    507                                                         return { 
     630                                                        return DataLayer.merge({ 
    508631                                                                id: attendee, 
    509                                                                 isOrganizer: ( !i ? 1 : 0 ), 
    510                                                                 isExternal: !!parseInt(form.attendeeType[i]) ? 1 : 0 
    511                                                         }; 
     632                                                                acl: form.attendeeAcl[i], 
     633                                                                isOrganizer: (form.attendee_organizer == attendee ? 1 : 0 ), 
     634                                                                isExternal: !!parseInt(form.attendeeType[i]) ? 1 : 0, 
     635                                                                acl: form.attendee_organizer == attendee ? (form.attendeeAcl[i].indexOf('o') < 0 ? form.attendeeAcl[i]+'o' : form.attendeeAcl[i]) : form.attendeeAcl[i].replace('o', '') 
     636                                                        }, form.delegatedFrom[i] != '0' ? {delegatedFrom: form.delegatedFrom[i]} : {});  
    512637                                                }; 
    513638                                          }) 
     
    719844                        for(var i = 0; i < evt.participants.length; i++){ 
    720845                                attendee = DataLayer.get('participant', evt.participants[i]); 
    721                                 if(!!parseInt(attendee.isOrganizer)) 
    722846                                        if(attendee.user == User.me.id) 
    723                                                 return true; 
    724                                         else 
    725                                                 return false; 
     847                                                return (attendee.acl.indexOf('w') >= 0 || attendee.acl.indexOf('o') >= 0 ) ? true : false; 
    726848                        } 
    727849                } 
  • trunk/prototype/modules/calendar/js/helpers.js

    r5510 r5514  
    4545} 
    4646*/ 
     47 
    4748function eventDetails( objEvent, decoded, path) 
    4849{ 
     
    6970         */ 
    7071        zebraDiscardEventDialog = false; 
     72         
     73        /** 
     74                ACLs do participant 
     75        */ 
     76        acl_names = { 
     77                'w': 'acl-white', 
     78                'i': 'acl-invite-guests', 
     79                'p': 'acl-participation-required' 
     80        }; 
     81        /** 
     82        * callback de participantes generico 
     83        */ 
     84        var callbackAttendee = function(){ 
     85                //Cria qtip de permissões pelo click do checkbox 
     86                var checked = false; 
     87                blkAddAtendee.find("li.not-attendee").addClass('hidden'); 
     88         
     89                blkAddAtendee.find("li .button").filter(".close.new").button({ 
     90                        icons: { 
     91                                primary: "ui-icon-close" 
     92                        }, 
     93                        text: false 
     94                }).click(function () { 
     95                        DataLayer.remove('participant', $(this).parents('li').find('[type=checkbox]').val()); 
     96                        $(this).parents('li').remove(); 
     97                        if(blkAddAtendee.find(".attendee-list li").length == 1) 
     98                                blkAddAtendee.find("li.not-attendee").removeClass('hidden'); 
     99                }) 
     100                .addClass('tiny disable ui-button-disabled ui-state-disabled') 
     101                .removeClass('new').end() 
     102         
     103                .filter(".delegate.new").button({ 
     104                        icons: { 
     105                                primary: "ui-icon-transferthick-e-w" 
     106                        }, 
     107                        text: false 
     108                }).click(function () { 
     109                                                 
     110                        if($(this).hasClass('attendee-permissions-change-button')){ 
     111                                $(this).removeClass('attendee-permissions-change-button')    
     112                                .find('.ui-icon-transferthick-e-w').removeClass('attendee-permissions-change').end();                
     113                                 
     114                                $(this).parents('li').find('input[name="delegatedFrom[]"]').val(''); 
     115                                 
     116                                blkAddAtendee.find('.request-update').addClass('hidden'); 
     117                                blkAddAtendee.find('.status option').toggleClass('hidden'); 
     118                                 
     119                                 
     120                                blkAddAtendee.find('option[value=1]').attr('selected','selected').trigger('change'); 
     121                                 
     122                        }else{ 
     123                                blkAddAtendee.find('.delegate').removeClass('attendee-permissions-change-button'); 
     124                                blkAddAtendee.find('.ui-icon-transferthick-e-w').removeClass('attendee-permissions-change'); 
     125                         
     126                                $(this).addClass('attendee-permissions-change-button')    
     127                                .find('.ui-icon-transferthick-e-w').addClass('attendee-permissions-change').end();                
     128                                $(this).parents('li').find('input[name="delegatedFrom[]"]').val(blkAddAtendee.find('.me input[name="attendee[]"]').val()); 
     129                         
     130                                blkAddAtendee.find('.request-update').removeClass('hidden'); 
     131                                if(blkAddAtendee.find('.status option.hidden').length == 1) 
     132                                        blkAddAtendee.find('.status option').toggleClass('hidden'); 
     133                         
     134                                blkAddAtendee.find('option[value=5]').attr('selected','selected').trigger('change'); 
     135                        } 
     136                }) 
     137                .addClass('tiny disable ui-button-disabled ui-state-disabled') 
     138                .removeClass('new').end() 
     139                 
     140                .filter(".edit.new").button({ 
     141                        icons: { 
     142                                primary: "ui-icon-key" 
     143                        }, 
     144                        text: false 
     145                }).click(function() { 
     146                         
     147                        if(!!!checked) 
     148                                $(this).parents('li').find('[type=checkbox]').attr('checked', (!$(this).parent().find('[type=checkbox]').is(':checked'))).end(); 
     149                         
     150                        var aclsParticipant =  $(this).parents('li').find('input[name="attendeeAcl[]"]').val(); 
     151                        checked = false; 
     152                         
     153                        if( $('.qtip.qtip-blue.qtip-active').val() !== ''){ 
     154                                blkAddAtendee.find('dd.attendee-list').qtip({ 
     155                                        show: {ready: true, solo: true, when: {event: 'click'}}, 
     156                                        hide: false, 
     157                                        content: { 
     158                                                text: $('<div></div>').html( DataLayer.render( 'templates/attendee_permissions.ejs', {} ) ),  
     159                                                title: { 
     160                                                        text:'Permissões',  
     161                                                        button: '<a class="button close" href="#">close</a>' 
     162                                                } 
     163                                        }, 
     164                                        style: {name: 'blue', tip: {corner: 'leftMiddle'}, border: {width: 4, radius: 8}, width: {min: 230, max:230}}, 
     165                                        position: { 
     166                                                corner: { 
     167                                                        target: 'rightMiddle', 
     168                                                        tooltip: 'leftMiddle' 
     169                                                }, 
     170                                                adjust: {x:0, y:0} 
     171                                        } 
     172                                }) 
     173                                .qtip("api").onShow = function(arg0) { 
     174                                        $('.qtip-active .button.close').button({ 
     175                                                icons: {primary: "ui-icon-close"}, 
     176                                                text: false 
     177                                        }) 
     178                                        .click(function(){ 
     179                                                blkAddAtendee.find('dd.attendee-list').qtip('destroy'); 
     180                                        }); 
     181                                         
     182                                        $('.qtip-active .button.save').button().click(function(){ 
     183                                                 
     184                                                var acl = ''; 
     185                                                $('.qtip-active').find('[type=checkbox]:checked').each(function(i, obj) { 
     186                                                        acl+= obj.value; 
     187                                                }); 
     188 
     189                                                blkAddAtendee.find('dd.attendee-list [type=checkbox]:checked').siblings('input[name="attendeeAcl[]"]').each(function(i, obj) {  
     190                                                        obj.value = 'r'+acl; 
     191                                                }).parents('li').find('.button.edit').addClass('attendee-permissions-change-button')    
     192                                                .find('.ui-icon-key').addClass('attendee-permissions-change');                
     193                                                 
     194                                                blkAddAtendee.find('dd.attendee-list [type=checkbox]').attr('checked', false); 
     195                                                 
     196                                                blkAddAtendee.find('dd.attendee-list').qtip('destroy'); 
     197                                         
     198                                        }); 
     199                                        $('.qtip-active .button.cancel').button().click(function(){ 
     200                                                blkAddAtendee.find('dd.attendee-list [type=checkbox]').attr('checked', false); 
     201                                                blkAddAtendee.find('dd.attendee-list').qtip('destroy'); 
     202                                        }); 
     203                                         
     204                                        if(aclsParticipant) 
     205                                                for(var i = 1; i < aclsParticipant.length; i++){ 
     206                                                        $('.qtip-active').find('input[name="'+acl_names[aclsParticipant.charAt(i)]+'"]').attr('checked', true); 
     207                                                } 
     208                                         
     209                                         
     210                                        $('.button').button(); 
     211                                         
     212                                }; 
     213                        }else{ 
     214                                if(!$('.new-event-win dd.attendee-list').find('[type=checkbox]:checked').length){ 
     215                                        blkAddAtendee.find('dd.attendee-list').qtip('destroy'); 
     216                                }else{ 
     217                                        $('.qtip-active .button.save .ui-button-text').html('Aplicar a todos') 
     218                                } 
     219                         
     220                        };                       
     221                }) 
     222                .addClass('tiny disable ui-button-disabled ui-state-disabled') 
     223                .removeClass('new').end() 
     224                 
     225                .filter(".open-delegate.new").click(function(){ 
     226                        if($(this).hasClass('ui-icon-triangle-1-e')){ 
     227                                $(this).removeClass('ui-icon-triangle-1-e').addClass('ui-icon-triangle-1-s'); 
     228                                $(this).parents('li').find('.list-delegates').removeClass('hidden'); 
     229                        }else{ 
     230                                $(this).removeClass('ui-icon-triangle-1-s').addClass('ui-icon-triangle-1-e'); 
     231                                $(this).parents('li').find('.list-delegates').addClass('hidden'); 
     232                        } 
     233                 
     234                }).removeClass('new'); 
     235         
     236         
     237                blkAddAtendee.find("li input[type=checkbox].new").click(function(){ 
     238                        if(!$('.new-event-win dd.attendee-list').find('[type=checkbox]:checked').length){ 
     239                                blkAddAtendee.find('dd.attendee-list').qtip('destroy'); 
     240                        }else{ 
     241                                checked = true; 
     242                                $(this).parents('li').find('.button.edit').click(); 
     243                                //$('.qtip-active .button.save .ui-button-text').html('Aplicar a todos') 
     244                        } 
     245                         
     246                        checked = true; 
     247                        $(this).parents('li').find('.button.edit').click(); 
     248                }).removeClass('new'); 
     249         
     250                UI.dialogs.addEvent.find('.attendees-list li').hover( 
     251                        function () { 
     252                                $(this).addClass("hover-attendee"); 
     253                                $(this).find('.button').removeClass('disable ui-button-disabled ui-state-disabled').end() 
     254                                .find('.attendee-options').addClass('hover-attendee'); 
     255                        }, 
     256                        function () { 
     257                                $(this).removeClass("hover-attendee"); 
     258                                $(this).find('.button').addClass('disable ui-button-disabled ui-state-disabled').end() 
     259                                .find('.attendee-options').removeClass('hover-attendee');; 
     260                        } 
     261                ); 
     262         
     263                 
     264        } 
    71265         
    72266        var html = DataLayer.render( path+'templates/event_add.ejs', {event:objEvent});  
     
    99293                                                                        if(clicked == 'Descartar alterações') { 
    100294                                                                                canDiscardEventDialog = true; 
     295                                                                                /** 
     296                                                                                *Remoção dos anexos do eventos caso seja cancelado a edição 
     297                                                                                */ 
     298                                                                                var ids = []; 
     299                                                                                $.each($('.attachment-list input'), function (i, input) { ids.push(input.value); }); 
     300                                                                                if(ids.length > 0) 
     301                                                                                        DataLayer.remove('attachment', {filter: ['IN', 'id', ids]}); 
     302                                                                                 
    101303                                                                                UI.dialogs.addEvent.dialog('close'); 
    102304                                                                        }else{ 
     
    256458                        canDiscardEventDialog = true; 
    257459                         
    258                         UI.dialogs.addEvent.children(".form-addevent").submit(); 
     460                        UI.dialogs.addEvent.children().find('form.form-addevent').submit(); 
    259461                        UI.dialogs.addEvent.dialog("close"); 
    260462            }).end() 
    261463                 
    262464                .children(".export").click(function(){ 
    263                         UI.dialogs.addEvent.children(".form-export").submit(); 
     465                        UI.dialogs.addEvent.children().find(".form-export").submit(); 
    264466            }); 
    265467 
     
    293495            }); 
    294496             
    295 //          UI.dialogs.addEvent.find('.button-add-attachment').click(function(){ 
    296 //                  var li_attach =  
    297 //                          '<li class="input_label">' +  
    298 //                                  '<input type="file" name="attachments[]"" />' + 
    299 //                          '</li>'; 
    300 //                  jQuery('.attachments-list').append(li_attach); 
    301 //          }); 
    302              
    303                 var attendeeHtml = DataLayer.render( path+'templates/attendee_add.ejs', {event:objEvent}); 
     497                  
     498                UI.dialogs.addEvent.find('.button.suggestion-hours').button({ 
     499                        icons: { 
     500                                primary: "ui-icon-clock" 
     501                        }, 
     502                        text: 'Sugerir horário' 
     503                }).click(function () { 
     504                        $(this).siblings('input').removeAttr('disabled') 
     505                        .end().parents().find('input[name="allDay"]').removeAttr('disabled');            
     506                }); 
     507 
     508                if(objEvent.me.id == User.me.id){ 
     509                        objEvent.me.id = DataLayer.put('participant', {user: objEvent.me.id, mail: objEvent.me.mail }); 
     510                        objEvent.organizer.id = objEvent.me.id; 
     511                } 
     512 
     513                var attendeeHtml = DataLayer.render( path+'templates/attendee_add.ejs', {event:objEvent});               
    304514         
    305515                        // load template of attendees 
    306516                        var blkAddAtendee = UI.dialogs.addEvent.find('#calendar_addevent_details6').append(attendeeHtml); 
    307                          
    308                         blkAddAtendee.find('li.attendee .button').addClass('small '+ (objEvent.isOrganizer == 1 ? '' : 'hidden')).button({text:false, icons: {primary:'ui-icon-close'}}).click(function () { 
    309                                 DataLayer.remove('participant', $(this).parent().find('[type=checkbox]').val()); 
    310                                 $(this).parent().remove(); 
    311                         }); 
     517                        if(objEvent.attendee.length) 
     518                                callbackAttendee(); 
     519                        /** 
     520                                Opções de delegação do participante/organizer 
     521                        */               
     522                        blkAddAtendee.find(".button.participant-delegate").button({ 
     523                                icons: { 
     524                                        primary: "ui-icon-transferthick-e-w" 
     525                                }, 
     526                                text: false 
     527                        }).click(function () { 
     528                                if($(this).hasClass('attendee-permissions-change-button')){ 
     529                                        if(!$(this).hasClass('disable')){ 
     530                                                $(this).removeClass('attendee-permissions-change-button')    
     531                                                .find('.ui-icon-transferthick-e-w').removeClass('attendee-permissions-change').end();                
     532                                                blkAddAtendee.find('.block-add-attendee.search').addClass('hidden'); 
     533                                                blkAddAtendee.find('.block-add-attendee.search dt').html('Adicionar outros contatos'); 
     534                                        } 
     535                                }else{                                                                   
     536                                        $(this).addClass('attendee-permissions-change-button')    
     537                                        .find('.ui-icon-transferthick-e-w').addClass('attendee-permissions-change').end();                
     538                                        blkAddAtendee.find('.block-add-attendee.search dt').html('Delegar participação para'); 
     539                                        blkAddAtendee.find('.block-add-attendee.search').removeClass('hidden'); 
     540                                        blkAddAtendee.find('.block-add-attendee.search input.search').focus(); 
     541                                } 
     542                        }) 
     543                        .addClass('tiny');               
     544                         
    312545                        //show or hidden permissions attendees 
    313546                        //blkAddAtendee.find('.block-attendee-list #attendees-users li').click(show_permissions_attendees);  
     
    481714                                                        user[0].id =  DataLayer.put('participant', {user: user[0].id, isExternal: isExternal}); 
    482715                                                        blkAddAtendee.find('dd.attendee-list ul.attendee-list').append( 
    483                                                                 DataLayer.render(path+'templates/participants_add_itemlist.ejs', user) 
     716                                                                DataLayer.render(path+'templates/participants_add_itemlist.ejs', {user:user, acl: objEvent.acl}) 
    484717                                                        ) 
    485                                                         .find('.button.close').addClass('small').button({text:false, icons:{primary:'ui-icon-close'}}).click(function() { 
    486                                                                 DataLayer.remove('participant', $(this).parent().find('[type=checkbox]').val()); 
    487                                                                 $(this).parent().remove(); 
    488                                                         }).end() 
    489718                                                        .scrollTo('max'); 
     719                                                        callbackAttendee(); 
    490720                                                } 
    491721                                                 
     
    503733                                                  
    504734                                                blkAddAtendee.find('dd.attendee-list ul.attendee-list').append( 
    505                                                         DataLayer.render(path+'templates/participants_add_itemlist.ejs', [{id:newAttendeeId, name: newAttendeeName, mail: newAttendeeEmail, isExternal: 1}]) 
    506                                                 ).find('.button.close').addClass('small').button({text:false, icons:{primary:'ui-icon-close'}}).click(function() { 
    507                                                         DataLayer.remove('participant', $(this).parent().find('[type=checkbox]').val()); 
    508                                                         $(this).parent().remove(); 
    509                                                 }).end() 
    510                                                 .scrollTo('max'); 
    511  
     735                                                        DataLayer.render(path+'templates/participants_add_itemlist.ejs', [{id:newAttendeeId, name: newAttendeeName, mail: newAttendeeEmail, isExternal: 1, acl: objEvent.acl}]) 
     736                                                ).scrollTo('max'); 
     737                                                callbackAttendee(); 
    512738 
    513739                                                /**  
     
    573799                                                        newAttendeeId = DataLayer.put('participant', {user: old_item.find('.id').html(), isExternal: 0}); 
    574800                                                        blkAddAtendee.find('dd.attendee-list ul.attendee-list') 
    575                                                         .append(DataLayer.render(path+'templates/participants_add_itemlist.ejs', [{id: newAttendeeId, name: old_item.find('.name').html(), mail: old_item.find('.mail').html(), isExternal: 0}])) 
    576                                                         .find('.button').addClass('small').button({text:false, icons: {primary:'ui-icon-close'}}).click(function () { 
    577                                                                 $(this).parent().remove(); 
    578                                                         }).end() 
     801                                                        .append(DataLayer.render(path+'templates/participants_add_itemlist.ejs', [{id: newAttendeeId, name: old_item.find('.name').html(), mail: old_item.find('.mail').html(), isExternal: 0, acl: objEvent.acl}])) 
    579802                                                        .scrollTo('max'); 
    580  
    581                                                         old_item.remove(); 
     803                                                        /** 
     804                                                        * Delegação de participação de um participante com permissão apenas de leitura 
     805                                                        * 
     806                                                        */ 
     807                                                        if(!objEvent.acl.organization && !objEvent.acl.write && !objEvent.acl.inviteGuests && objEvent.acl.read ){ 
     808                                                                 
     809                                                                blkAddAtendee.find('.block-add-attendee.search').addClass('hidden'); 
     810                                                                blkAddAtendee.find('.block-add-attendee.search dt').html('Adicionar outros contatos'); 
     811                                                                 
     812                                                                blkAddAtendee.find('.status option').toggleClass('hidden'); 
     813                                                                blkAddAtendee.find('option[value=5]').attr('selected','selected').trigger('change'); 
     814                                                                blkAddAtendee.find('.request-update').removeClass('hidden'); 
     815 
     816                                                                blkAddAtendee.find('dd.attendee-list ul.attendee-list li .button.close').parents('li').find('input[name="delegatedFrom[]"]').val(blkAddAtendee.find('.me input[name="attendee[]"]').val()); 
     817                                                                 
     818                                                                blkAddAtendee.find('.me .participant-delegate').addClass('disable ui-button-disabled ui-state-disabled'); 
     819                                                                blkAddAtendee.find(".button.close").button({ 
     820                                                                        icons: { 
     821                                                                                primary: "ui-icon-close" 
     822                                                                        }, 
     823                                                                        text: false 
     824                                                                }).click(function () { 
     825                                                                         
     826                                                                        $(this).parents('li').find('input[name="delegatedFrom[]"]').val(''); 
     827                                                                        blkAddAtendee.find('.request-update').addClass('hidden'); 
     828                                                                        blkAddAtendee.find('.status option').toggleClass('hidden'); 
     829                                                                        blkAddAtendee.find('option[value=1]').attr('selected','selected').trigger('change');                     
     830                                                                        blkAddAtendee.find('.me .participant-delegate').removeClass('disable ui-button-disabled ui-state-disabled attendee-permissions-change-button') 
     831                                                                        .find('.ui-icon-person').removeClass('attendee-permissions-change').end();                       
     832                                                                         
     833                                                                        DataLayer.remove('participant', $(this).parents('li').find('[type=checkbox]').val()); 
     834                                                                        $(this).parents('li').remove(); 
     835                                                                }) 
     836                                                                .addClass('tiny'); 
     837                                                        }else{ 
     838                                                                callbackAttendee(); 
     839                                                                old_item.remove(); 
     840                                                        } 
    582841                                                } 
    583842                                        }); 
     
    586845                                } 
    587846                        }); 
    588  
    589 /* 
    590                         UI.dialogs.addEvent.find('.attendees-list li').hover( 
    591                                 function () { 
    592                                         $(this).addClass("hover"); 
    593                                 }, 
    594                                 function () { 
    595                                         $(this).removeClass("hover"); 
     847                        //$('.block-add-attendee .search-result-list').selectable(); 
     848 
     849                UI.dialogs.addEvent.find('.row.fileupload-buttonbar .button').filter('.delete').button({ 
     850                        icons: { 
     851                                primary: "ui-icon-close" 
     852                        }, 
     853                                text: 'Excluir' 
     854                        }).click(function () { 
     855                                $('.row.fileupload-buttonbar .attachments-list p').remove(); 
     856                                 
     857                                var ids = []; 
     858                                $.each($('.attachment-list input'), function (i, input) { ids.push(input.value); }); 
     859                                if(ids.length > 0){ 
     860                                        DataLayer.remove('attachment', {filter: ['IN', 'id', ids]}); 
     861                                        $('.attachment-list input').remove(); 
    596862                                } 
    597                         ); 
    598 */ 
    599                         //$('.block-add-attendee .search-result-list').selectable(); 
    600  
    601                         UI.dialogs.addEvent.find('.block-attendee-list select.status').change(function(){ 
    602                                 if ($(this).val() == 'another') { 
    603         //                              jQuery('.block-attendee-list .add-attendee-search').removeClass('hidden'); 
    604                                         $(this).qtip({ 
    605                                                 show: {ready: true}, 
    606                                                 hide: false, 
    607                                                 content: { 
    608                                                         text: $('.block-attendee-list .add-attendee-search').clone().removeClass('hidden'),  
    609                                                         title: { 
    610                                                                 text:'Indique o participante',  
    611                                                                 button: '<a class="button close" href="#">close</a>' 
    612                                                         } 
    613                                                 }, 
    614                                                 style: {name: 'blue', tip: {corner: 'leftMiddle'}, border: {width: 4, radius: 8}, width: {min: 250, max:250}}, 
    615                                                 position: { 
    616                                                         corner: { 
    617                                                                 target: 'rightMiddle', 
    618                                                                 tooltip: 'leftMiddle' 
    619                                                         }, 
    620                                                         adjust: {x:0, y:0} 
    621                                                 } 
    622                                         }) 
    623                                         $(this).qtip.onShow = function() { 
    624                                                 $('.qtip .button.close').button({ 
    625                                                         icons: {primary: "ui-icon-close"}, 
    626                                                         text: false 
    627                                                 }); 
    628                                         } 
    629                                 } else { 
    630         //                              jQuery('.block-attendee-list .add-attendee-search').addClass('hidden'); 
    631                                 } 
    632                         }); 
    633                 UI.dialogs.addEvent.find(':input').change(function(event){ 
    634                         if (event.keyCode != '27' && event.keyCode != '13') 
    635                                 canDiscardEventDialog = false; 
    636                 }).keydown(function(event){ 
    637                         if (event.keyCode != '27' && event.keyCode != '13') 
    638                                 canDiscardEventDialog = false; 
     863                }).end() 
     864                .filter('.close').button({ 
     865                        icons: { 
     866                                primary: "ui-icon-close" 
     867                        }, 
     868                                text: false 
     869                        }).click(function () { 
     870                                DataLayer.remove('attachment', $(this).parents('p').find('input[name="fileId[]"]').val()); 
     871                                $(this).parents('p').remove(); 
     872                }).end() 
     873                .filter('.downlaod-archive').button({ 
     874                        icons: { 
     875                                primary: "ui-icon-arrowthickstop-1-s" 
     876                        }, 
     877                                text: false 
    639878                }); 
     879                 
     880        $('#fileupload').fileupload({ 
     881                sequentialUploads: true, 
     882                add: function (e, data) { 
     883                        if(data.files[0].size < 30000000) 
     884                                data.submit(); 
     885                }, 
     886                change: function (e, data) { 
     887                        $.each(data.files, function (index, file) { 
     888                                var attach = {}; 
     889                                attach.fileName = file.name; 
     890                                if(file.name.length > 10) 
     891                                        attach.fileName = file.name.substr(0, 6) + file.name.substr(file.name.length-4, file.name.length); 
     892                                attach.fileSize = file.size; 
     893                                if(file.size > 30000000) 
     894                                        attach.error = 'Tamanho de arquivo nao permitido!!' 
     895                                 
     896                                $('.attachments-list').append(DataLayer.render(path+'templates/attachment_add_itemlist.ejs', {file : attach})); 
     897                                 
     898                                if(file.size < 30000000){ 
     899                                        $('.fileinput-button.new').append(data.fileInput[0]).removeClass('new'); 
     900                                        $('.attachments-list').find('[type=file]').addClass('hidden'); 
     901                                         
     902                                }else 
     903                                        $('.fileinput-button.new').removeClass('new'); 
     904                                 
     905                                 
     906                                $('.attachments-list').find('.button.close').button({ 
     907                                        icons: { 
     908                                                primary: "ui-icon-close" 
     909                                        }, 
     910                                        text: false 
     911                                }).click(function(){ 
     912                                        var idAttach = $(this).parent().find('input[name="fileId[]"]').val(); 
     913                                        $('.attachment-list').find('input[value="'+idAttach+'"]') 
     914                                        $(this).parent().remove(); 
     915                                });      
     916                                 
     917                })}, 
     918                progress: function(e, data){ 
     919                        var value = parseInt(data.loaded / data.total * 100, 10); 
     920                        $('.progress.in-progress:first').removeClass('hidden') 
     921                        $('.progress.in-progress:first').progressbar({ 
     922                                value: value 
     923                        }); 
     924                         
     925                        if(value == 100){ 
     926                                $('.progress.in-progress:first').removeClass('in-progress').addClass('on-complete').fadeOut('slow'); 
     927                        } 
     928                                 
     929                }, 
     930                done: function(e, data){ 
     931                        if(!!data.result && data.result != "[]"){ 
     932                                var newAttach = jQuery.parseJSON(data.result); 
     933                                $('.attachment-list').append('<input tyepe="hidden" name="attachment[]" value="'+newAttach['attachment'][0][0].id+'"/>'); 
     934                                $('.progress.on-complete:first').removeClass('on-complete').parents('p') 
     935                                .append('<input type="hidden" name="fileId[]" value="'+newAttach['attachment'][0][0].id+'"/>') 
     936                                .find('.status-upload').addClass('ui-icon ui-icon-check'); 
     937                        }else 
     938                                $('.progress.on-complete:first').removeClass('on-complete').parents('p').find('.status-upload').addClass('ui-icon ui-icon-cancel'); 
     939                                 
     940                        console.log("oi doen"); 
     941                } 
     942        }); 
     943                $('.attachments-list .button').button(); 
     944                 
     945                 
     946                 
     947        $('#fileupload').bind('fileuploadstart', function () { 
     948                var widget = $(this), 
     949        progressElement = $('#fileupload-progress').fadeIn(), 
     950        interval = 500, 
     951        total = 0, 
     952        loaded = 0, 
     953        loadedBefore = 0, 
     954        progressTimer, 
     955        progressHandler = function (e, data) { 
     956            loaded = data.loaded; 
     957            total = data.total; 
     958        }, 
     959        stopHandler = function () { 
     960            widget 
     961                .unbind('fileuploadprogressall', progressHandler) 
     962                .unbind('fileuploadstop', stopHandler); 
     963            window.clearInterval(progressTimer); 
     964            progressElement.fadeOut(function () { 
     965                progressElement.html(''); 
     966            }); 
     967        }, 
     968        formatTime = function (seconds) { 
     969            var date = new Date(seconds * 1000); 
     970            return ('0' + date.getUTCHours()).slice(-2) + ':' + 
     971                ('0' + date.getUTCMinutes()).slice(-2) + ':' + 
     972                ('0' + date.getUTCSeconds()).slice(-2); 
     973        }, 
     974        formatBytes = function (bytes) { 
     975            if (bytes >= 1000000000) { 
     976                return (bytes / 1000000000).toFixed(2) + ' GB'; 
     977            } 
     978            if (bytes >= 1000000) { 
     979                return (bytes / 1000000).toFixed(2) + ' MB'; 
     980            } 
     981            if (bytes >= 1000) { 
     982                return (bytes / 1000).toFixed(2) + ' KB'; 
     983            } 
     984            return bytes + ' B'; 
     985        }, 
     986        formatPercentage = function (floatValue) { 
     987            return (floatValue * 100).toFixed(2) + ' %'; 
     988        }, 
     989        updateProgressElement = function (loaded, total, bps) { 
     990            progressElement.html( 
     991                formatBytes(bps) + 'ps | ' + 
     992                    formatTime((total - loaded) / bps) + ' | ' + 
     993                    formatPercentage(loaded / total) + ' | ' + 
     994                    formatBytes(loaded) + ' / ' + formatBytes(total) 
     995            ); 
     996        }, 
     997        intervalHandler = function () { 
     998            var diff = loaded - loadedBefore; 
     999            if (!diff) { 
     1000                return; 
     1001            } 
     1002            loadedBefore = loaded; 
     1003            updateProgressElement( 
     1004                loaded, 
     1005                total, 
     1006                diff * (1000 / interval) 
     1007            ); 
     1008        }; 
     1009                widget 
     1010                        .bind('fileuploadprogressall', progressHandler) 
     1011                        .bind('fileuploadstop', stopHandler); 
     1012                progressTimer = window.setInterval(intervalHandler, interval); 
     1013        }); 
     1014                 
     1015        UI.dialogs.addEvent.find(':input').change(function(event){ 
     1016                if (event.keyCode != '27' && event.keyCode != '13') 
     1017                        canDiscardEventDialog = false; 
     1018        }).keydown(function(event){ 
     1019                if (event.keyCode != '27' && event.keyCode != '13') 
     1020                        canDiscardEventDialog = false; 
     1021        });      
     1022                 
    6401023                 
    6411024                UI.dialogs.addEvent.dialog('open'); 
  • trunk/prototype/modules/calendar/templates/alarms_add_itemlist.ejs

    r5376 r5514  
    1717                        <input type="hidden" name="isDefaultAlarm[]" value="<%=data.alarm.useAlarmDefault ? 1 : 0%>" /> 
    1818                        <label> antes de cada evento.</label> 
    19                         <a class="button remove small"></a> 
     19                        <a class="button remove tiny"></a> 
    2020                </li> 
    2121        <%} 
     
    3636                <input type="hidden" name="alarmId[]" value="" /> 
    3737                <label> antes de cada evento.</label> 
    38                 <a class="button remove small"></a> 
     38                <a class="button remove tiny"></a> 
    3939        </li> 
    4040<%}%> 
  • trunk/prototype/modules/calendar/templates/attendee_add.ejs

    r5437 r5514  
     1        <%var iconStatus = ['','ui-icon-check', 'ui-icon-radio-off', 'ui-icon-close', 'ui-icon-help', 'ui-icon-transferthick-e-w', 'ui-icon-contact'] 
     2          var legendStatus = ['','Confirmado','Tentativa','Cancelado','Sem Resposta','Delegado', 'Participante'] 
     3        %> 
    14        <dl class="block-attendee-list attendees-list"> 
    25                <dt class="me"><%= data.event.me.name %></dt> 
    36                <dd class="me"> 
    47                        <select class="status" name="status"> 
    5                                 <option value="1" <%= data.event.status=='1' ? 'selected="selected"':'' %>>Eu vou</option> 
    6                                 <option value="3" <%= data.event.status=='3' ? 'selected="selected"':'' %>>Eu não vou</option> 
    7                                 <option value="2" <%= data.event.status=='2' ? 'selected="selected"':'' %>>Talvez</option> 
    8 <!--                            <option value="another">Outra pessoa vai</option>--> 
     8                                <%if(!data.event.delegatedFrom[data.event.me.id]){%> 
     9                                        <option value="1" <%= data.event.status=='1' ? 'selected="selected"':'' %>>Eu vou</option> 
     10                                        <%if(!data.event.acl.participationRequired){%> 
     11                                                <option value="3" <%= data.event.status=='3' ? 'selected="selected"':'' %>>Eu não vou</option> 
     12                                                <option value="2" <%= data.event.status=='2' ? 'selected="selected"':'' %>>Talvez</option> 
     13                                                <option class="hidden" value="5">Delegado</option> 
     14                                        <%}%> 
     15                                <%}else{%> 
     16                                        <option value="5" 'selected="selected"'>Delegado</option> 
     17                                <%}%> 
    918                        </select> 
    10                         <%if(data.event.organizer.id != data.event.me.id){%> 
    11                             <input type="hidden" name="meId" value="<%=data.event.me.id%>"> 
    12                         <%}%> 
    13                         <fieldset class="add-attendee-search search-field ui-corner-all hidden"> 
    14                                 <span class="ui-icon ui-icon-search"></span> 
    15                                 <input class="search" type="text" /> 
    16                         </fieldset> 
     19                        <% if (!data.event.acl.organization && !data.event.acl.write && !data.event.acl.inviteGuests && !data.event.acl.participationRequired && !data.event.delegatedFrom[data.event.me.id] ) { %> 
     20                                <fieldset class="add-attendee-options-read"> 
     21                                        <a href="#" class="button participant-delegate add-attendee-options-button">Delegar participação a um novo participante</a> 
     22                                </fieldset> 
     23                        <% } %> 
     24                         
     25                        <p class="input-group request-update <%=data.event.delegatedFrom[data.event.me.id] ? '' : "hidden"%>"> 
     26                                <input type="checkbox" name="receiveNotification" value="true" <%=data.event.me.receiveNotification=='1' ? 'checked="checked"' : ''%>/> 
     27                                <label for="request-update">Receber atualizações</label> 
     28                        </p> 
     29                         
     30                        <input type="hidden" name="delegatedFrom[]" value="<%=data.event.me.delegatedFrom%>"> 
     31                 
     32                        <input type="hidden" name="attendee[]" value="<%=data.event.me.id%>"> 
     33                        <input type="hidden" name="attendeeType[]" value="0"> 
     34                        <input type="hidden" name="attendeeAcl[]" value="<%=data.event.me.acl%>">                                
     35                         
    1736                </dd> 
    1837 
     
    2039                <dd class="attendee-list"> 
    2140                        <ul class="attendee-list"> 
    22                                 <li class="organizer <%= data.event.organizer.id == data.event.me.id ? "hidden" : ''%>">  
     41                                <li class="organizer <%= (data.event.acl.organization) ? "hidden" : "" %>">  
    2342                                        <div style="overflow:hidden; width:100%; display:table;"> 
    24                                                 <input type="checkbox" value="<%= data.event.organizer.id %>" disabled="disabled"> 
    25                                                 <input type="hidden" name="attendee[]" value="<%=data.event.organizer.id%>"> 
    26                                                 <input type="hidden" name="attendeeType[]" value="0"> 
    27                                                 <input type="hidden" name="attendee_organizer[]" value="<%=data.event.organizer.id%>"> 
    28                                                 <label for="attendee_organizer" title="<%= data.event.organizer.name ? data.event.organizer.name: '' %>" class="name"><%= data.event.organizer.name ? data.event.organizer.name : '' %></label> 
    29                                                 <label for="attendee_organizer" title="<%= data.event.organizer.mail ? data.event.organizer.mail: '' %>" class="mail"><%= data.event.organizer.mail ? data.event.organizer.mail : '' %></label> 
    30                                                 <% if (data.event.me.id == data.event.organizer.id && false) { %> 
    31                                                 <span class="button small swap">Mudar organizador</span> 
    32                                                 <% } %> 
     43                                                <span class="space-status ui-icon <%=iconStatus[data.event.organizer.status]%>" title="<%=legendStatus[data.event.organizer.status]%>"></span> 
     44                                                <span class="space-special ui-icon ui-icon-person" title="Organizador"></span> 
     45                                                <% if (!data.event.acl.organization && (data.event.organizer.id != data.event.me.id )) { %> 
     46                                                        <input type="checkbox" value="<%= data.event.organizer.id %>" disabled="disabled"> 
     47                                                        <input type="hidden" name="attendee[]" value="<%=data.event.organizer.id%>"> 
     48                                                        <input type="hidden" name="attendeeType[]" value="0"> 
     49                                                        <input type="hidden" name="attendeeAcl[]" value="<%=data.event.organizer.acl%>"> 
     50                                                        <input type="hidden" name="delegatedFrom[]" value="<%=data.event.organizer.delegatedFrom%>"> 
     51                                                <%}%> 
     52                                                <input type="hidden" name="attendee_organizer" value="<%=data.event.organizer.id%>"> 
     53                                                <label for="attendee_organizer" title="<%= data.event.organizer.name ? data.event.organizer.name: '' %>" class="name name-special"><%= data.event.organizer.name ? data.event.organizer.name : '' %></label> 
     54                                                <label for="attendee_organizer" title="<%= data.event.organizer.mail ? data.event.organizer.mail: '' %>" class="mail name-special"><%= data.event.organizer.mail ? data.event.organizer.mail : '' %></label> 
    3355                                        </div> 
    34                                 </li>            
    35                                  
    36                         <% if (data.event && data.event.attendee) { 
    37                                 for (var i=0; i< data.event.attendee.length; i++) { 
    38                         %> 
    39                                 <li class="attendee">  
     56                                </li> 
     57                        <%if(!!data.event.delegatedFrom[data.event.me.id]){ 
     58                                var delegated_me = data.event.delegatedFrom[data.event.me.id]%> 
     59                                <li class="me-delegated"> 
    4060                                        <div style="overflow:hidden; width:100%; display:table;"> 
    41                                                 <input type="checkbox" value="<%= data.event.attendee[i].id %>" disabled="disabled"> 
    42                                                 <input type="hidden" name="attendee[]" value="<%=data.event.attendee[i].id%>"> 
    43                                                 <input type="hidden" name="attendeeType[]" value="<%=data.event.attendee[i].isExternal%>"> 
    44                                                 <label title="<%= data.event.attendee[i].name ? data.event.attendee[i].name: '' %>" class="name"><%= data.event.attendee[i].name ? data.event.attendee[i].name : '' %></label> 
    45                                                 <label title="<%= data.event.attendee[i].mail ? data.event.attendee[i].mail : '' %>" class="mail"><%= data.event.attendee[i].mail ? data.event.attendee[i].mail : '' %></label> 
    46                                                 <span class="ui-icon ui-icon-close ui-corner-all ui-icon-float-right"></span> 
    47                                         </div>  
    48                                         <a class="button close">X</a> 
     61                                                <span class="space-status ui-icon <%=iconStatus[delegated_me.status]%>" title="<%=legendStatus[delegated_me.status]%>"></span> 
     62                                                <span class="space-special ui-icon <%=iconStatus[5]%>" title="Delegado para"></span> 
     63                                                <input type="checkbox" value="<%= delegated_me.id%>" disabled="disabled"> 
     64                                                <label for="me-delegated" title="<%= delegated_me.name ? delegated_me.name: '' %>" class="name name-special"><%= delegated_me.name ? delegated_me.name : '' %></label> 
     65                                                <label for="me-delegated" title="<%= delegated_me.mail ? delegated_me.mail: '' %>" class="mail name-special"><%= delegated_me.mail ? delegated_me.mail : '' %></label> 
     66                                        </div> 
    4967                                </li> 
    50                                  
    51                                  
    52                                  
    53                         <%       
    54                                 }  
    55                         } else { %> 
    56                                 <li>Não há outros participantes.</li> 
     68                        <%}%> 
     69                        <% if (data.event && data.event.attendee.length > 0) { 
     70                                for (var i=0; i< data.event.attendee.length; i++) {%> 
     71                                        <li class="attendee">  
     72                                                <div style="overflow:hidden; width:100%; display:table;"> 
     73                                                        <%if(data.event.delegatedFrom[data.event.attendee[i].id]){%> 
     74                                                                <span class="open-delegate new ui-icon ui-icon-triangle-1-e"></span> 
     75                                                        <%}else{%> 
     76                                                                <span class="space-status ui-icon <%=iconStatus[data.event.attendee[i].status]%>" title="<%=legendStatus[data.event.attendee[i].status]%>"></span> 
     77                                                        <%}%> 
     78                                                        <span class="space-special ui-icon <%= !!data.event.delegatedFrom[data.event.attendee[i].id] ? iconStatus[5] : iconStatus[6]%>" title="<%=!!data.event.delegatedFrom[data.event.attendee[i].id] ? legendStatus[5] : legendStatus[6]%>"></span> 
     79                                                        <%if(data.event.acl.organization || data.event.acl.write){%> 
     80                                                                <input type="checkbox" value="<%= data.event.attendee[i].id %>"> 
     81                                                        <%}else{%> 
     82                                                                <input type="checkbox" value="<%= data.event.attendee[i].id%>" disabled="disabled"> 
     83                                                        <%}%> 
     84                                                        <input type="hidden" name="attendee[]" value="<%=data.event.attendee[i].id%>"> 
     85                                                        <input type="hidden" name="attendeeType[]" value="<%=data.event.attendee[i].isExternal%>"> 
     86                                                        <input type="hidden" name="attendeeAcl[]" value="<%=data.event.attendee[i].acl%>"> 
     87                                                        <input type="hidden" name="delegatedFrom[]" value="<%=data.event.attendee[i].delegatedFrom%>"> 
     88                                                        <label title="<%= data.event.attendee[i].name ? data.event.attendee[i].name: '' %>" class="name <%= !!data.event.delegatedFrom[data.event.attendee[i].id] ? "name-special-delegated" : "name-special" %>"><%= data.event.attendee[i].name ? data.event.attendee[i].name : '' %></label> 
     89                                                        <label title="<%= data.event.attendee[i].mail ? data.event.attendee[i].mail : ''%>" class="mail <%= !!data.event.delegatedFrom[data.event.attendee[i].id] ? "name-special-delegated" : "name-special"%>"><%= data.event.attendee[i].mail ? data.event.attendee[i].mail : '' %></label> 
     90                                                        <span class="ui-icon ui-icon-close ui-corner-all ui-icon-float-right"></span> 
     91                                                </div>  
     92                                                <div class="attendee-options"> 
     93                                                        <%if(data.event.acl.organization || data.event.acl.write){%> 
     94                                                                <a class="button edit attendee-options-button-edit new">Editar permissões</a> 
     95                                                                <a class="button close new">Remover</a> 
     96                                                        <%}%> 
     97                                                </div> 
     98 
     99 
     100                                                <%if(!!data.event.delegatedFrom[data.event.attendee[i].id]){%> 
     101                                                        <%var attendee = data.event.delegatedFrom[data.event.attendee[i].id]%> 
     102                                                        <% while(attendee != 0){%> 
     103                                                                <div class="list-delegates hidden"> 
     104                                                                        <div style="overflow:hidden; width:100%; display:table;"> 
     105                                                                                <span class="status-delegate ui-icon <%=iconStatus[attendee.status]%>" title="<%=legendStatus[attendee.status]%>"></span> 
     106                                                                                <span class="space-special-delegated ui-icon <%= !!data.event.delegatedFrom[attendee.id] ? iconStatus[5] : iconStatus[6]%>" title="<%=!!data.event.delegatedFrom[attendee.id] ? legendStatus[5] : legendStatus[6]%>"></span> 
     107                                                                                <input type="hidden" name="attendee[]" value="<%=attendee.id%>"> 
     108                                                                                <input type="hidden" name="attendeeType[]" value="<%=attendee.isExternal%>"> 
     109                                                                                <input type="hidden" name="attendeeAcl[]" value="<%=attendee.acl%>"> 
     110                                                                                <input type="hidden" name="delegatedFrom[]" value="<%=attendee.delegatedFrom%>"> 
     111                                                                                <label title="<%= attendee.name ? attendee.name : '' %>" class="name <%=attendee.status == 5 ? "name-status-delegated-delegated" : "name-status-delegated-none"%>"><%= attendee.name ? attendee.name : '' %></label> 
     112                                                                                <label title="<%= attendee.mail ? attendee.mail : '' %>" class="mail <%=attendee.status == 5 ? "name-status-delegated-none" : "name-status-delegated-none"%>"><%= attendee.mail ? attendee.mail : '' %></label> 
     113                                                                                <span class="ui-icon ui-icon-close ui-corner-all ui-icon-float-right"></span> 
     114                                                                        </div>  
     115                                                                </div> 
     116                                                                <%attendee = !!data.event.delegatedFrom[attendee.id] ? data.event.delegatedFrom[attendee.id] : 0%> 
     117                                                        <%}%> 
     118                                                <%}%> 
     119                                                 
     120 
     121                                        </li>    
     122                                <%}  
     123                        } else if(data.event.me.id == data.event.organizer.id && !(data.event.attendee.length > 0) ) { %> 
     124                                <li class="not-attendee">Não há outros participantes.</li> 
    57125                        <% } %> 
    58126                        </ul> 
     
    86154                 
    87155        </dl> 
    88 <% if (data.event.isOrganizer == 1) { %> 
    89         <dl class="block-add-attendee"> 
    90                 <dt class="add-attendee">Adicionar convidados</dt> 
    91                 <dd class="add-attendee"> 
    92                         <fieldset class="block-add-attendee" title="Participantes"> 
    93                                 <fieldset class="add-attendee-search search-field ui-corner-all"> 
    94                                         <span class="ui-icon ui-icon-search"></span> 
    95                                         <input class="search" type="text" /> 
    96                                 </fieldset> 
    97                                 <ul class="search-result-list ui-corner-all"> 
     156<% var isSearch = (data.event.acl.organization || data.event.acl.write || data.event.acl.inviteGuests) ? '' : 'hidden' %> 
     157<dl class="block-add-attendee search <%=isSearch%>"> 
     158        <dt class="add-attendee search">Adicionar outros convidados</dt> 
     159        <dd class="add-attendee"> 
     160                <fieldset class="block-add-attendee" title="Participantes"> 
     161                        <fieldset class="add-attendee-search search-field ui-corner-all"> 
     162                                <span class="ui-icon ui-icon-search"></span> 
     163                                <input class="search" type="text" /> 
     164                        </fieldset> 
     165                        <ul class="search-result-list ui-corner-all"> 
    98166 
    99                                 </ul> 
     167                        </ul> 
    100168 
    101                         </fieldset> 
     169                </fieldset> 
     170        </dd> 
     171</dl> 
    102172 
    103                         <fieldset class="block-add-attendee-permissions ui-corner-all hidden"> 
    104                                 <legend>Convidados podem:</legend> 
    105                                 <ul class="add-attendee-permissions-list"> 
    106                                         <li><input type="checkbox" name="attendee-mod-event"><label for="attendee-mod-event">Modificar evento </label></li> 
    107                                         <li><input type="checkbox" name="attendee-invite-others"><label for="attendee-invite-others">Convidar outros</label></li> 
    108                                         <li><input type="checkbox" name="attendee-view-list-invited"><label for="attendee-view-list-invited">Ver lista de convidados</label></li> 
    109                                         <li><input type="checkbox" name="attendee-optional"><label for="attendee-optional">Participação opcional</label></li> 
    110                                 </ul> 
    111                         </fieldset> 
    112                 </dd> 
    113         </dl> 
    114 <% } %> 
  • trunk/prototype/modules/calendar/templates/event_add.ejs

    r5511 r5514  
    1 <!--<div title="Criar Evento" class="new-event-win active"> --> 
    2     <form method="POST" action="<%=((data.event.isOrganizer == 0) && (data.event.id)) ? "schedulable:preview" : "schedulable:detail"%>" class="form-addevent content"> 
     1<div title="Criar Evento" class="div-addevent content"> 
     2    <form method="POST" action="<%=(data.event.acl.organization || data.event.acl.write) ?  "schedulable:detail" : "schedulable:preview"%>" class="form-addevent content"> 
    33 
    44        <fieldset id="calendar_addevent_details1"> 
    55                <legend class="hidden">Detalhes do evento</legend> 
    66                <p class="input-group"> 
    7                         <input type="text" class="h1" name="summary" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> value="<%= (data.event.summary) ? data.event.summary : '' %>"/> 
     7                        <input type="text" class="h1" name="summary" <%=(data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> value="<%= (data.event.summary) ? data.event.summary : '' %>"/> 
    88                        <% if( data.event.id ){ %> 
    99                                <input type="hidden" class="id-event" name="idEvent" value="<%= data.event.id %>"/> 
     
    1111                </p> 
    1212                <p class="input-group date-info"> 
    13                         <input type="text" class="date start-date" value="<%= (data.event.startDate) ? data.event.startDate : '' %>" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> name="startDate" /> 
    14                         <input type="text" class="time start-time<%= (data.event.allDay) ? ' hidden' : '' %>" value="<%= (data.event.startHour) ? data.event.startHour : '' %>" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> name="startHour" />  
     13                        <input type="text" class="date start-date" value="<%= (data.event.startDate) ? data.event.startDate : '' %>" <%=(data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> name="startDate" /> 
     14                        <input type="text" class="time start-time<%= (data.event.allDay) ? ' hidden' : '' %>" value="<%= (data.event.startHour) ? data.event.startHour : '' %>" <%= (data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> name="startHour" />  
    1515                        <span>até</span> 
    16                         <input type="text" class="date end-date" value="<%= (data.event.endDate) ? data.event.endDate : '' %>" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> name="endDate" /> 
    17                         <input type="text" class="time end-time<%= (data.event.allDay) ? ' hidden' : '' %>" value="<%= (data.event.endHour) ? data.event.endHour : '' %>" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> name="endHour" /> 
    18  
    19                         <a href="#" class="calendar_addevent_details_lnk_timezone">Fuso horário</a> 
     16                        <input type="text" class="date end-date" value="<%= (data.event.endDate) ? data.event.endDate : '' %>" <%= (data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> name="endDate" /> 
     17                        <input type="text" class="time end-time<%= (data.event.allDay) ? ' hidden' : '' %>" value="<%= (data.event.endHour) ? data.event.endHour : '' %>" <%=(data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> name="endHour" /> 
     18 
     19                        <a href="#" class="calendar_addevent_details_lnk_timezone <%=((!data.event.acl.organization || !data.event.acl.write) && (data.event.id)) ? "hidden" : '' %>">Fuso horário</a> 
    2020<!--                    <input type="text" name="timezone" style="display: none;" />--> 
    2121                        <select name="timezone" class="hidden calendar-addevent-details-txt-timezone"> 
     
    2525                                <% } %> 
    2626                        </select> 
    27                 </p> 
    28                  
     27                         
     28                        <a class="button suggestion-hours small <%=(data.event.acl.organization || data.event.acl.write) ? "hidden" : '' %>" href="#">Sugerir horário</a> 
     29                         
     30                </p> 
     31                                 
    2932                <div class="ui-widget messages-validation hidden"> 
    3033                        <div style="padding: 0.2em 0.7em;" class="ui-state-error ui-corner-all">  
     
    3740                 
    3841                <p class="input-group event-type"> 
    39                         <input type="checkbox" name="allDay" value="true" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> <%= (data.event.allDay) ? 'checked="checked"' : '' %>/> 
     42                        <input type="checkbox" name="allDay" value="true" <%= (data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> <%= (data.event.allDay) ? 'checked="checked"' : '' %>/> 
    4043                        <label for="allDay">Dia inteiro</label> 
    4144<!-- 
     
    4851<!--            <li><a href="#calendar_addevent_details3">Repetir</a></li>--> 
    4952                <li><a href="#calendar_addevent_details4">Lembretes</a></li> 
    50 <!--            <li><a href="#calendar_addevent_details4" style="color:#BBB;">Anexos</a></li>--> 
     53                <li><a href="#calendar_addevent_details5">Anexos</a></li> 
    5154                <li><a href="#calendar_addevent_details6">Participantes</a></li> 
    5255        </ul> 
     
    5558                <p class="input-group event-info"> 
    5659                        <label for="calendar_addevent_details_txt_local">Onde</label> 
    57                         <input type="text" name="location" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> value="<%= (data.event) ? data.event.location : '' %>"/> 
     60                        <input type="text" name="location" <%=(data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> value="<%= (data.event) ? data.event.location : '' %>"/> 
    5861                </p> 
    5962 
    6063                <p class="input-group"> 
    6164                        <label for="calendar_addevent_details_txtarea_description" class="for-textarea" >Descrição</label> 
    62                         <textarea name="description" <%= (data.event.isOrganizer == 0) ? 'disabled="disabled"' : '' %> ><%=(data.event) ? data.event.description : '' %></textarea> 
     65                        <textarea name="description" <%= (data.event.acl.organization || data.event.acl.write) ? '' : 'disabled="disabled"' %> ><%=(data.event) ? data.event.description : '' %></textarea> 
    6366                </p> 
    6467 
     
    144147        <fieldset id="calendar_addevent_details6" class="tab-level2" title="Participantes"> 
    145148        </fieldset> 
     149         
     150         
     151        <fieldset class="attachment-list hidden"> 
     152        </fieldset> 
    146153    </form> 
    147     <form action="../../../../upload.php" method="POST">         
    148 <!-- 
     154     
     155 
    149156        <fieldset id="calendar_addevent_details5" class="tab-level2"> 
    150                 <span class="input_label">Anexos</span>  
    151                   <ul class="attachments-list"> 
    152                         <% if (data.event && data.event.attachments) { 
    153                                 for (var i=0; i< data.event.attachments.length; i++) { 
    154                         %> 
    155                                 <li> 
    156                                         <a href="<%= data.event.attachments[i].src %>" > 
    157                                                 <input type="checkbox" name="attachments['<%= data.event.attachments[i].name %>']" checked="checked" /> 
    158                                                 <label for="calendar_addevent_details_attach_<%=i%>"><%= data.event.attachments[i].name %></label> 
    159                                         </a> 
    160                                 </li> 
    161                         <%      } 
    162                            } 
    163                         %> 
    164  
    165                   </ul> 
    166                 <span class="button add button-add-attachment">Adicionar anexo</span> 
    167          
    168                 <div id="fileupload"> 
    169                         <div title="form:upload.php"> 
    170                                 <div class="fileupload-buttonbar"> 
    171                                         <label class="fileinput-button"> 
    172                                                 <span>Add files...</span> 
    173                                                 <input type="file" name="files[]" multiple> 
    174                                         </label> 
    175                                         <button type="submit" class="start">Start upload</button> 
    176                                         <button type="reset"  class="cancel">Cancel upload</button> 
    177                                         <button type="button" class="delete">Delete files</button> 
    178                                 </div> 
    179                         </div> 
    180                         <div class="fileupload-content"> 
    181                                 <table class="files"></table> 
    182                                 <div class="fileupload-progressbar"></div> 
    183                         </div> 
    184                 </div> 
     157                <form id="fileupload" action="attachment:detail" method="POST"> 
     158        <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> 
     159        <div class="row fileupload-buttonbar"> 
     160            <div class="button-files-upload"> 
     161                <!-- The fileinput-button span is used to style the file input field as button --> 
     162                <span class="button btn-success fileinput-button"> 
     163                    <span><i class="icon-plus icon-white"></i> Adicionar</span> 
     164                    <input type="file" name="files[]" multiple> 
     165                </span> 
     166                                <%if(data.event.acl.organization || data.event.acl.write){%> 
     167                                        <button type="button" class="button btn-danger delete"> 
     168                                                <i class="icon-trash icon-white"></i> Remover Todos 
     169                                        </button> 
     170                                <%}%> 
     171            </div> 
     172                        <div id="fileupload-progress"></div> 
     173            <div class="files-list"> 
     174               <ul class="attachments-list"> 
     175                           <%if(data.event && data.event.attachments){ 
     176                                        for (var i=0; i< data.event.attachments.length; i++) { 
     177                                        %> 
     178                                                <p class="input-group arquive-info"> 
     179                                                        <label class="lbl-archive-nome">Nome:</label> 
     180                                                        <span class="archive-nome"><%=data.event.attachments[i].name%></span> 
     181                                                         
     182                                                        <label class="lbl-archive-size">Tamanho:</label> 
     183                                                        <span class="archive-size"><%=data.event.attachments[i].size%> kb</span> 
     184                                                        <a href="../prototype/getArchive.php?attachment=<%=data.event.attachments[i].id%>" class="button tiny upload downlaod-archive">Download</a> 
     185                                                        <%if(data.event.acl.organization || data.event.acl.write){%> 
     186                                                                <span class="button close tiny upload delete-upload" title="Deletar">Deletar</span> 
     187                                                        <%}%> 
     188                                                        <input type="hidden" name="fileId[]" value="<%=data.event.attachments[i].id%>"/> 
     189                                                </p> 
     190                                        <%} 
     191                                }%> 
     192                            
     193                            
     194                           </ul> 
     195            </div> 
     196        </div> 
     197        <br> 
     198         
     199    </form> 
     200 
     201        </fieldset> 
    185202 
    186203        </fieldset> 
     
    194211    <div class="menu-container footer-container menu-addevent"> 
    195212            <% if (data.event.id) { %> 
    196                 <a class="button export" href="#">Exportar</a> 
    197             <a class="button delete" href="#">Excluir</a> 
     213                        <a class="button export" href="#">Exportar</a> 
     214                        <a class="button delete" href="#">Excluir</a> 
    198215            <% } %> 
    199216                <a class="button cancel" href="#">Cancelar</a> 
    200217            <a class="button save" href="#">Salvar</a> 
    201218    </div> 
    202 <!--</div>--> 
     219</div> 
    203220<!--<script src="application.js"></script>--> 
     221<!--<script src="application.js"></script>--> 
  • trunk/prototype/modules/calendar/templates/index.ejs

    r5468 r5514  
    4040<script type='text/javascript' src='<?= PLUGINSURL ?>/store/jquery.store.js'></script> 
    4141<script type='text/javascript' src='<?= PLUGINSURL ?>/fileupload/jquery.fileupload.js'></script> 
    42 <script type='text/javascript' src='<?= PLUGINSURL ?>/fileupload/jquery.fileupload-ui.js'></script> 
     42<!--<script type='text/javascript' src='<?= PLUGINSURL ?>/fileupload/jquery.fileupload-ui.js'></script>--> 
    4343<script type='text/javascript' src='<?= PLUGINSURL ?>/fileupload/jquery.iframe-transport.js'></script> 
    4444<script type='text/javascript' src='<?= PLUGINSURL ?>/store/jquery.store.js'></script> 
  • trunk/prototype/modules/calendar/templates/participants_add_itemlist.ejs

    r5360 r5514  
    11<li class="attendee">  
    22        <div style="overflow:hidden; width:100%; display:table;"> 
    3                 <input type="checkbox" value="<%= data[0].id %>" disabled="disabled"> 
     3                <div class="attendee-options"> 
     4                        <%if(data[0].acl.organization || data[0].acl.write || data[0].acl.inviteGuests){%> 
     5                                <a href="#" class="button delegate attendee-options-button-delegate new">Delegar participação a este participante</a> 
     6                        <%}%> 
     7                        <%if(data[0].acl.organization || data[0].acl.write){%> 
     8                                <a class="button edit attendee-options-button-edit new">Editar permissões</a> 
     9                        <%}%> 
     10                        <a class="button close new">Close</a> 
     11                </div> 
     12                 
     13                <input class="new" type="checkbox" value="<%= data[0].id %>"> 
    414                <input type="hidden" name="attendee[]" value="<%= data[0].id %>"> 
    515                <input type="hidden" name="attendeeType[]" value="<%=data[0].isExternal%>"> 
     16                <input type="hidden" name="attendeeAcl[]" value="r"> 
     17                <input type="hidden" name="delegatedFrom[]" value="0"> 
    618                <label title="<%= data[0].name ? data[0].name : '' %>" class="name"><%= data[0].name ? data[0].name : '' %></label> 
    7                 <label title="<%= data[0].mail ? data[0].mail : '' %>" class="mail"><%= data[0].mail ? data[0].mail : '' %></label> 
    8         </div>  
    9         <a class="button close">Close</a> 
     19                <label title="<%= data[0].mail ? data[0].mail : '' %>" class="mail <%= data[0].name ? 'hidden' : ''%>"><%= data[0].mail ? data[0].mail : '' %></label> 
     20 
     21        </div> 
     22         
    1023</li> 
  • trunk/prototype/post.php

    r5399 r5514  
    11<?php 
    2  
    3 if( !isset($_REQUEST['data']) ) return; 
    4  
    5 $data = $_REQUEST['data']; unset( $_REQUEST['data'] ); 
     2/* Upload de arquivos e encaminhado para seu respectivo conceito 
     3 * com o source em base64 melhoria na performace. 
     4 */ 
     5$data = $_POST; 
     6if( count($_FILES) ) 
     7{ 
     8        $files = array(); 
     9        foreach( $_FILES as $name => $file ) 
     10        { 
     11                if( is_array( $file['name'] ) ) 
     12                { 
     13                        foreach( $file['name'] as $key => $value ){ 
     14                                $counter = count($files); 
     15                                $files[$name.$counter] = array('name' => $file['name'][$counter],  
     16                                                                                                'type' => $file['type'][$counter], 
     17                                                                                                'source' => base64_encode(file_get_contents( $file['tmp_name'][$counter], $file['size'][$counter])), 
     18                                                                                                'size' => $file['size'][$counter]); 
     19                        } 
     20                }else 
     21                        $files[$name] = $file; 
     22        }  
     23         
     24        $_FILES = $files; 
     25} 
    626 
    727require_once "api/controller.php"; 
    828 
    9 echo json_encode( Controller::put( $_REQUEST, $data ) ); 
     29$result = array(); 
     30foreach( $data as $concept => &$content ) 
     31{ 
     32        if(!is_array($content)) 
     33                $content = array($content); 
     34                 
     35        foreach($content as $key => $value) 
     36                $result[$concept][] = Controller::put( array( 'concept' => $concept ), $value, isset($data['criteria']) ? $data['criteria'] : false ); 
     37}        
     38echo json_encode( $result ); 
  • trunk/prototype/services/PostgreSQL.php

    r5441 r5514  
    210210            if( isset($criteria["order"]) ) 
    211211            { 
    212                     $result .= ' ORDER BY '.( is_array($criteria["order"]) ? implode(', ', $criteria["order"]) : $criteria["order"] ).' '; 
     212                    $result .= ' ORDER BY '.self::parseOrder( $criteria["order"], $map ).' '; 
    213213            } 
    214214            if( isset($criteria["limit"]) ) 
     
    300300        return $return;   
    301301    } 
    302     
     302 
     303   private static function parseOrder($order , &$map) 
     304    { 
     305                   
     306        if($notArray = !is_array($order)) //Caso seja um full select pegar todas as keys 
     307            $order = array( $order ); 
     308 
     309        $return = array(); 
     310 
     311        foreach ($order as &$value)  
     312        { 
     313            if(!isset($map[$value])) continue; //Escapa itens não existentes no mapa 
     314 
     315            $value = $map[$value]; 
     316        } 
     317 
     318        return ( $notArray ?  $order[0] : implode(', ', $order) ); 
     319    } 
    303320} 
    304321 
  • trunk/prototype/services/iCal.php

    r5481 r5514  
    1414 
    1515    public function format ($data , $params = false) 
    16     { 
     16    {            
    1717        $timezones = array_flip(self::$timezonesMap); 
    1818            
     
    6363                           $vevent->setProperty( 'X-MICROSOFT-CDO-ALLDAYEVENT', 'FALSE' ); 
    6464                       } 
    65                         
    66                        if(isset($v['participants']) && is_array($v['participants']) && count($v['participants']) > 0 ) 
    67                            foreach ($v['participants'] as $pi => $pv) 
    68                            { 
    69                                 if($pv['isOrganizer'] == 1) 
    70                                    $vevent->setProperty( 'organizer' , $pv['user']['mail'], array( 'CN' => $pv['user']['name'] ));   
    71                                 else 
    72                                 { 
    73                                     $pParams = array(); 
    74                                     $pParams['CN'] = $pv['user']['name']; 
    75                                     $pParams['PARTSTAT'] = self::_getStatus( $pv['status'] ); 
    76                                     $pParams['RSVP'] = 'TRUE'; 
    77  
    78  
    79                                     //TODO: Implementar o delegated 
    80                                     $vevent->setProperty( 'attendee' , $pv['user']['mail'], $pParams);   
    81                                 } 
    82  
    83                            } 
    84  
     65 
     66                                                if(isset($v['participants']) && is_array($v['participants']) && count($v['participants']) > 0 ) 
     67                                                        $this->createAttendee($v['participants'], $vevent); 
     68 
     69                                                if(isset($v['attachments']) && is_array($v['attachments']) && count($v['attachments']) > 0 ) 
     70                                                        $this->createAttachment($v['attachments'], $vevent); 
     71                                                         
    8572                        $vevent->setProperty( 'uid' , $v['uid'] ); 
    86                         
     73 
    8774                       //Todo: Implementar Repetição 
    8875                                            
     
    9178                default: 
    9279                    break; 
    93             }  
    94              
    95            
     80            }            
    9681        } 
    9782                         
     
    9984     
    10085    } 
     86        //Trata a criacao de anexos do ics 
     87        public function createAttachment($attachments, &$vevent){ 
     88                foreach($attachments as $key => $attachment){ 
     89                        $pParams = array("ENCODING" => "BASE64", "VALUE" => "BINARY", 
     90                                                        "X-FILENAME"  => $attachment['name']); 
     91                 
     92                        $vevent->setProperty( "attach", $attachment['source'], $pParams ); 
     93                } 
     94        } 
     95         
     96        //Trata a criacao de attendees com tratamento de delegate 
     97        public function createAttendee($attendees, &$vevent){ 
     98                $delegate = array(); 
     99                foreach ($attendees as $di => $dv){ 
     100                        if($dv['delegatedFrom'] != 0){ 
     101                                $delegate[$dv['delegatedFrom']] = $dv; 
     102                        } 
     103                } 
     104 
     105                foreach ($attendees as $pi => $pv){ 
     106                        $isResponseDelegated = false; 
     107                        if($pv['delegatedFrom'] == 0){ 
     108                                if($pv['isOrganizer'] == 1) 
     109                                   $vevent->setProperty( 'organizer' , $pv['user']['mail'], array( 'CN' => $pv['user']['name'] ));   
     110                                else 
     111                                { 
     112                                        $pParams = array(); 
     113                                        $pParams['CN'] = $pv['user']['name']; 
     114                                        $pParams['PARTSTAT'] = self::_getStatus( $pv['status'] ); 
     115                                         
     116                                        if(isset($delegate[$pv['id']])){ 
     117                                                        $pParams['PARTSTAT'] = self::_getStatus( $delegate[$pv['id']]['status']); 
     118                                                        $pParams['DELEGATED-TO'] = $delegate[$pv['id']]['user']['mail']; 
     119                                                        $pParams['CN'] = $pv['user']['name']; 
     120                                                         
     121                                                        $vevent->setProperty( 'attendee' , $pv['user']['mail'], $pParams);   
     122                                                         
     123                                                        if($delegate[$pv['id']]['status'] == STATUS_UNANSWERED){ 
     124                                                                $pParams['RSVP'] = $pv['receiveNotification'] == 1 ? 'TRUE' : 'FALSE'; 
     125                                                                unset($pParams['PARTSTAT']); 
     126                                                        }else 
     127                                                                $pParams['PARTSTAT'] = self::_getStatus( $delegate[$pv['id']]['status']); 
     128                                                         
     129                                                        unset($pParams['DELEGATED-TO']); 
     130                                                        $pParams['DELEGATED-FROM'] = $pv['user']['mail']; 
     131                                                         
     132                                                        $vevent->setProperty( 'attendee' , $delegate[$pv['id']]['user']['mail'], $pParams);   
     133                                                        continue; 
     134                                        } 
     135                                        $pParams['RSVP'] = 'TRUE'; 
     136                                                 
     137                                        $vevent->setProperty( 'attendee' , $pv['user']['mail'], $pParams);   
     138                                }                        
     139                        } 
     140                }        
     141        } 
    101142       
    102      public function parse ( $data , $params = false) 
     143    public function parse ( $data , $params = false) 
    103144    { 
    104145        Config::regSet('noAlarm', TRUE); //Evita o envio de notificação 
     
    110151        $method = $vcalendar->getProperty('method',FALSE , FALSE); 
    111152        $params['prodid'] =  $vcalendar->getProperty( 'prodid' , false , false ); 
    112          
     153                 
    113154        while ($component = $vcalendar->getComponent()) 
    114155        {      
     
    183224                          
    184225                         case 'COUNTER': 
     226                                                        if($params['acceptedSuggestion'] !== 'false' ){ 
     227                                                         
     228                                                                $schedulable = self::_getSchedulable($uid); 
     229                                                                $params['calendar'] = self::_existInMyCalendars($schedulable['id']); 
     230                                                                 
     231                                $interation = self::_makeCOUNTER($schedulable , $component , $params);   
     232                                                                Config::regSet('noAlarm', FALSE);                                        
     233                                                        }else{ 
     234                                                                $response = array(); 
     235                                                                $response['from'] = $params['from']; 
     236                                                                $response['type'] = 'suggestionResponse'; 
     237                                                                $response['status'] = 'DECLINECOUNTER'; 
     238                                                                $response['schedulable'] = self::_getSchedulable($uid); 
     239                                                                 
     240                                                                Controller::create( array( 'concept' => 'notification' ) , $response);  
     241                                                        } 
    185242                               break; 
    186243                          
    187                          case 'DECLINE-COUNTER': 
     244                         case 'DECLINECOUNTER': 
    188245                               break; 
    189246                            
     
    194251                                $interation = self::_makeVEVENT($schedulable , $component , $params); 
    195252                             else // Importar evento 
    196                                  $interation = self::_makeVEVENT( array() , $component , $params); 
     253                                $interation = self::_makeVEVENT( array() , $component , $params); 
    197254 
    198255                             break; 
     
    214271        public function analize ( $data , $params = false) 
    215272        { 
    216             $vcalendar = new icalCreator( );  
     273                        $vcalendar = new icalCreator( );  
    217274            $vcalendar->parse(trim($data));  
    218275            $vcalendar->sort();          
     
    223280            while ($component = $vcalendar->getComponent()) 
    224281            {      
    225                 $interation = array(); 
     282                $interation = array(); 
    226283                $uid = $component->getProperty( 'uid' , false , false ); //Resgata o uid do componente 
    227284 
     
    269326 
    270327                             case 'COUNTER': 
     328                                                                        $interation = ICAL_ACTION_SUGGESTION; 
    271329                                   break; 
    272330 
    273                              case 'DECLINE-COUNTER': 
    274                                    break; 
     331                             case 'DECLINECOUNTER': 
     332                                   $interation = ICAL_ACTION_NONE; 
     333                                                                   break; 
    275334 
    276335                             default: 
     
    322381                        STATUS_CONFIRMED =>  'CONFIRMED', 
    323382                        STATUS_CANCELLED =>  'CANCELLED', 
    324                         STATUS_TENATIVE =>   'TENATIVE', 
     383                        STATUS_TENTATIVE =>   'TENTATIVE', 
    325384                        STATUS_UNANSWERED => 'NEEDS-ACTION', 
    326385                        STATUS_DELEGATED =>  'DELEGATED' 
     
    367426        } 
    368427 
    369         static private function _makeVEVENT( $schedulable , $component ,$params) 
    370         { 
    371             $interation = array();                   
     428                static private function _makeCOUNTER( $schedulable , $component ,$params) 
     429        { 
     430                        $interation = array();                   
    372431            $eventID = isset($schedulable['id']) ? $schedulable['id'] : mt_rand().'(Formatter)'; 
    373432             
    374433            /* Data de Inicio*/ 
    375434                $startTime = $component->getProperty( 'dtstart', false , true ); 
    376           
    377                     
     435                                 
    378436            /* Tiem zone do evento*/     
    379437               if(isset($startTime['params']['TZID'])) 
     
    389447                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC',$schedulable['timezone']) . '000'; 
    390448                } 
    391                 elseif(isset($startTime['params']['TZID']) && !isset($startTime['value']['tz']))/* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */ 
     449                elseif(isset($startTime['params']['TZID']) && !isset($startTime['value']['tz'])){/* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */ 
    392450                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC',$startTime['params']['TZID']) . '000';       
     451                                        $schedulable['allDay'] = 0; 
     452                                } 
     453                                else 
     454                { 
     455                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) . '000'; 
     456                     if( strpos($params['prodid'], 'Outlook') !== false ) 
     457                    { 
     458                        //Se o ics veio em utc não aplicar horario de verão 
     459                        $sTime = new DateTime( '@'.(int)($schedulable['startTime'] / 1000) , new DateTimeZone('UTC') );  
     460                        $sTime->setTimezone($objTimezone); 
     461                        if($sTime->format('I')) //Se o ics veio em utc não aplicar horario de verão 
     462                         $schedulable['startTime'] = $schedulable['startTime'] - 3600000; 
     463                    } 
     464                } 
     465                 
     466 
     467             /* Data de Termino*/ 
     468                $endTime = $component->getProperty( 'dtend', false , true );  
     469 
     470                if($endTime['params']['VALUE'] === 'DATE') 
     471                    $schedulable['endTime'] = self::date2timestamp($endTime['value']) - self::_getTzOffset('UTC',$schedulable['timezone']) . '000'; 
     472                else if(isset($endTime['params']['TZID']) && !isset($endTime['value']['tz'])) /* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */ 
     473                    $schedulable['endTime'] = self::date2timestamp($endTime['value']) - self::_getTzOffset('UTC',$endTime['params']['TZID']) . '000'; 
    393474                else 
     475                { 
     476                    $schedulable['endTime'] = self::date2timestamp($endTime['value']) . '000'; 
     477                    if( strpos($params['prodid'], 'Outlook') !== false ) 
     478                    { 
     479                    //Se o ics veio em utc não aplicar horario de verão 
     480                        $eTime = new DateTime( '@'.(int)($schedulable['endTime'] / 1000)  ,new DateTimeZone('UTC'));  
     481                        $eTime->setTimezone($objTimezone); 
     482                        if($eTime->format('I'))  
     483                            $schedulable['endTime'] = $schedulable['endTime'] - 3600000; 
     484                    
     485                                        } 
     486                                } 
     487                        unset($schedulable['participants']);                     
     488                        $interation['schedulable://'.$eventID] = $schedulable; 
     489                          
     490            return $interation; 
     491                } 
     492                 
     493        static private function _makeVEVENT( $schedulable , $component ,$params) 
     494        { 
     495                         
     496            $interation = array();                   
     497            $eventID = isset($schedulable['id']) ? $schedulable['id'] : mt_rand().'(Formatter)'; 
     498             
     499            /* Data de Inicio*/ 
     500                $startTime = $component->getProperty( 'dtstart', false , true ); 
     501                                 
     502            /* Tiem zone do evento*/     
     503               if(isset($startTime['params']['TZID'])) 
     504                  $schedulable['timezone'] = self::nomalizeTZID ($startTime['params']['TZID']);  
     505               else 
     506                  $schedulable['timezone'] = isset($params['calendar_timezone']) ? $params['calendar_timezone'] : 'America/Sao_Paulo';  
     507                
     508                $objTimezone =  new DateTimeZone($schedulable['timezone']);   
     509                 
     510                if($startTime['params']['VALUE'] === 'DATE' && isset($params['calendar_timezone']) ) 
     511                { 
     512                    $schedulable['allDay'] = 1; 
     513                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC',$schedulable['timezone']) . '000'; 
     514                } 
     515                elseif(isset($startTime['params']['TZID']) && !isset($startTime['value']['tz'])){/* Caso não tenha um tz na data mais exista um parametro TZID deve ser aplicado o timezone do TZID a data */ 
     516                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) - self::_getTzOffset('UTC',$startTime['params']['TZID']) . '000';       
     517                                        $schedulable['allDay'] = 0; 
     518                                } 
     519                                else 
    394520                { 
    395521                    $schedulable['startTime'] = self::date2timestamp($startTime['value']) . '000'; 
     
    519645                $participant['status'] = (isset($property['params']['PARTSTAT']) && constant('STATUS_'.$property['params']['PARTSTAT']) !== null ) ? constant('STATUS_'.$property['params']['PARTSTAT']) : STATUS_UNANSWERED; 
    520646                $participant['isOrganizer'] = '1'; 
     647                                $participant['acl'] = 'rowi'; 
    521648 
    522649                /* Verifica se este usuario é um usuario interno do ldap */      
     
    558685                    $participant['status'] = STATUS_CONFIRMED; 
    559686                    $participant['isOrganizer'] = '1'; 
     687                    $participant['acl'] = 'rowi'; 
    560688                    $participant['isExternal']  = 0; 
    561689                    $participant['user'] =  $params['owner']; 
     
    583711            if($uid = $component->getProperty( 'uid' , false , false )); 
    584712                  $schedulable['uid'] = $uid; 
    585                  
    586              $interation['schedulable://'.$eventID] = $schedulable; 
    587                           
    588              return $interation; 
     713 
     714                         while($attach = $component->getProperty('ATTACH',FALSE , TRUE)){ 
     715 
     716                                $attachCurrent = array( 'name' => $attach['params']['X-FILENAME'], 
     717                                                                'size' => strlen($attach['value']), 
     718                                                                'type' => self::_getContentType($attach['params']['X-FILENAME']) 
     719                                                        ); 
     720 
     721                                $ids = Controller::find( array( 'concept' => 'attachment' ) , array('id') ,array( 'filter' => array('AND' , array( '=' , 'name' ,  $attachCurrent['name'] ), array( '=' , 'size' , $attachCurrent['size'] ), array( '=' , 'type' , $attachCurrent['type'] ))));  
     722 
     723                                if(!is_array($ids)){ 
     724                                        $attachCurrent['source'] = $attach['value']; 
     725                                        //insere o anexo no banco e pega id para colcar no relacionamento                                
     726                                        $idAttachment =  Controller::create( array('concept' => 'attachment') , $attachCurrent ); 
     727                                }else 
     728                                        $idAttachment = array('id' => $ids[0]['id']); 
     729                                 
     730                                $calendarToAttachmentId = mt_rand().'2(Formatter)'; 
     731                                $calendarToAttachment['attachment'] = $idAttachment['id'] ; 
     732                                $calendarToAttachment['schedulable'] = $eventID ; 
     733                                $interation['schedulableToAttachment://'.$calendarToAttachmentId] = $calendarToAttachment; 
     734                                 
     735                                $schedulable['attachments'][] = $calendarToAttachmentId; 
     736 
     737                        } 
     738 
     739                        $interation['schedulable://'.$eventID] = $schedulable; 
     740 
     741            return $interation; 
    589742        } 
    590743         
     
    603756            
    604757           $return =  Controller::find( array( 'concept' => 'calendarToSchedulable' ) , null , array ( 'filter' => array('AND' , array( 'IN' , 'calendar' , $calendars ),array( '=' , 'schedulable' , $id )))); 
    605             
    606            return (isset($return[0])) ? true : false; 
     758 
     759           return (isset($return[0])) ? $return[0]['calendar'] : false; 
    607760        } 
    608761         
     
    614767           return false; 
    615768        } 
     769                 
     770                 
     771                 static private function _getContentType( $fileName ) 
     772        { 
     773            $strFileType = strtolower(substr ( $fileName , strrpos($fileName, '.') )); 
     774                          
     775                        switch( $strFileType ) 
     776                        { 
     777                                case ".asf": return "video/x-ms-asf"; 
     778                                case ".avi": return "video/avi"; 
     779                                case ".doc": return "application/msword"; 
     780                                case ".zip": return "application/zip"; 
     781                                case ".xls": return "application/vnd.ms-excel"; 
     782                                case ".gif": return "image/gif"; 
     783                                case ".bmp": return "image/bmp"; 
     784                                case ".jpeg": 
     785                                case ".jpg": return "image/jpeg"; 
     786                                case ".wav": return "audio/wav"; 
     787                                case ".mp3": return "audio/mpeg3"; 
     788                                case ".mpeg": 
     789                                case ".mpg": return "video/mpeg"; 
     790                                case ".rtf": return "application/rtf"; 
     791                                case ".html": 
     792                                case ".htm": return "text/html"; 
     793                                case ".xml": return "text/xml"; 
     794                                case ".xsl": return "text/xsl"; 
     795                                case ".css": return "text/css"; 
     796                                case ".php": return "text/php"; 
     797                                case ".asp": return "text/asp"; 
     798                                case ".pdf": return "application/pdf"; 
     799                                case ".png": return "image/png"; 
     800                                case ".txt": return "text/plain"; 
     801                                case ".log": return "text/plain"; 
     802                                case ".wmv": return "video/x-ms-wmv"; 
     803                                case ".sxc": return "application/vnd.sun.xml.calc"; 
     804                                case ".odt": return "application/vnd.oasis.opendocument.text"; 
     805                                case ".stc": return "application/vnd.sun.xml.calc.template"; 
     806                                case ".sxd": return "application/vnd.sun.xml.draw"; 
     807                                case ".std": return "application/vnd.sun.xml.draw.template"; 
     808                                case ".sxi": return "application/vnd.sun.xml.impress"; 
     809                                case ".sti": return "application/vnd.sun.xml.impress.template"; 
     810                                case ".sxm": return "application/vnd.sun.xml.math"; 
     811                                case ".sxw": return "application/vnd.sun.xml.writer"; 
     812                                case ".sxq": return "application/vnd.sun.xml.writer.global"; 
     813                                case ".stw": return "application/vnd.sun.xml.writer.template"; 
     814                                case ".pps": return "application/vnd.ms-powerpoint"; 
     815                                case ".odt": return "application/vnd.oasis.opendocument.text"; 
     816                                case ".ott": return "application/vnd.oasis.opendocument.text-template"; 
     817                                case ".oth": return "application/vnd.oasis.opendocument.text-web"; 
     818                                case ".odm": return "application/vnd.oasis.opendocument.text-master"; 
     819                                case ".odg": return "application/vnd.oasis.opendocument.graphics"; 
     820                                case ".otg": return "application/vnd.oasis.opendocument.graphics-template"; 
     821                                case ".odp": return "application/vnd.oasis.opendocument.presentation"; 
     822                                case ".otp": return "application/vnd.oasis.opendocument.presentation-template"; 
     823                                case ".ods": return "application/vnd.oasis.opendocument.spreadsheet"; 
     824                                case ".ots": return "application/vnd.oasis.opendocument.spreadsheet-template"; 
     825                                case ".odc": return "application/vnd.oasis.opendocument.chart"; 
     826                                case ".odf": return "application/vnd.oasis.opendocument.formula"; 
     827                                case ".odi": return "application/vnd.oasis.opendocument.image"; 
     828                                case ".ndl": return "application/vnd.lotus-notes"; 
     829                                case ".eml": return "text/plain"; 
     830                                case ".ps" : return "application/postscript"; 
     831                                default    : return "application/octet-stream"; 
     832                        } 
     833        }                
    616834} 
    617835?> 
Note: See TracChangeset for help on using the changeset viewer.