diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/comm/action/class/actionagenda.class.php dolibarr-svn/htdocs/comm/action/class/actionagenda.class.php --- dolibarr-snapshot/htdocs/comm/action/class/actionagenda.class.php 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/comm/action/class/actionagenda.class.php 2011-04-14 13:44:07.000000000 +0200 @@ -0,0 +1,877 @@ + + * Copyright (C) 2004-2008 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/comm/action/class/actioncomm.class.php + * \ingroup commercial + * \brief File of class to manage agenda events (actions) + * \version $Id: actioncomm.class.php,v 1.21.2.1 2011/01/26 22:33:14 eldy Exp $ + */ +require_once(DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php'); +require_once(DOL_DOCUMENT_ROOT.'/core/class/commonAgenda.class.php'); +require_once(DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'); +require_once(DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'); + + +/** \class ActionComm + * \brief Class to manage agenda events (actions) + */ +class ActionAgenda extends CommonAgenda +{ + var $db; + + var $offset = 3600; + var $summertime = 1; + + /** + * \brief Constructeur + * \param db Handler d'acces base de donnee + */ + function ActionAgenda($db) + { + $this->db = $db; + } + + + /** + * Format Actions into events array + * @param format 'vcal', 'ical/ics', 'rss' + * @param type 'event' or 'journal' + * @param cachedelay Do not rebuild file if date older than cachedelay seconds + * @param filename Force filename + * @param filters Array of filters + * @return array empty array if error + */ + function getEvent($id,$options= array()){ + global $conf,$langs,$dolibarr_main_url_root,$mysoc,$user; + + $actionComm = new ActionComm($this->db); + $showbirthday = (isset($options['showbirthday'])) ? $options['showbirthday'] : null; + $status = (isset($options['status'])) ? $options['status'] : null; + $filtera = (isset($options['userasked'])) ? $options['userasked'] : -1; + $filtert = (isset($options['usertodo'])) ? $options['usertodo'] : -1; + $filterd = (isset($options['userdone'])) ? $options['userdone'] : -1; + $pid = (isset($options['projectid'])) ? $options['projectid'] : 0; + + + $data = array(); + + //Setting dates + $start = date('Y-m-d H:i:s',substr($start,0,10)); + $end = date('Y-m-d H:i:s',substr($end,0,10)); + + $sql = ' SELECT a.id,a.label,'; + $sql.= ' concat(unix_timestamp(datep)) as datep, + concat(unix_timestamp(datep2)) as datep2, + concat(unix_timestamp(datea)) as datea, + concat(unix_timestamp(datea2)) as datea2,'; + $sql.= ' a.percent,'; + $sql.= ' a.fk_user_author,a.fk_user_action,a.fk_user_done,'; + $sql.= ' a.priority, a.fulldayevent, a.location,'; + $sql.= ' a.fk_soc, a.fk_contact,'; + $sql.= ' ca.code'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a'; + $sql.= ', '.MAIN_DB_PREFIX.'c_actioncomm as ca'; + $sql.= ', '.MAIN_DB_PREFIX.'user as u'; + $sql.= ' WHERE a.fk_action = ca.id'; + $sql.= ' AND a.fk_user_author = u.rowid'; + $sql.= " AND a.id = {$id}"; + + $resql = $this->db->query($sql); + $obj = $this->db->fetch_object($resql); + + $i= 0; + $data[$i]['eventid'] = $obj->id; + + + $data[$i]['readonly'] = 0; + $data[$i]['draggable'] = 1; + $data[$i]['resizable'] = 1; + $data[$i]['multiday'] = 0; + + $data[$i]['eventstart'] = $obj->datep; + $data[$i]['eventend'] = $obj->datep2; + $data[$i]['eventmessage'] = $obj->note; + + $data[$i]['color'] = "#666677"; + + //Formating the title + $langs->load("companies"); + $langs->load("commercial"); + $langs->load("other"); + + $actionComm->fetch($obj->id); + + + + $title = ""; + $data[$i]['type'] = $actionComm->type; + + + //Getting company name for title + + $langs->load('companies'); + if($actionComm->societe->id): + $company = new Societe($actionComm->db); + $company->fetch($actionComm->societe->id); + + $actionComm->societe = $company; + $data[$i]['company'] = "
{$actionComm->societe->getNomUrl(0)}
"; + else: + $data[$i]['company'] = ""; + endif; + + //Getting contact name for title + + if($actionComm->contact->id): + $contact = new Contact($actionComm->db); + $contact->fetch($actionComm->contact->id,$user); + $actionComm->contact = $contact; + $data[$i]['contact'] = "
{$actionComm->contact->getNomUrl(0)}
"; + if ($actionComm->contact->id && $actionComm->type_code == 'AC_TEL'): + + $data[$i]['extraInfo'] = "(".dol_print_phone($actionComm->contact->phone_pro).")"; + endif; + else: + $data[$i]['contact'] = ''; + $data[$i]['extraInfo'] = ''; + endif; + + + + //Getting Project name for title + if ($conf->projet->enabled) + { + if ($actionComm->fk_project) + { + $project=new Project($actionComm->db); + $project->fetch($actionComm->fk_project); + $data[$i]['project'] = $project->getNomUrl(0); + } + } + + $data[$i]['icon'] = $actionComm->getLibStatut(3); + + $data[$i]['eventtitle'] = "{$data[$i]['company']}{$data[$i]['contact']}
{$actionComm->label}
{$data[$i]['extraInfo']}"; + + + + + + + + return $data; + + } + + + /** + * Format Actions into events array + * @param format 'vcal', 'ical/ics', 'rss' + * @param type 'event' or 'journal' + * @param cachedelay Do not rebuild file if date older than cachedelay seconds + * @param filename Force filename + * @param filters Array of filters + * @return array empty array if error + */ + function getEvents($start,$end,$options){ + global $conf,$langs,$dolibarr_main_url_root,$mysoc,$user; + + $actionComm = new ActionComm($this->db); + $showbirthday = (isset($options['showbirthday'])) ? $options['showbirthday'] : null; + $status = (isset($options['status'])) ? $options['status'] : null; + $filtera = (isset($options['userasked'])) ? $options['userasked'] : -1; + $filtert = (isset($options['usertodo'])) ? $options['usertodo'] : -1; + $filterd = (isset($options['userdone'])) ? $options['userdone'] : -1; + $pid = (isset($options['projectid'])) ? $options['projectid'] : 0; + + + $data = array(); + + //Setting dates + $start = date('Y-m-d H:i:s',substr($start,0,10)); + $end = date('Y-m-d H:i:s',substr($end,0,10)); + + $sql = ' SELECT a.id,a.label,'; + $sql.= ' concat(unix_timestamp(datep)) as datep, + concat(unix_timestamp(datep2)) as datep2, + concat(unix_timestamp(datea)) as datea, + concat(unix_timestamp(datea2)) as datea2,'; + $sql.= ' a.percent,'; + $sql.= ' a.fk_user_author,a.fk_user_action,a.fk_user_done,'; + $sql.= ' a.priority, a.fulldayevent, a.location,'; + $sql.= ' a.fk_soc, a.fk_contact,'; + $sql.= ' ca.code'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a'; + $sql.= ', '.MAIN_DB_PREFIX.'c_actioncomm as ca'; + $sql.= ', '.MAIN_DB_PREFIX.'user as u'; + $sql.= ' WHERE a.fk_action = ca.id'; + $sql.= ' AND a.fk_user_author = u.rowid'; + $sql.= ' AND u.entity in (0,'.$conf->entity.')'; // To limit to entity + if ($user->societe_id) $sql.= ' AND a.fk_soc = '.$user->societe_id; // To limit to external user company + if ($pid) $sql.=" AND a.fk_project=".addslashes($pid); + $sql.= " AND ( + (datep BETWEEN '{$start}' AND '{$end}') + OR (datep2 BETWEEN '{$start}' AND '{$end}') + OR (datep < '{$start}' AND datep2 > '{$end}') + )"; + if ($filtera > 0 || $filtert > 0 || $filterd > 0) + { + $sql.= " AND ("; + if ($filtera > 0) $sql.= " a.fk_user_author = ".$filtera; + if ($filtert > 0) $sql.= ($filtera>0?" OR ":"")." a.fk_user_action = ".$filtert; + if ($filterd > 0) $sql.= ($filtera>0||$filtert>0?" OR ":"")." a.fk_user_done = ".$filterd; + $sql.= ")"; + } + if ($status == 'done') { $sql.= " AND a.percent = 100"; } + if ($status == 'todo') { $sql.= " AND a.percent < 100"; } + // Sort on date + $sql.= ' ORDER BY datep'; + $resql = $this->db->query($sql); + while ($obj = $this->db->fetch_object($resql)): + $data[$i]['eventid'] = $obj->id; + + + $data[$i]['readonly'] = 0; + $data[$i]['draggable'] = 1; + $data[$i]['resizable'] = 1; + $data[$i]['multiday'] = 0; + // + 3600 to be GMT! + $data[$i]['eventstart'] = $obj->datep; + $data[$i]['eventend'] = $obj->datep2; + $data[$i]['eventmessage'] = $obj->note; + + $data[$i]['color'] = "#666677"; + + //Formating the title + $langs->load("companies"); + $langs->load("commercial"); + $langs->load("other"); + + $actionComm->fetch($obj->id); + + + + $title = ""; + $data[$i]['type'] = $actionComm->type; + + + //Getting company name for title + + $langs->load('companies'); + if($actionComm->societe->id): + $company = new Societe($actionComm->db); + $company->fetch($actionComm->societe->id); + + $actionComm->societe = $company; + $data[$i]['company'] = "
{$actionComm->societe->getNomUrl(0)}
"; + else: + $data[$i]['company'] = ""; + endif; + + //Getting contact name for title + + if($actionComm->contact->id): + $contact = new Contact($actionComm->db); + $contact->fetch($actionComm->contact->id,$user); + $actionComm->contact = $contact; + $data[$i]['contact'] = "
{$actionComm->contact->getNomUrl(0)}
"; + if ($actionComm->contact->id && $actionComm->type_code == 'AC_TEL'): + + $data[$i]['extraInfo'] = "(".dol_print_phone($actionComm->contact->phone_pro).")"; + endif; + else: + $data[$i]['contact'] = ''; + $data[$i]['extraInfo'] = ''; + endif; + + + + //Getting Project name for title + if ($conf->projet->enabled) + { + if ($actionComm->fk_project) + { + $project=new Project($actionComm->db); + $project->fetch($actionComm->fk_project); + $data[$i]['project'] = $project->getNomUrl(0); + } + } + + $data[$i]['icon'] = $actionComm->getLibStatut(3); + + $data[$i]['eventtitle'] = "{$data[$i]['company']}{$data[$i]['contact']}
{$actionComm->label}
{$data[$i]['extraInfo']}"; + + + + $i++; + endwhile; + + + //Getting Birthdays + + + if($showbirthday): + $sql = 'SELECT sp.rowid, sp.name, sp.firstname, unix_timestamp(sp.birthday) as birthday'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'socpeople as sp'; + $sql.= ' WHERE (priv=0 OR (priv=1 AND fk_user_creat='.$user->id.'))'; + $sql.= ' AND sp.entity = '.$conf->entity; + $sql.= " AND (birthday BETWEEN '{$start}' AND '{$end}') "; + $sql.= ' ORDER BY birthday'; + + dol_syslog("comm/action/index.php sql=".$sql, LOG_DEBUG); + $resql=$actionComm->db->query($sql); + if ($resql) + { + $num = $actionComm->db->num_rows($resql); + $j=0; + $i++; + while ($j < $num) + { + $obj = $actionComm->db->fetch_object($resql); + + $data[$i]['eventid'] = "birthday_{$obj->rowid}"; + $data[$i]['multiday'] = 0; + $data[$i]['readonly'] = 1; + + //We set all the birthdays to One hour at 12 am. + //and, +3600 to be GMT! + $data[$i]['eventstart'] = $obj->birthday + (3600 * 12); + $data[$i]['eventend'] = $obj->birthday + (3600 * 13); + $data[$i]['type'] = $langs->trans('Birthday'); + $actionComm->percentage = 100; + $data[$i]['icon'] = $actionComm->getLibStatut(3); + + + $contact->fetch($obj->rowid,$user); + $actionComm->contact = $contact; + $data[$i]['contact'] = "
{$actionComm->contact->getNomUrl(0)}
"; + + $company->fetch($obj->fk_soc); + $actionComm->societe = $company; + $data[$i]['company'] = "
{$actionComm->societe->getNomUrl(0)}
"; + $data[$i]['eventtitle'] = "{$data[$i]['company']}{$data[$i]['contact']}
".$langs->trans("Birthday").' '.$obj->firstname.' '.$obj->name; + $i++; + $j++; + } + } + endif; + + return $data; + + } + + /** + * Récupère les évènements selon les fitres présent dans $options + * sous forme d'un tableau d'évènement structuré + * @see commonagenda.class.php pour voir la structure attendue + * @param $options tableau de filtres + * @return $events tableau d'évènements + */ + function getEventsForExport($options) + { + global $conf,$user,$langs,$dolibarr_main_url_root; + + // Build event array + $eventarray=array(); + + $sql = "SELECT a.id,"; + $sql.= " a.datep,"; // Start + $sql.= " a.datep2,"; // End + $sql.= " a.durationp,"; + $sql.= " a.datec, a.tms as datem,"; + $sql.= " a.note, a.label, a.fk_action as type_id,"; + $sql.= " a.fk_soc,"; + $sql.= " a.fk_user_author, a.fk_user_mod,"; + $sql.= " a.fk_user_action, a.fk_user_done,"; + $sql.= " a.fk_contact, a.fk_facture, a.percent as percentage, a.fk_commande,"; + $sql.= " a.priority, a.fulldayevent, a.location,"; + $sql.= " u.firstname, u.name,"; + $sql.= " s.nom as socname,"; + $sql.= " c.id as type_id, c.code as type_code, c.libelle"; + $sql.= " FROM (".MAIN_DB_PREFIX."c_actioncomm as c, ".MAIN_DB_PREFIX."actioncomm as a)"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_author"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on s.rowid = a.fk_soc"; + $sql.= " WHERE a.fk_action=c.id"; + foreach ($options as $key => $value) + { + if ($key == 'notolderthan' and $value > 0) $sql.=" AND a.datep >= '".$this->db->idate($now-($value*24*60*60))."'"; + if ($key == 'year' and $value > 0) $sql.=" AND a.datep BETWEEN '".$this->db->idate(dol_get_first_day($value,1))."' AND '".$this->db->idate(dol_get_last_day($value,12))."'"; + if ($key == 'id' and $value > 0) $sql.=" AND a.id=".(is_numeric($value)?$value:0); + if ($key == 'idfrom' and $value > 0) $sql.=" AND a.id >= ".(is_numeric($value)?$value:0); + if ($key == 'idto' and $value > 0) $sql.=" AND a.id <= ".(is_numeric($value)?$value:0); + if ($key == 'projectid' and $value > 0) $sql.=" AND a.fk_project=".(int)($value); + if ($key == 'status') + { + if ($value == 'done') { $sql.= " AND a.percent = 100"; } + if ($value == 'todo') { $sql.= " AND a.percent < 100"; } + } + if ($key == 'login' and $value > 0) + { + $login=$value; + $userforfilter=new User($this->db); + $result=$userforfilter->fetch('',$value); + $sql.= " AND ("; + $sql.= " a.fk_user_author = ".$userforfilter->id; + $sql.= " OR a.fk_user_action = ".$userforfilter->id; + $sql.= " OR a.fk_user_done = ".$userforfilter->id; + $sql.= ")"; + } + if ($key == 'userasked' and $value > 0) + { + $logina=$value; + $userforfilter=new User($this->db); + $result=$userforfilter->fetch('',$value); + $sql.= " AND a.fk_user_author = ".$userforfilter->id; + } + if ($key == 'usertodo' and $value > 0) + { + $logint=$value; + $userforfilter=new User($this->db); + $result=$userforfilter->fetch('',$value); + $sql.= " AND a.fk_user_action = ".$userforfilter->id; + } + if ($key == 'userdone' and $value > 0) + { + $logind=$value; + $userforfilter=new User($this->db); + $result=$userforfilter->fetch('',$value); + $sql.= " AND a.fk_user_done = ".$userforfilter->id; + } + } + $sql.= " AND a.datep IS NOT NULL"; // To exclude corrupted events and avoid errors in lightning/sunbird import + $sql.= " ORDER by datep"; + //print $sql;exit; + + dol_syslog("ActionComm::build_exportfile select events sql=".$sql); + $resql=$this->db->query($sql); + if ($resql) + { + // Note: Output of sql request is encoded in $conf->file->character_set_client + while ($obj=$this->db->fetch_object($resql)) + { + $qualified=true; + + // 'eid','startdate','duration','enddate','title','summary','category','email','url','desc','author' + $event=array(); + $event['uid']='dolibarragenda-'.$this->db->database_name.'-'.$obj->id."@".$_SERVER["SERVER_NAME"]; + $event['type']='event'; + //$datestart=$obj->datea?$obj->datea:$obj->datep; + //$dateend=$obj->datea2?$obj->datea2:$obj->datep2; + //$duration=$obj->durationa?$obj->durationa:$obj->durationp; + $datestart=$this->db->jdate($obj->datep); + //print $datestart.'x'; exit; + $dateend=$this->db->jdate($obj->datep2); + $duration=$obj->durationp; + $event['summary']=$langs->convToOutputCharset($obj->label.($obj->socname?" (".$obj->socname.")":"")); + $event['desc']=$langs->convToOutputCharset($obj->note); + $event['startdate']=$datestart; + $event['duration']=$duration; // Not required with type 'journal' + $event['enddate']=$dateend; // Not required with type 'journal' + $event['author']=$obj->firstname.($obj->name?" ".$obj->name:""); + $event['priority']=$obj->priority; + $event['fulldayevent']=$obj->fulldayevent; + $event['location']=$langs->convToOutputCharset($obj->location); + $event['transparency']='TRANSPARENT'; // OPAQUE (busy) or TRANSPARENT (not busy) + $event['category']=$langs->convToOutputCharset($obj->libelle); // libelle type action + $url=$dolibarr_main_url_root; + if (! preg_match('/\/$/',$url)) $url.='/'; + $url.='comm/action/fiche.php?id='.$obj->id; + $event['url']=$url; + $event['created']=$this->db->jdate($obj->datec); + $event['modified']=$this->db->jdate($obj->datem); + + if ($qualified && $datestart) + { + $eventarray[$datestart]=$event; + } + } + } + + + if(isset($options['showbirthday']) and $options['showbirthday'] > 0): + $sql = 'SELECT sp.rowid, sp.name, sp.firstname, unix_timestamp(sp.birthday) as birthday'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'socpeople as sp'; + $sql.= ' WHERE (priv=0 OR (priv=1 AND fk_user_creat='.$user->id.'))'; + $sql.= ' AND sp.entity = '.$conf->entity; + if (isset($options['notolderthan']) and $options['notolderthan'] > 0) $sql.=" AND birthday >= '".$this->db->idate($now-($options['notolderthan']*24*60*60))."'"; + $sql.= ' ORDER BY birthday'; + + dol_syslog("comm/action/index.php sql=".$sql, LOG_DEBUG); + $resql=$this->db->query($sql); + if ($resql) + { + $num = $this->db->num_rows($resql); + $j=0; + while ($j < $num) + { + $obj = $this->db->fetch_object($resql); + + $event=array(); + $event['uid']='dolibarragenda-'.$this->db->database_name.'-birthday-'.$obj->rowid."@".$_SERVER["SERVER_NAME"]; + $event['type']=$langs->trans('Birthday'); + $datestart=$this->db->jdate($obj->birthday) + (3600 * 12); + $dateend=$this->db->jdate($obj->birthday) + (3600 * 13); + $duration=3600; + $event['startdate']=$datestart; + $event['duration']=$duration; // Not required with type 'journal' + $event['enddate']=$dateend; // Not required with type 'journal' + $event['author']=$obj->firstname.($obj->name?" ".$obj->name:""); + $event['priority']=0; + $event['fulldayevent']=0; + $event['location']=''; + $event['transparency']='TRANSPARENT'; // OPAQUE (busy) or TRANSPARENT (not busy) + $event['category']= $langs->trans('Birthday'); + $url=$dolibarr_main_url_root; + if (! preg_match('/\/$/',$url)) $url.='/'; + $url.='contact/fiche.php?id='.$obj->rowid; + $event['url']=$url; + $event['created']=$this->db->jdate($obj->birthday); + $event['modified']=$this->db->jdate($obj->birthday); + + + $contact = new Contact($this->db); + $contact->fetch($obj->rowid,$user); + $actionComm->contact = $contact; + $data['contact'] = "
{$actionComm->contact->getNomUrl(0)}
"; + + $company = new Societe($this->db); + $company->fetch($obj->fk_soc); + $actionComm->societe = $company; + $data['company'] = "
{$actionComm->societe->getNomUrl(0)}
"; + $event['summary'] = "{$data[$i]['company']}{$data[$i]['contact']}
".$langs->trans("Birthday").' '.$obj->firstname.' '.$obj->name; + $event['desc'] = "{$data[$i]['company']}{$data[$i]['contact']}
".$langs->trans("Birthday").' '.$obj->firstname.' '.$obj->name; + + $j++; + + $eventarray[$datestart]=$event; + } + } + endif; + + return $eventarray; + + } + + + function editEvent($id,$start,$end,$option = array()) + { + global $conf,$user,$langs; + $actionComm = new ActionComm($this->db); + $actionComm->fetch($id); + + if(!is_null($start)) + $actionComm->datep = $start; + + if(!is_null($end)) + $actionComm->datef = $end; + + $actionComm->update($user); + + $title = ""; + + $i = 0; + $data[$i]['type'] = $actionComm->type; + + + //Getting company name for title + + $langs->load('companies'); + if($actionComm->societe->id): + $company = new Societe($actionComm->db); + $company->fetch($actionComm->societe->id); + + $actionComm->societe = $company; + $data[$i]['company'] = "
{$actionComm->societe->getNomUrl(0)}
"; + else: + $data[$i]['company'] = ""; + endif; + + //Getting contact name for title + + if($actionComm->contact->id): + $contact = new Contact($actionComm->db); + $contact->fetch($actionComm->contact->id,$user); + $actionComm->contact = $contact; + $data[$i]['contact'] = "
{$actionComm->contact->getNomUrl(0)}
"; + if ($actionComm->contact->id && $actionComm->type_code == 'AC_TEL'): + + $data[$i]['extraInfo'] = "(".dol_print_phone($actionComm->contact->phone_pro).")"; + endif; + else: + $data[$i]['contact'] = ''; + $data[$i]['extraInfo'] = ''; + endif; + + + + //Getting Project name for title + if ($conf->projet->enabled) + { + if ($actionComm->fk_project) + { + $project=new Project($actionComm->db); + $project->fetch($actionComm->fk_project); + $data[$i]['project'] = $project->getNomUrl(0); + } + } + + $data[$i]['icon'] = $actionComm->getLibStatut(3); + + $data[$i]['eventtitle'] = "{$data[$i]['company']}{$data[$i]['contact']}
{$actionComm->label}
{$data[$i]['extraInfo']}"; + + + return $data; + + } + + + function getTitle() + { + global $conf,$user,$langs; + return $langs->trans('Actions'); + } + + function getLabel() + { + global $user,$langs,$conf,$status; + + if ($status == 'done') + $title= $langs->trans("DoneActions"); + elseif ($status == 'todo') + $title= $langs->trans("ToDoActions"); + else + $title= $langs->trans("DoneAndToDoActions"); + ob_start(); + print_fiche_titre($title); + $label = ob_get_contents(); + ob_end_clean(); + + return $label; + } + + function getForm($get,$post) + { + global $user,$langs,$conf; + $form = new Form($this->db); + $post = $get + $post; + ob_start(); + + if (! empty($post["viewlist"])) + { + $param=''; + foreach($post as $key => $val) + { + if ($key=='token') continue; + $param.='&'.$key.'='.urlencode($val); + } + //print $param; + header("Location: ".DOL_URL_ROOT.'/comm/action/listactions.php?'.$param); + exit; + } + // Birthday Link + $link=''; + if (empty($post['showbirthday'])) $link.=$langs->trans("AgendaShowBirthdayEvents"); + else $link.=$langs->trans("AgendaHideBirthdayEvents"); + $link.=''; + + + // Filters + if ($user->rights->agenda->allactions->read || $conf->projet->enabled) + { + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + // Buttons + print ''; + print ''; + } + print '
'; + print ''; + + if ($user->rights->agenda->allactions->read) + { + print ''; + print ''; + print ''; + + print ''; + print ''; + + print ''; + print ''; + } + if ($conf->projet->enabled) + { + print ''; + print ''; + } + + print '
'; + print $langs->trans("ActionsAskedBy"); + print '  '; + print $form->select_users(((isset($post['filter']) and $post['filter'] == 'mine')?$user->id:$post['userasked']),'userasked',1,'',!$user->rights->agenda->allactions->read); + print '
'; + print $langs->trans("or").' '.$langs->trans("ActionsToDoBy"); + print '  '; + print $form->select_users(((isset($post['filter']) and $post['filter'] == 'mine')?$user->id:$post['usertodo']),'usertodo',1,'',!$user->rights->agenda->allactions->read); + print '
'; + print $langs->trans("or").' '.$langs->trans("ActionsDoneBy"); + print '  '; + print $form->select_users(((isset($post['filter']) and $post['filter'] == 'mine')?$user->id:$post['userdone']),'userdone',1,'',!$user->rights->agenda->allactions->read); + print '
'; + print $langs->trans("Project").'   '; + print ''; + select_projects($socid?$socid:-1,$post['projectid'],'projectid'); + print '
'; + print '
'; + print img_picto($langs->trans("ViewCal"),'object_calendar').' '; + print '
'; + print '
'; + print img_picto($langs->trans("ViewList"),'object_list').' '; + print '
'; + print '

'; + echo $link; + + + $form = ob_get_contents(); + ob_end_clean(); + + return $form; + } + + + function getFormItems() + { + global $conf; + + $fields = array( + 'token' => 'input', + 'status' => 'input', + 'userasked' => 'input', + 'usertodo' => 'input', + 'userdone' => 'input', + 'year' => 'input', + 'month' => 'input', + 'day' => 'input', + 'showbirthday' => 'input', + 'action' => 'input', + 'userasked' => 'select', + 'usertodo' => 'select', + 'userdone' => 'select', + 'projectid' => 'select', + ); + + return $fields; + + } + + function canCreate() + { + global $user,$langs,$conf; + + return ($user->rights->agenda->myactions->create) ? true : false; + + } + + + function getLink($action = "") + { + global $conf,$user; + $url = DOL_URL_ROOT."/comm/action/fiche.php"; + return (empty($action)) ? $url : $url."?action={$action}"; + } + + function getTitleForExport($format,$options) + { + global $user,$conf,$langs,$mysoc; + $langs->load("agenda"); + + // Define title and desc + $more=''; + + + if (isset($options['login']) and $options['login'] > 0) $more=$langs->transnoentities("User").' '.$langs->convToOutputCharset($options['login']); + if (isset($options['userasked']) and $options['userasked'] > 0) $more=$langs->transnoentities("ActionsAskedBy").' '.$langs->convToOutputCharset($options['userasked']); + if (isset($options['usertodo']) and $options['usertodo'] > 0) $more=$langs->transnoentities("ActionsToDoBy").' '.$langs->convToOutputCharset($options['usertodo']); + if (isset($options['userdone']) and $options['userdone'] > 0) $more=$langs->transnoentities("ActionsDoneBy").' '.$langs->convToOutputCharset($options['userdone']); + if ($more) + { + $title=$langs->convToOutputCharset('Dolibarr actions '.$mysoc->name).' - '.$more; + $desc=$more; + $desc.=$langs->convToOutputCharset(' ('.$mysoc->name.' - built by Dolibarr)'); + } + else + { + $title=$langs->convToOutputCharset('Dolibarr actions '.$mysoc->name); + $desc=$langs->transnoentities('ListOfActions'); + $desc.=$langs->convToOutputCharset(' ('.$mysoc->name.' - built by Dolibarr)'); + } + + return $title; + + } + + function getDescForExport($format,$options) + { + global $user,$conf,$langs,$mysoc; + $langs->load("agenda"); + + // Define title and desc + $more=''; + + + if (isset($options['login']) and $options['login'] > 0) $more=$langs->transnoentities("User").' '.$langs->convToOutputCharset($options['login']); + if (isset($options['userasked']) and $options['userasked'] > 0) $more=$langs->transnoentities("ActionsAskedBy").' '.$langs->convToOutputCharset($options['userasked']); + if (isset($options['usertodo']) and $options['usertodo'] > 0) $more=$langs->transnoentities("ActionsToDoBy").' '.$langs->convToOutputCharset($options['usertodo']); + if (isset($options['userdone']) and $options['userdone'] > 0) $more=$langs->transnoentities("ActionsDoneBy").' '.$langs->convToOutputCharset($options['userdone']); + if ($more) + { + $desc=$more; + $desc.=$langs->convToOutputCharset(' ('.$mysoc->name.' - built by Dolibarr)'); + } + else + { + $desc=$langs->transnoentities('ListOfActions'); + $desc.=$langs->convToOutputCharset(' ('.$mysoc->name.' - built by Dolibarr)'); + } + + return $desc; + + } + +} + +?> diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/comm/action/data.ajax.php dolibarr-svn/htdocs/comm/action/data.ajax.php --- dolibarr-snapshot/htdocs/comm/action/data.ajax.php 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/comm/action/data.ajax.php 2011-04-08 12:36:33.000000000 +0200 @@ -0,0 +1,177 @@ +projet->enabled) require_once(DOL_DOCUMENT_ROOT."/lib/project.lib.php"); + + foreach($conf->agendas_modules as $ag_path => $ag_classes): + foreach($ag_classes as $ag_filename) + require_once DOL_DOCUMENT_ROOT."/{$ag_path}/class/".strtolower($ag_filename).".class.php"; + + endforeach; +} /* End of Including Files */ + + +//Include default includes +//Switch on the get action on what the server needs to do +switch($_GET['cal_action']) { +case "edit": + + //Edit an event + + $start = $_POST['start']; + $end = $_POST['end']; + + //Check needed post var + + $data['start'] = isset($_POST['start']) ? $_POST['start'] : 'N/A'; + $data['end'] = isset($_POST['end']) ? $_POST['end'] : 'N/A'; + $data['multiday'] = isset($_POST['multiday']) ? $_POST['multiday'] : 'N/A'; + $data['id'] = isset($_POST['id']) ? $_POST['id'] : 'N/A'; + $data['onwhat'] = isset($_POST['onWhat']) ? $_POST['onWhat'] : 'N/A'; + $data['agenda'] = isset($_POST['agenda']) ? $_POST['agenda'] : 'N/A'; + + + if(in_array('N/A',$data)) + exit(); + + // in edit mode, we can have $start and $end as C format (date('c')), or as a TS + // Is-it a TS? + if(strlen($data['start']) == 13): + $ts_start = substr($data['start'],0,10); + $ts_end = substr($data['end'],0,10); + elseif(strlen($data['start']) == 10): + $ts_start = $data['start']; + $ts_end = $data['end']; + else: + exit(); + endif; + + + + // si l'évènement est de type multiday, nous devons vérifier l'action qui à provoqué l'édition. + // Pour plus de sécurité, un event multiday qui aura subu un resize : on ne modifiera que la date de fin + // Pour plus de sécurité, un event multiday qui aura subu un drag&drop : on ne modifiera que la date de début! + if($data['multiday']): + switch($data['onwhat']): + //case drop : just change the start date + case 'drop': + $ts_end = null; + break; + //case resize : just change the end date + case 'resize': + + //on a multiday action, 00:15 is the smallest time we can set + //so, if the end time is 00:15, we reduce 16 minutes to the action + //to make it last on N-1 days. + if(date('H:i',$ts_end) < '00:30'): + $minutes = date('i',$ts_end) * 60 + 60; + $secondes = date('s',$ts_end); + $ts_end = $ts_end - ($minutes + $secondes) ; + endif; + $action->datef = $ts_end; + $ts_start = null; + break; + endswitch; + endif; + + + $agenda = new $data['agenda']($db); + + $agenda->editEvent($_POST['id'],$ts_start,$ts_end); + + + $recordSet = $agenda->getEvent($_POST['id']); + + date_default_timezone_set('Universal'); + + + $id = $k = 0; + + $events[$id]['type'] = json_string($recordSet[$k]['type']); + $events[$id]['icon'] = isset($recordSet[$k]['icon']) ? json_string($recordSet[$k]['icon']) : ''; + $events[$id]['title'] = json_string($recordSet[$k]['eventtitle']); + $events[$id]['extraInfo'] = isset($recordSet[$k]['extraInfo']) ? json_string($recordSet[$k]['ExtraInfo']) : ''; + $events[$id]['project'] = isset($recordSet[$k]['project']) ? json_string($recordSet[$k]['project']) : ''; + $events[$id]['start'] = date('c',substr($recordSet[$k]['eventstart'],0,10) + $agenda->getOffset(substr($recordSet[$k]['eventstart'],0,10))); + //if no eventend is set, add one hour to the event to make it readable in the calendar! + $events[$id]['end'] = (!empty($recordSet[$k]['eventend'])) ? date('c',substr($recordSet[$k]['eventend'],0,10) + $agenda->getOffset(substr($recordSet[$k]['eventend'],0,10))) : date('c',substr($recordSet[$k]['eventstart'],0,10)+(60*60) + $agenda->getOffset(substr($recordSet[$k]['eventstart'],0,10))); + $events[$id]['color'] = $recordSet[$k]['color']; + $events[$id]['readOnly'] = (isset($recordSet[$k]['readonly'])) ? $recordSet[$k]['readonly'] : 0; + $events[$id]['draggable'] = (isset($recordSet[$k]['draggable'])) ? $recordSet[$k]['draggable'] : 0; + $events[$id]['resizable'] = (isset($recordSet[$k]['resizable'])) ? $recordSet[$k]['resizable'] : 0; + $events[$id]['multiday'] = (isset($recordSet[$k]['multiday'])) ? $recordSet[$k]['multiday'] : 0; + + + + + + echo generateeventjson($events); +break; +case "getevents": + //The JSON is always changed when loaded (forces brouwsers to load it again) else they could use cache + header ("Expires: Thu, 17 May 2001 10:17:17 GMT"); // Date in the past + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified + header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 + header ("Pragma: no-cache"); // HTTP/1.0 + date_default_timezone_set('Universal'); + + if(!isset($_GET['agenda'])) + exit; + + $agenda = new $_GET['agenda']($db); + + $recordSet = $agenda->getEvents($_GET['start'],$_GET['end'],$_GET); + + + /* + * + * Nous devons vérifier si des évènements doivent être affichés sur plusieurs jours! + * Si c'est le cas, en imaginant un évènement sur trois jours : + * l'évènement sera divisé en 3. + * le premier évènement commencera à l'heure de début fixé, jusqu'à minuit le lendemain, il perdra la propriété resizable! + * le second évènement commencera à minuit le lendemain, jusqu'à minuit le jour d'après, il perdra la propriété resizable & draggable! + * le dernier évènement commencera à minuit le dernier jour, jusqu'à l'heure de fin fixé, il perdra la propriété draggable mais sera resizable! + */ + $recordSet = $agenda->checkMultiDayTasks($recordSet); + + + + + $recordSet = (!$recordSet) ? array() : $recordSet; + $id =1; + foreach($recordSet as $k => $v): + $events[$id]['id'] = $recordSet[$k]['eventid']; + + $events[$id]['type'] = json_string($recordSet[$k]['type']); + $events[$id]['icon'] = isset($recordSet[$k]['icon']) ? json_string($recordSet[$k]['icon']) : ''; + $events[$id]['title'] = json_string($recordSet[$k]['eventtitle']); + $events[$id]['extraInfo'] = isset($recordSet[$k]['extraInfo']) ? json_string($recordSet[$k]['ExtraInfo']) : ''; + $events[$id]['project'] = isset($recordSet[$k]['project']) ? json_string($recordSet[$k]['project']) : ''; + $events[$id]['start'] = date('c',substr($recordSet[$k]['eventstart'],0,10) + $agenda->getOffset(substr($recordSet[$k]['eventstart'],0,10))); + //if no eventend is set, add one hour to the event to make it readable in the calendar! + $events[$id]['end'] = (!empty($recordSet[$k]['eventend'])) ? date('c',substr($recordSet[$k]['eventend'],0,10) + $agenda->getOffset(substr($recordSet[$k]['eventend'],0,10))) : date('c',substr($recordSet[$k]['eventstart'],0,10)+(60*60) + $agenda->getOffset(substr($recordSet[$k]['eventstart'],0,10))); + $events[$id]['color'] = $recordSet[$k]['color']; + $events[$id]['readOnly'] = (isset($recordSet[$k]['readonly'])) ? $recordSet[$k]['readonly'] : 0; + $events[$id]['draggable'] = (isset($recordSet[$k]['draggable'])) ? $recordSet[$k]['draggable'] : 0; + $events[$id]['resizable'] = (isset($recordSet[$k]['resizable'])) ? $recordSet[$k]['resizable'] : 0; + $events[$id]['multiday'] = (isset($recordSet[$k]['multiday'])) ? $recordSet[$k]['multiday'] : 0; + + $id++; + endforeach; + + //Generate the JSON en putting it back to the page + echo generateeventjson($events, true); +break; +default://When non of the supported events are given display a message + echo "Nothing to display"; +break; +} +?> \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/comm/action/index.php dolibarr-svn/htdocs/comm/action/index.php --- dolibarr-snapshot/htdocs/comm/action/index.php 2011-04-18 05:00:20.000000000 +0200 +++ dolibarr-svn/htdocs/comm/action/index.php 2011-04-15 15:34:33.000000000 +0200 @@ -1,9 +1,8 @@ * Copyright (C) 2003 Eric Seigne - * Copyright (C) 2004-2011 Laurent Destailleur - * Copyright (C) 2005-2011 Regis Houssin - * Copyright (C) 2011 Juanjo Menent + * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2005-2010 Regis Houssin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,803 +23,319 @@ * \file htdocs/comm/action/index.php * \ingroup agenda * \brief Home page of calendar events - * \version $Id: index.php,v 1.160 2011/04/17 22:57:12 hregis Exp $ + * \version $Id: index.php,v 1.144.2.2 2011/02/02 16:45:42 eldy Exp $ */ -require("../../main.inc.php"); -require_once(DOL_DOCUMENT_ROOT."/societe/class/societe.class.php"); -require_once(DOL_DOCUMENT_ROOT."/contact/class/contact.class.php"); -require_once(DOL_DOCUMENT_ROOT."/comm/action/class/actioncomm.class.php"); -require_once(DOL_DOCUMENT_ROOT."/lib/date.lib.php"); -require_once(DOL_DOCUMENT_ROOT."/lib/agenda.lib.php"); -if ($conf->projet->enabled) require_once(DOL_DOCUMENT_ROOT."/lib/project.lib.php"); - -$filter=GETPOST("filter"); -$filtera = GETPOST("userasked","int")?GETPOST("userasked","int"):GETPOST("filtera","int"); -$filtert = GETPOST("usertodo","int")?GETPOST("usertodo","int"):GETPOST("filtert","int"); -$filterd = GETPOST("userdone","int")?GETPOST("userdone","int"):GETPOST("filterd","int"); -$showbirthday = GETPOST("showbirthday","int")?GETPOST("showbirthday","int"):0; - -$sortfield = GETPOST("sortfield"); -$sortorder = GETPOST("sortorder"); -$page = GETPOST("page","int"); -if ($page == -1) { $page = 0 ; } -$limit = $conf->liste_limit; -$offset = $limit * $page ; -if (! $sortorder) $sortorder="ASC"; -if (! $sortfield) $sortfield="a.datec"; - -// Security check -$socid = GETPOST("socid","int",1); -if ($user->societe_id) $socid=$user->societe_id; -$result = restrictedArea($user, 'agenda', 0, '', 'myactions'); - -$canedit=1; -if (! $user->rights->agenda->myactions->read) accessforbidden(); -if (! $user->rights->agenda->allactions->read) $canedit=0; -if (! $user->rights->agenda->allactions->read || $filter =='mine') // If no permission to see all, we show only affected to me -{ - $filtera=$user->id; - $filtert=$user->id; - $filterd=$user->id; -} + +/* Including Files */ { + require("../../main.inc.php"); + + require_once(DOL_DOCUMENT_ROOT."/societe/class/societe.class.php"); + require_once(DOL_DOCUMENT_ROOT."/contact/class/contact.class.php"); + require_once(DOL_DOCUMENT_ROOT."/comm/action/class/actioncomm.class.php"); + require_once(DOL_DOCUMENT_ROOT."/lib/date.lib.php"); + require_once(DOL_DOCUMENT_ROOT."/lib/agenda.lib.php"); + if ($conf->projet->enabled) require_once(DOL_DOCUMENT_ROOT."/lib/project.lib.php"); +} /* End of Including Files */ + + +/* Getting POST & GET data */ { + $filter = GETPOST("filter"); + $filtera = GETPOST("userasked","int")?GETPOST("userasked","int"):GETPOST("filtera","int"); + $filtert = GETPOST("usertodo","int")?GETPOST("usertodo","int"):GETPOST("filtert","int"); + $filterd = GETPOST("userdone","int")?GETPOST("userdone","int"):GETPOST("filterd","int"); + $showbirthday = GETPOST("showbirthday","int")?GETPOST("showbirthday","int"):0; + $sortfield = GETPOST("sortfield"); + $sortorder = GETPOST("sortorder"); + $page = GETPOST("page","int"); + + + $action_btn = GETPOST('action','alpha'); + //$year = GETPOST("year"); + $year = GETPOST("year","int")?GETPOST("year","int"):date("Y"); + $month = GETPOST("month","int")?GETPOST("month","int"):date("m"); + $day = GETPOST("day","int")?GETPOST("day","int"):0; + $pid = GETPOST("projectid","int")?GETPOST("projectid","int"):0; + $status = GETPOST("status"); +} /* End of Getting POST & GET data */ + + +/* Security check */ { + $socid = GETPOST("socid","int",1); + if ($user->societe_id) $socid=$user->societe_id; + $result = restrictedArea($user, 'agenda', 0, '', 'myactions'); + + $canedit=1; + if (! $user->rights->agenda->myactions->read) accessforbidden(); + if (! $user->rights->agenda->allactions->read) $canedit=0; + if (! $user->rights->agenda->allactions->read || $filter =='mine') // If no permission to see all, we show only affected to me + { + $filtera=$user->id; + $filtert=$user->id; + $filterd=$user->id; + } +} /* End of Security Check */ + +/* Loading Language files */ { + $langs->load("other"); + $langs->load("commercial"); +} /* End of loading Language files */ + +/* Declaring objects */ { + $form = new Form($db); + $companystatic = new Societe($db); + $contactstatic = new Contact($db); + $action = new ActionComm($db); +} /* End of Declaring Objects */ + +/* Setting various var */ { + if ($page == -1) { $page = 0 ; } + $limit = $conf->liste_limit; + $offset = $limit * $page ; + if (! $sortorder) $sortorder="ASC"; + if (! $sortfield) $sortfield="a.datec"; + + if (! isset($conf->global->AGENDA_MAX_EVENTS_DAY_VIEW)) $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW=3; + + + //path for img + $path = 'theme/'.$conf->theme; + $url = DOL_URL_ROOT; + +} /* End of Setting various var */ -$action=GETPOST('action','alpha'); -//$year=GETPOST("year"); -$year=GETPOST("year","int")?GETPOST("year","int"):date("Y"); -$month=GETPOST("month","int")?GETPOST("month","int"):date("m"); -$week=GETPOST("week","int")?GETPOST("week","int"):date("W"); -$day=GETPOST("day","int")?GETPOST("day","int"):0; -$pid=GETPOST("projectid","int")?GETPOST("projectid","int"):0; -$status=GETPOST("status"); -$maxprint=GETPOST("maxprint"); -if (GETPOST('viewcal')) { $action='show_month'; $day=''; } // View by month -if (GETPOST('viewweek')) { $action='show_week'; $week=($week?$week:date("W")); $day=($day?$day:date("d")); } // View by week -if (GETPOST('viewday')) { $action='show_day'; $day=($day?$day:date("d")); } // View by day -$langs->load("other"); -$langs->load("commercial"); -if (! isset($conf->global->AGENDA_MAX_EVENTS_DAY_VIEW)) $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW=3; -/* - * Actions - */ -if (GETPOST("viewlist")) -{ - $param=''; - foreach($_POST as $key => $val) - { - if ($key=='token') continue; - $param.='&'.$key.'='.urlencode($val); - } - //print $param; - header("Location: ".DOL_URL_ROOT.'/comm/action/listactions.php?'.$param); - exit; -} -if ($action=='delete_action') -{ - $event = new ActionComm($db); - $event->fetch($actionid); - $result=$event->delete(); -} -/* - * View - */ -$help_url='EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; -llxHeader('',$langs->trans("Agenda"),$help_url); +/* Header */ { + $help_url='EN:Module_Agenda_En|FR:Module_Agenda|ES:M&omodulodulo_Agenda'; + llxHeader('',$langs->trans("Agenda"),$help_url); +} /* End of header */ + + + -$form=new Form($db); -$companystatic=new Societe($db); -$contactstatic=new Contact($db); - -$now=dol_now('tzref'); - -if (empty($action) || $action=='show_month') -{ - $prev = dol_get_prev_month($month, $year); - $prev_year = $prev['year']; - $prev_month = $prev['month']; - $next = dol_get_next_month($month, $year); - $next_year = $next['year']; - $next_month = $next['month']; - - $max_day_in_prev_month = date("t",dol_mktime(0,0,0,$prev_month,1,$prev_year)); // Nb of days in previous month - $max_day_in_month = date("t",dol_mktime(0,0,0,$month,1,$year)); // Nb of days in next month - // tmpday is a negative or null cursor to know how many days before the 1 to show on month view (if tmpday=0 we start on monday) - $tmpday = -date("w",dol_mktime(0,0,0,$month,1,$year))+2; - $tmpday+=((isset($conf->global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1)-1); - if ($tmpday >= 1) $tmpday -= 7; - // Define firstdaytoshow and lastdaytoshow - $firstdaytoshow=dol_mktime(0,0,0,$prev_month,$max_day_in_prev_month+$tmpday,$prev_year); - $next_day=7-($max_day_in_month+1-$tmpday)%7; - if ($next_day < 6) $next_day+=7; - $lastdaytoshow=dol_mktime(0,0,0,$next_month,$next_day,$next_year); -} -if ($action=='show_week') -{ - $prev = dol_get_first_day_week($day, $month, $year); - $prev_year = $prev['prev_year']; - $prev_month = $prev['prev_month']; - $prev_day = $prev['prev_day']; - $first_day = $prev['first_day']; - - $week = $prev['week']; - - $day =(int)$day; - $next = dol_get_next_week($day, $week, $month, $year); - $next_year = $next['year']; - $next_month = $next['month']; - $next_day = $next['day']; - - // Define firstdaytoshow and lastdaytoshow - $firstdaytoshow=dol_mktime(0,0,0,$prev_month,$first_day,$prev_year); - $lastdaytoshow=dol_mktime(0,0,0,$next_month,$next_day,$next_year); - $max_day_in_month = date("t",dol_mktime(0,0,0,$month,1,$year)); - $tmpday = $first_day; -} -if ($action=='show_day') -{ - $prev = dol_get_prev_day($day, $month, $year); - $prev_year = $prev['year']; - $prev_month = $prev['month']; - $prev_day = $prev['day']; - $next = dol_get_next_day($day, $month, $year); - $next_year = $next['year']; - $next_month = $next['month']; - $next_day = $next['day']; - - // Define firstdaytoshow and lastdaytoshow - $firstdaytoshow=dol_mktime(0,0,0,$prev_month,$prev_day,$prev_year); - $lastdaytoshow=dol_mktime(0,0,0,$next_month,$next_day,$next_year); -} -//print 'xx'.$prev_year.'-'.$prev_month.'-'.$prev_day; -//print 'xx'.$next_year.'-'.$next_month.'-'.$next_day; -//print dol_print_date($firstdaytoshow,'day'); -//print dol_print_date($lastdaytoshow,'day'); - -$title=$langs->trans("DoneAndToDoActions"); -if ($status == 'done') $title=$langs->trans("DoneActions"); -if ($status == 'todo') $title=$langs->trans("ToDoActions"); $param=''; -if ($status) $param="&status=".$status; -if ($filter) $param.="&filter=".$filter; -if ($filtera) $param.="&filtera=".$filtera; -if ($filtert) $param.="&filtert=".$filtert; -if ($filterd) $param.="&filterd=".$filterd; -if ($socid) $param.="&socid=".$socid; -if ($showbirthday) $param.="&showbirthday=1"; -if ($pid) $param.="&projectid=".$pid; -if (GETPOST("type")) $param.="&type=".GETPOST("type"); -if ($action == 'show_day' || $action == 'show_week') $param.='&action='.$action; -if ($maxprint) $param.="&maxprint=on"; - -// Show navigation bar -if (empty($action) || $action=='show_month') -{ - $nav ="".img_previous($langs->trans("Previous"))."\n"; - $nav.=" ".dol_print_date(dol_mktime(0,0,0,$month,1,$year),"%b %Y"); - $nav.=" \n"; - $nav.="".img_next($langs->trans("Next"))."\n"; -} -if ($action=='show_week') -{ - $nav ="".img_previous($langs->trans("Previous"))."\n"; - $nav.=" ".dol_print_date(dol_mktime(0,0,0,$month,1,$year),"%Y").", ".$langs->trans("Week")." ".$week; - $nav.=" \n"; - $nav.="".img_next($langs->trans("Next"))."\n"; -} -if ($action=='show_day') -{ - $nav ="".img_previous($langs->trans("Previous"))."\n"; - $nav.=" ".dol_print_date(dol_mktime(0,0,0,$month,$day,$year),"daytextshort"); - $nav.=" \n"; - $nav.="".img_next($langs->trans("Next"))."\n"; -} +if ($status) (!empty($param)) ? $param="&status=".$status : $param="status=".$status; +if ($filter) (!empty($param)) ? $param.="&filter=".$filter : $param.="filter=".$filter; +if ($filtera) (!empty($param)) ? $param.="&filtera=".$filtera : $param.="filtera=".$filtera; +if ($filtert) (!empty($param)) ? $param.="&filtert=".$filtert : $param.="filtert=".$filtert; +if ($filterd) (!empty($param)) ? $param.="&filterd=".$filterd : $param.="filterd=".$filterd; +if ($day) (!empty($param)) ? $param.="&day=".$day : $param.="day=".$day; +if ($month) (!empty($param)) ? $param.="&month=".$month : $param.="month=".$month; +if ($year) (!empty($param)) ? $param.="&year=".$year : $param.="year=".$year; +if ($socid) (!empty($param)) ? $param.="&socid=".$socid : $param.="socid=".$socid; +if ($showbirthday) (!empty($param)) ? $param.="&showbirthday=1" : $param.="showbirthday=1"; +if ($pid) (!empty($param)) ? $param.="&projectid=".$pid : $param.="projectid=".$pid; +if (! empty($_REQUEST["type"])) $param.="&type=".$_REQUEST["type"]; -// Must be after the nav definition -$param.='&year='.$year.'&month='.$month.($day?'&day='.$day:''); -//print 'x'.$param; - -print_fiche_titre($title,$nav); - -print_actions_filter($form,$canedit,$status,$year,$month,$day,$showborthday,$filtera,$filtert,$filterd,$pid,$socid); - - -// Get event in an array -$eventarray=array(); - -$sql = 'SELECT a.id,a.label,'; -$sql.= ' a.datep,'; -$sql.= ' a.datep2,'; -$sql.= ' a.datea,'; -$sql.= ' a.datea2,'; -$sql.= ' a.percent,'; -$sql.= ' a.fk_user_author,a.fk_user_action,a.fk_user_done,'; -$sql.= ' a.priority, a.fulldayevent, a.location,'; -$sql.= ' a.fk_soc, a.fk_contact,'; -$sql.= ' ca.code'; -$sql.= ' FROM '.MAIN_DB_PREFIX.'actioncomm as a'; -$sql.= ', '.MAIN_DB_PREFIX.'c_actioncomm as ca'; -$sql.= ', '.MAIN_DB_PREFIX.'user as u'; -$sql.= ' WHERE a.fk_action = ca.id'; -$sql.= ' AND a.fk_user_author = u.rowid'; -$sql.= ' AND u.entity in (0,'.$conf->entity.')'; // To limit to entity -$sql.= ' AND a.entity = '.$conf->entity; -if ($user->societe_id) $sql.= ' AND a.fk_soc = '.$user->societe_id; // To limit to external user company -if ($pid) $sql.=" AND a.fk_project=".$db->escape($pid); -if ($action == 'show_day') -{ - $sql.= " AND ("; - $sql.= " (datep BETWEEN '".$db->idate(dol_mktime(0,0,0,$month,$day,$year))."'"; - $sql.= " AND '".$db->idate(dol_mktime(23,59,59,$month,$day,$year))."')"; - $sql.= " OR "; - $sql.= " (datep2 BETWEEN '".$db->idate(dol_mktime(0,0,0,$month,$day,$year))."'"; - $sql.= " AND '".$db->idate(dol_mktime(23,59,59,$month,$day,$year))."')"; - $sql.= " OR "; - $sql.= " (datep < '".$db->idate(dol_mktime(0,0,0,$month,$day,$year))."'"; - $sql.= " AND datep2 > '".$db->idate(dol_mktime(23,59,59,$month,$day,$year))."')"; - $sql.= ')'; -} -else -{ - // To limit array - $sql.= " AND ("; - $sql.= " (datep BETWEEN '".$db->idate(dol_mktime(0,0,0,$month,1,$year)-(60*60*24*7))."'"; // Start 7 days before - $sql.= " AND '".$db->idate(dol_mktime(23,59,59,$month,28,$year)+(60*60*24*10))."')"; // End 7 days after + 3 to go from 28 to 31 - $sql.= " OR "; - $sql.= " (datep2 BETWEEN '".$db->idate(dol_mktime(0,0,0,$month,1,$year)-(60*60*24*7))."'"; - $sql.= " AND '".$db->idate(dol_mktime(23,59,59,$month,28,$year)+(60*60*24*10))."')"; - $sql.= " OR "; - $sql.= " (datep < '".$db->idate(dol_mktime(0,0,0,$month,1,$year)-(60*60*24*7))."'"; - $sql.= " AND datep2 > '".$db->idate(dol_mktime(23,59,59,$month,28,$year)+(60*60*24*10))."')"; - $sql.= ')'; -} -if ($filtera > 0 || $filtert > 0 || $filterd > 0) -{ - $sql.= " AND ("; - if ($filtera > 0) $sql.= " a.fk_user_author = ".$filtera; - if ($filtert > 0) $sql.= ($filtera>0?" OR ":"")." a.fk_user_action = ".$filtert; - if ($filterd > 0) $sql.= ($filtera>0||$filtert>0?" OR ":"")." a.fk_user_done = ".$filterd; - $sql.= ")"; -} -if ($status == 'done') { $sql.= " AND a.percent = 100"; } -if ($status == 'todo') { $sql.= " AND a.percent < 100"; } -// Sort on date -$sql.= ' ORDER BY datep'; -//print $sql; - -dol_syslog("comm/action/index.php sql=".$sql, LOG_DEBUG); -$resql=$db->query($sql); -if ($resql) -{ - $num = $db->num_rows($resql); - $i=0; - while ($i < $num) - { - $obj = $db->fetch_object($resql); - // Create a new object action - $event=new ActionComm($db); - $event->id=$obj->id; - $event->datep=$db->jdate($obj->datep); - $event->datef=$db->jdate($obj->datep2); - $event->type_code=$obj->code; - $event->libelle=$obj->label; - $event->percentage=$obj->percent; - $event->author->id=$obj->fk_user_author; - $event->usertodo->id=$obj->fk_user_action; - $event->userdone->id=$obj->fk_user_done; - - $event->priority=$obj->priority; - $event->fulldayevent=$obj->fulldayevent; - $event->location=$obj->location; - - $event->societe->id=$obj->fk_soc; - $event->contact->id=$obj->fk_contact; - - // Defined date_start_in_calendar and date_end_in_calendar property - // They are date start and end of action but modified to not be outside calendar view. - if ($event->percentage <= 0) - { - $event->date_start_in_calendar=$event->datep; - if ($event->datef != '' && $event->datef >= $event->datep) $event->date_end_in_calendar=$event->datef; - else $event->date_end_in_calendar=$event->datep; - } - else - { - $event->date_start_in_calendar=$event->datep; - if ($event->datef != '' && $event->datef >= $event->datep) $event->date_end_in_calendar=$event->datef; - else $event->date_end_in_calendar=$event->datep; - } - // Define ponctual property - if ($event->date_start_in_calendar == $event->date_end_in_calendar) - { - $event->ponctuel=1; - } - - // Check values - if ($event->date_end_in_calendar < $firstdaytoshow || - $event->date_start_in_calendar > $lastdaytoshow) - { - // This record is out of visible range - } - else - { - if ($event->date_start_in_calendar < $firstdaytoshow) $event->date_start_in_calendar=$firstdaytoshow; - if ($event->date_end_in_calendar > $lastdaytoshow) $event->date_end_in_calendar=$lastdaytoshow; - - // Add an entry in actionarray for each day - $daycursor=$event->date_start_in_calendar; - $annee = date('Y',$daycursor); - $mois = date('m',$daycursor); - $jour = date('d',$daycursor); - - // Loop on each day covered by action to prepare an index to show on calendar - $loop=true; $j=0; - $daykey=dol_mktime(0,0,0,$mois,$jour,$annee); - do - { - //if ($event->id==408) print 'daykey='.$daykey.' '.$event->datep.' '.$event->datef.'
'; - - $eventarray[$daykey][]=$event; - $j++; - - $daykey+=60*60*24; - if ($daykey > $event->date_end_in_calendar) $loop=false; - } - while ($loop); - - //print 'Event '.$i.' id='.$event->id.' (start='.dol_print_date($event->datep).'-end='.dol_print_date($event->datef); - //print ' startincalendar='.dol_print_date($event->date_start_in_calendar).'-endincalendar='.dol_print_date($event->date_end_in_calendar).') was added in '.$j.' different index key of array
'; - } - $i++; - } -} -else -{ - dol_print_error($db); -} -if ($showbirthday) -{ - // Add events in array - $sql = 'SELECT sp.rowid, sp.name, sp.firstname, sp.birthday'; - $sql.= ' FROM '.MAIN_DB_PREFIX.'socpeople as sp'; - $sql.= ' WHERE (priv=0 OR (priv=1 AND fk_user_creat='.$user->id.'))'; - $sql.= ' AND sp.entity = '.$conf->entity; - if ($action == 'show_day') - { - $sql.= ' AND MONTH(birthday) = '.$month; - $sql.= ' AND DAY(birthday) = '.$day; - } - else - { - $sql.= ' AND MONTH(birthday) = '.$month; - } - $sql.= ' ORDER BY birthday'; - dol_syslog("comm/action/index.php sql=".$sql, LOG_DEBUG); - $resql=$db->query($sql); - if ($resql) - { - $num = $db->num_rows($resql); - $i=0; - while ($i < $num) - { - $obj = $db->fetch_object($resql); - $event=new ActionComm($db); - $event->id=$obj->rowid; // We put contact id in action id for birthdays events - $datebirth=dol_stringtotime($obj->birthday); - //print 'ee'.$obj->birthday.'-'.$datebirth; - $datearray=dol_getdate($datebirth,true); - $event->datep=dol_mktime(0,0,0,$datearray['mon'],$datearray['mday'],$year); - $event->datef=$event->datep; - $event->type_code='BIRTHDAY'; - $event->libelle=$langs->trans("Birthday").' '.$obj->firstname.' '.$obj->name; - $event->percentage=100; - - $event->date_start_in_calendar=$event->datep; - $event->date_end_in_calendar=$event->datef; - $event->ponctuel=0; - - // Add an entry in actionarray for each day - $daycursor=$event->date_start_in_calendar; - $annee = date('Y',$daycursor); - $mois = date('m',$daycursor); - $jour = date('d',$daycursor); - - $loop=true; - $daykey=dol_mktime(0,0,0,$mois,$jour,$annee); - do - { - $eventarray[$daykey][]=$event; - $daykey+=60*60*24; - if ($daykey > $event->date_end_in_calendar) $loop=false; - } - while ($loop); - $i++; - } - } - else - { - dol_print_error($db); - } -} +// Inserting tabs -$maxlength=16; -$cachethirdparties=array(); -$cachecontacts=array(); - -// Define theme_datacolor array -$color_file = DOL_DOCUMENT_ROOT."/theme/".$conf->theme."/graph-color.php"; -if (is_readable($color_file)) -{ - include_once($color_file); -} -if (! is_array($theme_datacolor)) $theme_datacolor=array(array(120,130,150), array(200,160,180), array(190,190,220)); +$HTML[] = << + $(function() { + $( "#tabs" ).tabs(); + }); + +JS; -// Add link to show birthdays -$newparam=$param; // newparam is for birthday links -$newparam=preg_replace('/showbirthday=[0-1]/i','showbirthday='.(empty($showbirthday)?1:0),$newparam); -if (! preg_match('/showbirthday=/i',$newparam)) $newparam.='&showbirthday=1'; -$link=''; -if (empty($showbirthday)) $link.=$langs->trans("AgendaShowBirthdayEvents"); -else $link.=$langs->trans("AgendaHideBirthdayEvents"); -$link.=''; -print_fiche_titre('',$link); - -if (empty($action) || $action == 'show_month') // View by month -{ - $newparam=$param; // newparam is for birthday links - $newparam=preg_replace('/action=show_month&?/i','',$newparam); - $newparam=preg_replace('/action=show_week&?/i','',$newparam); - $newparam=preg_replace('/day=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/month=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/year=[0-9]+&?/i','',$newparam); - echo ''; - echo ' '; - $i=0; - while ($i < 7) - { - echo ' \n"; - $i++; - } - echo " \n"; +// Is there an already selected tab? +if(isset($_GET['selectedTab'])): +$HTML[] = << + $(function() { + var param = '{$_GET['selectedTab']}'; + $('#tabs').tabs('select', param); + }); + +JS; - // In loops, tmpday contains day nb in current month (can be zero or negative for days of previous month) - //var_dump($eventarray); - //print $tmpday; - for($iter_week = 0; $iter_week < 6 ; $iter_week++) - { - echo " \n"; - for($iter_day = 0; $iter_day < 7; $iter_day++) - { - /* Show days before the beginning of the current month (previous month) */ - if($tmpday <= 0) - { - $style='cal_other_month'; - echo ' \n"; - } - /* Show days of the current month */ - elseif(($tmpday <= $max_day_in_month)) - { - $curtime = dol_mktime (0, 0, 0, $month, $tmpday, $year); - - if ($curtime < $now) - $style='cal_current_month'; - else if($curtime == $now) - $style='cal_today'; - else - $style='cal_current_month'; - - echo ' \n"; - } - /* Show days after the current month (next month) */ - else - { - $style='cal_other_month'; - echo ' \n"; - } - $tmpday++; - } - echo " \n"; - } - echo "
'.$langs->trans("Day".(($i+(isset($conf->global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1)) % 7))."
'; - show_day_events ($db, $max_day_in_prev_month + $tmpday, $prev_month, $prev_year, $month, $style, $eventarray, $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW, $maxlength, $newparam); - echo " '; - show_day_events($db, $tmpday, $month, $year, $month, $style, $eventarray, $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW, $maxlength, $newparam); - echo " '; - show_day_events($db, $tmpday - $max_day_in_month, $next_month, $next_year, $month, $style, $eventarray, $conf->global->AGENDA_MAX_EVENTS_DAY_VIEW, $maxlength, $newparam); - echo "
\n"; -} -elseif ($action == 'show_week') // View by week -{ - $newparam=$param; // newparam is for birthday links - $newparam=preg_replace('/action=show_month&?/i','',$newparam); - $newparam=preg_replace('/action=show_week&?/i','',$newparam); - $newparam=preg_replace('/day=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/month=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/year=[0-9]+&?/i','',$newparam); - echo ''; - echo ' '; - $i=0; - while ($i < 7) - { - echo ' \n"; - $i++; - } - echo " \n"; +endif; - // In loops, tmpday contains day nb in current month (can be zero or negative for days of previous month) - //var_dump($eventarray); - //print $tmpday; - echo " \n"; - for($iter_day = 0; $iter_day < 7; $iter_day++) - { - if(($tmpday <= $max_day_in_month)) - { - // Show days of the current week - $curtime = dol_mktime (0, 0, 0, $month, $tmpday, $year); - - if($curtime == $now) - $style='cal_today'; - else - $style='cal_current_month'; - - echo ' \n"; - } - else - { - $style='cal_current_month'; - echo ' \n"; - } - $tmpday++; - } - echo " \n"; - echo "
'.$langs->trans("Day".(($i+(isset($conf->global->MAIN_START_WEEK)?$conf->global->MAIN_START_WEEK:1)) % 7))."
'; - show_day_events($db, $tmpday, $month, $year, $month, $style, $eventarray, 0, $maxlength, $newparam, 1, 300); - echo " '; - show_day_events($db, $tmpday - $max_day_in_month, $next_month, $next_year, $month, $style, $eventarray, 0, $maxlength, $newparam, 1, 300); - echo "
\n"; -} -else // View by day -{ - $newparam=$param; // newparam is for birthday links - $newparam=preg_replace('/action=show_month&?/i','',$newparam); - $newparam=preg_replace('/action=show_week&?/i','',$newparam); - $newparam=preg_replace('/day=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/month=[0-9][0-9]&?/i','',$newparam); - $newparam=preg_replace('/year=[0-9]+&?/i','',$newparam); - // Code to show just one day - $style='cal_current_month'; - $timestamp=dol_mktime(12,0,0,$month,$day,$year); - $arraytimestamp=adodb_getdate(dol_mktime(12,0,0,$month,$day,$year)); - echo ''; - echo ' '; - echo ' \n"; - echo " \n"; - echo " \n"; - echo ' \n"; - echo " \n"; - echo '
'.$langs->trans("Day".$arraytimestamp['wday'])."
'; - show_day_events ($db, $day, $month, $year, $month, $style, $eventarray, 0, 80, $newparam, 1, 300); - echo "
'; -} +$selectedTab = (isset($_GET['selectedTab'])) ? "&selectedTab={$_GET['selectedTab']}" : ''; + $HTML[] = ""; + $HTML[] = ""; -$db->close(); -llxFooter('$Date: 2011/04/17 22:57:12 $ - $Revision: 1.160 $'); -/** - * Show event of a particular day - * @param $db Database handler - * @param $day Day - * @param $month Month - * @param $year Year - * @param $monthshown Current month shown in calendar view - * @param $style Style to use for this day - * @param $eventarray Array of events - * @param $maxPrint Nb of actions to show each day on month view (0 means non limit) - * @param $maxnbofchar Nb of characters to show for event line - * @param $newparam Parameters on current URL - * @param $showinfo Add extended information (used by day view) - * @param $minheight Minimum height for each event. 60px by default. - */ -function show_day_events($db, $day, $month, $year, $monthshown, $style, &$eventarray, $maxPrint=0, $maxnbofchar=14, $newparam='', $showinfo=0, $minheight=60) -{ - global $user, $conf, $langs; - global $filter, $filtera, $filtert, $filterd, $status; - global $theme_datacolor; - global $cachethirdparties, $cachecontacts; - - if ($_GET["maxprint"] == 'on') $maxPrint=0; // Force to remove limits - - $curtime = dol_mktime (0, 0, 0, $month, $day, $year); - print ''; - print ''; - print ''; - print '
'; - print ''; - if ($showinfo) print dol_print_date($curtime,'daytext'); - else print dol_print_date($curtime,'%d'); - print ''; - print ''; - if ($user->rights->agenda->myactions->create || $user->rights->agenda->allactions->create) - { - //$param='month='.$monthshown.'&year='.$year; - $hourminsec='100000'; - print ''; - print img_picto($langs->trans("NewAction"),'edit_add.png'); - print ''; - } - print '
'; - //$curtime = dol_mktime (0, 0, 0, $month, $day, $year); - $i=0; - foreach ($eventarray as $daykey => $notused) - { - $annee = date('Y',$daykey); - $mois = date('m',$daykey); - $jour = date('d',$daykey); - if ($day==$jour && $month==$mois && $year==$annee) - { - foreach ($eventarray[$daykey] as $index => $event) - { - if ($i < $maxPrint || $maxPrint == 0) - { - $ponct=($event->date_start_in_calendar == $event->date_end_in_calendar); - // Show rect of event - $colorindex=0; - if ($event->author->id == $user->id || $event->usertodo->id == $user->id || $event->userdone->id == $user->id) $colorindex=1; - if ($event->type_code == 'BIRTHDAY') $colorindex=2; - $color=sprintf("%02x%02x%02x",$theme_datacolor[$colorindex][0],$theme_datacolor[$colorindex][1],$theme_datacolor[$colorindex][2]); - //print "x".$color; - print ''; - print ''; - // Status - Percent - print '
'; - if ($event->type_code != 'BIRTHDAY') - { - if ($showinfo) - { - print $event->getNomUrl(2).' '; - } - - if (empty($event->fulldayevent)) - { - // Show hours (start ... end) - $tmpyearstart = date('Y',$event->date_start_in_calendar); - $tmpmonthstart = date('m',$event->date_start_in_calendar); - $tmpdaystart = date('d',$event->date_start_in_calendar); - $tmpyearend = date('Y',$event->date_end_in_calendar); - $tmpmonthend = date('m',$event->date_end_in_calendar); - $tmpdayend = date('d',$event->date_end_in_calendar); - // Hour start - if ($tmpyearstart == $annee && $tmpmonthstart == $mois && $tmpdaystart == $jour) - { - print dol_print_date($event->date_start_in_calendar,'%H:%M'); - if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) - { - if ($tmpyearstart == $tmpyearend && $tmpmonthstart == $tmpmonthend && $tmpdaystart == $tmpdayend) - print '-'; - //else - //print '...'; - } - } - if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) - { - if ($tmpyearstart != $tmpyearend || $tmpmonthstart != $tmpmonthend || $tmpdaystart != $tmpdayend) - { - print '...'; - } - } - // Hour end - if ($event->date_end_in_calendar && $event->date_start_in_calendar != $event->date_end_in_calendar) - { - if ($tmpyearend == $annee && $tmpmonthend == $mois && $tmpdayend == $jour) - print dol_print_date($event->date_end_in_calendar,'%H:%M'); - } - print '
'."\n"; - } - else - { - if ($showinfo) - { - print $langs->trans("EventOnFullDay").'
'."\n"; - } - } - - // If action related to company / contact - $linerelatedto='';$length=16; - if (! empty($event->societe->id) && ! empty($event->contact->id)) $length=round($length/2); - if (! empty($event->societe->id) && $event->societe->id > 0) - { - if (! is_object($cachethirdparties[$event->societe->id])) - { - $thirdparty=new Societe($db); - $thirdparty->fetch($event->societe->id); - $cachethirdparties[$event->societe->id]=$thirdparty; - } - else $thirdparty=$cachethirdparties[$event->societe->id]; - $linerelatedto.=$thirdparty->getNomUrl(1,'',$length); - } - if (! empty($event->contact->id) && $event->contact->id > 0) - { - if (! is_object($cachecontacts[$event->contact->id])) - { - $contact=new Contact($db); - $contact->fetch($event->contact->id); - $cachecontacts[$event->contact->id]=$contact; - } - else $contact=$cachecontacts[$event->contact->id]; - if ($linerelatedto) $linerelatedto.=' / '; - $linerelatedto.=$contact->getNomUrl(1,'',$length); - } - if ($linerelatedto) print $linerelatedto.'
'; - - // Show label - print $event->getNomUrl(0,$maxnbofchar,'cal_event'); - } - else // It's a birthday - { - print $event->getNomUrl(1,$maxnbofchar,'cal_event','birthday','contact'); - } - // Show location - if ($showinfo) - { - if ($event->location) - { - print '
'; - print $langs->trans("Location").': '.$event->location; - } - } - print '
'; - if ($event->type_code != 'BIRTHDAY') print $event->getLibStatut(3,1); - else print ' '; - print '
'; - $i++; +$HTML[] = << +function Sp_toggle(myDiv,img,toShowHide){ + + + if($('#'+img).attr('class') == "up"){ + $('#'+myDiv).animate({ + height: 'toggle', + height: 15 + }, function(){ + $('#'+toShowHide+"_form").hide(); + $('#'+toShowHide+"_export").show(); + $('#'+img).attr('src',"{$url}/{$path}/img/1downarrow.png"); + $('#'+img).attr('class',"down"); } - else - { - print ''.img_picto("all","1downarrow_selected.png").' ...'; - print ' +'.(sizeof($eventarray[$daykey])-$maxPrint); - print ''; - break; - //$ok=false; // To avoid to show twice the link + ); + }else{ + $('#'+myDiv).animate({ + height: 'toggle', + height: 150 + }, function(){ + $('#'+toShowHide+"_form").show(); + $('#'+toShowHide+"_export").hide(); + $('#'+img).attr('src',"{$url}/{$path}/img/1uparrow.png"); + $('#'+img).attr('class',"up"); } - } - break; - } + ); + + } - if (! $i) print ' '; - print '
'; + } + + +JS; + + + + + + +foreach($conf->agendas_modules as $ag_path => $ag_classes): + foreach($ag_classes as $ag_filename) + require_once DOL_DOCUMENT_ROOT."/{$ag_path}/class/".strtolower($ag_filename).".class.php"; + +endforeach; + + +$Sp_agendas = new stdclass; +$Sp_agendas->agendas = array(); + +foreach($conf->agendas_modules as $ag_path => $ag_classes): + foreach($ag_classes as $ag_filename) + $Sp_agendas->agendas[strtolower($ag_filename)] = new $ag_filename($db); +endforeach; + +$tabsTitles = ""; +foreach($Sp_agendas->agendas as $ag_name => $ag_class) + $tabsTitles .= "
  • {$ag_class->getTitle()}
  • \r\n"; + +$HTML[] = << +
      + {$tabsTitles} +
    +HTML; + + + + + + + +$tabs = ""; +foreach($Sp_agendas->agendas as $ag_name => $ag_class): + $tabs .= << +
    + + +
    + {$ag_class->getLabel()} + {$ag_class->getForm($_GET,$_POST)} +
    + +
    + +
    +
    + +HTML; + +endforeach; + + + +$HTML[] = $tabs; + +foreach($Sp_agendas->agendas as $ag_name => $ag_class): +$fieldsGetter = ''; +foreach($ag_class->getFormItems() as $name => $type): + $function = "get".ucfirst(strtolower($name))."()"; + $fieldsGetter .= <<getxCalLink('ical'); + +// vCal Link +$vcal = $ag_class->getxCalLink('vcal'); + + +// Rss Link +$rss = $ag_class->getxCalLink('rss'); + + + +//Le lien d'accès aux calendrier iCal & RSS doivent être fait après l'enregistrement des fonctions! +$HTML[] = << +$("#{$ag_name}_rss_link").attr('href',"{$rss}"); +$("#{$ag_name}_ical_link").attr('href',"{$ical}"); +$("#{$ag_name}_vcal_link").attr('href',"{$vcal}"); + +JS; + +endforeach; + + +foreach($HTML as $output) + echo $output; + + + + + + + + + + + ?> diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/core/class/commonagenda.class.php dolibarr-svn/htdocs/core/class/commonagenda.class.php --- dolibarr-snapshot/htdocs/core/class/commonagenda.class.php 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/core/class/commonagenda.class.php 2011-04-15 15:35:33.000000000 +0200 @@ -0,0 +1,677 @@ + + * Copyright (C) 2005-2010 Regis Houssin + * Copyright (C) 2010 Juanjo Menent + * Copyright (C) 2011 Anthony Hebert + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/core/class/commonagenda.class.php + * \ingroup core + * \brief Fichier de la classe mere des classes Agenda (Agenda, temps consommés, ...) + * \version $Id: commonobject.class.php,v 1.87.2.3 2011/04/07 12:55:00 SphynXz Exp $ + */ + + +/** + * \class CommonAgenda + * \brief Classe mere pour heritage des classes Agenda + */ + +class CommonAgenda +{ + var $db; + + // Nombre de seconde à ajouter ou soustraire pour être GMT? + var $offset = 3600; + + // Pays ou calendrier assujetti à l'heure d'été? + var $summertime = 1; + + + + + /** + * Constructeur de la classe + * @param DB Handler acces base de donnees + */ + function CommonAgenda($DB) + { + $this->db = $DB; + } + + + /** + * Accesseur des évènements à mettre dans l'agenda + * @param $start Timestamp de début + * @param $end Timestamp de fin + * @param $options Array stockage de paramètre à utiliser au besoin. + * @return $events Events encodés en Json + */ + function getEvents($start,$end,$options = array()) + { + global $conf,$langs,$user; + + $events = array(array()); + + + return $events; + } + + /** + * Accesseur d'un évènements à mettre dans l'agenda + * @param $start Timestamp de début + * @param $end Timestamp de fin + * @param $options Array stockage de paramètre à utiliser au besoin. + * @return $events Events encodés en Json + */ + function getEvent($id,$options = array()) + { + global $conf,$langs,$user; + + $event = array(); + + + return $event; + } + + /** + * Editeur d'un évènement à modifier + * @param $id id de l'event + * @param $start Timestamp de début (Attention, peut être de 13 caractères! à tronquer si nécéssaire. Peut-être également NULL si le début n'est pas à modifier!) + * @param $end Timestamp de fin (Attention, peut être de 13 caractères! à tronquer si nécéssaire. Peut-être également NULL si la fin n'est pas à modifier!) + * @param $options Array stockage de paramètres à utiliser au besoin + * @return $event Event encodé en Json + */ + function editEvent($id,$start,$end,$options = array()) + { + global $conf,$langs,$user; + + + + //The TS may be of 13 digits, so truncate it! + if(strlen($start) == 13): + $start = substr($start,0,10); + endif; + + if(strlen($end) == 13): + $end = substr($end,0,10); + endif; + + //Making the event + $event = array(array()); + + + return $event; + + } + + /** + * Accesseur de la structure des champs du formulaire + * Tous les champs affichés par getForm doivent être spécifié + * et typé ici! + * + * @return $form tableau structuré des champs + */ + function getFormItems() + { + + return array(); + } + + /** + * Accesseur d'un formulaire à mettre en en-tête de l'agenda + * @param $get $_GET data + * @param $post $_POST data + * @return $form code html + */ + function getForm($get = array(),$post = array()) + { + global $conf,$langs,$user; + + + $form = "Ici sera affiché votre formulaire"; + + return $form; + } + + /** + * Exporteur du calendrier au format désiré + * @see http://tools.ietf.org/html/rfc5545 + * @param $format peut-être de type ical,vcal ou rss + * @param $options tableau de filtre (en réalité, $_GET) + * @return $iCal calendrier au format désiré + */ + function exportInxCal($format,$options = array()) + { + global $user,$conf,$langs; + //Check Config + if (! isset($conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY)) $conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY=100; + $filters['notolderthan']=$conf->global->MAIN_AGENDA_EXPORT_PAST_DELAY; + + + //Check Export Key + $this->checkExportKey($options['exportkey']); + + //set filename + $filename = $this->setFileName($format,$options); + + //Cache Delay + $cachedelay=0; + if (! empty($conf->global->MAIN_AGENDA_EXPORT_CACHE)) $cachedelay=$conf->global->MAIN_AGENDA_EXPORT_CACHE; + + switch($format) + { + + case 'vcal': + case 'ical': + $result = $this->build_exportfile($format,$cachedelay,$filename,$options); + if ($result >= 0) + { + + $attachment = true; + if (isset($options["attachment"])) $attachment=$options["attachment"]; + //$attachment = false; + $contenttype='text/calendar'; + if (isset($options["contenttype"])) $contenttype=$options["contenttype"]; + //$contenttype='text/plain'; + $outputencoding='UTF-8'; + + if ($contenttype) header('Content-Type: '.$contenttype.($outputencoding?'; charset='.$outputencoding:'')); + if ($attachment) header('Content-Disposition: attachment; filename="'.$filename.'"'); + + // Ajout directives pour resoudre bug IE + //header('Cache-Control: Public, must-revalidate'); + //header('Pragma: public'); + + // Clean parameters + $outputfile=$conf->agenda->dir_temp.'/'.$filename; + $result=readfile($outputfile); + if (! $result) print 'File '.$outputfile.' was empty.'; + + // header("Location: ".DOL_URL_ROOT.'/document.php?modulepart=agenda&file='.urlencode($filename)); + exit; + } + break; + + case 'rss': + $result = $this->build_exportfile($format,$cachedelay,$filename,$options); + + if ($result >= 0) + { + $attachment = true; + if (isset($options["attachment"])) $attachment=$options["attachment"]; + //$attachment = false; + $contenttype='application/rss+xml'; + if (isset($options["contenttype"])) $contenttype=$options["contenttype"]; + //$contenttype='text/plain'; + $outputencoding='UTF-8'; + + if ($contenttype) header('Content-Type: '.$contenttype.($outputencoding?'; charset='.$outputencoding:'')); + if ($attachment) header('Content-Disposition: attachment; filename="'.$filename.'"'); + + // Ajout directives pour resoudre bug IE + //header('Cache-Control: Public, must-revalidate'); + //header('Pragma: public'); + + // Clean parameters + $outputfile=$conf->agenda->dir_temp.'/'.$filename; + $result=readfile($outputfile); + if (! $result) print 'File '.$outputfile.' was empty.'; + + // header("Location: ".DOL_URL_ROOT.'/document.php?modulepart=agenda&file='.urlencode($filename)); + exit; + } + break; + + + + } + + } + + /** + * Export events from database into a cal file. + * @param format 'vcal', 'ical/ics', 'rss' + * @param type 'event' or 'journal' + * @param cachedelay Do not rebuild file if date older than cachedelay seconds + * @param filename Force filename + * @param filters Array of filters + * @return int <0 if error, nb of events in new file if ok + */ + function build_exportfile($format,$cachedelay,$filename,$filters) + { + global $conf,$langs,$dolibarr_main_url_root,$mysoc; + + + require_once (DOL_DOCUMENT_ROOT ."/lib/xcal.lib.php"); + require_once (DOL_DOCUMENT_ROOT ."/lib/date.lib.php"); + + dol_syslog("ActionComm::build_exportfile Build export file format=".$format.", type=".$filters['type'].", cachedelay=".$cachedelay.", filename=".$filename.", filters size=".sizeof($filters), LOG_DEBUG); + + // Check parameters + if (empty($format)) return -1; + + // Create dir and define output file (definitive and temporary) + $result=create_exdir($conf->agenda->dir_temp); + $outputfile=$conf->agenda->dir_temp.'/'.$filename; + $outputfiletmp=tempnam($conf->agenda->dir_temp,'tmp'); // Temporary file (allow call of function by different threads + + $buildfile = true; + // Check cacheDelay + if ($cachedelay) + { + $nowgmt = dol_now(); + if (filemtime($outputfile) > ($nowgmt - $cachedelay)) + { + dol_syslog("ActionComm::build_exportfile file ".$outputfile." is not older than now - cachedelay (".$nowgmt." - ".$cachedelay."). Build is canceled"); + $buildfile = false; + } + } + $result = 0; + + //do we have to build the file? + if ($buildfile) + { + + $eventarray = $this->getEventsForExport($filters); + $title = $this->getTitleForExport($format,$filters); + $desc = $this->getDescForExport($format,$filters); + + + if(!$eventarray) + { + $this->error=$this->db->lasterror(); + dol_syslog("ActionComm::build_exportfile ".$this->db->lasterror(), LOG_ERR); + return -1; + } + + $langs->load("agenda"); + + + + // Write file + if ($format == 'vcal') $result=build_calfile($format,$title,$desc,$eventarray,$outputfiletmp); + if ($format == 'ical') $result=build_calfile($format,$title,$desc,$eventarray,$outputfiletmp); + if ($format == 'rss') $result=build_rssfile($format,$title,$desc,$eventarray,$outputfiletmp); + + if ($result >= 0) + { + unlink($outputfile); + if (rename($outputfiletmp,$outputfile)) $result=1; + else $result=-1; + } + + + } + + return $result; + + } + + + + function getTitleForExport($format,$options = array()) + { + global $conf,$user,$langs; + + } + + + function getDescForExport($format,$options = array()) + { + global $conf,$user,$langs; + + + } + + function setFileName($format,$options = array()) + { + // Define filename with prefix on filters predica (each predica set must have on cache file) + $shortfilename='dolibarrcalendar'; + $filename=$shortfilename; + // Complete long filename + + // Add extension + if ($format == 'vcal') { $shortfilename.='.vcs'; $filename.='.vcs'; } + if ($format == 'ical') { $shortfilename.='.ics'; $filename.='.ics'; } + if ($format == 'rss') { $shortfilename.='.rss'; $filename.='.rss'; } + + if ($shortfilename=='dolibarrcalendar') + { + $langs->load("main"); + $langs->load("errors"); + llxHeaderVierge(); + print '
    '.$langs->trans("ErrorWrongValueForParameterX",'format').'
    '; + llxFooterVierge('$Date: 2010/11/21 16:11:53 $ - $Revision: 1.17 $'); + exit; + } + + return $shortfilename; + + } + + + + function getEventsForExport($options = array()) + { + + /*Structure attendue + array( + + (int)timestamp => array( + 'uid' => string, // identifiant de l'évènement + 'type' => string, // type d'évènement (anniversaire..) + 'summary' => string, // titre + 'desc' => string, // description + 'startdate' => timestamp, // date de début + 'duration' => string, // nombre de secondes + 'enddate' => timestamp, // date de fin + 'author' => string, // auteur + 'priority' => int, // niveau de priorité + 'location' => string, // lieu + 'transparency' => string, // OPAQUE (busy) or TRANSPARENT (not busy) + 'category' => string, // same as type + 'url' => string, // url d'accès à l'évènement + 'created' => timestamp, // date de création + 'modified' => timestamp // date de dernière modification + + ) + ); + + + */ + + } + + /** + * Vérificateur de clé + * @see http://tools.ietf.org/html/rfc5545 + * @param $key clé donné dans le lien + * @return void + */ + function checkExportKey($key) + { + global $conf,$user,$langs; + + if (empty($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY)) + { + $user->getrights(); + + llxHeaderVierge(); + print '
    Module Agenda was not configured properly.
    '; + llxFooterVierge('$Date: 2010/11/21 16:11:53 $ - $Revision: 1.17 $'); + exit; + } + + + // Check exportkey + if (empty($key) || $conf->global->MAIN_AGENDA_XCAL_EXPORTKEY != $key) + { + $user->getrights(); + + llxHeaderVierge(); + print '
    Bad value for key.
    '; + llxFooterVierge('$Date: 2010/11/21 16:11:53 $ - $Revision: 1.17 $'); + exit; + } + + + } + + + + /** + * Générateur du lien public d'accès au calendrier + * @see http://tools.ietf.org/html/rfc5545 + * @todo Générer le lien + * @return $iCal calendrier au format iCal + */ + function getxCalLink($format = "ical") + { + global $conf; + + $url = DOL_URL_ROOT."/public/agenda/agendaexport.php?format={$format}&type=".get_class($this)."&exportkey=".($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY?urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY):'...'); + $url .= $this->getFormItemsForLink("&"); + + return $url; + } + + /** + * Fonction formatant les items du formulaire pour + * être exploité par les exporteurs RSS & ICAL + * @todo Générer le lien + * @return $url url formaté + */ + function getFormItemsForLink($first = "?"){ + foreach($this->getFormItems() as $name => $type): + $extraFields .= "{$first}{$name}=\"+get".ucfirst(strtolower($name))."()+\""; + endforeach; + return $extraFields; + } + + /** + * Accesseur du titre de l'agenda à mettre dans l'onglet + * @return $title Titre de l'agenda + */ + function getTitle() + { + global $conf,$user,$langs; + return ''; + } + + + /** + * Accesseur du label à afficher par print_fiche_titre() + * @return $label Label de l'agenda + */ + function getLabel() + { + /* + global $user,$langs,$conf; + ob_start(); + print_fiche_titre('Exemple'); + $label = ob_get_contents(); + ob_end_clean(); + */ + return ''; + } + + + /** + * Accesseur du lien permettant d'ajouter un évènement, ou d'en éditer un. + * Ce lien sera utilisé dans le cas ou un évènement n'est pas readonly (event['readonly'] = 0) + * le calendrier redirigera automatiquement vers ce lien, en y ajoutant les deux paramètres suivants : + * -datep date sous la forme d'une chaine (YYYYMMDDHHIISS) + * -datef date sous la forme d'une chaine (YYYYMMDDHHIISS) + * @param $action soit "create", soit "edit" + * @return $label Label de l'agenda + */ + function getLink($action = "create") + { + global $user,$langs,$conf; + + + return ''; + } + + /** + * Accesseur de l'offset permettant de connaître le nombre de seconde + * à ajouter pour être en GMT + * + * N.B : les timestamps (TS) ici peuvent provenir du jQuery Week Calendar, et dans ce cas + * ces TS prennent compte de l'offset et sont donc de 13 caractères, si c'est le cas, on + * ajoute non pas 3600 secondes, mais 36000! + * + * @param $ts timestamp de l'heure témoin pour calculer l'offset + * @return $offset nombre de seconde à ajouter ou soustraire + */ + function getOffset($ts) + { + $sec = (strlen($ts) == 13) ? 36000 : 3600; + return ($this->isSummerTime($ts)) ? $this->offset + $sec : $this->offset; + + } + + + + + /** + * Calcul si l'heure est une heure d'été ou non + * + * @param $ts timestamp de l'heure témoin pour calculer l'offset + * @see http://fr.wikipedia.org/wiki/Heure_d'%C3%A9t%C3%A9_d'Europe_centrale + * @return bool true ou false selon que l'heure soit d'été ou non + */ + function isSummerTime($ts) + { + global $user,$conf,$langs; + + if(!$this->summertime) + return false; + //être sûr que notre timestamp soit de 10 digits. + $ts = substr($ts,0,10); + + //Recupère le dernier dimanche + $initDay = (31 - ( floor(5 * $year / 4) + 4) % 7) ; + $endDay = (31 - ( floor(5 * $year / 4) + 1) % 7) ; + $initTime = strtotime("$initDay March $year"); + $endTime = strtotime("$initDay October $year"); + + return ($ts > $initTime && $ts < $endTime) ? true : false; + } + + + + + + /** + * Calcul si l'utilisateur peut créer un évènement + * @return bool true ou false + */ + function canCreate() + { + return true; + } + + /** + * Calcul si l'utilisateur peut modifier un évènement + * @return bool true ou false + */ + function canUpdate() + { + return true; + } + + /** + * Calcul si l'utilisateur peut supprimer un évènement + * @return bool true ou false + */ + function canDelete() + { + return true; + } + + + + /** + * Vérifie si un évènement est sur plusieurs jours + * @param array Actions + * @return array Actions + */ + function isMultiDayTask($event){ + $diff = substr($event['eventend'],0,10) - substr($event['eventstart'],0,10); + $i = ceil($diff / 60 / 60 / 24); + + + $timeToMidnight = 24 - (date('H',substr($event['eventstart'],0,10) - (int)date('s',substr($event['eventstart'],0,10)) - ((int)date('i',substr($event['eventstart'],0,10)) * 60))); + + + return ($i>= 1 and ($diff/ 60 / 60) > $timeToMidnight) ? true : false; + } + + /** + * Split an action into x action if multiple day + * @param array Actions + * @return array Actions + */ + function checkMultiDayTasks($data){ + + $extraData = array(); + $i = count($data); + if(is_array($data)): + + foreach($data as $key => $event): + $diff = substr($event['eventend'],0,10) - substr($event['eventstart'],0,10); + $numberOfDays = ceil($diff / 60 / 60 / 24); + + + + + + if($this->isMultiDayTask($event)): + + //We save the real end to apply it on the last day. + $backup_end = (string)substr($data[$key]['eventend'],0,10); + + //We change the end of the original event to the start time with 23:59 h + $timeToMidnight = 24 - date('H',substr($event['eventstart'],0,10) - (int)date('s',substr($event['eventstart'],0,10)) - ((int)date('i',substr($event['eventstart'],0,10)) * 60)); + + + $data[$key]['eventend'] = substr($event['eventstart'],0,10) + ($timeToMidnight * 60 * 60) - (int)date('s',substr($event['eventstart'],0,10)) - ((int)date('i',substr($event['eventstart'],0,10)) * 60) - $this->getOffset(substr($event['eventstart'],0,10)); + + + //The deal is to make the first event draggable, and the last event resizable, between : unchangable! + $data[$key]['resizable'] = 0; + $data[$key]['multiday'] = 1; + + //The base start and end will help the split the event into x event. + $base_start = mktime('00','00','00',date('n',substr($event['eventstart'],0,10)),date('j',substr($event['eventstart'],0,10)),date('Y',substr($event['eventstart'],0,10))) - $this->getOffset(substr($event['eventstart'],0,10)); + $base_end = mktime('24','00','00',date('n',substr($event['eventstart'],0,10)),date('j',substr($event['eventstart'],0,10)),date('Y',substr($event['eventstart'],0,10))) - $this->getOffset(substr($event['eventstart'],0,10)); + + + //echo $base_end; + $x = 1; + + while($x <= $numberOfDays): + $extraData[$i] = $data[$key]; + $extraData[$i]['eventstart'] = $base_start + ((24 * 60 * 60) * ($x)); + + if($x < $numberOfDays): + $extraData[$i]['eventend'] = $base_end + ((24 * 60 * 60) * ($x)); + $extraData[$i]['draggable'] = 0; + $extraData[$i]['resizable'] = 0; + else: + $extraData[$i]['eventend'] = $backup_end; + $extraData[$i]['draggable'] = 0; + $extraData[$i]['resizable'] = ($data[$key]['readonly']) ? 0 : 1; + endif; + $i++; + $x++; + endwhile; + endif; + endforeach; + + return array_merge($data,$extraData); + else: + return array(); + endif; +} + +} + +?> diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/core/class/conf.class.php dolibarr-svn/htdocs/core/class/conf.class.php --- dolibarr-snapshot/htdocs/core/class/conf.class.php 2011-04-19 05:00:31.000000000 +0200 +++ dolibarr-svn/htdocs/core/class/conf.class.php 2011-04-20 10:01:30.000000000 +0200 @@ -4,6 +4,7 @@ * Copyright (C) 2004-2011 Laurent Destailleur * Copyright (C) 2005-2010 Regis Houssin * Copyright (C) 2006 Jean Heimburger + * Copyright (C) 2011 Anthony Hebert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -61,6 +62,7 @@ var $hooks_modules = array(); var $login_method_modules = array(); var $need_smarty = array(); + var $agendas_modules = array(); var $modules = array(); var $entities = array(); @@ -139,6 +141,19 @@ $this->tabs_modules[$params[0]][]=$value; //print 'xxx'.$params[0].'-'.$value; } + // If this is constant for a new Agenda tab activated by a module + elseif (preg_match('/^MAIN_MODULE_([A-Z_]+)_AGENDAS_/i',$key,$match)) + { + $param = explode(':',$value); + $value = $param[count($param) - 1]; + unset($param[count($param) - 1]); + foreach($param as &$path) + $path = strtolower($path); + + $param = implode('/',$param); + $this->agendas_modules[$param][]= $value; + //print 'xxx'.$params[0].'-'.$value; + } // If this is constant for triggers activated by a module elseif (preg_match('/^MAIN_MODULE_([A-Z_]+)_TRIGGERS$/i',$key,$reg)) { diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.css dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.css --- dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.css 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.css 2011-04-08 12:01:35.000000000 +0200 @@ -0,0 +1,195 @@ + + +.wc-container { + font-size: 14px; + font-family: arial, helvetica; +} + +.wc-nav { + padding: 1em; + text-align: right; +} + +.wc-nav button { + margin: 0 0.5em; +} + + +.wc-container table { + border-collapse: collapse; + border-spacing: 0; +} +.wc-container table td { + margin: 0; + padding: 0; +} + +.wc-header { + background: #eee; + border-top: 1px solid #aaa; + border-bottom: 1px solid #aaa; + width: 100%; +} + +.wc-header .wc-time-column-header { + width: 6%; +} + +.wc-header .wc-scrollbar-shim { + width: 16px; +} + +.wc-header .wc-day-column-header { + text-align: center; + padding: 0.4em; +} +.wc-header td { + background: url(../img/header-bg.png) repeat-x; +} + +.wc-grid-timeslot-header { + width: 6%; + background: #eee; +} + + + +.wc-scrollable-grid { + overflow: auto; + overflow-x: hidden !important; + overflow-y: auto !important; + position: relative; + background-color: #fff; + width: 100%; +} + + +table.wc-time-slots { + width: 100%; + table-layout: fixed; + cursor: default; +} + +.wc-day-column { + width: 13.5%; + border-left: 1px solid #ddd; + overflow: visible; + vertical-align: top; +} + +.wc-day-column-inner { + width: 100%; + position:relative; +} + +.wc-time-slot-wrapper { + position:relative; + height: 1px; + top: 1px; +} + +.wc-time-slots { + position: absolute; + width: 100%; +} + + +.wc-time-header-cell { + padding: 5px; + height: 80px; /* reference height */ +} + + +.wc-time-slot { + border-bottom: 1px dotted #ddd; +} + +.wc-hour-header { + text-align: right; +} + +.wc-hour-end, .wc-hour-header { + border-bottom: 1px solid #ccc; + color: #555; +} + +.wc-business-hours { + background-color: #E6EEF1; + border-bottom: 1px solid #ccc; + color: #333; + font-size: 1.4em; +} + +.wc-business-hours .wc-am-pm { + font-size: 0.6em; +} + +.wc-day-header-cell { + text-align: center; + vertical-align: middle; + padding: 5px; +} + + + +.wc-time-slot-header .wc-header-cell { + text-align: right; + padding-right: 10px; +} + +.wc-header .wc-today { + font-weight: bold; +} + +.wc-time-slots .wc-today { + background-color: #ffffcc; +} + + +.wc-cal-event { + background-color: #68a1e5; + filter:alpha(opacity=80); + -moz-opacity:0.8; + -khtml-opacity: 0.8; + opacity: 0.8; + position: absolute; + text-align: center; + overflow: hidden; + cursor: pointer; + color: #fff; + width: 100%; + display: none; +} + + +.wc-cal-event div { + padding: 0 5px; + +} + +.wc-cal-event .wc-time { + background-color: #2b72d0; + border: 1px solid #1b62c0; + color: #fff; + padding: 0; + font-weight: bold; +} + +.wc-container .ui-draggable .wc-time { + cursor: move; +} + +.wc-cal-event .wc-title { + position: relative; +} + +.wc-container .ui-resizable-s { + height: 10px; + bottom: -8px; +} + + +.wc-container .ui-draggable-dragging { + z-index: 1000; +} + diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.js.php dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.js.php --- dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.js.php 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/jquery.weekcalendar.js.php 2011-04-08 10:30:18.000000000 +0200 @@ -0,0 +1,1552 @@ +load('commercial'); + + $JS[] = <<trans('To')} ", + startParam : "start", + endParam : "end", + businessHours : {start: 8, end: 18, limitDisplay : false}, + newEventText : "{$langs->trans('NewAction')}", + timeslotHeight: 20, + defaultEventLength : 2, + timeslotsPerHour : 4, + buttons : true, + buttonText : { + today : "{$langs->trans('Today')}", + lastWeek : " << ", + nextWeek : " >> ", + nextDay : " > ", + prevDay : " < " + }, + scrollToHourMillis : 500, + allowCalEventOverlap : false, + overlapEventsSeparate: false, + readonly: false, + draggable : function(calEvent, element) { + if(calEvent.draggable) + return true; + }, + resizable : function(calEvent, element) { + if(calEvent.resizable) + return true; + }, + eventClick : function() { + }, + eventRender : function(calEvent, element) { + return element; + }, + eventAfterRender : function(calEvent, element) { + return element; + }, + eventDrag : function(calEvent, element) { + }, + eventDrop : function(calEvent, element) { + }, + eventResize : function(calEvent, element) { + }, + eventNew : function(calEvent, element) { + }, + eventMouseover : function(calEvent, \$event) { + }, + eventMouseout : function(calEvent, \$event) { + }, + calendarBeforeLoad : function(calendar) { + }, + calendarAfterLoad : function(calendar) { + }, + noEvents : function() { + }, + shortMonths : ['{$langs->trans('MonthShort01')}', '{$langs->trans('MonthShort02')}', '{$langs->trans('MonthShort03')}', '{$langs->trans('MonthShort04')}', '{$langs->trans('MonthShort05')}', '{$langs->trans('MonthShort06')}', '{$langs->trans('MonthShort07')}', '{$langs->trans('MonthShort08')}', '{$langs->trans('MonthShort09')}', '{$langs->trans('MonthShort10')}', '{$langs->trans('MonthShort11')}', '{$langs->trans('MonthShort12')}'], + longMonths : ['{$langs->trans('January')}', '{$langs->trans('February')}', '{$langs->trans('March')}', '{$langs->trans('April')}', '{$langs->trans('May')}', '{$langs->trans('June')}', '{$langs->trans('July')}', '{$langs->trans('August')}', '{$langs->trans('September')}', '{$langs->trans('October')}', '{$langs->trans('November')}', '{$langs->trans('December')}'], + shortDays : ['{$langs->trans('ShortSunday')}', '{$langs->trans('ShortMonday')}', '{$langs->trans('ShortTuesday')}', '{$langs->trans('ShortWednesday')}', '{$langs->trans('ShortThursday')}', '{$langs->trans('ShortFriday')}', '{$langs->trans('ShortSaturday')}'], + longDays : ['{$langs->trans('Day0')}', '{$langs->trans('Day1')}', '{$langs->trans('Day2')}', '{$langs->trans('Day3')}', '{$langs->trans('Day4')}', '{$langs->trans('Day5')}', '{$langs->trans('Day6')}'] + }, + + /*********************** + * Initialise calendar * + ***********************/ + _create : function() { + + var self = this; + self._computeOptions(); + self._setupEventDelegation(); + + self._renderCalendar(); + + self._loadCalEvents(); + + self._resizeCalendar(); + self._scrollToHour(self.options.date.getHours()); + + $(window).unbind("resize.weekcalendar"); + $(window).bind("resize.weekcalendar", function() { + self._resizeCalendar(); + }); + + }, + + + /******************** + * public functions * + ********************/ + /* + * Refresh the events for the currently displayed week. + */ + refresh : function() { + this._loadCalEvents(this.element.data("startDate")); //reload with existing week + }, + + /* + * Clear all events currently loaded into the calendar + */ + clear : function() { + this._clearCalendar(); + }, + + /* + * Go to this week + */ + today : function() { + this._clearCalendar(); + this._loadCalEvents(new Date()); + }, + + /* + * Go to the previous week relative to the currently displayed week + */ + prevWeek : function() { + //minus more than 1 day to be sure we're in previous week - account for daylight savings or other anomolies + var newDate = new Date(this.element.data("startDate").getTime() - (MILLIS_IN_WEEK / 6)); + this._clearCalendar(); + this._loadCalEvents(newDate); + }, + + /* + * Go to the previous day relative to the currently displayed week + */ + prevDay : function() { + //minus more than 1 day to be sure we're in previous week - account for daylight savings or other anomolies + var newDate = new Date(this.element.data("startDate").getTime() - 86400000); //JRi: minus one day + this._clearCalendar(); + + + this.options.firstDayOfWeek = (this.options.firstDayOfWeek == 0) ? 6 : this.options.firstDayOfWeek - 1; + + this._loadCalEvents(newDate); + }, + + /* + * Go to the next week relative to the currently displayed week + */ + nextWeek : function() { + //add 8 days to be sure of being in prev week - allows for daylight savings or other anomolies + var newDate = new Date(this.element.data("startDate").getTime() + MILLIS_IN_WEEK + (MILLIS_IN_WEEK / 7)); + this._clearCalendar(); + this._loadCalEvents(newDate); + }, + + /* + * Go to the next day relative to the currently displayed week + */ + nextDay : function() { + var newDate = new Date(this.element.data("startDate").getTime() + 86400000); //JRi: plus one day + this.options.firstDayOfWeek = (this.options.firstDayOfWeek == 6) ? 0 : this.options.firstDayOfWeek + 1; + this._clearCalendar(); + this._loadCalEvents(newDate); + }, + + /* + * Reload the calendar to whatever week the date passed in falls on. + */ + gotoWeek : function(date) { + this._clearCalendar(); + this._loadCalEvents(date); + }, + + /* + * Remove an event based on it's id + */ + removeEvent : function(eventId) { + + var self = this; + + self.element.find(".wc-cal-event").each(function() { + if ($(this).data("calEvent").id === eventId) { + $(this).remove(); + return false; + } + }); + + //this could be more efficient rather than running on all days regardless... + self.element.find(".wc-day-column-inner").each(function() { + self._adjustOverlappingEvents($(this)); + }); + }, + + /* + * Removes any events that have been added but not yet saved (have no id). + * This is useful to call after adding a freshly saved new event. + */ + removeUnsavedEvents : function() { + + var self = this; + + self.element.find(".wc-new-cal-event").each(function() { + $(this).remove(); + }); + + //this could be more efficient rather than running on all days regardless... + self.element.find(".wc-day-column-inner").each(function() { + self._adjustOverlappingEvents($(this)); + }); + }, + + /* + * update an event in the calendar. If the event exists it refreshes + * it's rendering. If it's a new event that does not exist in the calendar + * it will be added. + */ + updateEvent : function (calEvent) { + this._updateEventInCalendar(calEvent); + }, + + /* + * Returns an array of timeslot start and end times based on + * the configured grid of the calendar. Returns in both date and + * formatted time based on the 'timeFormat' config option. + */ + getTimeslotTimes : function(date) { + var options = this.options; + var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0; + var startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate(), firstHourDisplayed); + + var times = [] + var startMillis = startDate.getTime(); + for (var i = 0; i < options.timeslotsPerDay; i++) { + var endMillis = startMillis + options.millisPerTimeslot; + times[i] = { + start: new Date(startMillis), + startFormatted: this._formatDate(new Date(startMillis), options.timeFormat), + end: new Date(endMillis), + endFormatted: this._formatDate(new Date(endMillis), options.timeFormat) + }; + startMillis = endMillis; + } + return times; + }, + + formatDate : function(date, format) { + if (format) { + return this._formatDate(date, format); + } else { + return this._formatDate(date, this.options.dateFormat); + } + }, + + formatTime : function(date, format) { + if (format) { + return this._formatDate(date, format); + } else { + return this._formatDate(date, this.options.timeFormat); + } + }, + + + + + +/* + getData : function(key) { + return this._getData(key); + }, + */ + + /********************* + * private functions * + *********************/ + + + _setOption: function(key, value) { + var self = this; + if(self.options[key] != value) { + + // this could be made more efficient at some stage by caching the + // events array locally in a store but this should be done in conjunction + // with a proper binding model. + + var currentEvents = $.map(self.element.find(".wc-cal-event"), function() { + return $(this).data("calEvent"); + }); + + var newOptions = {}; + newOptions[key] = value; + self._renderEvents({events:currentEvents, options: newOptions}, self.element.find(".wc-day-column-inner")) + } + + }, + + + // compute dynamic options based on other config values + _computeOptions : function() { + + var options = this.options; + + if (options.businessHours.limitDisplay) { + options.timeslotsPerDay = options.timeslotsPerHour * (options.businessHours.end - options.businessHours.start); + options.millisToDisplay = (options.businessHours.end - options.businessHours.start) * 60 * 60 * 1000; + options.millisPerTimeslot = options.millisToDisplay / options.timeslotsPerDay; + } else { + options.timeslotsPerDay = options.timeslotsPerHour * 24; + options.millisToDisplay = MILLIS_IN_DAY; + options.millisPerTimeslot = MILLIS_IN_DAY / options.timeslotsPerDay; + } + }, + + /* + * Resize the calendar scrollable height based on the provided function in options. + */ + _resizeCalendar : function () { + + var options = this.options; + if (options && $.isFunction(options.height)) { + var calendarHeight = options.height(this.element); + var headerHeight = this.element.find(".wc-header").outerHeight(); + var navHeight = this.element.find(".wc-nav").outerHeight(); + this.element.find(".wc-scrollable-grid").height(calendarHeight - navHeight - headerHeight); + } + }, + + /* + * configure calendar interaction events that are able to use event + * delegation for greater efficiency + */ + _setupEventDelegation : function() { + var self = this; + var options = this.options; + this.element.click(function(event) { + var \$target = $(event.target); + if (\$target.data("preventClick")) { + return; + } + if (\$target.hasClass("wc-cal-event")) { + options.eventClick(\$target.data("calEvent"), \$target, event); + } else if (\$target.parent().hasClass("wc-cal-event")) { + options.eventClick(\$target.parent().data("calEvent"), \$target.parent(), event); + } + }).mouseover(function(event) { + var \$target = $(event.target); + + if (self._isDraggingOrResizing(\$target)) { + return; + } + + if (\$target.hasClass("wc-cal-event")) { + options.eventMouseover(\$target.data("calEvent"), \$target, event); + } + }).mouseout(function(event) { + var \$target = $(event.target); + if (self._isDraggingOrResizing(\$target)) { + return; + } + if (\$target.hasClass("wc-cal-event")) { + if (\$target.data("sizing")) return; + options.eventMouseout(\$target.data("calEvent"), \$target, event); + + } + }); + }, + + /* + * check if a ui draggable or resizable is currently being dragged or resized + */ + _isDraggingOrResizing : function (\$target) { + return \$target.hasClass("ui-draggable-dragging") || \$target.hasClass("ui-resizable-resizing"); + }, + + /* + * Render the main calendar layout + */ + _renderCalendar : function() { + + var \$calendarContainer, calendarNavHtml, calendarHeaderHtml, calendarBodyHtml, \$weekDayColumns; + var self = this; + var options = this.options; + + \$calendarContainer = $("
    ").appendTo(self.element); + + if (options.buttons) { + calendarNavHtml = ""; + + $(calendarNavHtml).appendTo(\$calendarContainer); + + \$calendarContainer.find(".wc-nav .wc-today").click(function() { + self.element.weekCalendarAction("today"); + return false; + }); + + + + + + \$calendarContainer.find(".wc-nav .wc-prev").click(function() { + self.element.weekCalendarAction("prevDay"); + return false; + }); + + \$calendarContainer.find(".wc-nav .wc-next").click(function() { + self.element.weekCalendarAction("nextDay"); + return false; + }); + + \$calendarContainer.find(".wc-nav .wc-prevprev").click(function() { + self.element.weekCalendarAction("prevWeek"); + return false; + }); + + \$calendarContainer.find(".wc-nav .wc-nextnext").click(function() { + self.element.weekCalendarAction("nextWeek"); + return false; + }); + + + + + + + + } + + //render calendar header + calendarHeaderHtml = ""; + for (var i = 1; i <= options.daysToShow; i++) { + calendarHeaderHtml += ""; + } + calendarHeaderHtml += "
    "; + + //render calendar body + calendarBodyHtml = "
    \ + \ + \ + \ + \ + "; + + for (var i = 1; i <= options.daysToShow; i++) { + calendarBodyHtml += "" + } + + calendarBodyHtml += "
    \ +
    \ +
    "; + + var start = options.businessHours.limitDisplay ? options.businessHours.start : 0; + var end = options.businessHours.limitDisplay ? options.businessHours.end : 24; + + for (var i = start; i < end; i++) { + for (var j = 0; j < options.timeslotsPerHour - 1; j++) { + calendarBodyHtml += "
    "; + } + calendarBodyHtml += "
    "; + } + + calendarBodyHtml += "
    "; + + for (var i = start; i < end; i++) { + + var bhClass = (options.businessHours.start <= i && options.businessHours.end > i) ? "wc-business-hours" : ""; + calendarBodyHtml += "
    " + if (options.use24Hour) { + calendarBodyHtml += "
    " + self._24HourForIndex(i) + "
    "; + } else { + calendarBodyHtml += "
    " + self._hourForIndex(i) + "" + self._amOrPm(i) + "
    "; + } + calendarBodyHtml += "
    "; + } + + calendarBodyHtml += "
    "; + + //append all calendar parts to container + $(calendarHeaderHtml + calendarBodyHtml).appendTo(\$calendarContainer); + + \$weekDayColumns = \$calendarContainer.find(".wc-day-column-inner"); + \$weekDayColumns.each(function(i, val) { + $(this).height(options.timeslotHeight * options.timeslotsPerDay); + if (!options.readonly) { + self._addDroppableToWeekDay($(this)); + self._setupEventCreationForWeekDay($(this)); + } + }); + + \$calendarContainer.find(".wc-time-slot").height(options.timeslotHeight - 1); //account for border + + \$calendarContainer.find(".wc-time-header-cell").css({ + height : (options.timeslotHeight * options.timeslotsPerHour) - 11, + padding: 5 + }); + + + }, + + /* + * setup mouse events for capturing new events + */ + _setupEventCreationForWeekDay : function(\$weekDay) { + var self = this; + var options = this.options; + \$weekDay.mousedown(function(event) { + var \$target = $(event.target); + if (\$target.hasClass("wc-day-column-inner")) { + + var \$newEvent = $("
    "); + + \$newEvent.css({lineHeight: (options.timeslotHeight - 2) + "px", fontSize: (options.timeslotHeight / 2) + "px"}); + \$target.append(\$newEvent); + + var columnOffset = \$target.offset().top; + var clickY = event.pageY - columnOffset; + var clickYRounded = (clickY - (clickY % options.timeslotHeight)) / options.timeslotHeight; + var topPosition = clickYRounded * options.timeslotHeight; + \$newEvent.css({top: topPosition}); + + \$target.bind("mousemove.newevent", function(event) { + \$newEvent.show(); + \$newEvent.addClass("ui-resizable-resizing"); + var height = Math.round(event.pageY - columnOffset - topPosition); + var remainder = height % options.timeslotHeight; + //snap to closest timeslot + if (remainder < (height / 2)) { + var useHeight = height - remainder; + \$newEvent.css("height", useHeight < options.timeslotHeight ? options.timeslotHeight : useHeight); + } else { + \$newEvent.css("height", height + (options.timeslotHeight - remainder)); + } + }).mouseup(function() { + \$target.unbind("mousemove.newevent"); + \$newEvent.addClass("ui-corner-all"); + }); + } + + }).mouseup(function(event) { + var \$target = $(event.target); + + var \$weekDay = \$target.closest(".wc-day-column-inner"); + var \$newEvent = \$weekDay.find(".wc-new-cal-event-creating"); + + if (\$newEvent.length) { + //if even created from a single click only, default height + if (!\$newEvent.hasClass("ui-resizable-resizing")) { + \$newEvent.css({height: options.timeslotHeight * options.defaultEventLength}).show(); + } + var top = parseInt(\$newEvent.css("top")); + var eventDuration = self._getEventDurationFromPositionedEventElement(\$weekDay, \$newEvent, top); + + \$newEvent.remove(); + var newCalEvent = {start: eventDuration.start, end: eventDuration.end, title: options.newEventText}; + var \$renderedCalEvent = self._renderEvent(newCalEvent, \$weekDay); + + if (!options.allowCalEventOverlap) { + self._adjustForEventCollisions(\$weekDay, \$renderedCalEvent, newCalEvent, newCalEvent); + self._positionEvent(\$weekDay, \$renderedCalEvent); + } else { + self._adjustOverlappingEvents(\$weekDay); + } + + options.eventNew(eventDuration, \$renderedCalEvent); + } + }); + }, + + /* + * load calendar events for the week based on the date provided + */ + _loadCalEvents : function(dateWithinWeek) { + + var date, weekStartDate, endDate, \$weekDayColumns; + var self = this; + + + + var options = this.options; + date = dateWithinWeek || options.date; + weekStartDate = self._dateFirstDayOfWeek(date); + + weekEndDate = self._dateLastMilliOfWeek(date); + + options.calendarBeforeLoad(self.element); + + self.element.data("startDate", weekStartDate); + self.element.data("endDate", weekEndDate); + + \$weekDayColumns = self.element.find(".wc-day-column-inner"); + + self._updateDayColumnHeader(\$weekDayColumns); + + //load events by chosen means + if (typeof options.data == 'string') { + if (options.loading) options.loading(true); + var jsonOptions = {}; + jsonOptions[options.startParam || 'start'] = Math.round(weekStartDate.getTime() / 1000); + jsonOptions[options.endParam || 'end'] = Math.round(weekEndDate.getTime() / 1000); + $.getJSON(options.data, jsonOptions, function(data) { + self._renderEvents(data, \$weekDayColumns); + if (options.loading) options.loading(false); + }); + } + else if ($.isFunction(options.data)) { + options.data(weekStartDate, weekEndDate, + function(data) { + self._renderEvents(data, \$weekDayColumns); + }); + } + else if (options.data) { + self._renderEvents(options.data, \$weekDayColumns); + } + + self._disableTextSelect(\$weekDayColumns); + + + }, + + /* + * update the display of each day column header based on the calendar week + */ + _updateDayColumnHeader : function (\$weekDayColumns) { + var self = this; + var options = this.options; + var currentDay = self._cloneDate(self.element.data("startDate")); + + self.element.find(".wc-header td.wc-day-column-header").each(function(i, val) { + var myDate = currentDay; + var myDay = myDate.getDate(); + var myYear = myDate.getFullYear(); + var myMonth = myDate.getMonth() + 1; + var dayName = "" + (options.useShortDayNames ? options.shortDays[currentDay.getDay()] : options.longDays[currentDay.getDay()]) + ""; + + $(this).html(dayName + "
    " + self._formatDate(currentDay, options.dateFormat)); + if (self._isToday(currentDay)) { + $(this).addClass("wc-today"); + } else { + $(this).removeClass("wc-today"); + } + currentDay = self._addDays(currentDay, 1); + + }); + + currentDay = self._dateFirstDayOfWeek(self._cloneDate(self.element.data("startDate"))); + + \$weekDayColumns.each(function(i, val) { + + $(this).data("startDate", self._cloneDate(currentDay)); + $(this).data("endDate", new Date(currentDay.getTime() + (MILLIS_IN_DAY))); + if (self._isToday(currentDay)) { + $(this).parent().addClass("wc-today"); + } else { + $(this).parent().removeClass("wc-today"); + } + + currentDay = self._addDays(currentDay, 1); + }); + + }, + + /* + * Render the events into the calendar + */ + _renderEvents : function (data, \$weekDayColumns) { + + this._clearCalendar(); + + var self = this; + var options = this.options; + var eventsToRender; + + if ($.isArray(data)) { + eventsToRender = self._cleanEvents(data); + } else if (data.events) { + eventsToRender = self._cleanEvents(data.events); + } + + if (data.options) { + + var updateLayout = false; + //update options + $.each(data.options, function(key, value) { + if (value !== options[key]) { + options[key] = value; + updateLayout = true; + } + }); + + self._computeOptions(); + + if (updateLayout) { + self.element.empty(); + self._renderCalendar(); + \$weekDayColumns = self.element.find(".wc-time-slots .wc-day-column-inner"); + self._updateDayColumnHeader(\$weekDayColumns); + self._resizeCalendar(); + } + + } + + + $.each(eventsToRender, function(i, calEvent) { + + var \$weekDay = self._findWeekDayForEvent(calEvent, \$weekDayColumns); + + if (\$weekDay) { + self._renderEvent(calEvent, \$weekDay); + } + }); + + \$weekDayColumns.each(function() { + self._adjustOverlappingEvents($(this)); + }); + + options.calendarAfterLoad(self.element); + + if (!eventsToRender.length) { + options.noEvents(); + } + + }, + + /* + * Render a specific event into the day provided. Assumes correct + * day for calEvent date + */ + _renderEvent: function (calEvent, \$weekDay) { + var self = this; + var options = this.options; + if (calEvent.start.getTime() > calEvent.end.getTime()) { + return; // can't render a negative height + } + + var eventClass, eventHtml, \$calEvent, \$modifiedEvent; + + eventClass = calEvent.id ? "wc-cal-event" : "wc-cal-event wc-new-cal-event"; + eventHtml = "
    \ +
    \ +
    \ +
    "; + + \$calEvent = $(eventHtml); + \$modifiedEvent = options.eventRender(calEvent, \$calEvent); + \$calEvent = \$modifiedEvent ? \$modifiedEvent.appendTo(\$weekDay) : \$calEvent.appendTo(\$weekDay); + \$calEvent.css({lineHeight: (options.timeslotHeight - 2) + "px", fontSize: (options.timeslotHeight / 2) + "px"}); + + self._refreshEventDetails(calEvent, \$calEvent); + self._positionEvent(\$weekDay, \$calEvent); + \$calEvent.show(); + + if (!options.readonly && options.resizable(calEvent, \$calEvent)) { + self._addResizableToCalEvent(calEvent, \$calEvent, \$weekDay) + } + if (!options.readonly && options.draggable(calEvent, \$calEvent)) { + self._addDraggableToCalEvent(calEvent, \$calEvent); + } + + options.eventAfterRender(calEvent, \$calEvent); + + return \$calEvent; + + }, + + _adjustOverlappingEvents : function(\$weekDay) { + var self = this; + if (self.options.allowCalEventOverlap) { + var groupsList = self._groupOverlappingEventElements(\$weekDay); + $.each(groupsList, function() { + var curGroups = this; + $.each(curGroups, function(groupIndex) { + var curGroup = this; + + // do we want events to be displayed as overlapping + if (self.options.overlapEventsSeparate) { + var newWidth = 100 / curGroups.length; + var newLeft = groupIndex * newWidth; + } else { + // TODO what happens when the group has more than 10 elements + var newWidth = 100 - ( (curGroups.length - 1) * 10 ); + var newLeft = groupIndex * 10; + } + $.each(curGroup, function() { + // bring mouseovered event to the front + if (!self.options.overlapEventsSeparate) { + $(this).bind("mouseover.z-index", function() { + var \$elem = $(this); + $.each(curGroup, function() { + $(this).css({"z-index": "1"}); + }); + \$elem.css({"z-index": "3"}); + }); + } + $(this).css({width: newWidth + "%", left:newLeft + "%", right: 0}); + }); + }); + }); + } + }, + + + /* + * Find groups of overlapping events + */ + _groupOverlappingEventElements : function(\$weekDay) { + var \$events = \$weekDay.find(".wc-cal-event:visible"); + var sortedEvents = \$events.sort(function(a, b) { + return $(a).data("calEvent").start.getTime() - $(b).data("calEvent").start.getTime(); + }); + + var lastEndTime = new Date(0, 0, 0); + var groups = []; + var curGroups = []; + var \$curEvent; + $.each(sortedEvents, function() { + \$curEvent = $(this); + //checks, if the current group list is not empty, if the overlapping is finished + if (curGroups.length > 0) { + if (lastEndTime.getTime() <= \$curEvent.data("calEvent").start.getTime()) { + //finishes the current group list by adding it to the resulting list of groups and cleans it + + groups.push(curGroups); + curGroups = []; + } + } + + //finds the first group to fill with the event + for (var groupIndex = 0; groupIndex < curGroups.length; groupIndex++) { + if (curGroups[groupIndex].length > 0) { + //checks if the event starts after the end of the last event of the group + if (curGroups[groupIndex][curGroups [groupIndex].length - 1].data("calEvent").end.getTime() <= \$curEvent.data("calEvent").start.getTime()) { + curGroups[groupIndex].push(\$curEvent); + if (lastEndTime.getTime() < \$curEvent.data("calEvent").end.getTime()) { + lastEndTime = \$curEvent.data("calEvent").end; + } + return; + } + } + } + //if not found, creates a new group + curGroups.push([\$curEvent]); + if (lastEndTime.getTime() < \$curEvent.data("calEvent").end.getTime()) { + lastEndTime = \$curEvent.data("calEvent").end; + } + }); + //adds the last groups in result + if (curGroups.length > 0) { + groups.push(curGroups); + } + return groups; + }, + + + /* + * find the weekday in the current calendar that the calEvent falls within + */ + _findWeekDayForEvent : function(calEvent, \$weekDayColumns) { + + var \$weekDay; + \$weekDayColumns.each(function() { + if ($(this).data("startDate").getTime() <= calEvent.start.getTime() && $(this).data("endDate").getTime() >= calEvent.end.getTime()) { + \$weekDay = $(this); + return false; + } + }); + return \$weekDay; + }, + + /* + * update the events rendering in the calendar. Add if does not yet exist. + */ + _updateEventInCalendar : function (calEvent) { + var self = this; + var options = this.options; + self._cleanEvent(calEvent); + + if (calEvent.id) { + self.element.find(".wc-cal-event").each(function() { + if ($(this).data("calEvent").id === calEvent.id || $(this).hasClass("wc-new-cal-event")) { + $(this).remove(); + return false; + } + }); + } + + var \$weekDay = self._findWeekDayForEvent(calEvent, self.element.find(".wc-time-slots .wc-day-column-inner")); + if (\$weekDay) { + var \$calEvent = self._renderEvent(calEvent, \$weekDay); + self._adjustForEventCollisions(\$weekDay, \$calEvent, calEvent, calEvent); + self._refreshEventDetails(calEvent, \$calEvent); + self._positionEvent(\$weekDay, \$calEvent); + self._adjustOverlappingEvents(\$weekDay); + } + }, + + /* + * Position the event element within the weekday based on it's start / end dates. + */ + _positionEvent : function(\$weekDay, \$calEvent) { + var options = this.options; + var calEvent = \$calEvent.data("calEvent"); + var pxPerMillis = \$weekDay.height() / options.millisToDisplay; + var firstHourDisplayed = options.businessHours.limitDisplay ? options.businessHours.start : 0; + var startMillis = calEvent.start.getTime() - new Date(calEvent.start.getFullYear(), calEvent.start.getMonth(), calEvent.start.getDate(), firstHourDisplayed).getTime(); + var eventMillis = calEvent.end.getTime() - calEvent.start.getTime(); + var pxTop = pxPerMillis * startMillis; + var pxHeight = pxPerMillis * eventMillis; + \$calEvent.css({top: pxTop, height: pxHeight}); + }, + + /* + * Determine the actual start and end times of a calevent based on it's + * relative position within the weekday column and the starting hour of the + * displayed calendar. + */ + _getEventDurationFromPositionedEventElement : function(\$weekDay, \$calEvent, top) { + var options = this.options; + var startOffsetMillis = options.businessHours.limitDisplay ? options.businessHours.start * 60 * 60 * 1000 : 0; + var start = new Date(\$weekDay.data("startDate").getTime() + startOffsetMillis + Math.round(top / options.timeslotHeight) * options.millisPerTimeslot); + var end = new Date(start.getTime() + (\$calEvent.height() / options.timeslotHeight) * options.millisPerTimeslot); + return {start: start, end: end}; + }, + + /* + * If the calendar does not allow event overlap, adjust the start or end date if necessary to + * avoid overlapping of events. Typically, shortens the resized / dropped event to it's max possible + * duration based on the overlap. If no satisfactory adjustment can be made, the event is reverted to + * it's original location. + */ + _adjustForEventCollisions : function(\$weekDay, \$calEvent, newCalEvent, oldCalEvent, maintainEventDuration) { + var options = this.options; + + if (options.allowCalEventOverlap) { + return; + } + var adjustedStart, adjustedEnd; + var self = this; + + \$weekDay.find(".wc-cal-event").not(\$calEvent).each(function() { + var currentCalEvent = $(this).data("calEvent"); + + //has been dropped onto existing event overlapping the end time + if (newCalEvent.start.getTime() < currentCalEvent.end.getTime() + && newCalEvent.end.getTime() >= currentCalEvent.end.getTime()) { + + adjustedStart = currentCalEvent.end; + } + + + //has been dropped onto existing event overlapping the start time + if (newCalEvent.end.getTime() > currentCalEvent.start.getTime() + && newCalEvent.start.getTime() <= currentCalEvent.start.getTime()) { + + adjustedEnd = currentCalEvent.start; + } + //has been dropped inside existing event with same or larger duration + if (oldCalEvent.resizable == false || (newCalEvent.end.getTime() <= currentCalEvent.end.getTime() + && newCalEvent.start.getTime() >= currentCalEvent.start.getTime())) { + + adjustedStart = oldCalEvent.start; + adjustedEnd = oldCalEvent.end; + return false; + } + + }); + + + newCalEvent.start = adjustedStart || newCalEvent.start; + + if (adjustedStart && maintainEventDuration) { + newCalEvent.end = new Date(adjustedStart.getTime() + (oldCalEvent.end.getTime() - oldCalEvent.start.getTime())); + self._adjustForEventCollisions(\$weekDay, \$calEvent, newCalEvent, oldCalEvent); + } else { + newCalEvent.end = adjustedEnd || newCalEvent.end; + } + + + //reset if new cal event has been forced to zero size + if (newCalEvent.start.getTime() >= newCalEvent.end.getTime()) { + newCalEvent.start = oldCalEvent.start; + newCalEvent.end = oldCalEvent.end; + } + + \$calEvent.data("calEvent", newCalEvent); + }, + + /* + * Add draggable capabilities to an event + */ + _addDraggableToCalEvent : function(calEvent, \$calEvent) { + if(calEvent.draggable == 1){ + var self = this; + var options = this.options; + var \$weekDay = self._findWeekDayForEvent(calEvent, self.element.find(".wc-time-slots .wc-day-column-inner")); + \$calEvent.draggable({ + handle : ".wc-time", + containment: ".wc-scrollable-grid", + revert: 'valid', + opacity: 0.5, + grid : [\$calEvent.outerWidth() + 1, options.timeslotHeight ], + start : function(event, ui) { + var \$calEvent = ui.draggable; + options.eventDrag(calEvent, \$calEvent); + } + }); + } + }, + + /* + * Add droppable capabilites to weekdays to allow dropping of calEvents only + */ + _addDroppableToWeekDay : function(\$weekDay) { + var self = this; + var options = this.options; + \$weekDay.droppable({ + accept: ".wc-cal-event", + drop: function(event, ui) { + var \$calEvent = ui.draggable; + var top = Math.round(parseInt(ui.position.top)); + var eventDuration = self._getEventDurationFromPositionedEventElement(\$weekDay, \$calEvent, top); + var calEvent = \$calEvent.data("calEvent"); + + + + var newCalEvent = $.extend(true, {}, calEvent, {start: eventDuration.start, end: eventDuration.end}); + self._adjustForEventCollisions(\$weekDay, \$calEvent, newCalEvent, calEvent, true); + var \$weekDayColumns = self.element.find(".wc-day-column-inner"); + + //trigger drop callback + options.eventDrop(newCalEvent, calEvent, \$newEvent); + + var \$newEvent = self._renderEvent(newCalEvent, self._findWeekDayForEvent(newCalEvent, \$weekDayColumns)); + \$calEvent.hide(); + + \$calEvent.data("preventClick", true); + + var \$weekDayOld = self._findWeekDayForEvent(\$calEvent.data("calEvent"), self.element.find(".wc-time-slots .wc-day-column-inner")); + + if (\$weekDayOld.data("startDate") != \$weekDay.data("startDate")) { + self._adjustOverlappingEvents(\$weekDayOld); + } + self._adjustOverlappingEvents(\$weekDay); + + setTimeout(function() { + \$calEvent.remove(); + }, 1000); + + } + }); + }, + + /* + * Add resizable capabilities to a calEvent + */ + _addResizableToCalEvent : function(calEvent, \$calEvent, \$weekDay) { + if(calEvent.resizable == 1){ + var self = this; + var options = this.options; + \$calEvent.resizable({ + grid: options.timeslotHeight, + containment : \$weekDay, + handles: "s", + minHeight: options.timeslotHeight, + stop :function(event, ui) { + var \$calEvent = ui.element; + var newEnd = new Date(\$calEvent.data("calEvent").start.getTime() + (\$calEvent.height() / options.timeslotHeight) * options.millisPerTimeslot); + var newCalEvent = $.extend(true, {}, calEvent, {start: calEvent.start, end: newEnd}); + self._adjustForEventCollisions(\$weekDay, \$calEvent, newCalEvent, calEvent); + + self._refreshEventDetails(newCalEvent, \$calEvent); + self._positionEvent(\$weekDay, \$calEvent); + self._adjustOverlappingEvents(\$weekDay); + //trigger resize callback + options.eventResize(newCalEvent, calEvent, \$calEvent); + \$calEvent.data("preventClick", true); + setTimeout(function() { + \$calEvent.removeData("preventClick"); + }, 500); + } + }); + } + }, + + /* + * Refresh the displayed details of a calEvent in the calendar + */ + _refreshEventDetails : function(calEvent, \$calEvent) { + var self = this; + var options = this.options; + var one_hour = 3600000; + var displayTitleWithTime = calEvent.end.getTime()-calEvent.start.getTime() <= (one_hour/options.timeslotsPerHour); + displayTitleWithTime = 1; + if (displayTitleWithTime){ + \$calEvent.find(".wc-time").html(''+calEvent.icon+''+self._formatDate(calEvent.start, options.timeFormat) + " : " + calEvent.type); + } + else { + \$calEvent.find(".wc-time").html(self._formatDate(calEvent.start, options.timeFormat) + options.timeSeparator + self._formatDate(calEvent.end, options.timeFormat)); + } + \$calEvent.find(".wc-title").html(calEvent.title); + \$calEvent.data("calEvent", calEvent); + }, + + /* + * Clear all cal events from the calendar + */ + _clearCalendar : function() { + this.element.find(".wc-day-column-inner div").remove(); + }, + + /* + * Scroll the calendar to a specific hour + */ + _scrollToHour : function(hour) { + var self = this; + var options = this.options; + var \$scrollable = this.element.find(".wc-scrollable-grid"); + var slot = hour; + if (self.options.businessHours.limitDisplay) { + if (hour <= self.options.businessHours.start) { + slot = 0; + } else if (hour > self.options.businessHours.end) { + slot = self.options.businessHours.end - + self.options.businessHours.start - 1; + } else { + slot = hour - self.options.businessHours.start; + } + + } + + var \$target = this.element.find(".wc-grid-timeslot-header .wc-hour-header:eq(" + slot + ")"); + + \$scrollable.animate({scrollTop: 0}, 0, function() { + var targetOffset = \$target.offset().top; + var scroll = targetOffset - \$scrollable.offset().top - \$target.outerHeight(); + \$scrollable.animate({scrollTop: scroll}, options.scrollToHourMillis); + }); + }, + + /* + * find the hour (12 hour day) for a given hour index + */ + _hourForIndex : function(index) { + if (index === 0) { //midnight + return 12; + } else if (index < 13) { //am + return index; + } else { //pm + return index - 12; + } + }, + + _24HourForIndex : function(index) { + if (index === 0) { //midnight + return "00:00"; + } else if (index < 10) { + return "0" + index + ":00"; + } else { + return index + ":00"; + } + }, + + _amOrPm : function (hourOfDay) { + return hourOfDay < 12 ? "AM" : "PM"; + }, + + _isToday : function(date) { + var clonedDate = this._cloneDate(date); + this._clearTime(clonedDate); + var today = new Date(); + this._clearTime(today); + return today.getTime() === clonedDate.getTime(); + }, + + /* + * Clean events to ensure correct format + */ + _cleanEvents : function(events) { + var self = this; + $.each(events, function(i, event) { + self._cleanEvent(event); + }); + return events; + }, + + /* + * Clean specific event + */ + _cleanEvent : function (event) { + if (event.date) { + event.start = event.date; + } + event.start = this._cleanDate(event.start); + event.end = this._cleanDate(event.end); + if (!event.end) { + event.end = this._addDays(this._cloneDate(event.start), 1); + } + }, + + /* + * Disable text selection of the elements in different browsers + */ + _disableTextSelect : function(\$elements) { + \$elements.each(function() { + if ($.browser.mozilla) {//Firefox + $(this).css('MozUserSelect', 'none'); + } else if ($.browser.msie) {//IE + $(this).bind('selectstart', function() { + return false; + }); + } else {//Opera, etc. + $(this).mousedown(function() { + return false; + }); + } + }); + }, + + /* + * returns the date on the first millisecond of the week + */ + + _dateFirstDayOfWeek : function(date) { + var self = this; + var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var adjustedDate = new Date(midnightCurrentDate); + adjustedDate.setDate(adjustedDate.getDate() - self._getAdjustedDayIndex(midnightCurrentDate)); + + return adjustedDate; + + }, + + /* + * returns the date on the first millisecond of the last day of the week + */ + _dateLastDayOfWeek : function(date) { + + + var self = this; + var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var adjustedDate = new Date(midnightCurrentDate); + adjustedDate.setDate(adjustedDate.getDate() + (6 - this._getAdjustedDayIndex(midnightCurrentDate))); + + return adjustedDate; + + }, + + /* + * gets the index of the current day adjusted based on options + */ + _getAdjustedDayIndex : function(date) { + + var midnightCurrentDate = new Date(date.getFullYear(), date.getMonth(), date.getDate()); + var currentDayOfStandardWeek = midnightCurrentDate.getDay(); + var days = [0,1,2,3,4,5,6]; + this._rotate(days, this.options.firstDayOfWeek); + return days[currentDayOfStandardWeek]; + }, + + /* + * returns the date on the last millisecond of the week + */ + _dateLastMilliOfWeek : function(date) { + var lastDayOfWeek = this._dateLastDayOfWeek(date); + return new Date(lastDayOfWeek.getTime() + (MILLIS_IN_DAY)); + + }, + + /* + * Clear the time components of a date leaving the date + * of the first milli of day + */ + _clearTime : function(d) { + d.setHours(0); + d.setMinutes(0); + d.setSeconds(0); + d.setMilliseconds(0); + return d; + }, + + /* + * add specific number of days to date + */ + _addDays : function(d, n, keepTime) { + d.setDate(d.getDate() + n); + if (keepTime) { + return d; + } + return this._clearTime(d); + }, + + /* + * Rotate an array by specified number of places. + */ + _rotate : function(a /*array*/, p /* integer, positive integer rotate to the right, negative to the left... */) { + for (var l = a.length, p = (Math.abs(p) >= l && (p %= l),p < 0 && (p += l),p), i, x; p; p = (Math.ceil(l / p) - 1) * p - l + (l = p)) { + for (i = l; i > p; x = a[--i],a[i] = a[i - p],a[i - p] = x); + } + return a; + }, + + _cloneDate : function(d) { + return new Date(d.getTime()); + }, + + /* + * return a date for different representations + */ + _cleanDate : function(d) { + if (typeof d == 'string') { + return $.weekCalendar.parseISO8601(d, true) || Date.parse(d) || new Date(parseInt(d)); + } + if (typeof d == 'number') { + return new Date(d); + } + return d; + }, + + /* + * date formatting is adapted from + * http://jacwright.com/projects/javascript/date_format + */ + _formatDate : function(date, format) { + var options = this.options; + var returnStr = ''; + for (var i = 0; i < format.length; i++) { + var curChar = format.charAt(i); + if ($.isFunction(this._replaceChars[curChar])) { + var res = this._replaceChars[curChar](date, options); + + if (res === '00' && options.alwaysDisplayTimeMinutes === false) { + //remove previous character + returnStr = returnStr.slice(0, -1); + } else { + + returnStr += res; + } + } else { + returnStr += curChar; + } + } + + return returnStr; + }, + + _replaceChars : { + + // Day + d: function(date) { + return (date.getDate() < 10 ? '0' : '') + date.getDate(); + }, + D: function(date, options) { + return options.shortDays[date.getDay()]; + }, + j: function(date) { + return date.getDate(); + }, + l: function(date, options) { + return options.longDays[date.getDay()]; + }, + N: function(date) { + return date.getDay() + 1; + }, + S: function(date) { + return (date.getDate() % 10 == 1 && date.getDate() != 11 ? 'st' : (date.getDate() % 10 == 2 && date.getDate() != 12 ? 'nd' : (date.getDate() % 10 == 3 && date.getDate() != 13 ? 'rd' : 'th'))); + }, + w: function(date) { + return date.getDay(); + }, + z: function(date) { + return "Not Yet Supported"; + }, + // Week + W: function(date) { + return "Not Yet Supported"; + }, + // Month + F: function(date, options) { + return options.longMonths[date.getMonth()]; + }, + m: function(date) { + return (date.getMonth() < 9 ? '0' : '') + (date.getMonth() + 1); + }, + M: function(date, options) { + return options.shortMonths[date.getMonth()]; + }, + n: function(date) { + return date.getMonth() + 1; + }, + t: function(date) { + return "Not Yet Supported"; + }, + // Year + L: function(date) { + return "Not Yet Supported"; + }, + o: function(date) { + return "Not Supported"; + }, + Y: function(date) { + return date.getFullYear(); + }, + y: function(date) { + return ('' + date.getFullYear()).substr(2); + }, + // Time + a: function(date) { + return date.getHours() < 12 ? 'am' : 'pm'; + }, + A: function(date) { + return date.getHours() < 12 ? 'AM' : 'PM'; + }, + B: function(date) { + return "Not Yet Supported"; + }, + g: function(date) { + return date.getHours() % 12 || 12; + }, + G: function(date) { + return date.getHours(); + }, + h: function(date) { + return ((date.getHours() % 12 || 12) < 10 ? '0' : '') + (date.getHours() % 12 || 12); + }, + H: function(date) { + return (date.getHours() < 10 ? '0' : '') + date.getHours(); + }, + i: function(date) { + return (date.getMinutes() < 10 ? '0' : '') + date.getMinutes(); + }, + s: function(date) { + return (date.getSeconds() < 10 ? '0' : '') + date.getSeconds(); + }, + // Timezone + e: function(date) { + return "Not Yet Supported"; + }, + I: function(date) { + return "Not Supported"; + }, + O: function(date) { + return (date.getTimezoneOffset() < 0 ? '-' : '+') + (date.getTimezoneOffset() / 60 < 10 ? '0' : '') + (date.getTimezoneOffset() / 60) + '00'; + }, + T: function(date) { + return "Not Yet Supported"; + }, + Z: function(date) { + return date.getTimezoneOffset() * 60; + }, + // Full Date/Time + c: function(date) { + return "Not Yet Supported"; + }, + r: function(date) { + return date.toString(); + }, + U: function(date) { + return date.getTime() / 1000; + } + } + + }); + + $.extend($.ui.weekCalendar, { + version: '1.2.2-pre', + + }); + + var MILLIS_IN_DAY = 86400000; + var MILLIS_IN_WEEK = MILLIS_IN_DAY * 7; + + $.weekCalendar = function() { + return { + parseISO8601 : function(s, ignoreTimezone) { + + // derived from http://delete.me.uk/2005/03/iso8601.html + var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" + + "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" + + "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"; + var d = s.match(new RegExp(regexp)); + if (!d) return null; + var offset = 0; + var date = new Date(d[1], 0, 1); + if (d[3]) { + date.setMonth(d[3] - 1); + } + if (d[5]) { + date.setDate(d[5]); + } + if (d[7]) { + date.setHours(d[7]); + } + if (d[8]) { + date.setMinutes(d[8]); + } + if (d[10]) { + date.setSeconds(d[10]); + } + if (d[12]) { + date.setMilliseconds(Number("0." + d[12]) * 1000); + } + if (!ignoreTimezone) { + if (d[14]) { + offset = (Number(d[16]) * 60) + Number(d[17]); + offset *= ((d[15] == '-') ? 1 : -1); + } + offset -= date.getTimezoneOffset(); + } + return new Date(Number(date) + (offset * 60 * 1000)); + } + }; + }(); + + +})(jQuery); + + + +JS; + +foreach($JS as $output) + echo $output; +?> \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/Sp_calendar.js.php dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/Sp_calendar.js.php --- dolibarr-snapshot/htdocs/includes/jquery/plugins/weekcalendar/Sp_calendar.js.php 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/includes/jquery/plugins/weekcalendar/Sp_calendar.js.php 2011-04-14 10:21:12.000000000 +0200 @@ -0,0 +1,293 @@ +agendas_modules as $ag_path => $ag_classes): + foreach($ag_classes as $ag_filename) + require_once DOL_DOCUMENT_ROOT."/{$ag_path}/class/".strtolower($ag_filename).".class.php"; + +endforeach; + + +$Sp_agendas = new stdclass; +$Sp_agendas->agendas = array(); + +foreach($conf->agendas_modules as $ag_path => $ag_classes): + foreach($ag_classes as $ag_filename) + $Sp_agendas->agendas[strtolower($ag_filename)] = new $ag_filename($db); +endforeach; + +foreach($Sp_agendas->agendas as $ag_name => $ag_class): + $JS[] = <<getFormItems() as $name => $type): + $extraFields .= "{$name} : get".ucfirst(strtolower($name))."(),"; +endforeach; + +$JS[] = <<" + timeslotTimes[i].startFormatted + ""); + + \$endTimeField.append(""); + } + \$endTimeOptions = \$endTimeField.find("option"); + \$startTimeField.trigger("change"); + } + + var \$endTimeField = jQuery("select[name='end']"); + var \$endTimeOptions = \$endTimeField.find("option"); + + + + + + + function storeevent(event,onWhat) { + jQuery.post("data.ajax.php?cal_action=edit", + { + "cal_action": "edit", + "offset" : getoffsethours(), + "id" : event.id, + "start": event.start.getTime(), + "end": event.end.getTime(), + "multiday" : event.multiday, + "onWhat" : onWhat, + "agenda": "{$ag_name}" + },function(json){ + }, 'json'); + } + + + + function getoffsethours() { + var d = new Date(); + var gmtHours = d.getTimezoneOffset()/60; + return 1; + } + + + +JS; + +$fieldsGetter = ""; +foreach($ag_class->getFormItems() as $name => $type): + $function = "get".ucfirst(strtolower($name))."()"; + $fieldsGetter .= << * Copyright (C) 2005-2011 Laurent Destailleur * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2011 Anthony Hebert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -110,7 +111,11 @@ // Create module's directories if (! $err) $err+=$this->create_dirs(); - + + // Insert new tabs for Agenda + if (! $err) $err+=$this->insert_agendas(); + + // Execute les requetes sql complementaires if (! $err) { @@ -187,6 +192,9 @@ // Remove activation of module's new tabs (MAIN_MODULE_MYMODULE_TABS_XXX in llx_const) if (! $err) $err+=$this->delete_tabs(); + + // Remove activation of module's new tabs (MAIN_MODULE_MYMODULE_TABS_XXX in llx_const) + if (! $err) $err+=$this->delete_agendas(); // Remove activation of module's triggers (MAIN_MODULE_MYMODULE_TRIGGERS in llx_const) if (! $err) $err+=$this->delete_triggers(); @@ -718,6 +726,33 @@ return $err; } + + /** + * \brief Remove links to new agenda tab present in llx_const + * \return int Nombre d'erreurs (0 si ok) + */ + function delete_agendas() + { + global $conf; + + $err=0; + + $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; + $sql.= " WHERE ".$this->db->decrypt('name')." like '".$this->const_name."_AGENDAS_%'"; + $sql.= " AND entity = ".$conf->entity; + + dol_syslog("DolibarrModules::delete_tabs sql=".$sql); + if (! $this->db->query($sql)) + { + $this->error=$this->db->lasterror(); + dol_syslog("DolibarrModules::delete_tabs ".$this->error, LOG_ERR); + $err++; + } + + return $err; + } + + /** * \brief Active la feuille de style associee au module par insertion ligne dans llx_const * \return int Nombre d'erreurs (0 si ok) @@ -809,6 +844,59 @@ return $err; } + /** + * \brief Add new agenda from modules in llx_const + * \return int Number of errors (0 if ok) + */ + function insert_agendas() + { + global $conf; + + $err=0; + + if(isset($this->Agenda) and $this->Agenda == 1){ + + if (! empty($this->agendas)) + { + $i=0; + foreach ($this->agendas as $key => $value) + { + if ($value) + { + $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; + $sql.= "name"; + $sql.= ", type"; + $sql.= ", value"; + $sql.= ", note"; + $sql.= ", visible"; + $sql.= ", entity"; + $sql.= ")"; + $sql.= " VALUES ("; + $sql.= $this->db->encrypt($this->const_name."_AGENDAS_".$i,1); + $sql.= ", 'chaine'"; + $sql.= ", '{$value}'"; + $sql.= ", null"; + $sql.= ", '0'"; + $sql.= ", ".$conf->entity; + $sql.= ")"; + + dol_syslog("DolibarrModules::insert_agendas sql=".$sql); + $resql=$this->db->query($sql); + /* Allow duplicate key + if (! $resql) + { + $err++; + } + */ + } + $i++; + } + } + } + + return $err; + } + /** * Insert constants defined into $this->const array into table llx_const * @return int Number of errors (0 if OK) diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/includes/modules/modAgenda.class.php dolibarr-svn/htdocs/includes/modules/modAgenda.class.php --- dolibarr-snapshot/htdocs/includes/modules/modAgenda.class.php 2011-02-02 17:44:15.000000000 +0100 +++ dolibarr-svn/htdocs/includes/modules/modAgenda.class.php 2011-04-20 10:16:01.000000000 +0200 @@ -5,6 +5,7 @@ * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2009-2011 Regis Houssin + * Copyright (C) 2011 Anthony Hebert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -353,7 +354,10 @@ 'user'=>2); $r++; - + // Agenda + $this->Agenda = 1; + $this->agendas = array('Comm:Action:ActionAgenda'); + // Exports //-------- $r=0; diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/includes/triggers/interface_modAgenda_ActionsAuto.class.php dolibarr-svn/htdocs/includes/triggers/interface_modAgenda_ActionsAuto.class.php --- dolibarr-snapshot/htdocs/includes/triggers/interface_modAgenda_ActionsAuto.class.php 2010-12-08 14:13:18.000000000 +0100 +++ dolibarr-svn/htdocs/includes/triggers/interface_modAgenda_ActionsAuto.class.php 2011-04-20 10:04:36.000000000 +0200 @@ -1,5 +1,6 @@ +/* Copyright (C) 2011 Anthony Hebert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -554,7 +555,7 @@ $actioncomm->label = $object->actionmsg2; $actioncomm->note = $object->actionmsg; $actioncomm->datep = $now; - $actioncomm->datef = $now; + $actioncomm->datef = $now + 3600; $actioncomm->durationp = 0; $actioncomm->punctual = 1; $actioncomm->percentage = 100; diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/langs/fr_FR/main.lang dolibarr-svn/htdocs/langs/fr_FR/main.lang --- dolibarr-snapshot/htdocs/langs/fr_FR/main.lang 2011-04-10 05:00:27.000000000 +0200 +++ dolibarr-svn/htdocs/langs/fr_FR/main.lang 2011-04-20 10:09:31.000000000 +0200 @@ -389,18 +389,18 @@ AddPhoto=Ajouter photo Login=Login CurrentLogin=Login courant -January=janvier -February=février -March=mars -April=avril -May=mai -June=juin -July=juillet -August=août -September=septembre -October=octobre -November=novembre -December=décembre +January=Janvier +February=Février +March=Mars +April=Avril +May=Mai +June=Juin +July=Juillet +August=Août +September=Septembre +October=Octobre +November=Novembre +December=Décembre Month01=janvier Month02=février Month03=mars diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/langs/fr_FR/projects.lang dolibarr-svn/htdocs/langs/fr_FR/projects.lang --- dolibarr-snapshot/htdocs/langs/fr_FR/projects.lang 2011-02-13 14:49:28.000000000 +0100 +++ dolibarr-svn/htdocs/langs/fr_FR/projects.lang 2011-04-20 10:08:46.000000000 +0200 @@ -28,6 +28,7 @@ NbOpenTasks=Nb Tâches Ouvertes NbOfProjects=Nombre de projets TimeSpent=Temps consommé +TimesSpent=Temps consommés RefTask=Ref. tâche LabelTask=Libellé tâche NewTimeSpent=Nouveau consommé diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/lib/agenda.lib.php dolibarr-svn/htdocs/lib/agenda.lib.php --- dolibarr-snapshot/htdocs/lib/agenda.lib.php 2011-03-09 05:01:42.000000000 +0100 +++ dolibarr-svn/htdocs/lib/agenda.lib.php 2011-04-20 09:51:28.000000000 +0200 @@ -2,6 +2,7 @@ /* Copyright (C) 2008-2010 Laurent Destailleur * Copyright (C) 2005-2009 Regis Houssin * Copyright (C) 2011 Juanjo Menent + * Copyright (C) 2011 Anthony Hebert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -345,4 +346,53 @@ return $head; } +/** + * Personnal json_encode() for php < 4 compatibility + * @param array events data + * @return json data + */ +function generateeventjson($d2array, $multi = false) { + if($multi || count($d2array) > 1) {$multi = true;} + $l1first = true; + $return = ""; + if($multi) { + $return .= "["; + } + if(!empty ($d2array)) { + foreach ($d2array as $key1 => $array) { + if($l1first) {$l1first = false;} else {$return .= ",\n";} + $l2first = true; + $return .= "{"; + foreach($array as $key2 => $value) { + if($l2first) {$l2first = false;} else {$return .= ",\n";} + $return .= "\"$key2\":\"$value\""; + } + $return .= "}"; + } + } + if($multi) { + $return .= "]"; + } + return $return; +} + +/** + * String encoding for json + * @param string + * @return encoded string + */ +function json_string($string) +{ + $replacements = array( + '@[\\\\"]@' => '\\\\$0', //escape backslashes and double quotes + '@\n@' => '\n', //convert new lines to their alias for readability + '@\r@' => '\r', //convert carriage returns to their alias for readability + '@\t@' => '\t', //convert tabs to their alias for readability + '@[[:cntrl:address@hidden' => 'sprintf("\\u%04x", ord("$0"))', //escape control characters + '@ '<\/$1', //escape slashes that could fool browsers + ); + $result = preg_replace(array_keys($replacements), array_values($replacements), $string); + $result = '' . $result . ''; + return $result; +} ?> \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/main.inc.php dolibarr-svn/htdocs/main.inc.php --- dolibarr-snapshot/htdocs/main.inc.php 2011-04-11 05:00:34.000000000 +0200 +++ dolibarr-svn/htdocs/main.inc.php 2011-04-20 09:55:01.000000000 +0200 @@ -5,6 +5,7 @@ * Copyright (C) 2004 Sebastien Di Cintio * Copyright (C) 2004 Benoit Mortier * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2011 Anthony Hebert * Copyright (C) 2008 Matteli * * This program is free software; you can redistribute it and/or modify @@ -878,6 +879,7 @@ if (!empty($conf->global->MAIN_USE_JQUERY_THEME)) $jquerytheme = $conf->global->MAIN_USE_JQUERY_THEME; print ''."\n"; print ''."\n"; + print ''."\n"; // jQuery jnotify if (!empty($conf->global->MAIN_USE_JQUERY_JNOTIFY)) print ''."\n"; } diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/main.inc.php.new dolibarr-svn/htdocs/main.inc.php.new --- dolibarr-snapshot/htdocs/main.inc.php.new 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/main.inc.php.new 2011-04-15 15:23:14.000000000 +0200 @@ -0,0 +1,1597 @@ + + * Copyright (C) 2003 Xavier Dutoit + * Copyright (C) 2004-2011 Laurent Destailleur + * Copyright (C) 2004 Sebastien Di Cintio + * Copyright (C) 2004 Benoit Mortier + * Copyright (C) 2005-2011 Regis Houssin + * Copyright (C) 2008 Matteli + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/** + * \file htdocs/main.inc.php + * \ingroup core + * \brief File that defines environment for Dolibarr pages only (variables not required by scripts) + * \version $Id: main.inc.php,v 1.673.2.10 2011/04/01 15:27:34 hregis Exp $ + */ + address@hidden('memory_limit', '64M'); // This may be useless if memory is hard limited by your PHP + +// For optionnal tuning. Enabled if environment variable DOL_TUNING is defined. +// A call first. Is the equivalent function dol_microtime_float not yet loaded. +$micro_start_time=0; +if (! empty($_SERVER['DOL_TUNING'])) +{ + list($usec, $sec) = explode(" ", microtime()); + $micro_start_time=((float)$usec + (float)$sec); + // Add Xdebug coverage of code + //define('XDEBUGCOVERAGE',1); + if (defined('XDEBUGCOVERAGE')) { xdebug_start_code_coverage(); } +} + +// Removed magic_quotes +if (function_exists('get_magic_quotes_gpc')) // magic_quotes_* removed in PHP6 +{ + if (get_magic_quotes_gpc()) + { + // Forcing parameter setting magic_quotes_gpc and cleaning parameters + // (Otherwise he would have for each position, condition + // Reading stripslashes variable according to state get_magic_quotes_gpc). + // Off mode (recommended, you just do $db->escape when an insert / update. + function stripslashes_deep($value) + { + return (is_array($value) ? array_map('stripslashes_deep', $value) : stripslashes($value)); + } + $_GET = array_map('stripslashes_deep', $_GET); + $_POST = array_map('stripslashes_deep', $_POST); + $_COOKIE = array_map('stripslashes_deep', $_COOKIE); + @set_magic_quotes_runtime(0); + } +} + + +// Security: SQL Injection and XSS Injection (scripts) protection (Filters on GET, POST) +function test_sql_and_script_inject($val,$get) +{ + $sql_inj = 0; + // For SQL Injection + $sql_inj += preg_match('/delete[\s]+from/i', $val); + $sql_inj += preg_match('/create[\s]+table/i', $val); + $sql_inj += preg_match('/update.+set.+=/i', $val); + $sql_inj += preg_match('/insert[\s]+into/i', $val); + $sql_inj += preg_match('/select.+from/i', $val); + $sql_inj += preg_match('/union.+select/i', $val); + // For XSS Injection done by adding javascript with script + $sql_inj += preg_match('/'."\n"; + + // Other external js + require_once DOL_DOCUMENT_ROOT.'/lib/ajax.lib.php'; + + $mini='';$ext='.js'; + if (isset($conf->global->MAIN_OPTIMIZE_SPEED) && ($conf->global->MAIN_OPTIMIZE_SPEED & 0x01)) { $mini='_mini'; $ext='.jgz'; } // mini='_mini', ext='.gz' + + // JQuery. Must be before other includes (prototype/scriptaculous/...) + print ''."\n"; + print ''."\n"; + print ''."\n"; + print ''."\n"; + print ''."\n"; + + if ($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT || defined('REQUIRE_JQUERY_LAYOUT')) + { + print ''."\n"; + } + } + + // Output module javascript + if (is_array($arrayofjs)) + { + print ''."\n"; + foreach($arrayofjs as $jsfile) + { + if (! preg_match('/^\//',$jsfile)) $jsfile='/'.$jsfile; // For backward compatibility + print ''."\n"; + } + } + + // Define tradMonths javascript array (we define this in datapicker AND in parent page to avoid errors with IE8) + $tradTemp=array($langs->trans("January"), + $langs->trans("February"), + $langs->trans("March"), + $langs->trans("April"), + $langs->trans("May"), + $langs->trans("June"), + $langs->trans("July"), + $langs->trans("August"), + $langs->trans("September"), + $langs->trans("October"), + $langs->trans("November"), + $langs->trans("December") + ); + print ''."\n"; + + if (! empty($head)) print $head."\n"; + if (! empty($conf->global->MAIN_HTML_HEADER)) print $conf->global->MAIN_HTML_HEADER."\n"; + + print "\n\n"; + } + + $conf->headerdone=1; // To tell header was output +} + + +/** + * Show an HTML header + a BODY + The top menu bar + * @param head Lines in the HEAD + * @param title Title of web page + * @param target Target to use in menu links + * @param disablejs Do not output links to js (Ex: qd fonction utilisee par sous formulaire Ajax) + * @param disablehead Do not output head section + * @param arrayofjs Array of js files to add in header + * @param arrayofcss Array of css files to add in header + * @param morequerystring Query string to add to the link "print" to get same parameters (use only if autodetect fails) + */ +function top_menu($head, $title='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='') +{ + global $user, $conf, $langs, $db, $dolibarr_main_authentication; + + $html=new Form($db); + + if (! $conf->top_menu) $conf->top_menu ='eldy_backoffice.php'; + + + // For backward compatibility with old modules + if (empty($conf->headerdone)) top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); + + print ''; + + if ($conf->use_javascript_ajax) + { + if ($conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) + { + print ''; + } + + if ($conf->global->MAIN_MENU_USE_JQUERY_ACCORDION) + { + print "\n".''; + } + + // Wrapper to show tooltips + print "\n".''; + } + + /* + * Top menu + */ + $top_menu=$conf->top_menu; + if (GETPOST('menu')) $top_menu=GETPOST('menu'); // menu=eldy_backoffice.php + + // Load the top menu manager + address@hidden(DOL_DOCUMENT_ROOT ."/includes/menus/standard/".$top_menu); + if (! $result) // If failed to include, we try with standard + { + $top_menu='eldy_backoffice.php'; + include_once(DOL_DOCUMENT_ROOT ."/includes/menus/standard/".$top_menu); + } + + print "\n".''."\n"; + + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print '
    '."\n"; + + print '
    '."\n"; + + // Show menu + $menutop = new MenuTop($db); + $menutop->atarget=$target; + $menutop->showmenu(); + + print "\n
    \n"; + + // Link to login card + $loginhtmltext=''; $logintext=''; + if ($user->societe_id) + { + $thirdpartystatic=new Societe($db); + $thirdpartystatic->fetch($user->societe_id); + $companylink=' ('.$thirdpartystatic->getNomUrl('','').')'; + $company=' ('.$langs->trans("Company").': '.$thirdpartystatic->name.')'; + } + $logintext=''; + $loginhtmltext.=''.$langs->trans("User").''; + $loginhtmltext.='
    '.$langs->trans("Name").': '.$user->getFullName($langs); + $loginhtmltext.='
    '.$langs->trans("Login").': '.$user->login; + $loginhtmltext.='
    '.$langs->trans("Administrator").': '.yn($user->admin); + $type=($user->societe_id?$langs->trans("External").$company:$langs->trans("Internal")); + $loginhtmltext.='
    '.$langs->trans("Type").': '.$type; + $loginhtmltext.='
    '; + $loginhtmltext.='
    '.$langs->trans("Connection").''; + if ($conf->global->MAIN_MODULE_MULTICOMPANY) $loginhtmltext.='
    '.$langs->trans("ConnectedOnMultiCompany").': '.$conf->entity.' (user entity '.$user->entity.')'; + $loginhtmltext.='
    '.$langs->trans("ConnectedSince").': '.dol_print_date($user->datelastlogin,"dayhour"); + $loginhtmltext.='
    '.$langs->trans("PreviousConnexion").': '.dol_print_date($user->datepreviouslogin,"dayhour"); + $loginhtmltext.='
    '.$langs->trans("AuthenticationMode").': '.$_SESSION["dol_authmode"]; + $loginhtmltext.='
    '.$langs->trans("CurrentTheme").': '.$conf->theme; + $s=picto_from_langcode($langs->getDefaultLang()); + $loginhtmltext.='
    '.$langs->trans("CurrentUserLanguage").': '.($s?$s.' ':'').$langs->getDefaultLang(); + $loginhtmltext.='
    '.$langs->trans("Browser").': '.$conf->browser->name.' ('.$_SERVER['HTTP_USER_AGENT'].')'; + if (! empty($conf->browser->phone)) $loginhtmltext.='
    '.$langs->trans("Phone").': '.$conf->browser->phone; + if (! empty($_SESSION["disablemodules"])) $loginhtmltext.='
    '.$langs->trans("DisabledModules").':
    '.join(', ',explode(',',$_SESSION["disablemodules"])); + + // Link info + $logouthtmltext=''; $logouttext=''; + $logouthtmltext=$langs->trans("Logout").'
    '; + //$logouthtmltext.="
    "; + if ($_SESSION["dol_authmode"] != 'forceuser' + && $_SESSION["dol_authmode"] != 'http') + { + $logouttext.='atarget?(' target="'.$menutop->atarget.'"'):''; + $logouttext.='>'; + $logouttext.='trans("Logout")).'" title=""'; + $logouttext.='>'; + $logouttext.=''; + } + else + { + $logouttext.='trans("Logout")).'" title=""'; + $logouttext.='>'; + } + + print '\n"; + + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print "
    \n"; + + print "\n"; + + if (! $conf->use_javascript_ajax || ! $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print ''; +} + + +/** + * Show left menu bar + * @param menu_array_before Table of menu entries to show before entries of menu handler + * @param helppagename Name of wiki page for help ('' by default). + * Syntax is: For a wiki page: EN:EnglishPage|FR:FrenchPage|ES:SpanishPage + * For other external page: http://server/url + * @param moresearchform Search Form Permanent Supplemental + * @param menu_array_after Table of menu entries to show after entries of menu handler + * @param leftmenuwithoutmainarea Must be set to 1. 0 by default for backward compatibility with old modules. + */ +function left_menu($menu_array_before, $helppagename='', $moresearchform='', $menu_array_after='', $leftmenuwithoutmainarea=0) +{ + global $user, $conf, $langs, $db; + + $searchform=''; + $bookmarks=''; + + // print '
    '."\n"; + + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print "\n".'
    '."\n"; + else print '
    '; + + print "\n".''."\n\n"; + // print ''."\n"; + // print '
    '."\n"; + + if (empty($leftmenuwithoutmainarea)) main_area(); +} + +/** + * Begin main area + */ +function main_area() +{ + global $conf, $langs; + + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) + { + print '
    '."\n"; + print '
    '; + + print "\n"; + + + // Define $searchform + if ($conf->societe->enabled && $conf->global->MAIN_SEARCHFORM_SOCIETE && $user->rights->societe->lire) + { + $langs->load("companies"); + $searchform.=printSearchForm(DOL_URL_ROOT.'/societe/societe.php', DOL_URL_ROOT.'/societe/societe.php', + img_object('','company').' '.$langs->trans("ThirdParties"), 'soc', 'socname'); + } + + if ($conf->societe->enabled && $conf->global->MAIN_SEARCHFORM_CONTACT && $user->rights->societe->lire) + { + $langs->load("companies"); + $searchform.=printSearchForm(DOL_URL_ROOT.'/contact/index.php', DOL_URL_ROOT.'/contact/index.php', + img_object('','contact').' '.$langs->trans("Contacts"), 'contact', 'contactname'); + } + + if ((($conf->product->enabled && $user->rights->produit->lire) || ($conf->service->enabled && $user->rights->service->lire)) + && $conf->global->MAIN_SEARCHFORM_PRODUITSERVICE) + { + $langs->load("products"); + $searchform.=printSearchForm(DOL_URL_ROOT.'/product/liste.php', DOL_URL_ROOT.'/product/liste.php', + img_object('','product').' '.$langs->trans("Products")."/".$langs->trans("Services"), 'products', 'sall'); + } + + if ($conf->adherent->enabled && $conf->global->MAIN_SEARCHFORM_ADHERENT && $user->rights->adherent->lire) + { + $langs->load("members"); + $searchform.=printSearchForm(DOL_URL_ROOT.'/adherents/liste.php', DOL_URL_ROOT.'/adherents/liste.php', + img_object('','user').' '.$langs->trans("Members"), 'member', 'sall'); + } + + // Define $bookmarks + if ($conf->bookmark->enabled && $user->rights->bookmark->lire) + { + include_once (DOL_DOCUMENT_ROOT.'/bookmarks/bookmarks.lib.php'); + $langs->load("bookmarks"); + + $bookmarks=printBookmarksList($db, $langs); + } + + + + //$left_menu=$conf->left_menu; + $left_menu=$conf->top_menu; + if (GETPOST('menu')) $left_menu=GETPOST('menu'); // menu=eldy_backoffice.php + + // Load the left menu manager + address@hidden(DOL_DOCUMENT_ROOT ."/includes/menus/standard/".$left_menu); + if (! $result) // If menu manager removed or not found + { + $left_menu='eldy_backoffice.php'; + include_once(DOL_DOCUMENT_ROOT ."/includes/menus/standard/".$left_menu); + } + + // Left column + print ''."\n"; + + print '
    '."\n"; + + $menuleft=new MenuLeft($db,$menu_array_before,$menu_array_after); + $menuleft->showmenu(); // output menu_array and menu found in database + + + // Show other forms + if ($searchform) + { + print "\n"; + print "\n"; + print '
    '."\n"; + print $searchform; + print '
    '."\n"; + print "\n"; + } + + // More search form + if ($moresearchform) + { + print $moresearchform; + } + + // Bookmarks + if ($bookmarks) + { + print "\n"; + print "\n"; + print '
    '."\n"; + print $bookmarks; + print '
    '."\n"; + print "\n"; + } + + // Link to Dolibarr wiki pages + if ($helppagename && empty($conf->global->MAIN_HELP_DISABLELINK)) + { + $langs->load("help"); + + $helpbaseurl=''; + $helppage=''; + $mode=''; + + // Get helpbaseurl, helppage and mode from helppagename and langs + $arrayres=getHelpParamFor($helppagename,$langs); + $helpbaseurl=$arrayres['helpbaseurl']; + $helppage=$arrayres['helppage']; + $mode=$arrayres['mode']; + + // Link to help pages + if ($helpbaseurl && $helppage) + { + print ''; + } + } + + // Link to bugtrack + if (! empty($conf->global->MAIN_SHOW_BUGTRACK_LINK)) + { + $bugbaseurl='http://savannah.nongnu.org/bugs/?'; + $bugbaseurl.='func=additem&group=dolibarr&privacy=1&'; + $bugbaseurl.="&details="; + $bugbaseurl.=urlencode("\n\n\n\n\n-------------\n"); + $bugbaseurl.=urlencode($langs->trans("Version").": ".DOL_VERSION."\n"); + $bugbaseurl.=urlencode($langs->trans("Server").": ".$_SERVER["SERVER_SOFTWARE"]."\n"); + $bugbaseurl.=urlencode($langs->trans("Url").": ".$_SERVER["REQUEST_URI"]."\n"); + print ''; + } + print "\n"; + print "
    \n"; + print "\n"; + + print "\n"; + + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print ' '."\n"; + else print '
    '; + } + + print '
    '."\n"; + + print "\n"; + + print '
    '."\n"; + + if (! empty($conf->global->MAIN_ONLY_LOGIN_ALLOWED)) print info_admin($langs->trans("WarningYouAreInMaintenanceMode",$conf->global->MAIN_ONLY_LOGIN_ALLOWED)); +} + + +/** + * \brief Return helpbaseurl, helppage and mode + * \param helppagename Page name (EN:xxx,ES:eee,FR:fff...) + * \param langs Language + */ +function getHelpParamFor($helppagename,$langs) +{ + if (preg_match('/^http/i',$helppagename)) + { + // If complete URL + $helpbaseurl='%s'; + $helppage=$helppagename; + $mode='local'; + } + else + { + // If WIKI URL + if (preg_match('/^es/i',$langs->defaultlang)) + { + $helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; + if (preg_match('/ES:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; + } + if (preg_match('/^fr/i',$langs->defaultlang)) + { + $helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; + if (preg_match('/FR:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; + } + if (empty($helppage)) // If help page not already found + { + $helpbaseurl='http://wiki.dolibarr.org/index.php/%s'; + if (preg_match('/EN:([^|]+)/i',$helppagename,$reg)) $helppage=$reg[1]; + } + $mode='wiki'; + } + return array('helpbaseurl'=>$helpbaseurl,'helppage'=>$helppage,'mode'=>$mode); +} + + +/** + * \brief Show a search area + * \param urlaction Url post + * \param urlobject Url of the link under the search box + * \param title Title search area + * \param htmlmodesearch 'search' + * \param htmlinputname Field Name input form + */ +function printSearchForm($urlaction,$urlobject,$title,$htmlmodesearch='search',$htmlinputname) +{ + global $langs; + $ret=''; + $ret.=''; + $ret.='
    '; + $ret.=''; + $ret.=''; + $ret.=''; + $ret.=' '; + $ret.=''; + $ret.="
    \n"; + return $ret; +} + +/** + * Return list of login method of third party module. + * @return array + */ +function getLoginMethod() +{ + global $conf,$langs; + + $login = ''; + + foreach($conf->login_method_modules as $dir) + { + // Check if directory exists + if (!is_dir($dir)) continue; + + $handle=opendir($dir); + if (is_resource($handle)) + { + while (($file = readdir($handle))!==false) + { + if (is_readable($dir.'/'.$file) && preg_match('/^functions_([^_]+)\.php/',$file,$reg)) + { + $authfile = $dir.'/'.$file; + $mode = $reg[1]; + + $result=include_once($authfile); + if ($result) + { + // Call function to check user/password + $usertotest=$_POST["username"]; + $passwordtotest=$_POST["password"]; + $function='check_user_password_'.$mode; + $login=$function($usertotest,$passwordtotest); + if ($login) + { + $conf->authmode=$mode; // This properties is defined only when logged + } + } + else + { + dol_syslog("Authentification ko - failed to load file '".$authfile."'",LOG_ERR); + sleep(1); + $langs->load('main'); + $langs->load('other'); + $_SESSION["dol_loginmesg"]=$langs->trans("ErrorFailedToLoadLoginFileForMode",$mode); + } + } + } + } + closedir($handle); + } + return $login; +} + +/** + * \brief Show HTML footer DIV + BODY + HTML + * \remarks Close 2 div + * \param foot A text to add in HTML generated page + */ +if (! function_exists("llxFooter")) +{ + function llxFooter($foot='') + { + global $conf, $langs, $dolibarr_auto_user, $micro_start_time; + + // Core error message + if (defined("MAIN_CORE_ERROR") && constant("MAIN_CORE_ERROR") == 1) + { + // Ajax version + if ($conf->use_javascript_ajax) + { + $title = img_warning().' '.$langs->trans('CoreErrorTitle'); + print ajax_dialog($title, $langs->trans('CoreErrorMessage')); + } + // html version + else + { + $msg = img_warning().' '.$langs->trans('CoreErrorMessage'); + print '
    '.$msg.'
    '; + } + + define("MAIN_CORE_ERROR",0); + } + + print "\n\n".'
    '."\n"; + + // print "\n".' '."\n"; + print "\n".'
    '."\n"; + if ($conf->use_javascript_ajax && $conf->global->MAIN_MENU_USE_JQUERY_LAYOUT) print '
    '."\n"; + + if (! empty($_SERVER['DOL_TUNING'])) + { + $micro_end_time=dol_microtime_float(true); + print "\n".''."\n"; + + // Add Xdebug coverage of code + if (defined('XDEBUGCOVERAGE')) { var_dump(xdebug_get_code_coverage()); } + } + + // If there is some logs in buffer to show + if (sizeof($conf->logbuffer)) + { + print "\n"; + print "\n"; + } + + print "\n"; + if ($foot) print ''."\n"; + + if (! empty($conf->global->MAIN_HTML_FOOTER)) print $conf->global->MAIN_HTML_FOOTER."\n"; + + print "\n"; + print "\n"; + } +} + +?> \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/theme/common/ical.gif dolibarr-svn/htdocs/theme/common/ical.gif --- dolibarr-snapshot/htdocs/theme/common/ical.gif 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/theme/common/ical.gif 2011-04-14 10:06:13.000000000 +0200 @@ -0,0 +1 @@ +GIF87a$¥™ÖÔAÖYÂìÏ0¸aaɆ³3ê÷" Ú4âøæ ¼Lqڈ¿)Ñ¡à¶AÝTÇüÅÒñÚ¡ðª‘ä£ÎQÃzqҐ²EaäoÆ3x ¦=‘ÛªË<˜ú×%QÏoòýó Ü3qàƒA½mqΒ‘í›0ÝC±æÃQÝd±ò¸»+Å#º>¬8QÔl0¼]Â&Ò÷ÖqՍqç}ÂòÉâúå‘Ü©Qá`È!ÒõØ,$ñÀ‰hH,È£I1h:ŸÐ¨4ÚaN›+ÉêÊT›¸’¸„µuÛOÌsºJªUb)QRž…®”A(( b0MoP_M%,2 %  #%: %1ˆ%ŠOŒ‰/N%;%«£‚¥V§©¸¤n%$5¿ºN¦¨,ª“º## cc Njs*v7z%6a,)),%)o'88ÉVac-c>49Â3Jxð†š=/¼xXè¡ ( x‡C`xPe‘aC„]€RJ‡!Rª\ɲ¥Ë–‚; \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/theme/common/rss.gif dolibarr-svn/htdocs/theme/common/rss.gif --- dolibarr-snapshot/htdocs/theme/common/rss.gif 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/theme/common/rss.gif 2011-04-14 10:04:49.000000000 +0200 @@ -0,0 +1,6 @@ +GIF89a$Õ!ð®‚ðcÕXúôïŸAߞrÿ…4}3íɱÐr3å„CÂPñÔÀÿf糑ÿšWå^÷àÐÿrূÿÿÿÿ«sÔaÿѲ罡÷éàù²‚ðlÿ|$ÿöððÁ¡ÿÿÿ!ù ,address@hidden,HcCq8ŸÐ¨t*E4Ÿ‡rà@;–Eðݒ¡Vè¦Ân/address@hidden(.  tl + ……‹NiOk +‚l yl— y‘{k lšm¤‹´ ’|r +tm‹Ç°¼¾«‰ˆš   ‚ gÐkŽ‰‹° +™l +èªê»å"à’#,B`Î¥‚rà!(PP!‚‰±†9°ˆqÜ3 QÐy2•ƒ’%Ï8A9ò ‚bʜI³¦M›A; \ Pas de fin de ligne à la fin du fichier. diff -BNaur --exclude=CVS --exclude='*.patch' --exclude='.#*' --exclude='*~' --exclude='*.rej' --exclude='*.orig' --exclude='*.bak' --exclude=conf.php --exclude=documents dolibarr-snapshot/htdocs/theme/common/vcal.gif dolibarr-svn/htdocs/theme/common/vcal.gif --- dolibarr-snapshot/htdocs/theme/common/vcal.gif 1970-01-01 01:00:00.000000000 +0100 +++ dolibarr-svn/htdocs/theme/common/vcal.gif 2011-04-14 14:05:27.000000000 +0200 @@ -0,0 +1,2 @@ +GIF89a$÷ÿÿÿÿÿÌÿÿ™ÿÿfÿÿ3ÿÿÿÌÿÿÌÌÿ̙ÿÌfÿÌ3ÿÌÿ™ÿÿ™Ìÿ™™ÿ™fÿ™3ÿ™ÿfÿÿfÌÿf™ÿffÿf3ÿfÿ3ÿÿ3Ìÿ3™ÿ3fÿ33ÿ3ÿÿÿÌÿ™ÿfÿ3ÿÌÿÿÌÿÌÌÿ™ÌÿfÌÿ3ÌÿÌÌÿÌÌÌÌ̙ÌÌfÌÌ3ÌÌ̙ÿ̙Ì̙™Ì™f̙3̙ÌfÿÌfÌÌf™ÌffÌf3ÌfÌ3ÿÌ3ÌÌ3™Ì3fÌ33Ì3ÌÿÌÌ̙ÌfÌ3̙ÿÿ™ÿ̙ÿ™™ÿf™ÿ3™ÿ™Ìÿ™Ì̙̙™Ìf™Ì3™Ì™™ÿ™™Ì™™™™™f™™3™™™fÿ™f̙f™™ff™f3™f™3ÿ™3̙3™™3f™33™3™ÿ™Ì™™™f™3™fÿÿfÿÌfÿ™fÿffÿ3fÿfÌÿfÌÌf̙fÌffÌ3fÌf™ÿf™Ìf™™f™ff™3f™ffÿffÌff™fffff3fff3ÿf3Ìf3™f3ff33f3fÿfÌf™fff3f3ÿÿ3ÿÌ3ÿ™3ÿf3ÿ33ÿ3Ìÿ3ÌÌ3̙3Ìf3Ì33Ì3™ÿ3™Ì3™™3™f3™33™3fÿ3fÌ3f™3ff3f33f33ÿ33Ì33™33f333333ÿ3Ì3™3f333ÿÿÿÌÿ™ÿfÿ3ÿÌÿÌÌ̙ÌfÌ3̙ÿ™Ì™™™f™3™fÿfÌf™fff3f3ÿ3Ì3™3f333ÿ̙f3-!³óòý·²ñª¤î5'Ð+ «e +36(×5'Ó5'Ñ1$Ã)£#Œ/#º."µ-!°&•!€C5ÚPCÜ\Pßh]ámcâ|s勃茄蛔멣ïÁ¼óÅÁóÕÒ÷äâúñðüzq姡îÑÎöÿÿÿ!ùÿ,$ÿýmH° ÁƒŽã†­¡Ã‡#JŒèáĆìÚ±»È[Evâ9Ô¶»|ÙRêۈÍ]Jw#³µ£ÈPŸ¿†ãô §/