feat(project_management): Add Project Type to the UI

ref: #294 #295 #300
This commit is contained in:
2024-09-18 00:05:15 +09:30
parent c1aeb3a258
commit 22c6b9d3fe
6 changed files with 340 additions and 1 deletions

View File

@ -0,0 +1,85 @@
from django import forms
from django.urls import reverse
from app import settings
from core.forms.common import CommonModelForm
from project_management.models.project_types import ProjectType
class ProjectTypeForm(CommonModelForm):
class Meta:
fields = '__all__'
model = ProjectType
prefix = 'project_type'
def clean(self):
cleaned_data = super().clean()
return cleaned_data
class DetailForm(ProjectTypeForm):
tabs: dict = {
"details": {
"name": "Details",
"slug": "details",
"sections": [
{
"layout": "double",
"left": [
'organization',
'name',
'runbook',
'c_created',
'c_modified',
],
"right": [
'model_notes',
]
},
]
},
"notes": {
"name": "Notes",
"slug": "notes",
"sections": []
}
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['c_created'] = forms.DateTimeField(
label = 'Created',
input_formats=settings.DATETIME_FORMAT,
disabled = True,
initial = self.instance.created,
)
self.fields['c_modified'] = forms.DateTimeField(
label = 'Modified',
input_formats=settings.DATETIME_FORMAT,
disabled = True,
initial = self.instance.modified,
)
self.tabs['details'].update({
"edit_url": reverse('Settings:_project_type_change', kwargs={'pk': self.instance.pk})
})
self.url_index_view = reverse('Settings:_project_types')

View File

@ -0,0 +1,42 @@
{% extends 'detail.html.j2' %}
{% block additional-stylesheet %}
{% load static %}
<link rel="stylesheet" href="{% static 'ticketing.css' %}">
{% endblock additional-stylesheet %}
{% load json %}
{% load markdown %}
{% block tabs %}
<div id="details" class="content-tab">
{% include 'content/section.html.j2' with tab=form.tabs.details %}
</div>
<div id="tasks" class="content-tab">
{% include 'content/section.html.j2' with tab=form.tabs.tasks %}
</div>
<div id="notes" class="content-tab">
{% include 'content/section.html.j2' with tab=form.tabs.notes %}
{{ notes_form }}
<input type="submit" name="{{notes_form.prefix}}" value="Submit" />
<div class="comments">
{% if notes %}
{% for note in notes %}
{% include 'note.html.j2' %}
{% endfor %}
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,48 @@
{% extends 'base.html.j2' %}
{% block content_header_icon %}{% endblock %}
{% block content %}
<input type="button" value="New Project Type" onclick="window.location='{% url 'Settings:_project_type_add' %}';">
<table class="data">
<tr>
<th>Name</th>
<th>Organization</th>
<th>Created</th>
<th>Modified</th>
<th>&nbsp;</th>
</tr>
{% for project_type in project_types %}
<tr>
<td>
<a href="{% url 'Settings:_project_type_view' pk=project_type.id %}">{{ project_type.name }}</a>
</td>
<td>{% if project_type.is_global %}Global{% else %}{{ project_type.organization }}{% endif %}</td>
<td>{{ project_type.created }}</td>
<td>{{ project_type.modified }}</td>
<td>&nbsp;</td>
</tr>
{% endfor %}
</table>
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
<a href="?page=1">&laquo; first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last &raquo;</a>
{% endif %}
</span>
</div>
{% endblock %}

View File

@ -0,0 +1,157 @@
from datetime import datetime
from django.contrib.auth import decorators as auth_decorator
from django.db.models import Q
from django.urls import reverse
from django.utils.decorators import method_decorator
from access.models import TeamUsers
from core.forms.comment import AddNoteForm
from core.models.notes import Notes
from core.views.common import AddView, ChangeView, DeleteView, DisplayView, IndexView
from project_management.forms.project_types import DetailForm, ProjectType, ProjectTypeForm
from settings.models.user_settings import UserSettings
class Add(AddView):
form_class = ProjectTypeForm
model = ProjectType
permission_required = [
'project_management.add_projecttype',
]
def get_success_url(self, **kwargs):
return reverse('Settings:_project_types')
class Change(ChangeView):
context_object_name = "project_type"
form_class = ProjectTypeForm
model = ProjectType
permission_required = [
'project_management.change_projecttype',
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['content_title'] = self.object.name
return context
def get_success_url(self, **kwargs):
return reverse('Settings:_project_type_view', args=(self.kwargs['pk'],))
class Index(IndexView):
context_object_name = "project_types"
model = ProjectType
paginate_by = 10
permission_required = [
'project_management.view_projecttype'
]
template_name = 'project_management/project_type_index.html.j2'
class View(ChangeView):
context_object_name = "project_type"
form_class = DetailForm
model = ProjectType
permission_required = [
'project_management.view_projecttype',
]
template_name = 'project_management/project_type.html.j2'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['notes_form'] = AddNoteForm(prefix='note')
context['notes'] = Notes.objects.filter(config_group=self.kwargs['pk'])
context['model_pk'] = self.kwargs['pk']
context['model_name'] = self.model._meta.model_name
context['model_delete_url'] = reverse('Settings:_project_type_delete', args=(self.kwargs['pk'],))
context['content_title'] = self.object.name
return context
def post(self, request, *args, **kwargs):
item = KnowledgeBase.objects.get(pk=self.kwargs['pk'])
notes = AddNoteForm(request.POST, prefix='note')
if notes.is_bound and notes.is_valid() and notes.instance.note != '':
notes.instance.organization = item.organization
notes.save()
# dont allow saving any post data outside notes.
# todo: figure out what needs to be returned
# return super().post(request, *args, **kwargs)
def get_success_url(self, **kwargs):
return reverse('Settings:_project_type_view', args=(self.kwargs['pk'],))
class Delete(DeleteView):
model = ProjectType
permission_required = [
'project_management.delete_projecttype',
]
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['content_title'] = 'Delete ' + self.object.name
return context
def get_success_url(self, **kwargs):
return reverse('Settings:_project_types')

View File

@ -79,6 +79,7 @@ div#content article h3 {
<h3>Project Management</h3>
<ul>
<li><a href="{% url 'Settings:_project_states' %}">Project States</a></li>
<li><a href="{% url 'Settings:_project_types' %}">Project Types</a></li>
</ul>
</article>

View File

@ -10,7 +10,7 @@ from itam.views import device_type, device_model, software_category
from itim.views import cluster_types, ports
from project_management.views import project_states
from project_management.views import project_states, project_types
app_name = "Settings"
urlpatterns = [
@ -67,6 +67,12 @@ urlpatterns = [
path("project_state/<int:pk>/edit", project_states.Change.as_view(), name="_project_state_change"),
path("project_state/<int:pk>/delete", project_states.Delete.as_view(), name="_project_state_delete"),
path("project_types", project_types.Index.as_view(), name="_project_types"),
path("project_type/<int:pk>", project_types.View.as_view(), name="_project_type_view"),
path("project_type/add", project_types.Add.as_view(), name="_project_type_add"),
path("project_type/<int:pk>/edit", project_types.Change.as_view(), name="_project_type_change"),
path("project_type/<int:pk>/delete", project_types.Delete.as_view(), name="_project_type_delete"),
path("software_category", software_categories.Index.as_view(), name="_software_categories"),
path("software_category/<int:pk>", software_category.View.as_view(), name="_software_category_view"),
path("software_category/add/", software_category.Add.as_view(), name="_software_category_add"),