Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
I
intranet-timesheet2-interval
Project
Project
Details
Activity
Releases
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
project-open
intranet-timesheet2-interval
Commits
016bb01e
Commit
016bb01e
authored
Jul 23, 2014
by
Frank Bergmann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
- Dunno
parent
89a576bf
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
181 additions
and
11 deletions
+181
-11
timesheet-interval.adp
lib/timesheet-interval.adp
+84
-11
timesheet-interval.tcl
lib/timesheet-interval.tcl
+3
-0
intranet-timesheet2-interval-create.sql
sql/postgresql/intranet-timesheet2-interval-create.sql
+94
-0
No files found.
lib/timesheet-interval.adp
View file @
016bb01e
...
...
@@ -6,6 +6,7 @@
Ext.Loader.setPath('PO.model', '/sencha-core/model');
Ext.Loader.setPath('PO.store', '/sencha-core/store');
Ext.Loader.setPath('PO.class', '/sencha-core/class');
Ext.Loader.setPath('Ext.ux', '/sencha-core/ux');
Ext.Loader.setPath('PO.view.gantt', '/sencha-core/view/gantt');
Ext.Loader.setPath('PO.controller', '/sencha-core/controller');
...
...
@@ -19,7 +20,8 @@ Ext.require([
'PO.model.timesheet.HourInterval',
'PO.store.timesheet.HourIntervalStore',
'PO.store.timesheet.TaskTreeStore',
'PO.store.timesheet.HourIntervalActivityStore'
'PO.store.timesheet.HourIntervalActivityStore',
'Ext.ux.TreeCombo'
]);
...
...
@@ -43,17 +45,40 @@ function launchTreePanel(){
return projectName;
};
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 2,
listeners: {
edit: function(editor, context, eOpts) {
context.record.save();
}
}
});
var hourIntervalGrid = Ext.create('Ext.grid.Panel', {
store: hourIntervalStore,
layout: 'fit',
region: 'center',
columns: [
{text: "Project", flex: 1, dataIndex: 'project_id', renderer: hourIntervalGridProjectRenderer},
{text: "Start", flex: 1, dataIndex: 'interval_start', renderer: Ext.util.Format.dateRenderer('Y-m-d H:i:s') },
{text: "End", flex: 1, dataIndex: 'interval_end', renderer: Ext.util.Format.dateRenderer('Y-m-d H:i:s') },
{text: "Note", flex: 1, dataIndex: 'note'}
],
plugins: [rowEditing],
columns: [{
text: "Project", flex: 1, dataIndex: 'project_id', renderer: hourIntervalGridProjectRenderer,
editor: {
xtype: 'treecombo',
store: taskTreeStore,
rootVisible: false,
displayField: 'project_name',
valueField: 'id',
allowBlank: false
}
}, {
text: "Start", flex: 1, dataIndex: 'interval_start', renderer: Ext.util.Format.dateRenderer('Y-m-d H:i:s'),
editor: { allowBlank: false }
}, {
text: "End", flex: 1, dataIndex: 'interval_end', renderer: Ext.util.Format.dateRenderer('Y-m-d H:i:s'),
editor: { allowBlank: false }
}, {
text: "Note", flex: 1, dataIndex: 'note',
editor: { allowBlank: false }
}],
columnLines: true,
enableLocking: true,
collapsible: false,
...
...
@@ -121,6 +146,7 @@ function launchTreePanel(){
'selectedTask': null, // Task selected by selection model
'loggingTask': null, // contains the task on which hours are logged or null otherwise
'loggingStartDate': null, // contains the time when "start" was pressed or null otherwise
'loggingInterval': null, // the hourInterval object created when logging
// Parameters
'renderDiv': null,
...
...
@@ -144,12 +170,27 @@ function launchTreePanel(){
// Listen to changes in the selction model in order to enable/disable the start/stop buttons
me.ganttTreePanel.on('selectionchange', this.onTreePanelSelectionChange, me);
// Listen to a click into the empty space below the
tree in order to add a new task
me.
ganttTreePanel.on('containerclick', me.ganttTreePanel.onContainerClick, me.ganttTreePanel
);
// Listen to a click into the empty space below the
grid entries in order to start creating a new entry
me.
hourIntervalGrid.on('containerclick', this.onGridContainerClick, me
);
return this;
},
// Click into the empty space below the grid entries in order to start creating a new entry
onGridContainerClick: function() {
console.log('GanttButtonController.GridContainerClick');
var buttonStartLogging = Ext.getCmp('buttonStartLogging');
var disabled = buttonStartLogging.disabled;
if (!disabled) {
this.onButtonStartLogging();
}
},
/*
* Start logging the time.
* Before calling this procedure, the user must have selected a single
* leaf in the task tree for logging hours.
*/
onButtonStartLogging: function() {
console.log('GanttButtonController.ButtonStartLogging');
var buttonStartLogging = Ext.getCmp('buttonStartLogging');
...
...
@@ -157,18 +198,41 @@ function launchTreePanel(){
buttonStartLogging.disable();
buttonStopLogging.enable();
rowEditing.cancelEdit();
// Start logging
this.loggingTask = selectedTask;
this.loggingStartTime = new Date();
var hourInterval = new Ext.create('PO.model.timesheet.HourInterval', {
user_id: @current_user_id@,
project_id: selectedTask.get('id'),
interval_start: this.loggingStartTime
// inverval_end: this.loggingStartTime
});
// Remember the new interval, add to store and start editing
this.loggingInterval = hourInterval;
hourIntervalStore.add(hourInterval);
//var rowIndex = hourIntervalStore.count() -1;
// rowEditing.startEdit(0, 0);
},
onButtonStopLogging: function() {
console.log('GanttButtonController.ButtonStopLogging');
var buttonStartLogging = Ext.getCmp('buttonStartLogging');
var buttonStopLogging = Ext.getCmp('buttonStopLogging');
buttonStartLogging.
dis
able();
buttonStartLogging.
en
able();
buttonStopLogging.disable();
// Complete the hourInterval created when starting to log
this.loggingInterval.set('interval_end', new Date());
var rowIndex = hourIntervalStore.count() -1;
rowEditing.startEdit(rowIndex, 3);
this.loggingInterval.save();
// Stop logging
this.loggingTask = null;
this.loggingStartTime = null;
...
...
@@ -191,6 +255,15 @@ function launchTreePanel(){
selectedTask = record; // Remember which task is selected
var isLeaf = record.isLeaf();
buttonStartLogging.setDisabled(!isLeaf);
// load the list of hourIntervals into the hourIntervalGrid
var projectId = record.get('id');
hourIntervalStore.getProxy().extraParams = { project_id: projectId, user_id: @current_user_id@, format: 'json' };
hourIntervalStore.load({
callback: function() {
console.log('PO.store.timesheet.HourIntervalStore: loaded');
}
});
} else { // Zero or two or more records enabled
buttonStartLogging.setDisabled(true);
}
...
...
lib/timesheet-interval.tcl
View file @
016bb01e
...
...
@@ -25,3 +25,6 @@ set task_editor_rand [expr round(rand() * 100000000.0)]
set
task_editor_id
"task_editor_
$task
_editor_rand"
set
please_add_note_required_l10n
[
lang::message::lookup
""
intranet-timesheet2-inverval.Please_add_a_note_required
"Please add a note (required)"
]
sql/postgresql/intranet-timesheet2-interval-create.sql
View file @
016bb01e
...
...
@@ -81,6 +81,100 @@ create index im_hour_intervals_interval_start_idx on im_hour_intervals(interval_
-- ------------------------------------------------------------
-- Trigger for synchronization between intervals and hours
-- ------------------------------------------------------------
-- Create a new im_hour row for the interval or update
-- an existing one.
create
or
replace
function
im_hour_interval_update_im_hours
(
integer
,
integer
,
date
)
returns
integer
as
$
body
$
DECLARE
p_user_id
alias
for
$
1
;
p_project_id
alias
for
$
2
;
p_day
alias
for
$
3
;
v_hour_id
integer
;
v_sum_hours
numeric
;
v_sum_notes
varchar
;
row
record
;
BEGIN
-- Check if there is already an im_hours entry
select
h
.
hour_id
into
v_hour_id
from
im_hours
h
where
h
.
user_id
=
p_user_id
and
h
.
project_id
=
p_project_id
and
h
.
day
=
p_day
;
-- Create a new entry if there wasnt one before
IF
v_hour_id
is
null
THEN
v_hour_id
:
=
nextval
(
'im_hours_seq'
);
RAISE
NOTICE
'im_hour_interval_insert_tr: About to insert a new im_hour with ID=%'
,
v_hour_id
;
insert
into
im_hours
(
hour_id
,
user_id
,
project_id
,
day
,
hours
,
note
)
values
(
v_hour_id
,
p_user_id
,
p_project_id
,
p_day
,
0
,
''
);
END
IF
;
-- Sum up all interval properties into one hour row
v_sum_hours
:
=
0
.
0
;
v_sum_notes
:
=
''
;
FOR
row
IN
select
*
from
im_hour_intervals
where
user_id
=
p_user_id
and
project_id
=
p_project_id
and
interval_start
::
date
=
p_day
LOOP
v_sum_hours
:
=
v_sum_hours
+
coalesce
(
extract
(
epoch
from
row
.
interval_end
-
row
.
interval_start
)
/
3600
.
0
,
0
.
0
);
v_sum_notes
:
=
v_sum_notes
||
coalesce
(
row
.
note
,
''
)
||
E
'
\n
'
;
END
LOOP
;
-- Update the im_hours entry with the sum of the values
update
im_hours
set
hours
=
v_sum_hours
,
note
=
v_sum_notes
where
hour_id
=
v_hour_id
;
return
0
;
END
;
$
body
$
language
'plpgsql'
;
create
or
replace
function
im_hour_interval_insert_tr
()
returns
trigger
as
$
body
$
BEGIN
PERFORM
im_hour_interval_update_im_hours
(
new
.
user_id
,
new
.
project_id
,
new
.
interval_start
::
date
);
return
new
;
END
;
$
body
$
language
'plpgsql'
;
create
or
replace
function
im_hour_interval_update_tr
()
returns
trigger
as
$
body
$
BEGIN
PERFORM
im_hour_interval_update_im_hours
(
new
.
user_id
,
new
.
project_id
,
new
.
interval_start
::
date
);
IF
new
.
interval_start
::
date
!=
old
.
interval_start
::
date
THEN
PERFORM
im_hour_interval_update_im_hours
(
old
.
user_id
,
old
.
project_id
,
old
.
interval_start
::
date
);
END
IF
;
return
new
;
END
;
$
body
$
language
'plpgsql'
;
create
or
replace
function
im_hour_interval_delete_tr
()
returns
trigger
as
$
body
$
BEGIN
PERFORM
im_hour_interval_update_im_hours
(
old
.
user_id
,
old
.
project_id
,
old
.
interval_start
::
date
);
return
old
;
END
;
$
body
$
language
'plpgsql'
;
create
trigger
im_hour_interval_insert_tr
after
insert
on
im_hour_intervals
for
each
row
execute
procedure
im_hour_interval_insert_tr
();
create
trigger
im_hour_interval_update_tr
after
update
on
im_hour_intervals
for
each
row
execute
procedure
im_hour_interval_update_tr
();
create
trigger
im_hour_interval_delete_tr
after
delete
on
im_hour_intervals
for
each
row
execute
procedure
im_hour_interval_delete_tr
();
-- ------------------------------------------------------------
-- Portlet
-- ------------------------------------------------------------
...
...
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