目标:为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页面,按钮部分,放在原本【链接】的功能之前:
期限链接
add页面,输入框部分放在后面,照着抄一个:
modify页面如法炮制,就是输入框部分预先调用一下数据:
现在全都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:
到modify.tpl.html(这个功能方便做测试,所以先做它),将之前的input再做一下修改:
(因为teamtoy是ajax页面,所以作者给的方式不管用,只好借用了一个p_w_picpath onload来做触发条件)
commit后测试,成功,就是datepicker的显示被编辑窗口给盖住了。所以再去修改一下datepicker.css,给.datepicker添加一个 z-index: 9999; 就ok了。
modify修改完毕,再对add如法炮制一通即可。
5、侧边栏加入相同的功能
找到code\view\layout\default\sidebar_top.tpl.html,按钮后面添加如下代码搞定:
期限:
6、在todo列表中显示due_date,并按照due_date排序
先去 code\view\layout\default\main\todo\index.tpl.html 里面查看一下,找到todo checkbox的位置,后面添加一行这个即可显示due_date:
如果觉得YYYY-mm-dd显示太长了,可以缩减为mm-dd格式(感谢不乖的指点):
排序可以从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处修改,将
更改为
不过,用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那行还需要修改一下:
其他一些感想:
- Subversion果然比FTP的土鳖方式强悍多了,Tortoise的设计很人性化,只是一开始没搞清楚Checkout、Commit和Update都是干啥的,折腾了一下下
- NotePad++确实是神器!不仅可以用Project View一边看目录一边看文件,还有Subversion的插件可以用~