Skip to content

Commit

Permalink
adds TODOs code scanner tool for Admin Tools
Browse files Browse the repository at this point in the history
  • Loading branch information
jontsai committed Apr 26, 2024
1 parent 82be588 commit 88e33a5
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 0 deletions.
3 changes: 3 additions & 0 deletions admintools/constants/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@
HTK_COMPANY_EMPLOYEE_EMAILS = ()

HTK_EMULATE_USER_COOKIE_EXPIRATION_MINUTES = 15

# See: `htk.admintools.dataclasses.TodosConfig`
HTK_ADMINTOOLS_TODOS_CONFIGS = []
24 changes: 24 additions & 0 deletions admintools/dataclasses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Python Standard Library Imports
from dataclasses import dataclass


@dataclass
class TodosConfig:
"""Todos Config
This class specifies section of the app or codebase to scan for TODOs in.
`HTK_ADMINTOOLS_TODOS_CONFIGS` will be set to a list of `TodosConfig` objects.
"""

name: str
directory: str

@property
def key(self):
key = self.name.lower().replace(' ', '-')
return key

@property
def exclusion_pattern(self):
return f'{self.directory}/'
56 changes: 56 additions & 0 deletions admintools/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Python Standard Library Imports
import subprocess

# Django Imports
from django.conf import settings

# HTK Imports
from htk.utils import (
htk_setting,
resolve_method_dynamically,
resolve_model_dynamically,
)
from htk.view_helpers import render_custom as _r


def todos_view(
request,
template='admintools/todos.html',
):
wrap_data = resolve_method_dynamically(
htk_setting('HTK_VIEW_CONTEXT_GENERATOR')
)
data = wrap_data(request)

def _build_todos_section(todos_config):
result = subprocess.run(
[
'grep',
'-n', # display line numbers
'-R', # recursive
'-C 5', # show context, 5 lines before/after
f'--group-separator={"~" * 10}', # a unique string that won't occur in code
'TODO',
todos_config.directory,
],
capture_output=True,
)
todos_groups = (
result.stdout.decode()
.replace(todos_config.exclusion_pattern, '')
.split('~' * 10)
)
todos_section = {
'key': todos_config.key,
'name': todos_config.name,
'groups': todos_groups,
}
return todos_section

todos_configs = htk_setting('HTK_ADMINTOOLS_TODOS_CONFIGS')
data['todos_sections'] = [
_build_todos_section(todos_config) for todos_config in todos_configs
]

response = _r(request, template, data=data)
return response
18 changes: 18 additions & 0 deletions templates/htk/admintools/fragments/js/todos.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script>
$(function() {
$('.todo-block').each((i, elt) => {
const html = $(elt).html();
const lines = html.split('\n');
const mappedLines = lines.map((line) => {
// https://coolors.co/cc2936-f3f9d2
const mappedLine = line.includes('TODO') ?
`<div style="color: #cc2936; font-weight: bold; font-style: italic; background-color: #f3f9d2;">${line}</div>` :
`${line}\n`;
return mappedLine;

});
const newHtml = mappedLines.join('');
$(elt).html(newHtml);
});
});
</script>
25 changes: 25 additions & 0 deletions templates/htk/admintools/fragments/todos.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{# Docs: https://getbootstrap.com/docs/5.3/components/navs-tabs/ #}
<ul class="nav nav-pills" id="todosTabs" role="tablist">
{% for todos_section in todos_sections %}
<li class="nav-item" role="presentation">
<button class="nav-link{% if forloop.first %} active{% endif %}" id="{{ todos_section.key }}-tab" data-bs-toggle="tab" data-bs-target="#{{ todos_section.key }}-tab-pane" type="button" role="tab" aria-controls="{{ todos_section.key }}-tab-pane" aria-selected="true">{{ todos_section.name }}</button>
</li>
{% endfor %}
</ul>
<div class="tab-content" id="todosTabsContent">
{% for todos_section in todos_sections %}
<div class="tab-pane fade show{% if forloop.first %} active{% endif %}" id="{{ todos_section.key }}-tab-pane" role="tabpanel" aria-labelledby="{{ todos_section.key }}-tab" tabindex="0">
<p>
There are <b>{{ todos_section.groups|length }} unresolved TODOs</b> in the <b>{{ todos_section.name }}</b> section of the codebase:
</p>

{% for todos_group in todos_section.groups %}

{% if forloop.counter0 > 0 %}<hr/>{% endif %}
<pre class="todo-block">{{ todos_group }}</pre>

{% endfor %}{# end todos_group in todos_section.groups #}

</div>
{% endfor %}
</div>

0 comments on commit 88e33a5

Please sign in to comment.