Commit adeebc7f authored by Frank Bergmann's avatar Frank Bergmann

Initial Import

parents
Pipeline #159 failed with stages
<?xml version="1.0" encoding="ISO-8859-1"?>
<message_catalog package_key="intranet-agile" locale="de_DE" charset="ISO-8859-1">
<msg key="Agile_Tasks">Agile Element</msg>
<msg key="Agile_Mgmt">Agilemanagement</msg>
<msg key="Agile_Projects">Agile Projekte</msg>
</message_catalog>
<?xml version="1.0" encoding="ISO-8859-1"?>
<message_catalog package_key="intranet-agile" locale="en_US" charset="ISO-8859-1">
<msg key="Agile_Tasks">Agile Tasks</msg>
<msg key="Agile_Mgmt">Agile Mgmt</msg>
<msg key="Agile_Projects">Agile Projects</msg>
</message_catalog>
<?xml version="1.0" encoding="ISO-8859-1"?>
<message_catalog package_key="intranet-agile" locale="es_ES" charset="ISO-8859-1">
<msg key="Agile_Mgmt">Gestin de agiles</msg>
<msg key="Agile_Projects">Proyectos de agile</msg>
</message_catalog>
<?xml version="1.0" encoding="ISO-8859-1"?>
<message_catalog package_key="intranet-agile" locale="it_IT" charset="ISO-8859-1">
<msg key="Agile_Mgmt">Gestione agile</msg>
<msg key="Agile_Projects">Progetti agile</msg>
</message_catalog>
<?xml version="1.0" encoding="ISO-8859-1"?>
<message_catalog package_key="intranet-agile" locale="nl_NL" charset="ISO-8859-1">
<msg key="Agile_Mgmt">Agile Mgmt</msg>
<msg key="Agile_Projects">Vrijgeven projecten</msg>
</message_catalog>
<?xml version="1.0" encoding="utf-8"?>
<message_catalog package_key="intranet-agile" locale="zh_CN" charset="utf-8">
<msg key="Agile_Mgmt">发布管理</msg>
<msg key="Agile_Projects">发布项目</msg>
</message_catalog>
<?xml version="1.0"?>
<!-- Generated by the OpenACS Package Manager -->
<package key="intranet-agile" url="http://openacs.org/repository/apm/packages/intranet-agile" type="apm_application">
<package-name>]project-open[ Agile</package-name>
<pretty-plural>]project-open[ Agile</pretty-plural>
<initial-install-p>f</initial-install-p>
<singleton-p>t</singleton-p>
<auto-mount>intranet-agile</auto-mount>
<version name="5.0.0.0.0" url="http://www.project-open.org/download/apm/intranet-agile-5.0.0.0.0.apm">
<owner url="mailto:frank.bergmann@project-open.com">Frank Bergmann</owner>
<summary>Support for agile methodologies including SCRUM, Kanban etc.</summary>
<vendor url="http://www.project-open.com/">]project-open[</vendor>
<description format="text/plain">Defines various agile workflows and provides task boards and burn-down charts.</description>
<provides url="intranet-agile" version="3.2.11.0.0"/>
<requires url="intranet-core" version="3.2"/>
<requires url="intranet-dynfield" version="3.2"/>
<callbacks>
</callbacks>
<parameters>
<parameter datatype="string" min_n_values="1" max_n_values="1" name="TaskCustomColumns" description="A list of DynField custom variables to show in the task list. You can use the associated &quot;_deref&quot; values for integer values such as user ids etc. Example: Let's asume a DynField &quot;pl_area&quot; in &quot;im_projects&quot;, referring to an Area Project Leader. Then DynFields define a &quot;pl_area_deref&quot; variable that you can use here. Multiple variables of this type can be specified separated by a space."/>
</parameters>
</version>
</package>
<?xml version="1.0"?>
<queryset>
<rdbms><type>postgresql</type><version>7.1</version></rdbms>
<fullquery name="journal_select">
<querytext>
select j.journal_id,
j.action,
j.action_pretty,
o.creation_date,
to_char(o.creation_date, :date_format) as creation_date_pretty,
o.creation_user,
acs_object__name(o.creation_user) as creation_user_name,
p.email as creation_user_email,
o.creation_ip,
j.msg,
a.attribute_name as attribute_name,
a.pretty_name as attribute_pretty_name,
a.datatype as attribute_datatype,
v.attr_value as attribute_value
from (journal_entries j LEFT OUTER JOIN wf_attribute_value_audit v
on (j.journal_id = v.journal_id)) LEFT OUTER JOIN acs_attributes a
on (v.attribute_id = a.attribute_id),
acs_objects o left outer join parties p on (o.creation_user = p.party_id)
where j.object_id = :object_id
and o.object_id = j.journal_id
order by o.creation_date $sql_order, j.journal_id $sql_order
</querytext>
</fullquery>
</queryset>
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td bgcolor="#cccccc" colspan="2">
<table width="100%" cellspacing="1" cellpadding="2" border="0">
<tr>
<td colspan="5" bgcolor="#ccccff">
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<th width="20%">&nbsp;</th>
<th>Journal</th>
<td width="20%" align="right">
</td>
</tr>
</table>
</td>
</tr>
<if @journal:rowcount@ eq 0>
<tr bgcolor="#ffffe4">
<td>
<em>No actions yet.</em>
</td>
</tr>
</if>
<if @journal:rowcount@ ne 0>
<tr bgcolor="#ffffe4">
<th align="left">Action</th>
<th align="left">Date</th>
<th align="left">User</th>
<th align="left">Output</th>
<th align="left">Comment</th>
</tr>
</if>
<multiple name="journal">
<tr bgcolor="#eeeeee">
<td>@journal.action_pretty@</td>
<td>@journal.creation_date_pretty@</td>
<td><a href="/shared/community-member?user_id=@journal.creation_user@">@journal.creation_user_name@</a></td>
<td>
<if @journal.attribute_pretty_name@ nil>&nbsp;</if>
<if @journal.attribute_pretty_name@ not nil>
<group column="journal_id">
@journal.attribute_pretty_name@: @journal.attribute_value@<br>
</group>
</if>
</td>
<td>
<if @journal.msg@ nil>&nbsp;</if>
<if @journal.msg@ not nil>@journal.msg@</if>
</td>
</tr>
</multiple>
</table>
</td>
</tr>
</table>
# assume that the following are set:
# object_id
set workflow_url [apm_package_url_from_key "acs-workflow"]
set return_url [ns_urlencode "[ad_conn url]?[ad_conn query]"]
if { ![info exists date_format] || $date_format eq "" } {
set date_format "Mon fmDDfm, YYYY HH24:MI:SS"
}
if { ![info exists order] || $order eq "" } {
set order latest_first
}
if { ![info exists comment_link] || $comment_link eq "" } {
set comment_link 1
}
switch -- $order {
latest_first {
set sql_order "desc"
}
latest_last {
set sql_order "asc"
}
default {
return -code error "Order must be latest_first or latest_last"
}
}
set entries [list]
db_multirow journal journal_select ""
<listtemplate name="referencing_projects"></listtemplate>
# -------------------------------------------------------------
# intranet-agile/www/referencing-projects.tcl
#
# (c) 2003-2007 ]project-open[
# All rights reserved
# Author: frank.bergmann@project-open.com
#
# Display component
# Shows all projects with this agile as agile_project.
# -------------------------------------------------------------
# Variables:
# project_id:integer
# return_url
set page_title [lang::message::lookup "" intranet-agile.Referencing_Project "Referencing Projects"]
set package_url "/intranet-agile"
set agile_project_id $project_id
set return_url [im_url_with_query]
# -------------------------------------------------------------
# Permissions
#
# The project admin (=> Agile Manager) can do everything.
# The managers of the individual Agile Tasks can change
# _their_ agile stati.
set user_id [auth::require_login]
im_project_permissions $user_id $project_id view read write admin
set edit_all_tasks_p $write
# -------------------------------------------------------------
# Create the list
set bulk_actions_list [list]
set elements {
project_name {
display_col project_name
label "Name"
link_url_eval $project_url
}
}
set custom_cols [parameter::get_from_package_key -package_key "intranet-agile" -parameter "AgileMgmtReferencingProjectsCustomColumns" -default ""]
foreach col $custom_cols {
set col_title [lang::message::lookup "" intranet-agile.[lang::util::suggest_key $col] $col]
lappend elements $col
lappend elements [list label $col_title ]
}
list::create \
-name referencing_projects \
-multirow referencing_projects \
-key project_id \
-row_pretty_plural $page_title \
-selected_format "normal" \
-class "list" \
-main_class "list" \
-sub_class "narrow" \
-actions { } \
-has_checkboxes \
-bulk_actions $bulk_actions_list \
-bulk_action_export_vars {
agile_project_id
return_url
} \
-bulk_action_method GET \
-elements $elements
db_multirow -extend { project_url } referencing_projects select_referencing_projects "
select p.*
from im_projects p
where p.agile_project_id = :project_id
order by lower(p.project_name)
" {
set project_url [export_vars -base "/intranet/projects/view?" {project_id return_url}]
}
<if @show_master_p@>
<master>
<property name="doc(title)">@page_title;literal@</property>
<property name="main_navbar_label">projects</property>
</if>
<style>
.fullwidth-list .component table.taskboard td {
vertical-align:top;
}
</style>
<table class="taskboard">
<tr>
@top_html;noquote@
</tr>
<tr>
@body_html;noquote@
</tr>
</table>
# /packages/intranet-agile/www/task-board.tcl
#
# Copyright (c) 2003-2010 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/ for licensing details.
# Expected variables:
# agile_project_id
set show_master_p 0
if {![info exists agile_project_id]} {
set show_master_p 1
ad_page_contract {
Show agile tasks with their status
@author Frank Bergmann (frank.bergmann@project-open.com)
@creation-date May 29, 2002
@cvs-id $Id$
} {
agile_project_id:integer
}
}
# ------------------------------------------------------------
# Page Title & Help Text
set page_title [lang::message::lookup "" intranet-agile.Task_Board "Task Board"]
set context_bar [im_context_bar $page_title]
set context ""
set return_url [im_url_with_query]
# ------------------------------------------------------------
# Defaults
set company_url "/intranet/companies/view?company_id="
set project_url "/intranet/projects/view?project_id="
set invoice_url "/intranet-invoices/view?invoice_id="
set user_url "/intranet/users/view?user_id="
set this_url [export_vars -base "/intranet-agile/task-board" {agile_project_id} ]
set task_board_action_url "/intranet-agile/task-board-action"
# ------------------------------------------------------------
# Get Top Dimension (Agile Status)
set top_states_sql "
select *
from im_categories c
where category_type = 'Intranet Agile Status' and
(c.enabled_p = 't' OR c.enabled_p is NULL)
order by category_id
"
set top_html ""
set top_states_list [list]
db_foreach top_states $top_states_sql {
append top_html "<td class=rowtitle>$category</td>\n"
lappend top_states_list $category_id
}
# ------------------------------------------------------------
# Calculate the tasks to be displayed
set tasks_sql "
select task.*,
ri.*,
im_category_from_id(ri.agile_status_id) as agile_status
from im_projects relp,
im_projects task,
acs_rels r,
im_agile_task_rels ri
where
relp.project_id = :agile_project_id and
r.object_id_one = relp.project_id and
r.object_id_two = task.project_id and
r.rel_id = ri.rel_id
order by ri.sort_order
"
db_foreach tasks $tasks_sql {
set cell ""
if {[info exists cell_hash($agile_status_id)]} { set cell $cell_hash($agile_status_id) }
set color "grey"
set left_url [export_vars -base $task_board_action_url {{agile_task_id $project_id} return_url {action left} agile_project_id}]
set right_url [export_vars -base $task_board_action_url {{agile_task_id $project_id} return_url {action right} agile_project_id}]
set up_url [export_vars -base $task_board_action_url {{agile_task_id $project_id} return_url {action up} agile_project_id}]
set down_url [export_vars -base $task_board_action_url {{agile_task_id $project_id} return_url {action down} agile_project_id}]
append cell "
<table width=150 bgcolor=$color>
<tr><td colspan=3 align=center><a href='$up_url'>[im_gif arrow_up]</a></td></tr>
<tr>
<td><a href='$left_url'>[im_gif arrow_left]</a></td>
<td>$project_name</td>
<td><a href='$right_url'>[im_gif arrow_right]</a></td>
</tr>
<tr><td colspan=3 align=center><a href='$down_url'>[im_gif arrow_down]</a></td></tr>
</table>
<br>
"
set cell_hash($agile_status_id) $cell
}
# ------------------------------------------------------------
# Render the table body
set body_html ""
foreach agile_status_id $top_states_list {
set cell ""
if {[info exists cell_hash($agile_status_id)]} { set cell $cell_hash($agile_status_id) }
append body_html "
<td>$cell</td>
"
}
# ---------------------------------------------------------------
# Navbar
# ---------------------------------------------------------------
# Setup the subnavbar
set bind_vars [ns_set create]
ns_set put $bind_vars project_id $agile_project_id
set show_context_help_p 0
set parent_menu_id [im_menu_id_from_label "project"]
set menu_label "agile_tasks"
set sub_navbar_html [im_sub_navbar \
-base_url "/intranet/projects/view?project_id=$agile_project_id" \
$parent_menu_id \
$bind_vars "" "pagedesriptionbar" $menu_label]
<listtemplate name="agile_tasks"></listtemplate>
<ul>
<if @edit_all_tasks_p@>
<li><a href="@add_task_url@"
><%= [lang::message::lookup "" intranet-agile.Add_Agile_Tasks "Add Agile Tasks"] %></a>
</if>
</ul>
# -------------------------------------------------------------
# intranet-agile/www/view-list-display.tcl
#
# (c) 2003-2007 ]project-open[
# All rights reserved
# Author: frank.bergmann@project-open.com
#
# Display component - this component is being used both by a
# ]po[ "component" and by the normal list page.
# -------------------------------------------------------------
# Variables:
# project_id:integer
# return_url
set page_title [lang::message::lookup "" intranet-agile.Tasks "Tasks"]
set package_url "/intranet-agile"
set project_id $project_id
set return_url [im_url_with_query]
set add_task_url [export_vars -base "/intranet-agile/add-tasks" {project_id return_url}]
# -------------------------------------------------------------
# Permissions
#
# The project admin can do everything.
# The managers of the individual tasks can change _their_ agile states
set user_id [auth::require_login]
im_project_permissions $user_id $project_id view read write admin
set edit_all_tasks_p $write
# -------------------------------------------------------------
# Create the list
set bulk_actions_list [list]
lappend bulk_actions_list "Save Status Changes" "$package_url/save-tasks" "Save status of tasks"
if {$edit_all_tasks_p} { lappend bulk_actions_list "Delete Checked Tasks" "$package_url/del-tasks" "Removed checked tasks" }
set elements {
task_name {
display_col task_name
label "Task"
link_url_eval $task_url
}
project_lead_id {
display_col project_lead_name
label "Project Manager"
link_url_eval $project_lead_url
}
}
set custom_cols [parameter::get_from_package_key -package_key "intranet-agile" -parameter "TaskCustomColumns" -default ""]
foreach col $custom_cols {
set col_title [lang::message::lookup "" intranet-agile.[lang::util::suggest_key $col] $col]
lappend elements $col
lappend elements [list label $col_title ]
}
lappend elements agile_status
lappend elements {
label "Agile Status"
display_template {
@agile_tasks.agile_status_template;noquote@
}
}
lappend elements sort_order
lappend elements {
label "Ord"
display_template { @agile_tasks.sort_order_template;noquote@ }
}
lappend elements task_chk
lappend elements {
label "<input type=\"checkbox\"
name=\"_dummy\"
onclick=\"acs_ListCheckAll('task_list', this.checked)\"
title=\"Check/uncheck all rows\">"
display_template {
@agile_tasks.task_chk;noquote@
}
}
list::create \
-name agile_tasks \
-multirow agile_tasks \
-key agile_task \
-row_pretty_plural $page_title \
-checkbox_name checkbox \
-selected_format "normal" \
-class "list" \
-main_class "list" \
-sub_class "narrow" \
-actions { } \
-has_checkboxes \
-bulk_actions $bulk_actions_list \
-bulk_action_export_vars {
project_id
return_url
} \
-bulk_action_method GET \
-elements $elements
set extra_selects [list "0 as zero"]
set column_sql "
select w.deref_plpgsql_function,
aa.attribute_name
from im_dynfield_widgets w,
im_dynfield_attributes a,
acs_attributes aa
where a.widget_name = w.widget_name and
a.acs_attribute_id = aa.attribute_id and
aa.object_type = 'im_project'
"
db_foreach column_list_sql $column_sql {
lappend extra_selects "${deref_plpgsql_function}($attribute_name) as ${attribute_name}_deref"
}
set extra_select [join $extra_selects ",\n\t"]
db_multirow -extend {
agile_task_url
agile_status_template
task_chk
project_lead_url
sort_order_template
} agile_tasks select_agile_tasks "
select
perm.admin_p,
i.agile_status_id,
im_category_from_id(i.agile_status_id) as agile_status,
p.project_name as task_name,
p.project_id as task_id,
im_name_from_user_id(p.project_lead_id) as project_lead_name,
p.*,
i.sort_order,
$extra_select
from
im_projects p
LEFT OUTER JOIN (
select count(*) as admin_p,
r.object_id_one as project_id
from acs_rels r,
im_biz_object_members m
where object_id_two = 624
and m.rel_id = r.rel_id
and m.object_role_id = 1301
group by
project_id
) perm ON (p.project_id = perm.project_id),
acs_rels r,
im_agile_task_rels i
where
r.rel_id = i.rel_id
and r.object_id_two = p.project_id
and r.object_id_one = :project_id
order by
i.sort_order
" {
set agile_task_url [export_vars -base "/intranet/projects/view?" {project_id return_url}]
set project_lead_url [export_vars -base "/intranet/users/view?" {{user_id $project_lead_id} return_url}]
set agile_status_template $agile_status
if {$edit_all_tasks_p || ("" != $admin_p && $admin_p)} {
set agile_status_template [im_category_select "Intranet Agile Status" "agile_status_id.$task_id" $agile_status_id]
}
set task_chk "<input type=\"checkbox\"
name=\"task_id\"
value=\"$task_id\"
id=\"task_list,$task_id\">
"
# set sort_order_template "
# <nobr>
# <a href=\"[export_vars -base "/intranet-agile/order-task" {{dir up} project_id project_id return_url} ]\">[im_gif arrow_comp_up]</a>
# <a href=\"[export_vars -base "/intranet-agile/order-task" {{dir down} project_id project_id return_url} ]\">[im_gif arrow_comp_down]</a>
# </nobr>
# "
set sort_order_template "
<input type=text name=\"agile_sort_order.$task_id\" size=5 value=\"$sort_order\">
"
}
-- /packages/intranet-agile/sql/postgresql/intranet-agile-create.sql
--
-- Copyright (c) 2003 - 2009 ]project-open[
--
-- All rights reserved. Please check
-- http://www.project-open.com/license/ for details.
--
-- @author frank.bergmann@project-open.com
-- --------------------------------------------------------
-- Agile Task - Agile Releationship
--
-- This relationship connects "Agile" projects with other
-- "Agile Task" projects. The agile_status_id determines
-- the readyness for the task in the parent agile.
-- --------------------------------------------------------
create table im_agile_task_rels (
rel_id integer
constraint im_agile_task_rels_rel_fk
references acs_rels (rel_id)
constraint im_agile_task_rels_rel_pk
primary key,
agile_status_id integer not null
constraint im_agile_task_rels_role_fk
references im_categories,
sort_order integer
);
select acs_rel_type__create_type (
'im_agile_task_rel', -- relationship (object) name
'Agile Task Rel', -- pretty name
'Agile Task Rel', -- pretty plural
'relationship', -- supertype
'im_agile_task_rels', -- table_name
'rel_id', -- id_column
'intranet-agile', -- package_name
'im_project', -- object_type_one
'member', -- role_one
0, -- min_n_rels_one
null, -- max_n_rels_one
'acs_object', -- object_type_two
'member', -- role_two
0, -- min_n_rels_two
null -- max_n_rels_two
);
create or replace function im_agile_task_rel__new (
integer, varchar, integer, integer, integer, integer, varchar, integer, integer)
returns integer as $body$
DECLARE
p_rel_id alias for $1; -- null
p_rel_type alias for $2; -- im_agile_task_rel
p_agile_id alias for $3;
p_task_id alias for $4;
p_context_id alias for $5;
p_creation_user alias for $6; -- null
p_creation_ip alias for $7; -- null
p_agile_status_id alias for $8;
p_sort_order alias for $9;
v_rel_id integer;
BEGIN
v_rel_id := acs_rel__new (
p_rel_id,
p_rel_type,
p_agile_id,
p_task_id,
p_context_id,
p_creation_user,
p_creation_ip
);
insert into im_agile_task_rels (
rel_id, agile_status_id, sort_order
) values (
v_rel_id, p_agile_status_id, p_sort_order
);
return v_rel_id;
end;$body$ language 'plpgsql';
create or replace function im_agile_task_rel__delete (integer)
returns integer as $body$
DECLARE
p_rel_id alias for $1;
BEGIN
delete from im_agile_task_rels
where rel_id = p_rel_id;
PERFORM acs_rel__delete(p_rel_id);
return 0;
end;$body$ language 'plpgsql';
create or replace function im_agile_task_rel__delete (integer, integer)
returns integer as $body$
DECLARE
p_object_id alias for $1;
p_user_id alias for $2;
v_rel_id integer;
BEGIN
select rel_id into v_rel_id
from acs_rels
where object_id_one = p_object_id
and object_id_two = p_user_id;
PERFORM im_agile_task_rel__delete(v_rel_id);
return 0;
end;$body$ language 'plpgsql';
---------------------------------------------------------
-- Agile Components
--
-- Show the forum component in project page
--
SELECT im_component_plugin__new (
null, -- plugin_id
'im_component_plugin', -- object_type
now(), -- creation_date
null, -- creation_user
null, -- creation_ip
null, -- context_id
'Agile Tasks', -- plugin_name
'intranet-agile', -- package_name
'bottom', -- location
'/intranet/projects/view', -- page_url
null, -- view_name
30, -- sort_order
'im_agile_project_component -project_id $project_id -return_url $return_url',
'lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"'
);
SELECT acs_permission__grant_permission(
(select plugin_id from im_component_plugins where plugin_name = 'Agile Tasks' and package_name = 'intranet-agile'),
(select group_id from groups where group_name = 'Employees'),
'read'
);
-- Task Board component
--
SELECT im_component_plugin__new (
null, -- plugin_id
'im_component_plugin', -- object_type
now(), -- creation_date
null, -- creation_user
null, -- creation_ip
null, -- context_id
'Plain Task Board', -- plugin_name
'intranet-agile', -- package_name
'bottom', -- location
'/intranet/projects/view', -- page_url
null, -- view_name
10, -- sort_order - top one of the "bottom" portlets
'im_agile_task_board_component -project_id $project_id',
'lang::message::lookup "" intranet-agile.Task_Board "Task Board"'
);
SELECT acs_permission__grant_permission(
(select plugin_id from im_component_plugins where plugin_name = 'Plain Task Board' and package_name = 'intranet-agile'),
(select group_id from groups where group_name = 'Employees'),
'read'
);
---------------------------------------------------------
-- Add category types
---------------------------------------------------------
-- 88000-88999 Agile Methodologies (1000)
-- 88000-88099 Intranet Project Type extensions (100)
-- 88100-88199 Intranet Agile SCRUM States (100)
-- 88200-88299 Intranet Agile Kanban States (100)
-- 88300-88999 still free
SELECT im_category_new(88000, 'Agile Project', 'Intranet Project Type',null);
SELECT im_category_new(88010, 'SCRUM', 'Intranet Project Type',null);
SELECT im_category_new(88020, 'Kanban', 'Intranet Project Type',null);
SELECT im_category_hierarchy_new(88010, 88000);
SELECT im_category_hierarchy_new(88020, 88000);
-- Define the category types with the states for each of the agile project types
update im_categories set
category_description = 'Project using an agile methodology'
where category_id = 88000;
update im_categories set
aux_string1 = 'Intranet Agile SCRUM States',
category_description = 'Project using SCRUM agile methodology',
sort_order = 10
where category_id = 88010;
update im_categories set
aux_string1 = 'Intranet Agile Kanban States',
category_description = 'Project using Kanban agile methodology',
sort_order = 20
where category_id = 88020;
create or replace view im_agile_scrum_status as
select category_id as status_id, category as status
from im_categories
where category_type = 'Intranet Agile SCRUM Status';
create or replace view im_agile_kanban_status as
select category_id as status_id, category as status
from im_categories
where category_type = 'Intranet Agile Kanban Status';
---------------------------------------------------------
-- DynField to mark agile tasks
---------------------------------------------------------
create or replace function inline_0 ()
returns integer as $body$
declare
v_attrib_name varchar;
v_attrib_pretty varchar;
v_acs_attrib_id integer;
v_attrib_id integer;
v_count integer;
begin
v_attrib_name := 'agile_task_p';
v_attrib_pretty := 'Agile Task';
select count(*) into v_count from acs_attributes
where attribute_name = v_attrib_name;
IF 0 != v_count THEN return 0; END IF;
v_acs_attrib_id := acs_attribute__create_attribute (
'im_project',
v_attrib_name,
'boolean',
v_attrib_pretty,
v_attrib_pretty,
'im_projects',
NULL, NULL, '0', '1',
NULL, NULL, NULL
);
alter table im_projects add agile_task_p varchar(1);
v_attrib_id := acs_object__new (
null,
'im_dynfield_attribute',
now(),
null, null, null
);
insert into im_dynfield_attributes
(attribute_id, acs_attribute_id, widget_name, deprecated_p) values
( v_attrib_id, v_acs_attrib_id, 'checkbox', 'f');
insert into im_dynfield_type_attribute_map (
attribute_id, object_type_id, display_mode
) values (
v_attrib_id, 4599, 'edit'
);
return 0;
end;$body$ language 'plpgsql';
-- select inline_0 ();
-- drop function inline_0();
-- /packages/intranet-agile/sql/postgresql/intranet-agile-drop.sql
--
-- Copyright (c) 2003-2007 ]project-open[
--
-- All rights reserved. Please check
-- http://www.project-open.com/license/ for details.
--
-- @author frank.bergmann@project-open.com
-----------------------------------------------------
-- Drop menus and components defined by the module
select im_menu__del_module('intranet-agile');
select im_component_plugin__del_module('intranet-agile');
# /packages/intranet-agile/tcl/intranet-agile.tcl
#
# Copyright (c) 2003-2007 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/license/ for details.
ad_library {
Library for ]po[ specific agile functionality
@author frank.bergmann@project-open.com
}
# ----------------------------------------------------------------------
# States and Types
# ----------------------------------------------------------------------
ad_proc -public im_project_type_agile {} { return 88000 }
ad_proc -public im_project_type_scrum {} { return 88010 }
ad_proc -public im_project_type_kanban {} { return 88020 }
ad_proc -public im_agile_scrum_status_default {} { return 88100 }
# ----------------------------------------------------------------------
#
# ----------------------------------------------------------------------
ad_proc -public im_package_agile_id {} {
Returns the package id of the intranet-agile module
} {
return [util_memoize [list db_string im_package_agile_id "select package_id from apm_packages where package_key = 'intranet-agile'" -default 0]]
}
# ----------------------------------------------------------------------
# Agile States
# ---------------------------------------------------------------------
# 88000-88999 Agile Methodologies (1000)
# 88000-88099 Intranet Project Type extensions (100)
# 88100-88199 Intranet Agile SCRUM States (100)
# 88200-88299 Intranet Agile Kanban States (100)
# 88300-88999 still free
# ----------------------------------------------------------------------
# Agile Components
# ---------------------------------------------------------------------
ad_proc -public im_agile_project_component {
-project_id
-return_url
} {
Returns a list of agile tasks associated to the current project
} {
if {![im_project_has_type $project_id "Agile Project"]} { return "" }
set params [list \
[list project_id $project_id] \
[list return_url [im_url_with_query]] \
]
set result [ad_parse_template -params $params "/packages/intranet-agile/lib/view-list-display"]
return $result
}
ad_proc -public im_agile_task_board_component {
-project_id
} {
Shows an interactive task board with agile tasks
} {
if {![im_project_has_type $project_id "Agile Project"]} { return "" }
set params [list \
[list agile_project_id $project_id] \
]
set result [ad_parse_template -params $params "/packages/intranet-agile/lib/task-board"]
return $result
}
# ----------------------------------------------------------------------
# Projects with reference to this agile
# ---------------------------------------------------------------------
ad_proc -public im_agile_referencing_projects_component {
-project_id
-return_url
} {
Returns a list of projects referencing to this agile
} {
# Is this a "Software Agile" Project
set agile_category [parameter::get -package_id [im_package_ganttproject_id] -parameter "AgileProjectType" -default "Software Agile"]
if {![im_project_has_type $project_id $agile_category]} { return "" }
set params [list \
[list project_id $project_id] \
[list return_url [im_url_with_query]] \
]
set result [ad_parse_template -params $params "/packages/intranet-agile/www/referencing-projects"]
return $result
}
# /packages/intranet-agile/www/add-tasks.tcl
#
# Copyright (c) 2003-2007 ]project-open[
# All rights reserved.
#
# Author: frank.bergmann@project-open.com
ad_page_contract {
Add a new agile task to a project
@author frank.bergmann@project-open.com
} {
agile_project_id:integer
project_id:integer,multiple
return_url
{ agile_status_id "[im_agile_status_default]" }
}
set user_id [auth::require_login]
set page_title [lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"]
# -------------------------------------------------------------
# Permissions
#
# The project admin (=> Agile Manager) can do everything.
# The managers of the individual Agile Tasks can change
# _their_ agile stati.
im_project_permissions $user_id $agile_project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
foreach pid $project_id {
set exists_p [db_string count "
select count(*)
from im_agile_task_rels i,
acs_rels r
where
i.rel_id = r.rel_id
and r.object_id_one = :agile_project_id
and r.object_id_two = :pid
"]
if {!$exists_p} {
set max_sort_order [db_string max_sort_order "
select coalesce(max(i.sort_order),0)
from im_agile_task_rels i,
acs_rels r
where
i.rel_id = r.rel_id
and r.object_id_one = :agile_project_id
" -default 0]
db_string add_user "
select im_agile_task_rel__new (
null,
'im_agile_task_rel',
:agile_project_id,
:pid,
null,
:user_id,
'[ad_conn peeraddr]',
:agile_status_id,
[expr {$max_sort_order + 10}]
)
"
}
}
ad_returnredirect $return_url
<master>
<property name="doc(title)">@page_title;literal@</property>
<property name="main_navbar_label">projects</property>
<property name="sub_navbar">@sub_navbar_html;literal@</property>
<property name="left_navbar">@left_navbar_html;literal@</property>
<property name="show_context_help">@show_context_help_p;literal@</property>
<listtemplate name="agile_tasks"></listtemplate>
# /packages/intranet-agile/www/add-tasks.tcl
#
# Copyright (c) 2003-2007 ]project-open[
# All rights reserved.
#
# Author: frank.bergmann@project-open.com
ad_page_contract {
Add a new agile task to a project
@author frank.bergmann@project-open.com
} {
project_id:integer
{ filter_project_type_id "" }
{ filter_project_status_id "" }
{ filter_ticket_type_id "" }
{ filter_ticket_status_id "" }
{ filter_agile_status_id 1 }
return_url
}
# -------------------------------------------------------------
# Permissions
#
# The project admin (=> Agile Manager) can do everything.
# The managers of the individual Agile Tasks can change
# _their_ agile stati.
set user_id [auth::require_login]
set page_title [lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"]
im_project_permissions $user_id $project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
if {"" == $filter_project_status_id} { set filter_project_status_id [im_project_status_open] }
if {"" == $filter_ticket_status_id} { set filter_ticket_status_id [im_ticket_status_open] }
if {"" != $filter_project_type_id && "" != $filter_ticket_type_id} {
ad_return_complaint 1 "<b>[lang::message::lookup "" intranet-agile.Ticket_and_project_selected "
You have selected both a project type and a ticket type.
"]</b>"
}
# -------------------------------------------------------------
# Create the list of potential agile tasks to add
set bulk_actions_list [list]
lappend bulk_actions_list "Add Agile Tasks" "add-tasks-2" "Add new agile tasks"
set elements {
project_chk {
label "<input type=\"checkbox\"
name=\"_dummy\"
onclick=\"acs_ListCheckAll('project_list', this.checked)\"
title=\"Check/uncheck all rows\">"
display_template {
@agile_tasks.project_chk;noquote@
}
}
object_type {
label ""
display_template {
@agile_tasks.object_type_html;noquote@
}
}
parent_project_name {
display_col parent_project_name
label "Parent"
link_url_eval $parent_project_url
}
project_nr {
display_col project_nr
label "Nr"
link_url_eval $agile_project_url
}
project_name {
display_col project_name
label "Agile Task"
link_url_eval $agile_project_url
}
}
list::create \
-name agile_tasks \
-multirow agile_tasks \
-key agile_task \
-row_pretty_plural $page_title \
-checkbox_name checkbox \
-selected_format "normal" \
-class "list" \
-main_class "list" \
-sub_class "narrow" \
-actions { } \
-has_checkboxes \
-bulk_actions $bulk_actions_list \
-bulk_action_export_vars { project_id return_url } \
-bulk_action_method GET \
-elements $elements
# -------------------------------------------------------------
# Prepare the SQL Statement
# -------------------------------------------------------------
set project_agile_task_p_sql ""
if {[im_column_exists im_projects agile_task_p]} {
set project_agile_task_p_sql "OR p.agile_task_p = 't'"
}
if {"" != $filter_project_status_id} {
lappend criteria "p.project_status_id in ([join [im_sub_categories $filter_project_status_id] ","])"
}
if {"" != $filter_project_type_id} {
lappend criteria "p.project_type_id in ([join [im_sub_categories $filter_project_type_id] ","])"
}
if {"" != $filter_ticket_status_id} {
lappend criteria "(t.ticket_status_id is null OR t.ticket_status_id in ([join [im_sub_categories $filter_ticket_status_id] ","]))"
}
if {"" != $filter_ticket_type_id} {
lappend criteria "t.ticket_type_id in ([join [im_sub_categories $filter_ticket_type_id] ","])"
}
set agile_tasks_sql "
select task.project_id
from im_projects relp,
im_projects task,
acs_rels r,
im_agile_task_rels ri
where
relp.project_type_id in ([join [im_sub_categories [im_project_type_agile]] ","]) and
r.object_id_one = relp.project_id and
r.object_id_two = task.project_id and
r.rel_id = ri.rel_id
"
switch $filter_agile_status_id {
1 {
# Not part of a agile project yet
lappend criteria "p.project_id not in ($agile_tasks_sql)"
}
2 {
# Already part of a agile project
lappend criteria "p.project_id in ($agile_tasks_sql)"
}
}
set where_clause [join $criteria " and\n "]
if { $where_clause ne "" } {
set where_clause " and $where_clause"
}
set restrict_to_rel_project_p [parameter::get_from_package_key -package_key "intranet-agile" -parameter "RestrictAgileTasksToAgileProjectP" -default 0]
set restrict_to_rel_project_sql ""
if {$restrict_to_rel_project_p} {
set restrict_to_rel_project_sql "and tree_root_key(p.tree_sortkey) = (select tree_root_key(tree_sortkey) from im_projects where project_id = :project_id)"
}
db_multirow -extend { object_type_html agile_project_url parent_project_url agile_status_template project_chk } agile_tasks select_agile_tasks "
select p.*,
p.parent_id as parent_project_id,
(select parent_p.project_name from im_projects parent_p where parent_p.project_id = p.parent_id) as parent_project_name,
o.object_type,
ot.pretty_name,
ot.object_type_gif
from acs_objects o,
acs_object_types ot,
im_projects p
LEFT OUTER JOIN im_tickets t ON (p.project_id = t.ticket_id)
where p.project_id = o.object_id and
o.object_type = ot.object_type and
(
project_type_id in ([join [im_sub_categories -include_disabled_p 1 [im_project_type_agile_task]] ","])
$project_agile_task_p_sql
)
$restrict_to_rel_project_sql
$where_clause
order by project_name
" {
set agile_project_url [export_vars -base "/intranet/projects/view?" {project_id return_url}]
set parent_project_url [export_vars -base "/intranet/projects/view?" {{project_id $parent_project_id} return_url}]
set project_chk "<input type=\"checkbox\"
name=\"project_id\"
value=\"$project_id\"
id=\"project_list,$project_id\">
"
set object_type_html [im_gif -translate_p 0 $object_type_gif $pretty_name]
}
# ---------------------------------------------------------------
# Navbar
# ---------------------------------------------------------------
# Setup the subnavbar
set bind_vars [ns_set create]
ns_set put $bind_vars project_id $project_id
set show_context_help_p 0
set parent_menu_id [im_menu_id_from_label "project"]
set menu_label "agile_tasks"
set sub_navbar_html [im_sub_navbar \
-base_url "/intranet/projects/view?project_id=$project_id" \
$parent_menu_id \
$bind_vars "" "pagedesriptionbar" $menu_label]
set agile_status_options [list 1 "Not part of a agile project yet" 2 "Already part of a agile project" 3 "Both"]
set left_navbar_html ""
append left_navbar_html "
<div class='filter-block'>
<div class='filter-title'>
[lang::message::lookup "" intranet-agile.Filter_Agile_Tasks "Filter Agile Tasks"]
</div>
<form action=add-tasks method=GET>
[export_vars -form {return_url project_id}]
<table>
<tr>
<td>[lang::message::lookup "" intranet-agile.Agile_Status "Part of Agile Project?"]</td>
<td>[im_select filter_agile_status_id $agile_status_options $filter_agile_status_id]<br>&nbsp;</td>
</tr>
<tr>
<td>[lang::message::lookup "" intranet-agile.Project_Type "Project Type"]</td>
<td>[im_category_select -include_empty_p 1 "Intranet Project Type" filter_project_type_id $filter_project_type_id]</td>
</tr>
<tr>
<td>[lang::message::lookup "" intranet-agile.Project_Status "Project Status"]</td>
<td>[im_category_select -include_empty_p 1 "Intranet Project Status" filter_project_status_id $filter_project_status_id]<br>&nbsp;</td>
</tr>
<tr>
<td>[lang::message::lookup "" intranet-agile.Ticket_Type "Ticket Type"]</td>
<td>[im_category_select -include_empty_p 1 "Intranet Ticket Type" filter_ticket_type_id $filter_ticket_type_id]</td>
</tr>
<tr>
<td>[lang::message::lookup "" intranet-agile.Ticket_Status "Ticket Status"]</td>
<td>[im_category_select -include_empty_p 1 "Intranet Ticket Status" filter_ticket_status_id $filter_ticket_status_id]<br>&nbsp;</td>
</tr>
<tr>
<td colspan=2><input type=submit name='[lang::message::lookup "" intranet-agile.Select "Select"]'></td>
</tr>
</table>
</form>
<br>
</div>
<hr/>
"
# /packages/intranet-agile/www/del-tasks.tcl
#
# Copyright (c) 2003-2007 ]project-open[
# All rights reserved.
#
# Author: frank.bergmann@project-open.com
ad_page_contract {
Add a new agile task to a project
@author frank.bergmann@project-open.com
} {
agile_project_id:integer
task_id:integer,multiple
return_url
}
set user_id [auth::require_login]
set page_title [lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"]
im_project_permissions $user_id $agile_project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
foreach pid $task_id {
im_exec_dml del_agile_task "im_agile_task_rel__delete(:agile_project_id, :pid)"
}
ad_returnredirect $return_url
# /packages/intranet-agile/www/order-tasks.tcl
#
# Copyright (c) 2003-2007 ]project-open[
# All rights reserved.
#
# Author: frank.bergmann@project-open.com
ad_page_contract {
Add a new agile task to a project
@param dir Is one of (up, down)
@author frank.bergmann@project-open.com
} {
agile_project_id:integer
project_id:integer
dir
return_url
}
set user_id [auth::require_login]
set page_title [lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"]
im_project_permissions $user_id $agile_project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
# -----------------------------------------------------
# Get the "sort_order" of the current task
set cur_task_ids [db_list cur_sort_order "
select rel_id
from acs_rels
where rel_type = 'im_agile_task_rel'
and object_id_one = :agile_project_id
and object_id_two = :project_id
"]
set cur_task_id [lindex $cur_task_ids 0]
set cur_sort_order [db_string cur_sort_order "
select sort_order
from im_agile_task_rels
where rel_id = :cur_task_id
" -default 0]
# ad_return_complaint 1 "<pre>cur_task_ids=$cur_task_ids \ncur_task_id=$cur_task_id \ncur_sort_order=$cur_sort_order\n</pre>"
# -----------------------------------------------------
# Move the task
switch $dir {
up {
# Get the "sort_order" of the task above
set above_sort_order [db_string above_sort_order "
select coalesce(max(i.sort_order),0)
from im_agile_task_rels i,
acs_rels r
where r.rel_id = i.rel_id
and r.object_id_one = :agile_project_id
and i.sort_order < :cur_sort_order
" -default 0]
if {0 != $above_sort_order} {
# There is an element above the current one:
# Get the ID of the component above
set above_ids [db_list above_list "
select i.rel_id
from acs_rels r,
im_agile_task_rels i
where i.sort_order = :above_sort_order
and r.object_id_one = :agile_project_id
and r.object_id_two = :project_id
"]
set above_task_id [lindex $above_ids 0]
# Exchange the sort orders of the user_map table
db_dml update "
update im_agile_task_rels
set sort_order = :above_sort_order
where rel_id = :cur_task_id
"
db_dml update "
update im_agile_task_rels
set sort_order = :cur_sort_order
where rel_id = :above_task_id
"
}
}
down {
# Get the "sort_order" of the task below
set below_sort_order [db_string below_sort_order "
select coalesce(min(i.sort_order),0)
from im_agile_task_rels i,
acs_rels r
where r.rel_id = i.rel_id
and r.object_id_one = :agile_project_id
and i.sort_order > :cur_sort_order
" -default 0]
if {0 != $below_sort_order} {
# There is an element below the current one:
# Get the ID of the component below
set below_ids [db_list below_list "
select i.rel_id
from acs_rels r,
im_agile_task_rels i
where i.sort_order = :below_sort_order
and r.object_id_one = :agile_project_id
and r.object_id_two = :project_id
"]
set below_task_id [lindex $below_ids 0]
# Exchange the sort orders of the user_map table
db_dml update "
update im_agile_task_rels
set sort_order = :below_sort_order
where rel_id = :cur_task_id
"
db_dml update "
update im_agile_task_rels
set sort_order = :cur_sort_order
where rel_id = :below_task_id
"
}
}
}
ad_returnredirect $return_url
# /packages/intranet-agile/www/agile-cube.tcl
#
# Copyright (c) 2003-2007 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/ for licensing details.
ad_page_contract {
Agile Cube
} {
}
# ------------------------------------------------------------
# Define Dimensions
set top_vars [list agile_date agile_nr]
set left_vars [list task_nr task_name]
set dimension_vars [concat $top_vars $left_vars]
# ------------------------------------------------------------
# Page Title & Help Text
set page_title "Agile Overview"
set context_bar [im_context_bar $page_title]
set context ""
set help_text "<strong>$page_title</strong><br>
"
# ------------------------------------------------------------
# Defaults
set rowclass(0) "roweven"
set rowclass(1) "rowodd"
set gray "gray"
set sigma "&Sigma;"
set cur_format [im_l10n_sql_currency_format]
set date_format [im_l10n_sql_date_format]
set company_url "/intranet/companies/view?company_id="
set project_url "/intranet/projects/view?project_id="
set invoice_url "/intranet-invoices/view?invoice_id="
set user_url "/intranet/users/view?user_id="
set this_url [export_vars -base "/intranet-reporting/finance-cube" {start_date end_date} ]
# ------------------------------------------------------------
# Start formatting the page
#
# Write out HTTP header, considering CSV/MS-Excel formatting
im_report_write_http_headers -output_format "html"
ns_write "
[im_header]
[im_navbar]
<table border=0 cellspacing=1 cellpadding=1>
"
# ------------------------------------------------------------
# Define the report - SQL, counters, headers and footers
#
# Aggregate additional/important fields to the fact table.
set middle_sql "
select
p.project_id as agile_id,
p.project_nr as agile_nr,
p.end_date as agile_end_date,
tasks.project_id as task_id,
tasks.project_nr as task_nr,
tasks.project_name as task_name,
i.sort_order as task_sort_order,
im_category_from_id(i.agile_status_id) as agile_status
from
im_projects p,
im_projects tasks,
acs_rels r,
im_agile_task_rels i
where
r.rel_id = i.rel_id
and r.object_id_one = p.project_id
and r.object_id_two = tasks.project_id
and p.project_status_id not in (
select child_id
from im_category_hierarchy
where parent_id = [im_project_status_closed]
UNION
select [im_project_status_closed]
)
"
# ------------------------------------------------------------
# Create upper & left dimensions
# Top scale is a list of lists such as {{2006 01} {2006 02} ...}
# The last element of the list the grand total sum.
set top_scale [db_list_of_lists top_scale "
select distinct
to_char(agile_end_date, 'YYYY-MM-DD'),
agile_nr
from ($middle_sql) c
order by
to_char(agile_end_date, 'YYYY-MM-DD')
"]
set left_scale_base [db_list_of_lists left_scale "
select distinct
to_char(agile_end_date, 'YYYY-MM-DD'),
task_nr,
task_name,
task_sort_order
from ($middle_sql) c
order by
to_char(agile_end_date, 'YYYY-MM-DD'), task_sort_order
"]
# Eliminate duplicate entries for same tasks
set left_scale [list]
foreach el $left_scale_base {
set agile_date [lindex $el 0]
set task_nr [lindex $el 1]
set task_name [lindex $el 2]
set task_sort_order [lindex $el 3]
if {![info exists task_nr_hash($task_nr)]} {
lappend left_scale [list $task_nr $task_name]
}
set task_nr_hash($task_nr) 1
}
# ------------------------------------------------------------
# Display the Table Header
# Determine how many date rows (year, month, day, ...) we've got
set first_cell [lindex $top_scale 0]
set top_scale_rows [llength $first_cell]
set left_scale_size [llength [lindex $left_scale 0]]
set header ""
for {set row 0} {$row < $top_scale_rows} { incr row } {
append header "<tr class=rowtitle>\n"
append header "<td colspan=$left_scale_size></td>\n"
for {set col 0} {$col <= [expr {[llength $top_scale]-1}]} { incr col } {
set scale_entry [lindex $top_scale $col]
set scale_task [lindex $scale_entry $row]
# Check if the previous task was of the same content
set prev_scale_entry [lindex $top_scale $col-1]
set prev_scale_task [lindex $prev_scale_entry $row]
# Check for the "sigma" sign. We want to display the sigma
# every time (disable the colspan logic)
if {$scale_task == $sigma} {
append header "\t<td class=rowtitle>$scale_task</td>\n"
continue
}
# Prev and current are same => just skip.
# The cell was already covered by the previous entry via "colspan"
if {$prev_scale_task == $scale_task} { continue }
# This is the first entry of a new content.
# Look forward to check if we can issue a "colspan" command
set colspan 1
set next_col [expr {$col+1}]
while {$scale_task == [lindex $top_scale $next_col $row]} {
incr next_col
incr colspan
}
append header "\t<td class=rowtitle colspan=$colspan>$scale_task</td>\n"
}
append header "</tr>\n"
}
ns_write $header
# ------------------------------------------------------------
# Execute query and aggregate values into a Hash array
db_foreach query $middle_sql {
set key "$agile_nr-$task_nr"
set hash($key) $agile_status
}
# ------------------------------------------------------------
# Display the table body
set ctr 0
foreach left_entry $left_scale {
set class $rowclass([expr {$ctr % 2}])
incr ctr
# Start the row and show the left_scale values at the left
ns_write "<tr class=$class>\n"
foreach val $left_entry { ns_write "<td>$val</td>\n" }
# Write the left_scale values to their corresponding local
# variables so that we can access them easily when calculating
# the "key".
for {set i 0} {$i < [llength $left_vars]} {incr i} {
set var_name [lindex $left_vars $i]
set var_value [lindex $left_entry $i]
set $var_name $var_value
}
foreach top_entry $top_scale {
# Write the top_scale values to their corresponding local
# variables so that we can access them easily for $key
for {set i 0} {$i < [llength $top_vars]} {incr i} {
set var_name [lindex $top_vars $i]
set var_value [lindex $top_entry $i]
set $var_name $var_value
}
# Calculate the key for this permutation
# something like "$year-$month-$customer_id"
set key "$agile_nr-$task_nr"
set val "&nbsp;"
if {[info exists hash($key)]} { set val $hash($key) }
ns_write "<td>$val</td>\n"
}
ns_write "</tr>\n"
}
# ------------------------------------------------------------
# Finish up the table
ns_write "</table>\n[im_footer]\n"
# /packages/intranet-agile/www/save-tasks.tcl
#
# Copyright (c) 2003-2007 ]project-open[
# All rights reserved.
#
# Author: frank.bergmann@project-open.com
ad_page_contract {
Add a new agile task to a project
@author frank.bergmann@project-open.com
} {
agile_project_id:integer
agile_status_id:integer,array
agile_sort_order:array
return_url
}
set user_id [auth::require_login]
set page_title [lang::message::lookup "" intranet-agile.Agile_Tasks "Agile Tasks"]
im_project_permissions $user_id $agile_project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
foreach task_id [array names agile_status_id] {
if {[info exists agile_sort_order($task_id)]} {
set sort_order $agile_sort_order($task_id)
db_dml update_sort_order "
update im_agile_task_rels set
sort_order = :sort_order
where rel_id in (
select r.rel_id
from acs_rels r,
im_agile_task_rels i
where r.rel_id = i.rel_id
and r.object_id_one = :agile_project_id
and r.object_id_two = :task_id
)
"
}
set status_id $agile_status_id($task_id)
set old_status_id [db_string old_status_id "
select agile_status_id
from acs_rels r,
im_agile_task_rels i
where r.rel_id = i.rel_id
and r.object_id_one = :agile_project_id
and r.object_id_two = :task_id
" -default ""]
if {$old_status_id != $status_id} {
db_dml update_task "
update im_agile_task_rels
set agile_status_id = :status_id
where rel_id in (
select rel_id
from acs_rels
where object_id_one = :agile_project_id
and object_id_two = :task_id
)
"
set status [db_string status "select im_category_from_id(:status_id)"]
set old_status [db_string status "select im_category_from_id(:old_status_id)"]
set task_nr [db_string task_name "select project_nr from im_projects where project_id = :task_id" -default "unknown"]
im_agile_new_journal \
-object_id $agile_project_id \
-action "agile_status" \
-action_pretty "Agile Status Changed" \
-message "Changed status of '$task_nr' from '$old_status' to '$status'"
}
}
ad_returnredirect $return_url
# /packages/intranet-agile/www/task-board-action.tcl
#
# Copyright (c) 2003-2010 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/ for licensing details.
ad_page_contract {
Task Board Action
Accepts "events" (clicking on an arrow) from the task-board
and moves the tasks accordingly.
} {
agile_project_id:integer
agile_task_id:integer
action
return_url
}
# ------------------------------------------------------------
# Defaults & Permissions
# ------------------------------------------------------------
set user_id [auth::require_login]
im_project_permissions $user_id $agile_project_id view read write admin
if {!$write} {
ad_return_complaint 1 "<li>[_ intranet-core.lt_You_have_insufficient_6]"
return
}
# ------------------------------------------------------------
# Get the list of agile states
set top_states_sql "
select *
from im_categories c
where category_type = 'Intranet Agile Status'
order by category_id
"
set top_states_list [list]
db_foreach top_states $top_states_sql {
lappend top_states_list $category_id
}
# ------------------------------------------------------------
# Get information about the affected agile task
set rel_task_info_sql "
select task.*,
ri.*,
ri.rel_id as agile_task_id,
im_category_from_id(ri.agile_status_id) as agile_status
from
im_projects relp,
im_projects task,
acs_rels r,
im_agile_task_rels ri
where
relp.project_id = :agile_project_id and
task.project_id = :agile_task_id and
r.object_id_one = relp.project_id and
r.object_id_two = task.project_id and
r.rel_id = ri.rel_id
"
set exists_p [db_0or1row rel_task_info $rel_task_info_sql]
if {!$exists_p} {
# The project doesn't exist
ad_return_complaint 1 [lang::message::lookup "" intranet-agile.Agile_project_does_not_exist "
<br>
<b>The specified task #$agile_task_id does not exist in project #$agile_project_id</b>:<br>
The task or the project may have been deleted.
<br>&nbsp;<br>
"]
}
# ------------------------------------------------------------
# Update the task according to action
# determine the position of the current agile_status_id in the
# list of agile states
set rel_state_pos [lsearch $top_states_list $agile_status_id]
switch $action {
left {
set rel_state_pos [expr {$rel_state_pos - 1}]
}
right {
set rel_state_pos [expr {$rel_state_pos + 1}]
}
up {
# Search for the tasks with the next lower sort_order
set prev_agile_task_id ""
set prev_sort_order ""
db_0or1row prev_sql "
select ri.rel_id as prev_agile_task_id,
ri.sort_order as prev_sort_order
from im_projects relp,
im_projects task,
acs_rels r,
im_agile_task_rels ri
where relp.project_id = :agile_project_id and
r.object_id_one = relp.project_id and
r.object_id_two = task.project_id and
r.rel_id = ri.rel_id and
ri.sort_order < :sort_order and
ri.agile_status_id = :agile_status_id
order by ri.sort_order DESC
LIMIT 1
"
if {"" != $prev_agile_task_id} {
# Exchange the sort_order with the previous task
db_dml update_prev "
update im_agile_task_rels
set sort_order = :sort_order
where rel_id = :prev_agile_task_id
"
db_dml update_prev "
update im_agile_task_rels
set sort_order = :prev_sort_order
where rel_id = :agile_task_id
"
}
}
down {
# Search for the tasks with the next higher sort_order
set prev_agile_task_id ""
set prev_sort_order ""
db_0or1row prev_sql "
select ri.rel_id as prev_agile_task_id,
ri.sort_order as prev_sort_order
from im_projects relp,
im_projects task,
acs_rels r,
im_agile_task_rels ri
where relp.project_id = :agile_project_id and
r.object_id_one = relp.project_id and
r.object_id_two = task.project_id and
r.rel_id = ri.rel_id and
ri.sort_order > :sort_order and
ri.agile_status_id = :agile_status_id
order by ri.sort_order
LIMIT 1
"
if {"" != $prev_agile_task_id} {
# Exchange the sort_order with the previous task
db_dml update_prev "
update im_agile_task_rels
set sort_order = :sort_order
where rel_id = :prev_agile_task_id
"
db_dml update_prev "
update im_agile_task_rels
set sort_order = :prev_sort_order
where rel_id = :agile_task_id
"
}
}
}
if {$rel_state_pos < 0} { set rel_state_pos 0 }
if {$rel_state_pos > [llength $top_states_list]} { set rel_state_pos [llength $top_states_list] }
set new_agile_status_id [lindex $top_states_list $rel_state_pos]
set new_agile_status [im_category_from_id $new_agile_status_id]
db_dml update_agile_task "
update im_agile_task_rels
set agile_status_id = $new_agile_status_id
where rel_id = :agile_task_id
"
if {$agile_status_id != $new_agile_status_id} {
# Record that somebody moved the task between states
im_agile_new_journal \
-object_id $agile_project_id \
-action "agile_status" \
-action_pretty "Agile Status Changed" \
-message "Changed status of '$project_name' from '$agile_status' to '$new_agile_status'"
}
ad_returnredirect $return_url
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment