summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes11
-rw-r--r--demos/time-tracker/protected/App_Code/CategoryDao.php5
-rw-r--r--demos/time-tracker/protected/App_Code/ProjectDao.php11
-rw-r--r--demos/time-tracker/protected/App_Data/time_tracker.dbbin16384 -> 17408 bytes
-rw-r--r--demos/time-tracker/protected/application.xml2
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.php94
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.tpl152
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.page77
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php107
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page70
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php160
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ProjectList.page40
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ProjectList.php34
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ReportProject.page15
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl2
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/TimeEntry.page4
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.php89
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.tpl66
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/UserList.page33
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/config.xml2
-rw-r--r--demos/time-tracker/themes/TimeTracker/project.css96
-rw-r--r--demos/time-tracker/themes/TimeTracker/site.css7
-rw-r--r--demos/time-tracker/themes/TimeTracker/time-entry.css46
-rw-r--r--framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php120
-rw-r--r--framework/DataAccess/SQLMap/Configuration/TInlineParameterMapParser.php2
-rw-r--r--framework/DataAccess/SQLMap/Configuration/TParameterProperty.php10
-rw-r--r--framework/DataAccess/SQLMap/Configuration/TResultProperty.php6
-rw-r--r--framework/DataAccess/SQLMap/Configuration/TSimpleDynamicParser.php23
-rw-r--r--framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php10
-rw-r--r--framework/DataAccess/SQLMap/Statements/TMappedStatement.php1
-rw-r--r--framework/DataAccess/SQLMap/Statements/TPreparedCommand.php2
-rw-r--r--framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php15
-rw-r--r--framework/DataAccess/SQLMap/Statements/TSimpleDynamicSql.php32
-rw-r--r--framework/DataAccess/SQLMap/Statements/TStaticSql.php2
-rw-r--r--framework/DataAccess/TAdodb.php12
-rw-r--r--framework/DataAccess/TDatabaseProvider.php6
-rw-r--r--framework/Web/Javascripts/js/validator.js2
-rw-r--r--framework/Web/Javascripts/prado/validation3.js2
38 files changed, 1208 insertions, 160 deletions
diff --git a/.gitattributes b/.gitattributes
index 15882b6b..53d71e94 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1112,6 +1112,10 @@ demos/time-tracker/protected/pages/Docs/project1.png -text
demos/time-tracker/protected/pages/Docs/unit_test1.png -text
demos/time-tracker/protected/pages/Docs/unit_test2.png -text
demos/time-tracker/protected/pages/Docs/unit_test3.png -text
+demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.php -text
+demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.tpl -text
+demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.page -text
+demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php -text
demos/time-tracker/protected/pages/TimeTracker/Login.page -text
demos/time-tracker/protected/pages/TimeTracker/Login.php -text
demos/time-tracker/protected/pages/TimeTracker/Logout.page -text
@@ -1121,11 +1125,13 @@ demos/time-tracker/protected/pages/TimeTracker/MainLayout.tpl -text
demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page -text
demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php -text
demos/time-tracker/protected/pages/TimeTracker/ProjectList.page -text
+demos/time-tracker/protected/pages/TimeTracker/ProjectList.php -text
demos/time-tracker/protected/pages/TimeTracker/ReportProject.page -text
demos/time-tracker/protected/pages/TimeTracker/ReportResource.page -text
demos/time-tracker/protected/pages/TimeTracker/SiteMap.php -text
demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl -text
-demos/time-tracker/protected/pages/TimeTracker/TimeEntry.page -text
+demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.php -text
+demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.tpl -text
demos/time-tracker/protected/pages/TimeTracker/UserCreate.page -text
demos/time-tracker/protected/pages/TimeTracker/UserCreate.php -text
demos/time-tracker/protected/pages/TimeTracker/UserList.page -text
@@ -1146,6 +1152,7 @@ demos/time-tracker/themes/TimeTracker/bar.png -text
demos/time-tracker/themes/TimeTracker/project.css -text
demos/time-tracker/themes/TimeTracker/site.css -text
demos/time-tracker/themes/TimeTracker/tabs.png -text
+demos/time-tracker/themes/TimeTracker/time-entry.css -text
docs/application.xml -text
docs/specs/application.dtd -text
docs/specs/application.xsd -text
@@ -1261,6 +1268,7 @@ framework/DataAccess/SQLMap/Configuration/TParameterMap.php -text
framework/DataAccess/SQLMap/Configuration/TParameterProperty.php -text
framework/DataAccess/SQLMap/Configuration/TResultMap.php -text
framework/DataAccess/SQLMap/Configuration/TResultProperty.php -text
+framework/DataAccess/SQLMap/Configuration/TSimpleDynamicParser.php -text
framework/DataAccess/SQLMap/Configuration/TSqlMapCacheModel.php -text
framework/DataAccess/SQLMap/Configuration/TSqlMapDelete.php -text
framework/DataAccess/SQLMap/Configuration/TSqlMapInsert.php -text
@@ -1284,6 +1292,7 @@ framework/DataAccess/SQLMap/Statements/TPreparedCommand.php -text
framework/DataAccess/SQLMap/Statements/TPreparedStatement.php -text
framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php -text
framework/DataAccess/SQLMap/Statements/TSelectMappedStatement.php -text
+framework/DataAccess/SQLMap/Statements/TSimpleDynamicSql.php -text
framework/DataAccess/SQLMap/Statements/TStaticSql.php -text
framework/DataAccess/SQLMap/Statements/TUpdateMappedStatement.php -text
framework/DataAccess/SQLMap/TMapper.php -text
diff --git a/demos/time-tracker/protected/App_Code/CategoryDao.php b/demos/time-tracker/protected/App_Code/CategoryDao.php
index f0149f0b..cb1b6399 100644
--- a/demos/time-tracker/protected/App_Code/CategoryDao.php
+++ b/demos/time-tracker/protected/App_Code/CategoryDao.php
@@ -5,7 +5,10 @@ class CategoryDao extends BaseDao
function addNewCategory($category)
{
$sqlmap = $this->getConnection();
- $sqlmap->insert('AddNewCategory', $category);
+ $exists = $this->getCategoryByNameInProject(
+ $category->Name, $category->ProjectID);
+ if(!$exists)
+ $sqlmap->insert('AddNewCategory', $category);
}
function getCategoryByID($categoryID)
diff --git a/demos/time-tracker/protected/App_Code/ProjectDao.php b/demos/time-tracker/protected/App_Code/ProjectDao.php
index 416c6540..0a0771e3 100644
--- a/demos/time-tracker/protected/App_Code/ProjectDao.php
+++ b/demos/time-tracker/protected/App_Code/ProjectDao.php
@@ -62,10 +62,17 @@ class ProjectDao extends BaseDao
return $sqlmap->queryForList('GetProjectMembers', $projectID);
}
- public function getAllProjects()
+ public function getAllProjects($sort='', $order='ASC')
{
$sqlmap = $this->getConnection();
- return $sqlmap->queryForList('GetAllProjects');
+ if($sort === '')
+ return $sqlmap->queryForList('GetAllProjects');
+ else
+ {
+ $param['sort'] = $sort;
+ $param['order'] = $order;
+ return $sqlmap->queryForList('GetAllProjectsOrdered', $param);
+ }
}
public function getProjectsByManagerName($manager)
diff --git a/demos/time-tracker/protected/App_Data/time_tracker.db b/demos/time-tracker/protected/App_Data/time_tracker.db
index 03fe9156..e7adaec3 100644
--- a/demos/time-tracker/protected/App_Data/time_tracker.db
+++ b/demos/time-tracker/protected/App_Data/time_tracker.db
Binary files differ
diff --git a/demos/time-tracker/protected/application.xml b/demos/time-tracker/protected/application.xml
index e7d3b330..02be327b 100644
--- a/demos/time-tracker/protected/application.xml
+++ b/demos/time-tracker/protected/application.xml
@@ -21,6 +21,6 @@
</module>
</modules>
<services>
- <service id="page" class="TPageService" DefaultPage="TimeTracker.TimeEntry"/>
+ <service id="page" class="TPageService" DefaultPage="TimeTracker.LogTimeEntry"/>
</services>
</application> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.php b/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.php
new file mode 100644
index 00000000..d2772067
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.php
@@ -0,0 +1,94 @@
+<?php
+
+class CategoryDataList extends TTemplateControl
+{
+ public function setProjectID($value)
+ {
+ $this->setViewState('ProjectID', $value, '');
+ }
+
+ public function getProjectID()
+ {
+ return $this->getViewState('ProjectID', '');
+ }
+
+ public function getCategories()
+ {
+ $this->ensureChildControls();
+ return $this->getRegisteredObject('categories');
+ }
+
+ protected function getCategoryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('CategoryDao');
+ }
+
+ public function showCategories()
+ {
+ $categoryDao = $this->getCategoryDao();
+ $list = $categoryDao->getCategoriesByProjectID($this->getProjectID());
+ $this->categories->DataSource = $list;
+ $this->categories->dataBind();
+ }
+
+ public function deleteCategoryItem($sender, $param)
+ {
+ $id = $this->categories->DataKeys[$param->Item->ItemIndex];
+ $this->getCategoryDao()->deleteCategory($id);
+ $this->refreshCategoryList($sender, $param);
+ }
+
+ public function editCategoryItem($sender, $param)
+ {
+ $this->categories->EditItemIndex=$param->Item->ItemIndex;
+ $this->showCategories();
+ }
+
+ public function refreshCategoryList($sender, $param)
+ {
+ $this->categories->EditItemIndex=-1;
+ $this->showCategories();
+ }
+
+ public function updateCategoryItem($sender, $param)
+ {
+ if(!$this->Page->IsValid)
+ return;
+
+ $item = $param->Item;
+
+ $id = $this->categories->DataKeys[$param->Item->ItemIndex];
+ $category = new Category;
+ $category->ID = $id;
+ $category->Name = $item->name->Text;
+ $category->Abbreviation = $item->abbrev->Text;
+ $category->EstimateDuration = floatval($item->duration->Text);
+ $category->ProjectID = $this->getProjectID();
+
+ $this->getCategoryDao()->updateCategory($category);
+
+ $this->refreshCategoryList($sender, $param);
+ }
+
+ public function addCategory_clicked($sender, $param)
+ {
+ if(!$this->Page->IsValid)
+ return;
+
+ $newCategory = new Category;
+ $newCategory->Name = $this->categoryName->Text;
+ $newCategory->Abbreviation = $this->abbrev->Text;
+ $newCategory->EstimateDuration = floatval($this->duration->Text);
+ $newCategory->ProjectID = $this->getProjectID();
+
+ $this->getCategoryDao()->addNewCategory($newCategory);
+
+ $this->categoryName->Text = '';
+ $this->abbrev->Text = '';
+ $this->duration->Text = '';
+
+ $this->showCategories();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.tpl b/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.tpl
new file mode 100644
index 00000000..7a19dadb
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/CategoryDataList.tpl
@@ -0,0 +1,152 @@
+
+<table class="categorylist">
+ <tr>
+ <th>Category Name</th>
+ <th>Abbreviation</th>
+ <th>Estimate Duration</th>
+ <th></th>
+ </tr>
+<com:TDataList ID="categories"
+ RepeatLayout="Raw"
+ DataKeyField="ID"
+ OnEditCommand="editCategoryItem"
+ OnCancelCommand="refreshCategoryList"
+ OnUpdateCommand="updateCategoryItem"
+ OnDeleteCommand="deleteCategoryItem">
+
+ <prop:ItemTemplate>
+ <tr>
+ <td class="categoryName"><%# $this->DataItem->Name %></td>
+ <td class="abbrev"><%# $this->DataItem->Abbreviation %></td>
+ <td class="duration"><%# $this->DataItem->EstimateDuration %></td>
+ <td class="edit">
+ <com:TButton Text="Edit" CommandName="edit"/>
+ <com:TButton Text="Delete" CommandName="delete"
+ Attributes.onclick="if(!confirm('Are you sure?')) return false;" />
+ </td>
+ </tr>
+ </prop:ItemTemplate>
+
+ <prop:EditItemTemplate>
+ <tr>
+ <td class="categoryName">
+ <com:TTextBox ID="name" Text=<%# $this->DataItem->Name %> />
+ <span class="required">*</span>
+ <com:TRequiredFieldValidator
+ ControlToValidate="name"
+ Display="None"
+ CssClass="validator"
+ ControlCssClass="required-input"
+ ValidationGroup="category-update"
+ ErrorMessage="Please enter the category name." />
+ </td>
+ <td class="abbrev">
+ <com:TTextBox ID="abbrev" Text=<%# $this->DataItem->Abbreviation %> />
+ <span class="required">*</span>
+ <com:TRequiredFieldValidator
+ ControlToValidate="abbrev"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-update"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter an abbreviation." />
+ <com:TRegularExpressionValidator
+ ControlToValidate="abbrev"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-update"
+ ControlCssClass="required-input1"
+ RegularExpression="[a-zA-Z0-9]*"
+ ErrorMessage="Abbreviation must be alphanumeric." />
+ </td>
+ <td class="duration">
+ <com:TTextBox ID="duration" Text=<%# $this->DataItem->EstimateDuration %> />
+ <span class="required">*</span>
+ <com:TRequiredFieldValidator
+ ControlToValidate="duration"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-update"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter a duration." />
+ <com:TRangeValidator
+ ControlToValidate="duration"
+ DataType="Float"
+ MinValue="0"
+ MaxValue="9999"
+ CssClass="validator"
+ Display="None"
+ ValidationGroup="category-update"
+ ControlCssClass="required-input1"
+ ErrorMessage="Duration must be between 0 and 9999." />
+ </td>
+ <td class="edit">
+ <com:TButton Text="Save" CommandName="update" ValidationGroup="category-update"/>
+ <com:TButton Text="Cancel" CommandName="cancel" />
+ </td>
+ </tr>
+ </prop:EditItemTemplate>
+
+</com:TDataList>
+ <tr>
+ <td class="categoryName">
+ <com:TTextBox ID="categoryName" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="categoryName"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-add"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter the category name." />
+ </td>
+
+ <td class="abbrev">
+ <com:TTextBox ID="abbrev" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="abbrev"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-add"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter an abbreviation." />
+ <com:TRegularExpressionValidator
+ ControlToValidate="abbrev"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-add"
+ RegularExpression="[a-zA-Z0-9]*"
+ ControlCssClass="required-input1"
+ ErrorMessage="Abbreviation must be alphanumeric." />
+ </td>
+
+ <td class="duration">
+ <com:TTextBox ID="duration" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="duration"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="category-add"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter a duration." />
+ <com:TRangeValidator
+ ControlToValidate="duration"
+ DataType="Float"
+ MinValue="0"
+ MaxValue="9999"
+ CssClass="validator"
+ Display="None"
+ ValidationGroup="category-add"
+ ControlCssClass="required-input1"
+ ErrorMessage="Duration must be between 0 and 9999." />
+ </td>
+ <td class="edit">
+ <com:TButton Text="Add Category" OnClick="addCategory_clicked" ValidationGroup="category-add" />
+ </td>
+ </tr>
+</table>
+<com:TValidationSummary
+ AutoUpdate="false"
+ ValidationGroup="category-add" />
+<com:TValidationSummary
+ AutoUpdate="false"
+ ValidationGroup="category-update" />
diff --git a/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.page b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.page
new file mode 100644
index 00000000..ca5797e4
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.page
@@ -0,0 +1,77 @@
+<com:TContent ID="Main">
+<h2>Time Entry</h2>
+
+<div class="loghours">
+
+<fieldset>
+<legend>Log your hours</legend>
+<div class="project">
+<com:TLabel ForControl="projects" Text="Project:" />
+<span class="required">*</span><br />
+<com:TDropDownList ID="projects" AutoPostBack="true" OnSelectedIndexChanged="projects_Changed" />
+</div>
+
+<div class="category">
+<com:TLabel ForControl="category" Text="Category:" />
+<span class="required">*</span><br />
+<com:TDropDownList ID="category" />
+</div>
+
+<div class="day">
+<com:TLabel ForControl="day" Text="Day:" />
+<span class="required">*</span><br />
+<com:TDatePicker ID="day" InputMode="DropDownList" />
+</div>
+
+<div class="hours">
+<com:TLabel ForControl="hours" Text="Hours:" />
+<span class="required">*</span><br />
+<com:TTextBox ID="hours" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="hours"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="hours-add"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter your work hours." />
+ <com:TRangeValidator
+ ControlToValidate="hours"
+ DataType="Float"
+ MinValue="0"
+ MaxValue="9999"
+ CssClass="validator"
+ Display="None"
+ ValidationGroup="hours-add"
+ ControlCssClass="required-input1"
+ ErrorMessage="Hours must be between 0 and 9999" />
+ </div>
+
+<div class="description">
+<com:TLabel ForControl="description" Text="Description:" /><br/>
+<com:TTextBox ID="description" TextMode="MultiLine" />
+</div>
+
+<div class="addEntry">
+
+<com:TValidationSummary AutoUpdate="false" ValidationGroup="hours-add" />
+
+<com:TButton Text="Add Entry" ValidationGroup="hours-add" OnClick="AddNewEntry" />
+</div>
+
+</fieldset>
+
+</div>
+
+<div class="timesheet">
+<fieldset>
+<legend>Time Sheet For:
+<com:TDropDownList ID="projectMembers" CssClass="sheetfor"
+ AutoPostBack="True" OnSelectedIndexChanged="showTimeSheet" />
+</legend>
+
+<com:Application.pages.TimeTracker.TimeEntryList ID="entryList" />
+
+</fieldset>
+
+</div>
+</com:TContent> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php
new file mode 100644
index 00000000..cc27c93c
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php
@@ -0,0 +1,107 @@
+<?php
+
+class LogTimeEntry extends TPage
+{
+
+ protected function getProjectDao()
+ {
+ return $this->Application->Modules['daos']->getDao('ProjectDao');
+ }
+
+ protected function getCategoryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('CategoryDao');
+ }
+
+ protected function getTimeEntryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('TimeEntryDao');
+ }
+
+ public function onLoad($param)
+ {
+ if(!$this->IsPostBack)
+ {
+ $projects = $this->getProjects();
+ $this->projects->DataSource = $projects;
+ $this->projects->dataBind();
+ $this->showCategories(key($projects));
+ }
+ }
+
+ protected function showCategories($projectID)
+ {
+ $categories = array();
+ foreach($this->getCategoryDao()->getCategoriesByProjectID($projectID) as $cat)
+ {
+ $categories[$cat->ID] = $cat->Name;
+ }
+ $this->category->DataSource = $categories;
+ $this->category->dataBind();
+ $this->showProjectUsers($projectID);
+ }
+
+ protected function showProjectUsers($projectID)
+ {
+ if($this->User->isInRole('manager'))
+ $users = $this->getProjectDao()->getProjectMembers($projectID);
+ else
+ $users = array($this->User->Name);
+ $this->projectMembers->DataSource = $users;
+ $this->projectMembers->dataBind();
+ if(is_int($index = array_search($this->User->Name, $users)))
+ $this->projectMembers->SelectedIndex = $index;
+ $this->showTimeSheet();
+ }
+
+ public function showTimeSheet()
+ {
+ $user = $this->projectMembers->SelectedItem->Text;
+ $project = $this->projects->SelectedValue;
+ $this->entryList->setProjectEntry($user,$project);
+ $this->entryList->refreshEntryList();
+ }
+
+ protected function getProjects()
+ {
+ $projects = array();
+ if($this->User->isInRole('admin'))
+ $list = $this->getProjectDao()->getAllProjects();
+ else if($this->User->isInRole('manager'))
+ $list = $this->getProjectDao()->getProjectsByManagerName($this->User->Name);
+ else
+ $list = $this->getProjectDao()->getProjectsByUserName($this->User->Name);
+ foreach($list as $project)
+ $projects[$project->ID] = $project->Name;
+ return $projects;
+ }
+
+ public function projects_Changed($sender, $param)
+ {
+ $this->showCategories($sender->SelectedValue);
+ }
+
+ public function AddNewEntry($sender, $param)
+ {
+ if(!$this->IsValid)
+ return;
+
+ $entry = new TimeEntry;
+ $entry->CreatorUserName = $this->User->Name;
+ $category = new Category;
+ $category->ID = $this->category->SelectedValue;
+ $entry->Category = $category;
+ $entry->Description = $this->description->Text;
+ $entry->Duration = floatval($this->hours->Text);
+ $entry->ReportDate = $this->day->TimeStamp;
+ $entry->Username = $this->projectMembers->SelectedItem->Text;
+
+ $this->hours->Text = '';
+ $this->description->Text = '';
+
+ $this->getTimeEntryDao()->addNewTimeEntry($entry);
+ $this->showTimeSheet();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page b/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page
index 2a7cb6dd..ea384452 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page
+++ b/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.page
@@ -1,5 +1,5 @@
<com:TContent ID="Main">
-<h1>Create New Project</h1>
+<h2>Project Details</h2>
<fieldset class="project"><legend>Project Configuration</legend>
<p>Define the project and specify which users will be part of the project.
@@ -10,22 +10,51 @@
<h2>Project Information</h2>
<div class="projectName">
<com:TLabel ForControl="projectName" Text="Project Name"/>
+ <span class="required">*</span><br />
<com:TTextBox ID="projectName" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="projectName"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="project-edit"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter a project name."/>
+
</div>
<div class="manager">
<com:TLabel ForControl="manager" Text="Project Manager" />
+ <span class="required">*</span><br />
<com:TDropDownList ID="manager" />
</div>
<div class="completionDate">
<com:TLabel ForControl="completionDate" Text="Estimated complete date:"/>
+ <span class="required">*</span><br />
<com:TDatePicker ID="completionDate" InputMode="DropDownList" />
</div>
<div class="estimateHours">
<com:TLabel ForControl="estimateHours" Text="Estimated Duration (in hours):"/>
+ <span class="required">*</span><br />
<com:TTextBox ID="estimateHours" />
+ <com:TRequiredFieldValidator
+ ControlToValidate="estimateHours"
+ Display="None"
+ CssClass="validator"
+ ValidationGroup="project-edit"
+ ControlCssClass="required-input"
+ ErrorMessage="Please enter the project duration." />
+ <com:TRangeValidator
+ ControlToValidate="estimateHours"
+ DataType="Float"
+ MinValue="0"
+ MaxValue="9999"
+ CssClass="validator"
+ Display="None"
+ ValidationGroup="project-edit"
+ ControlCssClass="required-input1"
+ ErrorMessage="Duration must be between 0 and 9999" />
</div>
<div class="description">
- <com:TLabel ForControl="description" Text="Description:" />
+ <com:TLabel ForControl="description" Text="Description:" /><br />
<com:TTextBox ID="description" TextMode="MultiLine" />
</div>
</div>
@@ -36,10 +65,39 @@
<com:TListBox ID="members" SelectionMode="Multiple" />
</div>
- <div class="actionButtons">
- <com:TButton Text="Save" />
- <com:TButton Text="Cancel" />
- <com:TButton Text="Delete" />
+ <com:TPanel CssClass="projectCategory" ID="projectCategoryColumn">
+ <h2>Define Project Categories for Project Management</h2>
+
+ <p>Categories can be added in two ways. You can <strong>ADD</strong> a category
+ by specifying name, abbreviation, and duration -
+ the amount of hours that may be charged under the category. Or,
+ You can <strong>COPY</strong> categories that already have been defined in
+ another project to this project. </p>
+
+ <com:Application.pages.TimeTracker.CategoryDataList ID="categories" />
+
+ <div class="fromProject">
+ <com:TLabel ForControl="projectList" Text="Add categories from another project:" />
+ <com:TDropDownList ID="projectList" />
+ <com:TButton Text="Copy" OnClick="copyButton_clicked" />
+ </div>
+
+ </com:TPanel>
+
+ <div class="actions">
+
+ <com:TValidationSummary AutoUpdate="false" ValidationGroup="project-edit" />
+ <p>Press the <tt>SAVE</tt> button for your configuration to take effect.
+ <com:TPlaceHolder Visible=<%= $this->deleteButton->Visible %>>
+ Press the <tt>DELETE</tt> button to delete the current project.
+ </com:TPlaceHolder>
+ </p>
+ <div class="buttons">
+ <com:TButton Text="Save" CssClass="save"
+ OnClick="saveButton_clicked" ValidationGroup="project-edit"/>
+ <com:TButton ID="deleteButton" Text="Delete" OnClick="deleteButton_clicked"
+ Attributes.onclick="if(!confirm('Are you sure?')) return false;" />
+ </div>
</div>
</fieldset>
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php b/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php
index 16c10e6f..767e259c 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php
+++ b/demos/time-tracker/protected/pages/TimeTracker/ProjectDetails.php
@@ -2,7 +2,30 @@
class ProjectDetails extends TPage
{
- private $allUsers = null;
+ private $allUsers;
+
+ private $currentProject;
+
+ protected function getCurrentProject()
+ {
+ if(!$this->currentProject)
+ {
+ $id = intval($this->Request['ProjectID']);
+ if($id > 0)
+ $this->currentProject = $this->getProjectDao()->getProjectByID($id);
+ }
+ return $this->currentProject;
+ }
+
+ protected function getProjectDao()
+ {
+ return $this->Application->Modules['daos']->getDao('ProjectDao');
+ }
+
+ protected function getCategoryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('CategoryDao');
+ }
public function onLoad($param)
{
@@ -12,7 +35,53 @@ class ProjectDetails extends TPage
$this->manager->dataBind();
$this->members->DataSource = $this->getUsersWithRole('consultant');
$this->members->dataBind();
+
+ $project = $this->getCurrentProject();
+
+ if($project !== null)
+ {
+ $this->projectName->Text = $project->Name;
+ $this->completionDate->TimeStamp = $project->CompletionDate;
+ $this->description->Text = $project->Description;
+ $this->estimateHours->Text = $project->EstimateDuration;
+ $this->manager->SelectedValue = $project->ManagerUserName;
+
+ $this->selectProjectMembers($project->ID);
+
+ $this->projectCategoryColumn->Visible = true;
+ $this->categories->ProjectID = $project->ID;
+ $this->categories->showCategories();
+
+ $this->deleteButton->Visible = true;
+
+ $this->projectList->DataSource = $this->getProjects();
+ $this->projectList->dataBind();
+
+ }
+ else
+ {
+ $this->projectCategoryColumn->Visible = false;
+ $this->deleteButton->Visible = false;
+ }
+
+ }
+ }
+
+ protected function getProjects()
+ {
+ $projects = array();
+ foreach($this->getProjectDao()->getAllProjects() as $project)
+ {
+ if($project->Name != $this->currentProject->Name)
+ $projects[$project->ID] = $project->Name;
}
+ return $projects;
+ }
+
+ protected function selectProjectMembers($projectID)
+ {
+ $members = $this->getProjectDao()->getProjectMembers($projectID);
+ $this->members->SelectedValues = $members;
}
protected function getUsersWithRole($role)
@@ -26,10 +95,97 @@ class ProjectDetails extends TPage
foreach($this->allUsers as $user)
{
if($user->isInRole($role))
- $users[] = $user->Name;
+ $users[$user->Name] = $user->Name;
}
return $users;
}
+
+ public function onPreRender($param)
+ {
+ $ids = array();
+ foreach($this->members->Items as $item)
+ {
+ if($item->Selected)
+ $ids[] = $item->Value;
+ }
+ $this->setViewState('ActiveConsultants', $ids);
+ }
+
+ public function saveButton_clicked($sender, $param)
+ {
+ if(!$this->Page->IsValid)
+ return;
+
+ $newProject = new Project;
+
+ $projectDao = $this->getProjectDao();
+
+ if($project = $this->getCurrentProject())
+ $newProject = $projectDao->getProjectByID($project->ID);
+ else
+ $newProject->CreatorUserName = $this->User->Name;
+
+ $newProject->Name = $this->projectName->Text;
+ $newProject->CompletionDate = $this->completionDate->TimeStamp;
+ $newProject->Description = $this->description->Text;
+ $newProject->EstimateDuration = floatval($this->estimateHours->Text);
+ $newProject->ManagerUserName = $this->manager->SelectedValue;
+
+ if($this->currentProject)
+ $projectDao->updateProject($newProject);
+ else
+ $projectDao->addNewProject($newProject);
+
+ $this->updateProjectMembers($newProject->ID);
+
+ $url = $this->Service->constructUrl('TimeTracker.ProjectDetails',
+ array('ProjectID'=> $newProject->ID));
+
+ $this->Response->redirect($url);
+ }
+
+ protected function updateProjectMembers($projectID)
+ {
+ $active = $this->getViewState('ActiveConsultants');
+ $projectDao = $this->getProjectDao();
+ foreach($this->members->Items as $item)
+ {
+ if($item->Selected)
+ {
+ if(!in_array($item->Value, $active))
+ $projectDao->addUserToProject($projectID, $item->Value);
+ }
+ else
+ {
+ if(in_array($item->Value, $active))
+ $projectDao->removeUserFromProject($projectID, $item->Value);
+ }
+ }
+ }
+
+ public function deleteButton_clicked($sender, $param)
+ {
+ if($project = $this->getCurrentProject())
+ {
+ $this->getProjectDao()->deleteProject($project->ID);
+ $url = $this->Service->constructUrl('TimeTracker.ProjectList');
+ $this->Response->redirect($url);
+ }
+ }
+
+ public function copyButton_clicked($sender, $param)
+ {
+ $project = $this->projectList->SelectedValue;
+ $categoryDao = $this->getCategoryDao();
+ $categories = $categoryDao->getCategoriesByProjectID($project);
+ $currentProject = $this->getCurrentProject();
+ foreach($categories as $cat)
+ {
+ $cat->ProjectID = $currentProject->ID;
+ $categoryDao->addNewCategory($cat);
+ }
+ $this->categories->showCategories();
+ }
}
?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ProjectList.page b/demos/time-tracker/protected/pages/TimeTracker/ProjectList.page
index 1bc50a4b..f55360c4 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/ProjectList.page
+++ b/demos/time-tracker/protected/pages/TimeTracker/ProjectList.page
@@ -1,4 +1,42 @@
<com:TContent ID="Main">
-<h1>Projects</h1>
+<h2>Projects</h2>
+
+<fieldset class="project-list">
+<legend>Project List</legend>
+<com:TDataGrid
+ ID="projectList"
+ AllowSorting="true"
+ OnSortCommand="sortProjects"
+ AutoGenerateColumns="false">
+ <com:THyperLinkColumn
+ HeaderText="Project Name"
+ DataTextField="Name"
+ DataNavigateUrlField="ID"
+ SortExpression="Name"
+ DataNavigateUrlFormatString="?page=TimeTracker.ProjectDetails&ProjectID=%d" />
+ <com:TBoundColumn
+ SortExpression="ManagerUserName"
+ HeaderText="Project Manager"
+ DataField="ManagerUserName" />
+ <com:TBoundColumn
+ SortExpression="Description"
+ HeaderText="Description"
+ DataField="Description" />
+ <com:TTemplateColumn HeaderText="Completion" SortExpression="CompletionDate">
+ <prop:ItemTemplate>
+ <com:System.I18N.TDateFormat
+ Pattern="dd/MM/yyyy"
+ Value=<%# $this->NamingContainer->DataItem->CompletionDate %> />
+ </prop:ItemTemplate>
+ </com:TTemplateColumn>
+ <com:TBoundColumn
+ SortExpression="EstimateDuration"
+ HeaderText="Estimate Duration"
+ DataField="EstimateDuration" />
+</com:TDataGrid>
+<div style="padding:1em">
+ <a href="?page=TimeTracker.ProjectDetails">Create New Project</a>
+</div>
+</fieldset>
</com:TContent> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ProjectList.php b/demos/time-tracker/protected/pages/TimeTracker/ProjectList.php
new file mode 100644
index 00000000..eb92dcb7
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/ProjectList.php
@@ -0,0 +1,34 @@
+<?php
+
+class ProjectList extends TPage
+{
+ protected function showProjects($sort='', $order='')
+ {
+ $dao = $this->Application->Modules['daos']->getDao('ProjectDao');
+ $this->projectList->DataSource = $dao->getAllProjects($sort, $order);
+ $this->projectList->dataBind();
+ }
+
+ protected function getSortOrder($sort)
+ {
+ $ordering = $this->getViewState('SortOrder', array());
+ $order = isset($ordering[$sort]) ? $ordering[$sort] : 'DESC';
+ $ordering[$sort] = $order == 'DESC' ? 'ASC' : 'DESC';
+ $this->setViewState('SortOrder', $ordering);
+ return $ordering[$sort];
+ }
+
+ protected function sortProjects($sender, $param)
+ {
+ $sort = $param->SortExpression;
+ $this->showProjects($sort, $this->getSortOrder($sort));
+ }
+
+ public function onLoad($param)
+ {
+ if(!$this->IsPostBack)
+ $this->showProjects();
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page b/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
index 699c2544..065b6b17 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
+++ b/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
@@ -1,4 +1,17 @@
<com:TContent ID="Main">
-<h1>Project Reports</h1>
+<h2>Project Reports</h2>
+
+<fieldset>
+ <legend>Project Report</legend>
+<com:TMultiView ID="views" ActiveViewIndex="0">
+ <com:TView>
+ <com:TLabel ForControl="projects"
+ Text="Select a project. Use ctrl+click to select multiple resources at once: "/>
+ <com:TListBox ID="projects" CssClass="projects" />
+ <com:TButton Text="Generate Report" />
+ </com:TView>
+</com:TMultiView>
+
+</fieldset>
</com:TContent> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl
index 808c233b..5bea2811 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl
+++ b/demos/time-tracker/protected/pages/TimeTracker/SiteMap.tpl
@@ -1,7 +1,7 @@
<com:TPanel CssClass="sitemap" Visible="true">
<ul class="level1">
<li class="<com:TPlaceHolder ID="LogMenu" />">
- <a class="menuitem" href="?page=TimeTracker.TimeEntry">Log</a>
+ <a class="menuitem" href="?page=TimeTracker.LogTimeEntry">Log</a>
</li>
<com:TPlaceHolder Visible=<%= $this->User->isInRole('manager') %> >
<li class="<com:TPlaceHolder ID="ReportMenu" />">
diff --git a/demos/time-tracker/protected/pages/TimeTracker/TimeEntry.page b/demos/time-tracker/protected/pages/TimeTracker/TimeEntry.page
deleted file mode 100644
index f934ca02..00000000
--- a/demos/time-tracker/protected/pages/TimeTracker/TimeEntry.page
+++ /dev/null
@@ -1,4 +0,0 @@
-<com:TContent ID="Main">
-<h1>Time Entry</h1>
-
-</com:TContent> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.php b/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.php
new file mode 100644
index 00000000..2b5f7a0f
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.php
@@ -0,0 +1,89 @@
+<?php
+
+class TimeEntryList extends TTemplateControl
+{
+ protected function getTimeEntryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('TimeEntryDao');
+ }
+
+ protected function getCategoryDao()
+ {
+ return $this->Application->Modules['daos']->getDao('CategoryDao');
+ }
+
+ public function setProjectEntry($userID,$projectID)
+ {
+ $this->setViewState('ProjectEntry', array($userID,$projectID));
+ }
+
+ protected function getCategories()
+ {
+ $project = $this->getViewState('ProjectEntry');
+ foreach($this->getCategoryDao()->getCategoriesByProjectID($project[1]) as $cat)
+ {
+ $categories[$cat->ID] = $cat->Name;
+ }
+ return $categories;
+ }
+
+ protected function showEntryList()
+ {
+ $project = $this->getViewState('ProjectEntry');
+ $list = $this->getTimeEntryDao()->getTimeEntriesInProject($project[0], $project[1]);
+ $this->entries->DataSource = $list;
+ $this->entries->dataBind();
+ }
+
+ public function refreshEntryList()
+ {
+ $this->entries->EditItemIndex=-1;
+ $this->showEntryList();
+ }
+
+ public function editEntryItem($sender, $param)
+ {
+ $this->entries->EditItemIndex=$param->Item->ItemIndex;
+ $this->showEntryList();
+ }
+
+ public function deleteEntryItem($sender, $param)
+ {
+ $id = $this->entries->DataKeys[$param->Item->ItemIndex];
+ $this->getTimeEntryDao()->deleteTimeEntry($id);
+ $this->refreshEntryList();
+ }
+
+ public function updateEntryItem($sender, $param)
+ {
+ if(!$this->Page->IsValid)
+ return;
+
+ $item = $param->Item;
+
+ $id = $this->entries->DataKeys[$param->Item->ItemIndex];
+
+ $entry = $this->getTimeEntryDao()->getTimeEntryByID($id);
+ $category = new Category;
+ $category->ID = $param->Item->category->SelectedValue;
+ $entry->Category = $category;
+ $entry->Description = $param->Item->description->Text;
+ $entry->Duration = floatval($param->Item->hours->Text);
+ $entry->ReportDate = $param->Item->day->TimeStamp;
+
+ $this->getTimeEntryDao()->updateTimeEntry($entry);
+ $this->refreshEntryList();
+ }
+
+ public function EntryItemCreated($sender, $param)
+ {
+ if($param->Item->ItemType == 'EditItem' && $param->Item->DataItem)
+ {
+ $param->Item->category->DataSource = $this->getCategories();
+ $param->Item->category->dataBind();
+ $param->Item->category->SelectedValue = $param->Item->DataItem->Category->ID;
+ }
+ }
+}
+
+?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.tpl b/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.tpl
new file mode 100644
index 00000000..ace8a95b
--- /dev/null
+++ b/demos/time-tracker/protected/pages/TimeTracker/TimeEntryList.tpl
@@ -0,0 +1,66 @@
+<com:TDataList ID="entries"
+ RepeatLayout="Raw"
+ DataKeyField="ID"
+ OnEditCommand="editEntryItem"
+ OnCancelCommand="refreshEntryList"
+ OnUpdateCommand="updateEntryItem"
+ OnDeleteCommand="deleteEntryItem"
+ OnItemCreated="EntryItemCreated" >
+ <prop:EmptyTemplate>
+ There are no time entries for this user.
+ </prop:EmptyTemplate>
+ <prop:HeaderTemplate>
+ <table class="time-entries">
+ <tr>
+ <th>Category Name</th>
+ <th>Description</th>
+ <th>Duration</th>
+ <th>Reported Date</th>
+ <th>Edit/Delete</th>
+ </tr>
+ </prop:HeaderTemplate>
+
+ <prop:FooterTemplate>
+ </table>
+ </prop:FooterTemplate>
+ <prop:ItemTemplate>
+ <tr>
+ <td class="categoryName"><%# $this->DataItem->Category->Name %></td>
+ <td class="description"><%# $this->DataItem->Description %></td>
+ <td class="duration"><%# $this->DataItem->Duration %></td>
+ <td class="date">
+ <com:System.I18N.TDateFormat
+ Pattern="dd/MM/yyyy"
+ Value=<%# $this->DataItem->ReportDate %> />
+ </td>
+ <td class="edit">
+ <com:TButton Text="Edit" CommandName="edit"/>
+ <com:TButton Text="Delete" CommandName="delete"
+ Attributes.onclick="if(!confirm('Are you sure?')) return false;" />
+ </td>
+ </tr>
+ </prop:ItemTemplate>
+
+ <prop:EditItemTemplate>
+ <tr>
+ <td class="categoryName">
+ <com:TDropDownList ID="category" />
+ </td>
+ <td class="description">
+ <com:TTextBox ID="description" Text=<%# $this->DataItem->Description %> />
+ </td>
+ <td class="duration">
+ <com:TTextBox ID="hours" Text=<%# $this->DataItem->Duration %> />
+ </td>
+ <td class="date">
+ <com:TDatePicker InputMode="DropDownList" ID="day"
+ TimeStamp=<%# $this->DataItem->ReportDate %> />
+ </td>
+ <td class="edit">
+ <com:TButton Text="Save" CommandName="update" ValidationGroup="entry-update"/>
+ <com:TButton Text="Cancel" CommandName="cancel" />
+ </td>
+ </tr>
+ </prop:EditItemTemplate>
+
+</com:TDataList> \ No newline at end of file
diff --git a/demos/time-tracker/protected/pages/TimeTracker/UserList.page b/demos/time-tracker/protected/pages/TimeTracker/UserList.page
index f0c88112..3696e1db 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/UserList.page
+++ b/demos/time-tracker/protected/pages/TimeTracker/UserList.page
@@ -1,31 +1,20 @@
<com:TContent ID="Main">
-<h1>List Users</h1>
+<h2>Users</h2>
<fieldset>
<legend>User List</legend>
<com:TRepeater ID="list" EnableViewState="false">
- <prop:HeaderTemplate>
- <table cellpadding="2">
- <tr class="header">
- <th>User Name</th>
- <th>E-Mail Address</th>
- </tr>
- </prop:HeaderTemplate>
- <prop:ItemTemplate>
- <tr class="row0">
- <td><%#$this->DataItem->Name %></td>
- <td><%#$this->DataItem->EmailAddress %></td>
- </tr>
- </prop:ItemTemplate>
- <prop:AlternatingItemTemplate>
- <tr class="row1">
- <td><%#$this->DataItem->Name %></td>
+ <prop:HeaderTemplate>
+ <table cellpadding="2">
+ <tr class="header">
+ <th>User Name</th>
+ <th>E-Mail Address</th>
+ </tr>
+ </prop:HeaderTemplate>
+ <prop:ItemTemplate>
+ <tr class="row0"> <td><%#$this->DataItem->Name %></td> <td><%#$this->DataItem->EmailAddress %></td> </tr> </prop:ItemTemplate> <prop:AlternatingItemTemplate> <tr class="row1"> <td><%#$this->DataItem->Name %></td>
<td><%#$this->DataItem->EmailAddress %></td>
- </tr>
- </prop:AlternatingItemTemplate>
- <prop:FooterTemplate>
- </table>
- </prop:FooterTemplate>
+ </tr> </prop:AlternatingItemTemplate> <prop:FooterTemplate> </table> </prop:FooterTemplate>
</com:TRepeater>
<div style="padding:1em">
<a href="?page=TimeTracker.UserCreate">Create New User</a>
diff --git a/demos/time-tracker/protected/pages/TimeTracker/config.xml b/demos/time-tracker/protected/pages/TimeTracker/config.xml
index 4497d9e3..b086f8a0 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/config.xml
+++ b/demos/time-tracker/protected/pages/TimeTracker/config.xml
@@ -13,7 +13,7 @@
<authorization>
<allow roles="admin" />
<allow pages="ProjectList, ProjectDetails, ReportResource, ReportProject" roles="manager" />
- <allow pages="TimeEntry" roles="consultant" />
+ <allow pages="LogTimeEntry" roles="consultant" />
<allow pages="UserCreate,Logout,Login" users="*" />
<deny users="*" />
</authorization>
diff --git a/demos/time-tracker/themes/TimeTracker/project.css b/demos/time-tracker/themes/TimeTracker/project.css
index 7b6863a0..809948cd 100644
--- a/demos/time-tracker/themes/TimeTracker/project.css
+++ b/demos/time-tracker/themes/TimeTracker/project.css
@@ -1,19 +1,17 @@
-fieldset.project label
+fieldset.project label, fieldset.project p
{
- display: block;
font-size: 0.9em;
- margin-bottom: 0.2em;
}
.projectInfo
{
- width: 40%;
+ width: 49%;
float: left;
}
.projectMembers
{
- width: 40%;
+ width: 50%;
float: left;
margin-left: 0.3em;
}
@@ -30,17 +28,20 @@ fieldset.project h2
background-position: center;
}
-.projectInfo div, .projectMembers div
+.projectInfo div, .projectMembers div, .projectCategory div
{
margin: 0.7em 0;
}
-.projectInfo div input, .projectInfo div.manager select
+.projectInfo div input, .projectInfo div.manager select,
+.projectCategory .categoryName input
{
width: 15em;
}
-.projectInfo .estimateHours input
+.projectInfo .estimateHours input,
+.projectCategory .abbrev input,
+.projectCategory .duration input
{
width: 4em;
}
@@ -57,14 +58,87 @@ fieldset.project h2
height: 17em;
}
-.actionButtons
+.projectCategory
{
float: left;
- width: 90%;
- padding: 0.65em;
+ display: block;
+}
+
+.actions
+{
+ float: left;
+ margin-top: 1em;
+ clear: both;
+ width: 100%;
text-align: center;
+}
+
+.actions .buttons
+{
background-color: #D2E8E8;
background-image: url(bar.png);
background-repeat: repeat-x;
background-position: center;
+ padding: 0.65em;
+}
+
+.actions .buttons input
+{
+ padding: 0.15em 1em;
+}
+
+.actions .buttons input.save
+{
+ padding: 0.15em 2.5em;
+}
+
+
+
+fieldset.project .validator
+{
+ display: block;
+}
+
+fieldset.project .categoryName
+{
+ width: 50%;
+ border: 1px solid red;
+}
+
+fieldset.project td.abbrev,
+fieldset.project td.duration,
+fieldset.project td.edit
+{
+ width: 20%;
+ border: 1px solid red;
+}
+
+
+.fromProject select
+{
+ width: 15em;
+}
+
+fieldset.project .projectCategory table
+{
+ border-collapse: collapse;
+ width: 100%;
+}
+
+fieldset.project .projectCategory table th, fieldset.project td.edit
+{
+ white-space: nowrap;
+ text-align: left;
+ padding: 0.2em;
+}
+
+fieldset.project .projectCategory table th
+{
+ font-size: 0.9em;
+}
+
+fieldset.project .projectCategory table td
+{
+ border: 1px solid #6495ED;
+ padding: 0.2em;
} \ No newline at end of file
diff --git a/demos/time-tracker/themes/TimeTracker/site.css b/demos/time-tracker/themes/TimeTracker/site.css
index 386260a6..8a162002 100644
--- a/demos/time-tracker/themes/TimeTracker/site.css
+++ b/demos/time-tracker/themes/TimeTracker/site.css
@@ -226,4 +226,11 @@ fieldset.signup .wizardNav
.row1
{
background-color: #eef;
+}
+
+
+.required-input, .required-input1, .required-input2
+{
+ border: 2px solid red;
+ background-color: #FFE4E1
} \ No newline at end of file
diff --git a/demos/time-tracker/themes/TimeTracker/time-entry.css b/demos/time-tracker/themes/TimeTracker/time-entry.css
new file mode 100644
index 00000000..0956f4e7
--- /dev/null
+++ b/demos/time-tracker/themes/TimeTracker/time-entry.css
@@ -0,0 +1,46 @@
+
+.loghours label, .timesheet label
+{
+ font-size: 0.9em;
+}
+
+.loghours div, .timesheet div
+{
+ margin-bottom: 0.7em;
+}
+.loghours .category select,
+.loghours .project select,
+.loghours .description textarea
+{
+ width: 14em;
+}
+
+.loghours .description textarea
+{
+ width: 95%;
+ height: 4em;
+}
+
+.loghours .hours input
+{
+ width: 4em;
+ font-weight: bold;
+ text-align: center;
+}
+
+.loghours .project, .loghours .category, .loghours .day
+{
+ width: 12em;
+ float: left;
+}
+
+.loghours .addEntry input
+{
+ margin-top: 1em;
+ padding: 0.15em 2.5em;
+}
+
+.sheetfor
+{
+ width: 15em;
+} \ No newline at end of file
diff --git a/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php b/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php
index ba8323cc..0d1172b0 100644
--- a/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php
+++ b/framework/DataAccess/SQLMap/Configuration/TDomSqlMapBuilder.php
@@ -64,8 +64,8 @@ class TDomSqlMapBuilder
if(isset($document->settings) && isset($document->settings->setting))
$this->configureSettings($document->settings);
- if(isset($document->typeHandler))
- $this->loadTypeHandler($document, $this->_configFile);
+ foreach($document->xpath('//typeHandler') as $handler)
+ $this->loadTypeHandler($handler, $this->_configFile);
//load database provider
if(isset($document->provider) && isset($document->provider->datasource))
@@ -79,8 +79,8 @@ class TDomSqlMapBuilder
'sqlmap_unable_to_find_db_config', $this->_configFile);
}
- if(isset($document->sqlMaps) && isset($document->sqlMaps->sqlMap))
- $this->loadSqlMappingFiles($document->sqlMaps);
+ foreach($document->xpath('//sqlMap') as $sqlmap)
+ $this->loadSqlMappingFiles($sqlmap);
if($this->_sqlMapper->getIsCacheModelsEnabled())
$this->attachCacheModel();
@@ -182,46 +182,40 @@ class TDomSqlMapBuilder
//var_dump($node);
}
- protected function loadTypeHandler($nodes, $file)
+ protected function loadTypeHandler($node, $file)
{
- foreach($nodes->typeHandler as $node)
+ if(!is_null($node['type']) && !is_null($node['callback']))
{
- if(!is_null($node['type']) && !is_null($node['callback']))
+ $type = (string)$node['type'];
+ $dbType = (string)$node['dbType'];
+ $class = (string)$node['callback'];
+ if(class_exists('Prado', false))
{
- $type = (string)$node['type'];
- $class = (string)$node['callback'];
- if(class_exists('Prado', false))
- {
- $handler = Prado::createComponent($class);
- }
- else
- {
- if(class_exists($class,false))
- $handler = new $class;
- else
- throw new TSqlMapConfigurationException(
- 'sqlmap_type_handler_class_undef', $file, $class);
- }
- $factory = $this->_sqlMapper->getTypeHandlerFactory();
- $factory->register($type, $handler);
+ $handler = Prado::createComponent($class);
}
else
{
+ if(class_exists($class,false))
+ $handler = new $class;
+ else
throw new TSqlMapConfigurationException(
- 'sqlmap_type_handler_callback_undef', $file);
+ 'sqlmap_type_handler_class_undef', $file, $class);
}
+ $factory = $this->_sqlMapper->getTypeHandlerFactory();
+ $factory->register($type, $handler, $dbType);
}
- }
-
- protected function loadSqlMappingFiles($sqlmappings)
- {
- foreach($sqlmappings->sqlMap as $node)
+ else
{
- $resource = $this->getResourceFromPath((string)$node['resource']);
- $sqlmap = $this->getConfigAsXmlDocument($resource);
- $this->configureSqlMap($sqlmap,$resource);
+ throw new TSqlMapConfigurationException(
+ 'sqlmap_type_handler_callback_undef', $file);
}
+ }
+ protected function loadSqlMappingFiles($node)
+ {
+ $resource = $this->getResourceFromPath((string)$node['resource']);
+ $sqlmap = $this->getConfigAsXmlDocument($resource);
+ $this->configureSqlMap($sqlmap,$resource);
$this->resolveResultMapping();
}
@@ -243,27 +237,26 @@ class TDomSqlMapBuilder
// if(isset($document->typeAlias))
// foreach($document->typeAlias as $node)
// TTypeAliasDeSerializer::Deserialize($node, $this->_sqlMapper);
- if(isset($document->resultMap))
- foreach($document->resultMap as $node)
- $this->loadResultMap($node,$document,$file);
- if(isset($document->parameterMap))
- foreach($document->parameterMap as $node)
- $this->loadParameterMap($node, $document, $file);
- if(isset($document->statement))
- foreach($document->statement as $node)
- $this->loadStatementTag($node, $document,$file);
- if(isset($document->select))
- foreach($document->select as $node)
- $this->loadSelectTag($node, $document, $file);
- if(isset($document->insert))
- foreach($document->insert as $node)
- $this->loadInsertTag($node, $document, $file);
- if(isset($document->update))
- foreach($document->update as $node)
- $this->loadUpdateTag($node, $document, $file);
- if(isset($document->delete))
- foreach($document->delete as $node)
- $this->loadDeleteTag($node, $document, $file);
+ foreach($document->xpath('//resultMap') as $node)
+ $this->loadResultMap($node,$document,$file);
+
+ foreach($document->xpath('//parameterMap') as $node)
+ $this->loadParameterMap($node, $document, $file);
+
+ foreach($document->xpath('//statement') as $node)
+ $this->loadStatementTag($node, $document,$file);
+
+ foreach($document->xpath('//select') as $node)
+ $this->loadSelectTag($node, $document, $file);
+
+ foreach($document->xpath('//insert') as $node)
+ $this->loadInsertTag($node, $document, $file);
+
+ foreach($document->xpath('//update') as $node)
+ $this->loadUpdateTag($node, $document, $file);
+
+ foreach($document->xpath('//delete') as $node)
+ $this->loadDeleteTag($node, $document, $file);
/* if(isset($document->procedure))
foreach($document->procedure as $node)
$this->loadProcedureTag($node);
@@ -391,7 +384,7 @@ class TDomSqlMapBuilder
if(isset($superNodes[0]))
$commandText = (string)$superNodes[0] . $commandText;
else
- throw TSqlMapConfigurationException(
+ throw new TSqlMapConfigurationException(
'sqlmap_unable_to_find_parent_sql', $extend, $file);
}
@@ -404,15 +397,15 @@ class TDomSqlMapBuilder
protected function applyInlineParameterMap($statement, $sqlStatement, $node, $file)
{
+ $scope['statement'] = $statement->getID();
+ $scope['file'] = $file;
+
if($statement->parameterMap() == null)
{
- $scope['statement'] = $statement->getID();
- $scope['file'] = $file;
-
// Build a Parametermap with the inline parameters.
// if they exist. Then delete inline infos from sqltext.
$parameterParser = new TInlineParameterMapParser;
- $sqlText = $parameterParser->parseInlineParameterMap(
+ $sqlText = $parameterParser->parse(
$this->_sqlMapper, $statement, $sqlStatement, $scope);
if(count($sqlText['parameters']) > 0)
{
@@ -424,7 +417,16 @@ class TDomSqlMapBuilder
}
$sqlStatement = $sqlText['sql'];
}
- $sql = new TStaticSql();
+
+ $simpleDynamic = new TSimpleDynamicParser;
+ $dynamics = $simpleDynamic->parse($this->_sqlMapper, $statement, $sqlStatement, $scope);
+ if(count($dynamics['parameters']) > 0)
+ {
+ $sql = new TSimpleDynamicSql($dynamics['parameters']);
+ $sqlStatement = $dynamics['sql'];
+ }
+ else
+ $sql = new TStaticSql();
$sql->buildPreparedStatement($statement, $sqlStatement);
$statement->setSql($sql);
}
diff --git a/framework/DataAccess/SQLMap/Configuration/TInlineParameterMapParser.php b/framework/DataAccess/SQLMap/Configuration/TInlineParameterMapParser.php
index 8b1ecf04..bc633b2c 100644
--- a/framework/DataAccess/SQLMap/Configuration/TInlineParameterMapParser.php
+++ b/framework/DataAccess/SQLMap/Configuration/TInlineParameterMapParser.php
@@ -4,7 +4,7 @@ class TInlineParameterMapParser
{
private $PARAMETER_TOKEN_REGEXP = '/#(#?[^#]+#?)#/';
- public function parseInlineParameterMap($sqlMap, $statement, $sqlText, $scope)
+ public function parse($sqlMap, $statement, $sqlText, $scope)
{
$parameterClass = !is_null($statement)
? $statement->getParameterClass() : null;
diff --git a/framework/DataAccess/SQLMap/Configuration/TParameterProperty.php b/framework/DataAccess/SQLMap/Configuration/TParameterProperty.php
index 2ff55f73..196f27f5 100644
--- a/framework/DataAccess/SQLMap/Configuration/TParameterProperty.php
+++ b/framework/DataAccess/SQLMap/Configuration/TParameterProperty.php
@@ -19,9 +19,13 @@ class TParameterProperty extends TComponent
{
if(is_null($this->_typeHandlerFactory)) return null;
if(!is_null($this->_typeHandler))
- return $this->_typeHandlerFactory->getTypeHandler($this->_typeHandler);
- else if(!is_null($this->getType()))
- return $this->_typeHandlerFactory->getTypeHandler($this->getType());
+ {
+ return $this->_typeHandlerFactory->getTypeHandler(
+ $this->_typeHandler, $this->_dbType);
+ }
+ else if(!is_null($this->getType()))
+ return $this->_typeHandlerFactory->getTypeHandler(
+ $this->getType(), $this->_dbType);
else
return null;
}
diff --git a/framework/DataAccess/SQLMap/Configuration/TResultProperty.php b/framework/DataAccess/SQLMap/Configuration/TResultProperty.php
index 9cc0df3a..29ee366e 100644
--- a/framework/DataAccess/SQLMap/Configuration/TResultProperty.php
+++ b/framework/DataAccess/SQLMap/Configuration/TResultProperty.php
@@ -45,9 +45,11 @@ class TResultProperty extends TComponent
{
if(is_null($this->_typeHandlerFactory)) return null;
if(!is_null($this->_typeHandler))
- return $this->_typeHandlerFactory->getTypeHandler($this->_typeHandler);
+ return $this->_typeHandlerFactory->getTypeHandler(
+ $this->_typeHandler, $this->_dbType);
else if(!is_null($this->getType()))
- return $this->_typeHandlerFactory->getTypeHandler($this->getType());
+ return $this->_typeHandlerFactory->getTypeHandler(
+ $this->getType(), $this->_dbType);
else
return null;
}
diff --git a/framework/DataAccess/SQLMap/Configuration/TSimpleDynamicParser.php b/framework/DataAccess/SQLMap/Configuration/TSimpleDynamicParser.php
new file mode 100644
index 00000000..e58d8af8
--- /dev/null
+++ b/framework/DataAccess/SQLMap/Configuration/TSimpleDynamicParser.php
@@ -0,0 +1,23 @@
+<?php
+
+class TSimpleDynamicParser
+{
+ private $PARAMETER_TOKEN_REGEXP = '/\$([^\$]+)\$/';
+
+ const DYNAMIC_TOKEN = '`!`';
+
+ public function parse($sqlMap, $statement, $sqlText, $scope)
+ {
+ $matches = array();
+ $mappings = array();
+ preg_match_all($this->PARAMETER_TOKEN_REGEXP, $sqlText, $matches);
+ for($i = 0, $k=count($matches[1]); $i<$k; $i++)
+ {
+ $mappings[] = $matches[1][$i];
+ $sqlText = str_replace($matches[0][$i], self::DYNAMIC_TOKEN, $sqlText);
+ }
+ return array('sql'=>$sqlText, 'parameters'=>$mappings);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php b/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php
index 55fb1f20..80af4345 100644
--- a/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php
+++ b/framework/DataAccess/SQLMap/DataMapper/TTypeHandlerFactory.php
@@ -11,25 +11,25 @@ class TTypeHandlerFactory
$this->_typeHandlerMap = new TMap;
}
- public function getTypeHandler($type, $dbType=null)
+ public function getTypeHandler($type, $dbType='')
{
$dbTypeHandlerMap = $this->_typeHandlerMap[$type];
$handler = null;
if(!is_null($dbTypeHandlerMap))
{
- if(is_null($dbType))
+ if(empty($dbType))
$handler = $dbTypeHandlerMap[self::NullDbType];
else
{
$handler = $dbTypeHandlerMap[$dbType];
- if(is_null($handler))
+ if(is_null($handler))
$handler = $dbTypeHandlerMap[self::NullDbType];
}
}
return $handler;
}
- public function register($type, $handler, $dbType=null)
+ public function register($type, $handler, $dbType='')
{
$map = $this->_typeHandlerMap[$type];
if(is_null($map))
@@ -37,7 +37,7 @@ class TTypeHandlerFactory
$map = new TMap;
$this->_typeHandlerMap->add($type, $map);
}
- if(is_null($dbType))
+ if(empty($dbType))
$map->add(self::NullDbType, $handler);
else
$map->add($dbType, $handler);
diff --git a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
index c621f285..9bc1143f 100644
--- a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
+++ b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
@@ -220,7 +220,6 @@ class TMappedStatement extends TComponent implements IMappedStatement
$list = $result instanceof ArrayAccess ? $result :
$this->_statement->createInstanceOfListClass();
$recordSet = $this->executeSQLQueryLimit($connection, $sql, $max, $skip);
-
if(!is_null($delegate))
{
while($row = $recordSet->fetchRow())
diff --git a/framework/DataAccess/SQLMap/Statements/TPreparedCommand.php b/framework/DataAccess/SQLMap/Statements/TPreparedCommand.php
index 1c0e5ad7..3557fc1f 100644
--- a/framework/DataAccess/SQLMap/Statements/TPreparedCommand.php
+++ b/framework/DataAccess/SQLMap/Statements/TPreparedCommand.php
@@ -5,7 +5,7 @@ class TPreparedCommand
public function create($connection, $statement, $parameterObject)
{
- $prepared = $statement->getSQL()->getPreparedStatement();
+ $prepared = $statement->getSQL()->getPreparedStatement($parameterObject);
$parameters = $this->applyParameterMap($connection,
$prepared, $statement, $parameterObject);
return array('sql'=>$prepared->getPreparedSql(),
diff --git a/framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php b/framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php
index 41059934..52461983 100644
--- a/framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php
+++ b/framework/DataAccess/SQLMap/Statements/TPreparedStatementFactory.php
@@ -11,36 +11,21 @@ class TPreparedStatementFactory
{
$this->_statement = $statement;
$this->_commandText = $sqlString;
- // $this->_statement = new TPreparedStatement();
-// $this->_statement->setSqlString($sqlString);
}
public function prepare()
{
- //$this->createParametersFromTextCommand();
- //return $this->_statement;
$this->_preparedStatement = new TPreparedStatement();
$this->_preparedStatement->setPreparedSql($this->_commandText);
if(!is_null($this->_statement->parameterMap()))
- {
$this->createParametersForTextCommand();
- //$this->evaluateParameterMap();
- }
- //var_dump($this->_preparedStatement);
return $this->_preparedStatement;
}
protected function createParametersForTextCommand()
{
- /*$matches = array();
- $string = $this->_statement->getSqlString();
- preg_match_all('/#([a-zA-Z0-9._]+)#/', $string, $matches);
- $this->_statement->getParameterNames()->copyFrom($matches[0]);*/
- //var_dump($this->_statement);
foreach($this->_statement->ParameterMap()->getProperties() as $prop)
- {
$this->_preparedStatement->getParameterNames()->add($prop->getProperty());
- }
}
}
diff --git a/framework/DataAccess/SQLMap/Statements/TSimpleDynamicSql.php b/framework/DataAccess/SQLMap/Statements/TSimpleDynamicSql.php
new file mode 100644
index 00000000..1230b4f7
--- /dev/null
+++ b/framework/DataAccess/SQLMap/Statements/TSimpleDynamicSql.php
@@ -0,0 +1,32 @@
+<?php
+
+class TSimpleDynamicSql extends TStaticSql
+{
+ private $_mappings=array();
+
+ public function __construct($mappings)
+ {
+ $this->_mappings = $mappings;
+ }
+
+ public function getPreparedStatement($parameter=null)
+ {
+ $statement = parent::getPreparedStatement($parameter);
+ if($parameter !== null)
+ $this->mapDynamicParameter($statement, $parameter);
+ return $statement;
+ }
+
+ protected function mapDynamicParameter($statement, $parameter)
+ {
+ $sql = $statement->getPreparedSql();
+ foreach($this->_mappings as $property)
+ {
+ $value = TPropertyAccess::get($parameter, $property);
+ $sql = preg_replace('/'.TSimpleDynamicParser::DYNAMIC_TOKEN.'/', $value, $sql, 1);
+ }
+ $statement->setPreparedSql($sql);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/DataAccess/SQLMap/Statements/TStaticSql.php b/framework/DataAccess/SQLMap/Statements/TStaticSql.php
index bf6e4a18..b99b86ed 100644
--- a/framework/DataAccess/SQLMap/Statements/TStaticSql.php
+++ b/framework/DataAccess/SQLMap/Statements/TStaticSql.php
@@ -10,7 +10,7 @@ class TStaticSql extends TComponent
$this->_preparedStatement = $factory->prepare();
}
- public function getPreparedStatement()
+ public function getPreparedStatement($parameter=null)
{
return $this->_preparedStatement;
}
diff --git a/framework/DataAccess/TAdodb.php b/framework/DataAccess/TAdodb.php
index cd188e49..a9b55e1e 100644
--- a/framework/DataAccess/TAdodb.php
+++ b/framework/DataAccess/TAdodb.php
@@ -402,21 +402,13 @@ class TAdodbConnection extends TDbConnection
}
/**
- * Finish and cleanup transactions.
- */
- public function completeTransaction()
- {
- return $this->connection->CompleteTrans();
- }
-
- /**
* End a transaction successfully.
* @return true if successful. If the database does not support
* transactions, will return true also as data is always committed.
*/
public function commit()
{
- return $this->connection->CommitTrans();
+ return $this->_connection->CommitTrans();
}
/**
@@ -426,7 +418,7 @@ class TAdodbConnection extends TDbConnection
*/
public function rollback()
{
- return $this->connection->RollbackTrans();
+ return $this->_connection->RollbackTrans();
}
/**
diff --git a/framework/DataAccess/TDatabaseProvider.php b/framework/DataAccess/TDatabaseProvider.php
index a39213f1..067c7243 100644
--- a/framework/DataAccess/TDatabaseProvider.php
+++ b/framework/DataAccess/TDatabaseProvider.php
@@ -268,12 +268,6 @@ interface IDbConnection
public function beginTransaction();
/**
- * Finish and cleanup transactions. Not all database will support
- * transactions.
- */
- public function completeTransaction();
-
- /**
* Makes all changes made since the previous commit/rollback permanent and
* releases any database locks. Not all database will support transactions.
*/
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
index fd206508..8869ab9e 100644
--- a/framework/Web/Javascripts/js/validator.js
+++ b/framework/Web/Javascripts/js/validator.js
@@ -55,7 +55,7 @@ this.visible=this.visible&&this.messages.style.display!="none";Prado.Validation.
return;}
var refresh=update||this.visible==false||this.options.Refresh!=false;if(this.options.ShowSummary!=false&&refresh)
{this.updateHTMLMessages(this.getMessages(validators));this.showSummary(validators);}
-if(this.options.ScrollToSummary!=false)
+if(this.options.ScrollToSummary!=false&&refresh)
window.scrollTo(this.messages.offsetLeft-20,this.messages.offsetTop-20);if(this.options.ShowMessageBox==true&&refresh)
{this.alertMessages(this.getMessages(validators));this.visible=true;}},updateHTMLMessages:function(messages)
{while(this.messages.childNodes.length>0)
diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js
index ae28e1fa..9535f8c5 100644
--- a/framework/Web/Javascripts/prado/validation3.js
+++ b/framework/Web/Javascripts/prado/validation3.js
@@ -396,7 +396,7 @@ Prado.WebUI.TValidationSummary.prototype =
this.showSummary(validators);
}
- if(this.options.ScrollToSummary != false)
+ if(this.options.ScrollToSummary != false && refresh)
window.scrollTo(this.messages.offsetLeft-20, this.messages.offsetTop-20);
if(this.options.ShowMessageBox == true && refresh)