update
This commit is contained in:
3
.claude/memory/MEMORY.md
Normal file
3
.claude/memory/MEMORY.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Memory Index
|
||||
|
||||
- [feedback_polish.md](feedback_polish.md) — Komunikacja po polsku
|
||||
10
.claude/memory/feedback_polish.md
Normal file
10
.claude/memory/feedback_polish.md
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Komunikacja po polsku
|
||||
description: Użytkownik chce, żeby Claude pisał do niego po polsku
|
||||
type: feedback
|
||||
---
|
||||
|
||||
Zawsze komunikuj się z użytkownikiem po polsku.
|
||||
|
||||
**Why:** Użytkownik wyraźnie poprosił o komunikację w języku polskim.
|
||||
**How to apply:** Wszystkie odpowiedzi, pytania i podsumowania pisz po polsku.
|
||||
@@ -593,6 +593,29 @@ class Tasks
|
||||
exit;
|
||||
}
|
||||
|
||||
static public function task_work_logs_popup()
|
||||
{
|
||||
global $user;
|
||||
|
||||
if ( !$user )
|
||||
{
|
||||
header( 'Location: /logowanie' );
|
||||
exit;
|
||||
}
|
||||
|
||||
$task_id = (int)\S::get( 'task_id' );
|
||||
$task = \factory\Tasks::task_details( $task_id, $user['id'] );
|
||||
|
||||
if ( !is_array( $task ) )
|
||||
$task = [ 'id' => $task_id, 'name' => '' ];
|
||||
|
||||
echo \Tpl::view( 'tasks/task_work_logs_popup', [
|
||||
'task' => $task,
|
||||
'task_works' => \factory\Tasks::task_works( $task_id )
|
||||
] );
|
||||
exit;
|
||||
}
|
||||
|
||||
static public function task_attachment_upload()
|
||||
{
|
||||
global $user;
|
||||
|
||||
81
templates/tasks/task_work_logs_popup.php
Normal file
81
templates/tasks/task_work_logs_popup.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?
|
||||
$to_input_datetime = function( $datetime ) {
|
||||
if ( !$datetime )
|
||||
return '';
|
||||
|
||||
$timestamp = strtotime( (string)$datetime );
|
||||
if ( $timestamp === false )
|
||||
return '';
|
||||
|
||||
return date( 'Y-m-d\TH:i', $timestamp );
|
||||
};
|
||||
|
||||
$resolve_user_name = function( $user_id ) {
|
||||
static $cache = [];
|
||||
$user_id = (int)$user_id;
|
||||
|
||||
if ( !isset( $cache[ $user_id ] ) )
|
||||
{
|
||||
$details = \factory\Users::user_details( $user_id );
|
||||
$name = 'Nieznany użytkownik';
|
||||
|
||||
if ( is_array( $details ) )
|
||||
{
|
||||
$full_name = trim( trim( (string)( $details['name'] ?? '' ) ) . ' ' . trim( (string)( $details['surname'] ?? '' ) ) );
|
||||
if ( $full_name !== '' )
|
||||
$name = $full_name;
|
||||
}
|
||||
|
||||
$cache[ $user_id ] = $name;
|
||||
}
|
||||
|
||||
return $cache[ $user_id ];
|
||||
};
|
||||
?>
|
||||
<div class="work-time-logs-popup">
|
||||
<div class="mb10">
|
||||
<div><b>Zadanie:</b> <?= htmlspecialchars( (string)( $this -> task['name'] ?? '' ), ENT_QUOTES, 'UTF-8' );?></div>
|
||||
<div><b>ID:</b> <?= (int)( $this -> task['id'] ?? 0 );?></div>
|
||||
</div>
|
||||
|
||||
<? if ( is_array( $this -> task_works ) and count( $this -> task_works ) ):?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped mb0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Użytkownik</th>
|
||||
<th style="width: 220px;">Start</th>
|
||||
<th style="width: 220px;">Koniec</th>
|
||||
<th class="text-center" style="width: 120px;">Akcja</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<? foreach ( $this -> task_works as $work ):?>
|
||||
<tr class="js-work-log-row" data-work-id="<?= (int)$work['id'];?>">
|
||||
<td><?= htmlspecialchars( $resolve_user_name( $work['user_id'] ), ENT_QUOTES, 'UTF-8' );?></td>
|
||||
<td>
|
||||
<input
|
||||
type="datetime-local"
|
||||
class="form-control js-work-log-start"
|
||||
value="<?= htmlspecialchars( $to_input_datetime( $work['date_start'] ), ENT_QUOTES, 'UTF-8' );?>"
|
||||
>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="datetime-local"
|
||||
class="form-control js-work-log-end"
|
||||
value="<?= htmlspecialchars( $to_input_datetime( $work['date_end'] ), ENT_QUOTES, 'UTF-8' );?>"
|
||||
>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="#" class="js-save-work-log btn btn-xs btn-primary" task_work_id="<?= (int)$work['id'];?>">zapisz</a>
|
||||
</td>
|
||||
</tr>
|
||||
<? endforeach;?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<? else:?>
|
||||
<div class="alert alert-info mb0">Brak wpisów time trackingu dla tego zadania.</div>
|
||||
<? endif;?>
|
||||
</div>
|
||||
@@ -157,7 +157,11 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
<tr class="billing-task-row" data-task-time="<?= (int)$row['time'];?>" data-task-amount="<?= number_format( (float)$row['amount'], 0, '.', '' );?>">
|
||||
<td><?= $row['month'];?></td>
|
||||
<td><?= $row['name'];?></td>
|
||||
<td class="text-center"><?= $format_time( $row['time'] );?></td>
|
||||
<td class="text-center">
|
||||
<a href="#" class="open-work-logs-popup" task-id="<?= (int)$row['id'];?>" task-name="<?= htmlspecialchars( (string)$row['name'], ENT_QUOTES, 'UTF-8' );?>">
|
||||
<?= $format_time( $row['time'] );?>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-right"><?= $format_amount( $row['amount'] );?></td>
|
||||
<td class="text-center">
|
||||
<a href="#" class="close-task" task-id="<?= $row['id'];?>" client="<?= $summary['firm'];?>">zamknij zadanie</a>
|
||||
@@ -250,6 +254,54 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
onConfirm();
|
||||
}
|
||||
|
||||
function showPopupMessage( message ) {
|
||||
if ( typeof $.alert === 'function' )
|
||||
{
|
||||
$.alert({
|
||||
title: 'Informacja',
|
||||
content: message
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
alert( message );
|
||||
}
|
||||
|
||||
function openWorkLogsPopup( task_id, task_name ) {
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/tasks/task_work_logs_popup/',
|
||||
data: {
|
||||
task_id: task_id
|
||||
},
|
||||
success: function( response ) {
|
||||
if ( typeof $.confirm !== 'function' )
|
||||
{
|
||||
showPopupMessage( 'Brak obsługi popupu w tej konfiguracji.' );
|
||||
return;
|
||||
}
|
||||
|
||||
$.confirm({
|
||||
title: 'Time tracking: ' + task_name,
|
||||
content: response,
|
||||
type: 'blue',
|
||||
boxWidth: '980px',
|
||||
useBootstrap: false,
|
||||
backgroundDismiss: true,
|
||||
buttons: {
|
||||
close: {
|
||||
text: 'Zamknij'
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
showPopupMessage( 'Nie udało się pobrać wpisów time trackingu.' );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$( 'body' ).on( 'click', '.toggle-billing-details', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
@@ -279,6 +331,70 @@ usort( $billing_clients, function( $a, $b ) {
|
||||
});
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.open-work-logs-popup', function(e){
|
||||
e.preventDefault();
|
||||
var task_id = parseInt( $( this ).attr( 'task-id' ), 10 ) || 0;
|
||||
var task_name = $( this ).attr( 'task-name' ) || ( 'Zadanie #' + task_id );
|
||||
|
||||
if ( !task_id )
|
||||
{
|
||||
showPopupMessage( 'Brak identyfikatora zadania.' );
|
||||
return;
|
||||
}
|
||||
|
||||
openWorkLogsPopup( task_id, task_name );
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.js-save-work-log', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var button = $( this );
|
||||
var row = button.closest( '.js-work-log-row' );
|
||||
var task_work_id = parseInt( button.attr( 'task_work_id' ), 10 ) || 0;
|
||||
var date_start = row.find( '.js-work-log-start' ).val();
|
||||
var date_end = row.find( '.js-work-log-end' ).val();
|
||||
|
||||
if ( !task_work_id )
|
||||
{
|
||||
showPopupMessage( 'Brak identyfikatora wpisu.' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !date_start || !date_end )
|
||||
{
|
||||
showPopupMessage( 'Uzupełnij datę start i koniec.' );
|
||||
return;
|
||||
}
|
||||
|
||||
button.attr( 'disabled', 'disabled' );
|
||||
|
||||
$.when(
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/tasks/change_task_work_date_start/',
|
||||
data: {
|
||||
task_work_id: task_work_id,
|
||||
date_start: date_start
|
||||
}
|
||||
}),
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
url: '/tasks/change_task_work_date_end/',
|
||||
data: {
|
||||
task_work_id: task_work_id,
|
||||
date_end: date_end
|
||||
}
|
||||
})
|
||||
).done( function() {
|
||||
window.location.reload();
|
||||
}).fail( function() {
|
||||
button.removeAttr( 'disabled' );
|
||||
showPopupMessage( 'Nie udało się zapisać zmian wpisu.' );
|
||||
});
|
||||
});
|
||||
|
||||
$( 'body' ).on( 'click', '.close-task', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
|
||||
@@ -35,9 +35,6 @@
|
||||
<? if ( is_array( $this -> categories ) and count( $this -> categories ) ):?>
|
||||
<? foreach ( $this -> categories as $category ):?>
|
||||
<? $category_name = isset( $category['name'] ) ? (string)$category['name'] : '';?>
|
||||
<? $category_text = isset( $category['text'] ) ? strip_tags( (string)$category['text'] ) : '';?>
|
||||
<? $category_preview = trim( $category_text );?>
|
||||
<? if ( strlen( $category_preview ) > 170 ) $category_preview = substr( $category_preview, 0, 170 ) . '...';?>
|
||||
<article class="wiki-card" data-name="<?= htmlspecialchars( strtolower( $category_name ) );?>">
|
||||
<div class="wiki-card-top">
|
||||
<label class="wiki-select-one-label">
|
||||
@@ -45,11 +42,6 @@
|
||||
</label>
|
||||
<a href="/wiki/category_preview/id=<?= (int)$category['id'];?>" class="wiki-card-title"><?= htmlspecialchars( $category_name );?></a>
|
||||
</div>
|
||||
<? if ( $category_preview !== '' ):?>
|
||||
<div class="wiki-card-preview"><?= htmlspecialchars( $category_preview );?></div>
|
||||
<? else:?>
|
||||
<div class="wiki-card-preview wiki-card-preview-empty">Brak podglądu treści.</div>
|
||||
<? endif;?>
|
||||
<div class="wiki-card-bottom">
|
||||
<div class="users">
|
||||
<? $category_users = \factory\Wiki::category_users( (int)$category['id'] );?>
|
||||
@@ -77,18 +69,10 @@
|
||||
<? if ( is_array( $this -> categories ) and count( $this -> categories ) ):?>
|
||||
<? foreach ( $this -> categories as $category ):?>
|
||||
<? $category_name = isset( $category['name'] ) ? (string)$category['name'] : '';?>
|
||||
<? $category_text = isset( $category['text'] ) ? strip_tags( (string)$category['text'] ) : '';?>
|
||||
<? $category_preview = trim( $category_text );?>
|
||||
<? if ( strlen( $category_preview ) > 170 ) $category_preview = substr( $category_preview, 0, 170 ) . '...';?>
|
||||
<article class="wiki-card" data-name="<?= htmlspecialchars( strtolower( $category_name ) );?>">
|
||||
<div class="wiki-card-top">
|
||||
<a href="/wiki/category_preview/id=<?= (int)$category['id'];?>" class="wiki-card-title"><?= htmlspecialchars( $category_name );?></a>
|
||||
</div>
|
||||
<? if ( $category_preview !== '' ):?>
|
||||
<div class="wiki-card-preview"><?= htmlspecialchars( $category_preview );?></div>
|
||||
<? else:?>
|
||||
<div class="wiki-card-preview wiki-card-preview-empty">Brak podglądu treści.</div>
|
||||
<? endif;?>
|
||||
</article>
|
||||
<? endforeach;?>
|
||||
<? else:?>
|
||||
@@ -154,21 +138,22 @@
|
||||
|
||||
.wiki-main .wiki-categories-grid {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||
gap: 14px;
|
||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
||||
}
|
||||
|
||||
.wiki-main .wiki-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
gap: 12px;
|
||||
border: 1px solid var(--wiki-border);
|
||||
border-radius: 10px;
|
||||
padding: 12px;
|
||||
padding: 14px;
|
||||
background: #fff;
|
||||
transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
min-height: 96px;
|
||||
}
|
||||
|
||||
.wiki-main .wiki-card:hover {
|
||||
@@ -197,20 +182,6 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.wiki-main .wiki-card-preview {
|
||||
color: var(--wiki-text);
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
min-height: 38px;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.wiki-main .wiki-card-preview-empty {
|
||||
color: var(--wiki-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.wiki-main .wiki-card-bottom {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -271,6 +242,12 @@
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
.wiki-main .wiki-categories-grid {
|
||||
grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
Reference in New Issue
Block a user