Bulk of the profile work is done.

This commit is contained in:
Adarnof
2017-03-23 22:54:25 -04:00
parent bb87fdd958
commit e15d79b834
155 changed files with 1693 additions and 3080 deletions

36
srp/managers.py Normal file
View File

@@ -0,0 +1,36 @@
from __future__ import unicode_literals
from django.conf import settings
import requests
import logging
logger = logging.getLogger(__name__)
class SRPManager:
def __init__(self):
pass
@staticmethod
def get_kill_id(killboard_link):
num_set = '0123456789'
kill_id = ''.join([c for c in killboard_link if c in num_set])
return kill_id
@staticmethod
def get_kill_data(kill_id):
url = ("https://www.zkillboard.com/api/killID/%s/" % kill_id)
headers = {
'User-Agent': "%s Alliance Auth" % settings.DOMAIN,
'Content-Type': 'application/json',
}
r = requests.get(url, headers=headers)
result = r.json()[0]
if result:
ship_type = result['victim']['shipTypeID']
logger.debug("Ship type for kill ID %s is determined to be %s" % (kill_id, ship_type))
ship_value = result['zkb']['totalValue']
logger.debug("total loss value for kill id %s is %s" % (kill_id, ship_value))
return ship_type, ship_value
else:
raise ValueError("Invalid Kill ID")

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-22 23:35
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('srp', '0002_srpuserrequest_srp_status_choices'),
]
operations = [
migrations.AlterModelOptions(
name='srpfleetmain',
options={'permissions': (('access_srp', 'Can access SRP module'),)},
),
migrations.AlterField(
model_name='srpfleetmain',
name='fleet_doctrine',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpfleetmain',
name='fleet_name',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpfleetmain',
name='fleet_srp_aar_link',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpfleetmain',
name='fleet_srp_code',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpfleetmain',
name='fleet_srp_status',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpuserrequest',
name='additional_info',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpuserrequest',
name='after_action_report_link',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpuserrequest',
name='killboard_link',
field=models.CharField(default='', max_length=254),
),
migrations.AlterField(
model_name='srpuserrequest',
name='srp_ship_name',
field=models.CharField(default='', max_length=254),
),
]

View File

@@ -26,6 +26,9 @@ class SrpFleetMain(models.Model):
def pending_requests(self):
return self.srpuserrequest_set.filter(srp_status='Pending').count()
class Meta:
permissions = (('access_srp', 'Can access SRP module'),)
@python_2_unicode_compatible
class SrpUserRequest(models.Model):

View File

@@ -1,21 +1,19 @@
from __future__ import unicode_literals
from django.shortcuts import render, redirect
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.decorators import permission_required
from django.contrib import messages
from eveonline.managers import EveManager
from authentication.models import AuthServicesInfo
from srp.models import SrpFleetMain
from srp.models import SrpUserRequest
from srp.form import SrpFleetMainForm
from srp.form import SrpFleetUserRequestForm
from srp.form import SrpFleetUpdateCostForm
from srp.form import SrpFleetMainUpdateForm
from services.managers.srp_manager import srpManager
from srp.managers import SRPManager
from notifications import notify
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from authentication.decorators import members_and_blues
import uuid
import logging
@@ -32,7 +30,7 @@ def random_string(string_length=10):
@login_required
@members_and_blues()
@permission_required('srp.access_srp')
def srp_management(request):
logger.debug("srp_management called by user %s" % request.user)
fleets = SrpFleetMain.objects.filter(fleet_srp_status="")
@@ -42,7 +40,7 @@ def srp_management(request):
@login_required
@members_and_blues()
@permission_required('srp.access_srp')
def srp_management_all(request):
logger.debug("srp_management_all called by user %s" % request.user)
fleets = SrpFleetMain.objects.all()
@@ -52,20 +50,15 @@ def srp_management_all(request):
@login_required
@members_and_blues()
@permission_required('srp.access_srp')
def srp_fleet_view(request, fleet_id):
logger.debug("srp_fleet_view called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
fleet_main = SrpFleetMain.objects.get(id=fleet_id)
context = {"fleet_id": fleet_id, "fleet_status": fleet_main.fleet_srp_status,
"srpfleetrequests": fleet_main.srpuserrequest_set.all(),
"totalcost": fleet_main.total_cost}
fleet_main = get_object_or_404(SrpFleetMain, id=fleet_id)
context = {"fleet_id": fleet_id, "fleet_status": fleet_main.fleet_srp_status,
"srpfleetrequests": fleet_main.srpuserrequest_set.all(),
"totalcost": fleet_main.total_cost}
return render(request, 'registered/srpfleetdata.html', context=context)
else:
logger.error(
"Unable to view SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user))
return redirect("auth_srp_management_view")
return render(request, 'registered/srpfleetdata.html', context=context)
@login_required
@@ -79,15 +72,12 @@ def srp_fleet_add_view(request):
form = SrpFleetMainForm(request.POST)
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
authinfo = AuthServicesInfo.objects.get(user=request.user)
character = EveManager.get_character_by_id(authinfo.main_char_id)
srp_fleet_main = SrpFleetMain()
srp_fleet_main.fleet_name = form.cleaned_data['fleet_name']
srp_fleet_main.fleet_doctrine = form.cleaned_data['fleet_doctrine']
srp_fleet_main.fleet_time = form.cleaned_data['fleet_time']
srp_fleet_main.fleet_srp_code = random_string(8)
srp_fleet_main.fleet_commander = character
srp_fleet_main.fleet_commander = request.user.profile.main_character
srp_fleet_main.save()
@@ -109,15 +99,10 @@ def srp_fleet_add_view(request):
@permission_required('auth.srp_management')
def srp_fleet_remove(request, fleet_id):
logger.debug("srp_fleet_remove called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.delete()
logger.info("SRP Fleet %s deleted by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Removed SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
else:
logger.error(
"Unable to delete SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
srpfleetmain.delete()
logger.info("SRP Fleet %s deleted by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Removed SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_management_view")
@@ -125,16 +110,11 @@ def srp_fleet_remove(request, fleet_id):
@permission_required('auth.srp_management')
def srp_fleet_disable(request, fleet_id):
logger.debug("srp_fleet_disable called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.fleet_srp_code = ""
srpfleetmain.save()
logger.info("SRP Fleet %s disabled by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Disabled SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
else:
logger.error(
"Unable to disable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
srpfleetmain.fleet_srp_code = ""
srpfleetmain.save()
logger.info("SRP Fleet %s disabled by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Disabled SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_management_view")
@@ -142,16 +122,11 @@ def srp_fleet_disable(request, fleet_id):
@permission_required('auth.srp_management')
def srp_fleet_enable(request, fleet_id):
logger.debug("srp_fleet_enable called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.fleet_srp_code = random_string(8)
srpfleetmain.save()
logger.info("SRP Fleet %s enable by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Enabled SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
else:
logger.error(
"Unable to enable SRP fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
srpfleetmain.fleet_srp_code = random_string(8)
srpfleetmain.save()
logger.info("SRP Fleet %s enable by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Enabled SRP fleet %(fleetname)s.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_management_view")
@@ -159,16 +134,11 @@ def srp_fleet_enable(request, fleet_id):
@permission_required('auth.srp_management')
def srp_fleet_mark_completed(request, fleet_id):
logger.debug("srp_fleet_mark_completed called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.fleet_srp_status = "Completed"
srpfleetmain.save()
logger.info("Marked SRP Fleet %s as completed by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Marked SRP fleet %(fleetname)s as completed.') % {"fleetname": srpfleetmain.fleet_name})
else:
logger.error("Unable to mark SRP fleet with id %s as completed for user %s - fleet matching id not found." % (
fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
srpfleetmain.fleet_srp_status = "Completed"
srpfleetmain.save()
logger.info("Marked SRP Fleet %s as completed by user %s" % (srpfleetmain.fleet_name, request.user))
messages.success(request, _('Marked SRP fleet %(fleetname)s as completed.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_fleet_view", fleet_id)
@@ -176,22 +146,16 @@ def srp_fleet_mark_completed(request, fleet_id):
@permission_required('auth.srp_management')
def srp_fleet_mark_uncompleted(request, fleet_id):
logger.debug("srp_fleet_mark_uncompleted called by user %s for fleet id %s" % (request.user, fleet_id))
if SrpFleetMain.objects.filter(id=fleet_id).exists():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.fleet_srp_status = ""
srpfleetmain.save()
logger.info("Marked SRP Fleet %s as incomplete for user %s" % (fleet_id, request.user))
messages.success(request, _('Marked SRP fleet %(fleetname)s as incomplete.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_fleet_view", fleet_id)
else:
logger.error("Unable to mark SRP Fleet id %s as incomplete for user %s - fleet matching id not found." % (
fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
return redirect('auth_srp_management_view')
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
srpfleetmain.fleet_srp_status = ""
srpfleetmain.save()
logger.info("Marked SRP Fleet %s as incomplete for user %s" % (fleet_id, request.user))
messages.success(request, _('Marked SRP fleet %(fleetname)s as incomplete.') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_fleet_view", fleet_id)
@login_required
@members_and_blues()
@permission_required('srp.access_srp')
def srp_request_view(request, fleet_srp):
logger.debug("srp_request_view called by user %s for fleet srp code %s" % (request.user, fleet_srp))
completed = False
@@ -206,8 +170,7 @@ def srp_request_view(request, fleet_srp):
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
authinfo = AuthServicesInfo.objects.get(user=request.user)
character = EveManager.get_character_by_id(authinfo.main_char_id)
character = request.user.profile.main_character
srp_fleet_main = SrpFleetMain.objects.get(fleet_srp_code=fleet_srp)
post_time = timezone.now()
@@ -218,8 +181,8 @@ def srp_request_view(request, fleet_srp):
srp_request.srp_fleet_main = srp_fleet_main
try:
srp_kill_link = srpManager.get_kill_id(srp_request.killboard_link)
(ship_type_id, ship_value) = srpManager.get_kill_data(srp_kill_link)
srp_kill_link = SRPManager.get_kill_id(srp_request.killboard_link)
(ship_type_id, ship_value) = SRPManager.get_kill_data(srp_kill_link)
except ValueError:
logger.debug("User %s Submitted Invalid Killmail Link %s or server could not be reached" % (
request.user, srp_request.killboard_link))
@@ -251,87 +214,57 @@ def srp_request_view(request, fleet_srp):
@permission_required('auth.srp_management')
def srp_request_remove(request, srp_request_id):
logger.debug("srp_request_remove called by user %s for srp request id %s" % (request.user, srp_request_id))
stored_fleet_view = None
if SrpUserRequest.objects.filter(id=srp_request_id).exists():
srpuserrequest = SrpUserRequest.objects.get(id=srp_request_id)
stored_fleet_view = srpuserrequest.srp_fleet_main.id
srpuserrequest.delete()
logger.info("Deleted SRP request id %s for user %s" % (srp_request_id, request.user))
messages.success(request, _('Deleted SRP request from %(character)s for their %(ship)s.') % {
srpuserrequest = get_object_or_404(SrpUserRequest, id=srp_request_id)
srpuserrequest.delete()
logger.info("Deleted SRP request id %s for user %s" % (srp_request_id, request.user))
messages.success(request, _('Deleted SRP request from %(character)s for their %(ship)s.') % {
"character": srpuserrequest.character, "ship": srpuserrequest.srp_ship_name})
if stored_fleet_view is None:
logger.error("Unable to delete srp request id %s for user %s - request matching id not found." % (
srp_request_id, request.user))
messages.error(request, _('Unable to locate SRP request with ID %(requestid)s') % {"requestid": srp_request_id})
return redirect("auth_srp_management_view")
else:
return redirect("auth_srp_fleet_view", stored_fleet_view)
return redirect("auth_srp_fleet_view", srpuserrequest.srp_fleet_main.id)
@login_required
@permission_required('auth.srp_management')
def srp_request_approve(request, srp_request_id):
logger.debug("srp_request_approve called by user %s for srp request id %s" % (request.user, srp_request_id))
stored_fleet_view = None
if SrpUserRequest.objects.filter(id=srp_request_id).exists():
srpuserrequest = SrpUserRequest.objects.get(id=srp_request_id)
stored_fleet_view = srpuserrequest.srp_fleet_main.id
srpuserrequest.srp_status = "Approved"
if srpuserrequest.srp_total_amount == 0:
srpuserrequest.srp_total_amount = srpuserrequest.kb_total_loss
srpuserrequest.save()
logger.info("Approved SRP request id %s for character %s by user %s" % (
srp_request_id, srpuserrequest.character, request.user))
messages.success(request, _('Approved SRP request from %(character)s for their %(ship)s.') % {
"character": srpuserrequest.character, "ship": srpuserrequest.srp_ship_name})
notify(
srpuserrequest.character.user,
'SRP Request Approved',
level='success',
message='Your SRP request for a %s lost during %s has been approved for %s ISK.' % (
srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name, srpuserrequest.srp_total_amount)
)
if stored_fleet_view is None:
logger.error("Unable to approve srp request id %s on behalf of user %s - request matching id not found." % (
srp_request_id, request.user))
messages.error(request, _('Unable to locate SRP request with ID %(requestid)s') % {"requestid": srp_request_id})
return redirect("auth_srp_management_view")
else:
return redirect("auth_srp_fleet_view", stored_fleet_view)
srpuserrequest = get_object_or_404(SrpUserRequest, id=srp_request_id)
srpuserrequest.srp_status = "Approved"
if srpuserrequest.srp_total_amount == 0:
srpuserrequest.srp_total_amount = srpuserrequest.kb_total_loss
srpuserrequest.save()
logger.info("Approved SRP request id %s for character %s by user %s" % (
srp_request_id, srpuserrequest.character, request.user))
messages.success(request, _('Approved SRP request from %(character)s for their %(ship)s.') % {
"character": srpuserrequest.character, "ship": srpuserrequest.srp_ship_name})
notify(
srpuserrequest.character.user,
'SRP Request Approved',
level='success',
message='Your SRP request for a %s lost during %s has been approved for %s ISK.' % (
srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name, srpuserrequest.srp_total_amount)
)
return redirect("auth_srp_fleet_view", srpuserrequest.srp_fleet_main.id)
@login_required
@permission_required('auth.srp_management')
def srp_request_reject(request, srp_request_id):
logger.debug("srp_request_reject called by user %s for srp request id %s" % (request.user, srp_request_id))
stored_fleet_view = None
if SrpUserRequest.objects.filter(id=srp_request_id).exists():
srpuserrequest = SrpUserRequest.objects.get(id=srp_request_id)
stored_fleet_view = srpuserrequest.srp_fleet_main.id
srpuserrequest.srp_status = "Rejected"
srpuserrequest.save()
logger.info("SRP request id %s for character %s rejected by %s" % (
srp_request_id, srpuserrequest.character, request.user))
messages.success(request, _('Rejected SRP request from %(character)s for their %(ship)s.') % {
"character": srpuserrequest.character, "ship": srpuserrequest.srp_ship_name})
notify(
srpuserrequest.character.user,
'SRP Request Rejected',
level='danger',
message='Your SRP request for a %s lost during %s has been rejected.' % (
srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name)
)
if stored_fleet_view is None:
logger.error("Unable to reject SRP request id %s on behalf of user %s - request matching id not found." % (
srp_request_id, request.user))
messages.error(request, _('Unable to locate SRP request with ID %(requestid)s') % {"requestid": srp_request_id})
return redirect("auth_srp_management_view")
else:
return redirect("auth_srp_fleet_view", stored_fleet_view)
srpuserrequest = get_object_or_404(SrpUserRequest, id=srp_request_id)
srpuserrequest.srp_status = "Rejected"
srpuserrequest.save()
logger.info("SRP request id %s for character %s rejected by %s" % (
srp_request_id, srpuserrequest.character, request.user))
messages.success(request, _('Rejected SRP request from %(character)s for their %(ship)s.') % {
"character": srpuserrequest.character, "ship": srpuserrequest.srp_ship_name})
notify(
srpuserrequest.character.user,
'SRP Request Rejected',
level='danger',
message='Your SRP request for a %s lost during %s has been rejected.' % (
srpuserrequest.srp_ship_name, srpuserrequest.srp_fleet_main.fleet_name)
)
return redirect("auth_srp_fleet_view", srpuserrequest.srp_fleet_main.id)
@login_required
@@ -340,16 +273,11 @@ def srp_request_update_amount_view(request, fleet_srp_request_id):
logger.debug("srp_request_update_amount_view called by user %s for fleet srp request id %s" % (
request.user, fleet_srp_request_id))
if SrpUserRequest.objects.filter(id=fleet_srp_request_id).exists() is False:
logger.error("Unable to locate SRP request id %s for user %s" % (fleet_srp_request_id, request.user))
messages.error(request, _('Unable to locate SRP request with ID %(requestid)s') % {"requestid": fleet_srp_request_id})
return redirect("auth_srp_management_view")
srp_request = get_object_or_404(SrpUserRequest, id=fleet_srp_request_id)
if request.method == 'POST':
form = SrpFleetUpdateCostForm(request.POST)
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
srp_request = SrpUserRequest.objects.get(id=fleet_srp_request_id)
srp_request.srp_total_amount = form.cleaned_data['srp_total_amount']
srp_request.save()
logger.info("Updated srp request id %s total to %s by user %s" % (
@@ -369,26 +297,17 @@ def srp_request_update_amount_view(request, fleet_srp_request_id):
@permission_required('auth.srp_management')
def srp_fleet_edit_view(request, fleet_id):
logger.debug("srp_fleet_edit_view called by user %s for fleet id %s" % (request.user, fleet_id))
no_fleet_id = False
if SrpFleetMain.objects.filter(id=fleet_id).exists():
if request.method == 'POST':
form = SrpFleetMainUpdateForm(request.POST)
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
srpfleetmain = SrpFleetMain.objects.get(id=fleet_id)
srpfleetmain.fleet_srp_aar_link = form.cleaned_data['fleet_aar_link']
srpfleetmain.save()
logger.info("User %s edited SRP Fleet %s" % (request.user, srpfleetmain.fleet_name))
messages.success(request, _('Saved changes to SRP fleet %(fleetname)s') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_management_view")
else:
logger.debug("Returning blank SrpFleetMainUpdateForm")
form = SrpFleetMainUpdateForm()
render_items = {'form': form, "no_fleet_id": no_fleet_id}
return render(request, 'registered/srpfleetupdate.html', context=render_items)
srpfleetmain = get_object_or_404(SrpFleetMain, id=fleet_id)
if request.method == 'POST':
form = SrpFleetMainUpdateForm(request.POST)
logger.debug("Request type POST contains form valid: %s" % form.is_valid())
if form.is_valid():
srpfleetmain.fleet_srp_aar_link = form.cleaned_data['fleet_aar_link']
srpfleetmain.save()
logger.info("User %s edited SRP Fleet %s" % (request.user, srpfleetmain.fleet_name))
messages.success(request, _('Saved changes to SRP fleet %(fleetname)s') % {"fleetname": srpfleetmain.fleet_name})
return redirect("auth_srp_management_view")
else:
logger.error(
"Unable to edit srp fleet id %s for user %s - fleet matching id not found." % (fleet_id, request.user))
messages.error(request, _('Unable to locate SRP fleet with ID %(fleetid)s') % {"fleetid": fleet_id})
return redirect("auth_srp_management_view")
logger.debug("Returning blank SrpFleetMainUpdateForm")
form = SrpFleetMainUpdateForm()
return render(request, 'registered/srpfleetupdate.html', context={'form': form})