diff --git a/dispatcher/migrations/0007_parent_is_productive.py b/dispatcher/migrations/0007_parent_is_productive.py new file mode 100644 index 0000000..31975cd --- /dev/null +++ b/dispatcher/migrations/0007_parent_is_productive.py @@ -0,0 +1,18 @@ +# Generated by Django 5.1.5 on 2025-02-02 16:35 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dispatcher', '0006_alter_parent_project_num'), + ] + + operations = [ + migrations.AddField( + model_name='parent', + name='is_productive', + field=models.BooleanField(default=False), + ), + ] diff --git a/dispatcher/migrations/0008_alter_clocking_in_am_alter_clocking_in_pm_and_more.py b/dispatcher/migrations/0008_alter_clocking_in_am_alter_clocking_in_pm_and_more.py new file mode 100644 index 0000000..c343739 --- /dev/null +++ b/dispatcher/migrations/0008_alter_clocking_in_am_alter_clocking_in_pm_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.1.5 on 2025-02-02 17:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dispatcher', '0007_parent_is_productive'), + ] + + operations = [ + migrations.AlterField( + model_name='clocking', + name='in_am', + field=models.TimeField(default=None, null=True, verbose_name='Clock in AM'), + ), + migrations.AlterField( + model_name='clocking', + name='in_pm', + field=models.TimeField(default=None, null=True, verbose_name='Clock in PM'), + ), + migrations.AlterField( + model_name='clocking', + name='out_am', + field=models.TimeField(default=None, null=True, verbose_name='Clock out AM'), + ), + migrations.AlterField( + model_name='clocking', + name='out_pm', + field=models.TimeField(default=None, null=True, verbose_name='Clock out PM'), + ), + migrations.AlterField( + model_name='parent', + name='project_num', + field=models.CharField(blank=True, max_length=32, verbose_name='Project number'), + ), + ] diff --git a/dispatcher/models.py b/dispatcher/models.py index 18e91f3..3d5df08 100644 --- a/dispatcher/models.py +++ b/dispatcher/models.py @@ -1,8 +1,9 @@ from django.db import models class Parent(models.Model): - project_num = models.CharField(max_length=32, blank=True) + project_num = models.CharField(max_length=32, blank=True, verbose_name="Project number") name = models.CharField(max_length=256) + is_productive = models.BooleanField(default=False) def __str__(self): return self.name @@ -34,8 +35,8 @@ class Task(models.Model): class Clocking(models.Model): date = models.DateField() - in_am = models.TimeField(null=True, default=None) - out_am = models.TimeField(null=True, default=None) - in_pm = models.TimeField(null=True, default=None) - out_pm = models.TimeField(null=True, default=None) + in_am = models.TimeField(null=True, default=None, verbose_name="Clock in AM") + out_am = models.TimeField(null=True, default=None, verbose_name="Clock out AM") + in_pm = models.TimeField(null=True, default=None, verbose_name="Clock in PM") + out_pm = models.TimeField(null=True, default=None, verbose_name="Clock out PM") remote = models.TimeField(null=True, default=None) \ No newline at end of file diff --git a/dispatcher/static/edit.css b/dispatcher/static/edit.css index ec1034f..900767e 100644 --- a/dispatcher/static/edit.css +++ b/dispatcher/static/edit.css @@ -27,4 +27,27 @@ form label { form button { align-self: center; padding: 0.4em 1.2em; +} + +form input[type="checkbox"] { + width: 1.6em; + height: 1.6em; + border: solid var(--light1) 2px; + appearance: none; + background: none; + border-radius: 0; + position: relative; + cursor: pointer; +} + +form input[type="checkbox"]:checked::after { + content: ""; + background-color: #69c935; + width: 80%; + height: 80%; + border-radius: 10%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); } \ No newline at end of file diff --git a/dispatcher/static/list.css b/dispatcher/static/list.css index 5216988..c9ae09d 100644 --- a/dispatcher/static/list.css +++ b/dispatcher/static/list.css @@ -13,6 +13,7 @@ marker: none; gap: 0.8em; border: solid var(--dark4) 1px; + align-items: center; } .list li .actions { diff --git a/dispatcher/static/parents.css b/dispatcher/static/parents.css new file mode 100644 index 0000000..8e91c8e --- /dev/null +++ b/dispatcher/static/parents.css @@ -0,0 +1,3 @@ +.productive { + box-shadow: 0.2em 0 0 #69c935 inset; +} \ No newline at end of file diff --git a/dispatcher/static/table.js b/dispatcher/static/table.js index f74d037..3c046c4 100644 --- a/dispatcher/static/table.js +++ b/dispatcher/static/table.js @@ -127,11 +127,14 @@ class Table { weekTotalCell.colSpan = length } - addProject(id, name, sagexNum, times, isParent=false) { + addProject(id, name, sagexNum, times, isParent=false, isProductive=false) { let row = this.times.insertRow(-1) row.classList.add("project") if (isParent) { row.classList.add("parent") + if (isProductive) { + row.classList.add("productive") + } } row.dataset.id = id row.insertCell(-1).innerText = name @@ -155,11 +158,13 @@ class Table { if (isParent) { row.dataset.total = total - this.totalProjects += total - row.insertCell(-1) - row.insertCell(-1) - row.insertCell(-1) + if (isProductive) { + this.totalProjects += total + } } + row.insertCell(-1) + row.insertCell(-1) + row.insertCell(-1) } addMonth(anchorDate) { @@ -230,7 +235,8 @@ class Table { parent.name, parent.project_num, parentDurations.map(v => v === 0 ? "" : v), - true + true, + parent.is_productive ) projects.forEach(project => { @@ -319,7 +325,7 @@ class Table { console.log("Total projects = 0") return } - this.times.querySelectorAll(".project.parent").forEach(parent => { + this.times.querySelectorAll(".project.parent.productive").forEach(parent => { let total = +parent.dataset.total let workingTimeRatio = total / totalClockings let imputedTimeRatio = total / totalProjects diff --git a/dispatcher/views.py b/dispatcher/views.py index bb12bf5..d2bf874 100644 --- a/dispatcher/views.py +++ b/dispatcher/views.py @@ -70,7 +70,6 @@ def set_parent(request, id): return JsonResponse({"status": "success"}) - def import_view(request): if request.method == "POST": form = ImportForm(request.POST, request.FILES) @@ -168,6 +167,7 @@ def get_table_data(request, start_date: datetime.date, end_date: datetime.date): "id": parent.id, "name": parent.name, "project_num": parent.project_num, + "is_productive": parent.is_productive, "projects": [ { "id": project.id, diff --git a/templates/list.html b/templates/list.html index cf8fd31..c1fda05 100644 --- a/templates/list.html +++ b/templates/list.html @@ -7,7 +7,7 @@ {% block main %}