Update Sprint & Task Management style

This commit is contained in:
2025-07-09 10:43:25 +02:00
committed by Jens Luedicke
parent bd681b5c00
commit 032472a621
6 changed files with 159 additions and 196 deletions

View File

@@ -65,7 +65,7 @@
<div class="category-card" data-category-id="{{ category.id }}">
<div class="category-header" style="background: linear-gradient(135deg, {{ category.color }}20 0%, {{ category.color }}10 100%); border-left: 4px solid {{ category.color }};">
<div class="category-title">
<span class="category-icon">{{ category.icon or '<i class="ti ti-folder"></i>' }}</span>
<span class="category-icon">{{ category.icon|safe if category.icon else '<i class="ti ti-folder"></i>'|safe }}</span>
<span class="category-name">{{ category.name }}</span>
</div>
<div class="category-stats">
@@ -141,7 +141,7 @@
{% if project.category %}
<div class="project-category">
<span class="category-badge" style="background-color: {{ project.category.color }}20; color: {{ project.category.color }};">
{{ project.category.icon or '<i class="ti ti-folder"></i>' }} {{ project.category.name }}
{{ project.category.icon|safe if project.category.icon else '<i class="ti ti-folder"></i>'|safe }} {{ project.category.name }}
</span>
</div>
{% endif %}
@@ -226,7 +226,7 @@
<td>
{% if project.category %}
<span class="category-badge" style="background-color: {{ project.category.color }}20; color: {{ project.category.color }};">
{{ project.category.icon or '<i class="ti ti-folder"></i>' }} {{ project.category.name }}
{{ project.category.icon|safe if project.category.icon else '<i class="ti ti-folder"></i>'|safe }} {{ project.category.name }}
</span>
{% else %}
<span class="text-muted">-</span>

View File

@@ -2,15 +2,25 @@
{% block content %}
<div class="page-container timetrack-container">
<div class="page-header analytics-header">
<h2><i class="ti ti-chart-bar"></i> Time Analytics</h2>
<div class="mode-switcher">
<button class="mode-btn {% if mode == 'personal' %}active{% endif %}"
onclick="switchMode('personal')">Personal</button>
{% if g.user.team_id and g.user.role in [Role.TEAM_LEADER, Role.SUPERVISOR, Role.ADMIN] %}
<button class="mode-btn {% if mode == 'team' %}active{% endif %}"
onclick="switchMode('team')">Team</button>
{% endif %}
<div class="page-header">
<div class="header-content">
<div class="header-left">
<h1 class="page-title">
<span class="page-icon"><i class="ti ti-chart-bar"></i></span>
Time Analytics
</h1>
<p class="page-subtitle">Analyze time tracking data and generate insights</p>
</div>
<div class="header-actions">
<div class="mode-switcher">
<button class="mode-btn {% if mode == 'personal' %}active{% endif %}"
onclick="switchMode('personal')">Personal</button>
{% if g.user.team_id and g.user.role in [Role.TEAM_LEADER, Role.SUPERVISOR, Role.ADMIN] %}
<button class="mode-btn {% if mode == 'team' %}active{% endif %}"
onclick="switchMode('team')">Team</button>
{% endif %}
</div>
</div>
</div>
</div>

View File

@@ -1,43 +1,56 @@
{% extends "layout.html" %}
{% block content %}
<div class="management-container sprint-management-container">
<div class="page-container">
<!-- Header Section -->
<div class="management-header sprint-header">
<h1>🏃‍♂️ Sprint Management</h1>
<div class="management-controls sprint-controls">
<!-- View Switcher -->
<div class="view-switcher">
<button class="view-btn active" data-view="active">Active Sprints</button>
<button class="view-btn" data-view="all">All Sprints</button>
<button class="view-btn" data-view="planning">Planning</button>
<button class="view-btn" data-view="completed">Completed</button>
<div class="page-header">
<div class="header-content">
<div class="header-left">
<h1 class="page-title">
<span class="page-icon"><i class="ti ti-run"></i></span>
Sprint Management
</h1>
<p class="page-subtitle">Manage sprints and track progress</p>
</div>
<!-- Actions -->
<div class="management-actions sprint-actions">
<button id="add-sprint-btn" class="btn btn-primary">+ New Sprint</button>
<button id="refresh-sprints" class="btn btn-secondary">🔄 Refresh</button>
<div class="header-actions">
<button id="refresh-sprints" class="btn btn-secondary">
<i class="ti ti-refresh"></i>
Refresh
</button>
<button id="add-sprint-btn" class="btn btn-primary">
<i class="ti ti-plus"></i>
New Sprint
</button>
</div>
</div>
</div>
<!-- Filter Section -->
<div class="filter-section">
<div class="view-switcher">
<button class="view-btn active" data-view="active">Active Sprints</button>
<button class="view-btn" data-view="all">All Sprints</button>
<button class="view-btn" data-view="planning">Planning</button>
<button class="view-btn" data-view="completed">Completed</button>
</div>
</div>
<!-- Sprint Statistics -->
<div class="management-stats sprint-stats">
<div class="stats-section">
<div class="stat-card">
<div class="stat-number" id="total-sprints">0</div>
<div class="stat-value" id="total-sprints">0</div>
<div class="stat-label">Total Sprints</div>
</div>
<div class="stat-card">
<div class="stat-number" id="active-sprints">0</div>
<div class="stat-value" id="active-sprints">0</div>
<div class="stat-label">Active</div>
</div>
<div class="stat-card">
<div class="stat-number" id="completed-sprints">0</div>
<div class="stat-value" id="completed-sprints">0</div>
<div class="stat-label">Completed</div>
</div>
<div class="stat-card">
<div class="stat-number" id="total-tasks">0</div>
<div class="stat-value" id="total-tasks">0</div>
<div class="stat-label">Total Tasks</div>
</div>
</div>
@@ -112,7 +125,7 @@
<div class="hybrid-date-input">
<input type="date" id="sprint-start-date-native" class="date-input-native" required>
<input type="text" id="sprint-start-date" class="date-input-formatted" required placeholder="{{ "YYYY-MM-DD" if (g.user.preferences.date_format if g.user.preferences else "ISO") == "ISO" else "MM/DD/YYYY" if (g.user.preferences.date_format if g.user.preferences else "ISO") == "US" else "DD/MM/YYYY" if (g.user.preferences.date_format if g.user.preferences else "ISO") in ["EU", "UK"] else "Mon, Dec 25, 2024" }}">
<button type="button" class="calendar-picker-btn" onclick="openCalendarPicker('sprint-start-date')" title="Open calendar">📅</button>
<button type="button" class="calendar-picker-btn" onclick="openCalendarPicker('sprint-start-date')" title="Open calendar"><i class="ti ti-calendar"></i></button>
</div>
<div class="date-error" id="sprint-start-date-error" style="display: none; color: #dc3545; font-size: 0.8rem; margin-top: 0.25rem;"></div>
</div>
@@ -121,7 +134,7 @@
<div class="hybrid-date-input">
<input type="date" id="sprint-end-date-native" class="date-input-native" required>
<input type="text" id="sprint-end-date" class="date-input-formatted" required placeholder="{{ "YYYY-MM-DD" if (g.user.preferences.date_format if g.user.preferences else "ISO") == "ISO" else "MM/DD/YYYY" if (g.user.preferences.date_format if g.user.preferences else "ISO") == "US" else "DD/MM/YYYY" if (g.user.preferences.date_format if g.user.preferences else "ISO") in ["EU", "UK"] else "Mon, Dec 25, 2024" }}">
<button type="button" class="calendar-picker-btn" onclick="openCalendarPicker('sprint-end-date')" title="Open calendar">📅</button>
<button type="button" class="calendar-picker-btn" onclick="openCalendarPicker('sprint-end-date')" title="Open calendar"><i class="ti ti-calendar"></i></button>
</div>
<div class="date-error" id="sprint-end-date-error" style="display: none; color: #dc3545; font-size: 0.8rem; margin-top: 0.25rem;"></div>
</div>
@@ -143,38 +156,23 @@
<!-- Styles -->
<style>
.sprint-management-container {
padding: 1rem;
max-width: 100%;
margin: 0 auto;
}
/* Container styles - using default page spacing */
.sprint-header {
display: flex;
justify-content: space-between;
align-items: center;
/* Header styles handled by common page-header classes */
.filter-section {
margin-bottom: 1.5rem;
flex-wrap: wrap;
gap: 1rem;
}
.sprint-header h1 {
margin: 0;
color: #333;
}
.sprint-controls {
display: flex;
gap: 1rem;
flex-wrap: wrap;
align-items: center;
padding: 1rem;
background: #f8f9fa;
border-radius: 8px;
}
.view-switcher {
display: flex;
background: #f8f9fa;
background: white;
border-radius: 6px;
padding: 2px;
width: fit-content;
}
.view-btn {
@@ -198,37 +196,7 @@
color: #212529;
}
.sprint-actions {
display: flex;
gap: 0.5rem;
}
.sprint-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 1rem;
margin-bottom: 1.5rem;
}
.stat-card {
background: white;
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
text-align: center;
}
.stat-number {
font-size: 2rem;
font-weight: bold;
color: #007bff;
}
.stat-label {
font-size: 0.9rem;
color: #666;
margin-top: 0.25rem;
}
/* Statistics styles handled by common stats-section classes */
.sprint-grid {
display: grid;
@@ -731,7 +699,7 @@ class SprintManager {
</div>
<div class="sprint-dates">
📅 ${formatUserDate(sprint.start_date)} - ${formatUserDate(sprint.end_date)}
<i class="ti ti-calendar"></i> ${formatUserDate(sprint.start_date)} - ${formatUserDate(sprint.end_date)}
${sprint.days_remaining > 0 ? `(${sprint.days_remaining} days left)` : ''}
</div>

View File

@@ -1,51 +1,67 @@
{% extends "layout.html" %}
{% block content %}
<div class="management-container task-management-container">
<div class="page-container">
<!-- Header Section -->
<div class="management-header task-header">
<h1><i class="ti ti-clipboard-list"></i> Task Management</h1>
<div class="management-controls task-controls">
<!-- Smart Search -->
<div class="smart-search-container">
<div class="smart-search-box">
<input type="text" id="smart-search-input" class="smart-search-input" placeholder="Search tasks... (e.g., my-tasks priority:high, project:TimeTrack, overdue)">
<button type="button" class="smart-search-clear" id="smart-search-clear" title="Clear search"><i class="ti ti-x"></i></button>
</div>
<div class="smart-search-suggestions" id="smart-search-suggestions" style="display: none;">
<!-- Suggestions will be populated here -->
</div>
<div class="page-header">
<div class="header-content">
<div class="header-left">
<h1 class="page-title">
<span class="page-icon"><i class="ti ti-clipboard-list"></i></span>
Task Management
</h1>
<p class="page-subtitle">Manage and track all tasks across projects</p>
</div>
<!-- Actions -->
<div class="management-actions task-actions">
<button id="add-task-btn" class="btn btn-primary"><i class="ti ti-plus"></i> Add Task</button>
<button id="refresh-tasks" class="btn btn-secondary"><i class="ti ti-refresh"></i> Refresh</button>
<button id="toggle-archived" class="btn btn-outline" title="Show/Hide Archived Tasks"><i class="ti ti-archive"></i> Show Archived</button>
<div class="header-actions">
<button id="refresh-tasks" class="btn btn-secondary">
<i class="ti ti-refresh"></i>
Refresh
</button>
<button id="toggle-archived" class="btn btn-outline" title="Show/Hide Archived Tasks">
<i class="ti ti-archive"></i>
Show Archived
</button>
<button id="add-task-btn" class="btn btn-primary">
<i class="ti ti-plus"></i>
Add Task
</button>
</div>
</div>
</div>
<!-- Search Section -->
<div class="search-section">
<div class="smart-search-container">
<div class="smart-search-box">
<input type="text" id="smart-search-input" class="smart-search-input" placeholder="Search tasks... (e.g., my-tasks priority:high, project:TimeTrack, overdue)">
<button type="button" class="smart-search-clear" id="smart-search-clear" title="Clear search"><i class="ti ti-x"></i></button>
</div>
<div class="smart-search-suggestions" id="smart-search-suggestions" style="display: none;">
<!-- Suggestions will be populated here -->
</div>
</div>
</div>
<!-- Task Statistics -->
<div class="management-stats task-stats">
<div class="stats-section">
<div class="stat-card">
<div class="stat-number" id="total-tasks">0</div>
<div class="stat-value" id="total-tasks">0</div>
<div class="stat-label">Total Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number" id="completed-tasks">0</div>
<div class="stat-value" id="completed-tasks">0</div>
<div class="stat-label">Completed</div>
</div>
<div class="stat-card">
<div class="stat-number" id="in-progress-tasks">0</div>
<div class="stat-value" id="in-progress-tasks">0</div>
<div class="stat-label">In Progress</div>
</div>
<div class="stat-card">
<div class="stat-number" id="overdue-tasks">0</div>
<div class="stat-value" id="overdue-tasks">0</div>
<div class="stat-label">Overdue</div>
</div>
<div class="stat-card" id="archived-stat-card" style="display: none;">
<div class="stat-number" id="archived-tasks">0</div>
<div class="stat-value" id="archived-tasks">0</div>
<div class="stat-label">Archived</div>
</div>
</div>
@@ -129,12 +145,26 @@
<!-- Styles -->
<style>
/* Header adjustments for Task Management */
.header-actions {
display: flex;
gap: 0.75rem;
align-items: center;
flex-wrap: wrap;
}
/* Search Section */
.search-section {
margin-bottom: 1.5rem;
padding: 1rem;
background: #f8f9fa;
border-radius: 8px;
}
/* Smart Search Styles */
.smart-search-container {
margin-bottom: 1rem;
position: relative;
width: 100%;
flex: 1;
}
.smart-search-box {
@@ -237,71 +267,9 @@
font-size: 0.8rem;
}
/* Task Management Layout */
.task-controls {
display: flex;
gap: 1rem;
align-items: center;
flex-wrap: wrap;
width: 100%;
}
/* Task Management specific styles removed - using common page styles */
.task-controls .smart-search-container {
flex: 1;
min-width: 300px;
max-width: 600px;
margin-bottom: 0; /* Remove margin to align with buttons */
}
.task-controls .management-actions {
flex-shrink: 0;
display: flex;
gap: 0.5rem;
align-items: center;
}
/* Ensure all buttons and search input have same height */
.smart-search-input,
.task-controls .btn {
height: 38px; /* Standard height for consistency */
}
.task-controls .btn {
padding: 0.5rem 1rem;
display: inline-flex;
align-items: center;
justify-content: center;
white-space: nowrap; /* Prevent button text from wrapping */
}
/* Responsive adjustments */
@media (max-width: 992px) {
.task-controls {
flex-direction: column;
align-items: stretch;
}
.task-controls .smart-search-container {
max-width: 100%;
margin-bottom: 0.5rem;
}
.task-controls .management-actions {
justify-content: center;
}
}
@media (max-width: 576px) {
.task-controls .management-actions {
flex-wrap: wrap;
gap: 0.25rem;
}
.task-controls .btn {
font-size: 0.875rem;
padding: 0.4rem 0.8rem;
}
}
/* Responsive adjustments handled by common page styles */
/* Subtask progress styles */
.task-subtasks {
@@ -336,18 +304,6 @@
white-space: nowrap;
}
@media (max-width: 768px) {
.task-controls {
flex-direction: column;
align-items: stretch;
gap: 0.75rem;
}
.task-controls .smart-search-container {
min-width: auto;
max-width: none;
}
}