BO 1.27 Drag&Drop TrainingPlanDetail, TrainingPlan clone

This commit is contained in:
Tibor Bossanyi (Freelancer) 2021-09-09 20:20:25 +02:00
parent 462877c8a9
commit 2340c3e21a
6 changed files with 141 additions and 15 deletions

View File

@ -0,0 +1,8 @@
{% extends "adminsortable2/change_list.html" %}
{% block object-tools-items %}
{{ block.super }}
<li>
<a href="mylink/">My Link</a>
</li>
{% endblock %}

View File

@ -0,0 +1,81 @@
{% load i18n admin_urls static admin_modify %}
<div class="js-inline-admin-formset inline-group" id="{{ inline_admin_formset.formset.prefix }}-group"
data-inline-type="tabular"
data-inline-formset="{{ inline_admin_formset.inline_formset_data }}">
<div class="tabular inline-related {% if forloop.last %}last-related{% endif %}">
{{ inline_admin_formset.formset.management_form }}
<fieldset class="module {{ inline_admin_formset.classes }}">
{% if inline_admin_formset.formset.max_num == 1 %}
<h2>{{ inline_admin_formset.opts.verbose_name|capfirst }}</h2>
{% else %}
<h2>{{ inline_admin_formset.opts.verbose_name_plural|capfirst }}</h2>
{% endif %}
{{ inline_admin_formset.formset.non_form_errors }}
<table>
<thead><tr>
<th class="original"></th>
{% for field in inline_admin_formset.fields %}
{% if not field.widget.is_hidden %}
<th class="column-{{ field.name }}{% if field.required %} required{% endif %}">{{ field.label|capfirst }}
{% if field.help_text %}<img src="{% static "admin/img/icon-unknown.svg" %}" class="help help-tooltip" width="10" height="10" alt="({{ field.help_text|striptags }})" title="{{ field.help_text|striptags }}">{% endif %}
</th>
{% endif %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}<th>{% translate "Delete?" %}</th>{% endif %}
<th>{% translate "Clone?" %}</th>
</tr></thead>
<tbody>
{% for inline_admin_form in inline_admin_formset %}
{% if inline_admin_form.form.non_field_errors %}
<tr class="row-form-errors"><td colspan="{{ inline_admin_form|cell_count }}">{{ inline_admin_form.form.non_field_errors }}</td></tr>
{% endif %}
<tr class="form-row {% if inline_admin_form.original or inline_admin_form.show_url %}has_original{% endif %}{% if forloop.last and inline_admin_formset.has_add_permission %} empty-form{% endif %}"
id="{{ inline_admin_formset.formset.prefix }}-{% if not forloop.last %}{{ forloop.counter0 }}{% else %}empty{% endif %}">
<td class="original">
{% if inline_admin_form.original or inline_admin_form.show_url %}<p>
{% if inline_admin_form.original %}
{{ inline_admin_form.original }}
{% if inline_admin_form.model_admin.show_change_link and inline_admin_form.model_admin.has_registered_model %}<a href="{% url inline_admin_form.model_admin.opts|admin_urlname:'change' inline_admin_form.original.pk|admin_urlquote %}" class="{% if inline_admin_formset.has_change_permission %}inlinechangelink{% else %}inlineviewlink{% endif %}">{% if inline_admin_formset.has_change_permission %}{% translate "Change" %}{% else %}{% translate "View" %}{% endif %}</a>{% endif %}
{% endif %}
{% if inline_admin_form.show_url %}<a href="{{ inline_admin_form.absolute_url }}">{% translate "View on site" %}</a>{% endif %}
</p>{% endif %}
{% if inline_admin_form.needs_explicit_pk_field %}{{ inline_admin_form.pk_field.field }}{% endif %}
{% if inline_admin_form.fk_field %}{{ inline_admin_form.fk_field.field }}{% endif %}
{% spaceless %}
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if not field.is_readonly and field.field.is_hidden %}{{ field.field }}{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endspaceless %}
</td>
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_readonly or not field.field.is_hidden %}
<td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
{% if field.is_readonly %}
<p>{{ field.contents }}</p>
{% else %}
{{ field.field.errors.as_ul }}
{{ field.field }}
{% endif %}
</td>
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% if inline_admin_formset.formset.can_delete and inline_admin_formset.has_delete_permission %}
<td class="delete">{% if inline_admin_form.original %}{{ inline_admin_form.deletion_field.field }}{% endif %}</td>
{% endif %}
<td class="clone">{{ inline_admin_form.clone_field.field }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
</div>
</div>

View File

@ -1,20 +1,22 @@
from adminsortable2.admin import SortableAdminMixin, SortableInlineAdminMixin
from django.contrib import admin from django.contrib import admin
from django.utils.html import format_html from django.utils.html import format_html
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from inline_actions.admin import InlineActionsMixin
from inline_actions.admin import InlineActionsModelAdminMixin
from ..models.training_plan import TrainingPlan, TrainingPlanDetail, TrainingPlanTranslation from ..models.training_plan import TrainingPlan, TrainingPlanDetail, TrainingPlanTranslation
class TrainingPlanDetailInline(admin.TabularInline): class TrainingPlanDetailInline(InlineActionsMixin, SortableInlineAdminMixin, admin.TabularInline):
model = TrainingPlanDetail model = TrainingPlanDetail
#fk_name = 'training_plan_detail_id'
extra = 0 extra = 0
list_display = ( list_display = (
'training_plan', 'exercise_type', 'sort', 'set', 'repeats', 'max', 'weight', 'calc', 'sort', 'training_plan', 'exercise_type', 'set', 'repeats', 'max', 'weight', 'calc',
'resting_time', 'parallel', 'day') 'resting_time', 'parallel', 'day')
list_filter = ('training_plan__name', 'exercise_type__name')
list_editable = ( list_editable = (
'exercise_type', 'sort', 'set', 'repeats', 'weight', 'resting_time', 'parallel', 'day') 'sort', 'exercise_type', 'set', 'repeats', 'weight', 'resting_time', 'parallel', 'day')
list_display_links = ('sort', )
ordering = ('sort',) ordering = ('sort',)
def repeat_max(self, obj): def repeat_max(self, obj):
@ -39,12 +41,17 @@ class TrainingPlanDetailInline(admin.TabularInline):
pass pass
return response return response
def copy_attributes(self, request, queryset): def get_inline_actions(self, request, obj=None):
name = str(queryset[0].training_plan) actions = super(TrainingPlanDetailInline, self).get_inline_actions(request, obj)
return actions
def copy_attributes(self, request, obj, parent_obj=None):
name = str(request.queryset[0].training_plan)
details = TrainingPlanDetail.objects.filter(training_plan__name=name).order_by('sort') details = TrainingPlanDetail.objects.filter(training_plan__name=name).order_by('sort')
new_sort = details[len(details) - 1].sort + 1 new_sort = details[len(details) - 1].sort + 1
for objectAttr in queryset: for objectAttr in request.queryset:
objectAttr.pk = None objectAttr.pk = None
objectAttr.sort = new_sort objectAttr.sort = new_sort
objectAttr.save() objectAttr.save()
@ -82,8 +89,6 @@ class TrainingPlanDetailInline(admin.TabularInline):
html = '<span style="color: #{};font-size:32px">{}</span>'.format(color_code, "*") html = '<span style="color: #{};font-size:32px">{}</span>'.format(color_code, "*")
return format_html(html) return format_html(html)
actions = [copy_attributes, select_max_repeat, select_weight_calc]
class TranslationTrainingPlanInline(admin.TabularInline): class TranslationTrainingPlanInline(admin.TabularInline):
model = TrainingPlanTranslation model = TrainingPlanTranslation
@ -91,7 +96,7 @@ class TranslationTrainingPlanInline(admin.TabularInline):
extra = 0 extra = 0
class TrainingPlanAdmin(admin.ModelAdmin): class TrainingPlanAdmin(InlineActionsModelAdminMixin, admin.ModelAdmin):
list_display = ('training_plan_id', 'name', 'internal_name', 'free', 'active') list_display = ('training_plan_id', 'name', 'internal_name', 'free', 'active')
fields = ('tree', 'name', 'description', 'internal_name', 'free', 'active') fields = ('tree', 'name', 'description', 'internal_name', 'free', 'active')
list_editable = ('name', 'internal_name', 'free', 'active') list_editable = ('name', 'internal_name', 'free', 'active')
@ -101,14 +106,41 @@ class TrainingPlanAdmin(admin.ModelAdmin):
TrainingPlanDetailInline TrainingPlanDetailInline
] ]
@admin.action(description='clone selected training plans')
def clone(self, request, queryset):
for trainingPlan in queryset:
print("clone " + trainingPlan.name)
id = trainingPlan.training_plan_id
trainingPlan.pk = None
trainingPlan.name = trainingPlan.name + " COPY"
trainingPlan.internal_name = trainingPlan.internal_name + "_copy"
trainingPlan.active = False
trainingPlan.save()
newId = trainingPlan.pk
class TrainingPlanDetailAdmin(admin.ModelAdmin): details = TrainingPlanDetail.objects.filter(training_plan__training_plan_id=id)
for detail in details:
detail.pk = None
detail.training_plan_id = newId
detail.save()
translations = TrainingPlanTranslation.objects.filter(training_plan__training_plan_id=id)
for translation in translations:
translation.pk = None
translation.training_plan_id = newId
translation.name_translation = translation.name_translation + " COPY"
translation.save()
actions = ['clone']
class TrainingPlanDetailAdmin(SortableAdminMixin, admin.ModelAdmin):
list_display = ( list_display = (
'training_plan', 'exercise_type', 'sort', 'set', 'repeats', 'max', 'weight', 'calc', 'sort', 'training_plan', 'exercise_type', 'set', 'repeats', 'max', 'weight', 'calc',
'resting_time', 'parallel', 'day') 'resting_time', 'parallel', 'day')
list_filter = ('training_plan__name', 'exercise_type__name') list_filter = ('training_plan__name', 'exercise_type__name')
list_editable = ( list_editable = (
'exercise_type', 'sort', 'set', 'repeats', 'weight', 'resting_time', 'parallel', 'day') 'exercise_type', 'set', 'repeats', 'weight', 'resting_time', 'parallel', 'day')
ordering = ('sort',) ordering = ('sort',)
def repeat_max(self, obj): def repeat_max(self, obj):
@ -180,5 +212,5 @@ class TrainingPlanDetailAdmin(admin.ModelAdmin):
admin.site.register(TrainingPlan, TrainingPlanAdmin) admin.site.register(TrainingPlan, TrainingPlanAdmin)
#admin.site.register(TrainingPlanDetail, TrainingPlanDetailAdmin) admin.site.register(TrainingPlanDetail, TrainingPlanDetailAdmin)
admin.autodiscover() admin.autodiscover()

View File

@ -43,6 +43,7 @@ class TrainingPlanDetail(models.Model):
db_table = 'training_plan_detail' db_table = 'training_plan_detail'
verbose_name = _("Training Plan Detail") verbose_name = _("Training Plan Detail")
verbose_name_plural = _("Training Plan Details") verbose_name_plural = _("Training Plan Details")
ordering = ['sort']
class TrainingPlanTranslation(models.Model): class TrainingPlanTranslation(models.Model):

View File

@ -49,6 +49,8 @@ INSTALLED_APPS = [
'ckeditor_uploader', 'ckeditor_uploader',
'django_admin_json_editor', 'django_admin_json_editor',
'rangefilter', 'rangefilter',
'adminsortable2',
'inline_actions',
#'django_cron', #'django_cron',
] ]

View File

@ -45,6 +45,8 @@ INSTALLED_APPS = [
'ckeditor_uploader', 'ckeditor_uploader',
'django_admin_json_editor', 'django_admin_json_editor',
'rangefilter', 'rangefilter',
'adminsortable2',
'inline_actions',
#'django_cron', #'django_cron',
] ]