菜鸟学编程:为TeamToy的todo添加Due Date的功能

目标:为TeamToy的todo添加Due Date的功能。


TeamToy简介:

一个团队协作平台,有SAE迁移版本,可以在SAE上很轻松的部署:
http://sae.sina.com.cn/?m=recommendapps&a=detail&id=3 
(昨天的博文有更多功能介绍: http://lazycai.blog.51cto.com/690494/765201)

TeamToy完全按照lazyphp 框架的结构写的,代码和模板分离。
 
代码在code/mod/todo.class.php 
模板在view/layout/default(ajax)/todo/xxx.tpl.html 
lazyphp简介:  http://code.google.com/p/lazyphp/ 
 
代码文件概述:
 
code/mod/todo.class.php 
这里包含的主要是涉及数据操作的函数
 
view/layout/default/todo/index.tpl.html
进入teamtoy的todo首页的页面
 
view/layout/ajax/todo/xxx.tpl.html
这里的文件都是弹出窗口中包含的页面,一个页面一个功能,分别为
  • add 添加todo
  • assign_confirm 转让todo
  • link_confirm 关联todo到项目
  • modify 编辑todo
  • remove_confirm 删除todo
  • set_project 选择默认的项目
  • time 设置todo耗时
添加Due Date功能的思路(编程小白的实验):
 
1、数据结构更改,在主表下的todo表中增添due_date的域,类型为DATE
(注:我的due_date域添加在了todo表的末尾,不知道是否添加在desp域的后面更加合适)
 
2、进入 code/mod/todo.class.php ,搜索`desp`(写入数据库的操作),找到了save和update两个function,加点料:
     public function update()
     {
          $tid = intval(v('tid'));
          if( $tid < 1 ) return ajax_box('错误的TODO ID');
          
          $todo = z(v('todo'));
          $link = z(v('link'));
          $desp = z(v('desp'));
          $due_date = z(v('due_date'));

          //如果期限未设置,则设置默认期限为当日
          if($due_date=="") $due_date = date("Y-m-d");

          if( $todo == '' ) return ajax_box('TODO内容不能为空');
          
          $sql = "UPDATE `todo` SET  `name` = '" . s($todo) . "' , `link` = '" . s($link) . "' , `desp` = '" . s($desp) . "' , `due_date` = '" . $due_date . "' WHERE `id` = '" .intval($tid) . "' AND `uid` = '" . uid() . "' LIMIT 1 "; ... } public function save() {
          $todo = z(v('todo'));
          $link = z(v('link'));
          $desp = z(v('desp'));
          $due_date = z(v('due_date'));
          $pid = intval(v('pid'));
          
          //如果期限未设置,则设置默认期限为当日
          if($due_date=="") $due_date = date("Y-m-d");
          ...
          
          $sql = "INSERT INTO `todo` (  `name` , `link` , `desp`  , `uid` , `creator_uid` , `pid` , `is_done` , `follow_uids` ,  `timeline` , `check_time`, `due_date` ) VALUES (    '" . s($todo) . "'  ,  '" . s($link) . "',  '" . s($desp) . "' , '" . $uid . "'  , '" . uid() . "'  ,  '" . intval($pid) . "' , '" . intval( $is_done ) . "'  , '" . s( serialize( $follow_uids ) ) . "' , NOW() , NOW() , '" . $due_date . "' )";
          
          ...
     }
 
3、进入 view/layout/ajax/todo/ 下的 add.tpl.html 和 modify.tpl.html,添加due_date的输入框:
 
add页面,按钮部分,放在原本【链接】的功能之前:
<a href="javascript:$('todo_due_date').setStyle('display' ,'');void(0)">期限</a>&nbsp;&nbsp;<img src=\'#\'" /image/paperclip.gif" />&nbsp;<a href="javascript:$('todo_link').setStyle('display' ,'');void(0)">链接</a>
 
add页面,输入框部分放在后面,照着抄一个:
<div id="todo_due_date" style="display:none;padding-top:5px"><input type="text" name="due_date" class="text" style="width:300px" /></div>
 
modify页面如法炮制,就是输入框部分预先调用一下数据:
 
<div id="todo_due_date" style="<?php if( $tinfo['due_date'] == '' ){ echo 'display:none;'; } ?>padding-top:5px"><input type="text" name="due_date" class="text" style="width:300px" value="<?=$tinfo['due_date']?>" /></div>
 
现在全都Commit一下,上线测试,发现基本功能已经有了,哦也~
 
接下来就是一些细化的工作:
 
4、输入框修改成日期选择框
 
日期选择框(datepicker)有一些现成的jquery实现,当然,这也要求页面预先include一些js脚本。整个TeamToy的脚本嵌入在
code\view\layout\default\index.tpl.html
这个页面当中控制。
 
在TeamToy的代码库中,可以找到一个现成的Calendar脚本:
\static\script\calendar.compat.js
可以从代码里面看看相关的说明。这是一个基于mootools重写的插件,脚本的引用要添加在mootools的引用之后。
从index.tpl.html可以看到,原本已经引用了moo.min.js和core.min.js。由于calendar需要的功能比moo.min.js提供的要多,所以需要去mootools官网获取更多文件。Mootools当前最新版本已经是1.4.x,而calendar基于mootools 1.1.x,里面的Fx.Style等功能已经改没了。选项有三:
a)修改calendar.js以适应新版
b)找一个1.1.x的mootools
c)找另一个calendar插件
TeamToy全局使用的moo.min.js是1.2.1版本的,所以b排除;a看了一下,比较麻烦,所以用了方法c。
 
先将moo.min.js更新到1.2.5的内容:
http://mootools.net/download/version/1.2.5
另外找了一个calendar插件,就叫datepicker:
http://www.monkeyphysics.com/mootools/script/2/datepicker
然后就很好办啦。在code\view\layout\default\index.tpl.html中加入相关的css和script:
<link rel="stylesheet" type="text/css" href="static/css/datepicker.css">
<script type="text/javascript" src=\'#\'" /script/datepicker.js" ></script>

到modify.tpl.html(这个功能方便做测试,所以先做它),将之前的input再做一下修改:
<input type="text" id="due_date" name="due_date" class="text" style="width:200px" value="<?=$tinfo['due_date']?>" />
<img src=\'#\'" /image/transparent.gif" DatePicker('#due_date', { format: 'Y-m-d', inputOutputFormat: 'Y-m-d', positionOffset: { x: 0, y: 5 } }); "/>
(因为teamtoy是ajax页面,所以作者给的方式不管用,只好借用了一个image onload来做触发条件)

commit后测试,成功,就是datepicker的显示被编辑窗口给盖住了。所以再去修改一下datepicker.css,给.datepicker添加一个 z-index: 9999; 就ok了。
modify修改完毕,再对add如法炮制一通即可。

5、侧边栏加入相同的功能
 
找到code\view\layout\default\sidebar_top.tpl.html,按钮后面添加如下代码搞定:
<div style="padding-top:5px;">期限:<input type="text" id="due_date" name="due_date" class="text" style="width:80px" value="<?=date('Y-m-d')?>" />
<img src=\'#\'" /image/transparent.gif" DatePicker('#due_date', { format: 'Y-m-d', inputOutputFormat: 'Y-m-d', positionOffset: { x: 0, y: 5 } }); "/></div> 

6、在todo列表中显示due_date,并按照due_date排序
 
先去 code\view\layout\default\main\todo\index.tpl.html 里面查看一下,找到todo checkbox的位置,后面添加一行这个即可显示due_date:
<label>[<?=$todo['due_date']?>]</label> 
如果觉得YYYY-mm-dd显示太长了,可以缩减为mm-dd格式(感谢不乖的指点):
<label>[<?=date('m-d',strtotime($todo['due_date']))?>]</label>
排序可以从index.tpl.html中看到引用了$date['todos_open'],进入 todo.class.php 中找到 $data['todos_open'] ,修改当中的ORDER BY 后面的部分就行:
 
todos_open 按照 ORDER BY `is_start` DESC , `due_date` 排序。
 
这样就基本差不多啦!先show一下当前的效果:
 

 

7、设置任务循环周期,如每天/每周/每月重复(默认为不重复)
 
这个暂时还没想好怎么做,初步构思后发现可能还是有点复杂,回头单开帖子吧。
 
其他修改:

·侧边栏todo直接按enter提交
在view/layout/default/sidebar_top.tpl.html处修改,将
<input type="button" class="button" value="添加"
更改为
<input type="submit" class="button" value="添加"
不过,用enter键提交也有一个问题,就是ajax页面在提交后并不刷新,导致容易被判定为连续提交,而弹出“todo内容不能为空”的提示。
为了解决这个问题,还需要进一步修改sidebar_top.tpl.html当中与form相关的部分:
onsubmit="show_float_box('?m=todo&a=save&pid=<?=get_current_pid()?>&todo=' + encodeURIComponent( $('todo_box_side').value ));$('todo_box_side').value='';$('todo_side_link').value='';$('todo_side_link').setStyle('display' ,'none');return false;void(0)"
这里需要添加一个todo_box_side是否为空的判定,如果为空就啥都不做:
onsubmit="if($('todo_box_side').value != ''){show_float_box('?m=todo&a=save&pid=<?=get_current_pid()?>&todo=' + encodeURIComponent( $('todo_box_side').value ));$('todo_box_side').value='';$('todo_side_link').value='';$('todo_side_link').setStyle('display' ,'none');}return false;void(0)"
(注意if结束的括号位置)
至于按钮部分的
 onclick="if($('todo_box_side').value != ''){send_form_pop('form_todo_side');$('todo_box_side').value='';}else{$('todo_box_side').value='这里不能为空哦!';$('todo_box_side').focus();}"
这段貌似没有效果,所以删除了。
--更正--
之前删除的button上的send_form_pop实际上是必需的,否则form上面原本的onsubmit部分的代码只会把todo的内容传走,其他的链接、备注、due_date信息都没传走。
所以,form那行还需要修改一下:
<form action="?m=todo&a=save&pid=<?=get_current_pid()?>" method="post" id="form_todo_side" onsubmit="if($('todo_box_side').value != ''){send_form_pop('form_todo_side');$('todo_box_side').value='';$('todo_side_link').value='';$('todo_side_link').setStyle('display' ,'none');}return false;void(0)">
 
其他一些感想:
  • Subversion果然比FTP的土鳖方式强悍多了,Tortoise的设计很人性化,只是一开始没搞清楚Checkout、Commit和Update都是干啥的,折腾了一下下
  • NotePad++确实是神器!不仅可以用Project View一边看目录一边看文件,还有Subversion的插件可以用~
 
 

你可能感兴趣的:(编程,职场,休闲,TeamToy)