Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Position Postings #572

Closed
wants to merge 8 commits into from
Closed
4 changes: 4 additions & 0 deletions events/views/indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from events.models import BaseEvent, Workshop, CrewAttendanceRecord
from helpers.challenges import is_officer
from pages.models import OnboardingScreen, OnboardingRecord
from positions.models import Position


# FRONT 3 PAGES
Expand Down Expand Up @@ -80,6 +81,9 @@ def admin(request, msg=None):
datetime_end__gte=(now - datetime.timedelta(hours=3))).distinct()
context['selfcrew_events'] = selfcrew_events

open_positions = Position.objects.filter(closes__gte=datetime.datetime.now()).count()
context['open_positions'] = open_positions

return render(request, 'admin.html', context)


Expand Down
1 change: 1 addition & 0 deletions lnldb/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def from_runtime(*x):
'api',
'rt',
'slack',
'positions',

'bootstrap3',
'crispy_forms',
Expand Down
1 change: 1 addition & 0 deletions lnldb/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
url(r'^mdm/', include(('devices.urls.mdm', 'mdm'), namespace="mdm")),
url(r'^support/', include(('rt.urls', 'support'), namespace='support')),
url(r'', include(('pages.urls', 'pages'), namespace='pages')),
url(r'^db/positions/', include('positions.urls', 'positions')),

# special urls
url(r'^db/$', db_home, name="home"),
Expand Down
Empty file added positions/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions positions/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.contrib import admin

from .models import Position

# Register your models here.

admin.site.register(Position)
6 changes: 6 additions & 0 deletions positions/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class PositionsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'positions'
14 changes: 14 additions & 0 deletions positions/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from django import forms
from .models import Position
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Submit

class UpdateCreatePosition(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.add_input(Submit('submit', 'Submit'))
class Meta:
model = Position
fields = ('name', 'description', 'position_start', 'position_end',
'closes', 'reports_to', 'application_form')
28 changes: 28 additions & 0 deletions positions/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.1.13 on 2021-11-03 20:49

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Position',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32, verbose_name='Position Name')),
('description', models.TextField(verbose_name='Position Description')),
('position_start', models.DateField(verbose_name='Term Start')),
('position_end', models.DateField(verbose_name='Term End')),
('reports_to', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]
37 changes: 37 additions & 0 deletions positions/migrations/0002_auto_20211104_1125.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 3.1.13 on 2021-11-04 15:25

import datetime
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('positions', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='position',
name='application_form',
field=models.CharField(default='', max_length=128, verbose_name='Link to external application form'),
preserve_default=False,
),
migrations.AddField(
model_name='position',
name='closes',
field=models.DateTimeField(default=datetime.datetime.now, verbose_name='Applications Close'),
preserve_default=False,
),
migrations.CreateModel(
name='ApplicationInstance',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('applicant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
('position', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='positions.position')),
],
),
]
23 changes: 23 additions & 0 deletions positions/migrations/0003_auto_20211111_1309.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 3.1.13 on 2021-11-11 18:09

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('positions', '0002_auto_20211104_1125'),
]

operations = [
migrations.AlterField(
model_name='position',
name='closes',
field=models.DateField(blank=True, null=True, verbose_name='Applications Close'),
),
migrations.AlterField(
model_name='position',
name='name',
field=models.CharField(max_length=64, verbose_name='Position Name'),
),
]
21 changes: 21 additions & 0 deletions positions/migrations/0004_auto_20211111_1419.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 3.1.13 on 2021-11-11 19:19

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('positions', '0003_auto_20211111_1309'),
]

operations = [
migrations.AlterField(
model_name='position',
name='reports_to',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
]
17 changes: 17 additions & 0 deletions positions/migrations/0005_auto_20211112_1115.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.1.13 on 2021-11-12 16:15

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('positions', '0004_auto_20211111_1419'),
]

operations = [
migrations.AlterModelOptions(
name='position',
options={'permissions': [('apply', 'Can apply for positions')]},
),
]
16 changes: 16 additions & 0 deletions positions/migrations/0006_delete_applicationinstance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Generated by Django 3.1.13 on 2021-11-12 17:00

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('positions', '0005_auto_20211112_1115'),
]

operations = [
migrations.DeleteModel(
name='ApplicationInstance',
),
]
Empty file.
37 changes: 37 additions & 0 deletions positions/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from django.db import models
from django.contrib.auth import get_user_model

import datetime

# Create your models here.

class Position(models.Model):
"""
Describes a leadership position for a specific time. A new position instance
should be created every time one needs to be filled.
"""
name = models.CharField(verbose_name="Position Name", max_length=64,
null=False, blank=False)
description = models.TextField(verbose_name="Position Description",
null=False, blank=False)
position_start = models.DateField(verbose_name="Term Start", null=False,
blank=False)
position_end = models.DateField(verbose_name="Term End", null=False,
blank=False)
reports_to = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,
blank=True, null=True)
closes = models.DateField(verbose_name="Applications Close", null=True,
blank=True)
application_form = models.CharField(verbose_name="Link to external application form", null=False, blank=False, max_length=128)

def __str__(self):
return f"{self.name}"

class Meta:
permissions = [
('apply', 'Can apply for positions')
]

def is_open(self):
return self.closes >= datetime.datetime.now()

3 changes: 3 additions & 0 deletions positions/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
12 changes: 12 additions & 0 deletions positions/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from django.urls import path

from . import views

app_name="positions"

urlpatterns = [
path('create/', views.CreatePosition.as_view(), name="create"),
path('list/', views.ListPositions.as_view(), name="list"),
path('detail/<int:pk>', views.ViewPosition.as_view(), name="detail"),
path('detail/<int:pk>/edit', views.UpdatePosition.as_view(), name="update"),
]
41 changes: 41 additions & 0 deletions positions/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
from django.shortcuts import render
from django.views import generic
from django.urls import reverse
import datetime

from .models import Position
from .forms import UpdateCreatePosition

from django.contrib.auth.mixins import PermissionRequiredMixin, LoginRequiredMixin

# Create your views here.

class CreatePosition(generic.CreateView, PermissionRequiredMixin, LoginRequiredMixin):
model = Position
form_class = UpdateCreatePosition
template_name="form_crispy_cbv.html"
permission_required="positions.add_position"

def get_success_url(self):
return reverse("accounts:me")

class UpdatePosition(generic.UpdateView, PermissionRequiredMixin, LoginRequiredMixin):
model = Position
template_name="form_crispy_cbv.html"
permission_required="positions.change_position"
form_class = UpdateCreatePosition

def get_success_url(self):
return reverse("positions:detail", args=[self.object.id])

class ListPositions(generic.ListView, PermissionRequiredMixin, LoginRequiredMixin):
model = Position
queryset = Position.objects.filter(closes__gte=datetime.datetime.now())
fields = ('name', 'position_start', 'position_end', 'closes')
template_name = 'position_list.html'
permission_required = "positions.apply"

class ViewPosition(generic.DetailView, PermissionRequiredMixin, LoginRequiredMixin):
model = Position
template_name = "position_detail.html"
permission_required = "positions.apply"
12 changes: 12 additions & 0 deletions site_tmpl/admin.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ <h2>Welcome to the LNL Database</h2>
</table>
</div>
</div><!--/row-->
<div class="divider"></div>
<br>
{% if open_positions >= 1 %}
{% permission request.user has 'positions.apply' %}
<div class="container">
<div class="alert alert-info">There {% if open_positions == 1 %}is {% else %}are {% endif %}{{ open_positions }}
open position{{ open_positions|pluralize }} available!
Check out our <a href="{% url 'positions:list' %}">list
</a> for more information</div>
</div>
{% endpermission %}
{% endif %}
<hr>
{% endblock %}

9 changes: 9 additions & 0 deletions site_tmpl/admin.nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,15 @@
<li><a href="{% url "emails:dispatch" %}">Send Message...</a></li>
<li class="divider"></li>
{% endpermission %}
{% permission request.user has 'positions.apply' or request.user has 'positions.add_position' %}
<li><a href="{% url "positions:list" %}">Open
Positions</a></li>
{% permission request.user has 'positions.add_position' %}
<li><a href="{% url "positions:create" %}">Add
Position</a></li>
{% endpermission %}
<li class="divider"></li>
{% endpermission %}
{% permission request.user has 'events.view_attendance_records' %}
<li><a href="{% url "events:crew-logs" %}">Crew Logs</a></li>
{% endpermission %}
Expand Down
40 changes: 40 additions & 0 deletions site_tmpl/position_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{% extends 'base_admin.html' %}
{% load permissionif %}

{% block content %}
<div class="jumbotron">
<div class="clearfix">
<h1>{{ object }}</h1>
<h2>Term: {{ object.position_start}} through {{object.position_end}}</h2>
</div>
{% permission user has 'positions.change_position' %}
<a class="btn btn-lg btn-primary" href="{% url 'positions:update' object.id %}">Edit</a>
{% endpermission %}
<a class="btn btn-lg btn-success" href="{{ object.application_form }}">Apply</a>
</div>

<table class="table">
<tr>
<th>Description</th>
<td>{{ object.description }}</td>
</tr>
<tr>
<th>Term Start</th>
<td>{{ object.position_start }}</td>
</tr>
<tr>
<th>Term End</th>
<td>{{ object.position_end }}</td>
</tr>
<tr>
<th>Reports To</th>
<td><a href="{% url 'accounts:detail' object.reports_to.id %}">{{ object.reports_to }}</a></td>
</tr>
<tr>
<th>Applications Close</th>
<td>{% if object.closes %}{{ object.closes }}{% else %}Doesn't
close{% endif %}</td>
</tr>
</table>

{% endblock %}
Loading