Skip to content

Added possibility to manage filters hints from admin interface #80

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/base/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,23 @@

from django.contrib import admin

from base.models import Link
from base.models import (
DescriptedFilter,
DescriptedFilterField,
Link,
)


class DescriptedFilterFieldInline(admin.TabularInline):
model = DescriptedFilterField
fields = ('description',)
extra = 0
can_create = False


@admin.register(DescriptedFilter)
class DescriptedFilterAdmin(admin.ModelAdmin):
inlines = [DescriptedFilterFieldInline]


@admin.register(Link)
Expand Down
18 changes: 18 additions & 0 deletions src/base/context_processors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Any

from base.models import DescriptedFilter
from base.tools import split_class_name


def filters_descriptions(request) -> dict[str, list[dict[str, Any]]]:
"""
Adds signal filters descriftions to the context.
"""
descripted_filters = DescriptedFilter.objects.all()

results: dict[str, dict[dict[str, dict[str, str]]]] = {
'filters_descriptions': {
split_class_name(str(df.filter_name))[-1]: df.descriptions
} for df in descripted_filters
}
return results
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 5.0.2 on 2024-02-29 10:56

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


class Migration(migrations.Migration):

dependencies = [
('base', '0002_link_created_link_modified'),
]

operations = [
migrations.CreateModel(
name='DescriptedFilter',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('filter_name', models.CharField(choices=[('signals.filters.SignalFilter', 'signals.filters.SignalFilter')], max_length=256, unique=True)),
],
),
migrations.AlterField(
model_name='link',
name='link_type',
field=models.CharField(choices=[('api_documentation', 'API Documentation'), ('dua', 'DUA'), ('interpreting_mask', 'Interpreting mask use in context'), ('question_text', 'Question text'), ('survey_details', 'Survey details'), ('survey_documentation', 'Survey documentation'), ('technical_description', 'Technical description'), ('wave_10_revision', 'Wave 10 revision updates'), ('wave_11_revision', 'Wave 11 revision updates'), ('other', 'Other'), ('example_url', 'Example URL')], help_text='Link type', max_length=128),
),
migrations.CreateModel(
name='DescriptedFilterField',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('filter_field', models.CharField(help_text='Filter field', max_length=256)),
('description', models.TextField(blank=True, help_text='Filter field description', null=True)),
('filter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='filter_fields', to='base.descriptedfilter')),
],
options={
'unique_together': {('filter', 'filter_field')},
},
),
]
64 changes: 64 additions & 0 deletions src/base/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,70 @@
from linkpreview import LinkPreview, link_preview
from models_extensions.models import TimeStampedModel

from base.tools import get_class_by_name, split_class_name

FILTERS_LIST: list = [
('signals.filters.SignalFilter', 'signals.filters.SignalFilter'),
]


class DescriptedFilterField(models.Model):
"""
A model representing a filter field that is descripted.
"""
filter = models.ForeignKey(
'DescriptedFilter',
on_delete=models.CASCADE,
related_name='filter_fields'
)
filter_field = models.CharField(help_text=_('Filter field'), max_length=256)
description = models.TextField(help_text=_('Filter field description'), blank=True, null=True)

class Meta:
unique_together = ('filter', 'filter_field')

def __str__(self) -> str:
"""
Returns the name of the filter and the filter field
that associated with description.
"""
return self.filter_field


class DescriptedFilter(models.Model):
"""
A model representing a filter wich fields are descripted.
"""
filter_name = models.CharField(max_length=256, unique=True, choices=FILTERS_LIST)

def __str__(self) -> str:
"""
Returns the name of the filter and the filter field
that associated with description.
"""
return self.filter_name

def save(self, *args, **kwargs) -> None:
"""
Saves the filter description.
"""
super().save(*args, **kwargs)
if not self.filter_fields.exists():
filter_class = get_class_by_name(*split_class_name(self.filter_name))
for field_name, field in filter_class.base_filters.items():
DescriptedFilterField.objects.create(
filter=self,
filter_field=field_name
)
super().save(*args, **kwargs)

@property
def descriptions(self) -> dict:
"""
Returns a dictionary with filter fields descriptions.
"""
return {field.filter_field: field.description for field in self.filter_fields.all()}


class LinkTypeChoices(models.TextChoices):
"""
Expand Down
20 changes: 20 additions & 0 deletions src/base/tools.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import importlib
from typing import Any


def split_class_name(class_name) -> tuple[str, Any]:
"""
Splits a class name into module name and class name.
"""
parts = class_name.split('.')
module_name = '.'.join(parts[:-1])
class_name = parts[-1]
return module_name, class_name


def get_class_by_name(module_name, class_name) -> Any:
"""
Returns a class by its name.
"""
module = importlib.import_module(module_name)
return getattr(module, class_name)
1 change: 1 addition & 0 deletions src/signal_documentation/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'base.context_processors.filters_descriptions'
],
},
},
Expand Down
40 changes: 8 additions & 32 deletions src/templates/signals/signals.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ <h5 class="modal-title">Pathogen</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.pathogen }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -63,10 +60,7 @@ <h5 class="modal-title">Active</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.active }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -94,10 +88,7 @@ <h5 class="modal-title">Available Geography</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.available_geography }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -125,10 +116,7 @@ <h5 class="modal-title">Signal Type</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.signal_type }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -156,10 +144,7 @@ <h5 class="modal-title">Category</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.category }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -187,10 +172,7 @@ <h5 class="modal-title">Format Type</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.format_type }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -218,10 +200,7 @@ <h5 class="modal-title">Source</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.source }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down Expand Up @@ -249,10 +228,7 @@ <h5 class="modal-title">Time Label</h5>
aria-label="Close"></button>
</div>
<div class="modal-body">
Non omnis incidunt qui sed occaecati magni asperiores est mollitia. Soluta
at et reprehenderit. Placeat autem numquam et fuga numquam. Tempora in
facere consequatur sit dolor ipsum. Consequatur nemo amet incidunt est
facilis. Dolorem neque recusandae quo sit molestias sint dignissimos.
{{ filters_descriptions.SignalFilter.time_label }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary"
Expand Down