Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
emT3web
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mac Stephens
emT3web
Commits
d87ba778
Commit
d87ba778
authored
Nov 04, 2026
by
Daniel Barker
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add web task picker with Focused Task option
parent
44a9fed1
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
353 additions
and
104 deletions
+353
-104
.gitignore
.gitignore
+1
-0
View.TimeEntries.html
emT3Web/View.TimeEntries.html
+10
-1
View.TimeEntries.pas
emT3Web/View.TimeEntries.pas
+67
-4
uTaskPickerOffCanvas.pas
emT3Web/uTaskPickerOffCanvas.pas
+138
-23
Api.Database.dfm
emT3XDataServer/Source/Api.Database.dfm
+43
-47
Api.Database.pas
emT3XDataServer/Source/Api.Database.pas
+4
-3
TaskItem.ServiceImpl.pas
emT3XDataServer/Source/TaskItem.ServiceImpl.pas
+1
-0
TimeEntry.Service.pas
emT3XDataServer/Source/TimeEntry.Service.pas
+5
-3
TimeEntry.ServiceImpl.pas
emT3XDataServer/Source/TimeEntry.ServiceImpl.pas
+78
-17
emT3XDataServer.ini
emT3XDataServer/bin/emT3XDataServer.ini
+4
-4
emT3XDataServer.dproj
emT3XDataServer/emT3XDataServer.dproj
+2
-2
No files found.
.gitignore
View file @
d87ba778
...
...
@@ -13,6 +13,7 @@ emT3XDataServer/bin/static/
emT3XDataServer/Source/__history/
emT3XDataServer/Source/__recovery/
emT3XDataServer/Win32/
.validation/
*.exe
*.local
...
...
emT3Web/View.TimeEntries.html
View file @
d87ba778
...
...
@@ -3,6 +3,7 @@
<h5
class=
"mb-0 text-nowrap"
id=
"lbl_time_entries_title"
></h5>
<div
class=
"d-flex align-items-center gap-2 ms-auto flex-nowrap"
>
<div
id=
"lbl_time_total_hours"
class=
"me-2 text-nowrap fw-semibold"
>
Total Hours: 0
</div>
<div
id=
"lbl_time_total_rows"
class=
"me-2 text-nowrap"
></div>
<div
class=
"d-flex align-items-center gap-2 flex-nowrap"
>
...
...
@@ -72,10 +73,18 @@
<div
id=
"task_picker_status"
class=
"alert alert-danger py-1 px-2 mb-3 d-none small"
></div>
<div
class=
"d-flex justify-content-end gap-2"
>
<div
class=
"d-flex align-items-center gap-2"
>
<div
class=
"d-flex align-items-center gap-2 me-auto"
>
<input
class=
"form-check-input m-0"
type=
"checkbox"
id=
"task_picker_add_focus"
/>
<label
class=
"form-check-label mb-0"
for=
"task_picker_add_focus"
>
Focused Task
</label>
</div>
<button
type=
"button"
class=
"btn btn-outline-secondary btn-sm"
data-bs-dismiss=
"offcanvas"
>
Cancel
</button>
<button
type=
"button"
class=
"btn btn-primary btn-sm"
id=
"btn_task_picker_save"
disabled
>
Save
</button>
...
...
emT3Web/View.TimeEntries.pas
View file @
d87ba778
...
...
@@ -76,6 +76,7 @@ type
function
DateToIso
(
const
AValue
:
TDateTime
):
string
;
procedure
SetWeekRangeFromAnchor
(
const
ADateValue
:
string
;
ALoadAfterSet
:
Boolean
);
procedure
SetTotalRowsLabel
(
ARowCount
:
Integer
);
procedure
UpdateTotalHours
;
procedure
SetTimeEntriesLabel
(
const
AName
:
string
);
procedure
CaptureTableScroll
;
procedure
RestoreTableScroll
;
...
...
@@ -93,7 +94,7 @@ type
function
GetTargetRowIndex
(
ATarget
:
TJSHTMLElement
):
Integer
;
procedure
DocumentMouseDown
(
Event
:
TJSEvent
);
[
async
]
procedure
TaskPickerButtonClick
(
Event
:
TJSEvent
);
procedure
TaskPickerTaskSelected
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
);
procedure
TaskPickerTaskSelected
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
;
AAddedToFocus
:
Boolean
);
procedure
ApplyActiveRowState
;
procedure
EditorBlur
(
Event
:
TJSEvent
);
[
async
]
procedure
SaveField
(
AIndex
:
Integer
;
const
AFieldName
:
string
);
...
...
@@ -215,7 +216,7 @@ var
weekEnd
:
TDateTime
;
begin
anchorDate
:=
IsoToDate
(
ADateValue
);
weekStart
:=
anchorDate
-
(
DayOfTheWeek
(
anchorDate
)
-
1
)
;
weekStart
:=
anchorDate
;
weekEnd
:=
weekStart
+
6
;
FUpdatingDates
:=
True
;
...
...
@@ -271,6 +272,37 @@ begin
el
.
innerText
:=
'Total Rows: '
+
IntToStr
(
ARowCount
);
end
;
procedure
TFTimeEntries
.
UpdateTotalHours
;
var
el
:
TJSHTMLElement
;
totalHours
:
Double
;
currentRecNo
:
Integer
;
begin
totalHours
:=
0
;
if
xdwdsTimeEntries
.
Active
then
begin
currentRecNo
:=
xdwdsTimeEntries
.
RecNo
;
xdwdsTimeEntries
.
First
;
while
not
xdwdsTimeEntries
.
Eof
do
begin
if
(
xdwdsTimeEntriesentryId
.
AsInteger
>
0
)
and
(
xdwdsTimeEntriestaskDate
.
AsString
>=
FStartDate
)
and
(
xdwdsTimeEntriestaskDate
.
AsString
<=
FEndDate
)
and
(
not
xdwdsTimeEntrieshours
.
IsNull
)
then
totalHours
:=
totalHours
+
xdwdsTimeEntrieshours
.
AsFloat
;
xdwdsTimeEntries
.
Next
;
end
;
if
currentRecNo
>
0
then
xdwdsTimeEntries
.
RecNo
:=
currentRecNo
;
end
;
el
:=
TJSHTMLElement
(
document
.
getElementById
(
'lbl_time_total_hours'
));
el
.
innerText
:=
'Total Hours: '
+
FormatFloat
(
'0.##'
,
totalHours
);
end
;
procedure
TFTimeEntries
.
SetTimeEntriesLabel
(
const
AName
:
string
);
var
el
:
TJSHTMLElement
;
...
...
@@ -333,6 +365,7 @@ begin
xdwdsTimeEntries
.
Close
;
xdwdsTimeEntries
.
SetJsonData
(
itemsArray
);
xdwdsTimeEntries
.
Open
;
UpdateTotalHours
;
FActiveRowIndex
:=
-
1
;
HideRowValidationMessage
;
...
...
@@ -1667,14 +1700,17 @@ begin
if
not
Assigned
(
FTaskPickerOffCanvas
)
then
FTaskPickerOffCanvas
:=
TTaskPickerOffCanvas
.
Create
(
xdwcTimeEntries
,
@
TaskPickerTaskSelected
);
await
(
FTaskPickerOffCanvas
.
Open
(
FUserId
,
idx
));
await
(
FTaskPickerOffCanvas
.
Open
(
FUserId
,
idx
,
FTaskOptions
));
end
;
procedure
TFTimeEntries
.
TaskPickerTaskSelected
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
);
procedure
TFTimeEntries
.
TaskPickerTaskSelected
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
;
AAddedToFocus
:
Boolean
);
var
btn
:
TJSHTMLElement
;
triggerId
:
string
;
i
:
Integer
;
taskOption
:
TJSObject
;
taskFound
:
Boolean
;
begin
if
not
xdwdsTimeEntries
.
Active
then
Exit
;
...
...
@@ -1692,6 +1728,30 @@ begin
btnDeleteEntry
.
Enabled
:=
not
IsNewEntryRow
(
ARowIndex
);
btnCopyEntry
.
Enabled
:=
not
IsNewEntryRow
(
ARowIndex
);
if
AAddedToFocus
then
begin
taskFound
:=
False
;
for
i
:=
0
to
FTaskOptions
.
length
-
1
do
begin
taskOption
:=
TJSObject
(
FTaskOptions
[
i
]);
if
string
(
taskOption
[
'taskId'
])
=
ATaskId
then
begin
taskFound
:=
True
;
Break
;
end
;
end
;
if
not
taskFound
then
begin
taskOption
:=
TJSObject
.
new
;
taskOption
[
'taskId'
]
:=
ATaskId
;
taskOption
[
'taskDisplay'
]
:=
ATaskDisplay
;
FTaskOptions
.
push
(
taskOption
);
end
;
end
;
CaptureTableScroll
;
RenderTable
;
...
...
@@ -1833,6 +1893,9 @@ begin
));
console
.
log
(
'SaveField: response='
+
string
(
TJSJSON
.
stringify
(
response
.
Result
)));
if
SameText
(
AFieldName
,
'hours'
)
or
SameText
(
AFieldName
,
'taskDate'
)
then
UpdateTotalHours
;
except
on
E
:
EXDataClientRequestException
do
begin
...
...
emT3Web/uTaskPickerOffCanvas.pas
View file @
d87ba778
...
...
@@ -6,7 +6,11 @@ uses
System
.
SysUtils
,
JS
,
Web
,
XData
.
Web
.
Client
;
type
TTaskPickedProc
=
reference
to
procedure
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
);
TTaskPickedProc
=
reference
to
procedure
(
ARowIndex
:
Integer
;
const
ATaskId
,
ATaskDisplay
:
string
;
AAddedToFocus
:
Boolean
);
TTaskPickerOffCanvas
=
class
private
...
...
@@ -17,10 +21,12 @@ type
FCustomers
:
TJSArray
;
FProjects
:
TJSArray
;
FTasks
:
TJSArray
;
FFocusedTasks
:
TJSArray
;
procedure
BindEvents
;
procedure
ClearSelect
(
const
AElementId
:
string
;
ADisabled
:
Boolean
);
procedure
FillSelect
(
const
AElementId
:
string
;
AItems
:
TJSArray
);
procedure
FilterProjects
(
const
ACustomerId
:
string
);
function
SelectedValue
(
const
AElementId
:
string
):
string
;
function
FindDisplay
(
AItems
:
TJSArray
;
const
AValue
:
string
):
string
;
procedure
SetStatus
(
const
AMessage
:
string
);
...
...
@@ -33,13 +39,14 @@ type
[
async
]
procedure
LoadProjects
(
const
ACustomerId
:
string
);
[
async
]
procedure
LoadTasks
(
const
AProjectId
:
string
);
[
async
]
procedure
CustomerChanged
(
Event
:
TJSEvent
);
procedure
CustomerChanged
(
Event
:
TJSEvent
);
[
async
]
procedure
ProjectChanged
(
Event
:
TJSEvent
);
procedure
TaskChanged
(
Event
:
TJSEvent
);
procedure
SaveClicked
(
Event
:
TJSEvent
);
procedure
UpdateFocusCheckbox
;
[
async
]
procedure
SaveClicked
(
Event
:
TJSEvent
);
public
constructor
Create
(
AClient
:
TXDataWebClient
;
AOnTaskPicked
:
TTaskPickedProc
);
[
async
]
procedure
Open
(
const
AUserId
:
string
;
ARowIndex
:
Integer
);
[
async
]
procedure
Open
(
const
AUserId
:
string
;
ARowIndex
:
Integer
;
AFocusedTasks
:
TJSArray
);
end
;
implementation
...
...
@@ -115,6 +122,28 @@ begin
selectEl
.
disabled
:=
False
;
end
;
procedure
TTaskPickerOffCanvas
.
FilterProjects
(
const
ACustomerId
:
string
);
var
filteredProjects
:
TJSArray
;
project
:
TJSObject
;
i
:
Integer
;
begin
//create an empty filtered project list
filteredProjects
:=
TJSArray
.
new
;
//loop through the full project list
for
i
:=
0
to
FProjects
.
length
-
1
do
begin
project
:=
TJSObject
(
FProjects
[
i
]);
if
(
ACustomerId
=
''
)
or
(
string
(
project
[
'customerId'
])
=
ACustomerId
)
then
begin
filteredProjects
.
push
(
project
);
end
;
end
;
FillSelect
(
'task_picker_project'
,
filteredProjects
)
end
;
function
TTaskPickerOffCanvas
.
SelectedValue
(
const
AElementId
:
string
):
string
;
var
selectEl
:
TJSHTMLSelectElement
;
...
...
@@ -202,8 +231,7 @@ var
resultObj
:
TJSObject
;
begin
response
:=
await
(
FClient
.
RawInvokeAsync
(
'ITimeEntryService.GetTaskPickerCustomers'
,
[
FUserId
]
'ITimeEntryService.GetTaskPickerCustomers'
,
[]
));
resultObj
:=
TJSObject
(
response
.
Result
);
...
...
@@ -218,12 +246,11 @@ var
begin
response
:=
await
(
FClient
.
RawInvokeAsync
(
'ITimeEntryService.GetTaskPickerProjects'
,
[
FUserId
,
ACustomerId
]
[
ACustomerId
]
));
resultObj
:=
TJSObject
(
response
.
Result
);
FProjects
:=
TJSArray
(
resultObj
[
'options'
]);
FillSelect
(
'task_picker_project'
,
FProjects
);
end
;
[
async
]
procedure
TTaskPickerOffCanvas
.
LoadTasks
(
const
AProjectId
:
string
);
...
...
@@ -233,7 +260,7 @@ var
begin
response
:=
await
(
FClient
.
RawInvokeAsync
(
'ITimeEntryService.GetTaskPickerTasks'
,
[
FUserId
,
AProjectId
]
[
AProjectId
]
));
resultObj
:=
TJSObject
(
response
.
Result
);
...
...
@@ -241,7 +268,7 @@ begin
FillSelect
(
'task_picker_task'
,
FTasks
);
end
;
[
async
]
procedure
TTaskPickerOffCanvas
.
CustomerChanged
(
Event
:
TJSEvent
);
procedure
TTaskPickerOffCanvas
.
CustomerChanged
(
Event
:
TJSEvent
);
var
customerId
:
string
;
begin
...
...
@@ -249,31 +276,48 @@ begin
SetSaveEnabled
(
False
);
ClearSelect
(
'task_picker_project'
,
True
);
ClearSelect
(
'task_picker_task'
,
True
);
UpdateFocusCheckbox
;
customerId
:=
SelectedValue
(
'task_picker_customer'
);
if
customerId
=
''
then
Exit
;
try
await
(
LoadProjects
(
customerId
));
except
on
E
:
Exception
do
SetStatus
(
'Unable to load projects.'
);
end
;
FilterProjects
(
customerId
);
end
;
[
async
]
procedure
TTaskPickerOffCanvas
.
ProjectChanged
(
Event
:
TJSEvent
);
var
projectId
:
string
;
customerId
:
string
;
project
:
TJSObject
;
i
:
Integer
;
begin
ClearStatus
;
SetSaveEnabled
(
False
);
ClearSelect
(
'task_picker_task'
,
True
);
UpdateFocusCheckbox
;
projectId
:=
SelectedValue
(
'task_picker_project'
);
if
projectId
=
''
then
Exit
;
customerId
:=
SelectedValue
(
'task_picker_customer'
);
if
customerId
=
''
then
begin
for
i
:=
0
to
FProjects
.
length
-
1
do
begin
project
:=
TJSObject
(
FProjects
[
i
]);
if
string
(
project
[
'value'
])
=
projectId
then
begin
customerId
:=
string
(
project
[
'customerId'
]);
Break
;
end
;
end
;
TJSHTMLSelectElement
(
document
.
getElementById
(
'task_picker_customer'
)).
value
:=
customerId
;
FilterProjects
(
customerId
);
TJSHTMLSelectElement
(
document
.
getElementById
(
'task_picker_project'
)).
value
:=
projectId
;
end
;
try
await
(
LoadTasks
(
projectId
));
except
...
...
@@ -282,16 +326,52 @@ begin
end
;
end
;
procedure
TTaskPickerOffCanvas
.
UpdateFocusCheckbox
;
var
taskId
:
string
;
taskOption
:
TJSObject
;
alreadyFocused
:
Boolean
;
addFocus
:
TJSHTMLInputElement
;
i
:
Integer
;
begin
taskId
:=
SelectedValue
(
'task_picker_task'
);
alreadyFocused
:=
False
;
if
taskId
<>
''
then
begin
for
i
:=
0
to
FFocusedTasks
.
length
-
1
do
begin
taskOption
:=
TJSObject
(
FFocusedTasks
[
i
]);
if
string
(
taskOption
[
'taskId'
])
=
taskId
then
begin
alreadyFocused
:=
True
;
Break
;
end
;
end
;
end
;
addFocus
:=
TJSHTMLInputElement
(
document
.
getElementById
(
'task_picker_add_focus'
)
);
addFocus
.
checked
:=
alreadyFocused
;
addFocus
.
disabled
:=
alreadyFocused
or
(
taskId
=
''
);
end
;
procedure
TTaskPickerOffCanvas
.
TaskChanged
(
Event
:
TJSEvent
);
begin
ClearStatus
;
UpdateFocusCheckbox
;
SetSaveEnabled
(
SelectedValue
(
'task_picker_task'
)
<>
''
);
end
;
procedure
TTaskPickerOffCanvas
.
SaveClicked
(
Event
:
TJSEvent
);
[
async
]
procedure
TTaskPickerOffCanvas
.
SaveClicked
(
Event
:
TJSEvent
);
var
taskId
:
string
;
taskDisplay
:
string
;
addFocus
:
TJSHTMLInputElement
;
addedToFocus
:
Boolean
;
begin
Event
.
preventDefault
;
...
...
@@ -303,31 +383,66 @@ begin
end
;
taskDisplay
:=
FindDisplay
(
FTasks
,
taskId
);
addFocus
:=
TJSHTMLInputElement
(
document
.
getElementById
(
'task_picker_add_focus'
)
);
ClearStatus
;
addedToFocus
:=
False
;
if
addFocus
.
checked
and
not
addFocus
.
disabled
then
begin
SetSaveEnabled
(
False
);
try
await
(
FClient
.
RawInvokeAsync
(
'ITimeEntryService.AddTaskToFocus'
,
[
FUserId
,
taskId
]
));
addedToFocus
:=
True
;
except
on
E
:
EXDataClientRequestException
do
begin
SetStatus
(
E
.
ErrorResult
.
ErrorMessage
);
SetSaveEnabled
(
True
);
Exit
;
end
;
end
;
SetSaveEnabled
(
True
);
end
;
if
Assigned
(
FOnTaskPicked
)
then
FOnTaskPicked
(
FRowIndex
,
taskId
,
taskDisplay
);
FOnTaskPicked
(
FRowIndex
,
taskId
,
taskDisplay
,
addedToFocus
);
Hide
;
end
;
[
async
]
procedure
TTaskPickerOffCanvas
.
Open
(
const
AUserId
:
string
;
ARowIndex
:
Integer
);
[
async
]
procedure
TTaskPickerOffCanvas
.
Open
(
const
AUserId
:
string
;
ARowIndex
:
Integer
;
AFocusedTasks
:
TJSArray
);
begin
FUserId
:=
AUserId
;
FRowIndex
:=
ARowIndex
;
FFocusedTasks
:=
AFocusedTasks
;
ClearStatus
;
SetSaveEnabled
(
False
);
ClearSelect
(
'task_picker_customer'
,
True
);
ClearSelect
(
'task_picker_project'
,
True
);
ClearSelect
(
'task_picker_task'
,
True
);
UpdateFocusCheckbox
;
Show
;
try
await
(
LoadCustomers
);
await
(
LoadProjects
(
''
));
FilterProjects
(
''
);
except
on
E
:
Exception
do
SetStatus
(
'Unable to load customers.'
);
SetStatus
(
'Unable to load customers
or projects
.'
);
end
;
end
;
...
...
emT3XDataServer/Source/Api.Database.dfm
View file @
d87ba778
...
...
@@ -7,10 +7,10 @@ object ApiDatabase: TApiDatabase
ProviderName = 'MySQL'
Database = 'eTask'
Username = 'root'
Server = '192.168.
102.133
'
Server = '192.168.
90.131
'
LoginPrompt = False
Left = 43
5
Top = 3
59
Left = 43
9
Top = 3
63
EncryptedPassword = '9AFF92FF8CFF86FF8CFFCFFFCEFF'
end
object MySQLUniProvider1: TMySQLUniProvider
...
...
@@ -300,8 +300,8 @@ object ApiDatabase: TApiDatabase
'from task_items'
'where TASK_ID = :TASK_ID'
' and TASK_ITEM_ID = :TASK_ITEM_ID')
Left =
656
Top =
28
2
Left =
708
Top =
30
2
ParamData = <
item
DataType = ftInteger
...
...
@@ -853,7 +853,7 @@ object ApiDatabase: TApiDatabase
'where target_task.TASK_ID = :TASK_ID'
'order by tia.NAME')
Left = 58
Top = 31
4
Top = 31
6
ParamData = <
item
DataType = ftUnknown
...
...
@@ -1279,50 +1279,47 @@ object ApiDatabase: TApiDatabase
SQL.Strings = (
'select distinct'
' c.CUSTOMER_ID,'
' c.
SHORT_NAME as CUSTOMER_SHORT
_NAME'
'from
user_project up
'
'join project p on p.
PROJECT_ID = up.PROJECT
_ID'
'
join customers c on c.CUSTOMER_ID = p.CUSTOMER_ID'
'
where up.USER_ID = :USER_ID
'
'
order by c.SHORT_NAME
')
Left = 40
2
' c.
NAME as CUSTOMER
_NAME'
'from
customers c
'
'join project p on p.
CUSTOMER_ID = c.CUSTOMER
_ID'
'
where p.STATUS = '#39'ACTIVE'#39
'
order by c.NAME
'
'')
Left = 40
4
Top = 494
ParamData = <
item
DataType = ftUnknown
Name = 'USER_ID'
Value = nil
end>
object uqTaskPickerCustomersCUSTOMER_ID: TStringField
FieldName = 'CUSTOMER_ID'
Size = 7
end
object uqTaskPickerCustomersCUSTOMER_
SHORT_
NAME: TStringField
FieldName = 'CUSTOMER_
SHORT_
NAME'
Size =
1
0
object uqTaskPickerCustomersCUSTOMER_NAME: TStringField
FieldName = 'CUSTOMER_NAME'
Size =
3
0
end
end
object uqTaskPickerProjects: TUniQuery
Connection = ucETaskApi
SQL.Strings = (
'select
distinct
'
'select'
' p.PROJECT_ID,'
' p.NAME as PROJECT_NAME'
'from user_project up'
'join project p on p.PROJECT_ID = up.PROJECT_ID'
'where up.USER_ID = :USER_ID'
' and p.CUSTOMER_ID = :CUSTOMER_ID'
'order by p.NAME')
' p.NAME as PROJECT_NAME,'
' p.CUSTOMER_ID'
'from project p '
'join customers c on c.CUSTOMER_ID = p.CUSTOMER_ID'
'where p.STATUS = '#39'ACTIVE'#39
'and (:CUSTOMER_ID = '#39#39' or p.CUSTOMER_ID = :CUSTOMER_ID)'
'order by p.NAME'
''
''
''
''
''
''
'')
Left = 544
Top = 494
ParamData = <
item
DataType = ftUnknown
Name = 'USER_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'CUSTOMER_ID'
Value = nil
end>
...
...
@@ -1335,13 +1332,17 @@ object ApiDatabase: TApiDatabase
FieldName = 'PROJECT_NAME'
Size = 30
end
object uqTaskPickerProjectsCUSTOMER_ID: TStringField
FieldName = 'CUSTOMER_ID'
Size = 7
end
end
object uqTaskPickerTasks: TUniQuery
Connection = ucETaskApi
SQL.Strings = (
'select distinct'
' t.TASK_ID,'
' c.
SHORT_NAME as CUSTOMER_SHORT
_NAME,'
' c.
NAME as CUSTOMER
_NAME,'
' p.NAME as PROJECT_NAME,'
' t.TASK_NUM_1,'
' t.TASK_NUM_2,'
...
...
@@ -1353,9 +1354,8 @@ object ApiDatabase: TApiDatabase
'from tasks t'
'join project p on p.PROJECT_ID = t.PROJECT_ID'
'join customers c on c.CUSTOMER_ID = p.CUSTOMER_ID'
'join user_project up on up.PROJECT_ID = p.PROJECT_ID'
'where up.USER_ID = :USER_ID'
' and t.PROJECT_ID = :PROJECT_ID'
' where t.PROJECT_ID = :PROJECT_ID'
' and p.STATUS = '#39'ACTIVE'#39
'order by'
' t.TASK_NUM_1,'
' t.TASK_NUM_2,'
...
...
@@ -1363,17 +1363,13 @@ object ApiDatabase: TApiDatabase
' t.TASK_NUM_4,'
' t.TASK_NUM_5,'
' t.TASK_NUM_6,'
' t.SUBJECT')
' t.SUBJECT'
'')
Left = 676
Top = 502
ParamData = <
item
DataType = ftUnknown
Name = 'USER_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'PROJECT_ID'
Value = nil
end>
...
...
@@ -1382,10 +1378,10 @@ object ApiDatabase: TApiDatabase
Required = True
Size = 7
end
object uqTaskPickerTasksCUSTOMER_
SHORT_
NAME: TStringField
FieldName = 'CUSTOMER_
SHORT_
NAME'
object uqTaskPickerTasksCUSTOMER_NAME: TStringField
FieldName = 'CUSTOMER_NAME'
ReadOnly = True
Size =
1
0
Size =
3
0
end
object uqTaskPickerTasksPROJECT_NAME: TStringField
FieldName = 'PROJECT_NAME'
...
...
emT3XDataServer/Source/Api.Database.pas
View file @
d87ba778
...
...
@@ -94,12 +94,11 @@ type
uqTaskPickerCustomers
:
TUniQuery
;
uqTaskPickerProjects
:
TUniQuery
;
uqTaskPickerTasks
:
TUniQuery
;
uqTaskPickerCustomersCUSTOMER_ID
:
TStringField
;
uqTaskPickerCustomersCUSTOMER_SHORT_NAME
:
TStringField
;
uqTaskPickerProjectsPROJECT_ID
:
TStringField
;
uqTaskPickerProjectsPROJECT_NAME
:
TStringField
;
uqTaskPickerProjectsCUSTOMER_ID
:
TStringField
;
uqTaskPickerTasksTASK_ID
:
TStringField
;
uqTaskPickerTasksCUSTOMER_
SHORT_
NAME
:
TStringField
;
uqTaskPickerTasksCUSTOMER_NAME
:
TStringField
;
uqTaskPickerTasksPROJECT_NAME
:
TStringField
;
uqTaskPickerTasksTASK_NUM_1
:
TIntegerField
;
uqTaskPickerTasksTASK_NUM_2
:
TIntegerField
;
...
...
@@ -108,6 +107,8 @@ type
uqTaskPickerTasksTASK_NUM_5
:
TIntegerField
;
uqTaskPickerTasksTASK_NUM_6
:
TIntegerField
;
uqTaskPickerTasksTASK_SUBJECT
:
TStringField
;
uqTaskPickerCustomersCUSTOMER_ID
:
TStringField
;
uqTaskPickerCustomersCUSTOMER_NAME
:
TStringField
;
procedure
DataModuleCreate
(
Sender
:
TObject
);
procedure
uqUsersCalcFields
(
DataSet
:
TDataSet
);
private
...
...
emT3XDataServer/Source/TaskItem.ServiceImpl.pas
View file @
d87ba778
...
...
@@ -51,6 +51,7 @@ implementation
procedure
TTaskItemService
.
AfterConstruction
;
begin
inherited
;
Logger
.
Log
(
4
,
'TaskItemService.AfterConstruction->TApiDatabase.Create(nil)'
);
apiDB
:=
TApiDatabase
.
Create
(
nil
);
Logger
.
Log
(
4
,
'TaskItemService.AfterConstruction - apiDB created'
);
end
;
...
...
emT3XDataServer/Source/TimeEntry.Service.pas
View file @
d87ba778
...
...
@@ -78,6 +78,7 @@ type
public
value
:
string
;
display
:
string
;
customerId
:
string
;
end
;
TTaskPickerOptionsResponse
=
class
...
...
@@ -95,9 +96,10 @@ type
[
HttpPost
]
function
SaveTimeEntry
(
Item
:
TTimeEntrySave
):
string
;
[
HttpPost
]
function
SaveTimeEntryField
(
Item
:
TTimeEntryFieldSave
):
Boolean
;
[
HttpPost
]
function
DeleteTimeEntry
(
userId
:
string
;
entryId
:
Integer
):
Boolean
;
function
GetTaskPickerCustomers
(
userId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerProjects
(
userId
,
customerId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerTasks
(
userId
,
projectId
:
string
):
TTaskPickerOptionsResponse
;
[
HttpPost
]
function
AddTaskToFocus
(
userId
,
taskId
:
string
):
Boolean
;
function
GetTaskPickerCustomers
:
TTaskPickerOptionsResponse
;
function
GetTaskPickerProjects
(
customerId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerTasks
(
projectId
:
string
):
TTaskPickerOptionsResponse
;
end
;
implementation
...
...
emT3XDataServer/Source/TimeEntry.ServiceImpl.pas
View file @
d87ba778
...
...
@@ -34,10 +34,11 @@ type
function
AddTimeEntry
(
userId
,
taskDate
:
string
):
string
;
function
SaveTimeEntry
(
Item
:
TTimeEntrySave
):
string
;
function
SaveTimeEntryField
(
Item
:
TTimeEntryFieldSave
):
Boolean
;
function
GetTaskPickerCustomers
(
userId
:
string
)
:
TTaskPickerOptionsResponse
;
function
GetTaskPickerProjects
(
userId
,
customerId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerTasks
(
userId
,
projectId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerCustomers
:
TTaskPickerOptionsResponse
;
function
GetTaskPickerProjects
(
customerId
:
string
):
TTaskPickerOptionsResponse
;
function
GetTaskPickerTasks
(
projectId
:
string
):
TTaskPickerOptionsResponse
;
function
DeleteTimeEntry
(
userId
:
string
;
entryId
:
Integer
):
Boolean
;
function
AddTaskToFocus
(
userId
,
taskId
:
string
):
Boolean
;
end
;
implementation
...
...
@@ -50,7 +51,9 @@ uses
procedure
TTimeEntryService
.
AfterConstruction
;
begin
inherited
;
Logger
.
Log
(
4
,
'TTimeEntryService.AfterConstruction->TApiDatabase.Create(nil)'
);
apiDB
:=
TApiDatabase
.
Create
(
nil
);
Logger
.
Log
(
4
,
'TTimeEntryService.AfterConstruction - apiDB created'
)
end
;
...
...
@@ -130,7 +133,7 @@ var
leftText
:
string
;
taskText
:
string
;
begin
customerText
:=
FieldText
(
AQuery
,
'CUSTOMER_
SHORT_
NAME'
);
customerText
:=
FieldText
(
AQuery
,
'CUSTOMER_NAME'
);
projectText
:=
FieldText
(
AQuery
,
'PROJECT_NAME'
);
taskNumberText
:=
BuildTaskNumber
(
AQuery
);
subjectText
:=
FieldText
(
AQuery
,
'TASK_SUBJECT'
);
...
...
@@ -210,7 +213,7 @@ begin
' ti.CATEGORY, '
+
' cat.CODE_DESC as CATEGORY_DESC, '
+
' ti.SUMMARY, '
+
' c.
SHORT_NAME as CUSTOMER_SHORT
_NAME, '
+
' c.
NAME as CUSTOMER
_NAME, '
+
' p.NAME as PROJECT_NAME, '
+
' t.TASK_NUM_1, '
+
' t.TASK_NUM_2, '
+
...
...
@@ -290,7 +293,7 @@ begin
tasksQuery
.
SQL
.
Text
:=
'select distinct '
+
' t.TASK_ID, '
+
' c.
SHORT_NAME as CUSTOMER_SHORT
_NAME, '
+
' c.
NAME as CUSTOMER
_NAME, '
+
' p.NAME as PROJECT_NAME, '
+
' t.TASK_NUM_1, '
+
' t.TASK_NUM_2, '
+
...
...
@@ -305,7 +308,7 @@ begin
'join customers c on c.CUSTOMER_ID = p.CUSTOMER_ID '
+
'where tau.USER_ID = :USER_ID '
+
' and upper(trim(coalesce(tau.FOCUSED_TASK, ''''))) = ''T'' '
+
'order by c.
SHORT_
NAME, p.NAME, t.TASK_NUM_1, t.TASK_NUM_2, t.TASK_NUM_3, t.TASK_NUM_4, t.TASK_NUM_5, t.TASK_NUM_6'
;
'order by c.NAME, p.NAME, t.TASK_NUM_1, t.TASK_NUM_2, t.TASK_NUM_3, t.TASK_NUM_4, t.TASK_NUM_5, t.TASK_NUM_6'
;
tasksQuery
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
tasksQuery
.
Open
;
...
...
@@ -764,15 +767,14 @@ begin
end
;
function
TTimeEntryService
.
GetTaskPickerCustomers
(
userId
:
string
)
:
TTaskPickerOptionsResponse
;
function
TTimeEntryService
.
GetTaskPickerCustomers
:
TTaskPickerOptionsResponse
;
begin
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.GetTaskPickerCustomers - USER_ID="%s"'
,
[
userId
])
);
Logger
.
Log
(
4
,
'TimeEntryService.GetTaskPickerCustomers Start'
);
Result
:=
TTaskPickerOptionsResponse
.
Create
;
TXDataOperationContext
.
Current
.
Handler
.
ManagedObjects
.
Add
(
Result
);
apiDB
.
uqTaskPickerCustomers
.
Close
;
apiDB
.
uqTaskPickerCustomers
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
apiDB
.
uqTaskPickerCustomers
.
Open
;
try
while
not
apiDB
.
uqTaskPickerCustomers
.
Eof
do
...
...
@@ -780,7 +782,7 @@ begin
AddTaskPickerOption
(
Result
,
FieldText
(
apiDB
.
uqTaskPickerCustomers
,
'CUSTOMER_ID'
),
FieldText
(
apiDB
.
uqTaskPickerCustomers
,
'CUSTOMER_
SHORT_
NAME'
)
FieldText
(
apiDB
.
uqTaskPickerCustomers
,
'CUSTOMER_NAME'
)
);
apiDB
.
uqTaskPickerCustomers
.
Next
;
...
...
@@ -791,15 +793,14 @@ begin
end
;
function
TTimeEntryService
.
GetTaskPickerProjects
(
userId
,
customerId
:
string
):
TTaskPickerOptionsResponse
;
function
TTimeEntryService
.
GetTaskPickerProjects
(
customerId
:
string
):
TTaskPickerOptionsResponse
;
begin
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.GetTaskPickerProjects -
USER_ID="%s" CUSTOMER_ID="%s"'
,
[
userId
,
customerId
]));
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.GetTaskPickerProjects -
CUSTOMER_ID="%s"'
,
[
customerId
]));
Result
:=
TTaskPickerOptionsResponse
.
Create
;
TXDataOperationContext
.
Current
.
Handler
.
ManagedObjects
.
Add
(
Result
);
apiDB
.
uqTaskPickerProjects
.
Close
;
apiDB
.
uqTaskPickerProjects
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
apiDB
.
uqTaskPickerProjects
.
ParamByName
(
'CUSTOMER_ID'
).
AsString
:=
customerId
;
apiDB
.
uqTaskPickerProjects
.
Open
;
try
...
...
@@ -811,6 +812,9 @@ begin
FieldText
(
apiDB
.
uqTaskPickerProjects
,
'PROJECT_NAME'
)
);
Result
.
options
[
Result
.
options
.
Count
-
1
].
customerId
:=
apiDB
.
uqTaskPickerProjectsCUSTOMER_ID
.
AsString
;
apiDB
.
uqTaskPickerProjects
.
Next
;
end
;
finally
...
...
@@ -819,15 +823,14 @@ begin
end
;
function
TTimeEntryService
.
GetTaskPickerTasks
(
userId
,
projectId
:
string
):
TTaskPickerOptionsResponse
;
function
TTimeEntryService
.
GetTaskPickerTasks
(
projectId
:
string
):
TTaskPickerOptionsResponse
;
begin
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.GetTaskPickerTasks -
USER_ID="%s" PROJECT_ID="%s"'
,
[
userId
,
projectId
]));
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.GetTaskPickerTasks -
PROJECT_ID="%s"'
,
[
projectId
]));
Result
:=
TTaskPickerOptionsResponse
.
Create
;
TXDataOperationContext
.
Current
.
Handler
.
ManagedObjects
.
Add
(
Result
);
apiDB
.
uqTaskPickerTasks
.
Close
;
apiDB
.
uqTaskPickerTasks
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
apiDB
.
uqTaskPickerTasks
.
ParamByName
(
'PROJECT_ID'
).
AsString
:=
projectId
;
apiDB
.
uqTaskPickerTasks
.
Open
;
try
...
...
@@ -890,6 +893,64 @@ begin
end
;
end
;
function
TTimeEntryService
.
AddTaskToFocus
(
userId
,
taskId
:
string
):
Boolean
;
var
q
:
TUniQuery
;
begin
Logger
.
Log
(
4
,
Format
(
'TimeEntryService.AddTaskToFocus - USER_ID="%s" TASK_ID="%s"'
,
[
userId
,
taskId
]
));
q
:=
TUniQuery
.
Create
(
nil
);
try
q
.
Connection
:=
apiDB
.
ucETaskApi
;
q
.
Connection
.
StartTransaction
;
try
q
.
SQL
.
Text
:=
'select TASK_ID from task_assigned_user '
+
'where USER_ID = :USER_ID and TASK_ID = :TASK_ID'
;
q
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
q
.
ParamByName
(
'TASK_ID'
).
AsString
:=
taskId
;
q
.
Open
;
if
q
.
IsEmpty
then
begin
q
.
Close
;
q
.
SQL
.
Text
:=
'insert into task_assigned_user '
+
'(USER_ID, TASK_ID, FOCUSED_TASK) '
+
'values (:USER_ID, :TASK_ID, ''T'')'
;
end
else
begin
q
.
Close
;
q
.
SQL
.
Text
:=
'update task_assigned_user '
+
'set FOCUSED_TASK = ''T'' '
+
'where USER_ID = :USER_ID and TASK_ID = :TASK_ID'
;
end
;
q
.
ParamByName
(
'USER_ID'
).
AsString
:=
userId
;
q
.
ParamByName
(
'TASK_ID'
).
AsString
:=
taskId
;
q
.
ExecSQL
;
q
.
Connection
.
Commit
;
Result
:=
True
;
except
on
E
:
Exception
do
begin
if
q
.
Connection
.
InTransaction
then
q
.
Connection
.
Rollback
;
Logger
.
Log
(
2
,
'TimeEntryService.AddTaskToFocus - ERROR: '
+
E
.
Message
);
raise
;
end
;
end
;
finally
q
.
Free
;
end
;
end
;
initialization
RegisterServiceType
(
TTimeEntryService
);
...
...
emT3XDataServer/bin/emT3XDataServer.ini
View file @
d87ba778
[Settings]
MemoLogLevel
=
4
FileLogLevel
=
4
MemoLogLevel
=
5
FileLogLevel
=
5
webClientVersion
=
0.9.3
LogFileNum
=
16
7
LogFileNum
=
20
7
[Database]
--Server
=
192.168.102.131
--Server
=
192.168.116.128
--Server
=
192.168.102.131
--Server
=
192.168.159.10
Server
=
192.168.90.12
9
Server
=
192.168.90.12
Database
=
eTask
Username
=
root
Password
=
emsys01
...
...
emT3XDataServer/emT3XDataServer.dproj
View file @
d87ba778
...
...
@@ -114,11 +114,11 @@
<VerInfo_Locale>1033</VerInfo_Locale>
<DCC_ExeOutput>.\bin</DCC_ExeOutput>
<DCC_UnitSearchPath>C:\RADTOOLS\FastMM4;$(DCC_UnitSearchPath)</DCC_UnitSearchPath>
<VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.3.
3
;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.11;Comments=</VerInfo_Keys>
<VerInfo_Keys>CompanyName=EM Systems;FileDescription=$(MSBuildProjectName);FileVersion=0.9.3.
16
;InternalName=;LegalCopyright=;LegalTrademarks=;OriginalFilename=;ProgramID=com.embarcadero.$(MSBuildProjectName);ProductName=$(MSBuildProjectName);ProductVersion=0.9.11;Comments=</VerInfo_Keys>
<VerInfo_MajorVer>0</VerInfo_MajorVer>
<VerInfo_MinorVer>9</VerInfo_MinorVer>
<VerInfo_AutoIncVersion>true</VerInfo_AutoIncVersion>
<VerInfo_Build>
3
</VerInfo_Build>
<VerInfo_Build>
16
</VerInfo_Build>
<VerInfo_Release>3</VerInfo_Release>
</PropertyGroup>
<PropertyGroup Condition="'$(Cfg_1_Win64)'!=''">
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment