Allow changing the asset filter list
This commit is contained in:
parent
da9f32e882
commit
287facbab2
16
app/urls.py
16
app/urls.py
|
@ -284,4 +284,20 @@ urlpatterns = [
|
||||||
assets.AssetRestrictionDelete.as_view(),
|
assets.AssetRestrictionDelete.as_view(),
|
||||||
name="assetrestriction_delete",
|
name="assetrestriction_delete",
|
||||||
),
|
),
|
||||||
|
# Asset group filters
|
||||||
|
path(
|
||||||
|
"assetfilter/<str:group_id>/flip/<str:symbol>/",
|
||||||
|
assets.AssetFilterFlip.as_view(),
|
||||||
|
name="assetfilter_flip",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"assetfilter/<str:group_id>/delete/<str:symbol>/",
|
||||||
|
assets.AssetFilterDelete.as_view(),
|
||||||
|
name="assetfilter_delete",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"assetfilter/<str:type>/view/<str:group_id>/",
|
||||||
|
assets.AssetFilterList.as_view(),
|
||||||
|
name="assetfilters",
|
||||||
|
),
|
||||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
|
|
|
@ -94,7 +94,7 @@ class RiskModelAdmin(admin.ModelAdmin):
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupAdmin(admin.ModelAdmin):
|
class AssetGroupAdmin(admin.ModelAdmin):
|
||||||
list_display = ("user", "name", "description", "account")
|
list_display = ("user", "name", "description")
|
||||||
|
|
||||||
|
|
||||||
class AssetRestrictionAdmin(admin.ModelAdmin):
|
class AssetRestrictionAdmin(admin.ModelAdmin):
|
||||||
|
|
|
@ -309,12 +309,10 @@ class AssetGroupForm(RestrictedFormMixin, ModelForm):
|
||||||
fields = (
|
fields = (
|
||||||
"name",
|
"name",
|
||||||
"description",
|
"description",
|
||||||
"account",
|
|
||||||
)
|
)
|
||||||
help_texts = {
|
help_texts = {
|
||||||
"name": "Name of the asset group. Informational only.",
|
"name": "Name of the asset group. Informational only.",
|
||||||
"description": "Description of the asset group. Informational only.",
|
"description": "Description of the asset group. Informational only.",
|
||||||
"account": "Account to pull assets from.",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
# Generated by Django 4.1.6 on 2023-02-11 18:46
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0057_alter_assetgroup_account_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='assetgroup',
|
||||||
|
name='account',
|
||||||
|
),
|
||||||
|
]
|
|
@ -411,11 +411,6 @@ class AssetGroup(models.Model):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
description = models.TextField(null=True, blank=True)
|
description = models.TextField(null=True, blank=True)
|
||||||
|
|
||||||
# Account for checking pairs on children if specified
|
|
||||||
account = models.ForeignKey(
|
|
||||||
Account, on_delete=models.PROTECT, null=True, blank=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# Dict like {"RUB": True, "USD": False}
|
# Dict like {"RUB": True, "USD": False}
|
||||||
allowed = models.JSONField(null=True, blank=True, default=dict)
|
allowed = models.JSONField(null=True, blank=True, default=dict)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
{% load cache %}
|
||||||
|
{% load cachalot cache %}
|
||||||
|
{% get_last_invalidation 'core.AssetGroup' as last %}
|
||||||
|
{% include 'mixins/partials/notify.html' %}
|
||||||
|
{% cache 600 objects_assetgroups_field request.user.id object_list last %}
|
||||||
|
<table
|
||||||
|
class="table is-fullwidth is-hoverable"
|
||||||
|
hx-target="#{{ context_object_name }}-table"
|
||||||
|
id="{{ context_object_name }}-table"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-trigger="{{ context_object_name_singular }}Event from:body"
|
||||||
|
hx-get="{{ list_url }}">
|
||||||
|
<thead>
|
||||||
|
<th>symbol</th>
|
||||||
|
<th>status</th>
|
||||||
|
<th>actions</th>
|
||||||
|
</thead>
|
||||||
|
{% for key, item in object_list.items %}
|
||||||
|
<tr class="
|
||||||
|
{% if item is True %}has-background-success-light
|
||||||
|
{% elif item is False %}has-background-danger-light
|
||||||
|
{% endif %}">
|
||||||
|
<td>{{ key }}</td>
|
||||||
|
<td>{{ item }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="buttons">
|
||||||
|
<button
|
||||||
|
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||||
|
hx-get="{% url 'assetfilter_flip' group_id=group_id symbol=key %}"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#modals-here"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
class="button">
|
||||||
|
<span class="icon-text">
|
||||||
|
<span class="icon" data-tooltip="Flip direction">
|
||||||
|
<i class="fa-solid fa-arrows-repeat"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||||
|
hx-delete="{% url 'assetfilter_delete' group_id=group_id symbol=key %}"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#modals-here"
|
||||||
|
hx-swap="innerHTML"
|
||||||
|
class="button">
|
||||||
|
<span class="icon-text">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="fa-solid fa-xmark"></i>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
{% endcache %}
|
|
@ -15,7 +15,6 @@
|
||||||
<th>user</th>
|
<th>user</th>
|
||||||
<th>name</th>
|
<th>name</th>
|
||||||
<th>description</th>
|
<th>description</th>
|
||||||
<th>account</th>
|
|
||||||
<th>status</th>
|
<th>status</th>
|
||||||
<th>restrictions</th>
|
<th>restrictions</th>
|
||||||
<th>actions</th>
|
<th>actions</th>
|
||||||
|
@ -26,8 +25,16 @@
|
||||||
<td>{{ item.user }}</td>
|
<td>{{ item.user }}</td>
|
||||||
<td>{{ item.name }}</td>
|
<td>{{ item.name }}</td>
|
||||||
<td>{{ item.description }}</td>
|
<td>{{ item.description }}</td>
|
||||||
<td>{{ item.account }}</td>
|
<td>
|
||||||
<td>{{ item.matches }}</td>
|
<a
|
||||||
|
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
|
||||||
|
hx-get="{% url 'assetfilters' type=type group_id=item.id %}"
|
||||||
|
hx-trigger="click"
|
||||||
|
hx-target="#{{ type }}s-here"
|
||||||
|
hx-swap="innerHTML">
|
||||||
|
{{ item.matches }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td>{{ item.restrictions }}</td>
|
<td>{{ item.restrictions }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
|
|
|
@ -3,7 +3,16 @@ import json
|
||||||
from cachalot.api import invalidate
|
from cachalot.api import invalidate
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from mixins.views import AbortSave, ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate
|
from django.shortcuts import render
|
||||||
|
from django.views import View
|
||||||
|
from mixins.views import (
|
||||||
|
AbortSave,
|
||||||
|
ObjectCreate,
|
||||||
|
ObjectDelete,
|
||||||
|
ObjectList,
|
||||||
|
ObjectNameMixin,
|
||||||
|
ObjectUpdate,
|
||||||
|
)
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.parsers import JSONParser
|
from rest_framework.parsers import JSONParser
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
@ -154,3 +163,68 @@ class AssetRestrictionAPI(APIView):
|
||||||
|
|
||||||
return HttpResponse(status=status.HTTP_200_OK)
|
return HttpResponse(status=status.HTTP_200_OK)
|
||||||
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
return HttpResponse(status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
|
|
||||||
|
# Asset group allowed field
|
||||||
|
class AssetFilterList(LoginRequiredMixin, ObjectList):
|
||||||
|
list_template = "partials/asset-filter-list.html"
|
||||||
|
page_title = "List of asset filters."
|
||||||
|
page_subtitle = None
|
||||||
|
|
||||||
|
context_object_name_singular = "asset filter"
|
||||||
|
context_object_name = "asset filters"
|
||||||
|
|
||||||
|
list_url_name = "assetfilters"
|
||||||
|
list_url_args = ["type", "group_id"]
|
||||||
|
|
||||||
|
def get_queryset(self, **kwargs):
|
||||||
|
group_id = kwargs.get("group_id", None)
|
||||||
|
self.extra_context = {"group_id": group_id}
|
||||||
|
try:
|
||||||
|
group = AssetGroup.objects.get(id=group_id, user=self.request.user)
|
||||||
|
except AssetGroup.DoesNotExist:
|
||||||
|
context = {"message": "Asset group does not exist", "class": "danger"}
|
||||||
|
return self.render_to_response(context)
|
||||||
|
return group.allowed
|
||||||
|
|
||||||
|
|
||||||
|
class AssetFilterFlip(LoginRequiredMixin, ObjectNameMixin, View):
|
||||||
|
template_name = "mixins/partials/notify.html"
|
||||||
|
model = AssetGroup
|
||||||
|
|
||||||
|
def get(self, request, group_id, symbol):
|
||||||
|
try:
|
||||||
|
group = AssetGroup.objects.get(id=group_id, user=request.user)
|
||||||
|
except AssetGroup.DoesNotExist:
|
||||||
|
context = {"message": "Asset group does not exist", "class": "danger"}
|
||||||
|
return render(request, self.template_name, context)
|
||||||
|
if symbol not in group.allowed:
|
||||||
|
context = {"message": "Asset filter does not exist", "class": "danger"}
|
||||||
|
return render(request, self.template_name, context)
|
||||||
|
group.allowed[symbol] = not group.allowed[symbol]
|
||||||
|
group.save()
|
||||||
|
context = {"message": "Asset filter updated", "class": "success"}
|
||||||
|
response = render(request, self.template_name, context)
|
||||||
|
response["HX-Trigger"] = "assetgroupEvent"
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class AssetFilterDelete(LoginRequiredMixin, ObjectNameMixin, View):
|
||||||
|
template_name = "mixins/partials/notify.html"
|
||||||
|
model = AssetGroup
|
||||||
|
|
||||||
|
def delete(self, request, group_id, symbol):
|
||||||
|
try:
|
||||||
|
group = AssetGroup.objects.get(id=group_id, user=request.user)
|
||||||
|
except AssetGroup.DoesNotExist:
|
||||||
|
context = {"message": "Asset group does not exist", "class": "danger"}
|
||||||
|
return render(request, self.template_name, context)
|
||||||
|
if symbol not in group.allowed:
|
||||||
|
context = {"message": "Asset filter does not exist", "class": "danger"}
|
||||||
|
return render(request, self.template_name, context)
|
||||||
|
del group.allowed[symbol]
|
||||||
|
group.save()
|
||||||
|
context = {"message": "Asset filter deleted", "class": "success"}
|
||||||
|
response = render(request, self.template_name, context)
|
||||||
|
response["HX-Trigger"] = "assetgroupEvent"
|
||||||
|
return response
|
||||||
|
|
Loading…
Reference in New Issue