From 608498b296ce17e8be118b63e41a2a4ac0a8655d Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Mon, 26 Jul 2021 17:30:38 -0600 Subject: [PATCH 1/4] Add development settings file --- onboard/settings_dev.py | 134 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 onboard/settings_dev.py diff --git a/onboard/settings_dev.py b/onboard/settings_dev.py new file mode 100644 index 0000000..e8b8f9e --- /dev/null +++ b/onboard/settings_dev.py @@ -0,0 +1,134 @@ +""" +Django settings for onboard project. + +Generated by 'django-admin startproject' using Django 3.2.5. + +For more information on this file, see +https://docs.djangoproject.com/en/3.2/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.2/ref/settings/ +""" + +from pathlib import Path + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = 'django-insecure-fdq1(f%l*__obb*zvb3gqnlki!ryr@_1_5om(_2ju3mu70mi4%' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = [] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django.contrib.sites', + 'django.contrib.flatpages', + 'accounts.apps.AccountsConfig', + 'board.apps.BoardConfig', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'onboard.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [BASE_DIR / 'templates'], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'onboard.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': BASE_DIR / 'db.sqlite3', + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.2/topics/i18n/ + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.2/howto/static-files/ + +STATIC_URL = '/static/' +STATICFILES_DIRS = [BASE_DIR / 'static'] + + +# Default primary key field type +# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' + +# Site ID +SITE_ID = 1 \ No newline at end of file From fa98be63fa4de48f528a7732d4d5e3566a8dc3ff Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Tue, 27 Jul 2021 09:48:58 -0600 Subject: [PATCH 2/4] Add basic events --- .../templates/accounts/account_detail.html | 14 ++-- accounts/templates/accounts/profile.html | 54 ++++++++++++++ accounts/views.py | 14 +++- board/admin.py | 2 + board/forms.py | 25 ++++++- board/migrations/0003_auto_20210727_0006.py | 70 +++++++++++++++++++ .../0004_rename_description_event_name.py | 18 +++++ board/models.py | 16 +++++ board/templates/board/employee_detail.html | 24 +++++-- .../templates/board/event_confirm_delete.html | 13 ++++ board/templates/board/event_create_form.html | 16 +++++ board/templates/board/event_detail.html | 17 +++++ board/templates/board/event_form.html | 16 +++++ board/templates/board/event_list.html | 24 +++++++ board/urls.py | 8 +++ board/views.py | 30 +++++++- onboard/middleware.py | 17 +++++ onboard/settings.py | 1 + onboard/settings_dev.py | 3 +- static/styles/main.css | 38 ++++++++-- templates/base.html | 8 +++ 21 files changed, 405 insertions(+), 23 deletions(-) create mode 100644 board/migrations/0003_auto_20210727_0006.py create mode 100644 board/migrations/0004_rename_description_event_name.py create mode 100644 board/templates/board/event_confirm_delete.html create mode 100644 board/templates/board/event_create_form.html create mode 100644 board/templates/board/event_detail.html create mode 100644 board/templates/board/event_form.html create mode 100644 board/templates/board/event_list.html create mode 100644 onboard/middleware.py diff --git a/accounts/templates/accounts/account_detail.html b/accounts/templates/accounts/account_detail.html index 4e6c6e3..0e277e6 100755 --- a/accounts/templates/accounts/account_detail.html +++ b/accounts/templates/accounts/account_detail.html @@ -1,11 +1,13 @@ {% extends 'base.html' %} {% block content %} -
+
+
+

{{ user.email }}

+

+ Update email/change password +

+
+ {% endblock %} diff --git a/accounts/templates/accounts/profile.html b/accounts/templates/accounts/profile.html index 927dec5..acf3d50 100644 --- a/accounts/templates/accounts/profile.html +++ b/accounts/templates/accounts/profile.html @@ -6,5 +6,59 @@

Hi, {{user.first_name}}

+
+

Today, {% now "D, M j" %}

+
+ {% for event in today %} +
+ {{event.date|date:"D, M j"}} + {{event.name}} + {% if event.employee %} for + {{event.employee}} + {% endif %} + + {{event.time|time:"TIME_FORMAT"}} + Edit +
+ {% endfor %} +
+
+

Add event

+
+

Upcoming

+
+ {% for event in upcoming_events %} +
+ {{event.date|date:"D, M j"}} + {{event.name}} + {% if event.employee %} for + {{event.employee}} + {% endif %} + + {{event.time|time:"TIME_FORMAT"}} + Edit +
+ {% endfor %} +
+

See all events

+
+
+

Recent Activity

+ {% regroup latest_activity by created_at.date as latest_activity_re %} + {% for date in latest_activity_re %} +
{{date.grouper|date:"D, M j"}}
+ {% for entry in date.list %} +

+ {{entry.notes}} + for + {{entry.employee}} +

+ {% endfor %} + {% endfor %} +
{% endblock %} + + + + diff --git a/accounts/views.py b/accounts/views.py index b13a258..1d0ffad 100755 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,5 +1,6 @@ import pytz from django.utils import timezone +from datetime import date, timedelta from django.shortcuts import render, reverse, redirect from django.urls import reverse_lazy from django.views.generic.base import TemplateView @@ -12,14 +13,25 @@ from django.contrib.auth.models import User from .models import Profile from .forms import AccountUpdateForm, ProfileUpdateForm +from board.models import LogEntry, Event + class ProfileView(LoginRequiredMixin, TemplateView): template_name = 'accounts/profile.html' def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) + today = date.today() + tomorrow = today + timedelta(days=1) + enddate = today + timedelta(days=6) context['profile'] = self.request.user.profile - + context['latest_activity'] = LogEntry.objects.all()[:10] + context['today'] = Event.objects.filter( + date=today + ) + context['upcoming_events'] = Event.objects.filter( + date__range=[tomorrow, enddate] + ) return context class ProfileUpdateView(LoginRequiredMixin, UpdateView): diff --git a/board/admin.py b/board/admin.py index fa58b84..2bbcd67 100644 --- a/board/admin.py +++ b/board/admin.py @@ -4,8 +4,10 @@ from .models import ( Employee, LogEntry, Todo, + Event, ) admin.site.register(Employee) admin.site.register(LogEntry) admin.site.register(Todo) +admin.site.register(Event) diff --git a/board/forms.py b/board/forms.py index d32ebe2..0305e3c 100644 --- a/board/forms.py +++ b/board/forms.py @@ -1,6 +1,7 @@ from datetime import datetime from django import forms -from .models import Employee, LogEntry, Todo +from django.utils import timezone +from .models import Employee, LogEntry, Todo, Event from .regex import process_regex class EmployeePreCreateForm(forms.Form): @@ -89,3 +90,25 @@ class TodoCreateForm(forms.ModelForm): 'autofocus': 'autofocus' }) } + +class EventForm(forms.ModelForm): + class Meta: + model = Event + fields = ( + 'name', + 'date', + 'time', + 'employee', + ) + widgets = { + 'name': forms.TextInput(attrs = { + 'autofocus': 'autofocus' + }), + 'date': forms.DateInput(attrs = { + 'type': 'date', + 'value': timezone.now().date(), + }), + 'time': forms.DateInput(attrs = { + 'type': 'time', + }), + } diff --git a/board/migrations/0003_auto_20210727_0006.py b/board/migrations/0003_auto_20210727_0006.py new file mode 100644 index 0000000..07ee0d7 --- /dev/null +++ b/board/migrations/0003_auto_20210727_0006.py @@ -0,0 +1,70 @@ +# Generated by Django 3.2.5 on 2021-07-27 00:06 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('board', '0002_auto_20210709_0103'), + ] + + operations = [ + migrations.AlterModelOptions( + name='employee', + options={'ordering': ('-hire_date',)}, + ), + migrations.AlterModelOptions( + name='logentry', + options={'ordering': ('-created_at',)}, + ), + migrations.AlterField( + model_name='employee', + name='department', + field=models.CharField(blank=True, max_length=64, null=True), + ), + migrations.AlterField( + model_name='employee', + name='first_name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='employee', + name='last_name', + field=models.CharField(max_length=64), + ), + migrations.AlterField( + model_name='employee', + name='manager', + field=models.CharField(blank=True, max_length=64, null=True), + ), + migrations.AlterField( + model_name='employee', + name='title', + field=models.CharField(blank=True, max_length=64, null=True), + ), + migrations.AlterField( + model_name='logentry', + name='notes', + field=models.CharField(max_length=500), + ), + migrations.AlterField( + model_name='todo', + name='description', + field=models.CharField(max_length=64), + ), + migrations.CreateModel( + name='Event', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('description', models.CharField(max_length=64)), + ('date', models.DateField()), + ('time', models.TimeField(blank=True, null=True)), + ('employee', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='board.employee')), + ], + options={ + 'ordering': ('date', 'time'), + }, + ), + ] diff --git a/board/migrations/0004_rename_description_event_name.py b/board/migrations/0004_rename_description_event_name.py new file mode 100644 index 0000000..dc8a6d3 --- /dev/null +++ b/board/migrations/0004_rename_description_event_name.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.5 on 2021-07-27 01:53 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('board', '0003_auto_20210727_0006'), + ] + + operations = [ + migrations.RenameField( + model_name='event', + old_name='description', + new_name='name', + ), + ] diff --git a/board/models.py b/board/models.py index 1d3ac53..b56eeba 100644 --- a/board/models.py +++ b/board/models.py @@ -57,3 +57,19 @@ class Todo(models.Model): def get_absolute_url(self): return reverse('todo-detail', kwargs={'pk': self.employee.pk, 'todo_pk': self.pk}) + + +class Event(models.Model): + class Meta: + ordering = ('date', 'time') + + name = models.CharField(max_length=64) + date = models.DateField() + time = models.TimeField(blank=True, null=True) + employee = models.ForeignKey(Employee, on_delete=models.CASCADE, blank=True, null=True) + + def __str__(self): + return f"{self.description} on {self.date} @ {self.time}" + + def get_absolute_url(self): + return reverse('event-detail', kwargs={'pk': self.pk}) diff --git a/board/templates/board/employee_detail.html b/board/templates/board/employee_detail.html index 4874dd1..f5eb452 100644 --- a/board/templates/board/employee_detail.html +++ b/board/templates/board/employee_detail.html @@ -31,6 +31,17 @@

Initial comments:

{{employee.initial_comments|linebreaksbr}}
+
+

Employee Events

+ {% for event in employee.event_set.all %} +
+ {{event.date|date:"D, M j"}} + {{event.name}} + {{event.time|time:"TIME_FORMAT"}} + Edit +
+ {% endfor %} +

To-do's

{% include "board/todo_list.html" with todo_list=employee.todo_set.all %} @@ -45,11 +56,14 @@

Add an Entry

- {% for entry in employee.logentry_set.all %} -

- {{entry.created_at|date:"SHORT_DATE_FORMAT"}}— - {{entry.notes}} -

+ {% regroup employee.logentry_set.all by created_at.date as activity %} + {% for date in activity %} +
{{date.grouper|date:"D, M j"}}
+ {% for entry in date.list %} +

+ {{entry.created_at|time:"H:i"}} + {{entry.notes}}

+ {% endfor %} {% endfor %}
diff --git a/board/templates/board/event_confirm_delete.html b/board/templates/board/event_confirm_delete.html new file mode 100644 index 0000000..831a651 --- /dev/null +++ b/board/templates/board/event_confirm_delete.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% block content %} +
+

Delete {{event}}

+
+ {% csrf_token %} +

+ or cancel +

+
+
+{% endblock %} \ No newline at end of file diff --git a/board/templates/board/event_create_form.html b/board/templates/board/event_create_form.html new file mode 100644 index 0000000..698740d --- /dev/null +++ b/board/templates/board/event_create_form.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} +
+

Create Event

+
+
+ {% csrf_token %} + {{form.as_p}} +

+ or cancel +

+
+
+
+{% endblock %} \ No newline at end of file diff --git a/board/templates/board/event_detail.html b/board/templates/board/event_detail.html new file mode 100644 index 0000000..c1934b8 --- /dev/null +++ b/board/templates/board/event_detail.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block content %} +
+

Event

+
+
+ {{event.name}} + {% if event.employee %} for + {{event.employee}} + {% endif %} + + {{event.time|time:"TIME_FORMAT"}} +
+
+
+{% endblock %} \ No newline at end of file diff --git a/board/templates/board/event_form.html b/board/templates/board/event_form.html new file mode 100644 index 0000000..5ca737b --- /dev/null +++ b/board/templates/board/event_form.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block content %} +
+

Update Event

+
+
+ {% csrf_token %} + {{form.as_p}} +

+ or cancel +

+
+
+
+{% endblock %} \ No newline at end of file diff --git a/board/templates/board/event_list.html b/board/templates/board/event_list.html new file mode 100644 index 0000000..5e8efb0 --- /dev/null +++ b/board/templates/board/event_list.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block content %} +
+

Schedule

+

Add event

+
+ {% for event in event_list %} +
+ {{event.date|date:"D, M j"}} + {{event.name}} + {% if event.employee %} for + {{event.employee}} + {% endif %} + + {{event.time|time:"TIME_FORMAT"}} + Edit +
+ {% empty %} +

There are no events yet.

+ {% endfor %} +
+
+{% endblock %} diff --git a/board/urls.py b/board/urls.py index 0da3ec1..0ac94c6 100644 --- a/board/urls.py +++ b/board/urls.py @@ -32,4 +32,12 @@ urlpatterns = [ ])), ])), + + path('events/', views.EventListView.as_view(), name='event-list'), + path('events/new/', views.EventCreateView.as_view(), name='event-create'), + path('events//', include([ + path('', views.EventDetailView.as_view(), name='event-detail'), + path('update/', views.EventUpdateView.as_view(), name='event-update'), + path('delete/', views.EventDeleteView.as_view(), name='event-delete'), + ])), ] diff --git a/board/views.py b/board/views.py index d0be241..0cbd418 100644 --- a/board/views.py +++ b/board/views.py @@ -7,14 +7,15 @@ from django.views.generic.list import ListView from django.contrib.auth.mixins import LoginRequiredMixin from django.db.models import Q -from .models import Employee, LogEntry, Todo +from .models import Employee, LogEntry, Todo, Event from .forms import ( EmployeeForm, EmployeePreCreateForm, EmployeeArchiveForm, LogEntryForm, TodoForm, - TodoCreateForm + TodoCreateForm, + EventForm, ) class SearchResultsView(ListView): @@ -170,4 +171,27 @@ class TodoDeleteView(LoginRequiredMixin, DeleteView): return reverse('todo-deleted', kwargs={'pk': self.kwargs['pk']}) class TodoDeleteDoneView(LoginRequiredMixin, TemplateView): - template_name = 'board/item_deleted.html' \ No newline at end of file + template_name = 'board/item_deleted.html' + + +# Events +class EventListView(LoginRequiredMixin, ListView): + model = Event + +class EventCreateView(LoginRequiredMixin, CreateView): + model = Event + template_name_suffix = '_create_form' + form_class = EventForm + success_url = reverse_lazy('profile-detail') + +class EventDetailView(LoginRequiredMixin, DetailView): + model = Event + +class EventUpdateView(LoginRequiredMixin, UpdateView): + model = Event + form_class = EventForm + +class EventDeleteView(LoginRequiredMixin, DeleteView): + model = Event + success_url = reverse_lazy('profile-detail') + diff --git a/onboard/middleware.py b/onboard/middleware.py new file mode 100644 index 0000000..8260705 --- /dev/null +++ b/onboard/middleware.py @@ -0,0 +1,17 @@ +import pytz + +from django.utils import timezone + +class TimezoneMiddleware: + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + tzname = request.session.get('timezone') + if request.user.is_authenticated: + tzname = request.user.profile.timezone + if tzname: + timezone.activate(pytz.timezone(tzname)) + else: + timezone.deactivate() + return self.get_response(request) diff --git a/onboard/settings.py b/onboard/settings.py index 6d2e0bb..086bd93 100644 --- a/onboard/settings.py +++ b/onboard/settings.py @@ -53,6 +53,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'onboard.middleware.TimezoneMiddleware', ] ROOT_URLCONF = 'onboard.urls' diff --git a/onboard/settings_dev.py b/onboard/settings_dev.py index e8b8f9e..8e9fb55 100644 --- a/onboard/settings_dev.py +++ b/onboard/settings_dev.py @@ -25,7 +25,7 @@ SECRET_KEY = 'django-insecure-fdq1(f%l*__obb*zvb3gqnlki!ryr@_1_5om(_2ju3mu70mi4% # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True -ALLOWED_HOSTS = [] +ALLOWED_HOSTS = ['localhost', '127.0.0.1', 'xcarbon.lan'] # Application definition @@ -51,6 +51,7 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'onboard.middleware.TimezoneMiddleware', ] ROOT_URLCONF = 'onboard.urls' diff --git a/static/styles/main.css b/static/styles/main.css index 07c66e4..a82652e 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -2,7 +2,7 @@ --white: #fdfdff; --black: #393d3f; --grey: #a7b4bb; - --blue: #2288a2; + --blue: #10638c; } html { @@ -63,7 +63,7 @@ blockquote { border-left: 2px solid var(--blue); } -header { +body > header { padding: 1rem; } @@ -95,6 +95,7 @@ article { .navbar__mobile { display: none; + font-weight: 900; } .navbar__menu { @@ -203,6 +204,8 @@ article { /* FORMS */ input[type=text]:not([name=description]), input[type=number], +input[type=date], +input[type=time], input[type=password], input[type=search], textarea, select { @@ -223,10 +226,6 @@ input[name=description] { box-sizing: border-box; } -input:focus, textarea:focus, select:focus { - border-color: var(--blue); -} - input[type=radio], input[type=checkbox] { cursor: pointer; width: 1.5rem; @@ -256,6 +255,10 @@ li label { display: inline-block; } +input:focus, textarea:focus, select:focus { + border-color: var(--blue) !important; +} + @@ -300,4 +303,27 @@ hgroup { right: 0; text-align: left; } +} + + + +.log_entry { + display: grid; + grid-template-columns: 1fr 2fr 1fr; + column-gap: 0.5rem; + margin-bottom: 1rem; +} + +.log_entry--employee { + grid-template-columns: 1fr auto; +} + + +.today__event { + display: grid; + grid-template-columns: 1fr 2fr 0.5fr 0.5fr; + column-gap: 1rem; + margin-bottom: 2rem; + padding-bottom: 0.5rem; + border-bottom: 0.046rem solid var(--grey); } \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 61f2fc5..4e7d227 100644 --- a/templates/base.html +++ b/templates/base.html @@ -26,6 +26,8 @@ {% else %} + OnBoard {% endif %} @@ -51,12 +54,17 @@
+
Today
+
+
Events
+
Employees

Logout
{% else %} + OnBoard {% endif %} From 391fe5c42aab5d9edf6540e80df7c93f1c917b5c Mon Sep 17 00:00:00 2001 From: Nathan Chapman Date: Wed, 28 Jul 2021 18:10:07 -0600 Subject: [PATCH 3/4] Add basic event system --- accounts/templates/accounts/profile.html | 12 ++++++---- board/templates/board/employee_detail.html | 8 ++++--- board/templates/board/employee_list.html | 3 ++- board/templates/board/event_create_form.html | 2 +- board/templates/board/event_form.html | 2 +- board/templates/board/event_list.html | 17 +++++++++++++ .../board/logentry_confirm_delete.html | 4 ++-- board/templates/board/logentry_form.html | 19 +++++++++++---- board/views.py | 12 ++++++++-- onboard/settings.py | 24 +++++++++---------- static/styles/main.css | 22 ++++++++++++++--- templates/base.html | 5 +--- 12 files changed, 91 insertions(+), 39 deletions(-) diff --git a/accounts/templates/accounts/profile.html b/accounts/templates/accounts/profile.html index acf3d50..9a54ced 100644 --- a/accounts/templates/accounts/profile.html +++ b/accounts/templates/accounts/profile.html @@ -25,7 +25,7 @@

Add event

-

Upcoming

+

Upcoming (next seven days)

{% for event in upcoming_events %}
@@ -49,9 +49,13 @@
{{date.grouper|date:"D, M j"}}
{% for entry in date.list %}

- {{entry.notes}} - for - {{entry.employee}} + {{entry.created_at|time:"TIME_FORMAT"}} + + {{entry.notes}} + for + {{entry.employee}} + + Edit

{% endfor %} {% endfor %} diff --git a/board/templates/board/employee_detail.html b/board/templates/board/employee_detail.html index f5eb452..4f57e28 100644 --- a/board/templates/board/employee_detail.html +++ b/board/templates/board/employee_detail.html @@ -60,9 +60,11 @@ {% for date in activity %}
{{date.grouper|date:"D, M j"}}
{% for entry in date.list %} -

- {{entry.created_at|time:"H:i"}} - {{entry.notes}}

+

+ {{entry.created_at|time:"TIME_FORMAT"}} + {{entry.notes}} + Edit +

{% endfor %} {% endfor %}
diff --git a/board/templates/board/employee_list.html b/board/templates/board/employee_list.html index ac68ece..13f37a0 100644 --- a/board/templates/board/employee_list.html +++ b/board/templates/board/employee_list.html @@ -8,7 +8,8 @@ {% for employee in employee_list %}

{{employee.full_name}}
- Hire date: {{employee.hire_date|date:"SHORT_DATE_FORMAT"}} + Hire date: {{employee.hire_date|date:"SHORT_DATE_FORMAT"}}
+ Department: {{employee.department}}

{% endfor %} diff --git a/board/templates/board/event_create_form.html b/board/templates/board/event_create_form.html index 698740d..aaa0dfc 100644 --- a/board/templates/board/event_create_form.html +++ b/board/templates/board/event_create_form.html @@ -8,7 +8,7 @@ {% csrf_token %} {{form.as_p}}

- or cancel + or cancel

diff --git a/board/templates/board/event_form.html b/board/templates/board/event_form.html index 5ca737b..4cd0c9c 100644 --- a/board/templates/board/event_form.html +++ b/board/templates/board/event_form.html @@ -8,7 +8,7 @@ {% csrf_token %} {{form.as_p}}

- or cancel + or cancel

diff --git a/board/templates/board/event_list.html b/board/templates/board/event_list.html index 5e8efb0..50110fc 100644 --- a/board/templates/board/event_list.html +++ b/board/templates/board/event_list.html @@ -20,5 +20,22 @@

There are no events yet.

{% endfor %} +
+ + {% if page_obj.has_previous %} + « first + previous + {% endif %} + + + Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. + + + {% if page_obj.has_next %} + next + last » + {% endif %} + +
{% endblock %} diff --git a/board/templates/board/logentry_confirm_delete.html b/board/templates/board/logentry_confirm_delete.html index 7aae8ca..8eb1b92 100644 --- a/board/templates/board/logentry_confirm_delete.html +++ b/board/templates/board/logentry_confirm_delete.html @@ -3,10 +3,10 @@ {% block content %}

Delete {{logentry}}

-
+ {% csrf_token %}

- or cancel + or cancel

diff --git a/board/templates/board/logentry_form.html b/board/templates/board/logentry_form.html index b35e99a..0708d6a 100644 --- a/board/templates/board/logentry_form.html +++ b/board/templates/board/logentry_form.html @@ -2,9 +2,18 @@ {% block content %}
-

-
- -
-
+
+

Update Event

+

Delete this entry

+
+
+
+ {% csrf_token %} + {{form.as_p}} +

+ or cancel +

+
+
+ {% endblock %} \ No newline at end of file diff --git a/board/views.py b/board/views.py index 0cbd418..dc4ccce 100644 --- a/board/views.py +++ b/board/views.py @@ -118,7 +118,14 @@ class LogEntryUpdateView(LoginRequiredMixin, UpdateView): class LogEntryDeleteView(LoginRequiredMixin, DeleteView): model = LogEntry pk_url_kwarg = 'entry_pk' - success_url = reverse_lazy('entry-list') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['employee'] = Employee.objects.get(pk=self.kwargs['pk']) + return context + + def get_success_url(self): + return reverse('employee-detail', kwargs={'pk': self.kwargs['pk']}) # Todos @@ -177,6 +184,8 @@ class TodoDeleteDoneView(LoginRequiredMixin, TemplateView): # Events class EventListView(LoginRequiredMixin, ListView): model = Event + paginate_by = 100 + ordering = ('-date', '-time') class EventCreateView(LoginRequiredMixin, CreateView): model = Event @@ -194,4 +203,3 @@ class EventUpdateView(LoginRequiredMixin, UpdateView): class EventDeleteView(LoginRequiredMixin, DeleteView): model = Event success_url = reverse_lazy('profile-detail') - diff --git a/onboard/settings.py b/onboard/settings.py index 086bd93..a0775c0 100644 --- a/onboard/settings.py +++ b/onboard/settings.py @@ -25,7 +25,7 @@ with open('/etc/secret_key.txt') as f: SECRET_KEY = f.read().strip() # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.environ.get('DJANGO_DEBUG', '') != 'False' +DEBUG = False ALLOWED_HOSTS = ['onboard.windmillapps.org', '127.0.0.1'] @@ -53,7 +53,6 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'onboard.middleware.TimezoneMiddleware', ] ROOT_URLCONF = 'onboard.urls' @@ -127,10 +126,11 @@ USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.2/howto/static-files/ - +STATICFILES_DIRS = [ + BASE_DIR / 'static' + ] STATIC_URL = '/static/' -STATIC_ROOT = [BASE_DIR / 'static/'] -STATICFILES_DIRS = [BASE_DIR / 'static'] +STATIC_ROOT = '/var/www/onboard.windmillapps.org/static/' # Default primary key field type @@ -163,7 +163,7 @@ LOGGING = { # Email ANYMAIL = { - "MAILGUN_API_KEY": os.environ.get('MAILGUN_API_KEY'), + "MAILGUN_API_KEY": "key-b65d1f9e486825a7d01d099fd3062c2b", } SERVER_EMAIL = 'noreply@onboard.windmillapps.org' @@ -174,10 +174,8 @@ ADMINS = ( ) MANAGERS = ADMINS -EMAIL_BACKEND = os.environ.get('EMAIL_BACKEND') - - -SECURE_HSTS_SECONDS = os.environ.get('DJANGO_SECURE_HSTS_SECONDS', '') != 'False' -SECURE_SSL_REDIRECT = os.environ.get('DJANGO_SECURE_SSL_REDIRECT', '') != 'False' -SESSION_COOKIE_SECURE = os.environ.get('DJANGO_SESSION_COOKIE_SECURE', '') != 'False' -CSRF_COOKIE_SECURE = os.environ.get('DJANGO_CSRF_COOKIE_SECURE', '') != 'False' \ No newline at end of file +EMAIL_BACKEND = 'anymail.backends.mailgun.EmailBackend' +SECURE_HSTS_SECONDS = True +SECURE_SSL_REDIRECT = True +SESSION_COOKIE_SECURE = True +CSRF_COOKIE_SECURE = True diff --git a/static/styles/main.css b/static/styles/main.css index a82652e..0e037c5 100644 --- a/static/styles/main.css +++ b/static/styles/main.css @@ -1,8 +1,9 @@ :root { - --white: #fdfdff; + --white: #f8f8fb; --black: #393d3f; --grey: #a7b4bb; --blue: #10638c; + --red: #8c1016; } html { @@ -98,9 +99,11 @@ article { font-weight: 900; } -.navbar__menu { - +.navbar__mobile .menu__items { + text-align: center; } + + .navbar__menu_title { font-weight: 900; padding: 0.2rem 1rem; @@ -200,6 +203,10 @@ article { text-decoration: none; } +.action-button--danger { + background-color: var(--red); +} + /* FORMS */ input[type=text]:not([name=description]), @@ -326,4 +333,13 @@ hgroup { margin-bottom: 2rem; padding-bottom: 0.5rem; border-bottom: 0.046rem solid var(--grey); +} + + + +.activity__item { + display: grid; + grid-template-columns: 0.25fr 2fr 0.25fr; + column-gap: 0.5rem; + margin-bottom: 1rem; } \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 4e7d227..9ec42f9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -27,7 +27,6 @@