<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="100%"
height="100%"
creationComplete="initApp();"
viewSourceURL="srcview/index.html" xmlns:local="*"
>
<mx:VBox id="main_box" width="100%" height="100%" resize="{this.width = main_box.width;this.height = main_box.height;}">
<mx:HBox backgroundColor="white" width="100%" horizontalAlign="center">
<mx:Label color="black" id="ver" />
<mx:HBox alpha="0.3">
<mx:Button label="usage" click="{navigateToURL(new URLRequest(youtubeVideo));}"/>
<mx:Button label="report issue" click="{navigateToURL(new URLRequest('http://code.google.com/p/tasktracer2/issues/list'));}"/>
</mx:HBox>
</mx:HBox>
<mx:HBox width="100%" horizontalGap="0">
<mx:HBox id="inputs" width="100%" horizontalGap="0" horizontalScrollPolicy="off">
</mx:HBox>
<mx:HBox horizontalGap="2">
<mx:Button label="ADD COLUMN" click="AddDataGrid();" visible="true" includeInLayout="true" width="98" toolTip="Adds another sub-task-level."/>
<mx:Button label="UPDATE" click="UPDATE();" visible="true" includeInLayout="true" width="66" toolTip="Updates a selected entry."/>
<mx:Button label="DELETE" click="DELETE();" visible="true" includeInLayout="true" width="65" toolTip="Deletes a selected entry."/>
</mx:HBox>
</mx:HBox>
<mx:HBox width="100%" height="100%">
<mx:HBox id="taskGrids" width="100%" height="100%" horizontalGap="0" horizontalScrollPolicy="on" scroll="SyncScroll(event);">
</mx:HBox>
<local:DataGrid2 id="timeGrid" height="100%" width="115" click="datagrid_clickTime(event);" dataProvider="{new Array()}"/>
<mx:VBox horizontalGap="0" verticalGap="0">
<mx:Label text="CURRENT TIME"/>
<mx:Label id="TIME_CURRENT" text=""/>
<mx:HBox horizontalGap="0">
<mx:Button label="START" click="StartTimer();" toolTip="Start couting how much time you spend on the selected task."/>
<mx:Button label="STOP" click="StopTimer();" toolTip="Stop couting how much time you spend on the selected task."/>
</mx:HBox>
<mx:HBox horizontalGap="0">
<s:ComboBox id="STATUS" dataProvider="{new ArrayCollection(['complete','billed'])}" width="100%" toolTip="hit enter to defined a custom status" keyDown="KEYDOWN_status(event);"/>
<mx:Button label="ADD" width="43" toolTip="Add or update a predifined/custom status to a task and all it's subtasks/times, e.g. mark it as completed etc." click="AddStatus();"/>
</mx:HBox>
<mx:Label text="START"/>
<mx:TextInput id="TIME_START" width="100%"/>
<mx:Label text="STOP"/>
<mx:TextInput id="TIME_STOP" width="100%"/>
<mx:Label text="TIME FINISHED"/>
<mx:TextInput id="TIME_ESTIMATED" width="100%"/>
<mx:Label text="SPEND"/>
<mx:TextInput id="TIME_SPEND" width="100%"/>
<mx:Label text="LEFT"/>
<mx:TextInput id="TIME_LEFT" width="100%"/>
</mx:VBox>
</mx:HBox>
<mx:HBox width="100%" horizontalGap="0">
<mx:TextArea id="COMMENT" width="100%" keyDown="KEYDOWN_comment(event);" toolTip="Hit Ctrl+Enter to add or update a comment." height="85"/>
<mx:VBox>
<mx:Button label="ADD COMENT" click="AddUpdateComment(null,COMMENT.text);"/>
<mx:Label id="LABEL_STATUS" width="150"/>
</mx:VBox>
</mx:HBox>
</mx:VBox>
<fx:Declarations>
</fx:Declarations>
<fx:Script>
<![CDATA[
import flashx.textLayout.elements.SpecialCharacterElement;
import flashx.textLayout.tlf_internal;
import misc.c_ARRAY;
import misc.c_DATE;
import misc.c_OBJECT;
import misc.c_STRING;
import mx.charts.series.ColumnSeries;
import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.controls.DataGrid;
import mx.controls.dataGridClasses.DataGridColumn;
import mx.core.Container;
import mx.effects.Sequence;
import mx.events.EffectEvent;
import mx.events.ScrollEvent;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import org.osmf.events.TimeEvent;
import spark.effects.Fade;
import sqllite.air_sqllite_interaction;
public var MaxTasks:int = 10;
public var youtubeVideo:String = "http://www.youtube.com/watch?feature=player_embedded&v=Mpuo1rlWj5k";
public var air_sqllite_interaction_inst:air_sqllite_interaction = null;
public var DataBaseLayout:Object = null;
public var c_ARRAY_inst:c_ARRAY = new c_ARRAY();
public var c_OBJECT_inst:c_OBJECT = new c_OBJECT();
public var c_STRING_inst:c_STRING = new c_STRING();
public var c_DATE_inst:c_DATE = new c_DATE();
public function initApp():void
{
this.addEventListener(Event.CLOSING, onExit);
var DATE:Date = new Date();
air_sqllite_interaction_inst = new air_sqllite_interaction("TaskTracer.sqlite" ,null ,LOAD_STUFF ,HandleFault ,null);
checkForUpdate();
AddTimeGrid();
}
import flash.events.ErrorEvent;
import air.update.ApplicationUpdaterUI;
import air.update.events.UpdateEvent;
import mx.controls.Alert;
private var appUpdater:ApplicationUpdaterUI = new ApplicationUpdaterUI();
private function checkForUpdate():void {
setApplicationVersion(); appUpdater.updateURL = "http://praxis2.dyndns.org/tools/TaskTracer/update.xml"; appUpdater.isCheckForUpdateVisible = false; appUpdater.addEventListener(UpdateEvent.INITIALIZED, onUpdate); appUpdater.addEventListener(ErrorEvent.ERROR, onError); appUpdater.initialize(); }
private function onError(event:ErrorEvent):void {
Alert.show(event.toString());
}
private function onUpdate(event:UpdateEvent):void {
appUpdater.checkNow(); }
private function setApplicationVersion():void {
var appXML:XML = NativeApplication.nativeApplication.applicationDescriptor;
var ns:Namespace = appXML.namespace();
ver.text = "Version " + appXML.ns::version;
}
public var LEVEL:int = 0;
public function LOAD_STUFF(event:Event = null):void
{
if(LEVEL == 0)
{
CreateDatabaseLayout();
}
else if(LEVEL == 1)
{
DO_LOAD_STUFF = true;
readTable(null,"TASKS");
}
else if(LEVEL == 2)
{
readTable(null,"TIMES");
}
else if(LEVEL == 3)
{
DO_LOAD_STUFF = false;
ShowTime();
}
LEVEL++;
}
/** will hold all the tables from the database **/
public var TABLES:Object = {TASKS:"",TIMES:"",COMMENTS:"",DATAPROVIDERS:new Object()};
/** NAME OF THE TABLE that is currently fetched from database **/
public var CURRENT_TABLE_NAME:String = "";
public function readTable2(event:Event = null):void
{
readTable(null,CURRENT_TABLE_NAME);
}
public function readTableTasksAndTimes(event:Event = null):void
{
CURRENT_TABLE_NAME = "TASKS";
readTable(null,CURRENT_TABLE_NAME);
CURRENT_TABLE_NAME = "TIMES";
readTable(null,CURRENT_TABLE_NAME);
}
var DO_LOAD_STUFF:Boolean = false;
public function readTable(event:Event = null,TABLENAME:String = ""):void
{
if(event == null)
{
if(c_OBJECT_inst.not_empty(TABLENAME))
{
CURRENT_TABLE_NAME = TABLENAME;
air_sqllite_interaction_inst.READTABLE(null,TABLENAME,readTable);
}
}
else
{
if(event is ResultEvent)
{
var RESULTEVENT:ResultEvent = event as ResultEvent;
TABLES["DATAPROVIDERS"] = new Array();
TABLES[CURRENT_TABLE_NAME] = RESULTEVENT.result;
var MAX_PARENT_COUNT:int = 0;
if(CURRENT_TABLE_NAME == "TASKS")
{
var ARRAY:Array = RESULTEVENT.result as Array;
for each(var TASK:Object in ARRAY)
{
if(TASK["PARENTTASKID"] == "")
{
if(TABLES["DATAPROVIDERS"][0] == null)
{
TABLES["DATAPROVIDERS"][0] = new Array();
}
TABLES["DATAPROVIDERS"][0].push(TASK);
}
else
{
recursionCount = 0;
var PARENT_COUNT:int = ParentCount(ARRAY,TASK);
if(PARENT_COUNT > MAX_PARENT_COUNT)
{
MAX_PARENT_COUNT = PARENT_COUNT;
}
if(TABLES["DATAPROVIDERS"][PARENT_COUNT] == null)
{
TABLES["DATAPROVIDERS"][PARENT_COUNT] = new Array();
}
TABLES["DATAPROVIDERS"][PARENT_COUNT].push(TASK);
}
}
while(taskGrids.getChildren().length > (MAX_PARENT_COUNT+1))
{
var pos:int = taskGrids.getChildren().length-1;
taskGrids.removeChildAt(pos);
inputs.removeChildAt(pos);
}
for(var counter:int = 0;!(counter > MAX_PARENT_COUNT);counter++)
{
var DATAGRID2:DataGrid2 = null;
if(DO_LOAD_STUFF || (taskGrids.getChildren().length == 0))
{
DATAGRID2 = AddDataGrid(null,"TASK");
}
else
{
DATAGRID2 = taskGrids.getChildAt(counter) as DataGrid2;
}
DATAGRID2.dataGrid.dataProvider = TABLES["DATAPROVIDERS"][counter];
DATAGRID2.dataProvider = TABLES["DATAPROVIDERS"][counter];
}
}
else if(CURRENT_TABLE_NAME == "TIMES")
{
var RESULTEVENT:ResultEvent = event as ResultEvent;
TABLES[CURRENT_TABLE_NAME] = new Array();
TABLES[CURRENT_TABLE_NAME] = RESULTEVENT.result;
datagrid_click(new MouseEvent(MouseEvent.CLICK,false,false,null,null,timeGrid));
}
if(DO_LOAD_STUFF)
{
LOAD_STUFF();
}
if(itemChanged_while_Timer_running_useLastSelectedItem)
{
itemChanged_while_Timer_running_useLastSelectedItem = false;
}
else
{
ReSelected();
}
}
else if(event is FaultEvent)
{
var FAULTEVENT:FaultEvent = event as FaultEvent;
trace(FAULTEVENT);
}
}
}
/** o 7.1. after update/add of task or time the last selected task must again be selected again **/
public function ReSelected():void
{
if(c_OBJECT_inst.not_empty(lastSelectedDataGrid))
{
for each(var ELEMENT:Object in lastSelectedDataGrid.dataGrid.dataProvider["source"])
{
if(ELEMENT["id"] == lastSelectedItem["id"])
{
lastSelectedDataGrid.dataGrid.selectedItem = ELEMENT;
selectedDatagrid = lastSelectedDataGrid;
}
}
datagrid_click(new MouseEvent(MouseEvent.CLICK,false,false,null,null,lastSelectedDataGrid));
}
}
public function FindParentTask(ARRAY:Array,PARENTTASKID:String):Object
{
var RESULT:Object = null;
for each(var ELEMENT:Object in ARRAY)
{
if(ELEMENT["id"] == PARENTTASKID)
{
RESULT = ELEMENT;
break;
}
}
return RESULT;
}
var recursionCount:int = 0;
public function ParentCount(TASKS:Array,TASK:Object):int
{
if(TASK["PARENTTASKID"] != "")
{
var TASK:Object = FindParentTask(TASKS,TASK["PARENTTASKID"])
if(TASK == null)
{
return recursionCount;
}
recursionCount++;
if(TASK["PARENTTASKID"] == "")
{
return recursionCount;
}
else
{
ParentCount(TASKS,TASK);
}
}
return recursionCount;
}
public function FindParentTaskID(ARRAY:Array,TASK:Object):String
{
var RESULT:String = "";
var TASK:Object = FindParentTask(ARRAY,TASK["id"]);
RESULT = TASK["id"];
return RESULT;
}
/** the currently selected datagrid **/
public var selectedDatagrid:DataGrid2 = null;
public var lastSelectedDataGrid:DataGrid2 = null;
public var lastSelectedItem:Object = null;
public var parentDatagrid:DataGrid2 = null;
public var selectedInput:Object = null;
public function HandleFault(event:Event):void
{
if(event is SQLErrorEvent)
{
var ERROR:String = event['error']['message']+" "+event['error']['details'];
Alert.show(ERROR,"SQLITE ERROR");
}
}
public function UPDATE(ELEMENT:Object = null):void
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
var UPDATE_ELEMENT:Object = c_OBJECT_inst.copy(selectedDatagrid.dataGrid.selectedItem);
delete UPDATE_ELEMENT["mx_internal_uid"];
if(UPDATE_ELEMENT.hasOwnProperty("hide"))
{
delete UPDATE_ELEMENT["hide"];
}
UPDATE_ELEMENT["STATUS"] = STATUS.textInput.text;
for(var counter:int = 0;!(counter == taskGrids.getChildren().length);counter++)
{
if(taskGrids.getChildAt(counter) == selectedDatagrid)
{
selectedInput = inputs.getChildAt(counter) as TextInput;
if(selectedDatagrid.parent == taskGrids)
{
CURRENT_TABLE_NAME = "TASKS";
UPDATE_ELEMENT["TASK"] = selectedInput.text;
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,UPDATE_ELEMENT,UPDATE_ELEMENT.id,readTable2)
}
else if(selectedDatagrid.parent == timeGrid)
{
CURRENT_TABLE_NAME = "TIMES";
UPDATE_ELEMENT["TIME"] = selectedInput.text;
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,UPDATE_ELEMENT,UPDATE_ELEMENT.id,readTable2)
}
break;
}
}
}
else
{
Alert.show("Can not update element","No element selected");
}
}
public function UPDATE_ELEMENT(ELEMENT:Object = null,TABLE:String = "TASKS"):void
{
delete ELEMENT["mx_internal_uid"];
if(ELEMENT.hasOwnProperty("hide"))
{
delete ELEMENT["hide"];
}
CURRENT_TABLE_NAME = TABLE;
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,ELEMENT,ELEMENT.id,readTable2,readTable2)
}
/**
TIMES = Array (@1a135039)
COMMENT = null -> user can comment on this record
id = 1
STATUS = "" -> billed, completed... custom status possible
TASKID = "4" -> with what task is this time record associated
TIME = "2011:07:12 17:59:12"
TIME_DIFF = "3648" -> difference in MSeconds between start and stop
TIME_ESTIMATED = "1310486352194" -> seconds since estimated - start
TIME_LEFT = ""
TIME_START = "1310486352194" -> when the task was started (milliseconds since 1970)
TIME_STOP = "1310486355842" -> when the task was stoped (milliseconds since 1970)
TASKS = Array (@1af5c809)
COMMENT = null -> user can comment on this record
PARENTTASKID = "" -> if this task is a child of another parent-task, save parentID here
SPEND = null -> time in seconds that was spend on this task and all subtasks
STATUS = "" -> billed, completed... custom status possible
TASK = "task1" -> the name of the task
TIMECREATED = "1310471342508" -> when the task was created (milliseconds since 1970)
**/
public function insertRecord(TABLENAME:String,ELEMENT:Object,onComplete:Function):void
{
CURRENT_TABLE_NAME = TABLENAME;
if(ELEMENT.hasOwnProperty("hide"))
{
delete ELEMENT["hide"];
}
if(ELEMENT.hasOwnProperty("mx_internal_uid"))
{
delete ELEMENT["mx_internal_uid"];
}
air_sqllite_interaction_inst.INSERT(null,CURRENT_TABLE_NAME,ELEMENT,onComplete,HandleFault);
}
public var currentTime:Object = new Object();
/**
* ok -6. how much time spend on each task (tooltip? or in TIME_SPEND TextInput)
ok -6.1 summarize all time spend on all subtasks
-5. instead of sqlite use simple ; separated ascii-text files maybe in this way:
tasks (root dir)
\->year 2011
\-> month 07
\-> task-id: 1.txt
ok -6.2 continue counting @ the last time spend time
*
* adds time record to task
* currentTime = {TASKID:selectedDatagrid.dataGrid.selectedItem["id"],
TIME_ESTIMATED:DATE_ESTIMATED.getTime(),
TIME_START:DATE_START.getTime(),
TIME_STOP:DATE_STOP.getTime(),
TIME_DIFF:DATE_DIFF_STRING,
TIME_LEFT:""};
**/
public function AddTime(event:Event = null,time:Object = null):void
{
if(event == null)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
var DATE:Date = new Date();
var DATE_STRING:String = DATE.getTime().toString();
CURRENT_TABLE_NAME = "TIMES";
if(itemChanged_while_Timer_running_useLastSelectedItem)
{
time["TASKID"] = lastSelectedItem["id"];
}
else
{
time["TASKID"] = selectedDatagrid.dataGrid.selectedItem["id"];
}
currentTime = time;
insertRecord(CURRENT_TABLE_NAME,currentTime,AddTime);
if(isNaN(selectedDatagrid.dataGrid.selectedItem["SPEND"]))
{
selectedDatagrid.dataGrid.selectedItem["SPEND"] = 0;
}
}
else
{
NoTask("can not add time");
}
}
else
{
var ITEMS_TO_UPDATE:Array = new Array();
var currentlySelectedItem:Object = null;
if(itemChanged_while_Timer_running_useLastSelectedItem)
{
currentlySelectedItem = lastSelectedItem;
}
else
{
currentlySelectedItem = selectedDatagrid.dataGrid.selectedItem;
}
var SPEND_UNTIL_NOW:Number = parseFloat(currentlySelectedItem["SPEND"]);
TIME_SPEND_CURRENT_SESSION_AND_ALL_SUBTASKS_IN_SECONDS = TIME_SPEND_CURRENT_SESSION_IN_SECONDS;
TIME_SPEND.text = c_DATE_inst.SecondsToYearMonthDayHoursMinutesSeconds( TIME_SPEND_CURRENT_SESSION_AND_ALL_SUBTASKS_IN_SECONDS );
currentlySelectedItem["SPEND"] = TIME_SPEND_CURRENT_SESSION_AND_ALL_SUBTASKS_IN_SECONDS;
ITEMS_TO_UPDATE.push(currentlySelectedItem);
var currentChildTask:Object = currentlySelectedItem;
var PARENTTASK:Object = FindParentTask(TABLES["TASKS"],currentChildTask["PARENTTASKID"]);
do
{
if(isNaN(PARENTTASK["SPEND"]))
{
PARENTTASK["SPEND"] = 0;
}
/** subtract previous value and add new value **/
if(parseFloat(PARENTTASK["SPEND"]) != 0)
{
PARENTTASK["SPEND"] = parseFloat(PARENTTASK["SPEND"]) - TIME_SPEND_BEFORE_CURRENT_SESSION;
}
PARENTTASK["SPEND"] = parseFloat(PARENTTASK["SPEND"]) + TIME_SPEND_CURRENT_SESSION_IN_SECONDS;
ITEMS_TO_UPDATE.push(PARENTTASK);
currentChildTask = PARENTTASK;
PARENTTASK = FindParentTask(TABLES["TASKS"],currentChildTask["PARENTTASKID"]);
}
while(c_OBJECT_inst.not_empty(PARENTTASK))
UPDATE_MULTIPLE_ITEMS(null,ITEMS_TO_UPDATE,"TASKS");
TIME_SPEND_CURRENT_SESSION_IN_SECONDS = 0;
}
}
public function NoTask(error:String):void
{
Alert.show("no task was selected",error);
}
public var itemChanged_while_Timer_running_useLastSelectedItem:Boolean = false;
public function datagrid_clickTime(event:MouseEvent):void
{
trace(timeGrid.dataGrid.selectedItem);
}
/**
* 7. automatically select parent-tasks when selecting a subtask... and deselect all other tasks right of this task.
* and display times of this task
*
* -1.1 show only sub-tasks that belong to the selected task. (otherwise people might get confused)
*
* **/
public function datagrid_click(event:MouseEvent):void
{
timeGrid.dataGrid.selectedItem = null;
if(event.currentTarget is DataGrid2)
{
selectedDatagrid = event.currentTarget as DataGrid2;
if(lastSelectedItem != selectedDatagrid.dataGrid.selectedItem)
{
if(TIMER != null)
{
if(TIMER.running)
{
itemChanged_while_Timer_running_useLastSelectedItem = true;
onExit();
}
}
else
{
lastSelectedItem = c_OBJECT_inst.copy(selectedDatagrid.dataGrid.selectedItem);
lastSelectedDataGrid = selectedDatagrid;
}
}
}
if(selectedDatagrid != null)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
for(var counter:int = 0;!(counter == taskGrids.getChildren().length);counter++)
{
if(taskGrids.getChildAt(counter) == selectedDatagrid)
{
selectedInput = inputs.getChildAt(counter) as TextInput;
if(selectedDatagrid.dataGrid.selectedItem.hasOwnProperty("TASK"))
{
selectedInput.text = selectedDatagrid.dataGrid.selectedItem["TASK"];
}
else if(selectedDatagrid.dataGrid.selectedItem.hasOwnProperty("TIME"))
{
selectedInput.text = selectedDatagrid.dataGrid.selectedItem["TIME"];
}
selectParentTask(selectedDatagrid);
deselectDataGridsRightOf(selectedDatagrid);
displayTaskProperties();
hideNotRelatedTasks();
break;
}
}
}
}
if(DO_LOAD_STUFF == false)
{
if(TABLES["TIMES"] != null)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
var DATAPROVIDER:Array = new Array();
for each(var time:Object in TABLES["TIMES"])
{
if(time["TASKID"] == selectedDatagrid.dataGrid.selectedItem["id"])
{
DATAPROVIDER.push(time);
}
}
timeGrid.dataGrid.dataProvider = DATAPROVIDER;
}
}
}
}
/** -1. preferences:
-1.1 show only sub-tasks that belong to the selected task. (otherwise people might get confused)
* exactly the other way around than "select parent task" the task columns need to be processed top-down
* from left to right.
* showing only the tasks that belong to the selected parent-task.
*
* but always show all root (level0) tasks.
* **/
public function hideNotRelatedTasks():void
{
var pos:int = positionOfIn(selectedDatagrid,taskGrids);
var ChildDG:DataGrid2 = null;
try
{
ChildDG = taskGrids.getChildAt(pos+1) as DataGrid2;
}
catch(e:Error)
{
ChildDG = null;
}
if(ChildDG != null)
{
if((ChildDG.dataProvider != null) && (selectedDatagrid.dataGrid.selectedItem != null))
{
if(ChildDG.dataProvider != null)
{
if(ChildDG.dataProvider["length"] != 0)
{
ChildDG.dataProvider = ChildDG.dataProvider;
for each(var TASK:Object in ChildDG.dataProvider)
{
if(TASK["PARENTTASKID"] == selectedDatagrid.dataGrid.selectedItem["id"])
{
TASK["hide"] = false;
}
else
{
TASK["hide"] = true;
}
}
ChildDG.filteredDataProvider = ChildDG.dataProvider;
}
}
}
}
while((pos+2) < taskGrids.getChildren().length)
{
ChildDG = taskGrids.getChildAt(pos+2) as DataGrid2;
for each(var TASK:Object in ChildDG.dataProvider)
{
TASK["hide"] = true;
}
ChildDG.filteredDataProvider = ChildDG.dataProvider;
pos++;
}
}
public var AddingComment:Boolean = false;
/** adds/updates a comment of a task/time
depending on what is selected a comment belonging to a task
* or a comment belonging to a time must be updated
*
* -7. Adding a comment resets time counter!?
* **/
public function AddUpdateComment(event:Event = null,COMMENT_STRING:String = ""):void
{
if(event == null)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
var UPDATE_ELEMENT:Object = null;
if(timeGrid.dataGrid.selectedItem != null)
{
CURRENT_TABLE_NAME = "TIMES";
UPDATE_ELEMENT = c_OBJECT_inst.copy(timeGrid.dataGrid.selectedItem);
}
else
{
UPDATE_ELEMENT = c_OBJECT_inst.copy(selectedDatagrid.dataGrid.selectedItem);
CURRENT_TABLE_NAME = "TASKS";
}
if(c_OBJECT_inst.not_empty(UPDATE_ELEMENT))
{
delete UPDATE_ELEMENT["mx_internal_uid"];
if(UPDATE_ELEMENT.hasOwnProperty("hide"))
{
delete UPDATE_ELEMENT["hide"];
}
AddingComment = true;
UPDATE_ELEMENT["COMMENT"] = COMMENT.text;
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,UPDATE_ELEMENT,UPDATE_ELEMENT.id,AddUpdateComment)
}
}
else
{
Alert.show("sorry master, i do not know with what task i should associate this comment.","Please select a task");
}
}
else if(event.type == SQLEvent.RESULT)
{
DisplayStatus(null,"Comment added/updated.",LABEL_STATUS);
readTable2();
}
}
/** display comment of a task, if it exists -> selectedDatagrid.dataGrid.selectedItem **/
public function displayTaskProperties():void
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
COMMENT.text = "";
if(c_OBJECT_inst.empty(selectedDatagrid.dataGrid.selectedItem["COMMENT"]))
{
selectedDatagrid.dataGrid.selectedItem["COMMENT"] = ""; }
else
{
COMMENT.text = selectedDatagrid.dataGrid.selectedItem["COMMENT"]
}
STATUS.selectedItem = "";
if(c_OBJECT_inst.empty(selectedDatagrid.dataGrid.selectedItem["STATUS"]))
{
selectedDatagrid.dataGrid.selectedItem["STATUS"] = ""; }
else
{
STATUS.selectedItem = selectedDatagrid.dataGrid.selectedItem["STATUS"]
}
if(c_OBJECT_inst.empty(selectedDatagrid.dataGrid.selectedItem["SPEND"]))
{
selectedDatagrid.dataGrid.selectedItem["SPEND"] = 0; TIME_SPEND.text = "0 seconds";
TIME_SPEND_CURRENT_SESSION_IN_SECONDS = 0;
}
else
{
TIME_SPEND.text = c_DATE_inst.SecondsToYearMonthDayHoursMinutesSeconds( parseFloat(selectedDatagrid.dataGrid.selectedItem["SPEND"]) );
}
}
else
{
Alert.show("sorry my master may i ask you humbly... ","... to select a task or time to display it's comment.");
}
}
var TIMER:Timer = null;
var DATE_CURRENT:Date = null;
var DATE_START:Date = null;
var DATE_STOP:Date = null;
var DATE_SPEND:Date = null;
/** the time that is spend on the current session/task/time between start and stop **/
var TIME_SPEND_CURRENT_SESSION_IN_SECONDS:Number = 0;
/** the time that is spend on the current session/task/time between start and stop and all subtasks **/
var TIME_SPEND_CURRENT_SESSION_AND_ALL_SUBTASKS_IN_SECONDS:Number = 0;
/** the value that was spend on the time before the current session **/
var TIME_SPEND_BEFORE_CURRENT_SESSION:Number = 0;
var DATE_ESTIMATED:Date = null;
var DATE_LEFT:Date = null;
/** start time taking/logging **/
public function StartTimer(event:TimerEvent = null):void
{
if(event == null)
{
if(TIMER != null)
{
if(TIMER.running)
{
StopTimer();
}
}
DATE_START = new Date();
TIMER = new Timer(1000,Infinity);
TIMER.addEventListener(TimerEvent.TIMER, StartTimer);
TIMER.addEventListener(TimerEvent.TIMER_COMPLETE, StartTimer);
TIME_START.text = c_DATE_inst.date_to_string(DATE_START,"YYYY:MM:DD",true);
TIMER.start();
if(isNaN(selectedDatagrid.dataGrid.selectedItem["SPEND"]))
{
selectedDatagrid.dataGrid.selectedItem["SPEND"] = 0;
}
TIME_SPEND_CURRENT_SESSION_IN_SECONDS = parseFloat(selectedDatagrid.dataGrid.selectedItem["SPEND"]);
TIME_SPEND_BEFORE_CURRENT_SESSION = parseFloat(selectedDatagrid.dataGrid.selectedItem["SPEND"]);
}
else if(event.type == TimerEvent.TIMER)
{
TIME_SPEND.text = c_DATE_inst.SecondsToYearMonthDayHoursMinutesSeconds( TIME_SPEND_CURRENT_SESSION_IN_SECONDS );
CalcEstimate();
TIME_SPEND_CURRENT_SESSION_IN_SECONDS++;
}
else if(event.type == TimerEvent.TIMER_COMPLETE)
{
}
}
/** display current time **/
public function ShowTime(event:TimerEvent = null):void
{
if(event == null)
{
var SHOW_TIMER:Timer = new Timer(1000,Infinity);
SHOW_TIMER.addEventListener(TimerEvent.TIMER, ShowTime);
SHOW_TIMER.addEventListener(TimerEvent.TIMER_COMPLETE, ShowTime);
SHOW_TIMER.start();
}
else if(event.type == TimerEvent.TIMER)
{
DATE_CURRENT = new Date();
TIME_CURRENT.text = c_DATE_inst.date_to_string(DATE_CURRENT,"YYYY.MM.DD",true);
}
else if(event.type == TimerEvent.TIMER_COMPLETE)
{
}
}
/** stop time taking/logging/add a time record **/
public function StopTimer(selectedItem:Object = null):void
{
if(TIMER.running)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
DATE_STOP = new Date();
currentTime["TIME_STOP"] = DATE_STOP.getTime();
TIME_STOP.text = c_DATE_inst.date_to_string(DATE_STOP,"YYYY:MM:DD",true);
TIMER.stop();
var DATE_DIFF_STRING:String = (DATE_STOP.getTime() - DATE_START.getTime()).toString();
var time:Object = {
TIME_ESTIMATED:DATE_ESTIMATED.getTime(),
TIME_START:DATE_START.getTime(),
TIME:TIME_START.text,
TIME_STOP:DATE_STOP.getTime(),
TIME_DIFF:DATE_DIFF_STRING,
TIME_LEFT:""};
AddTime(null,time);
}
else
{
NoTask("can not add time");
}
}
}
/** **/
public function AddTask(event:Event = null):void
{
if(event == null)
{
var DATE:Date = new Date();
var DATE_STRING:String = DATE.getTime().toString();
var PARENTTASKID:String = "";
var STATUS:String = "";
var proceed:Boolean = true;
var pos:int = positionOfIn(selectedInput,inputs);
if(pos > 0)
{
if(c_OBJECT_inst.not_empty(selectedDatagrid.dataGrid.selectedItem))
{
proceed = true;
}
else
{
Alert.show("This sub task needs to be associated with a parent task, please select one.","No Parent-Task-Selected");
proceed = false;
}
}
if(proceed)
{
selectedDatagrid = null;
try
{
selectedDatagrid = taskGrids.getChildAt(pos) as DataGrid2;
}
catch(e:Error)
{
AddDataGrid(null,"TASK");
selectedDatagrid = taskGrids.getChildAt(pos) as DataGrid2;
}
if(pos > 0)
{
PARENTTASKID = getParentTaskID(selectedDatagrid);
if(c_OBJECT_inst.empty(PARENTTASKID))
{
Alert.show("This sub task needs to be associated with a parent task, please select one.","No Parent-Task-Selected");
proceed = false;
}
}
for each(var TASK:Object in selectedDatagrid.dataGrid.dataProvider)
{
lastSelectedDataGrid
if(TASK["TASK"] == selectedInput["text"])
{
Alert.show("A task with this name allready exists.","My master, i am sorry, but it would be wise to enter a different task name.");
proceed = false;
}
}
if(c_OBJECT_inst.empty(selectedInput["text"]))
{
Alert.show("Please enter a Task","No Task was entered.");
proceed = false;
}
if(proceed)
{
var ELEMENT:Object = {TASK:selectedInput["text"],PARENTTASKID:PARENTTASKID ,STATUS:STATUS,TIMECREATED:DATE_STRING,SPEND:0};
insertRecord("TASKS",ELEMENT,AddTask);
}
}
}
else if(event.type == SQLEvent.RESULT)
{
readTable(null,"TASKS");
}
}
/** tries to figure out, what is the id of the parent of the selected TASK **/
public function getParentTaskID(DATAGRID2:DataGrid2):String
{
var RESULT:String = "";
var pos:int = positionOfIn(DATAGRID2,taskGrids);
if(pos > 0)
{
parentDatagrid = DATAGRID2 = taskGrids.getChildAt(pos-1) as DataGrid2;
if(parentDatagrid.dataGrid.selectedItem != null)
{
RESULT = parentDatagrid.dataGrid.selectedItem["id"];
}
}
return RESULT;
}
/** checks what childs belong to the given task,
* what tasks have PARENTTASKID of current task and return them **/
public function findChildTasks(TASK:Object):Array
{
var CHILD_TASKS:Array = new Array();
var TASKS:Array = TABLES["TASKS"];
for(var counter:int = 0;!(counter == TASKS.length);counter++)
{
if(TASK["id"] == TASKS[counter]["PARENTTASKID"])
{
CHILD_TASKS.push(TASKS[counter]);
}
}
return CHILD_TASKS;
}
/** select parent task, return parent task **/
public function selectParentTask(selectedDatagrid:DataGrid2):Object
{
var RESULT:Object = null;
var pos:int = positionOfIn(selectedDatagrid,taskGrids);
if(pos > 0)
{
parentDatagrid = taskGrids.getChildAt(pos-1) as DataGrid2;
for each(var TASK:Object in parentDatagrid.dataGrid.dataProvider)
{
if(TASK["id"] == selectedDatagrid.dataGrid.selectedItem["PARENTTASKID"])
{
parentDatagrid.dataGrid.selectedItem = TASK;
RESULT = TASK;
break;
}
}
selectParentTask(parentDatagrid);
}
return RESULT;
}
/** deselect all selected items right of the current selected DataGrid **/
public function deselectDataGridsRightOf(selectedDatagrid:DataGrid2):void
{
var pos:int = positionOfIn(selectedDatagrid,taskGrids);
pos++;
while(pos < taskGrids.getChildren().length)
{
var DATAGRID2:DataGrid2 = taskGrids.getChildAt(pos) as DataGrid2;
DATAGRID2.dataGrid.selectedItem = null;
pos++;
}
}
/** returns the position-index of a DisplayObject in a container, returns
* -1 if the child was not found in the container **/
public function positionOfIn(selectedInput:Object,CONTAINER:Container):int
{
var counter:int = -1;
var CHILDREN:int = CONTAINER.getChildren().length;
for(counter = 0;!(counter == CHILDREN);counter++)
{
var ELEMENT:Object = CONTAINER.getChildAt(counter);
if(ELEMENT == selectedInput)
{
return counter;
}
}
return counter;
}
/** deletes a task or time **/
public function DELETE():void
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
if(selectedDatagrid.parent == taskGrids)
{
CURRENT_TABLE_NAME = "TASKS";
air_sqllite_interaction_inst.DELETE(null,CURRENT_TABLE_NAME,selectedDatagrid.dataGrid.selectedItem.id,readTable2,HandleFault);
}
if(selectedDatagrid.parent == timeGrid)
{
CURRENT_TABLE_NAME = "TIMES";
air_sqllite_interaction_inst.DELETE(null,CURRENT_TABLE_NAME,selectedDatagrid.dataGrid.selectedItem.id,readTable2,HandleFault);
}
}
else
{
Alert.show("Sorry dude, can not delete element","No element selected");
}
}
public var TABLECOUNT:int = 0;
/**
* currently the program only needs 2x tables: TASKS and TIMES
* currently it has this layout: ( i hope i do not forget to update this comment )
*
* TASKS = Array (@1af5c809)
COMMENT = null -> user can comment on this record
PARENTTASKID = "" -> if this task is a child of another parent-task, save parentID here
SPEND = null -> time in seconds that was spend on this task and all subtasks
STATUS = "" -> billed, completed... custom status possible
TASK = "task1" -> the name of the task
TIMECREATED = "1310471342508" -> when the task was created (milliseconds since 1970)
TIMES = Array (@1a135039)
COMMENT = null -> user can comment on this record
id = 1
STATUS = "" -> billed, completed... custom status possible
TASKID = "4" -> with what task is this time record associated
TIME = "2011:07:12 17:59:12"
TIME_DIFF = "3648" -> difference in MSeconds between start and stop
TIME_ESTIMATED = "1310486352194" -> seconds since estimated - start
TIME_LEFT = ""
TIME_START = "1310486352194" -> when the task was started (milliseconds since 1970)
TIME_STOP = "1310486355842" -> when the task was stoped (milliseconds since 1970)
* **/
public function CreateDatabaseLayout(event:Event = null):void
{
if(TABLECOUNT == 0)
{
DataBaseLayout = {TableName:'TASKS',TASK:'TEXT',PARENTTASKID:'TEXT',STATUS:'TEXT',TIMECREATED:'TEXT',COMMENT:'TEXT',STATUS:'TEXT'};
air_sqllite_interaction_inst.CreateTable(null,DataBaseLayout,CreateDatabaseLayout,CreateDatabaseLayout);
}
else if(TABLECOUNT == 1)
{
DataBaseLayout = {TableName:'TIMES',TASKID:'TEXT',TIME_ESTIMATED:'TEXT',TIME_START:'TEXT',TIME:'TEXT',TIME_STOP:'TEXT',TIME_DIFF:'TEXT',TIME_LEFT:'TEXT',COMMENT:'TEXT',STATUS:'TEXT'};
air_sqllite_interaction_inst.CreateTable(null,DataBaseLayout,CreateDatabaseLayout,CreateDatabaseLayout);
}
else if(TABLECOUNT == 2)
{
var LIST_OF_NEW_COLUMNS_SINCE_LAST_UPDATE:Array = ["STATUS","SPEND"];
for each(var COLUMN:String in LIST_OF_NEW_COLUMNS_SINCE_LAST_UPDATE)
{
air_sqllite_interaction_inst.AddColumn(null,"TASKS",COLUMN,"TEXT");
}
LIST_OF_NEW_COLUMNS_SINCE_LAST_UPDATE = ["STATUS"];
for each(var COLUMN:String in LIST_OF_NEW_COLUMNS_SINCE_LAST_UPDATE)
{
air_sqllite_interaction_inst.AddColumn(null,"TIMES",COLUMN,"TEXT");
}
LOAD_STUFF();
}
else if(TABLECOUNT == 3)
{
}
else if(TABLECOUNT == 4)
{
}
TABLECOUNT++;
}
public function FOCUS_IN_input(event:FocusEvent):void
{
selectedInput = event.target["parent"];
}
public function KEYDOWN_input(event:KeyboardEvent):void
{
if(event.keyCode == 13)
{
AddTask();
}
}
public function KEYDOWN_comment(event:KeyboardEvent):void
{
if(event.ctrlKey && (event.keyCode == 13))
{
AddUpdateComment(null,COMMENT.text);
}
}
public function KEYDOWN_status(event:KeyboardEvent):void
{
if(event.keyCode == 13)
{
AddStatus();
}
}
public function AddDataGrid(event:Event = null,HeaderText:String = "TASK"):DataGrid2
{
/** build tasks iterate through array tasks and **/
var DATAGRID2:DataGrid2 = new DataGrid2();
DATAGRID2.dataGrid.dataProvider = new Array();
var proceed:Boolean = true;
var LAST_DataGrid:DataGrid2 = null;
try
{
LAST_DataGrid = taskGrids.getChildAt(taskGrids.getChildren().length-1) as DataGrid2;
if(c_OBJECT_inst.empty(LAST_DataGrid.dataGrid.dataProvider["source"]))
{
if(DO_LOAD_STUFF == false)
{
Alert.show("By adding more than one empty column at a time.","Sorry master. please don't confuse me.");
proceed = false;
}
}
}
catch(e:Error)
{
}
if(proceed)
{
DATAGRID2.addEventListener(MouseEvent.CLICK, datagrid_click);
if(c_OBJECT_inst.not_empty(HeaderText))
{
var COLUMN:DataGridColumn = DATAGRID2.dataGrid.columns[0] as DataGridColumn;
COLUMN.headerText = HeaderText;
COLUMN.dataField = HeaderText;
}
if(HeaderText == "TASK")
{
taskGrids.addChild(DATAGRID2);
var INPUT:TextInput = new TextInput();
INPUT.width = 100;
INPUT.addEventListener(FocusEvent.FOCUS_IN, FOCUS_IN_input);
INPUT.addEventListener(KeyboardEvent.KEY_DOWN, KEYDOWN_input);
INPUT.toolTip = "Hit Enter to add a task.";
inputs.addChild(INPUT);
}
}
return DATAGRID2;
}
/** build tasks iterate through array tasks and **/
public function AddTimeGrid():void
{
var COLUMN:DataGridColumn = timeGrid.dataGrid.columns[0] as DataGridColumn;
COLUMN.headerText = "TIMES";
COLUMN.dataField = "TIME";
COLUMN.setStyle("fontSize",10);
COLUMN.width = 150;
}
/** sync datagrid and input textfields scroll **/
public function SyncScroll(event:ScrollEvent):void
{
inputs.horizontalScrollPosition = event.position;
taskGrids.horizontalScrollPosition = event.position;
}
public function CalcEstimate():void
{
DATE_ESTIMATED = new Date();
}
/** displays a status in a given displayobject with property ["text"] for a given amount of senconds
* the idea is that it fades in
* and out in 3 seconds
* **/
var DISPLAYTIMER:Timer = null;
public function DisplayStatus(event:Event = null,STATUS:String = "",DISPLAYOBJECT:DisplayObject = null,SECONDS:int = 1):void
{
if(event == null)
{
if(DISPLAYOBJECT.hasOwnProperty("text"))
{
if(DISPLAYTIMER != null)
{
DISPLAYTIMER.stop();
}
DISPLAYOBJECT.visible = false;
DISPLAYOBJECT["text"] = STATUS;
var EFX_FADE_IN:Fade = new Fade(DISPLAYOBJECT);
EFX_FADE_IN.alphaFrom = 0;
EFX_FADE_IN.alphaTo = 1;
EFX_FADE_IN.duration = SECONDS*1000/2;
var EFX_FADE_OUT:Fade = new Fade(DISPLAYOBJECT);
EFX_FADE_OUT.alphaFrom = 1;
EFX_FADE_OUT.alphaTo = 0;
EFX_FADE_OUT.duration = SECONDS*1000/2;
var SEQUENCE:Sequence = new Sequence();
SEQUENCE.addChild(EFX_FADE_IN);
SEQUENCE.addChild(EFX_FADE_OUT);
SEQUENCE.end();
SEQUENCE.play();
SEQUENCE.addEventListener(EffectEvent.EFFECT_END, DisplayStatus);
}
}
else if(event.type == EffectEvent.EFFECT_END)
{
trace(event);
}
}
/** marks a task as e.g. "complete"
* ok -4. button: add status
user can define his own status
or select from predefined values: as
"completed" -> sets status of a task to complete -> background of task will be darkened. a checkbox in preferences allows hiding/showing of completed tasks and also setting the background color individually?
"billed" -> task was put on a bill and send to the customer
ok when a status is put to a top-level task, it automatically needs to be put to all sub-level tasks and times.
* **/
public function AddStatus():void
{
var DATAPROVIDER:Array = STATUS.dataProvider.toArray();
if(!c_ARRAY_inst.IN_ARRAY(DATAPROVIDER,STATUS.textInput.text,'boolean'))
{
DATAPROVIDER.push(STATUS.textInput.text);
STATUS.selectedIndex = STATUS.dataProvider.length-1;
STATUS.selectedItem = DATAPROVIDER[DATAPROVIDER.length-1];
STATUS.validateProperties();
}
if(selectedDatagrid.dataGrid.selectedItem != null)
{
ITEMS_TO_UPDATE = new Array();
selectedDatagrid.dataGrid.selectedItem["STATUS"] = STATUS.textInput.text;
ITEMS_TO_UPDATE = findChildTasks(selectedDatagrid.dataGrid.selectedItem);
ITEMS_TO_UPDATE.push(selectedDatagrid.dataGrid.selectedItem);
for each(var TASK:Object in ITEMS_TO_UPDATE)
{
CURRENT_TABLE_NAME = "TASKS";
TASK["STATUS"] = STATUS.textInput.text;
}
UPDATE_MULTIPLE_ITEMS(null,ITEMS_TO_UPDATE,"TASKS");
}
}
var ITEMS_TO_UPDATE:Array = new Array();
/** updates multipe items tasks or times **/
public function UPDATE_MULTIPLE_ITEMS(event:Event = null,ITEMS:Array = null,TABLE:String = "",whenFinished:Function = null):void
{
if(event == null)
{
if(c_OBJECT_inst.not_empty(ITEMS) && c_OBJECT_inst.not_empty(TABLE))
{
ITEMS_TO_UPDATE = ITEMS;
CURRENT_TABLE_NAME = TABLE;
var LAST_ITEM:Object = ITEMS_TO_UPDATE.pop();
delete LAST_ITEM["mx_internal_uid"];
if(LAST_ITEM.hasOwnProperty("hide"))
{
delete LAST_ITEM["hide"];
}
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,LAST_ITEM,LAST_ITEM["id"],UPDATE_MULTIPLE_ITEMS,UPDATE_MULTIPLE_ITEMS);
}
}
else
{
if(ITEMS_TO_UPDATE.length > 1)
{
var LAST_ITEM:Object = ITEMS_TO_UPDATE.pop();
delete LAST_ITEM["mx_internal_uid"];
if(LAST_ITEM.hasOwnProperty("hide"))
{
delete LAST_ITEM["hide"];
}
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,LAST_ITEM,LAST_ITEM["id"],UPDATE_MULTIPLE_ITEMS,UPDATE_MULTIPLE_ITEMS);
}
else
{
var LAST_ITEM:Object = ITEMS_TO_UPDATE.pop();
delete LAST_ITEM["mx_internal_uid"];
if(LAST_ITEM.hasOwnProperty("hide"))
{
delete LAST_ITEM["hide"];
}
air_sqllite_interaction_inst.UPDATE(null,CURRENT_TABLE_NAME,LAST_ITEM,LAST_ITEM["id"],readTableTasksAndTimes,readTableTasksAndTimes);
}
}
}
/** when application exits, always save the last started time-tracking record **/
public function onExit(event:Event = null):void
{
if(selectedDatagrid != null)
{
if(selectedDatagrid.dataGrid.selectedItem != null)
{
if(selectedDatagrid.dataGrid.selectedItem["STATUS"] != STATUS.textInput.text)
{
AddStatus();
}
}
if(TIMER != null)
{
if(TIMER.running)
{
StopTimer();
}
}
}
}
]]>
</fx:Script>
</s:WindowedApplication>