mirror of
git://git.yoctoproject.org/layerindex-web.git
synced 2025-07-05 13:14:46 +02:00

Recipes come and go over time, so when a recipe gets deleted the history for it goes away, which means that if you look back in time you do not see an accurate picture - you only see the subset of recipes that are currently present. Introduce an indirection between recipes and history that allows for old recipes to persist (mostly in name only). Signed-off-by: Paul Eggleton <paul.eggleton@linux.intel.com>
212 lines
8.1 KiB
Python
212 lines
8.1 KiB
Python
# rrs-web - admin interface definitions
|
|
#
|
|
# Copyright (C) 2014 Intel Corporation
|
|
#
|
|
# Licensed under the MIT license, see COPYING.MIT for details
|
|
|
|
from django.utils.functional import curry
|
|
|
|
from django.contrib import admin
|
|
from django.contrib.admin import DateFieldListFilter
|
|
from django import forms
|
|
from django.forms.models import BaseInlineFormSet
|
|
from django.core.exceptions import ValidationError
|
|
|
|
from rrs.models import Release, Milestone, Maintainer, RecipeMaintainerHistory, \
|
|
RecipeMaintainer, RecipeDistro, RecipeUpgrade, RecipeUpstream, \
|
|
RecipeUpstreamHistory, MaintenancePlan, MaintenancePlanLayerBranch, \
|
|
RecipeMaintenanceLink, RecipeSymbol
|
|
|
|
class MaintenancePlanLayerBranchFormSet(BaseInlineFormSet):
|
|
def __init__(self, *args, **kwargs):
|
|
from layerindex.models import PythonEnvironment
|
|
initialfields = {}
|
|
py2env = PythonEnvironment.get_default_python2_environment()
|
|
if py2env:
|
|
initialfields['python2_environment'] = py2env.id
|
|
py3env = PythonEnvironment.get_default_python3_environment()
|
|
if py3env:
|
|
initialfields['python3_environment'] = py3env.id
|
|
if initialfields:
|
|
kwargs['initial'] = [initialfields]
|
|
super(MaintenancePlanLayerBranchFormSet, self).__init__(*args, **kwargs)
|
|
|
|
@property
|
|
def empty_form(self):
|
|
from layerindex.models import PythonEnvironment
|
|
form = super(MaintenancePlanLayerBranchFormSet, self).empty_form
|
|
py2env = PythonEnvironment.get_default_python2_environment()
|
|
if py2env:
|
|
form.fields['python2_environment'].initial = py2env
|
|
py3env = PythonEnvironment.get_default_python3_environment()
|
|
if py3env:
|
|
form.fields['python3_environment'].initial = py3env
|
|
return form
|
|
|
|
def clean(self):
|
|
super(MaintenancePlanLayerBranchFormSet, self).clean()
|
|
total_checked = 0
|
|
|
|
for form in self.forms:
|
|
if not form.is_valid():
|
|
return
|
|
if form.cleaned_data and not form.cleaned_data.get('DELETE'):
|
|
layerbranch = form.cleaned_data['layerbranch']
|
|
if not layerbranch:
|
|
raise ValidationError('You must select a layerbranch')
|
|
# Only allow one plan per layer
|
|
# NOTE: This restriction is in place because we don't have enough safeguards in the
|
|
# processing code to avoid processing a layer multiple times if it's part of
|
|
# more than one plan, and there may be other challenges. For now, just keep it simple.
|
|
mplayerbranches = layerbranch.maintenanceplanlayerbranch_set.all()
|
|
if form.instance.pk is not None:
|
|
mplayerbranches = mplayerbranches.exclude(id=form.instance.id)
|
|
if mplayerbranches.exists():
|
|
raise ValidationError('A layer branch can only be part of one maintenance plan - layer branch %s is already part of maintenance plan %s' % (layerbranch, mplayerbranches.first().plan.name))
|
|
total_checked += 1
|
|
|
|
|
|
class MaintenancePlanLayerBranchInline(admin.StackedInline):
|
|
model = MaintenancePlanLayerBranch
|
|
formset = MaintenancePlanLayerBranchFormSet
|
|
readonly_fields = ['upgrade_date', 'upgrade_rev']
|
|
min_num = 1
|
|
extra = 0
|
|
|
|
class MaintenancePlanAdminForm(forms.ModelForm):
|
|
model = MaintenancePlan
|
|
|
|
def clean_email_to(self):
|
|
val = self.cleaned_data['email_to']
|
|
if self.cleaned_data['email_enabled']:
|
|
if not val:
|
|
raise ValidationError('To email address must be specified if emails are enabled')
|
|
return val
|
|
|
|
def clean_email_from(self):
|
|
val = self.cleaned_data['email_from']
|
|
if self.cleaned_data['email_enabled']:
|
|
if not val:
|
|
raise ValidationError('From email address must be specified if emails are enabled')
|
|
return val
|
|
|
|
def clean_email_subject(self):
|
|
val = self.cleaned_data['email_subject']
|
|
if self.cleaned_data['email_enabled']:
|
|
if not val:
|
|
raise ValidationError('Email subject must be specified if emails are enabled')
|
|
return val
|
|
|
|
class MaintenancePlanAdmin(admin.ModelAdmin):
|
|
model = MaintenancePlan
|
|
form = MaintenancePlanAdminForm
|
|
inlines = [
|
|
MaintenancePlanLayerBranchInline,
|
|
]
|
|
def save_model(self, request, obj, form, change):
|
|
# For new maintenance plans, copy releases from the first plan
|
|
if obj.pk is None:
|
|
copyfrom_mp = MaintenancePlan.objects.all().first()
|
|
else:
|
|
copyfrom_mp = None
|
|
super().save_model(request, obj, form, change)
|
|
if copyfrom_mp:
|
|
for release in copyfrom_mp.release_set.all():
|
|
release.pk = None
|
|
release.plan = obj
|
|
release.save()
|
|
milestone = Milestone(release=release)
|
|
milestone.name='Default'
|
|
milestone.start_date = release.start_date
|
|
milestone.end_date = release.end_date
|
|
milestone.save()
|
|
|
|
class MilestoneFormSet(BaseInlineFormSet):
|
|
def clean(self):
|
|
super(MilestoneFormSet, self).clean()
|
|
total = 0
|
|
for form in self.forms:
|
|
if not form.is_valid():
|
|
return
|
|
if form.cleaned_data and not form.cleaned_data.get('DELETE'):
|
|
total += 1
|
|
if not total:
|
|
raise ValidationError('Releases must have at least one milestone')
|
|
|
|
class MilestoneInline(admin.StackedInline):
|
|
model = Milestone
|
|
formset = MilestoneFormSet
|
|
|
|
class ReleaseAdmin(admin.ModelAdmin):
|
|
search_fields = ['name']
|
|
list_filter = ['plan']
|
|
model = Release
|
|
inlines = [
|
|
MilestoneInline,
|
|
]
|
|
|
|
class MilestoneAdmin(admin.ModelAdmin):
|
|
search_fields = ['name']
|
|
list_filter = ['release__plan', 'release__name']
|
|
model = Milestone
|
|
|
|
class MaintainerAdmin(admin.ModelAdmin):
|
|
search_fields = ['name']
|
|
model = Maintainer
|
|
|
|
class RecipeMaintainerHistoryAdmin(admin.ModelAdmin):
|
|
search_fields = ['title', 'author__name', 'sha1']
|
|
list_filter = ['layerbranch__layer', 'author__name', ('date', DateFieldListFilter)]
|
|
model = RecipeMaintainerHistory
|
|
|
|
class RecipeMaintainerAdmin(admin.ModelAdmin):
|
|
search_fields = ['recipesymbol__pn']
|
|
list_filter = ['recipesymbol__layerbranch__layer__name', 'history', 'maintainer__name']
|
|
model = RecipeMaintainer
|
|
|
|
class RecipeDistroAdmin(admin.ModelAdmin):
|
|
search_fields = ['recipe__pn']
|
|
list_filter = ['recipe__layerbranch__layer__name', 'distro']
|
|
model = RecipeDistro
|
|
|
|
class RecipeUpgradeAdmin(admin.ModelAdmin):
|
|
search_fields = ['recipesymbol__pn']
|
|
list_filter = ['recipesymbol__layerbranch__layer__name',
|
|
('commit_date', DateFieldListFilter), 'maintainer__name']
|
|
model = RecipeUpgrade
|
|
|
|
class RecipeUpstreamHistoryAdmin(admin.ModelAdmin):
|
|
list_filter = [
|
|
'layerbranch__layer',
|
|
('start_date', DateFieldListFilter),
|
|
('end_date', DateFieldListFilter)
|
|
]
|
|
model = RecipeUpstreamHistory
|
|
|
|
class RecipeUpstreamAdmin(admin.ModelAdmin):
|
|
search_fields = ['recipesymbol__pn']
|
|
list_filter = ['recipesymbol__layerbranch__layer__name', 'status',
|
|
'type', ('date', DateFieldListFilter), 'history']
|
|
model = RecipeUpstream
|
|
|
|
class RecipeMaintenanceLinkAdmin(admin.ModelAdmin):
|
|
model = RecipeMaintenanceLink
|
|
|
|
class RecipeSymbolAdmin(admin.ModelAdmin):
|
|
model = RecipeSymbol
|
|
search_fields = ['pn']
|
|
list_filter = ['layerbranch']
|
|
|
|
admin.site.register(MaintenancePlan, MaintenancePlanAdmin)
|
|
admin.site.register(Release, ReleaseAdmin)
|
|
admin.site.register(Milestone, MilestoneAdmin)
|
|
admin.site.register(Maintainer, MaintainerAdmin)
|
|
admin.site.register(RecipeMaintainerHistory, RecipeMaintainerHistoryAdmin)
|
|
admin.site.register(RecipeMaintainer, RecipeMaintainerAdmin)
|
|
admin.site.register(RecipeDistro, RecipeDistroAdmin)
|
|
admin.site.register(RecipeUpgrade, RecipeUpgradeAdmin)
|
|
admin.site.register(RecipeUpstreamHistory, RecipeUpstreamHistoryAdmin)
|
|
admin.site.register(RecipeUpstream, RecipeUpstreamAdmin)
|
|
admin.site.register(RecipeMaintenanceLink, RecipeMaintenanceLinkAdmin)
|
|
admin.site.register(RecipeSymbol, RecipeSymbolAdmin)
|