diff options
Diffstat (limited to 'demos')
22 files changed, 1059 insertions, 53 deletions
| 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.dbBinary files differ index 03fe9156..e7adaec3 100644 --- a/demos/time-tracker/protected/App_Data/time_tracker.db +++ b/demos/time-tracker/protected/App_Data/time_tracker.db 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 | 
